[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