1 /*****************************************************************************
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 *****************************************************************************/
32 #include <vlc_codec.h>
35 #include <vlc_modules.h>
36 #include <vlc_strings.h>
37 #include "input_internal.h"
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
)
76 return demux_NewAdvanced( p_obj
, NULL
, psz_name
, "", s
, out
, false );
79 struct vlc_demux_private
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
103 if (vlc_stream_Tell(demux
->s
) != 0 && vlc_stream_Seek(demux
->s
, 0))
105 msg_Err(demux
, "seek failure before probing");
109 demux
->obj
.force
= forced
;
111 int ret
= probe(VLC_OBJECT(demux
));
113 vlc_objres_clear(VLC_OBJECT(demux
));
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
))
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
))
136 p_demux
->psz_url
= strdup(url
);
137 if (unlikely(p_demux
->psz_url
== NULL
))
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 */
145 msg_Dbg( p_obj
, "creating demux \"%s\", URL: %s, path: %s",
146 module
, url
, p_demux
->psz_filepath
);
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
;
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
);
165 module
= demux_NameFromMimeType(type
);
171 if (strcasecmp(module
, "any") == 0 && p_demux
->psz_filepath
!= NULL
)
173 const char *ext
= strrchr(p_demux
->psz_filepath
, '.');
176 if (b_preparsing
&& !vlc_ascii_strcasecmp(ext
, ".mp3"))
179 if (likely(asprintf(&modbuf
, "ext-%s", ext
+ 1) >= 0))
185 priv
->module
= vlc_module_load(p_demux
, "demux", module
, strict
,
186 demux_Probe
, p_demux
);
189 if (priv
->module
== NULL
)
191 free( p_demux
->psz_filepath
);
197 free( p_demux
->psz_name
);
198 stream_CommonDelete( p_demux
);
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
)
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
);
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
) )
270 case DEMUX_CAN_PAUSE
:
271 case DEMUX_CAN_CONTROL_PACE
:
272 case DEMUX_GET_PTS_DELAY
:
274 case DEMUX_GET_SIGNAL
:
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
);
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
);
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
);
304 case DEMUX_GET_NORMAL_TIME
:
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
) )
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
) )
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
:
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
:
352 case DEMUX_NAV_RIGHT
:
353 case DEMUX_NAV_POPUP
:
355 case DEMUX_FILTER_ENABLE
:
356 case DEMUX_FILTER_DISABLE
:
359 case DEMUX_SET_TITLE
:
360 case DEMUX_SET_SEEKPOINT
:
361 case DEMUX_SET_RECORD_STATE
:
364 msg_Err( s
, "unknown query 0x%x in %s", i_query
, __func__
);
370 /****************************************************************************
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" );
380 es_format_Clean( p_fmt
);
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
);
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
))
423 int demux_GetTitle( demux_t
*p_demux
)
427 if (demux_Control(p_demux
, DEMUX_GET_TITLE
, &title
))
432 int demux_GetSeekpoint( demux_t
*p_demux
)
436 if (demux_Control(p_demux
, DEMUX_GET_SEEKPOINT
, &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
),
447 if (unlikely(p_demux
== NULL
))
450 priv
= vlc_stream_Private(p_demux
);
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
;
460 priv
->module
= module_need(p_demux
, "demux_filter", p_name
,
462 if (priv
->module
== NULL
)
467 stream_CommonDelete( p_demux
);
471 demux_t
*demux_FilterChainNew( demux_t
*p_demux
, const char *psz_chain
)
473 if( !psz_chain
|| !*psz_chain
)
476 char *psz_parser
= strdup(psz_chain
);
483 config_chain_t
*p_cfg
;
485 char *psz_rest_chain
= config_ChainCreate( &psz_name
, &p_cfg
, psz_parser
);
487 psz_parser
= psz_rest_chain
;
489 demux_t
*filter
= demux_FilterNew(p_demux
, psz_name
);
494 config_ChainDestroy(p_cfg
);
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
);
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
);
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 );