[vlc-devel] commit: Added lock around es_out for multiple thread access. ( Laurent Aimar )

git version control git at videolan.org
Sat Nov 1 16:47:23 CET 2008


vlc | branch: master | Laurent Aimar <fenrir at videolan.org> | Sat Nov  1 16:19:52 2008 +0100| [007185b1ab1125ec04c9aa5bea1446f802dd5d5f] | committer: 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.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=007185b1ab1125ec04c9aa5bea1446f802dd5d5f
---

 src/input/es_out.c |   66 ++++++++++++++++++++++++++++++++++++++++++---------
 src/input/es_out.h |    3 ++
 src/input/input.c  |   21 +++++++++++++++-
 3 files changed, 77 insertions(+), 13 deletions(-)

diff --git a/src/input/es_out.c b/src/input/es_out.c
index 986ada5..c4e46e3 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -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
diff --git a/src/input/es_out.h b/src/input/es_out.h
index dbf79df..2766371 100644
--- a/src/input/es_out.h
+++ b/src/input/es_out.h
@@ -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
diff --git a/src/input/input.c b/src/input/input.c
index 1720a1c..7e4c8f9 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -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 );
     }




More information about the vlc-devel mailing list