Commit 007185b1 authored by Laurent Aimar's avatar Laurent Aimar

Added lock around es_out for multiple thread access.

It should fix race conditions when using stream demuxer.
It is a temporary way until I finish a few es_out modification.
parent e34927d3
...@@ -99,6 +99,9 @@ struct es_out_sys_t ...@@ -99,6 +99,9 @@ struct es_out_sys_t
{ {
input_thread_t *p_input; input_thread_t *p_input;
/* */
vlc_mutex_t lock;
/* all programs */ /* all programs */
int i_pgrm; int i_pgrm;
es_out_pgrm_t **pgrm; es_out_pgrm_t **pgrm;
...@@ -203,10 +206,11 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate ) ...@@ -203,10 +206,11 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
vlc_value_t val; vlc_value_t val;
int i; int i;
es_out_t *out = malloc( sizeof( es_out_t ) ); es_out_t *out = malloc( sizeof( *out ) );
if( !out ) return NULL; if( !out )
return NULL;
es_out_sys_t *p_sys = malloc( sizeof( es_out_sys_t ) ); es_out_sys_t *p_sys = malloc( sizeof( *p_sys ) );
if( !p_sys ) if( !p_sys )
{ {
free( out ); free( out );
...@@ -220,6 +224,8 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate ) ...@@ -220,6 +224,8 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
out->p_sys = p_sys; out->p_sys = p_sys;
out->b_sout = p_input->p->p_sout != NULL; out->b_sout = p_input->p->p_sout != NULL;
vlc_mutex_init_recursive( &p_sys->lock );
p_sys->p_input = p_input; p_sys->p_input = p_input;
p_sys->b_active = false; p_sys->b_active = false;
...@@ -352,6 +358,7 @@ void input_EsOutDelete( es_out_t *out ) ...@@ -352,6 +358,7 @@ void input_EsOutDelete( es_out_t *out )
free( p_pgrm ); free( p_pgrm );
} }
TAB_CLEAN( p_sys->i_pgrm, p_sys->pgrm ); TAB_CLEAN( p_sys->i_pgrm, p_sys->pgrm );
vlc_mutex_destroy( &p_sys->lock );
free( p_sys ); free( p_sys );
free( out ); free( out );
...@@ -362,7 +369,7 @@ es_out_id_t *input_EsOutGetFromID( es_out_t *out, int i_id ) ...@@ -362,7 +369,7 @@ es_out_id_t *input_EsOutGetFromID( es_out_t *out, int i_id )
int i; int i;
if( i_id < 0 ) if( i_id < 0 )
{ {
/* Special HACK, -i_id is tha cat of the stream */ /* Special HACK, -i_id is the cat of the stream */
return (es_out_id_t*)((uint8_t*)NULL-i_id); return (es_out_id_t*)((uint8_t*)NULL-i_id);
} }
...@@ -652,6 +659,15 @@ void input_EsOutFrameNext( es_out_t *out ) ...@@ -652,6 +659,15 @@ void input_EsOutFrameNext( es_out_t *out )
p_sys->i_preroll_end = -1; p_sys->i_preroll_end = -1;
} }
void input_EsOutLock( es_out_t *out )
{
vlc_mutex_lock( &out->p_sys->lock );
}
void input_EsOutUnlock( es_out_t *out )
{
vlc_mutex_unlock( &out->p_sys->lock );
}
/***************************************************************************** /*****************************************************************************
* *
*****************************************************************************/ *****************************************************************************/
...@@ -1275,19 +1291,21 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt ) ...@@ -1275,19 +1291,21 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
es_out_sys_t *p_sys = out->p_sys; es_out_sys_t *p_sys = out->p_sys;
input_thread_t *p_input = p_sys->p_input; input_thread_t *p_input = p_sys->p_input;
es_out_id_t *es = malloc( sizeof( es_out_id_t ) );
es_out_pgrm_t *p_pgrm = NULL;
int i;
if( !es ) return NULL;
if( fmt->i_group < 0 ) if( fmt->i_group < 0 )
{ {
msg_Err( p_input, "invalid group number" ); msg_Err( p_input, "invalid group number" );
free( es );
return NULL; return NULL;
} }
es_out_id_t *es = malloc( sizeof( *es ) );
es_out_pgrm_t *p_pgrm = NULL;
int i;
if( !es )
return NULL;
vlc_mutex_lock( &p_sys->lock );
/* Search the program */ /* Search the program */
for( i = 0; i < p_sys->i_pgrm; i++ ) for( i = 0; i < p_sys->i_pgrm; i++ )
{ {
...@@ -1391,6 +1409,8 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt ) ...@@ -1391,6 +1409,8 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
EsOutAddInfo( out, es ); EsOutAddInfo( out, es );
vlc_mutex_unlock( &p_sys->lock );
return es; return es;
} }
...@@ -1790,6 +1810,8 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ) ...@@ -1790,6 +1810,8 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
vlc_mutex_unlock( &p_input->p->counters.counters_lock ); vlc_mutex_unlock( &p_input->p->counters.counters_lock );
} }
vlc_mutex_lock( &p_sys->lock );
/* Mark preroll blocks */ /* Mark preroll blocks */
if( p_sys->i_preroll_end >= 0 ) if( p_sys->i_preroll_end >= 0 )
{ {
...@@ -1806,6 +1828,7 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ) ...@@ -1806,6 +1828,7 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
if( !es->p_dec ) if( !es->p_dec )
{ {
block_Release( p_block ); block_Release( p_block );
vlc_mutex_unlock( &p_sys->lock );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -1853,6 +1876,8 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ) ...@@ -1853,6 +1876,8 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
if( b_cc_new ) if( b_cc_new )
var_SetBool( p_sys->p_input, "intf-change", true ); var_SetBool( p_sys->p_input, "intf-change", true );
vlc_mutex_unlock( &p_sys->lock );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -1865,6 +1890,8 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es ) ...@@ -1865,6 +1890,8 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
bool b_reselect = false; bool b_reselect = false;
int i; int i;
vlc_mutex_lock( &p_sys->lock );
/* We don't try to reselect */ /* We don't try to reselect */
if( es->p_dec ) if( es->p_dec )
{ {
...@@ -1911,17 +1938,21 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es ) ...@@ -1911,17 +1938,21 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
/* Re-select another track when needed */ /* Re-select another track when needed */
if( b_reselect ) if( b_reselect )
{
for( i = 0; i < p_sys->i_es; i++ ) for( i = 0; i < p_sys->i_es; i++ )
{ {
if( es->fmt.i_cat == p_sys->es[i]->fmt.i_cat ) if( es->fmt.i_cat == p_sys->es[i]->fmt.i_cat )
EsOutSelect( out, p_sys->es[i], false ); EsOutSelect( out, p_sys->es[i], false );
} }
}
free( es->psz_language ); free( es->psz_language );
free( es->psz_language_code ); free( es->psz_language_code );
es_format_Clean( &es->fmt ); es_format_Clean( &es->fmt );
vlc_mutex_unlock( &p_sys->lock );
free( es ); free( es );
} }
...@@ -1933,7 +1964,7 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es ) ...@@ -1933,7 +1964,7 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
* \param args a variable list of arguments for the query * \param args a variable list of arguments for the query
* \return VLC_SUCCESS or an error code * \return VLC_SUCCESS or an error code
*/ */
static int EsOutControl( es_out_t *out, int i_query, va_list args ) static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
{ {
es_out_sys_t *p_sys = out->p_sys; es_out_sys_t *p_sys = out->p_sys;
bool b, *pb; bool b, *pb;
...@@ -2257,6 +2288,17 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args ) ...@@ -2257,6 +2288,17 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
} }
static int EsOutControl( es_out_t *out, int i_query, va_list args )
{
es_out_sys_t *p_sys = out->p_sys;
int i_ret;
vlc_mutex_lock( &p_sys->lock );
i_ret = EsOutControlLocked( out, i_query, args );
vlc_mutex_unlock( &p_sys->lock );
return i_ret;
}
/**************************************************************************** /****************************************************************************
* LanguageGetName: try to expend iso639 into plain name * LanguageGetName: try to expend iso639 into plain name
......
...@@ -44,4 +44,7 @@ bool input_EsOutDecodersIsEmpty( es_out_t * ); ...@@ -44,4 +44,7 @@ bool input_EsOutDecodersIsEmpty( es_out_t * );
bool input_EsOutIsBuffering( es_out_t * ); bool input_EsOutIsBuffering( es_out_t * );
void input_EsOutFrameNext( es_out_t * ); void input_EsOutFrameNext( es_out_t * );
void input_EsOutLock( es_out_t * );
void input_EsOutUnlock( es_out_t * );
#endif #endif
...@@ -743,13 +743,18 @@ static void MainLoop( input_thread_t *p_input ) ...@@ -743,13 +743,18 @@ static void MainLoop( input_thread_t *p_input )
/* FIXME if p_input->i_state == PAUSE_S the access/access_demux /* FIXME if p_input->i_state == PAUSE_S the access/access_demux
* is paused -> this may cause problem with some of them * is paused -> this may cause problem with some of them
* The same problem can be seen when seeking while paused */ * The same problem can be seen when seeking while paused */
input_EsOutLock( p_input->p->p_es_out );
b_paused = p_input->i_state == PAUSE_S && b_paused = p_input->i_state == PAUSE_S &&
!input_EsOutIsBuffering( p_input->p->p_es_out ); !input_EsOutIsBuffering( p_input->p->p_es_out );
input_EsOutUnlock( p_input->p->p_es_out );
if( !b_paused ) if( !b_paused )
{ {
MainLoopDemux( p_input, &b_force_update, &i_start_mdate ); MainLoopDemux( p_input, &b_force_update, &i_start_mdate );
input_EsOutLock( p_input->p->p_es_out );
i_wakeup = input_EsOutGetWakeup( p_input->p->p_es_out ); i_wakeup = input_EsOutGetWakeup( p_input->p->p_es_out );
input_EsOutUnlock( p_input->p->p_es_out );
} }
/* */ /* */
...@@ -764,6 +769,7 @@ static void MainLoop( input_thread_t *p_input ) ...@@ -764,6 +769,7 @@ static void MainLoop( input_thread_t *p_input )
while( !ControlPopNoLock( p_input, &i_type, &val, i_deadline ) ) while( !ControlPopNoLock( p_input, &i_type, &val, i_deadline ) )
{ {
msg_Dbg( p_input, "control type=%d", i_type ); msg_Dbg( p_input, "control type=%d", i_type );
if( Control( p_input, i_type, val ) ) if( Control( p_input, i_type, val ) )
b_force_update = true; b_force_update = true;
} }
...@@ -786,9 +792,11 @@ static void MainLoop( input_thread_t *p_input ) ...@@ -786,9 +792,11 @@ static void MainLoop( input_thread_t *p_input )
/* Check if i_wakeup is still valid */ /* Check if i_wakeup is still valid */
if( i_wakeup != 0 ) if( i_wakeup != 0 )
{ {
input_EsOutLock( p_input->p->p_es_out );
mtime_t i_new_wakeup = input_EsOutGetWakeup( p_input->p->p_es_out ); mtime_t i_new_wakeup = input_EsOutGetWakeup( p_input->p->p_es_out );
if( !i_new_wakeup ) if( !i_new_wakeup )
i_wakeup = 0; i_wakeup = 0;
input_EsOutUnlock( p_input->p->p_es_out );
} }
} while( i_current < i_wakeup ); } while( i_current < i_wakeup );
} }
...@@ -798,7 +806,11 @@ static void MainLoop( input_thread_t *p_input ) ...@@ -798,7 +806,11 @@ static void MainLoop( input_thread_t *p_input )
/* We have finish to demux data but not to play them */ /* We have finish to demux data but not to play them */
while( vlc_object_alive( p_input ) ) while( vlc_object_alive( p_input ) )
{ {
if( input_EsOutDecodersIsEmpty( p_input->p->p_es_out ) ) input_EsOutLock( p_input->p->p_es_out );
bool b_empty = input_EsOutDecodersIsEmpty( p_input->p->p_es_out );
input_EsOutUnlock( p_input->p->p_es_out );
if( b_empty )
break; break;
msg_Dbg( p_input, "waiting decoder fifos to empty" ); msg_Dbg( p_input, "waiting decoder fifos to empty" );
...@@ -1547,6 +1559,8 @@ static bool Control( input_thread_t *p_input, int i_type, ...@@ -1547,6 +1559,8 @@ static bool Control( input_thread_t *p_input, int i_type,
if( !p_input ) if( !p_input )
return b_force_update; return b_force_update;
input_EsOutLock( p_input->p->p_es_out );
switch( i_type ) switch( i_type )
{ {
case INPUT_CONTROL_SET_DIE: case INPUT_CONTROL_SET_DIE:
...@@ -2063,6 +2077,8 @@ static bool Control( input_thread_t *p_input, int i_type, ...@@ -2063,6 +2077,8 @@ static bool Control( input_thread_t *p_input, int i_type,
break; break;
} }
input_EsOutUnlock( p_input->p->p_es_out );
return b_force_update; return b_force_update;
} }
...@@ -3094,10 +3110,13 @@ static void SubtitleAdd( input_thread_t *p_input, char *psz_subtitle, bool b_for ...@@ -3094,10 +3110,13 @@ static void SubtitleAdd( input_thread_t *p_input, char *psz_subtitle, bool b_for
if( count.i_int < list.p_list->i_count ) if( count.i_int < list.p_list->i_count )
{ {
int i_id = list.p_list->p_values[count.i_int].i_int; int i_id = list.p_list->p_values[count.i_int].i_int;
input_EsOutLock( p_input->p->p_es_out );
es_out_id_t *p_es = input_EsOutGetFromID( p_input->p->p_es_out, i_id ); es_out_id_t *p_es = input_EsOutGetFromID( p_input->p->p_es_out, i_id );
es_out_Control( p_input->p->p_es_out, ES_OUT_SET_DEFAULT, p_es ); es_out_Control( p_input->p->p_es_out, ES_OUT_SET_DEFAULT, p_es );
es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ES, p_es ); es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ES, p_es );
input_EsOutUnlock( p_input->p->p_es_out );
} }
var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, NULL ); var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, NULL );
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment