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.
This commit is contained in:
Laurent Aimar 2008-11-01 16:19:52 +01:00
parent e34927d31d
commit 007185b1ab
3 changed files with 77 additions and 13 deletions

View File

@ -99,6 +99,9 @@ struct es_out_sys_t
{
input_thread_t *p_input;
/* */
vlc_mutex_t lock;
/* all programs */
int i_pgrm;
es_out_pgrm_t **pgrm;
@ -203,10 +206,11 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
vlc_value_t val;
int i;
es_out_t *out = malloc( sizeof( es_out_t ) );
if( !out ) return NULL;
es_out_t *out = malloc( sizeof( *out ) );
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 )
{
free( out );
@ -220,6 +224,8 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
out->p_sys = p_sys;
out->b_sout = p_input->p->p_sout != NULL;
vlc_mutex_init_recursive( &p_sys->lock );
p_sys->p_input = p_input;
p_sys->b_active = false;
@ -352,6 +358,7 @@ void input_EsOutDelete( es_out_t *out )
free( p_pgrm );
}
TAB_CLEAN( p_sys->i_pgrm, p_sys->pgrm );
vlc_mutex_destroy( &p_sys->lock );
free( p_sys );
free( out );
@ -362,7 +369,7 @@ es_out_id_t *input_EsOutGetFromID( es_out_t *out, int i_id )
int i;
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);
}
@ -652,6 +659,15 @@ void input_EsOutFrameNext( es_out_t *out )
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 )
es_out_sys_t *p_sys = out->p_sys;
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 )
{
msg_Err( p_input, "invalid group number" );
free( es );
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 */
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 )
EsOutAddInfo( out, es );
vlc_mutex_unlock( &p_sys->lock );
return es;
}
@ -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_lock( &p_sys->lock );
/* Mark preroll blocks */
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 )
if( !es->p_dec )
{
block_Release( p_block );
vlc_mutex_unlock( &p_sys->lock );
return VLC_SUCCESS;
}
@ -1853,6 +1876,8 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
if( b_cc_new )
var_SetBool( p_sys->p_input, "intf-change", true );
vlc_mutex_unlock( &p_sys->lock );
return VLC_SUCCESS;
}
@ -1865,6 +1890,8 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
bool b_reselect = false;
int i;
vlc_mutex_lock( &p_sys->lock );
/* We don't try to reselect */
if( es->p_dec )
{
@ -1911,17 +1938,21 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
/* Re-select another track when needed */
if( b_reselect )
{
for( i = 0; i < p_sys->i_es; i++ )
{
if( es->fmt.i_cat == p_sys->es[i]->fmt.i_cat )
EsOutSelect( out, p_sys->es[i], false );
}
}
free( es->psz_language );
free( es->psz_language_code );
es_format_Clean( &es->fmt );
vlc_mutex_unlock( &p_sys->lock );
free( 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
* \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;
bool b, *pb;
@ -2257,6 +2288,17 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
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

View File

@ -44,4 +44,7 @@ bool input_EsOutDecodersIsEmpty( es_out_t * );
bool input_EsOutIsBuffering( es_out_t * );
void input_EsOutFrameNext( es_out_t * );
void input_EsOutLock( es_out_t * );
void input_EsOutUnlock( es_out_t * );
#endif

View File

@ -743,13 +743,18 @@ static void MainLoop( input_thread_t *p_input )
/* FIXME if p_input->i_state == PAUSE_S the access/access_demux
* is paused -> this may cause problem with some of them
* 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 &&
!input_EsOutIsBuffering( p_input->p->p_es_out );
input_EsOutUnlock( p_input->p->p_es_out );
if( !b_paused )
{
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 );
input_EsOutUnlock( p_input->p->p_es_out );
}
/* */
@ -764,6 +769,7 @@ static void MainLoop( input_thread_t *p_input )
while( !ControlPopNoLock( p_input, &i_type, &val, i_deadline ) )
{
msg_Dbg( p_input, "control type=%d", i_type );
if( Control( p_input, i_type, val ) )
b_force_update = true;
}
@ -786,9 +792,11 @@ static void MainLoop( input_thread_t *p_input )
/* Check if i_wakeup is still valid */
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 );
if( !i_new_wakeup )
i_wakeup = 0;
input_EsOutUnlock( p_input->p->p_es_out );
}
} while( i_current < i_wakeup );
}
@ -798,7 +806,11 @@ static void MainLoop( input_thread_t *p_input )
/* We have finish to demux data but not to play them */
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;
msg_Dbg( p_input, "waiting decoder fifos to empty" );
@ -1547,6 +1559,8 @@ static bool Control( input_thread_t *p_input, int i_type,
if( !p_input )
return b_force_update;
input_EsOutLock( p_input->p->p_es_out );
switch( i_type )
{
case INPUT_CONTROL_SET_DIE:
@ -2063,6 +2077,8 @@ static bool Control( input_thread_t *p_input, int i_type,
break;
}
input_EsOutUnlock( p_input->p->p_es_out );
return b_force_update;
}
@ -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 )
{
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_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 );
input_EsOutUnlock( p_input->p->p_es_out );
}
var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, NULL );
}