[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