[vlc-devel] [RFC PATCH 3/9] es_out: add a refcounted ctx

Thomas Guillem thomas at gllm.fr
Wed Feb 12 15:43:21 CET 2020


Refcounted and passed from input_EsOutContextNew() to the timeshift es_out to
the core es_out, via cbs->add().
---
 include/vlc_es_out.h                          |   6 +-
 modules/access/bluray.c                       |   3 +-
 modules/demux/adaptive/plumbing/FakeESOut.cpp |   4 +-
 modules/demux/timestamps_filter.h             |   3 +-
 src/Makefile.am                               |   1 +
 src/input/es_out.c                            |   3 +-
 src/input/es_out.h                            |  11 ++
 src/input/es_out_ctx.c                        | 160 ++++++++++++++++++
 src/input/es_out_timeshift.c                  |  17 +-
 9 files changed, 196 insertions(+), 12 deletions(-)
 create mode 100644 src/input/es_out_ctx.c

diff --git a/include/vlc_es_out.h b/include/vlc_es_out.h
index 46dffa98462..15bcdbc166e 100644
--- a/include/vlc_es_out.h
+++ b/include/vlc_es_out.h
@@ -126,9 +126,11 @@ enum es_out_policy_e
     ES_OUT_ES_POLICY_SIMULTANEOUS, /* Allows multiple ES per cat */
 };
 
+typedef struct es_out_ctx_t es_out_ctx_t;
+
 struct es_out_callbacks
 {
-    es_out_id_t *(*add)(es_out_t *, const es_format_t *);
+    es_out_id_t *(*add)(es_out_t *, es_out_ctx_t *ctx, 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);
@@ -143,7 +145,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 )
diff --git a/modules/access/bluray.c b/modules/access/bluray.c
index a2998782828..5e8af77fb90 100644
--- a/modules/access/bluray.c
+++ b/modules/access/bluray.c
@@ -1337,8 +1337,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, es_out_ctx_t *ctx, const es_format_t *p_fmt)
 {
+    VLC_UNUSED(ctx);
     bluray_esout_priv_t *esout_priv = container_of(p_out, bluray_esout_priv_t, es_out);
 
     vlc_mutex_lock(&esout_priv->lock);
diff --git a/modules/demux/adaptive/plumbing/FakeESOut.cpp b/modules/demux/adaptive/plumbing/FakeESOut.cpp
index 052191d3e0b..758689989f3 100644
--- a/modules/demux/adaptive/plumbing/FakeESOut.cpp
+++ b/modules/demux/adaptive/plumbing/FakeESOut.cpp
@@ -37,7 +37,7 @@ 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 *, es_out_ctx_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 );
@@ -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, es_out_ctx_t *, const es_format_t *p_fmt)
 {
     AbstractFakeEsOut *me = container_of(fakees, Private, es_out)->fake;
     return me->esOutAdd(p_fmt);
diff --git a/modules/demux/timestamps_filter.h b/modules/demux/timestamps_filter.h
index f56c4e71377..cc22053f32c 100644
--- a/modules/demux/timestamps_filter.h
+++ b/modules/demux/timestamps_filter.h
@@ -303,8 +303,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, es_out_ctx_t *ctx, const es_format_t *fmt)
 {
+    VLC_UNUSED(ctx);
     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));
diff --git a/src/Makefile.am b/src/Makefile.am
index b6c59968370..f0f5197e402 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -258,6 +258,7 @@ libvlccore_la_SOURCES = \
 	input/demux.c \
 	input/demux_chained.c \
 	input/es_out.c \
+	input/es_out_ctx.c \
 	input/es_out_timeshift.c \
 	input/input.c \
 	input/info.h \
diff --git a/src/input/es_out.c b/src/input/es_out.c
index e39e117bdbc..a9b5f635309 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -1998,8 +1998,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, es_out_ctx_t *ctx, const es_format_t *fmt )
 {
+    VLC_UNUSED(ctx);
     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 );
diff --git a/src/input/es_out.h b/src/input/es_out.h
index e6cde26366f..08c130d5609 100644
--- a/src/input/es_out.h
+++ b/src/input/es_out.h
@@ -179,7 +179,18 @@ static inline void es_out_Eos( es_out_t *p_out )
 
 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_EsOutContextNew(es_out_t *master_out, es_out_ctx_t *ctx);
 
 es_out_id_t *vlc_es_id_get_out(vlc_es_id_t *id);
 
+es_out_ctx_t *es_out_ctx_New(const char *source_id);
+
+es_out_ctx_t *es_out_ctx_Hold(es_out_ctx_t *ctx);
+
+void es_out_ctx_Release(es_out_ctx_t *ctx);
+
+const char *es_out_ctx_GetSourceId(es_out_ctx_t *ctx);
+
+int es_out_ctx_GetNewEsID(es_out_ctx_t *ctx, enum es_format_category_e cat);
+
 #endif
diff --git a/src/input/es_out_ctx.c b/src/input/es_out_ctx.c
new file mode 100644
index 00000000000..6ae17d529bf
--- /dev/null
+++ b/src/input/es_out_ctx.c
@@ -0,0 +1,160 @@
+/*****************************************************************************
+ * es_out_ctx.c: Es Out context handle
+ *****************************************************************************
+ * Copyright (C) 2019 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;
+    es_out_ctx_t *ctx;
+    es_out_t *parent_out;
+} es_out_sys_t;
+
+struct es_out_ctx_t
+{
+    vlc_atomic_rc_t rc;
+    char *source_id;
+    int es_ids[DATA_ES+1];
+};
+
+es_out_ctx_t *es_out_ctx_New(const char *source_id)
+{
+    es_out_ctx_t *ctx = malloc(sizeof(*ctx));
+    if (!ctx)
+        return NULL;
+
+    if (source_id)
+    {
+        ctx->source_id = strdup(source_id);
+        if (!ctx->source_id)
+        {
+            free(ctx);
+            return NULL;
+        }
+    }
+    else
+        ctx->source_id = NULL;
+
+    vlc_atomic_rc_init(&ctx->rc);
+
+    for (size_t i = 0; i < ARRAY_SIZE(ctx->es_ids); ++i)
+        ctx->es_ids[i] = 0;
+
+    return ctx;
+}
+
+es_out_ctx_t *es_out_ctx_Hold(es_out_ctx_t *ctx)
+{
+    vlc_atomic_rc_inc(&ctx->rc);
+    return ctx;
+}
+
+void es_out_ctx_Release(es_out_ctx_t *ctx)
+{
+    if (vlc_atomic_rc_dec(&ctx->rc))
+    {
+        free(ctx->source_id);
+        free(ctx);
+    }
+}
+
+const char *es_out_ctx_GetSourceId(es_out_ctx_t *ctx)
+{
+    return ctx->source_id;
+}
+
+int es_out_ctx_GetNewEsID(es_out_ctx_t *ctx, enum es_format_category_e cat)
+{
+    assert(cat >= UNKNOWN_ES && cat <= DATA_ES);
+    return ctx->es_ids[cat]++;
+}
+
+static es_out_id_t *EsOutContextAdd(es_out_t *out, es_out_ctx_t *ctx,
+                                    const es_format_t *fmt)
+{
+    assert(ctx == NULL);
+    es_out_sys_t *sys = container_of(out, es_out_sys_t, out);
+    return sys->parent_out->cbs->add(sys->parent_out, sys->ctx, fmt);
+}
+
+static int EsOutContextSend(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 EsOutContextDel(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 EsOutContextControl(es_out_t *out, int query, va_list args)
+{
+    es_out_sys_t *sys = container_of(out, es_out_sys_t, out);
+    return es_out_vaControl(sys->parent_out, query, args);
+}
+
+static void EsOutContextDestroy(es_out_t *out)
+{
+    es_out_sys_t *sys = container_of(out, es_out_sys_t, out);
+    es_out_ctx_Release(sys->ctx);
+    free(sys);
+}
+
+es_out_t *input_EsOutContextNew(es_out_t *parent_out, es_out_ctx_t *ctx)
+{
+    assert(parent_out && ctx);
+
+    static const struct es_out_callbacks es_out_cbs =
+    {
+        .add = EsOutContextAdd,
+        .send = EsOutContextSend,
+        .del = EsOutContextDel,
+        .control = EsOutContextControl,
+        .destroy = EsOutContextDestroy,
+    };
+
+    es_out_sys_t *sys = malloc(sizeof(*sys));
+    if (!sys)
+        return NULL;
+
+    sys->ctx = ctx;
+    sys->out.cbs = &es_out_cbs;
+    sys->parent_out = parent_out;
+
+    return &sys->out;
+}
diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c
index ed79000f65f..9f59e1fb968 100644
--- a/src/input/es_out_timeshift.c
+++ b/src/input/es_out_timeshift.c
@@ -69,6 +69,7 @@ enum
 
 typedef struct attribute_packed
 {
+    es_out_ctx_t *p_ctx;
     es_out_id_t *p_es;
     es_format_t *p_fmt;
 } ts_cmd_add_t;
@@ -274,7 +275,7 @@ 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 *, es_out_ctx_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 );
@@ -409,7 +410,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, es_out_ctx_t *p_ctx, 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;
@@ -422,7 +423,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, p_ctx, p_es, p_fmt, p_sys->b_delayed ) )
     {
         vlc_mutex_unlock( &p_sys->lock );
         free( p_es );
@@ -1313,7 +1314,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, es_out_ctx_t *p_ctx,  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();
@@ -1324,21 +1326,26 @@ 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.p_ctx = p_ctx ? es_out_ctx_Hold( p_ctx ) : NULL;
     }
     else
     {
         p_cmd->u.add.p_fmt = (es_format_t*)p_fmt;
+        p_cmd->u.add.p_ctx = p_ctx;
     }
     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.p_ctx,
+                                               p_cmd->u.add.p_fmt );
 }
 static void CmdCleanAdd( ts_cmd_t *p_cmd )
 {
     es_format_Clean( p_cmd->u.add.p_fmt );
     free( p_cmd->u.add.p_fmt );
+    if( p_cmd->u.add.p_ctx )
+        es_out_ctx_Release( p_cmd->u.add.p_ctx );
 }
 
 static void CmdInitSend( ts_cmd_t *p_cmd, es_out_id_t *p_es, block_t *p_block )
-- 
2.20.1



More information about the vlc-devel mailing list