[vlc-commits] es_out: add sticky programs handling
Thomas Guillem
git at videolan.org
Fri Feb 28 20:46:17 CET 2020
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Thu Feb 13 15:22:54 2020 +0100| [df8a69b97cc50a08f980496711e8e024592b2100] | committer: Thomas Guillem
es_out: add sticky programs handling
ES tracks created from a slave source with a default group (== 0) will use
sticky programs. Such tracks will be attached to any selected programs (created
from the main source).
Fixes #3075
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=df8a69b97cc50a08f980496711e8e024592b2100
---
src/input/es_out.c | 114 +++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 88 insertions(+), 26 deletions(-)
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 14c06285fa..99efdc5e08 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -1254,6 +1254,18 @@ static void EsOutSendEsEvent(es_out_t *out, es_out_id_t *es, int action)
});
}
+/* EsOutIsGroupSticky
+ *
+ * A sticky group can be attached to any other programs. This is the case for
+ * default groups (i_group == 0) sent by slave sources.
+ */
+static inline bool EsOutIsGroupSticky( es_out_t *p_out, input_source_t *source,
+ int i_group )
+{
+ es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out);
+ return source != input_priv(p_sys->p_input)->master && i_group == 0;
+}
+
static bool EsOutIsProgramVisible( es_out_t *out, input_source_t *source, int i_group )
{
es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
@@ -1287,10 +1299,16 @@ static void EsOutProgramSelect( es_out_t *out, es_out_pgrm_t *p_pgrm )
if (EsIsSelected(es) && p_sys->i_mode != ES_OUT_MODE_ALL)
EsOutUnselectEs(out, es, true);
- /* ES tracks are deleted (and unselected) when their programs are
- * unselected (they will be added back when their programs are
- * selected back). */
- EsOutSendEsEvent( out, es, VLC_INPUT_ES_DELETED );
+ if( EsOutIsGroupSticky( out, es->id.source, es->fmt.i_group ) )
+ es->p_pgrm = NULL; /* Skip the DELETED event, cf. bellow */
+ else
+ {
+ /* ES tracks are deleted (and unselected) when their programs
+ * are unselected (they will be added back when their programs
+ * are selected back). */
+ EsOutSendEsEvent( out, es, VLC_INPUT_ES_DELETED );
+ }
+
}
p_sys->audio.p_main_es = NULL;
@@ -1314,7 +1332,14 @@ static void EsOutProgramSelect( es_out_t *out, es_out_pgrm_t *p_pgrm )
foreach_es_then_es_slaves(es)
{
- if (es->p_pgrm == p_sys->p_pgrm)
+
+ if (es->p_pgrm == NULL)
+ {
+ /* Attach this sticky ES to this new program. Skip the ADDED event,
+ * cf.above */
+ es->p_pgrm = p_sys->p_pgrm;
+ }
+ else if (es->p_pgrm == p_sys->p_pgrm)
{
EsOutSendEsEvent(out, es, VLC_INPUT_ES_ADDED);
EsOutUpdateInfo(out, es, NULL);
@@ -1348,6 +1373,11 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, input_source_t *source, in
es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
input_thread_t *p_input = p_sys->p_input;
+ /* Sticky groups will be attached to any existing programs, no need to
+ * create one. */
+ if( EsOutIsGroupSticky( out, source, i_group ) )
+ return NULL;
+
es_out_pgrm_t *p_pgrm = malloc( sizeof( es_out_pgrm_t ) );
if( !p_pgrm )
return NULL;
@@ -1405,7 +1435,7 @@ static es_out_pgrm_t *EsOutProgramSearch( es_out_t *p_out, input_source_t *sourc
es_out_pgrm_t *pgrm;
vlc_list_foreach(pgrm, &p_sys->programs, node)
- if (pgrm->i_id == i_group && (pgrm->source == source || i_group == 0))
+ if (pgrm->i_id == i_group && pgrm->source == source)
return pgrm;
return NULL;
@@ -1439,6 +1469,21 @@ static int EsOutProgramDel( es_out_t *out, input_source_t *source, int i_group )
return VLC_EGENERIC;
}
+ /* Unselect sticky ES tracks */
+ es_out_id_t *es;
+ foreach_es_then_es_slaves(es)
+ {
+ if (es->p_pgrm != p_pgrm)
+ continue;
+
+ /* The remaining ES tracks are necessary sticky, cf. 'p_pgrm->i_es'
+ * test above. */
+ assert(EsOutIsGroupSticky( out, es->id.source, es->fmt.i_group));
+
+ EsOutUnselectEs(out, es, true);
+ es->p_pgrm = NULL;
+ }
+
vlc_list_remove(&p_pgrm->node);
/* If program is selected we need to unselect it */
@@ -1979,19 +2024,27 @@ static es_out_id_t *EsOutAddLocked( es_out_t *out, input_source_t *source,
return NULL;
}
- /* Search the program */
- p_pgrm = EsOutProgramInsert( out, source, fmt->i_group );
- if( !p_pgrm )
+ if( !EsOutIsGroupSticky( out, source, fmt->i_group ) )
{
- es_format_Clean( &es->fmt );
- input_source_Release( es->id.source );
- free( str_id );
- free( es );
- return NULL;
- }
+ /* Search the program */
+ p_pgrm = EsOutProgramInsert( out, source, fmt->i_group );
+ if( !p_pgrm )
+ {
+ es_format_Clean( &es->fmt );
+ input_source_Release( es->id.source );
+ free( str_id );
+ free( es );
+ return NULL;
+ }
+ /* Increase ref count for program */
+ if( p_pgrm )
+ p_pgrm->i_es++;
- /* The group 0 is the default one and can be used by different contexts */
- assert( fmt->i_group == 0 || p_pgrm->source == es->id.source );
+ /* The group 0 is the default one and can be used by different contexts */
+ assert( fmt->i_group == 0 || p_pgrm->source == es->id.source );
+ }
+ else
+ p_pgrm = p_sys->p_pgrm; /* Use the selected program (can be NULL) */
/* Get the number of ES already added in order to get the position of the es */
es->i_pos = 0;
@@ -2000,9 +2053,6 @@ static es_out_id_t *EsOutAddLocked( es_out_t *out, input_source_t *source,
if( it->fmt.i_cat == fmt->i_cat && it->fmt.i_group == fmt->i_group )
es->i_pos++;
- /* Increase ref count for program */
- p_pgrm->i_es++;
-
/* Set up ES */
es->p_pgrm = p_pgrm;
@@ -2119,6 +2169,8 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es )
.on_update = ClockUpdate
};
+ assert( p_es->p_pgrm );
+
if( p_es->fmt.i_cat != UNKNOWN_ES
&& p_es->fmt.i_cat == p_sys->i_master_source_cat
&& p_es->p_pgrm->p_master_clock == NULL )
@@ -2183,6 +2235,8 @@ static void EsOutDestroyDecoder( es_out_t *out, es_out_id_t *p_es )
if( !p_es->p_dec )
return;
+ assert( p_es->p_pgrm );
+
input_DecoderDelete( p_es->p_dec );
p_es->p_dec = NULL;
if( p_es->p_pgrm->p_master_clock == p_es->p_clock )
@@ -2211,6 +2265,9 @@ static void EsOutSelectEs( es_out_t *out, es_out_id_t *es )
return;
}
+ if( !es->p_pgrm )
+ return;
+
if( es->p_master )
{
int i_channel;
@@ -2372,7 +2429,8 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
es_out_es_props_t *p_esprops = GetPropsByCat( p_sys, es->fmt.i_cat );
if( !p_sys->b_active ||
- ( !b_force && es->fmt.i_priority < ES_PRIORITY_SELECTABLE_MIN ) )
+ ( !b_force && es->fmt.i_priority < ES_PRIORITY_SELECTABLE_MIN ) ||
+ !es->p_pgrm )
{
return;
}
@@ -2733,11 +2791,15 @@ static void EsOutDelLocked( es_out_t *out, es_out_id_t *es )
EsOutDeleteInfoEs( out, es );
/* Update program */
- es->p_pgrm->i_es--;
- if( es->p_pgrm->i_es == 0 )
- msg_Dbg( p_sys->p_input, "Program doesn't contain anymore ES" );
+ if( EsOutIsGroupSticky( out, es->id.source, es->fmt.i_group ) )
+ {
+ assert( es->p_pgrm );
- if( es->b_scrambled )
+ es->p_pgrm->i_es--;
+ if( es->p_pgrm->i_es == 0 )
+ msg_Dbg( p_sys->p_input, "Program doesn't contain anymore ES" );
+ }
+ if( es->b_scrambled && es->p_pgrm )
EsOutProgramUpdateScrambled( out, es->p_pgrm );
/* */
@@ -3158,7 +3220,7 @@ static int EsOutVaControlLocked( es_out_t *out, input_source_t *source,
es_out_id_t *es = va_arg( args, es_out_id_t * );
bool b_scrambled = (bool)va_arg( args, int );
- if( !es->b_scrambled != !b_scrambled )
+ if( es->p_pgrm && !es->b_scrambled != !b_scrambled )
{
es->b_scrambled = b_scrambled;
EsOutProgramUpdateScrambled( out, es->p_pgrm );
More information about the vlc-commits
mailing list