[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