[vlc-devel] [PATCH] es_out: fully refactor es_selection
Francois Cartegnie
fcvlcdev at free.fr
Mon Sep 26 18:57:38 CEST 2016
also changes sub-language to "none", fixing the none/any logic.
---
src/input/es_out.c | 271 +++++++++++++++++++++-------------------------------
src/libvlc-module.c | 2 +-
2 files changed, 112 insertions(+), 161 deletions(-)
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 60703e2..25a3be2 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -104,6 +104,19 @@ struct es_out_id_t
int i_meta_id;
};
+typedef struct
+{
+ int i_count; /* es count */
+ es_out_id_t *p_main_es; /* current main es */
+ enum es_out_policy_e e_policy;
+
+ /* Parameters used for es selection */
+ int i_id; /* es id as set by es fmt.id */
+ int i_demux_id; /* same as previous, demuxer set default value */
+ int i_channel; /* es number in creation order */
+ char **ppsz_language;
+} es_out_es_props_t;
+
struct es_out_sys_t
{
input_thread_t *p_input;
@@ -125,20 +138,10 @@ struct es_out_sys_t
bool b_active;
int i_mode;
- struct es_out_es_props_s
- {
- int i_count; /* es count */
- int i_id; /* es id as set by es fmt.id */
- int i_channel; /* es number in creation order */
- es_out_id_t *p_main_es; /* current main es */
- enum es_out_policy_e e_policy;
- } video, audio, sub;
+ es_out_es_props_t video, audio, sub;
/* es/group to select */
int i_group_id;
- int i_default_sub_id; /* As specified in container; if applicable */
- char **ppsz_audio_language;
- char **ppsz_sub_language;
/* delay */
int64_t i_audio_delay;
@@ -221,7 +224,10 @@ static inline bool EsFmtIsTeletext( const es_format_t *p_fmt )
return p_fmt->i_cat == SPU_ES && p_fmt->i_codec == VLC_CODEC_TELETEXT;
}
-static struct es_out_es_props_s * GetPropsByCat( es_out_sys_t *p_sys, int i_cat )
+/*****************************************************************************
+ * Es category specific structs
+ *****************************************************************************/
+static es_out_es_props_t * GetPropsByCat( es_out_sys_t *p_sys, int i_cat )
{
switch( i_cat )
{
@@ -235,6 +241,45 @@ static struct es_out_es_props_s * GetPropsByCat( es_out_sys_t *p_sys, int i_cat
return NULL;
}
+static void EsOutPropsCleanup( es_out_es_props_t *p_props )
+{
+ if( p_props->ppsz_language )
+ {
+ for( int i = 0; p_props->ppsz_language[i]; i++ )
+ free( p_props->ppsz_language[i] );
+ free( p_props->ppsz_language );
+ }
+}
+
+static void EsOutPropsInit( es_out_es_props_t *p_props,
+ input_thread_t *p_input,
+ enum es_out_policy_e e_default_policy,
+ const char *psz_trackidvar,
+ const char *psz_trackvar,
+ const char *psz_langvar,
+ const char *psz_debug )
+{
+ p_props->e_policy = e_default_policy;
+ p_props->i_count = 0;
+ p_props->i_id = (psz_trackidvar) ? var_GetInteger( p_input, psz_trackidvar ): -1;
+ p_props->i_channel = (psz_trackvar) ? var_GetInteger( p_input, psz_trackvar ): -1;
+ p_props->i_demux_id = -1;
+ p_props->p_main_es = NULL;
+
+ if( !p_input->b_preparsing && psz_langvar )
+ {
+ char *psz_string = var_GetString( p_input, psz_langvar );
+ p_props->ppsz_language = LanguageSplit( psz_string, true );
+ if( p_props->ppsz_language )
+ {
+ for( int i = 0; p_props->ppsz_language[i]; i++ )
+ msg_Dbg( p_input, "selected %s language[%d] %s",
+ psz_debug, i, p_props->ppsz_language[i] );
+ }
+ free( psz_string );
+ }
+}
+
/*****************************************************************************
* input_EsOutNew:
*****************************************************************************/
@@ -269,53 +314,15 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
TAB_INIT( p_sys->i_es, p_sys->es );
/* */
- p_sys->video.e_policy = ES_OUT_ES_POLICY_SIMULTANEOUS;
- p_sys->video.i_count = 0;
- p_sys->video.i_id = -1;
- p_sys->video.i_channel = -1;
- p_sys->video.p_main_es = NULL;
-
- p_sys->audio.e_policy = ES_OUT_ES_POLICY_EXCLUSIVE;
- p_sys->audio.i_count = 0;
- p_sys->audio.i_id = var_GetInteger( p_input, "audio-track-id" );
- p_sys->audio.i_channel = var_GetInteger( p_input, "audio-track" );
- p_sys->audio.p_main_es = NULL;
-
- p_sys->sub.e_policy = ES_OUT_ES_POLICY_EXCLUSIVE;
- p_sys->sub.i_count = 0;
- p_sys->sub.i_id = var_GetInteger( p_input, "sub-track-id" );
- p_sys->sub.i_channel = var_GetInteger( p_input, "sub-track" );
- p_sys->sub.p_main_es = NULL;
+ EsOutPropsInit( &p_sys->video, p_input, ES_OUT_ES_POLICY_SIMULTANEOUS,
+ NULL, NULL, NULL, NULL );
+ EsOutPropsInit( &p_sys->audio, p_input, ES_OUT_ES_POLICY_EXCLUSIVE,
+ "audio-track-id", "audio-track", "audio-language", "audio" );
+ EsOutPropsInit( &p_sys->sub, p_input, ES_OUT_ES_POLICY_EXCLUSIVE,
+ "sub-track-id", "sub-track", "sub-language", "sub" );
p_sys->i_group_id = var_GetInteger( p_input, "program" );
- p_sys->i_default_sub_id = -1;
-
- if( !p_input->b_preparsing )
- {
- char *psz_string;
-
- psz_string = var_GetString( p_input, "audio-language" );
- p_sys->ppsz_audio_language = LanguageSplit( psz_string, true );
- if( p_sys->ppsz_audio_language )
- {
- for( int i = 0; p_sys->ppsz_audio_language[i]; i++ )
- msg_Dbg( p_input, "selected audio language[%d] %s",
- i, p_sys->ppsz_audio_language[i] );
- }
- free( psz_string );
-
- psz_string = var_GetString( p_input, "sub-language" );
- p_sys->ppsz_sub_language = LanguageSplit( psz_string, false );
- if( p_sys->ppsz_sub_language )
- {
- for( int i = 0; p_sys->ppsz_sub_language[i]; i++ )
- msg_Dbg( p_input, "selected subtitle language[%d] %s",
- i, p_sys->ppsz_sub_language[i] );
- }
- free( psz_string );
- }
-
p_sys->i_pause_date = -1;
p_sys->i_rate = i_rate;
@@ -335,18 +342,8 @@ static void EsOutDelete( es_out_t *out )
es_out_sys_t *p_sys = out->p_sys;
assert( !p_sys->i_es && !p_sys->i_pgrm && !p_sys->p_pgrm );
- if( p_sys->ppsz_audio_language )
- {
- for( int i = 0; p_sys->ppsz_audio_language[i]; i++ )
- free( p_sys->ppsz_audio_language[i] );
- free( p_sys->ppsz_audio_language );
- }
- if( p_sys->ppsz_sub_language )
- {
- for( int i = 0; p_sys->ppsz_sub_language[i]; i++ )
- free( p_sys->ppsz_sub_language[i] );
- free( p_sys->ppsz_sub_language );
- }
+ EsOutPropsCleanup( &p_sys->audio );
+ EsOutPropsCleanup( &p_sys->sub );
vlc_mutex_destroy( &p_sys->lock );
@@ -1770,9 +1767,7 @@ static void EsUnselect( es_out_t *out, es_out_id_t *es, bool b_update )
static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
{
es_out_sys_t *p_sys = out->p_sys;
-
- int i_cat = es->fmt.i_cat;
- struct es_out_es_props_s *p_esprops = GetPropsByCat( p_sys, es->fmt.i_cat );
+ 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 ) )
@@ -1813,104 +1808,60 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
if( es->p_pgrm != p_sys->p_pgrm || !p_esprops )
return;
- if( i_cat == AUDIO_ES )
+ /* user designated by ID ES have higher prio than everything */
+ if ( p_esprops->i_id >= 0 )
{
- if( p_sys->ppsz_audio_language )
- {
- int es_idx = LanguageArrayIndex( p_sys->ppsz_audio_language,
- es->psz_language_code );
- if( !p_sys->audio.p_main_es )
- {
- /* Only select the language if it's in the list */
- if( es_idx >= 0 )
- wanted_es = es;
- }
- else
- {
- int selected_es_idx =
- LanguageArrayIndex( p_sys->ppsz_audio_language,
- p_sys->audio.p_main_es->psz_language_code );
- if( es_idx >= 0 &&
- ( selected_es_idx < 0 || es_idx < selected_es_idx ||
- ( es_idx == selected_es_idx &&
- p_sys->audio.p_main_es->fmt.i_priority < es->fmt.i_priority ) ) )
- wanted_es = es;
- }
- }
- else
- {
- /* Select the first one if there is no selected audio yet
- * then choose by ES priority */
- if( !p_sys->audio.p_main_es ||
- p_sys->audio.p_main_es->fmt.i_priority < es->fmt.i_priority )
- wanted_es = es;
- }
+ if( es->i_id == p_esprops->i_id )
+ wanted_es = es;
+ }
+ /* then per pos */
+ else if( p_esprops->i_channel >= 0 )
+ {
+ if( p_esprops->i_channel == es->i_channel )
+ wanted_es = es;
}
- else if( i_cat == SPU_ES )
+ else if( p_esprops->ppsz_language )
{
- if( p_sys->ppsz_sub_language )
+ /* If not deactivated */
+ const int i_stop_idx = LanguageArrayIndex( p_esprops->ppsz_language, "none" );
{
- int es_idx = LanguageArrayIndex( p_sys->ppsz_sub_language,
- es->psz_language_code );
- if( !p_sys->sub.p_main_es )
+ int current_es_idx = ( p_esprops->p_main_es == NULL ) ? -1 :
+ LanguageArrayIndex( p_esprops->ppsz_language,
+ p_esprops->p_main_es->psz_language_code );
+ int es_idx = LanguageArrayIndex( p_esprops->ppsz_language,
+ es->psz_language_code );
+ if( es_idx >= 0 && (i_stop_idx < 0 || i_stop_idx > es_idx) )
{
- /* Select the language if it's in the list */
- if( es_idx >= 0 ||
- /*FIXME: Should default subtitle not in the list be
- * displayed if not forbidden by none? */
- ( p_sys->i_default_sub_id >= 0 &&
- /* check if the subtitle isn't forbidden by none */
- LanguageArrayIndex( p_sys->ppsz_sub_language, "none" ) < 0 &&
- es->i_id == p_sys->i_default_sub_id ) )
+ /* Only select the language if it's in the list */
+ if( p_esprops->p_main_es == NULL ||
+ current_es_idx < 0 || /* current es was not selected by lang prefs */
+ es_idx < current_es_idx || /* current es has lower lang prio */
+ ( es_idx == current_es_idx && /* lang is same, but es has higher prio */
+ p_esprops->p_main_es->fmt.i_priority < es->fmt.i_priority ) )
+ {
wanted_es = es;
+ }
}
- else
- {
- int selected_es_idx =
- LanguageArrayIndex( p_sys->ppsz_sub_language,
- p_sys->sub.p_main_es->psz_language_code );
-
- if( es_idx >= 0 &&
- ( selected_es_idx < 0 || es_idx < selected_es_idx ||
- ( es_idx == selected_es_idx &&
- p_sys->sub.p_main_es->fmt.i_priority < es->fmt.i_priority ) ) )
+ else if( i_stop_idx < 0 &&
+ ( p_esprops->p_main_es == NULL ||
+ ( p_esprops->i_demux_id >= 0 &&
+ current_es_idx < 0 &&
+ es->i_id == p_esprops->i_demux_id ) ) )
+ {
wanted_es = es;
- }
- }
- else
- {
- /* If there is no user preference, select the default subtitle
- * or adapt by ES priority */
- if( ( !p_sys->sub.p_main_es &&
- ( p_sys->i_default_sub_id >= 0 &&
- es->i_id == p_sys->i_default_sub_id ) ) ||
- ( p_sys->sub.p_main_es &&
- p_sys->sub.p_main_es->fmt.i_priority < es->fmt.i_priority ) )
- wanted_es = es;
- else if( p_sys->sub.p_main_es &&
- p_sys->sub.p_main_es->fmt.i_priority >= es->fmt.i_priority )
- wanted_es = p_sys->sub.p_main_es;
+ }
}
+
}
- else if( i_cat == VIDEO_ES )
+ /* If there is no user preference, select the default subtitle
+ * or adapt by ES priority */
+ else if( ( p_esprops->i_demux_id >= 0 && es->i_id == p_esprops->i_demux_id ) ||
+ p_esprops->p_main_es == NULL ||
+ es->fmt.i_priority > p_esprops->p_main_es->fmt.i_priority )
{
wanted_es = es;
}
- if( p_esprops )
- {
- if( p_esprops->i_channel == es->i_channel )
- wanted_es = es;
-
- if( p_esprops->i_id >= 0 )
- {
- if( es->i_id == p_esprops->i_id )
- wanted_es = es;
- else
- return;
- }
- }
-
if( wanted_es == es && !EsIsSelected( es ) )
EsSelect( out, es );
}
@@ -2069,7 +2020,7 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
vlc_mutex_lock( &p_sys->lock );
- struct es_out_es_props_s *p_esprops = GetPropsByCat( p_sys, es->fmt.i_cat );
+ es_out_es_props_t *p_esprops = GetPropsByCat( p_sys, es->fmt.i_cat );
/* We don't try to reselect */
if( es->p_dec )
@@ -2178,7 +2129,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
{
enum es_format_category_e i_cat = va_arg( args, enum es_format_category_e );
enum es_out_policy_e i_pol = va_arg( args, enum es_out_policy_e );
- struct es_out_es_props_s *p_esprops = GetPropsByCat( p_sys, i_cat );
+ es_out_es_props_t *p_esprops = GetPropsByCat( p_sys, i_cat );
if( p_esprops == NULL )
return VLC_EGENERIC;
p_esprops->e_policy = i_pol;
@@ -2300,7 +2251,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
{
/*p_sys->i_default_video_id = -1;*/
/*p_sys->i_default_audio_id = -1;*/
- p_sys->i_default_sub_id = -1;
+ p_sys->sub.i_demux_id = -1;
}
else if( es == (es_out_id_t*)((uint8_t*)NULL+AUDIO_ES) )
{
@@ -2312,7 +2263,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
}
else if( es == (es_out_id_t*)((uint8_t*)NULL+SPU_ES) )
{
- p_sys->i_default_sub_id = -1;
+ p_sys->sub.i_demux_id = -1;
}
else
{
@@ -2323,7 +2274,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
p_sys->i_default_audio_id = es->i_id;
else*/
if( es->fmt.i_cat == SPU_ES )
- p_sys->i_default_sub_id = es->i_id;
+ p_sys->sub.i_demux_id = es->i_id;
}
return VLC_SUCCESS;
}
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index ea13769..5d6f466 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -1683,7 +1683,7 @@ vlc_module_begin ()
INPUT_AUDIOTRACK_LANG_TEXT, INPUT_AUDIOTRACK_LANG_LONGTEXT,
false )
change_safe ()
- add_string( "sub-language", "",
+ add_string( "sub-language", "none",
INPUT_SUBTRACK_LANG_TEXT, INPUT_SUBTRACK_LANG_LONGTEXT,
false )
change_safe ()
--
2.7.4
More information about the vlc-devel
mailing list