demux: mp4: set bitmap mask when possible
[vlc.git] / src / input / demux.c
blob370a65082e4679cd056777cc66cd8b40f18b26b3
1 /*****************************************************************************
2 * demux.c
3 *****************************************************************************
4 * Copyright (C) 1999-2004 VLC authors and VideoLAN
5 * $Id$
7 * Author: Laurent Aimar <fenrir@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include <assert.h>
29 #include <limits.h>
31 #include "demux.h"
32 #include <libvlc.h>
33 #include <vlc_codec.h>
34 #include <vlc_meta.h>
35 #include <vlc_input.h>
36 #include <vlc_url.h>
37 #include <vlc_modules.h>
38 #include <vlc_strings.h>
40 typedef const struct
42 char const key[20];
43 char const name[8];
45 } demux_mapping;
47 static int demux_mapping_cmp( const void *k, const void *v )
49 demux_mapping* entry = v;
50 return vlc_ascii_strcasecmp( k, entry->key );
53 static demux_mapping* demux_lookup( char const* key,
54 demux_mapping* data, size_t size )
56 return bsearch( key, data, size, sizeof( *data ), demux_mapping_cmp );
59 static const char *demux_NameFromMimeType(const char *mime)
61 static demux_mapping types[] =
62 { /* Must be sorted in ascending ASCII order */
63 { "audio/aac", "m4a" },
64 { "audio/aacp", "m4a" },
65 { "audio/mpeg", "mp3" },
66 //{ "video/MP1S", "es,mpgv" }, !b_force
67 { "video/dv", "rawdv" },
68 { "video/MP2P", "ps" },
69 { "video/MP2T", "ts" },
70 { "video/nsa", "nsv" },
71 { "video/nsv", "nsv" },
73 demux_mapping *type = demux_lookup( mime, types, ARRAY_SIZE( types ) );
74 return (type != NULL) ? type->name : "any";
77 static const char* DemuxNameFromExtension( char const* ext,
78 bool b_preparsing )
80 /* NOTE: Add only file without any problems here and with strong detection:
81 * - no .mp3, .a52, ...
82 * - wav can't be added 'cause of a52 and dts in them as raw audio
84 static demux_mapping strong[] =
85 { /* NOTE: must be sorted in asc order */
86 { "aiff", "aiff" },
87 { "asf", "asf" },
88 { "au", "au" },
89 { "avi", "avi" },
90 { "drc", "dirac" },
91 { "dv", "dv" },
92 { "flac", "flac" },
93 { "h264", "h264" },
94 { "kar", "smf" },
95 { "m3u", "m3u" },
96 { "m4a", "mp4" },
97 { "m4v", "m4v" },
98 { "mid", "smf" },
99 { "mka", "mkv" },
100 { "mks", "mkv" },
101 { "mkv", "mkv" },
102 { "moov", "mp4" },
103 { "mov", "mp4" },
104 { "mp4", "mp4" },
105 { "nsv", "nsv" },
106 { "oga", "ogg" },
107 { "ogg", "ogg" },
108 { "ogm", "ogg" },
109 { "ogv", "ogg" },
110 { "ogx", "ogg" }, /*RFC5334*/
111 { "opus", "ogg" }, /*draft-terriberry-oggopus-01*/
112 { "pva", "pva" },
113 { "rm", "avformat" },
114 { "rmi", "smf" },
115 { "spx", "ogg" },
116 { "voc", "voc" },
117 { "wma", "asf" },
118 { "wmv", "asf" },
121 /* Here, we don't mind if it does not work, it must be quick */
122 static demux_mapping quick[] =
123 { /* NOTE: shall be sorted in asc order */
124 { "mp3", "mpga" },
125 { "ogg", "ogg" },
126 { "wma", "asf" },
129 struct {
130 demux_mapping* data;
131 size_t size;
133 } lookup = {
134 .data = b_preparsing ? quick : strong,
135 .size = b_preparsing ? ARRAY_SIZE( quick ) : ARRAY_SIZE( strong )
138 demux_mapping* result = demux_lookup( ext, lookup.data, lookup.size );
139 return result ? result->name : NULL;
142 demux_t *demux_New( vlc_object_t *p_obj, const char *psz_name,
143 stream_t *s, es_out_t *out )
145 assert(s != NULL );
146 return demux_NewAdvanced( p_obj, NULL, psz_name, "", s, out, false );
149 struct vlc_demux_private
151 module_t *module;
154 static void demux_DestroyDemux(demux_t *demux)
156 struct vlc_demux_private *priv = vlc_stream_Private(demux);
158 module_unneed(demux, priv->module);
159 free(demux->psz_filepath);
160 free(demux->psz_name);
162 assert(demux->s != NULL);
163 vlc_stream_Delete(demux->s);
166 static int demux_Probe(void *func, va_list ap)
168 int (*probe)(vlc_object_t *) = func;
169 demux_t *demux = va_arg(ap, demux_t *);
171 /* Restore input stream offset (in case previous probed demux failed to
172 * to do so). */
173 if (vlc_stream_Tell(demux->s) != 0 && vlc_stream_Seek(demux->s, 0))
175 msg_Err(demux, "seek failure before probing");
176 return VLC_EGENERIC;
179 return probe(VLC_OBJECT(demux));
182 demux_t *demux_NewAdvanced( vlc_object_t *p_obj, input_thread_t *p_input,
183 const char *psz_demux, const char *url,
184 stream_t *s, es_out_t *out, bool b_preparsing )
186 struct vlc_demux_private *priv;
187 demux_t *p_demux = vlc_stream_CustomNew(p_obj, demux_DestroyDemux,
188 sizeof (*priv), "demux");
190 if (unlikely(p_demux == NULL))
191 return NULL;
193 assert(s != NULL);
194 priv = vlc_stream_Private(p_demux);
196 if (!strcasecmp( psz_demux, "any" ) || !psz_demux[0])
197 { /* Look up demux by mime-type for hard to detect formats */
198 char *type = stream_MimeType( s );
199 if( type != NULL )
201 psz_demux = demux_NameFromMimeType( type );
202 free( type );
206 p_demux->p_input_item = p_input ? input_GetItem(p_input) : NULL;
207 p_demux->psz_name = strdup( psz_demux );
208 if (unlikely(p_demux->psz_name == NULL))
209 goto error;
211 p_demux->psz_url = strdup(url);
212 if (unlikely(p_demux->psz_url == NULL))
213 goto error;
215 const char *p = strstr(p_demux->psz_url, "://");
216 p_demux->psz_location = (p != NULL) ? (p + 3) : "";
217 p_demux->psz_filepath = get_path(p_demux->psz_location); /* parse URL */
219 if( !b_preparsing )
220 msg_Dbg( p_obj, "creating demux \"%s\", URL: %s, path: %s",
221 psz_demux, url, p_demux->psz_filepath );
223 p_demux->s = s;
224 p_demux->out = out;
225 p_demux->b_preparsing = b_preparsing;
227 p_demux->pf_demux = NULL;
228 p_demux->pf_control = NULL;
229 p_demux->p_sys = NULL;
231 const char *psz_module = NULL;
233 if( !strcmp( p_demux->psz_name, "any" ) && p_demux->psz_filepath )
235 char const* psz_ext = strrchr( p_demux->psz_filepath, '.' );
237 if( psz_ext )
238 psz_module = DemuxNameFromExtension( psz_ext + 1, b_preparsing );
241 if( psz_module == NULL )
242 psz_module = p_demux->psz_name;
244 priv->module = vlc_module_load(p_demux, "demux", psz_module,
245 !strcmp(psz_module, p_demux->psz_name), demux_Probe, p_demux);
247 if (priv->module == NULL)
249 free( p_demux->psz_filepath );
250 goto error;
253 return p_demux;
254 error:
255 free( p_demux->psz_name );
256 stream_CommonDelete( p_demux );
257 return NULL;
260 #define static_control_match(foo) \
261 static_assert((unsigned) DEMUX_##foo == STREAM_##foo, "Mismatch")
263 int demux_vaControl( demux_t *demux, int query, va_list args )
265 return demux->pf_control( demux, query, args );
268 /*****************************************************************************
269 * demux_vaControlHelper:
270 *****************************************************************************/
271 int demux_vaControlHelper( stream_t *s,
272 int64_t i_start, int64_t i_end,
273 int64_t i_bitrate, int i_align,
274 int i_query, va_list args )
276 int64_t i_tell;
277 double f, *pf;
278 vlc_tick_t i64;
280 if( i_end < 0 ) i_end = stream_Size( s );
281 if( i_start < 0 ) i_start = 0;
282 if( i_align <= 0 ) i_align = 1;
283 i_tell = vlc_stream_Tell( s );
285 static_control_match(CAN_PAUSE);
286 static_control_match(CAN_CONTROL_PACE);
287 static_control_match(GET_PTS_DELAY);
288 static_control_match(GET_META);
289 static_control_match(GET_SIGNAL);
290 static_control_match(SET_PAUSE_STATE);
292 switch( i_query )
294 case DEMUX_CAN_SEEK:
296 bool *b = va_arg( args, bool * );
298 if( (i_bitrate <= 0 && i_start >= i_end)
299 || vlc_stream_Control( s, STREAM_CAN_SEEK, b ) )
300 *b = false;
301 break;
304 case DEMUX_CAN_PAUSE:
305 case DEMUX_CAN_CONTROL_PACE:
306 case DEMUX_GET_PTS_DELAY:
307 case DEMUX_GET_META:
308 case DEMUX_GET_SIGNAL:
309 case DEMUX_SET_PAUSE_STATE:
310 return vlc_stream_vaControl( s, i_query, args );
312 case DEMUX_GET_LENGTH:
313 if( i_bitrate > 0 && i_end > i_start )
315 *va_arg( args, vlc_tick_t * ) = INT64_C(8000000) * (i_end - i_start) / i_bitrate;
316 return VLC_SUCCESS;
318 return VLC_EGENERIC;
320 case DEMUX_GET_TIME:
321 if( i_bitrate > 0 && i_tell >= i_start )
323 *va_arg( args, vlc_tick_t * ) = INT64_C(8000000) * (i_tell - i_start) / i_bitrate;
324 return VLC_SUCCESS;
326 return VLC_EGENERIC;
328 case DEMUX_GET_POSITION:
329 pf = va_arg( args, double * );
330 if( i_start < i_end )
332 *pf = (double)( i_tell - i_start ) /
333 (double)( i_end - i_start );
334 return VLC_SUCCESS;
336 return VLC_EGENERIC;
339 case DEMUX_SET_POSITION:
340 f = va_arg( args, double );
341 if( i_start < i_end && f >= 0.0 && f <= 1.0 )
343 int64_t i_block = (f * ( i_end - i_start )) / i_align;
345 if( vlc_stream_Seek( s, i_start + i_block * i_align ) )
347 return VLC_EGENERIC;
349 return VLC_SUCCESS;
351 return VLC_EGENERIC;
353 case DEMUX_SET_TIME:
354 i64 = va_arg( args, vlc_tick_t );
355 if( i_bitrate > 0 && i64 >= 0 )
357 int64_t i_block = i64 * i_bitrate / INT64_C(8000000) / i_align;
358 if( vlc_stream_Seek( s, i_start + i_block * i_align ) )
360 return VLC_EGENERIC;
362 return VLC_SUCCESS;
364 return VLC_EGENERIC;
366 case DEMUX_IS_PLAYLIST:
367 *va_arg( args, bool * ) = false;
368 return VLC_SUCCESS;
370 case DEMUX_GET_FPS:
371 case DEMUX_HAS_UNSUPPORTED_META:
372 case DEMUX_SET_NEXT_DEMUX_TIME:
373 case DEMUX_GET_TITLE_INFO:
374 case DEMUX_SET_GROUP_DEFAULT:
375 case DEMUX_SET_GROUP_ALL:
376 case DEMUX_SET_GROUP_LIST:
377 case DEMUX_SET_ES:
378 case DEMUX_GET_ATTACHMENTS:
379 case DEMUX_CAN_RECORD:
380 case DEMUX_TEST_AND_CLEAR_FLAGS:
381 case DEMUX_GET_TITLE:
382 case DEMUX_GET_SEEKPOINT:
383 case DEMUX_NAV_ACTIVATE:
384 case DEMUX_NAV_UP:
385 case DEMUX_NAV_DOWN:
386 case DEMUX_NAV_LEFT:
387 case DEMUX_NAV_RIGHT:
388 case DEMUX_NAV_POPUP:
389 case DEMUX_NAV_MENU:
390 case DEMUX_FILTER_ENABLE:
391 case DEMUX_FILTER_DISABLE:
392 return VLC_EGENERIC;
394 case DEMUX_SET_TITLE:
395 case DEMUX_SET_SEEKPOINT:
396 case DEMUX_SET_RECORD_STATE:
397 assert(0);
398 default:
399 msg_Err( s, "unknown query 0x%x in %s", i_query, __func__ );
400 return VLC_EGENERIC;
402 return VLC_SUCCESS;
405 /****************************************************************************
406 * Utility functions
407 ****************************************************************************/
408 decoder_t *demux_PacketizerNew( demux_t *p_demux, es_format_t *p_fmt, const char *psz_msg )
410 decoder_t *p_packetizer;
411 p_packetizer = vlc_custom_create( p_demux, sizeof( *p_packetizer ),
412 "demux packetizer" );
413 if( !p_packetizer )
415 es_format_Clean( p_fmt );
416 return NULL;
418 p_fmt->b_packetized = false;
420 p_packetizer->pf_decode = NULL;
421 p_packetizer->pf_packetize = NULL;
423 p_packetizer->fmt_in = *p_fmt;
424 es_format_Init( &p_packetizer->fmt_out, p_fmt->i_cat, 0 );
426 p_packetizer->p_module = module_need( p_packetizer, "packetizer", NULL, false );
427 if( !p_packetizer->p_module )
429 es_format_Clean( p_fmt );
430 vlc_object_release( p_packetizer );
431 msg_Err( p_demux, "cannot find packetizer for %s", psz_msg );
432 return NULL;
435 return p_packetizer;
438 void demux_PacketizerDestroy( decoder_t *p_packetizer )
440 if( p_packetizer->p_module )
441 module_unneed( p_packetizer, p_packetizer->p_module );
442 es_format_Clean( &p_packetizer->fmt_in );
443 es_format_Clean( &p_packetizer->fmt_out );
444 if( p_packetizer->p_description )
445 vlc_meta_Delete( p_packetizer->p_description );
446 vlc_object_release( p_packetizer );
449 unsigned demux_TestAndClearFlags( demux_t *p_demux, unsigned flags )
451 unsigned update = flags;
453 if (demux_Control( p_demux, DEMUX_TEST_AND_CLEAR_FLAGS, &update))
454 return 0;
455 return update;
458 int demux_GetTitle( demux_t *p_demux )
460 int title;
462 if (demux_Control(p_demux, DEMUX_GET_TITLE, &title))
463 title = 0;
464 return title;
467 int demux_GetSeekpoint( demux_t *p_demux )
469 int seekpoint;
471 if (demux_Control(p_demux, DEMUX_GET_SEEKPOINT, &seekpoint))
472 seekpoint = 0;
473 return seekpoint;
476 static demux_t *demux_FilterNew( demux_t *p_next, const char *p_name )
478 struct vlc_demux_private *priv;
479 demux_t *p_demux = vlc_stream_CustomNew(VLC_OBJECT(p_next),
480 demux_DestroyDemux, sizeof (*priv),
481 "demux filter");
482 if (unlikely(p_demux == NULL))
483 return NULL;
485 priv = vlc_stream_Private(p_demux);
486 p_demux->p_next = p_next;
487 p_demux->p_input_item = NULL;
488 p_demux->p_sys = NULL;
489 p_demux->psz_name = NULL;
490 p_demux->psz_url = NULL;
491 p_demux->psz_location = NULL;
492 p_demux->psz_filepath = NULL;
493 p_demux->out = NULL;
495 priv->module = module_need(p_demux, "demux_filter", p_name,
496 p_name != NULL);
497 if (priv->module == NULL)
498 goto error;
500 return p_demux;
501 error:
502 stream_CommonDelete( p_demux );
503 return NULL;
506 demux_t *demux_FilterChainNew( demux_t *p_demux, const char *psz_chain )
508 if( !psz_chain || !*psz_chain )
509 return NULL;
511 char *psz_parser = strdup(psz_chain);
512 if(!psz_parser)
513 return NULL;
515 /* parse chain */
516 while(psz_parser)
518 config_chain_t *p_cfg;
519 char *psz_name;
520 char *psz_rest_chain = config_ChainCreate( &psz_name, &p_cfg, psz_parser );
521 free( psz_parser );
522 psz_parser = psz_rest_chain;
524 demux_t *filter = demux_FilterNew(p_demux, psz_name);
525 if (filter != NULL)
526 p_demux = filter;
528 free(psz_name);
529 config_ChainDestroy(p_cfg);
532 return p_demux;
535 static bool demux_filter_enable_disable(demux_t *p_demux,
536 const char *psz_demux, bool b_enable)
538 struct vlc_demux_private *priv = vlc_stream_Private(p_demux);
540 if ( psz_demux &&
541 (strcmp(module_get_name(priv->module, false), psz_demux) == 0
542 || strcmp(module_get_name(priv->module, true), psz_demux) == 0) )
544 demux_Control( p_demux,
545 b_enable ? DEMUX_FILTER_ENABLE : DEMUX_FILTER_DISABLE );
546 return true;
548 return false;
551 bool demux_FilterEnable( demux_t *p_demux_chain, const char* psz_demux )
553 return demux_filter_enable_disable( p_demux_chain, psz_demux, true );
556 bool demux_FilterDisable( demux_t *p_demux_chain, const char* psz_demux )
558 return demux_filter_enable_disable( p_demux_chain, psz_demux, false );