[vlc-devel] [PATCH 1/4] es_out: add es_out_Replace
Thomas Guillem
thomas at gllm.fr
Tue Jul 17 18:58:26 CEST 2018
On Tue, Jul 17, 2018, at 18:57, Thomas Guillem wrote:
> 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 */
Yes, not complete.
> 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
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list