[vlc-devel] [PATCH 01/10] [RFC] core: add demux-filter objects to intercept & filter demuxer calls

Steve Lhomme robux4 at videolabs.io
Mon May 9 13:18:53 CEST 2016


This can be used to tweak the results of some Control() calls or delay the
actual Demux() call.

--
removed the config parameters from the demux-filter API from
https://patches.videolan.org/patch/13144/
---
 NEWS                                        |   3 +
 include/vlc_common.h                        |   1 +
 include/vlc_demux.h                         |  69 +++++++++++++++----
 modules/demux/adaptive/plumbing/Demuxer.cpp |   8 +--
 src/input/demux.c                           | 100 ++++++++++++++++++++++++++++
 src/input/input.c                           |  69 ++++++++++---------
 src/input/input_internal.h                  |   2 +-
 src/input/var.c                             |   1 +
 src/libvlc-module.c                         |   5 ++
 src/libvlc.c                                |   2 +
 10 files changed, 212 insertions(+), 48 deletions(-)

diff --git a/NEWS b/NEWS
index 73b06a5..4457b87 100644
--- a/NEWS
+++ b/NEWS
@@ -99,6 +99,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_common.h b/include/vlc_common.h
index f05d9c6..4bc9698 100644
--- a/include/vlc_common.h
+++ b/include/vlc_common.h
@@ -227,6 +227,7 @@ typedef struct stream_t     stream_t;
 typedef struct stream_sys_t stream_sys_t;
 typedef struct demux_t  demux_t;
 typedef struct demux_sys_t demux_sys_t;
+typedef struct demux_filter_t  demux_filter_t;
 typedef struct es_out_t     es_out_t;
 typedef struct es_out_id_t  es_out_id_t;
 typedef struct es_out_sys_t es_out_sys_t;
diff --git a/include/vlc_demux.h b/include/vlc_demux.h
index 45f5416..836adac 100644
--- a/include/vlc_demux.h
+++ b/include/vlc_demux.h
@@ -40,12 +40,23 @@
  * Demultiplexer modules interface
  */
 
+#define DEMUX_FILTER_COMMON_MEMBERS                                  \
+    VLC_COMMON_MEMBERS                                               \
+    module_t    *p_module;                                           \
+    union {                                                          \
+        int (*pf_demux)       ( demux_t * );                         \
+        int (*pf_filter_demux)( demux_filter_t * );                  \
+    };                                                               \
+    union {                                                          \
+        int (*pf_control)( demux_t *, int i_query, va_list args);    \
+        int (*pf_filter_control)( demux_filter_t *, int i_query, va_list args);        \
+    };                                                               \
+    demux_sys_t *p_sys;                                              \
+    demux_filter_t       *p_next;
+
 struct demux_t
 {
-    VLC_COMMON_MEMBERS
-
-    /* Module properties */
-    module_t    *p_module;
+    DEMUX_FILTER_COMMON_MEMBERS
 
     /* eg informative but needed (we can have access+demux) */
     char        *psz_access;
@@ -59,10 +70,6 @@ struct demux_t
     /* es output */
     es_out_t    *out;   /* our p_es_out */
 
-    /* set by demuxer */
-    int (*pf_demux)  ( demux_t * );   /* demux one frame only */
-    int (*pf_control)( demux_t *, int i_query, va_list args);
-
     /* Demux has to maintain them uptodate
      * when it is responsible of seekpoint/title */
     struct
@@ -73,12 +80,16 @@ struct demux_t
         int          i_title;       /* idem, start from 0 (could be menu) */
         int          i_seekpoint;   /* idem, start from 0 */
     } info;
-    demux_sys_t *p_sys;
 
     /* Weak link to parent input */
     input_thread_t *p_input;
 };
 
+struct demux_filter_t
+{
+    DEMUX_FILTER_COMMON_MEMBERS
+};
+
 /* pf_demux return values */
 #define VLC_DEMUXER_EOF       0
 #define VLC_DEMUXER_EGENERIC -1
@@ -294,27 +305,56 @@ VLC_API void demux_Delete( demux_t * );
 VLC_API int demux_vaControlHelper( stream_t *, int64_t i_start, int64_t i_end,
                                    int64_t i_bitrate, int i_align, int i_query, va_list args );
 
-VLC_USED static inline int demux_Demux( demux_t *p_demux )
+VLC_USED static inline demux_t *demux_FilterDemuxer( demux_filter_t *p_filter )
+{
+    while ( p_filter->p_next )
+        p_filter = p_filter->p_next;
+    return (demux_t *) p_filter;
+}
+
+VLC_USED static inline int demux_Demux( demux_filter_t *p_demux )
 {
     if( !p_demux->pf_demux )
         return 1;
 
-    return p_demux->pf_demux( p_demux );
+    return p_demux->pf_filter_demux( p_demux );
+}
+
+VLC_USED static inline int demux_FilterDemuxNext( demux_filter_t *p_demux_filter )
+{
+    p_demux_filter = p_demux_filter->p_next;
+    if ( p_demux_filter->p_next != NULL )
+        return p_demux_filter->pf_filter_demux( p_demux_filter );
+    /* last in the chain is the real demuxer */
+    return demux_Demux( p_demux_filter );
 }
 
 VLC_API int demux_vaControl( demux_t *p_demux, int i_query, va_list args );
 
-static inline int demux_Control( demux_t *p_demux, int i_query, ... )
+static inline int demux_Control( demux_filter_t *p_demux, int i_query, ... )
 {
     va_list args;
     int     i_result;
 
     va_start( args, i_query );
-    i_result = demux_vaControl( p_demux, i_query, args );
+    if ( p_demux->p_next != NULL )
+        i_result = p_demux->pf_filter_control( p_demux, i_query, args );
+    else
+        /* last in the chain is the real demuxer */
+        i_result = demux_vaControl( (demux_t*) p_demux, i_query, args  );
     va_end( args );
     return i_result;
 }
 
+VLC_USED static inline int demux_vaFilterControlNext( demux_filter_t *p_demux_filter, int i_query, va_list args )
+{
+    p_demux_filter = p_demux_filter->p_next;
+    if ( p_demux_filter->p_next != NULL )
+        return p_demux_filter->pf_filter_control( p_demux_filter, i_query, args );
+    /* last in the chain is the real demuxer */
+    return demux_vaControl( (demux_t*) p_demux_filter, i_query, args );
+}
+
 /*************************************************************************
  * Miscellaneous helpers for demuxers
  *************************************************************************/
@@ -395,6 +435,9 @@ VLC_API void demux_PacketizerDestroy( decoder_t *p_packetizer );
     if( !p_demux->p_sys ) return VLC_ENOMEM;\
     } while(0)
 
+demux_filter_t *demux_FilterChainNew( demux_filter_t *p_demux, const char *psz_name );
+void demux_FilterDelete( demux_filter_t * );
+
 /**
  * @}
  */
diff --git a/modules/demux/adaptive/plumbing/Demuxer.cpp b/modules/demux/adaptive/plumbing/Demuxer.cpp
index 1ad942e..560e07c 100644
--- a/modules/demux/adaptive/plumbing/Demuxer.cpp
+++ b/modules/demux/adaptive/plumbing/Demuxer.cpp
@@ -106,14 +106,14 @@ bool Demuxer::restart(CommandsQueue &queue)
 
 void Demuxer::drain()
 {
-    while(p_demux && demux_Demux(p_demux) == VLC_DEMUXER_SUCCESS);
+    while(p_demux && demux_Demux((demux_filter_t*) p_demux) == VLC_DEMUXER_SUCCESS);
 }
 
 int Demuxer::demux(mtime_t)
 {
     if(!p_demux || b_eof)
         return VLC_DEMUXER_EOF;
-    int i_ret = demux_Demux(p_demux);
+    int i_ret = demux_Demux( (demux_filter_t*) p_demux);
     if(i_ret != VLC_DEMUXER_SUCCESS)
         b_eof = true;
     return i_ret;
@@ -137,7 +137,7 @@ bool SlaveDemuxer::create()
     if(Demuxer::create())
     {
         length = VLC_TS_INVALID;
-        if(demux_Control(p_demux, DEMUX_GET_LENGTH, &length) != VLC_SUCCESS)
+        if(demux_Control( (demux_filter_t*) p_demux, DEMUX_GET_LENGTH, &length) != VLC_SUCCESS)
             b_eof = true;
         return true;
     }
@@ -146,7 +146,7 @@ bool SlaveDemuxer::create()
 
 int SlaveDemuxer::demux(mtime_t nz_deadline)
 {
-    if( demux_Control(p_demux, DEMUX_SET_NEXT_DEMUX_TIME, VLC_TS_0 + nz_deadline) != VLC_SUCCESS )
+    if( demux_Control( (demux_filter_t*) p_demux, DEMUX_SET_NEXT_DEMUX_TIME, VLC_TS_0 + nz_deadline) != VLC_SUCCESS )
     {
         b_eof = true;
         return VLC_DEMUXER_EOF;
diff --git a/src/input/demux.c b/src/input/demux.c
index 303c0b8..e07d1b8 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_sys      = NULL;
+    p_demux->p_next     = NULL;
     p_demux->info.i_update = 0;
     p_demux->info.i_title  = 0;
     p_demux->info.i_seekpoint = 0;
@@ -354,6 +355,20 @@ void demux_Delete( demux_t *p_demux )
         stream_Delete( s );
 }
 
+void demux_FilterDelete( demux_filter_t *p_demux )
+{
+    demux_filter_t *p_next = p_demux->p_next;
+
+    if ( p_next == NULL )
+        demux_Delete( (demux_t *) p_demux );
+    else
+    {
+        module_unneed( p_demux, p_demux->p_module );
+        vlc_object_release( p_demux );
+        demux_FilterDelete( p_next );
+    }
+}
+
 #define static_control_match(foo) \
     static_assert((unsigned) DEMUX_##foo == STREAM_##foo, "Mismatch")
 
@@ -656,3 +671,88 @@ static bool SkipAPETag( demux_t *p_demux )
     return true;
 }
 
+static demux_filter_t *demux_FilterNew( demux_filter_t *p_wrapped, const char *p_name )
+{
+    demux_filter_t *p_demux = vlc_custom_create( VLC_OBJECT( p_wrapped ),
+                                                 sizeof( demux_filter_t ), "demux_filter" );
+    if( unlikely(p_demux == NULL) )
+        return NULL;
+
+    p_demux->pf_demux   = NULL;
+    p_demux->pf_control = NULL;
+    p_demux->p_sys      = NULL;
+    p_demux->p_next     = (demux_filter_t *) p_wrapped;
+    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_filter_t *demux_FilterChainNew( demux_filter_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_filter_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));
+    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/input.c b/src/input/input.c
index 5591a4e..cb91a2b 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -88,7 +88,7 @@ static void SlaveDemux( input_thread_t *p_input );
 static void SlaveSeek( input_thread_t *p_input );
 
 static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta );
-static void InputUpdateMeta( input_thread_t *p_input, demux_t *p_demux );
+static void InputUpdateMeta( input_thread_t *p_input, demux_filter_t *p_demux );
 static void InputGetExtraFiles( input_thread_t *p_input,
                                 int *pi_list, char ***pppsz_list,
                                 const char *psz_access, const char *psz_path );
@@ -553,12 +553,13 @@ static void MainLoopDemux( input_thread_t *p_input, bool *pb_changed )
 
     if( i_ret > 0 )
     {
-        if( p_input->p->master->p_demux->info.i_update )
+        demux_t *p_demux = demux_FilterDemuxer( p_input->p->master->p_demux );
+        if( p_demux->info.i_update )
         {
-            if( p_input->p->master->p_demux->info.i_update & INPUT_UPDATE_TITLE_LIST )
+            if( p_demux->info.i_update & INPUT_UPDATE_TITLE_LIST )
             {
                 UpdateTitleListfromDemux( p_input );
-                p_input->p->master->p_demux->info.i_update &= ~INPUT_UPDATE_TITLE_LIST;
+                p_demux->info.i_update &= ~INPUT_UPDATE_TITLE_LIST;
             }
             if( p_input->p->master->b_title_demux )
             {
@@ -696,7 +697,8 @@ static void MainLoop( input_thread_t *p_input, bool b_interactive )
 
                 MainLoopDemux( p_input, &b_force_update );
 
-                if( p_input->p->master->p_demux->pf_demux != NULL )
+                demux_t *p_demux = demux_FilterDemuxer( p_input->p->master->p_demux );
+                if( p_demux->pf_demux != NULL )
                     i_wakeup = es_out_GetWakeup( p_input->p->p_es_out );
                 if( b_force_update )
                     i_intf_update = 0;
@@ -1524,9 +1526,7 @@ static void ControlPause( input_thread_t *p_input, mtime_t i_control_date )
 
     if( p_input->p->b_can_pause )
     {
-        demux_t *p_demux = p_input->p->master->p_demux;
-
-        if( demux_Control( p_demux, DEMUX_SET_PAUSE_STATE, true ) )
+        if( demux_Control( p_input->p->master->p_demux, DEMUX_SET_PAUSE_STATE, true ) )
         {
             msg_Warn( p_input, "cannot set pause state" );
             return;
@@ -1549,9 +1549,7 @@ static void ControlUnpause( input_thread_t *p_input, mtime_t i_control_date )
 {
     if( p_input->p->b_can_pause )
     {
-        demux_t *p_demux = p_input->p->master->p_demux;
-
-        if( demux_Control( p_demux, DEMUX_SET_PAUSE_STATE, false ) )
+        if( demux_Control( p_input->p->master->p_demux, DEMUX_SET_PAUSE_STATE, false ) )
         {
             msg_Err( p_input, "cannot resume" );
             input_ChangeState( p_input, ERROR_S );
@@ -1724,7 +1722,7 @@ static bool Control( input_thread_t *p_input,
             if( i_rate != p_input->p->i_rate &&
                 !p_input->p->b_can_pace_control && p_input->p->b_can_rate_control )
             {
-                demux_t *p_demux = p_input->p->master->p_demux;
+                demux_t *p_demux = demux_FilterDemuxer( p_input->p->master->p_demux );
                 int i_ret = VLC_EGENERIC;
 
                 if( p_demux->s == NULL )
@@ -1803,7 +1801,8 @@ static bool Control( input_thread_t *p_input,
             if( p_input->p->master->i_title <= 0 )
                 break;
 
-            int i_title = p_input->p->master->p_demux->info.i_title;
+            demux_t *p_demux = demux_FilterDemuxer( p_input->p->master->p_demux );
+            int i_title = p_demux->info.i_title;
             if( i_type == INPUT_CONTROL_SET_TITLE_PREV )
                 i_title--;
             else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
@@ -1831,7 +1830,7 @@ static bool Control( input_thread_t *p_input,
             if( p_input->p->master->i_title <= 0 )
                 break;
 
-            demux_t *p_demux = p_input->p->master->p_demux;
+            demux_t *p_demux = demux_FilterDemuxer( p_input->p->master->p_demux );
 
             int i_title = p_demux->info.i_title;
             int i_seekpoint = p_demux->info.i_seekpoint;
@@ -2023,7 +2022,7 @@ static int UpdateTitleSeekpoint( input_thread_t *p_input,
  *****************************************************************************/
 static int UpdateTitleSeekpointFromDemux( input_thread_t *p_input )
 {
-    demux_t *p_demux = p_input->p->master->p_demux;
+    demux_t *p_demux = demux_FilterDemuxer( p_input->p->master->p_demux );
 
     /* TODO event-like */
     if( p_demux->info.i_update & INPUT_UPDATE_TITLE )
@@ -2047,18 +2046,18 @@ static int UpdateTitleSeekpointFromDemux( input_thread_t *p_input )
 
 static void UpdateGenericFromDemux( input_thread_t *p_input )
 {
-    demux_t *p_demux = p_input->p->master->p_demux;
+    demux_t *p_demux = demux_FilterDemuxer( p_input->p->master->p_demux );
 
     if( p_demux->info.i_update & INPUT_UPDATE_META )
     {
-        InputUpdateMeta( p_input, p_demux );
+        InputUpdateMeta( p_input, p_input->p->master->p_demux );
         p_demux->info.i_update &= ~INPUT_UPDATE_META;
     }
     {
         double quality;
         double strength;
 
-        if( !demux_Control( p_demux, DEMUX_GET_SIGNAL, &quality, &strength ) )
+        if( !demux_Control( p_input->p->master->p_demux, DEMUX_GET_SIGNAL, &quality, &strength ) )
             input_SendEventSignal( p_input, quality, strength );
     }
 }
@@ -2178,7 +2177,7 @@ static input_source_t *InputSourceNew( input_thread_t *p_input,
         TAB_CLEAN( count, tab );
     }
 
-    in->p_demux = input_DemuxNew( VLC_OBJECT(in), psz_access, psz_demux,
+    in->p_demux = (demux_filter_t*) input_DemuxNew( VLC_OBJECT(in), psz_access, psz_demux,
                                   psz_path, p_input->p->p_es_out,
                                   p_input->b_preparsing, p_input );
     free( psz_dup );
@@ -2193,6 +2192,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_filter_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 ) )
@@ -2203,9 +2211,10 @@ static input_source_t *InputSourceNew( input_thread_t *p_input,
                        &in->b_can_pace_control ) )
         in->b_can_pace_control = false;
 
-    assert( in->p_demux->pf_demux != NULL || !in->b_can_pace_control );
+    demux_t *p_demux = demux_FilterDemuxer( in->p_demux );
+    assert( p_demux->pf_demux != NULL || !in->b_can_pace_control );
 
-    if( in->p_demux->s != NULL )
+    if( p_demux->s != NULL )
     {
         if( !in->b_can_pace_control )
         {
@@ -2267,7 +2276,7 @@ static input_source_t *InputSourceNew( input_thread_t *p_input,
         {
             vlc_mutex_lock( &p_input->p->p_item->lock );
             AppendAttachment( &p_input->p->i_attachment, &p_input->p->attachment, &p_input->p->attachment_demux,
-                              i_attachment, attachment, in->p_demux );
+                              i_attachment, attachment, p_demux);
             vlc_mutex_unlock( &p_input->p->p_item->lock );
         }
 
@@ -2295,7 +2304,7 @@ static void InputSourceDestroy( input_source_t *in )
     int i;
 
     if( in->p_demux )
-        demux_Delete( in->p_demux );
+        demux_FilterDelete( in->p_demux );
 
     if( in->i_title > 0 )
     {
@@ -2311,9 +2320,9 @@ static void InputSourceDestroy( input_source_t *in )
  * InputSourceMeta:
  *****************************************************************************/
 static void InputSourceMeta( input_thread_t *p_input,
-                             input_source_t *p_source, vlc_meta_t *p_meta )
+                             input_source_t *p_next, vlc_meta_t *p_meta )
 {
-    demux_t *p_demux = p_source->p_demux;
+    demux_filter_t *p_demux = p_next->p_demux;
 
     /* XXX Remember that checking against p_item->p_meta->i_status & ITEM_PREPARSED
      * is a bad idea */
@@ -2334,7 +2343,7 @@ static void InputSourceMeta( input_thread_t *p_input,
         return;
 
     demux_meta_t *p_demux_meta =
-        vlc_custom_create( p_source, sizeof( *p_demux_meta ), "demux meta" );
+        vlc_custom_create( p_next, sizeof( *p_demux_meta ), "demux meta" );
     if( unlikely(p_demux_meta == NULL) )
         return;
     p_demux_meta->p_item = p_input->p->p_item;
@@ -2352,7 +2361,7 @@ static void InputSourceMeta( input_thread_t *p_input,
         {
             vlc_mutex_lock( &p_input->p->p_item->lock );
             AppendAttachment( &p_input->p->i_attachment, &p_input->p->attachment, &p_input->p->attachment_demux,
-                              p_demux_meta->i_attachments, p_demux_meta->attachments, p_demux);
+                              p_demux_meta->i_attachments, p_demux_meta->attachments, demux_FilterDemuxer( p_demux ));
             vlc_mutex_unlock( &p_input->p->p_item->lock );
         }
         module_unneed( p_demux, p_id3 );
@@ -2503,7 +2512,7 @@ static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_atta
  * InputUpdateMeta: merge p_item meta data with p_meta taking care of
  * arturl and locking issue.
  *****************************************************************************/
-static void InputUpdateMeta( input_thread_t *p_input, demux_t *p_demux )
+static void InputUpdateMeta( input_thread_t *p_input, demux_filter_t *p_demux )
 {
     vlc_meta_t *p_meta = vlc_meta_New();
     if( unlikely(p_meta == NULL) )
@@ -2525,7 +2534,7 @@ static void InputUpdateMeta( input_thread_t *p_input, demux_t *p_demux )
             int j = 0;
             for( int i = 0; i < p_input->p->i_attachment; i++ )
             {
-                if( p_input->p->attachment_demux[i] == p_demux )
+                if( p_input->p->attachment_demux[i] == demux_FilterDemuxer( p_demux ) )
                     vlc_input_attachment_Delete( p_input->p->attachment[i] );
                 else
                 {
@@ -2537,7 +2546,7 @@ static void InputUpdateMeta( input_thread_t *p_input, demux_t *p_demux )
             p_input->p->i_attachment = j;
         }
         AppendAttachment( &p_input->p->i_attachment, &p_input->p->attachment, &p_input->p->attachment_demux,
-                          i_attachment, attachment, p_demux );
+                          i_attachment, attachment, demux_FilterDemuxer( p_demux ) );
         vlc_mutex_unlock( &p_input->p->p_item->lock );
     }
 
diff --git a/src/input/input_internal.h b/src/input/input_internal.h
index b68bec7..b57ba2e 100644
--- a/src/input/input_internal.h
+++ b/src/input/input_internal.h
@@ -42,7 +42,7 @@ typedef struct
 {
     VLC_COMMON_MEMBERS
 
-    demux_t  *p_demux; /**< Demux plugin instance */
+    demux_filter_t  *p_demux; /**< Demux plugin instance */
 
     /* Title infos for that input */
     bool         b_title_demux; /* Titles/Seekpoints provided by demux */
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 9cd6daf..d16db8c 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -980,6 +980,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 " \
@@ -1868,6 +1872,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/libvlc.c b/src/libvlc.c
index 4e33a04..ccc62ca 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -409,6 +409,8 @@ dbus_out:
     var_Create( p_libvlc, "app-version", VLC_VAR_STRING );
     var_SetString( p_libvlc, "app-version", PACKAGE_VERSION );
 
+    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 );
 
-- 
2.7.0



More information about the vlc-devel mailing list