vlc/vlc-3.0 | branch: master | Thomas Guillem <[email protected]> | Wed Feb 14 11:59:05 2018 +0100| [d029df0a8d3bf12a619e11d3d0b4be8243ed7741] | committer: Thomas Guillem
input: fix restart of all ES when changing renderer The sout was destroyed before decoders were deleted. This could lead to a use-after-free of the sout from the DecoderThread. To fix this issue, we stop all ES, save the stopped state of all ES, change the renderer/sout configuration and restart all previously stopped ES. Deprecate ES_OUT_RESTART_ALL_ES since it was only used for this case. And replace it by ES_OUT_STOP_ALL_ES/ES_OUT_START_ALL_ES, but in private headers. (cherry picked from commit 72f780a4b4819776fa0df2a7aa1fb69763fbdaa5) Signed-off-by: Thomas Guillem <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc/vlc-3.0.git/?a=commit;h=d029df0a8d3bf12a619e11d3d0b4be8243ed7741 --- include/vlc_es_out.h | 4 +--- src/input/es_out.c | 27 +++++++++++++++++++++++++-- src/input/es_out.h | 6 ++++++ src/input/es_out_timeshift.c | 2 ++ src/input/input.c | 8 +++++++- 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/include/vlc_es_out.h b/include/vlc_es_out.h index fbed8bd3ae..fe53c2a3d3 100644 --- a/include/vlc_es_out.h +++ b/include/vlc_es_out.h @@ -38,9 +38,7 @@ enum es_out_query_e /* set or change the selected ES in its category (audio/video/spu) */ ES_OUT_SET_ES, /* arg1= es_out_id_t* */ ES_OUT_RESTART_ES, /* arg1= es_out_id_t* */ - /* Restart all ES, destroying and recreating decoder/sout and potential - * video/audio outputs. This is not recommended and might not even work */ - ES_OUT_RESTART_ALL_ES, /* No arg */ + ES_OUT_RESTART_ALL_ES, /* Deprecated, no effect */ /* set 'default' tag on ES (copied across from container) */ ES_OUT_SET_ES_DEFAULT, /* arg1= es_out_id_t* */ diff --git a/src/input/es_out.c b/src/input/es_out.c index 02ba4f6a15..69cd7bc7b9 100644 --- a/src/input/es_out.c +++ b/src/input/es_out.c @@ -2390,16 +2390,39 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) } return VLC_SUCCESS; } - case ES_OUT_RESTART_ALL_ES: + case ES_OUT_STOP_ALL_ES: { + int *selected_es = vlc_alloc(p_sys->i_es + 1, sizeof(int)); + if (!selected_es) + return VLC_ENOMEM; + selected_es[0] = p_sys->i_es; for( int i = 0; i < p_sys->i_es; i++ ) { if( EsIsSelected( p_sys->es[i] ) ) { EsDestroyDecoder( out, p_sys->es[i] ); - EsCreateDecoder( out, p_sys->es[i] ); + selected_es[i + 1] = p_sys->es[i]->i_id; + } + else + selected_es[i + 1] = -1; + } + *va_arg( args, void **) = selected_es; + return VLC_SUCCESS; + } + case ES_OUT_START_ALL_ES: + { + int *selected_es = va_arg( args, void * ); + int count = selected_es[0]; + for( int i = 0; i < count; ++i ) + { + int i_id = selected_es[i + 1]; + if( i_id != -1 ) + { + es_out_id_t *p_es = EsOutGetFromID( out, i_id ); + EsCreateDecoder( out, p_es ); } } + free(selected_es); return VLC_SUCCESS; } diff --git a/src/input/es_out.h b/src/input/es_out.h index 56cefed7c9..8f202266e8 100644 --- a/src/input/es_out.h +++ b/src/input/es_out.h @@ -50,6 +50,12 @@ enum es_out_query_private_e ES_OUT_SET_ES_DEFAULT_BY_ID, ES_OUT_GET_ES_OBJECTS_BY_ID, /* arg1=int id, vlc_object_t **dec, vout_thread_t **, audio_output_t ** res=can fail*/ + /* Stop all selected ES and save the stopped state in a context. free the + * context or call ES_OUT_STOP_ALL_ES */ + ES_OUT_STOP_ALL_ES, /* arg1=void ** */ + /* Start all ES from the context returned by ES_OUT_STOP_ALL_ES */ + ES_OUT_START_ALL_ES, /* arg1=void * */ + /* Get buffering state */ ES_OUT_GET_BUFFERING, /* arg1=bool* res=cannot fail */ diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c index c6dd83ebb8..e30f923958 100644 --- a/src/input/es_out_timeshift.c +++ b/src/input/es_out_timeshift.c @@ -743,6 +743,8 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args ) case ES_OUT_RESTART_ES_BY_ID: case ES_OUT_SET_ES_DEFAULT_BY_ID: case ES_OUT_GET_ES_OBJECTS_BY_ID: + case ES_OUT_STOP_ALL_ES: + case ES_OUT_START_ALL_ES: case ES_OUT_SET_DELAY: case ES_OUT_SET_RECORD_STATE: default: diff --git a/src/input/input.c b/src/input/input.c index 7eafa55ce7..92befcd2a8 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -1902,7 +1902,6 @@ static void ControlUpdateRenderer( input_thread_t *p_input, bool b_enable ) input_priv(p_input)->p_sout, NULL ); input_priv(p_input)->p_sout = NULL; } - es_out_Control( input_priv(p_input)->p_es_out, ES_OUT_RESTART_ALL_ES ); } #endif @@ -2331,6 +2330,11 @@ static bool Control( input_thread_t *p_input, if ( p_item == NULL && p_priv->p_renderer == NULL ) break; + void *context; + if( es_out_Control( input_priv(p_input)->p_es_out_display, + ES_OUT_STOP_ALL_ES, &context ) != VLC_SUCCESS ) + break; + if ( p_priv->p_renderer ) { ControlUpdateRenderer( p_input, false ); @@ -2351,6 +2355,8 @@ static bool Control( input_thread_t *p_input, } input_resource_TerminateVout( p_priv->p_resource ); } + es_out_Control( input_priv(p_input)->p_es_out_display, ES_OUT_START_ALL_ES, + context ); #endif break; } _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
