1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 1999-2004 VLC authors and VideoLAN
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 *****************************************************************************/
33 #include <vlc_codec.h>
35 #include <vlc_input.h>
37 #include <vlc_modules.h>
38 #include <vlc_strings.h>
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
,
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 */
110 { "ogx", "ogg" }, /*RFC5334*/
111 { "opus", "ogg" }, /*draft-terriberry-oggopus-01*/
113 { "rm", "avformat" },
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 */
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
)
146 return demux_NewAdvanced( p_obj
, NULL
, psz_name
, "", s
, out
, false );
149 struct vlc_demux_private
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
173 if (vlc_stream_Tell(demux
->s
) != 0 && vlc_stream_Seek(demux
->s
, 0))
175 msg_Err(demux
, "seek failure before probing");
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
))
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
);
201 psz_demux
= demux_NameFromMimeType( 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
))
211 p_demux
->psz_url
= strdup(url
);
212 if (unlikely(p_demux
->psz_url
== NULL
))
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 */
220 msg_Dbg( p_obj
, "creating demux \"%s\", URL: %s, path: %s",
221 psz_demux
, url
, p_demux
->psz_filepath
);
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
, '.' );
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
);
255 free( p_demux
->psz_name
);
256 stream_CommonDelete( p_demux
);
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
)
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
);
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
) )
304 case DEMUX_CAN_PAUSE
:
305 case DEMUX_CAN_CONTROL_PACE
:
306 case DEMUX_GET_PTS_DELAY
:
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
;
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
;
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
);
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
) )
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
) )
366 case DEMUX_IS_PLAYLIST
:
367 *va_arg( args
, bool * ) = false;
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
:
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
:
387 case DEMUX_NAV_RIGHT
:
388 case DEMUX_NAV_POPUP
:
390 case DEMUX_FILTER_ENABLE
:
391 case DEMUX_FILTER_DISABLE
:
394 case DEMUX_SET_TITLE
:
395 case DEMUX_SET_SEEKPOINT
:
396 case DEMUX_SET_RECORD_STATE
:
399 msg_Err( s
, "unknown query 0x%x in %s", i_query
, __func__
);
405 /****************************************************************************
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" );
415 es_format_Clean( p_fmt
);
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
);
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
))
458 int demux_GetTitle( demux_t
*p_demux
)
462 if (demux_Control(p_demux
, DEMUX_GET_TITLE
, &title
))
467 int demux_GetSeekpoint( demux_t
*p_demux
)
471 if (demux_Control(p_demux
, DEMUX_GET_SEEKPOINT
, &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
),
482 if (unlikely(p_demux
== 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
;
495 priv
->module
= module_need(p_demux
, "demux_filter", p_name
,
497 if (priv
->module
== NULL
)
502 stream_CommonDelete( p_demux
);
506 demux_t
*demux_FilterChainNew( demux_t
*p_demux
, const char *psz_chain
)
508 if( !psz_chain
|| !*psz_chain
)
511 char *psz_parser
= strdup(psz_chain
);
518 config_chain_t
*p_cfg
;
520 char *psz_rest_chain
= config_ChainCreate( &psz_name
, &p_cfg
, psz_parser
);
522 psz_parser
= psz_rest_chain
;
524 demux_t
*filter
= demux_FilterNew(p_demux
, psz_name
);
529 config_ChainDestroy(p_cfg
);
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
);
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
);
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 );