[vlc-devel] [PATCH 1/4] es_out: add es_out_Replace
Thomas Guillem
thomas at gllm.fr
Tue Jul 17 18:57:33 CEST 2018
Destroy an es, replace it by a new one with a different format and save the
same selected state.
---
include/vlc_es_out.h | 7 ++
modules/demux/adaptive/plumbing/FakeESOut.cpp | 1 +
src/input/es_out.c | 52 ++++++++---
src/input/es_out_timeshift.c | 89 +++++++++++++++++++
4 files changed, 136 insertions(+), 13 deletions(-)
diff --git a/include/vlc_es_out.h b/include/vlc_es_out.h
index 30112072a7..380685e085 100644
--- a/include/vlc_es_out.h
+++ b/include/vlc_es_out.h
@@ -125,6 +125,7 @@ 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 *(*replace)(es_out_t *, es_out_id_t *, 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);
@@ -141,6 +142,12 @@ static inline es_out_id_t * es_out_Add( es_out_t *out, const es_format_t *fmt )
{
return out->cbs->add( out, fmt );
}
+static inline es_out_id_t * es_out_Replace( es_out_t *out, es_out_id_t *id,
+ const es_format_t *fmt )
+{
+ return out->cbs->replace( out, id, fmt );
+}
+
static inline void es_out_Del( es_out_t *out, es_out_id_t *id )
{
diff --git a/modules/demux/adaptive/plumbing/FakeESOut.cpp b/modules/demux/adaptive/plumbing/FakeESOut.cpp
index e377759aa3..0ac971ce40 100644
--- a/modules/demux/adaptive/plumbing/FakeESOut.cpp
+++ b/modules/demux/adaptive/plumbing/FakeESOut.cpp
@@ -34,6 +34,7 @@ using namespace adaptive;
static const struct es_out_callbacks esOutCallbacks =
{
FakeESOut::esOutAdd_Callback,
+ NULL, /* TODO */
FakeESOut::esOutSend_Callback,
FakeESOut::esOutDel_Callback,
FakeESOut::esOutControl_Callback,
diff --git a/src/input/es_out.c b/src/input/es_out.c
index c1c8fd824d..3a23425510 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -1519,7 +1519,7 @@ static void EsOutGlobalMeta( es_out_t *p_out, const vlc_meta_t *p_meta )
(p_sys->p_pgrm && p_sys->p_pgrm->p_meta) ? p_sys->p_pgrm->p_meta : NULL );
}
-static es_out_id_t *EsOutAddSlave( es_out_t *out, const es_format_t *fmt, es_out_id_t *p_master )
+static es_out_id_t *EsOutAddSlaveLocked( es_out_t *out, const es_format_t *fmt, es_out_id_t *p_master )
{
es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
input_thread_t *p_input = p_sys->p_input;
@@ -1537,13 +1537,10 @@ static es_out_id_t *EsOutAddSlave( es_out_t *out, const es_format_t *fmt, es_out
if( !es )
return NULL;
- vlc_mutex_lock( &p_sys->lock );
-
/* Search the program */
p_pgrm = EsOutProgramFind( out, fmt->i_group );
if( !p_pgrm )
{
- vlc_mutex_unlock( &p_sys->lock );
free( es );
return NULL;
}
@@ -1638,8 +1635,6 @@ static es_out_id_t *EsOutAddSlave( es_out_t *out, const es_format_t *fmt, es_out
if( es->b_scrambled )
EsOutProgramUpdateScrambled( out, es->p_pgrm );
- vlc_mutex_unlock( &p_sys->lock );
-
return es;
}
@@ -1648,7 +1643,11 @@ static es_out_id_t *EsOutAddSlave( es_out_t *out, const es_format_t *fmt, es_out
*/
static es_out_id_t *EsOutAdd( es_out_t *out, const es_format_t *fmt )
{
- return EsOutAddSlave( out, fmt, NULL );
+ es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
+ vlc_mutex_lock( &p_sys->lock );
+ es_out_id_t *id = EsOutAddSlaveLocked( out, fmt, NULL );
+ vlc_mutex_unlock( &p_sys->lock );
+ return id;
}
static bool EsIsSelected( es_out_id_t *es )
@@ -2017,7 +2016,9 @@ static void EsOutCreateCCChannels( es_out_t *out, vlc_fourcc_t codec, uint64_t i
fmt.psz_description = NULL;
es_out_id_t **pp_es = &parent->cc.pp_es[i];
- *pp_es = EsOutAddSlave( out, &fmt, parent );
+ vlc_mutex_lock( &p_sys->lock );
+ *pp_es = EsOutAddSlaveLocked( out, &fmt, parent );
+ vlc_mutex_unlock( &p_sys->lock );
es_format_Clean( &fmt );
/* */
@@ -2138,13 +2139,11 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
/*****************************************************************************
* EsOutDel:
*****************************************************************************/
-static void EsOutDel( es_out_t *out, es_out_id_t *es )
+static void EsOutDelLocked( es_out_t *out, es_out_id_t *es, bool *was_main_es )
{
es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
bool b_reselect = false;
- vlc_mutex_lock( &p_sys->lock );
-
es_out_es_props_t *p_esprops = GetPropsByCat( p_sys, es->fmt.i_cat );
/* We don't try to reselect */
@@ -2192,7 +2191,9 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
}
/* Re-select another track when needed */
- if( b_reselect )
+ if( was_main_es )
+ *was_main_es = b_reselect;
+ else if( b_reselect )
{
es_out_id_t *other;
@@ -2216,9 +2217,33 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
es_format_Clean( &es->fmt );
+ free( es );
+}
+static void EsOutDel( es_out_t *out, es_out_id_t *es )
+{
+ es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
+ vlc_mutex_lock( &p_sys->lock );
+ EsOutDelLocked( out, es, NULL );
vlc_mutex_unlock( &p_sys->lock );
+}
- free( es );
+static es_out_id_t *EsOutReplace( es_out_t *out, es_out_id_t *oldes,
+ const es_format_t *fmt )
+{
+ es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
+ if (fmt->i_cat != oldes->fmt.i_cat)
+ return NULL;
+ vlc_mutex_lock( &p_sys->lock );
+ bool was_main_es;
+ EsOutDelLocked( out, oldes, &was_main_es );
+ es_out_id_t *es = EsOutAddSlaveLocked( out, fmt, NULL );
+
+ /* The new track should be automatically selected but just in case : */
+ if (was_main_es && !EsIsSelected(es))
+ EsOutSelect(out, es, true);
+
+ vlc_mutex_unlock( &p_sys->lock );
+ return es;
}
/**
@@ -2933,6 +2958,7 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
static const struct es_out_callbacks es_out_cbs =
{
.add = EsOutAdd,
+ .replace = EsOutReplace,
.send = EsOutSend,
.del = EsOutDel,
.control = EsOutControl,
diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c
index edf3983c8f..f20dc3c1dd 100644
--- a/src/input/es_out_timeshift.c
+++ b/src/input/es_out_timeshift.c
@@ -65,6 +65,7 @@
enum
{
C_ADD,
+ C_REPLACE,
C_SEND,
C_DEL,
C_CONTROL,
@@ -76,6 +77,13 @@ typedef struct attribute_packed
es_format_t *p_fmt;
} ts_cmd_add_t;
+typedef struct attribute_packed
+{
+ es_out_id_t *p_oldes;
+ es_out_id_t *p_es;
+ es_format_t *p_fmt;
+} ts_cmd_replace_t;
+
typedef struct attribute_packed
{
es_out_id_t *p_es;
@@ -156,6 +164,7 @@ typedef struct attribute_packed
union
{
ts_cmd_add_t add;
+ ts_cmd_replace_t replace;
ts_cmd_del_t del;
ts_cmd_send_t send;
ts_cmd_control_t control;
@@ -277,17 +286,21 @@ 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 CmdInitReplace( ts_cmd_t *, es_out_id_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 void CmdCleanAdd ( ts_cmd_t * );
+static void CmdCleanReplace ( ts_cmd_t * );
static void CmdCleanSend ( ts_cmd_t * );
static void CmdCleanControl( ts_cmd_t *p_cmd );
/* XXX these functions will take the destination es_out_t */
static void CmdExecuteAdd ( es_out_t *, ts_cmd_t * );
+static void CmdExecuteReplace( es_out_t *, ts_cmd_t * );
static int CmdExecuteSend ( es_out_t *, ts_cmd_t * );
static void CmdExecuteDel ( es_out_t *, ts_cmd_t * );
static int CmdExecuteControl( es_out_t *, ts_cmd_t * );
@@ -442,6 +455,42 @@ static es_out_id_t *Add( es_out_t *p_out, const es_format_t *p_fmt )
return p_es;
}
+
+static es_out_id_t *Replace( es_out_t *p_out, es_out_id_t *p_oldes,
+ 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;
+
+ es_out_id_t *p_es = malloc( sizeof( *p_es ) );
+ if( !p_es )
+ return NULL;
+
+ vlc_mutex_lock( &p_sys->lock );
+
+ TsAutoStop( p_out );
+
+ if( CmdInitReplace( &cmd, p_oldes, p_es, p_fmt, p_sys->b_delayed ) )
+ {
+ vlc_mutex_unlock( &p_sys->lock );
+ free( p_es );
+ return NULL;
+ }
+
+ TAB_APPEND( p_sys->i_es, p_sys->pp_es, p_es );
+
+ if( p_sys->b_delayed )
+ TsPushCmd( p_sys->p_ts, &cmd );
+ else
+ CmdExecuteReplace( p_sys->p_out, &cmd );
+
+ TAB_REMOVE( p_sys->i_es, p_sys->pp_es, p_oldes );
+
+ vlc_mutex_unlock( &p_sys->lock );
+
+ return p_es;
+}
+
static int Send( es_out_t *p_out, es_out_id_t *p_es, block_t *p_block )
{
es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out);
@@ -771,6 +820,7 @@ static int Control( es_out_t *p_out, int i_query, va_list args )
static const struct es_out_callbacks es_out_timeshift_cbs =
{
.add = Add,
+ .replace = Replace,
.send = Send,
.del = Del,
.control = Control,
@@ -1087,6 +1137,10 @@ static void *TsRun( void *p_data )
CmdExecuteAdd( p_ts->p_out, &cmd );
CmdCleanAdd( &cmd );
break;
+ case C_REPLACE:
+ CmdExecuteReplace( p_ts->p_out, &cmd );
+ CmdCleanReplace( &cmd );
+ break;
case C_SEND:
CmdExecuteSend( p_ts->p_out, &cmd );
CmdCleanSend( &cmd );
@@ -1298,6 +1352,9 @@ static void CmdClean( ts_cmd_t *p_cmd )
case C_ADD:
CmdCleanAdd( p_cmd );
break;
+ case C_REPLACE:
+ CmdCleanReplace( p_cmd );
+ break;
case C_SEND:
CmdCleanSend( p_cmd );
break;
@@ -1330,6 +1387,26 @@ static int CmdInitAdd( ts_cmd_t *p_cmd, es_out_id_t *p_es, const es_format_t *p_
}
return VLC_SUCCESS;
}
+static int CmdInitReplace( ts_cmd_t *p_cmd, es_out_id_t *p_oldes,
+ es_out_id_t *p_es, const es_format_t *p_fmt, bool b_copy )
+{
+ p_cmd->i_type = C_REPLACE;
+ p_cmd->i_date = vlc_tick_now();
+ p_cmd->u.replace.p_oldes = p_oldes;
+ p_cmd->u.replace.p_es = p_es;
+ if( b_copy )
+ {
+ p_cmd->u.replace.p_fmt = malloc( sizeof(*p_fmt) );
+ if( !p_cmd->u.replace.p_fmt )
+ return VLC_EGENERIC;
+ es_format_Copy( p_cmd->u.replace.p_fmt, p_fmt );
+ }
+ else
+ {
+ p_cmd->u.replace.p_fmt = (es_format_t*)p_fmt;
+ }
+ 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 );
@@ -1339,6 +1416,18 @@ static void CmdCleanAdd( ts_cmd_t *p_cmd )
es_format_Clean( p_cmd->u.add.p_fmt );
free( p_cmd->u.add.p_fmt );
}
+static void CmdExecuteReplace( es_out_t *p_out, ts_cmd_t *p_cmd )
+{
+ p_cmd->u.replace.p_es->p_es =
+ es_out_Replace( p_out, p_cmd->u.replace.p_oldes->p_es,
+ p_cmd->u.replace.p_fmt );
+ free( p_cmd->u.replace.p_oldes );
+}
+static void CmdCleanReplace( ts_cmd_t *p_cmd )
+{
+ es_format_Clean( p_cmd->u.replace.p_fmt );
+ free( p_cmd->u.replace.p_fmt );
+}
static void CmdInitSend( ts_cmd_t *p_cmd, es_out_id_t *p_es, block_t *p_block )
{
--
2.18.0
More information about the vlc-devel
mailing list