[vlc-devel] [PATCH 1/2] [RFC] core: add a demux-filter similar to stream-filter for demuxers
Rémi Denis-Courmont
remi at remlab.net
Sat Apr 23 11:27:43 CEST 2016
On Friday 22 April 2016 17:57:20 Steve Lhomme wrote:
> it allows filtering the Demux calls to the underlying muxer
> it can be chained like stream-filters
> internally it's a regular demuxer_t with the p_source demuxer set
>
> the base value of "demux-filter" is set in libvlc, each input_thread_t has
> their own copy
> diff --git a/include/vlc_demux.h b/include/vlc_demux.h
> index 45f5416..0dcee90 100644
> --- a/include/vlc_demux.h
> +++ b/include/vlc_demux.h
> @@ -77,6 +77,10 @@ struct demux_t
>
> /* Weak link to parent input */
> input_thread_t *p_input;
> +
> + /* for demux-filter */
> + demux_t *p_source;
union with s.
> + config_chain_t *p_cfg;
This is pointless. A demux can´t spawn a chain.
Also I don´t get how the filter is supposed to pass on ES output requests, and
direct accesses from access/stream/demux to p_input.
> };
>
> /* pf_demux return values */
> @@ -396,6 +400,11 @@ VLC_API void demux_PacketizerDestroy( decoder_t
> *p_packetizer ); } while(0)
>
> /**
> + * This function will create a packetizer suitable for a demuxer that
> parses + */
> +VLC_API demux_t *demux_FilterChainNew( demux_t *p_demux, const char
> *psz_name ); +
> +/**
> * @}
> */
>
> diff --git a/include/vlc_plugin.h b/include/vlc_plugin.h
> index 42c3288..2e9d4d8 100644
> --- a/include/vlc_plugin.h
> +++ b/include/vlc_plugin.h
> @@ -165,6 +165,7 @@ enum vlc_module_properties
> #define SUBCAT_INPUT_ACODEC 405
> #define SUBCAT_INPUT_SCODEC 406
> #define SUBCAT_INPUT_STREAM_FILTER 407
> +#define SUBCAT_INPUT_DEMUX_FILTER 408
>
> #define CAT_SOUT 5
> #define SUBCAT_SOUT_GENERAL 501
> diff --git a/src/input/demux.c b/src/input/demux.c
> index 303c0b8..e26f7e5 100644
> --- a/src/input/demux.c
> +++ b/src/input/demux.c
> @@ -84,7 +84,7 @@ demux_t *demux_New( vlc_object_t *p_obj, const char
> *psz_name, return demux_NewAdvanced( p_obj, NULL,
> (s == NULL) ? psz_name : "",
> (s != NULL) ? psz_name : "",
> - psz_location, s, out, false );
> + psz_location, s, out, false, NULL, NULL );
> }
>
> /**************************************************************************
> *** @@ -95,7 +95,8 @@ demux_t *demux_New( vlc_object_t *p_obj, const char
> *psz_name, demux_t *demux_NewAdvanced( vlc_object_t *p_obj, input_thread_t
> *p_parent_input, const char *psz_access, const char *psz_demux, const char
> *psz_location,
> - stream_t *s, es_out_t *out, bool b_quick )
> + stream_t *s, es_out_t *out, bool b_quick,
> + demux_t *p_wrapped, config_chain_t *p_cfg )
> {
> demux_t *p_demux = vlc_custom_create( p_obj, sizeof( *p_demux ),
> "demux" ); if( unlikely(p_demux == NULL) )
> @@ -116,6 +117,8 @@ demux_t *demux_NewAdvanced( vlc_object_t *p_obj,
> input_thread_t *p_parent_input, p_demux->psz_demux = strdup( psz_demux );
> p_demux->psz_location = strdup( psz_location );
> p_demux->psz_file = get_path( psz_location ); /* parse URL */
> + p_demux->p_source = p_wrapped;
> + p_demux->p_cfg = p_cfg;
>
> if( unlikely(p_demux->psz_access == NULL
>
> || p_demux->psz_demux == NULL
>
> @@ -275,7 +278,7 @@ demux_t *input_DemuxNew( vlc_object_t *obj, const char
> *access_name, }
> else /* Try access_demux first */
> demux = demux_NewAdvanced( obj, input, access_name, demux_name,
> path, - NULL, out, false );
> + NULL, out, false, NULL, NULL );
>
> if( demux == NULL )
> { /* Then try a real access,stream,demux chain */
> @@ -323,7 +326,7 @@ demux_t *input_DemuxNew( vlc_object_t *obj, const char
> *access_name, }
>
> demux = demux_NewAdvanced( obj, input, access_name, demux_name,
> path, - stream, out, quick );
> + stream, out, quick, NULL, NULL );
> if( demux == NULL )
> {
> msg_Err( obj, "cannot parse %s://%s", access_name, path );
> diff --git a/src/input/demux.h b/src/input/demux.h
> index f841f68..9a5b557 100644
> --- a/src/input/demux.h
> +++ b/src/input/demux.h
> @@ -33,8 +33,10 @@
> /* stream_t *s could be null and then it mean a access+demux in one */
> demux_t *demux_NewAdvanced( vlc_object_t *p_obj, input_thread_t
> *p_parent_input, const char *psz_access, const char *psz_demux, -
> const char *psz_path, stream_t *s, es_out_t *out, bool );
> -#define demux_NewAdvanced( a, b, c, d, e, f, g, h )
> demux_NewAdvanced(VLC_OBJECT(a),b,c,d,e,f,g,h) +
> const char *psz_path, stream_t *s, es_out_t *out, bool, +
> demux_t *p_wrapped, config_chain_t *p_cfg ); +#define
> demux_NewAdvanced( a, b, c, d, e, f, g, h, i, j ) \
> + demux_NewAdvanced(VLC_OBJECT(a),b,c,d,e,f,g,h,i,j)
>
> demux_t *input_DemuxNew( vlc_object_t *, const char *access, const char
> *demux, const char *path, es_out_t *out, bool quick, diff --git
> a/src/input/input.c b/src/input/input.c
> index e8a6f9e..7e9c0bc 100644
> --- a/src/input/input.c
> +++ b/src/input/input.c
> @@ -78,7 +78,8 @@ static void MRLSections( const char *, int *, int *, int
> *, int *);
>
> static input_source_t *InputSourceNew( input_thread_t *, const char *,
> const char *psz_forced_demux,
> - bool b_in_can_fail );
> + bool b_in_can_fail, bool
> b_with_filter ); +static void UpdateDemuxer(input_thread_t *,
> input_source_t *, const char *psz_demux_chain); static void
> InputSourceDestroy( input_source_t * );
> static void InputSourceMeta( input_thread_t *, input_source_t *, vlc_meta_t
> * ); #ifdef ENABLE_SOUT
> @@ -1088,7 +1089,7 @@ static void LoadSlaves( input_thread_t *p_input )
> continue;
> msg_Dbg( p_input, "adding slave input '%s'", uri );
>
> - input_source_t *p_slave = InputSourceNew( p_input, uri, NULL, false
> );
> + input_source_t *p_slave = InputSourceNew( p_input, uri, NULL,
> false, false );
That´s bizarre.
> if( p_slave )
> TAB_APPEND( p_input->p->i_slave, p_input->p->slave, p_slave );
> free( uri );
> @@ -1191,6 +1192,7 @@ static int Init( input_thread_t * p_input )
> msg_Dbg( p_input, "Input is a meta file: disabling unneeded
> options" ); var_SetString( p_input, "sout", "" );
> var_SetBool( p_input, "sout-all", false );
> + var_SetString( p_input, "demux-filter", "" );
I don´t really see the point in a demux filter if it can´t modify anything.
> var_SetString( p_input, "input-slave", "" );
> var_SetInteger( p_input, "input-repeat", 0 );
> var_SetString( p_input, "sub-file", "" );
> @@ -1203,6 +1205,10 @@ static int Init( input_thread_t * p_input )
> goto error;
> #endif
>
> + /* the sout may have modified the "demux-filter" */
Hell no.
> + char *psz_fwd_var = var_GetString( p_input->p_libvlc, "demux-filter" );
> + var_SetString( p_input, "demux-filter", psz_fwd_var );
> +
> /* Create es out */
> p_input->p->p_es_out = input_EsOutTimeshiftNew( p_input,
> p_input->p->p_es_out_display, p_input->p->i_rate );
>
> @@ -1212,7 +1218,7 @@ static int Init( input_thread_t * p_input )
>
> /* */
> master = InputSourceNew( p_input, p_input->p->p_item->psz_uri, NULL,
> - false );
> + false, true );
> if( master == NULL )
> goto error;
> p_input->p->master = master;
> @@ -1924,7 +1930,7 @@ static bool Control( input_thread_t *p_input,
> {
> const char *uri = val.psz_string;
> input_source_t *slave = InputSourceNew( p_input, uri, NULL,
> - false );
> + false, false );
> if( slave == NULL )
> {
> msg_Warn( p_input, "failed to add %s as slave", uri );
> @@ -2145,7 +2151,8 @@ static void UpdateTitleListfromDemux( input_thread_t
> *p_input ) static input_source_t *InputSourceNew( input_thread_t *p_input,
> const char *psz_mrl,
> const char *psz_forced_demux,
> - bool b_in_can_fail )
> + bool b_in_can_fail,
> + bool b_with_filter)
I don´t see why there should be a flag here.
> {
> input_source_t *in = vlc_custom_create( p_input, sizeof( *in ),
> "input source" );
> @@ -2244,6 +2251,31 @@ static input_source_t *InputSourceNew( input_thread_t
> *p_input, return NULL;
> }
>
> + char *psz_demux_chain = NULL;
> + if (b_with_filter)
> + psz_demux_chain = var_InheritString(p_input, "demux-filter");
> + UpdateDemuxer( p_input, in, psz_demux_chain );
> + if (psz_demux_chain)
> + free(psz_demux_chain);
> +
> + if( var_GetInteger( p_input, "clock-synchro" ) != -1 )
> + in->b_can_pace_control = !var_GetInteger( p_input, "clock-synchro"
> ); +
> + return in;
> +}
> +
> +static void UpdateDemuxer(input_thread_t *p_input, input_source_t *in,
> const char *psz_var_demux_filters) +{
> + /* add the chain of demux filters */
> + if (psz_var_demux_filters != NULL && psz_var_demux_filters[0])
> + {
> + demux_t *p_filtered_demux = demux_FilterChainNew(in->p_demux,
> psz_var_demux_filters); + if (p_filtered_demux == NULL)
> + msg_Dbg(p_input, "Failed to create demux filter %s",
> psz_var_demux_filters); + else
> + in->p_demux = p_filtered_demux;
> + }
> +
> /* Get infos from (access_)demux */
> bool b_can_seek;
> if( demux_Control( in->p_demux, DEMUX_CAN_SEEK, &b_can_seek ) )
> @@ -2331,11 +2363,6 @@ static input_source_t *InputSourceNew( input_thread_t
> *p_input,
>
> if( demux_Control( in->p_demux, DEMUX_GET_FPS, &in->f_fps ) )
> in->f_fps = 0.f;
> -
> - if( var_GetInteger( p_input, "clock-synchro" ) != -1 )
> - in->b_can_pace_control = !var_GetInteger( p_input, "clock-synchro"
> ); -
> - return in;
> }
>
> /**************************************************************************
> *** @@ -2346,7 +2373,17 @@ static void InputSourceDestroy( input_source_t
> *in ) int i;
>
> if( in->p_demux )
> + {
> + while (in->p_demux->p_source )
> + {
> + demux_t *p_old = in->p_demux;
> + in->p_demux = p_old->p_source;
> + in->p_demux->s = p_old->s;
> + p_old->s = NULL;
> + demux_Delete( p_old );
> + }
> demux_Delete( in->p_demux );
> + }
>
> if( in->i_title > 0 )
> {
> @@ -2831,7 +2868,7 @@ static void input_SubtitleAdd( input_thread_t
> *p_input, var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &count, NULL
> );
>
> input_source_t *sub = InputSourceNew( p_input, url, "subtitle",
> - (i_flags & SUB_CANFAIL) );
> + (i_flags & SUB_CANFAIL), false );
> if( sub == NULL )
> return;
>
> diff --git a/src/input/stream_demux.c b/src/input/stream_demux.c
> index 76ca3e3..b06d250 100644
> --- a/src/input/stream_demux.c
> +++ b/src/input/stream_demux.c
> @@ -249,7 +249,7 @@ static void* DStreamThread( void *obj )
>
> /* Create the demuxer */
> p_demux = demux_NewAdvanced( s, s->p_input, "", p_sys->psz_name, "",
> - s, p_sys->out, false );
> + s, p_sys->out, false, NULL, NULL );
> if( p_demux == NULL )
> return NULL;
>
> diff --git a/src/input/var.c b/src/input/var.c
> index 0cc1217..080f358 100644
> --- a/src/input/var.c
> +++ b/src/input/var.c
> @@ -505,6 +505,7 @@ void input_ConfigVarInit ( input_thread_t *p_input )
> /* */
> var_Create( p_input, "access", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
> var_Create( p_input, "demux", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
> + var_Create( p_input, "demux-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT
> ); var_Create( p_input, "stream-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT
> );
>
> /* Meta */
> diff --git a/src/libvlc-module.c b/src/libvlc-module.c
> index 5c6a6e0..ebd89ba 100644
> --- a/src/libvlc-module.c
> +++ b/src/libvlc-module.c
> @@ -988,6 +988,10 @@ static const char *const ppsz_prefres[] = {
> #define STREAM_FILTER_LONGTEXT N_( \
> "Stream filters are used to modify the stream that is being read. " )
>
> +#define DEMUX_FILTER_TEXT N_("Demux filter module")
> +#define DEMUX_FILTER_LONGTEXT N_( \
> + "Demux filters are used to modify/control the stream that is being
> read. " ) +
> #define DEMUX_TEXT N_("Demux module")
> #define DEMUX_LONGTEXT N_( \
> "Demultiplexers are used to separate the \"elementary\" streams " \
> @@ -1881,6 +1885,10 @@ vlc_module_begin ()
> add_module_list( "stream-filter", "stream_filter", NULL,
> STREAM_FILTER_TEXT, STREAM_FILTER_LONGTEXT, false )
>
> + set_subcategory( SUBCAT_INPUT_DEMUX_FILTER )
> + add_module_list( "demux-filter", "demux_filter", NULL,
> + DEMUX_FILTER_TEXT, DEMUX_FILTER_LONGTEXT, false )
> +
>
> /* Stream output options */
> set_category( CAT_SOUT )
> diff --git a/src/libvlc.c b/src/libvlc.c
> index 30bb985..d06f6dd 100644
> --- a/src/libvlc.c
> +++ b/src/libvlc.c
> @@ -411,7 +411,7 @@ dbus_out:
>
> /* dynamic variables that may have already been set in the command-line
> */ var_Create( p_libvlc, "sout", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); -
> + var_Create( p_libvlc, "demux-filter", VLC_VAR_STRING |
> VLC_VAR_DOINHERIT );
>
> /* System specific configuration */
> system_Configure( p_libvlc, i_argc - vlc_optind, ppsz_argv + vlc_optind
> );
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list