[vlc-devel] [PATCH 2/2] core: add demux filters that are similar in API to regular demuxers

Rémi Denis-Courmont remi at remlab.net
Wed Jun 15 09:06:29 CEST 2016


Le 2016-06-12 08:22, Steve Lhomme a écrit :
> ---
>  NEWS                  |  3 ++
>  include/vlc_demux.h   |  3 ++
>  src/input/demux.c     | 95
> +++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/input/demux.h     |  2 ++
>  src/input/input.c     | 15 ++++++++
>  src/input/var.c       |  1 +
>  src/libvlc-module.c   |  5 +++
>  src/playlist/engine.c |  1 +
>  8 files changed, 125 insertions(+)
>
> diff --git a/NEWS b/NEWS
> index 352f2b0..008ecec 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -101,6 +101,9 @@ Stream filter:
>   * Added stream prebuffering plugin
>   * Removed HTTP Live streaming stream filter
>   * Added zlib (a.k.a. deflate) decompression filter
> +
> +Demux filter:
> + * Added a demuxer filter chain to filter or intercept control
> commands and demuxing
>
>  Audio output:
>   * Complete rewrite of the AudioTrack Android module. This is now
> the default.
> diff --git a/include/vlc_demux.h b/include/vlc_demux.h
> index 33f7df3..82b4dd4 100644
> --- a/include/vlc_demux.h
> +++ b/include/vlc_demux.h
> @@ -79,6 +79,9 @@ struct demux_t
>
>      /* Weak link to parent input */
>      input_thread_t *p_input;
> +
> +    /* demux_t filter chaining */
> +    demux_t        *p_next;

I think I already mentioned it, but that ought to be unionized with s.

>  };
>
>  /* pf_demux return values */
> diff --git a/src/input/demux.c b/src/input/demux.c
> index 9d962f5..3f5d0c9 100644
> --- a/src/input/demux.c
> +++ b/src/input/demux.c
> @@ -134,6 +134,7 @@ demux_t *demux_NewAdvanced( vlc_object_t *p_obj,
> input_thread_t *p_parent_input,
>
>      p_demux->pf_demux   = NULL;
>      p_demux->pf_control = NULL;
> +    p_demux->p_next     = NULL;

Pointless. A plugin should intrinsically know if it's an 
access_demux/demux or a demux_filter.

>      p_demux->p_sys      = NULL;
>      p_demux->info.i_update = 0;
>      p_demux->info.i_title  = 0;
> @@ -343,6 +344,10 @@ void demux_Delete( demux_t *p_demux )
>  {
>      stream_t *s;
>
> +    demux_t *p_next = p_demux->p_next;
> +    if ( p_next != NULL )
> +        demux_Delete( p_next );

Potential use after free...

> +
>      module_unneed( p_demux, p_demux->p_module );

... in there ^.

>      free( p_demux->psz_file );
>      free( p_demux->psz_location );
> @@ -682,3 +687,93 @@ int demux_GetSeekpoint( demux_t *p_demux )
>          return i_seekpoint;
>      return p_demux->info.i_seekpoint;
>  }
> +
> +static demux_t *demux_FilterNew( demux_t *p_next, const char *p_name 
> )
> +{
> +    demux_t *p_demux = vlc_custom_create( p_next, sizeof( demux_t ),
> "demux_filter" );
> +    if( unlikely(p_demux == NULL) )
> +        return NULL;
> +
> +    p_demux->p_next       = p_next;
> +    p_demux->s            = NULL;
> +    p_demux->p_input      = NULL;
> +    p_demux->p_sys        = NULL;
> +    p_demux->psz_access   = NULL;
> +    p_demux->psz_demux    = NULL;
> +    p_demux->psz_location = NULL;
> +    p_demux->psz_file     = NULL;
> +    p_demux->out          = NULL;
> +    p_demux->p_module =
> +        module_need( p_demux, "demux_filter", p_name, p_name != NULL 
> );
> +
> +    if( p_demux->p_module == NULL )
> +        goto error;
> +
> +    return p_demux;
> +error:
> +    vlc_object_release( p_demux );
> +    return NULL;
> +}
> +
> +demux_t *demux_FilterChainNew( demux_t *p_demux, const char 
> *psz_chain )
> +{
> +    if( !psz_chain || !*psz_chain )
> +        return NULL;
> +
> +    char *psz_parser = strdup(psz_chain);
> +    if(!psz_parser)
> +        return NULL;
> +
> +    vlc_array_t name;
> +    vlc_array_init(&name);
> +
> +    /* parse chain */
> +    while(psz_parser)
> +    {
> +        config_chain_t *p_cfg;
> +        char *psz_name;
> +        char *psz_rest_chain = config_ChainCreate( &psz_name,
> &p_cfg, psz_parser );
> +        free( psz_parser );
> +        psz_parser = psz_rest_chain;
> +
> +        vlc_array_append(&name, psz_name);
> +        config_ChainDestroy(p_cfg);
> +    }
> +
> +    int i = vlc_array_count(&name);
> +    vlc_array_t module;
> +    vlc_array_init(&module);
> +    while(i--)
> +    {
> +        const char *p_name = vlc_array_item_at_index(&name, i);
> +        demux_t *p_next = demux_FilterNew( p_demux, p_name );
> +        if(!p_next)
> +            goto error;
> +
> +        vlc_array_append(&module, p_next);
> +        p_demux = p_next;
> +    }
> +
> +    vlc_array_clear(&name);
> +    vlc_array_clear(&module);
> +
> +    return p_demux;
> + error:
> +    i++;    /* last module couldn't be created */
> +
> +    /* destroy all modules created, starting with the last one */
> +    int modules = vlc_array_count(&module);
> +    while(modules--)
> +        demux_Delete(vlc_array_item_at_index(&module, modules));

Dubious.

> +    vlc_array_clear(&module);
> +
> +    /* then destroy all names and config which weren't destroyed by
> +     * sout_StreamDelete */


??????

> +    while(i--)
> +    {
> +        free(vlc_array_item_at_index(&name, i));
> +    }
> +    vlc_array_clear(&name);
> +
> +    return NULL;
> +}
> diff --git a/src/input/demux.h b/src/input/demux.h
> index 5b75cbc..c981a8d 100644
> --- a/src/input/demux.h
> +++ b/src/input/demux.h
> @@ -44,4 +44,6 @@ unsigned demux_TestAndClearFlags( demux_t *, 
> unsigned );
>  int demux_GetTitle( demux_t * );
>  int demux_GetSeekpoint( demux_t * );
>
> +demux_t *demux_FilterChainNew( demux_t *p_demux, const char 
> *psz_name );
> +
>  #endif
> diff --git a/src/input/input.c b/src/input/input.c
> index 43965ea..4207bd9 100644
> --- a/src/input/input.c
> +++ b/src/input/input.c
> @@ -682,6 +682,8 @@ static void MainLoop( input_thread_t *p_input,
> bool b_interactive )
>                               var_InheritBool( p_input, 
> "play-and-pause" );
>
>      demux_t *p_demux = p_input->p->master->p_demux;
> +    while (p_demux->p_next)
> +        p_demux = p_demux->p_next;
>      const bool b_can_demux = p_demux->pf_demux != NULL;
>
>      while( !input_Stopped( p_input ) && p_input->p->i_state != 
> ERROR_S )
> @@ -1852,6 +1854,8 @@ static bool Control( input_thread_t *p_input,
>              {
>                  demux_t *p_demux = p_input->p->master->p_demux;
>                  int i_ret = VLC_EGENERIC;
> +                while (p_demux->p_next)
> +                    p_demux = p_demux->p_next;

NO. ONCE AGAIN, YOU CANNOT DO THAT. p_next belongs to p_demux, and only 
to p_demux. Input thread cannot use it, at least not after it's handed 
over to p_demux.

And yes, it means that the following predicate can no longer be 
computed. But that's quite normal since that predicate no longer makes 
any sense if you have a demux-filter:

>
>                  if( p_demux->s == NULL )
>                  {
> @@ -2298,6 +2302,15 @@ static input_source_t *InputSourceNew(
> input_thread_t *p_input,
>          return NULL;
>      }
>
> +    char *psz_demux_chain = var_GetNonEmptyString(p_input, 
> "demux-filter");
> +    /* add the chain of demux filters */
> +    demux_t *p_filtered_demux = demux_FilterChainNew( in->p_demux,
> psz_demux_chain );
> +    if ( p_filtered_demux != NULL )
> +        in->p_demux = p_filtered_demux;
> +    else if ( psz_demux_chain != NULL )
> +        msg_Dbg(p_input, "Failed to create demux filter %s",
> psz_demux_chain);
> +    free( psz_demux_chain );
> +
>      /* Get infos from (access_)demux */
>      bool b_can_seek;
>      if( demux_Control( in->p_demux, DEMUX_CAN_SEEK, &b_can_seek ) )
> @@ -2309,6 +2322,8 @@ static input_source_t *InputSourceNew(
> input_thread_t *p_input,
>          in->b_can_pace_control = false;
>
>      demux_t *p_demux = in->p_demux;
> +    while (p_demux->p_next)
> +        p_demux = p_demux->p_next;

Same as above.

>      assert( p_demux->pf_demux != NULL || !in->b_can_pace_control );
>
>      if( p_demux->s != NULL )
> diff --git a/src/input/var.c b/src/input/var.c
> index 6534603..437c614 100644
> --- a/src/input/var.c
> +++ b/src/input/var.c
> @@ -513,6 +513,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 0fee435..ee9566d 100644
> --- a/src/libvlc-module.c
> +++ b/src/libvlc-module.c
> @@ -993,6 +993,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 
> " \
> @@ -1888,6 +1892,7 @@ vlc_module_begin ()
>      add_module_list( "stream-filter", "stream_filter", NULL,
>                       STREAM_FILTER_TEXT, STREAM_FILTER_LONGTEXT, 
> false )
>
> +    add_string( "demux-filter", NULL, DEMUX_FILTER_TEXT,
> DEMUX_FILTER_LONGTEXT, true )
>
>  /* Stream output options */
>      set_category( CAT_SOUT )
> diff --git a/src/playlist/engine.c b/src/playlist/engine.c
> index 9f3abf0..1ff64c7 100644
> --- a/src/playlist/engine.c
> +++ b/src/playlist/engine.c
> @@ -472,6 +472,7 @@ static void VariablesInit( playlist_t *p_playlist 
> )
>
>      /* sout variables */
>      var_Create( p_playlist, "sout", VLC_VAR_STRING | 
> VLC_VAR_DOINHERIT );
> +    var_Create( p_playlist, "demux-filter", VLC_VAR_STRING |
> VLC_VAR_DOINHERIT );
>
>      /* */
>      var_Create( p_playlist, "album-art", VLC_VAR_INTEGER |
> VLC_VAR_DOINHERIT );

-- 
Rémi Denis-Courmont
http://www.remlab.net/


More information about the vlc-devel mailing list