es_out: propagate the input_source_t
authorThomas Guillem <thomas@gllm.fr>
Tue, 11 Feb 2020 08:56:28 +0000 (09:56 +0100)
committerThomas Guillem <thomas@gllm.fr>
Fri, 28 Feb 2020 19:29:35 +0000 (20:29 +0100)
It will be used to differentiate the master source (in = NULL) from the slave
ones.

It is passed from input_EsOutSourceNew() to the timeshift es_out to the core
es_out, via cbs->add() and cbs->control().

include/vlc_es_out.h
modules/access/bluray.c
modules/demux/adaptive/plumbing/FakeESOut.cpp
modules/demux/timestamps_filter.h
src/Makefile.am
src/input/es_out.c
src/input/es_out.h
src/input/es_out_source.c [new file with mode: 0644]
src/input/es_out_timeshift.c
test/modules/demux/timestamps_filter.c

index 5cf5116..d7dd98a 100644 (file)
@@ -125,10 +125,10 @@ enum es_out_policy_e
 
 struct es_out_callbacks
 {
-    es_out_id_t *(*add)(es_out_t *, const es_format_t *);
+    es_out_id_t *(*add)(es_out_t *, input_source_t *in, const es_format_t *);
     int          (*send)(es_out_t *, es_out_id_t *, block_t *);
     void         (*del)(es_out_t *, es_out_id_t *);
-    int          (*control)(es_out_t *, int query, va_list);
+    int          (*control)(es_out_t *, input_source_t *in, int query, va_list);
     void         (*destroy)(es_out_t *);
     /**
      * Private control callback, must be NULL for es_out created from modules.
@@ -144,7 +144,7 @@ struct es_out_t
 VLC_USED
 static inline es_out_id_t * es_out_Add( es_out_t *out, const es_format_t *fmt )
 {
-    return out->cbs->add( out, fmt );
+    return out->cbs->add( out, NULL, fmt );
 }
 
 static inline void es_out_Del( es_out_t *out, es_out_id_t *id )
@@ -160,7 +160,7 @@ static inline int es_out_Send( es_out_t *out, es_out_id_t *id,
 
 static inline int es_out_vaControl( es_out_t *out, int i_query, va_list args )
 {
-    return out->cbs->control( out, i_query, args );
+    return out->cbs->control( out, NULL, i_query, args );
 }
 
 static inline int es_out_Control( es_out_t *out, int i_query, ... )
index f044063..2796f09 100644 (file)
@@ -1331,8 +1331,9 @@ static es_out_id_t *bluray_esOutAddUnlocked(bluray_esout_priv_t *esout_priv,
     return p_es;
 }
 
-static es_out_id_t *bluray_esOutAdd(es_out_t *p_out, const es_format_t *p_fmt)
+static es_out_id_t *bluray_esOutAdd(es_out_t *p_out, input_source_t *in, const es_format_t *p_fmt)
 {
+    VLC_UNUSED(in);
     bluray_esout_priv_t *esout_priv = container_of(p_out, bluray_esout_priv_t, es_out);
 
     vlc_mutex_lock(&esout_priv->lock);
@@ -1408,8 +1409,9 @@ static void bluray_esOutDel(es_out_t *p_out, es_out_id_t *p_es)
     vlc_mutex_unlock(&esout_priv->lock);
 }
 
-static int bluray_esOutControl(es_out_t *p_out, int i_query, va_list args)
+static int bluray_esOutControl(es_out_t *p_out, input_source_t *in, int i_query, va_list args)
 {
+    VLC_UNUSED(in);
     bluray_esout_priv_t *esout_priv = container_of(p_out, bluray_esout_priv_t, es_out);
     int i_ret;
     vlc_mutex_lock(&esout_priv->lock);
index f16503b..5ada11d 100644 (file)
@@ -37,10 +37,10 @@ namespace adaptive
     {
         public:
             /* static callbacks for demuxer */
-            static es_out_id_t *es_out_Add( es_out_t *, const es_format_t * );
+            static es_out_id_t *es_out_Add( es_out_t *, input_source_t *, const es_format_t * );
             static int es_out_Send( es_out_t *, es_out_id_t *, block_t * );
             static void es_out_Del( es_out_t *, es_out_id_t * );
-            static int es_out_Control( es_out_t *, int, va_list );
+            static int es_out_Control( es_out_t *, input_source_t *in, int, va_list );
             static void es_out_Destroy( es_out_t * );
             static const struct es_out_callbacks cbs;
             struct Private
@@ -60,7 +60,7 @@ const struct es_out_callbacks EsOutCallbacks::cbs =
     EsOutCallbacks::es_out_Destroy,
 };
 
-es_out_id_t * EsOutCallbacks::es_out_Add(es_out_t *fakees, const es_format_t *p_fmt)
+es_out_id_t * EsOutCallbacks::es_out_Add(es_out_t *fakees, input_source_t *, const es_format_t *p_fmt)
 {
     AbstractFakeEsOut *me = container_of(fakees, Private, es_out)->fake;
     return me->esOutAdd(p_fmt);
@@ -78,7 +78,7 @@ void EsOutCallbacks::es_out_Del(es_out_t *fakees, es_out_id_t *p_es)
     me->esOutDel(p_es);
 }
 
-int EsOutCallbacks::es_out_Control(es_out_t *fakees, int i_query, va_list args)
+int EsOutCallbacks::es_out_Control(es_out_t *fakees, input_source_t *, int i_query, va_list args)
 {
     AbstractFakeEsOut *me = container_of(fakees, Private, es_out)->fake;
     return me->esOutControl(i_query, args);
index 4d2b2e0..a356332 100644 (file)
@@ -156,8 +156,9 @@ static void timestamps_filter_es_out_Reset(struct tf_es_out_s *out)
     out->b_discontinuity = false;
 }
 
-static int timestamps_filter_es_out_Control(es_out_t *out, int i_query, va_list va_list)
+static int timestamps_filter_es_out_Control(es_out_t *out, input_source_t *in, int i_query, va_list va_list)
 {
+    VLC_UNUSED(in);
     struct tf_es_out_s *p_sys = container_of(out, struct tf_es_out_s, es_out);
     switch(i_query)
     {
@@ -303,8 +304,9 @@ static void timestamps_filter_es_out_Delete(es_out_t *out)
     free(p_sys);
 }
 
-static es_out_id_t *timestamps_filter_es_out_Add(es_out_t *out, const es_format_t *fmt)
+static es_out_id_t *timestamps_filter_es_out_Add(es_out_t *out, input_source_t *in, const es_format_t *fmt)
 {
+    VLC_UNUSED(in);
     struct tf_es_out_s *p_sys = container_of(out, struct tf_es_out_s, es_out);
 
     struct tf_es_out_id_s *tf_es_sys = malloc(sizeof(*tf_es_sys));
index bf91159..896aeb5 100644 (file)
@@ -258,6 +258,7 @@ libvlccore_la_SOURCES = \
        input/demux.c \
        input/demux_chained.c \
        input/es_out.c \
+       input/es_out_source.c \
        input/es_out_timeshift.c \
        input/input.c \
        input/info.h \
index 81083e5..51be6e7 100644 (file)
@@ -243,7 +243,7 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced );
 static void EsOutGlobalMeta( es_out_t *p_out, const vlc_meta_t *p_meta );
 static void EsOutMeta( es_out_t *p_out, const vlc_meta_t *p_meta, const vlc_meta_t *p_progmeta );
 static int EsOutEsUpdateFmt(es_out_t *out, es_out_id_t *es, const es_format_t *fmt);
-static int EsOutControlLocked( es_out_t *out, int i_query, ... );
+static int EsOutControlLocked( es_out_t *out, input_source_t *, int i_query, ... );
 static int EsOutPrivControlLocked( es_out_t *out, int i_query, ... );
 
 static char *LanguageGetName( const char *psz_code );
@@ -1982,8 +1982,9 @@ static es_out_id_t *EsOutAddLocked( es_out_t *out, const es_format_t *fmt,
 /* EsOutAdd:
  *  Add an es_out
  */
-static es_out_id_t *EsOutAdd( es_out_t *out, const es_format_t *fmt )
+static es_out_id_t *EsOutAdd( es_out_t *out, input_source_t *source, const es_format_t *fmt )
 {
+    VLC_UNUSED(source);
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
     vlc_mutex_lock( &p_sys->lock );
     es_out_id_t *es = EsOutAddLocked( out, fmt, NULL );
@@ -2693,13 +2694,13 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
     vlc_mutex_unlock( &p_sys->lock );
 }
 
-static int EsOutVaControlLocked( es_out_t *, int, va_list );
-static int EsOutControlLocked( es_out_t *out, int i_query, ... )
+static int EsOutVaControlLocked( es_out_t *, input_source_t *, int, va_list );
+static int EsOutControlLocked( es_out_t *out, input_source_t *source, int i_query, ... )
 {
     va_list args;
 
     va_start( args, i_query );
-    int ret = EsOutVaControlLocked( out, i_query, args );
+    int ret = EsOutVaControlLocked( out, source, i_query, args );
     va_end( args );
     return ret;
 }
@@ -2742,7 +2743,8 @@ static vlc_tick_t EsOutGetTracksDelay(es_out_t *out)
  * \param args a variable list of arguments for the query
  * \return VLC_SUCCESS or an error code
  */
-static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
+static int EsOutVaControlLocked( es_out_t *out, input_source_t *source,
+                                 int i_query, va_list args )
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
 
@@ -3002,7 +3004,7 @@ static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
                 }
 
                 /* Force a rebufferization when we are too late */
-                EsOutControlLocked( out, ES_OUT_RESET_PCR );
+                EsOutControlLocked( out, source, ES_OUT_RESET_PCR );
 
                 EsOutPrivControlLocked( out, ES_OUT_PRIV_SET_JITTER,
                                         p_sys->i_pts_delay, i_new_jitter,
@@ -3292,7 +3294,7 @@ static int EsOutVaPrivControlLocked( es_out_t *out, int query, va_list args )
             case ES_OUT_PRIV_RESTART_ES: new_query = ES_OUT_RESTART_ES; break;
             default: vlc_assert_unreachable();
         }
-        return EsOutControlLocked( out, new_query, es );
+        return EsOutControlLocked( out, NULL, new_query, es );
     }
     case ES_OUT_PRIV_GET_WAKE_UP:
     {
@@ -3350,7 +3352,7 @@ static int EsOutVaPrivControlLocked( es_out_t *out, int query, va_list args )
         default:
           vlc_assert_unreachable();
         }
-        int i_ret = EsOutControlLocked( out, i_new_query, p_es );
+        int i_ret = EsOutControlLocked( out, NULL, i_new_query, p_es );
 
         return i_ret;
     }
@@ -3567,13 +3569,14 @@ static int EsOutVaPrivControlLocked( es_out_t *out, int query, va_list args )
 
 }
 
-static int EsOutControl( es_out_t *out, int i_query, va_list args )
+static int EsOutControl( es_out_t *out, input_source_t *source,
+                         int i_query, va_list args )
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
     int i_ret;
 
     vlc_mutex_lock( &p_sys->lock );
-    i_ret = EsOutVaControlLocked( out, i_query, args );
+    i_ret = EsOutVaControlLocked( out, source, i_query, args );
     vlc_mutex_unlock( &p_sys->lock );
 
     return i_ret;
index 6d9d606..953b6a5 100644 (file)
@@ -260,6 +260,7 @@ static inline int es_out_SetVbiTransparency( es_out_t *p_out, vlc_es_id_t *id,
 
 es_out_t  *input_EsOutNew( input_thread_t *, float rate );
 es_out_t  *input_EsOutTimeshiftNew( input_thread_t *, es_out_t *, float i_rate );
+es_out_t  *input_EsOutSourceNew(es_out_t *master_out, input_source_t *in);
 
 es_out_id_t *vlc_es_id_get_out(vlc_es_id_t *id);
 
diff --git a/src/input/es_out_source.c b/src/input/es_out_source.c
new file mode 100644 (file)
index 0000000..41bb3a1
--- /dev/null
@@ -0,0 +1,102 @@
+/*****************************************************************************
+ * es_out_source.c: Es Out Source handle
+ *****************************************************************************
+ * Copyright (C) 2020 VLC authors, VideoLAN and Videolabs SAS
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <vlc_common.h>
+
+#include <vlc_atomic.h>
+#include <vlc_es_out.h>
+#include <vlc_block.h>
+
+#include "input_internal.h"
+#include "es_out.h"
+
+typedef struct
+{
+    es_out_t out;
+    input_source_t *in;
+    es_out_t *parent_out;
+} es_out_sys_t;
+
+static es_out_id_t *EsOutSourceAdd(es_out_t *out, input_source_t *in,
+                                    const es_format_t *fmt)
+{
+    assert(in == NULL);
+    es_out_sys_t *sys = container_of(out, es_out_sys_t, out);
+    return sys->parent_out->cbs->add(sys->parent_out, sys->in, fmt);
+}
+
+static int EsOutSourceSend(es_out_t *out, es_out_id_t *es, block_t *block)
+{
+    es_out_sys_t *sys = container_of(out, es_out_sys_t, out);
+    return es_out_Send(sys->parent_out, es, block);
+}
+
+static void EsOutSourceDel(es_out_t *out, es_out_id_t *es)
+{
+    es_out_sys_t *sys = container_of(out, es_out_sys_t, out);
+    es_out_Del(sys->parent_out, es);
+}
+
+static int EsOutSourceControl(es_out_t *out, input_source_t *in, int query,
+                               va_list args)
+{
+    assert(in == NULL);
+    es_out_sys_t *sys = container_of(out, es_out_sys_t, out);
+    return sys->parent_out->cbs->control(sys->parent_out, sys->in, query, args);
+}
+
+static void EsOutSourceDestroy(es_out_t *out)
+{
+    es_out_sys_t *sys = container_of(out, es_out_sys_t, out);
+    free(sys);
+}
+
+es_out_t *input_EsOutSourceNew(es_out_t *parent_out, input_source_t *in)
+{
+    assert(parent_out && in);
+
+    static const struct es_out_callbacks es_out_cbs =
+    {
+        .add = EsOutSourceAdd,
+        .send = EsOutSourceSend,
+        .del = EsOutSourceDel,
+        .control = EsOutSourceControl,
+        .destroy = EsOutSourceDestroy,
+    };
+
+    es_out_sys_t *sys = malloc(sizeof(*sys));
+    if (!sys)
+        return NULL;
+
+    sys->in = in;
+    sys->out.cbs = &es_out_cbs;
+    sys->parent_out = parent_out;
+
+    return &sys->out;
+}
index 96229a9..65c1526 100644 (file)
@@ -69,6 +69,7 @@ enum
 
 typedef struct attribute_packed
 {
+    input_source_t *in;
     es_out_id_t *p_es;
     es_format_t *p_fmt;
 } ts_cmd_add_t;
@@ -87,6 +88,7 @@ typedef struct attribute_packed
 
 typedef struct attribute_packed
 {
+    input_source_t *in;
     int  i_query;
 
     union
@@ -284,10 +286,10 @@ static void         TsStoragePopCmd( ts_storage_t *p_storage, ts_cmd_t *p_cmd, b
 static void CmdClean( ts_cmd_t * );
 static void cmd_cleanup_routine( void *p ) { CmdClean( p ); }
 
-static int  CmdInitAdd    ( ts_cmd_t *, es_out_id_t *, const es_format_t *, bool b_copy );
+static int  CmdInitAdd    ( ts_cmd_t *, input_source_t *, es_out_id_t *, const es_format_t *, bool b_copy );
 static void CmdInitSend   ( ts_cmd_t *, es_out_id_t *, block_t * );
 static int  CmdInitDel    ( ts_cmd_t *, es_out_id_t * );
-static int  CmdInitControl( ts_cmd_t *, int i_query, va_list, bool b_copy );
+static int  CmdInitControl( ts_cmd_t *, input_source_t *, int i_query, va_list, bool b_copy );
 static int  CmdInitPrivControl( ts_cmd_t *, int i_query, va_list, bool b_copy );
 
 /* */
@@ -420,7 +422,7 @@ static void Destroy( es_out_t *p_out )
     free( p_sys );
 }
 
-static es_out_id_t *Add( es_out_t *p_out, const es_format_t *p_fmt )
+static es_out_id_t *Add( es_out_t *p_out, input_source_t *in, const es_format_t *p_fmt )
 {
     es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out);
     ts_cmd_t cmd;
@@ -433,7 +435,7 @@ static es_out_id_t *Add( es_out_t *p_out, const es_format_t *p_fmt )
 
     TsAutoStop( p_out );
 
-    if( CmdInitAdd( &cmd, p_es, p_fmt, p_sys->b_delayed ) )
+    if( CmdInitAdd( &cmd, in, p_es, p_fmt, p_sys->b_delayed ) )
     {
         vlc_mutex_unlock( &p_sys->lock );
         free( p_es );
@@ -491,14 +493,36 @@ static void Del( es_out_t *p_out, es_out_id_t *p_es )
     vlc_mutex_unlock( &p_sys->lock );
 }
 
-static int ControlLockedGetEmpty( es_out_t *p_out, bool *pb_empty )
+static inline int es_out_in_vaControl( es_out_t *p_out, input_source_t *in,
+                                       int i_query, va_list args)
+{
+    return p_out->cbs->control( p_out, in, i_query, args );
+}
+
+static inline int es_out_in_Control( es_out_t *p_out, input_source_t *in,
+                                     int i_query, ... )
+{
+    va_list args;
+    int     i_result;
+
+    va_start( args, i_query );
+    i_result = es_out_in_vaControl( p_out, in, i_query, args );
+    va_end( args );
+    return i_result;
+}
+
+static int ControlLockedGetEmpty( es_out_t *p_out, input_source_t *in,
+                                  bool *pb_empty )
 {
     es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out);
 
     if( p_sys->b_delayed && TsHasCmd( p_sys->p_ts ) )
         *pb_empty = false;
     else
-        *pb_empty = es_out_GetEmpty( p_sys->p_out );
+    {
+        int ret = es_out_in_Control( p_sys->p_out, in, ES_OUT_GET_EMPTY, pb_empty );
+        assert( ret == VLC_SUCCESS );
+    }
 
     return VLC_SUCCESS;
 }
@@ -607,7 +631,8 @@ static int ControlLockedSetFrameNext( es_out_t *p_out )
     return es_out_SetFrameNext( p_sys->p_out );
 }
 
-static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
+static int ControlLocked( es_out_t *p_out, input_source_t *in, int i_query,
+                          va_list args )
 {
     es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out);
 
@@ -635,7 +660,7 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
     case ES_OUT_SET_ES_FMT:
     {
         ts_cmd_t cmd;
-        if( CmdInitControl( &cmd, i_query, args, p_sys->b_delayed ) )
+        if( CmdInitControl( &cmd, in, i_query, args, p_sys->b_delayed ) )
             return VLC_EGENERIC;
         if( p_sys->b_delayed )
         {
@@ -656,43 +681,44 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
             *pb_enabled = true;
             return VLC_SUCCESS;
         }
-        return es_out_Control( p_sys->p_out, ES_OUT_GET_ES_STATE, p_es->p_es, pb_enabled );
+        return es_out_in_Control( p_sys->p_out, in, ES_OUT_GET_ES_STATE,
+                                  p_es->p_es, pb_enabled );
     }
     case ES_OUT_VOUT_SET_MOUSE_EVENT:
     {
         es_out_id_t *p_es = va_arg( args, es_out_id_t * );
         vlc_mouse_event cb = va_arg( args, vlc_mouse_event );
         void *user_data = va_arg( args, void * );
-        return es_out_Control( p_sys->p_out, ES_OUT_VOUT_SET_MOUSE_EVENT,
-                               p_es->p_es, cb, user_data );
+        return es_out_in_Control( p_sys->p_out, in, ES_OUT_VOUT_SET_MOUSE_EVENT,
+                                  p_es->p_es, cb, user_data );
     }
     case ES_OUT_VOUT_ADD_OVERLAY:
     {
         es_out_id_t *p_es = va_arg( args, es_out_id_t * );
         subpicture_t *sub = va_arg( args, subpicture_t * );
         size_t *channel = va_arg( args, size_t * );
-        return es_out_Control( p_sys->p_out, ES_OUT_VOUT_ADD_OVERLAY,
-                               p_es->p_es, sub, channel );
+        return es_out_in_Control( p_sys->p_out, in, ES_OUT_VOUT_ADD_OVERLAY,
+                                  p_es->p_es, sub, channel );
     }
     case ES_OUT_VOUT_DEL_OVERLAY:
     {
         es_out_id_t *p_es = va_arg( args, es_out_id_t * );
         size_t channel = va_arg( args, size_t );
-        return es_out_Control( p_sys->p_out, ES_OUT_VOUT_DEL_OVERLAY,
-                               p_es->p_es, channel );
+        return es_out_in_Control( p_sys->p_out, in, ES_OUT_VOUT_DEL_OVERLAY,
+                                  p_es->p_es, channel );
     }
     case ES_OUT_SPU_SET_HIGHLIGHT:
     {
         es_out_id_t *p_es = va_arg( args, es_out_id_t * );
         const vlc_spu_highlight_t *p_hl = va_arg( args, const vlc_spu_highlight_t * );
-        return es_out_Control( p_sys->p_out, ES_OUT_SPU_SET_HIGHLIGHT,
-                               p_es->p_es, p_hl );
+        return es_out_in_Control( p_sys->p_out, in, ES_OUT_SPU_SET_HIGHLIGHT,
+                                  p_es->p_es, p_hl );
     }
     /* Special internal input control */
     case ES_OUT_GET_EMPTY:
     {
         bool *pb_empty = va_arg( args, bool* );
-        return ControlLockedGetEmpty( p_out, pb_empty );
+        return ControlLockedGetEmpty( p_out, in, pb_empty );
     }
 
     case ES_OUT_GET_PCR_SYSTEM:
@@ -700,7 +726,7 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
             return VLC_EGENERIC;
         /* fall through */
     case ES_OUT_POST_SUBNODE:
-        return es_out_vaControl( p_sys->p_out, i_query, args );
+        return es_out_in_vaControl( p_sys->p_out, in, i_query, args );
 
     case ES_OUT_MODIFY_PCR_SYSTEM:
     {
@@ -710,7 +736,8 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
         if( b_absolute && p_sys->b_delayed )
             return VLC_EGENERIC;
 
-        return es_out_ControlModifyPcrSystem( p_sys->p_out, b_absolute, i_system );
+        return es_out_in_Control( p_sys->p_out, in, i_query, b_absolute,
+                                  i_system );
     }
 
     default:
@@ -719,7 +746,7 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
     }
 }
 
-static int Control( es_out_t *p_out, int i_query, va_list args )
+static int Control( es_out_t *p_out, input_source_t *in, int i_query, va_list args )
 {
     es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out);
     int i_ret;
@@ -728,7 +755,7 @@ static int Control( es_out_t *p_out, int i_query, va_list args )
 
     TsAutoStop( p_out );
 
-    i_ret = ControlLocked( p_out, i_query, args );
+    i_ret = ControlLocked( p_out, in, i_query, args );
 
     vlc_mutex_unlock( &p_sys->lock );
 
@@ -1366,7 +1393,8 @@ static void CmdClean( ts_cmd_t *p_cmd )
     }
 }
 
-static int CmdInitAdd( ts_cmd_t *p_cmd, es_out_id_t *p_es, const es_format_t *p_fmt, bool b_copy )
+static int CmdInitAdd( ts_cmd_t *p_cmd, input_source_t *in,  es_out_id_t *p_es,
+                       const es_format_t *p_fmt, bool b_copy )
 {
     p_cmd->i_type = C_ADD;
     p_cmd->i_date = vlc_tick_now();
@@ -1377,20 +1405,25 @@ static int CmdInitAdd( ts_cmd_t *p_cmd, es_out_id_t *p_es, const es_format_t *p_
         if( !p_cmd->u.add.p_fmt )
             return VLC_EGENERIC;
         es_format_Copy( p_cmd->u.add.p_fmt, p_fmt );
+        p_cmd->u.add.in = in ? input_source_Hold( in ) : NULL;
     }
     else
     {
         p_cmd->u.add.p_fmt = (es_format_t*)p_fmt;
+        p_cmd->u.add.in = in;
     }
     return VLC_SUCCESS;
 }
 static void CmdExecuteAdd( es_out_t *p_out, ts_cmd_t *p_cmd )
 {
-    p_cmd->u.add.p_es->p_es = es_out_Add( p_out, p_cmd->u.add.p_fmt );
+    p_cmd->u.add.p_es->p_es = p_out->cbs->add( p_out, p_cmd->u.add.in,
+                                               p_cmd->u.add.p_fmt );
 }
 static void CmdCleanAdd( ts_cmd_t *p_cmd )
 {
     es_format_Clean( p_cmd->u.add.p_fmt );
+    if( p_cmd->u.add.in )
+        input_source_Release( p_cmd->u.add.in );
     free( p_cmd->u.add.p_fmt );
 }
 
@@ -1435,12 +1468,18 @@ static void CmdExecuteDel( es_out_t *p_out, ts_cmd_t *p_cmd )
     free( p_cmd->u.del.p_es );
 }
 
-static int CmdInitControl( ts_cmd_t *p_cmd, int i_query, va_list args, bool b_copy )
+static int CmdInitControl( ts_cmd_t *p_cmd, input_source_t *in,
+                           int i_query, va_list args, bool b_copy )
 {
     p_cmd->i_type = C_CONTROL;
     p_cmd->i_date = vlc_tick_now();
     p_cmd->u.control.i_query = i_query;
 
+    if( b_copy )
+        p_cmd->u.control.in = in ? input_source_Hold( in ) : NULL;
+    else
+        p_cmd->u.control.in = in;
+
     switch( i_query )
     {
     /* Pass-through control */
@@ -1575,66 +1614,67 @@ static int CmdInitControl( ts_cmd_t *p_cmd, int i_query, va_list args, bool b_co
 static int CmdExecuteControl( es_out_t *p_out, ts_cmd_t *p_cmd )
 {
     const int i_query = p_cmd->u.control.i_query;
+    input_source_t *in = p_cmd->u.control.in;
 
     switch( i_query )
     {
     /* Pass-through control */
     case ES_OUT_SET_GROUP:   /* arg1= int                            */
     case ES_OUT_DEL_GROUP:   /* arg1=int i_group */
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.i_int );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.i_int );
 
     case ES_OUT_SET_PCR:                /* arg1=vlc_tick_t i_pcr(microsecond!) (using default group 0)*/
     case ES_OUT_SET_NEXT_DISPLAY_TIME:  /* arg1=int64_t i_pts(microsecond) */
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.i_i64 );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.i_i64 );
 
     case ES_OUT_SET_GROUP_PCR:          /* arg1= int i_group, arg2=vlc_tick_t i_pcr(microsecond!)*/
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.int_i64.i_int,
-                                               p_cmd->u.control.u.int_i64.i_i64 );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.int_i64.i_int,
+                                  p_cmd->u.control.u.int_i64.i_i64 );
 
     case ES_OUT_RESET_PCR:           /* no arg */
-        return es_out_Control( p_out, i_query );
+        return es_out_in_Control( p_out, in, i_query );
 
     case ES_OUT_SET_GROUP_META:  /* arg1=int i_group arg2=const vlc_meta_t* */
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.int_meta.i_int,
-                                               p_cmd->u.control.u.int_meta.p_meta );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.int_meta.i_int,
+                                  p_cmd->u.control.u.int_meta.p_meta );
 
     case ES_OUT_SET_GROUP_EPG:   /* arg1=int i_group arg2=const vlc_epg_t* */
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.int_epg.i_int,
-                                               p_cmd->u.control.u.int_epg.p_epg );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.int_epg.i_int,
+                                  p_cmd->u.control.u.int_epg.p_epg );
 
     case ES_OUT_SET_GROUP_EPG_EVENT: /* arg1=int i_group arg2=const vlc_epg_event_t* */
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.int_epg_evt.i_int,
-                                               p_cmd->u.control.u.int_epg_evt.p_evt );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.int_epg_evt.i_int,
+                                  p_cmd->u.control.u.int_epg_evt.p_evt );
 
     case ES_OUT_SET_EPG_TIME: /* arg1=int64_t */
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.i_i64 );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.i_i64 );
 
     case ES_OUT_SET_ES_SCRAMBLED_STATE: /* arg1=int es_out_id_t* arg2=bool */
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.es_bool.p_es->p_es,
-                                               p_cmd->u.control.u.es_bool.b_bool );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.es_bool.p_es->p_es,
+                                  p_cmd->u.control.u.es_bool.b_bool );
 
     case ES_OUT_SET_META:  /* arg1=const vlc_meta_t* */
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.int_meta.p_meta );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.int_meta.p_meta );
 
     /* Modified control */
     case ES_OUT_SET_ES:      /* arg1= es_out_id_t*                   */
     case ES_OUT_UNSET_ES:    /* arg1= es_out_id_t*                   */
     case ES_OUT_RESTART_ES:  /* arg1= es_out_id_t*                   */
     case ES_OUT_SET_ES_DEFAULT: /* arg1= es_out_id_t*                */
-        return es_out_Control( p_out, i_query, !p_cmd->u.control.u.p_es ? NULL :
-                                               p_cmd->u.control.u.p_es->p_es );
+        return es_out_in_Control( p_out, in, i_query, !p_cmd->u.control.u.p_es ? NULL :
+                                  p_cmd->u.control.u.p_es->p_es );
 
     case ES_OUT_SET_ES_STATE:/* arg1= es_out_id_t* arg2=bool   */
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.es_bool.p_es->p_es,
-                                               p_cmd->u.control.u.es_bool.b_bool );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.es_bool.p_es->p_es,
+                                  p_cmd->u.control.u.es_bool.b_bool );
 
     case ES_OUT_SET_ES_CAT_POLICY:
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.es_policy.i_cat,
-                                               p_cmd->u.control.u.es_policy.i_policy );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.es_policy.i_cat,
+                                  p_cmd->u.control.u.es_policy.i_policy );
 
     case ES_OUT_SET_ES_FMT:     /* arg1= es_out_id_t* arg2=es_format_t* */
-        return es_out_Control( p_out, i_query, p_cmd->u.control.u.es_fmt.p_es->p_es,
-                                               p_cmd->u.control.u.es_fmt.p_fmt );
+        return es_out_in_Control( p_out, in, i_query, p_cmd->u.control.u.es_fmt.p_es->p_es,
+                                  p_cmd->u.control.u.es_fmt.p_fmt );
 
     default:
         vlc_assert_unreachable();
@@ -1643,6 +1683,9 @@ static int CmdExecuteControl( es_out_t *p_out, ts_cmd_t *p_cmd )
 }
 static void CmdCleanControl( ts_cmd_t *p_cmd )
 {
+    if( p_cmd->u.control.in )
+        input_source_Release( p_cmd->u.control.in );
+
     switch( p_cmd->u.control.i_query )
     {
     case ES_OUT_SET_GROUP_META:
index f115fc3..6c5038b 100644 (file)
 #define TRASH_ID 0xfeca1
 #define ESID(n) ((void *)(INT64_C(0)+TRASH_ID+n))
 
-static int trash_es_out_Control(es_out_t *out, int i_query, va_list va_list)
+static int trash_es_out_Control(es_out_t *out, input_source_t *in, int i_query, va_list va_list)
 {
     VLC_UNUSED(i_query);
     VLC_UNUSED(out);
+    VLC_UNUSED(in);
     VLC_UNUSED(va_list);
     return VLC_EGENERIC;
 }
@@ -56,9 +57,10 @@ static void trash_es_out_Delete(es_out_t *out)
     VLC_UNUSED(out);
 }
 
-static es_out_id_t *trash_es_out_Add(es_out_t *out, const es_format_t *fmt)
+static es_out_id_t *trash_es_out_Add(es_out_t *out, input_source_t *in, const es_format_t *fmt)
 {
     VLC_UNUSED(out);
+    VLC_UNUSED(in);
     VLC_UNUSED(fmt);
     return ESID(fmt->i_id);
 }