[vlc-devel] [RFC PATCH 8/9] RFC: es_out: fix group_id and i_id collision

Thomas Guillem thomas at gllm.fr
Wed Feb 12 15:43:26 CET 2020


A specified program (group > 0) is identified by its group id and by its
context pointer. The default program (group = 0) can be used by more than one
contexts.

An ES track is now identified by its i_id and by its context pointer.  In case
of automatic track ids, the id counter will be handled by each contexts (or
input source). This mean that the id counter starts at 0 for each new source.

A slave specifying its group won't be able to be played alongside the master
source by default (except if we play more than one programs at a time).

PS: This still need a major reworking of the variables used to select a
track/program.
---
 src/input/es_out.c | 109 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 78 insertions(+), 31 deletions(-)

diff --git a/src/input/es_out.c b/src/input/es_out.c
index 6a49be6ef75..d11ef22be33 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -61,6 +61,9 @@
  *****************************************************************************/
 typedef struct
 {
+    /* Program context */
+    es_out_ctx_t *ctx;
+
     /* Program ID */
     int i_id;
 
@@ -98,6 +101,10 @@ struct es_out_id_t
     /* weak reference, used by input_decoder_callbacks and vlc_clock_cbs */
     es_out_t *out;
 
+    /* Context used to create this ES. Equals to p_pgrm->ctx when not using a
+     * default program id. */
+    es_out_ctx_t *ctx;
+
     /* ES ID */
     es_out_pgrm_t *p_pgrm;
 
@@ -139,7 +146,7 @@ struct es_out_id_t
     es_out_id_t *p_master;
 
     /* ID for the meta data */
-    int         i_meta_id;
+    int         i_meta_id; /* TODO: remove */
 
     struct vlc_list node;
 
@@ -165,6 +172,9 @@ typedef struct
 {
     input_thread_t *p_input;
 
+    /* Main source context */
+    es_out_ctx_t *main_ctx;
+
     /* */
     vlc_mutex_t   lock;
 
@@ -484,6 +494,13 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, float rate )
 
     p_sys->out.cbs = &es_out_cbs;
 
+    p_sys->main_ctx = es_out_ctx_New(NULL);
+    if( !p_sys->main_ctx )
+    {
+        free( p_sys );
+        return NULL;
+    }
+
     vlc_mutex_init( &p_sys->lock );
     p_sys->p_input = p_input;
 
@@ -581,6 +598,7 @@ static void EsRelease(es_out_id_t *es)
         free(es->psz_language);
         free(es->psz_language_code);
         es_format_Clean(&es->fmt);
+        es_out_ctx_Release(es->ctx);
         free(es);
     }
 }
@@ -603,6 +621,8 @@ static void EsOutDelete( es_out_t *out )
 
     vlc_mutex_destroy( &p_sys->lock );
 
+    es_out_ctx_Release( p_sys->main_ctx );
+
     free( p_sys );
 }
 
@@ -634,6 +654,7 @@ static void EsOutTerminate( es_out_t *out )
 
         vlc_list_remove(&p_pgrm->node);
         input_SendEventProgramDel( p_sys->p_input, p_pgrm->i_id );
+        es_out_ctx_Release( p_pgrm->ctx );
         free( p_pgrm );
     }
 
@@ -1244,9 +1265,10 @@ static void EsOutSendEsEvent(es_out_t *out, es_out_id_t *es, int action)
     });
 }
 
-static bool EsOutIsProgramVisible( es_out_t *out, int i_group )
+static bool EsOutIsProgramVisible( es_out_t *out, es_out_ctx_t *ctx, int i_group )
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
+    /* TODO */
     return p_sys->i_group_id == 0 || p_sys->i_group_id == i_group;
 }
 
@@ -1327,7 +1349,7 @@ static void EsOutProgramSelect( es_out_t *out, es_out_pgrm_t *p_pgrm )
 /* EsOutAddProgram:
  *  Add a program
  */
-static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
+static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, es_out_ctx_t *ctx, int i_group )
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
     input_thread_t    *p_input = p_sys->p_input;
@@ -1337,6 +1359,7 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
         return NULL;
 
     /* Init */
+    p_pgrm->ctx = es_out_ctx_Hold( ctx );
     p_pgrm->i_id = i_group;
     p_pgrm->i_es = 0;
     p_pgrm->b_selected = false;
@@ -1370,7 +1393,7 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
     vlc_list_append(&p_pgrm->node, &p_sys->programs);
 
     /* Update "program" variable */
-    if( EsOutIsProgramVisible( out, i_group ) )
+    if( EsOutIsProgramVisible( out, ctx, i_group ) )
         input_SendEventProgramAdd( p_input, i_group, NULL );
 
     if( i_group == p_sys->i_group_id || ( !p_sys->p_pgrm && p_sys->i_group_id == 0 ) )
@@ -1381,34 +1404,38 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
 
 /* EsOutProgramFind
  */
-static es_out_pgrm_t *EsOutProgramFind( es_out_t *p_out, int i_group )
+static es_out_pgrm_t *EsOutProgramFind( es_out_t *p_out, es_out_ctx_t *ctx,
+                                        int i_group )
 {
     es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out);
     es_out_pgrm_t *pgrm;
 
     vlc_list_foreach(pgrm, &p_sys->programs, node)
-        if (pgrm->i_id == i_group)
+        if (pgrm->i_id == i_group && (pgrm->ctx == ctx || i_group == 0))
             return pgrm;
+
     return NULL;
 }
 
+
 /* EsOutProgramFindOrAdd
  */
-static es_out_pgrm_t *EsOutProgramFindOrAdd( es_out_t *p_out, int i_group )
+static es_out_pgrm_t *EsOutProgramFindOrAdd( es_out_t *p_out, es_out_ctx_t *ctx,
+                                             int i_group )
 {
-    es_out_pgrm_t *pgrm = EsOutProgramFind( p_out, i_group );
-    return pgrm ? pgrm : EsOutProgramAdd( p_out, i_group );
+    es_out_pgrm_t *pgrm = EsOutProgramFind( p_out, ctx, i_group );
+    return pgrm ? pgrm : EsOutProgramAdd( p_out, ctx, i_group );
 }
 
 /* EsOutDelProgram:
  *  Delete a program
  */
-static int EsOutProgramDel( es_out_t *out, int i_group )
+static int EsOutProgramDel( es_out_t *out, es_out_ctx_t *ctx, int i_group )
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
     input_thread_t    *p_input = p_sys->p_input;
 
-    es_out_pgrm_t *p_pgrm = EsOutProgramFind( out, i_group );
+    es_out_pgrm_t *p_pgrm = EsOutProgramFind( out, ctx, i_group );
     if( p_pgrm == NULL )
         return VLC_EGENERIC;
 
@@ -1430,6 +1457,9 @@ static int EsOutProgramDel( es_out_t *out, int i_group )
 
     if( p_pgrm->p_meta )
         vlc_meta_Delete( p_pgrm->p_meta );
+
+    es_out_ctx_Release( p_pgrm->ctx );
+
     free( p_pgrm );
 
     /* Update "program" variable */
@@ -1482,7 +1512,8 @@ static char *EsInfoCategoryName( es_out_id_t* es )
     return psz_category;
 }
 
-static void EsOutProgramMeta( es_out_t *out, int i_group, const vlc_meta_t *p_meta )
+static void EsOutProgramMeta( es_out_t *out, es_out_ctx_t *ctx,
+                              int i_group, const vlc_meta_t *p_meta )
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
     es_out_pgrm_t     *p_pgrm;
@@ -1510,9 +1541,9 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, const vlc_meta_t *p_me
     }
 
     /* Find program */
-    if( !EsOutIsProgramVisible( out, i_group ) )
+    if( !EsOutIsProgramVisible( out, ctx, i_group ) )
         return;
-    p_pgrm = EsOutProgramFindOrAdd( out, i_group );
+    p_pgrm = EsOutProgramFindOrAdd( out, ctx, i_group );
     if( !p_pgrm )
         return;
 
@@ -1611,7 +1642,8 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, const vlc_meta_t *p_me
         input_SendEventMetaInfo( p_input );
 }
 
-static void EsOutProgramEpgEvent( es_out_t *out, int i_group, const vlc_epg_event_t *p_event )
+static void EsOutProgramEpgEvent( es_out_t *out, es_out_ctx_t *ctx,
+                                  int i_group, const vlc_epg_event_t *p_event )
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
     input_thread_t    *p_input = p_sys->p_input;
@@ -1619,16 +1651,17 @@ static void EsOutProgramEpgEvent( es_out_t *out, int i_group, const vlc_epg_even
     es_out_pgrm_t     *p_pgrm;
 
     /* Find program */
-    if( !EsOutIsProgramVisible( out, i_group ) )
+    if( !EsOutIsProgramVisible( out, ctx, i_group ) )
         return;
-    p_pgrm = EsOutProgramFindOrAdd( out, i_group );
+    p_pgrm = EsOutProgramFindOrAdd( out, ctx, i_group );
     if( !p_pgrm )
         return;
 
     input_item_SetEpgEvent( p_item, p_event );
 }
 
-static void EsOutProgramEpg( es_out_t *out, int i_group, const vlc_epg_t *p_epg )
+static void EsOutProgramEpg( es_out_t *out, es_out_ctx_t *ctx,
+                             int i_group, const vlc_epg_t *p_epg )
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
     input_thread_t    *p_input = p_sys->p_input;
@@ -1637,9 +1670,9 @@ static void EsOutProgramEpg( es_out_t *out, int i_group, const vlc_epg_t *p_epg
     char *psz_cat;
 
     /* Find program */
-    if( !EsOutIsProgramVisible( out, i_group ) )
+    if( !EsOutIsProgramVisible( out, ctx, i_group ) )
         return;
-    p_pgrm = EsOutProgramFindOrAdd( out, i_group );
+    p_pgrm = EsOutProgramFindOrAdd( out, ctx, i_group );
     if( !p_pgrm )
         return;
 
@@ -1873,7 +1906,8 @@ static void EsOutFillEsFmt(es_out_t *out, es_format_t *fmt)
     }
 }
 
-static es_out_id_t *EsOutAddLocked( es_out_t *out, const es_format_t *fmt,
+static es_out_id_t *EsOutAddLocked( es_out_t *out, es_out_ctx_t *ctx,
+                                    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);
@@ -1892,6 +1926,7 @@ static es_out_id_t *EsOutAddLocked( es_out_t *out, const es_format_t *fmt,
         return NULL;
 
     es->out = out;
+    es->ctx = es_out_ctx_Hold( ctx );
 
     if( es_format_Copy( &es->fmt, fmt ) != VLC_SUCCESS )
     {
@@ -1912,19 +1947,23 @@ static es_out_id_t *EsOutAddLocked( es_out_t *out, const es_format_t *fmt,
 #endif
 
     if( es->fmt.i_id < 0 )
-        es->fmt.i_id = p_sys->i_id;
+        es->fmt.i_id = es_out_ctx_GetNewEsID( ctx, es->fmt.i_cat );
     if( !es->fmt.i_original_fourcc )
         es->fmt.i_original_fourcc = es->fmt.i_codec;
 
     /* Search the program */
-    p_pgrm = EsOutProgramFindOrAdd( out, fmt->i_group );
+    p_pgrm = EsOutProgramFindOrAdd( out, ctx, fmt->i_group );
     if( !p_pgrm )
     {
         es_format_Clean( &es->fmt );
+        es_out_ctx_Release( es->ctx );
         free( es );
         return NULL;
     }
 
+    /* The group 0 is the default one and can be used by different contexts */
+    assert( fmt->i_group == 0 || p_pgrm->ctx == es->ctx );
+
     /* Get the number of ES already added in order to get the position of the es */
     es->i_pos = 0;
     es_out_id_t *it;
@@ -2004,8 +2043,12 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_out_ctx_t *ctx, const es_format_
 {
     VLC_UNUSED(ctx);
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
+
+    if( !ctx )
+        ctx = p_sys->main_ctx;
+
     vlc_mutex_lock( &p_sys->lock );
-    es_out_id_t *es = EsOutAddLocked( out, fmt, NULL );
+    es_out_id_t *es = EsOutAddLocked( out, ctx, fmt, NULL );
     vlc_mutex_unlock( &p_sys->lock );
     return es;
 }
@@ -2496,7 +2539,7 @@ 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 = EsOutAddLocked( out, &fmt, parent );
+        *pp_es = EsOutAddLocked( out, parent->p_pgrm->ctx, &fmt, parent );
         es_format_Clean( &fmt );
 
         /* */
@@ -2765,6 +2808,7 @@ static int EsOutVaControlLocked( es_out_t *out, es_out_ctx_t *ctx,
                                  int i_query, va_list args )
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
+    assert( ctx ); /* == p_sys->main_ctx if the given ctx is NULL */
 
     switch( i_query )
     {
@@ -3039,12 +3083,12 @@ static int EsOutVaControlLocked( es_out_t *out, es_out_ctx_t *ctx,
         {
             p_pgrm = p_sys->p_pgrm;
             if( !p_pgrm )
-                p_pgrm = EsOutProgramAdd( out, i_group );   /* Create it */
+                p_pgrm = EsOutProgramAdd( out, ctx, i_group );   /* Create it */
         }
         else
         {
             i_group = va_arg( args, int );
-            p_pgrm = EsOutProgramFindOrAdd( out, i_group );
+            p_pgrm = EsOutProgramFindOrAdd( out, ctx, i_group );
         }
         if( !p_pgrm )
             return VLC_EGENERIC;
@@ -3217,7 +3261,7 @@ static int EsOutVaControlLocked( es_out_t *out, es_out_ctx_t *ctx,
         int i_group = va_arg( args, int );
         const vlc_meta_t *p_meta = va_arg( args, const vlc_meta_t * );
 
-        EsOutProgramMeta( out, i_group, p_meta );
+        EsOutProgramMeta( out, ctx, i_group, p_meta );
         return VLC_SUCCESS;
     }
     case ES_OUT_SET_GROUP_EPG:
@@ -3225,7 +3269,7 @@ static int EsOutVaControlLocked( es_out_t *out, es_out_ctx_t *ctx,
         int i_group = va_arg( args, int );
         const vlc_epg_t *p_epg = va_arg( args, const vlc_epg_t * );
 
-        EsOutProgramEpg( out, i_group, p_epg );
+        EsOutProgramEpg( out, ctx, i_group, p_epg );
         return VLC_SUCCESS;
     }
     case ES_OUT_SET_GROUP_EPG_EVENT:
@@ -3233,7 +3277,7 @@ static int EsOutVaControlLocked( es_out_t *out, es_out_ctx_t *ctx,
         int i_group = va_arg( args, int );
         const vlc_epg_event_t *p_evt = va_arg( args, const vlc_epg_event_t * );
 
-        EsOutProgramEpgEvent( out, i_group, p_evt );
+        EsOutProgramEpgEvent( out, ctx, i_group, p_evt );
         return VLC_SUCCESS;
     }
     case ES_OUT_SET_EPG_TIME:
@@ -3248,7 +3292,7 @@ static int EsOutVaControlLocked( es_out_t *out, es_out_ctx_t *ctx,
     {
         int i_group = va_arg( args, int );
 
-        return EsOutProgramDel( out, i_group );
+        return EsOutProgramDel( out, ctx, i_group );
     }
 
     case ES_OUT_SET_META:
@@ -3574,6 +3618,9 @@ static int EsOutControl( es_out_t *out, es_out_ctx_t *ctx,
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
     int i_ret;
 
+    if( !ctx )
+        ctx = p_sys->main_ctx;
+
     vlc_mutex_lock( &p_sys->lock );
     i_ret = EsOutVaControlLocked( out, ctx, i_query, args );
     vlc_mutex_unlock( &p_sys->lock );
-- 
2.20.1



More information about the vlc-devel mailing list