demux: mp4: remove unused chunk sample index
[vlc.git] / src / input / demux.c
bloba1e081b95774f46f9a4a4a7a548251a6f611f987
1 /*****************************************************************************
2 * demux.c
3 *****************************************************************************
4 * Copyright (C) 1999-2004 VLC authors and VideoLAN
6 * Author: Laurent Aimar <fenrir@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <assert.h>
28 #include <limits.h>
30 #include "demux.h"
31 #include <libvlc.h>
32 #include <vlc_codec.h>
33 #include <vlc_meta.h>
34 #include <vlc_url.h>
35 #include <vlc_modules.h>
36 #include <vlc_strings.h>
37 #include "input_internal.h"
39 typedef const struct
41 char const key[20];
42 char const name[8];
44 } demux_mapping;
46 static int demux_mapping_cmp( const void *k, const void *v )
48 demux_mapping* entry = v;
49 return vlc_ascii_strcasecmp( k, entry->key );
52 static const char *demux_NameFromMimeType(const char *mime)
54 static demux_mapping types[] =
55 { /* Must be sorted in ascending ASCII order */
56 { "audio/aac", "m4a" },
57 { "audio/aacp", "m4a" },
58 { "audio/mpeg", "mp3" },
59 //{ "video/MP1S", "es,mpgv" }, !b_force
60 { "video/dv", "rawdv" },
61 { "video/MP2P", "ps" },
62 { "video/MP2T", "ts" },
63 { "video/nsa", "nsv" },
64 { "video/nsv", "nsv" },
67 demux_mapping *type = bsearch(mime, types, ARRAY_SIZE(types),
68 sizeof (*types), demux_mapping_cmp);
69 return (type != NULL) ? type->name : "any";
72 demux_t *demux_New( vlc_object_t *p_obj, const char *psz_name,
73 stream_t *s, es_out_t *out )
75 assert(s != NULL );
76 return demux_NewAdvanced( p_obj, NULL, psz_name, "", s, out, false );
79 struct vlc_demux_private
81 module_t *module;
84 static void demux_DestroyDemux(demux_t *demux)
86 struct vlc_demux_private *priv = vlc_stream_Private(demux);
88 module_unneed(demux, priv->module);
89 free(demux->psz_filepath);
90 free(demux->psz_name);
92 assert(demux->s != NULL);
93 vlc_stream_Delete(demux->s);
96 static int demux_Probe(void *func, bool forced, va_list ap)
98 int (*probe)(vlc_object_t *) = func;
99 demux_t *demux = va_arg(ap, demux_t *);
101 /* Restore input stream offset (in case previous probed demux failed to
102 * to do so). */
103 if (vlc_stream_Tell(demux->s) != 0 && vlc_stream_Seek(demux->s, 0))
105 msg_Err(demux, "seek failure before probing");
106 return VLC_EGENERIC;
109 demux->obj.force = forced;
111 int ret = probe(VLC_OBJECT(demux));
112 if (ret)
113 vlc_objres_clear(VLC_OBJECT(demux));
114 return ret;
117 demux_t *demux_NewAdvanced( vlc_object_t *p_obj, input_thread_t *p_input,
118 const char *module, const char *url,
119 stream_t *s, es_out_t *out, bool b_preparsing )
121 struct vlc_demux_private *priv;
122 demux_t *p_demux = vlc_stream_CustomNew(p_obj, demux_DestroyDemux,
123 sizeof (*priv), "demux");
125 if (unlikely(p_demux == NULL))
126 return NULL;
128 assert(s != NULL);
129 priv = vlc_stream_Private(p_demux);
131 p_demux->p_input_item = p_input ? input_GetItem(p_input) : NULL;
132 p_demux->psz_name = strdup(module);
133 if (unlikely(p_demux->psz_name == NULL))
134 goto error;
136 p_demux->psz_url = strdup(url);
137 if (unlikely(p_demux->psz_url == NULL))
138 goto error;
140 const char *p = strstr(p_demux->psz_url, "://");
141 p_demux->psz_location = (p != NULL) ? (p + 3) : "";
142 p_demux->psz_filepath = get_path(p_demux->psz_location); /* parse URL */
144 if( !b_preparsing )
145 msg_Dbg( p_obj, "creating demux \"%s\", URL: %s, path: %s",
146 module, url, p_demux->psz_filepath );
148 p_demux->s = s;
149 p_demux->out = out;
150 p_demux->b_preparsing = b_preparsing;
152 p_demux->pf_readdir = NULL;
153 p_demux->pf_demux = NULL;
154 p_demux->pf_control = NULL;
155 p_demux->p_sys = NULL;
157 char *modbuf = NULL;
158 bool strict = true;
160 if (!strcasecmp(module, "any" ) || module[0] == '\0') {
161 /* Look up demux by content type for hard to detect formats */
162 char *type = stream_MimeType(s);
164 if (type != NULL) {
165 module = demux_NameFromMimeType(type);
166 free(type);
168 strict = false;
171 if (strcasecmp(module, "any") == 0 && p_demux->psz_filepath != NULL)
173 const char *ext = strrchr(p_demux->psz_filepath, '.');
175 if (ext != NULL) {
176 if (b_preparsing && !vlc_ascii_strcasecmp(ext, ".mp3"))
177 module = "mpga";
178 else
179 if (likely(asprintf(&modbuf, "ext-%s", ext + 1) >= 0))
180 module = modbuf;
182 strict = false;
185 priv->module = vlc_module_load(p_demux, "demux", module, strict,
186 demux_Probe, p_demux);
187 free(modbuf);
189 if (priv->module == NULL)
191 free( p_demux->psz_filepath );
192 goto error;
195 return p_demux;
196 error:
197 free( p_demux->psz_name );
198 stream_CommonDelete( p_demux );
199 return NULL;
202 int demux_Demux(demux_t *demux)
204 if (demux->pf_demux != NULL)
205 return demux->pf_demux(demux);
207 if (demux->pf_readdir != NULL && demux->p_input_item != NULL) {
208 input_item_node_t *node = input_item_node_Create(demux->p_input_item);
210 if (unlikely(node == NULL))
211 return VLC_DEMUXER_EGENERIC;
213 if (vlc_stream_ReadDir(demux, node)) {
214 input_item_node_Delete(node);
215 return VLC_DEMUXER_EGENERIC;
218 if (es_out_Control(demux->out, ES_OUT_POST_SUBNODE, node))
219 input_item_node_Delete(node);
220 return VLC_DEMUXER_EOF;
223 return VLC_DEMUXER_SUCCESS;
226 #define static_control_match(foo) \
227 static_assert((unsigned) DEMUX_##foo == STREAM_##foo, "Mismatch")
229 int demux_vaControl( demux_t *demux, int query, va_list args )
231 return demux->pf_control( demux, query, args );
234 /*****************************************************************************
235 * demux_vaControlHelper:
236 *****************************************************************************/
237 int demux_vaControlHelper( stream_t *s,
238 int64_t i_start, int64_t i_end,
239 int64_t i_bitrate, int i_align,
240 int i_query, va_list args )
242 int64_t i_tell;
243 double f, *pf;
244 vlc_tick_t i64;
246 if( i_end < 0 ) i_end = stream_Size( s );
247 if( i_start < 0 ) i_start = 0;
248 if( i_align <= 0 ) i_align = 1;
249 i_tell = vlc_stream_Tell( s );
251 static_control_match(CAN_PAUSE);
252 static_control_match(CAN_CONTROL_PACE);
253 static_control_match(GET_PTS_DELAY);
254 static_control_match(GET_META);
255 static_control_match(GET_SIGNAL);
256 static_control_match(SET_PAUSE_STATE);
258 switch( i_query )
260 case DEMUX_CAN_SEEK:
262 bool *b = va_arg( args, bool * );
264 if( (i_bitrate <= 0 && i_start >= i_end)
265 || vlc_stream_Control( s, STREAM_CAN_SEEK, b ) )
266 *b = false;
267 break;
270 case DEMUX_CAN_PAUSE:
271 case DEMUX_CAN_CONTROL_PACE:
272 case DEMUX_GET_PTS_DELAY:
273 case DEMUX_GET_META:
274 case DEMUX_GET_SIGNAL:
275 case DEMUX_GET_TYPE:
276 case DEMUX_SET_PAUSE_STATE:
277 return vlc_stream_vaControl( s, i_query, args );
279 case DEMUX_GET_LENGTH:
280 if( i_bitrate > 0 && i_end > i_start )
282 *va_arg( args, vlc_tick_t * ) = vlc_tick_from_samples((i_end - i_start) * 8, i_bitrate);
283 return VLC_SUCCESS;
285 return VLC_EGENERIC;
287 case DEMUX_GET_TIME:
288 if( i_bitrate > 0 && i_tell >= i_start )
290 *va_arg( args, vlc_tick_t * ) = vlc_tick_from_samples((i_tell - i_start) * 8, i_bitrate);
291 return VLC_SUCCESS;
293 return VLC_EGENERIC;
295 case DEMUX_GET_POSITION:
296 pf = va_arg( args, double * );
297 if( i_start < i_end )
299 *pf = (double)( i_tell - i_start ) /
300 (double)( i_end - i_start );
301 return VLC_SUCCESS;
303 return VLC_EGENERIC;
304 case DEMUX_GET_NORMAL_TIME:
305 return VLC_EGENERIC;
307 case DEMUX_SET_POSITION:
308 f = va_arg( args, double );
309 if( i_start < i_end && f >= 0.0 && f <= 1.0 )
311 int64_t i_block = (f * ( i_end - i_start )) / i_align;
313 if( vlc_stream_Seek( s, i_start + i_block * i_align ) )
315 return VLC_EGENERIC;
317 return VLC_SUCCESS;
319 return VLC_EGENERIC;
321 case DEMUX_SET_TIME:
322 i64 = va_arg( args, vlc_tick_t );
323 if( i_bitrate > 0 && i64 >= 0 )
325 int64_t i_block = samples_from_vlc_tick( i64, i_bitrate ) / (8 * i_align);
326 if( vlc_stream_Seek( s, i_start + i_block * i_align ) )
328 return VLC_EGENERIC;
330 return VLC_SUCCESS;
332 return VLC_EGENERIC;
334 case DEMUX_GET_FPS:
335 case DEMUX_HAS_UNSUPPORTED_META:
336 case DEMUX_SET_NEXT_DEMUX_TIME:
337 case DEMUX_GET_TITLE_INFO:
338 case DEMUX_SET_GROUP_DEFAULT:
339 case DEMUX_SET_GROUP_ALL:
340 case DEMUX_SET_GROUP_LIST:
341 case DEMUX_SET_ES:
342 case DEMUX_SET_ES_LIST:
343 case DEMUX_GET_ATTACHMENTS:
344 case DEMUX_CAN_RECORD:
345 case DEMUX_TEST_AND_CLEAR_FLAGS:
346 case DEMUX_GET_TITLE:
347 case DEMUX_GET_SEEKPOINT:
348 case DEMUX_NAV_ACTIVATE:
349 case DEMUX_NAV_UP:
350 case DEMUX_NAV_DOWN:
351 case DEMUX_NAV_LEFT:
352 case DEMUX_NAV_RIGHT:
353 case DEMUX_NAV_POPUP:
354 case DEMUX_NAV_MENU:
355 case DEMUX_FILTER_ENABLE:
356 case DEMUX_FILTER_DISABLE:
357 return VLC_EGENERIC;
359 case DEMUX_SET_TITLE:
360 case DEMUX_SET_SEEKPOINT:
361 case DEMUX_SET_RECORD_STATE:
362 assert(0);
363 default:
364 msg_Err( s, "unknown query 0x%x in %s", i_query, __func__ );
365 return VLC_EGENERIC;
367 return VLC_SUCCESS;
370 /****************************************************************************
371 * Utility functions
372 ****************************************************************************/
373 decoder_t *demux_PacketizerNew( demux_t *p_demux, es_format_t *p_fmt, const char *psz_msg )
375 decoder_t *p_packetizer;
376 p_packetizer = vlc_custom_create( p_demux, sizeof( *p_packetizer ),
377 "demux packetizer" );
378 if( !p_packetizer )
380 es_format_Clean( p_fmt );
381 return NULL;
383 p_fmt->b_packetized = false;
385 p_packetizer->pf_decode = NULL;
386 p_packetizer->pf_packetize = NULL;
388 p_packetizer->fmt_in = *p_fmt;
389 es_format_Init( &p_packetizer->fmt_out, p_fmt->i_cat, 0 );
391 p_packetizer->p_module = module_need( p_packetizer, "packetizer", NULL, false );
392 if( !p_packetizer->p_module )
394 es_format_Clean( p_fmt );
395 vlc_object_delete(p_packetizer);
396 msg_Err( p_demux, "cannot find packetizer for %s", psz_msg );
397 return NULL;
400 return p_packetizer;
403 void demux_PacketizerDestroy( decoder_t *p_packetizer )
405 if( p_packetizer->p_module )
406 module_unneed( p_packetizer, p_packetizer->p_module );
407 es_format_Clean( &p_packetizer->fmt_in );
408 es_format_Clean( &p_packetizer->fmt_out );
409 if( p_packetizer->p_description )
410 vlc_meta_Delete( p_packetizer->p_description );
411 vlc_object_delete(p_packetizer);
414 unsigned demux_TestAndClearFlags( demux_t *p_demux, unsigned flags )
416 unsigned update = flags;
418 if (demux_Control( p_demux, DEMUX_TEST_AND_CLEAR_FLAGS, &update))
419 return 0;
420 return update;
423 int demux_GetTitle( demux_t *p_demux )
425 int title;
427 if (demux_Control(p_demux, DEMUX_GET_TITLE, &title))
428 title = 0;
429 return title;
432 int demux_GetSeekpoint( demux_t *p_demux )
434 int seekpoint;
436 if (demux_Control(p_demux, DEMUX_GET_SEEKPOINT, &seekpoint))
437 seekpoint = 0;
438 return seekpoint;
441 static demux_t *demux_FilterNew( demux_t *p_next, const char *p_name )
443 struct vlc_demux_private *priv;
444 demux_t *p_demux = vlc_stream_CustomNew(VLC_OBJECT(p_next),
445 demux_DestroyDemux, sizeof (*priv),
446 "demux filter");
447 if (unlikely(p_demux == NULL))
448 return NULL;
450 priv = vlc_stream_Private(p_demux);
451 p_demux->s = p_next;
452 p_demux->p_input_item = NULL;
453 p_demux->p_sys = NULL;
454 p_demux->psz_name = NULL;
455 p_demux->psz_url = NULL;
456 p_demux->psz_location = NULL;
457 p_demux->psz_filepath = NULL;
458 p_demux->out = NULL;
460 priv->module = module_need(p_demux, "demux_filter", p_name,
461 p_name != NULL);
462 if (priv->module == NULL)
463 goto error;
465 return p_demux;
466 error:
467 stream_CommonDelete( p_demux );
468 return NULL;
471 demux_t *demux_FilterChainNew( demux_t *p_demux, const char *psz_chain )
473 if( !psz_chain || !*psz_chain )
474 return NULL;
476 char *psz_parser = strdup(psz_chain);
477 if(!psz_parser)
478 return NULL;
480 /* parse chain */
481 while(psz_parser)
483 config_chain_t *p_cfg;
484 char *psz_name;
485 char *psz_rest_chain = config_ChainCreate( &psz_name, &p_cfg, psz_parser );
486 free( psz_parser );
487 psz_parser = psz_rest_chain;
489 demux_t *filter = demux_FilterNew(p_demux, psz_name);
490 if (filter != NULL)
491 p_demux = filter;
493 free(psz_name);
494 config_ChainDestroy(p_cfg);
497 return p_demux;
500 static bool demux_filter_enable_disable(demux_t *p_demux,
501 const char *psz_demux, bool b_enable)
503 struct vlc_demux_private *priv = vlc_stream_Private(p_demux);
505 if ( psz_demux &&
506 (strcmp(module_get_name(priv->module, false), psz_demux) == 0
507 || strcmp(module_get_name(priv->module, true), psz_demux) == 0) )
509 demux_Control( p_demux,
510 b_enable ? DEMUX_FILTER_ENABLE : DEMUX_FILTER_DISABLE );
511 return true;
513 return false;
516 bool demux_FilterEnable( demux_t *p_demux_chain, const char* psz_demux )
518 return demux_filter_enable_disable( p_demux_chain, psz_demux, true );
521 bool demux_FilterDisable( demux_t *p_demux_chain, const char* psz_demux )
523 return demux_filter_enable_disable( p_demux_chain, psz_demux, false );