[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