[vlc-devel] [RFC PATCH 3/3] decoder: protect vout and aout during read

Thomas Guillem thomas at gllm.fr
Wed Apr 1 16:13:18 CEST 2015


---
 src/input/decoder.c | 72 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 58 insertions(+), 14 deletions(-)

diff --git a/src/input/decoder.c b/src/input/decoder.c
index 1fd5b90..4f0e5f8 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -89,12 +89,11 @@ struct decoder_owner_sys_t
     vlc_mutex_t lock;
     vlc_cond_t  wait;
 
-    /* -- These variables need locking on write(only) -- */
+    /* -- Theses variables need locking on read *and* write -- */
     audio_output_t *p_aout;
 
     vout_thread_t   *p_vout;
 
-    /* -- Theses variables need locking on read *and* write -- */
     /* Pause */
     bool b_paused;
     struct
@@ -182,6 +181,28 @@ static block_t *DecoderBlockFlushNew()
     return p_null;
 }
 
+static audio_output_t *DecoderGetAout( decoder_t *p_dec )
+{
+    decoder_owner_sys_t *p_owner = p_dec->p_owner;
+    audio_output_t *p_aout;
+
+    vlc_mutex_lock( &p_owner->lock );
+    p_aout = p_owner->p_aout;
+    vlc_mutex_unlock( &p_owner->lock );
+    return p_aout;
+}
+
+static vout_thread_t *DecoderGetVout( decoder_t *p_dec )
+{
+    decoder_owner_sys_t *p_owner = p_dec->p_owner;
+    vout_thread_t *p_vout;
+
+    vlc_mutex_lock( &p_owner->lock );
+    p_vout = p_owner->p_vout;
+    vlc_mutex_unlock( &p_owner->lock );
+    return p_vout;
+}
+
 /*****************************************************************************
  * Buffers allocation callbacks for the decoders
  *****************************************************************************/
@@ -870,7 +891,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
                               int *pi_played_sum, int *pi_lost_sum )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
-    vout_thread_t  *p_vout = p_owner->p_vout;
+    vout_thread_t  *p_vout;
 
     if( p_picture->date <= VLC_TS_INVALID )
     {
@@ -905,6 +926,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
     DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
                   &i_rate, DECODER_BOGUS_VIDEO_DELAY );
 
+    p_vout = p_owner->p_vout;
     vlc_mutex_unlock( &p_owner->lock );
 
     /* */
@@ -949,14 +971,20 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
 
     while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )
     {
-        vout_thread_t  *p_vout = p_owner->p_vout;
-        if( DecoderIsFlushing( p_dec ) )
+        vout_thread_t *p_vout;
+
+        vlc_mutex_lock( &p_owner->lock );
+        if( p_owner->b_flushing )
         {   /* It prevent freezing VLC in case of broken decoder */
+            vlc_mutex_unlock( &p_owner->lock );
+
             picture_Release( p_pic );
             if( p_block )
                 block_Release( p_block );
             break;
         }
+        p_vout = p_owner->p_vout;
+        vlc_mutex_unlock( &p_owner->lock );
 
         i_decoded++;
 
@@ -1057,8 +1085,13 @@ static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block, bool b_flus
         DecoderDecodeVideo( p_dec, p_block );
     }
 
-    if( b_flush && p_owner->p_vout )
-        vout_Flush( p_owner->p_vout, VLC_TS_INVALID+1 );
+    if( b_flush )
+    {
+        vout_thread_t *p_vout = DecoderGetVout( p_dec );
+
+        if( p_vout )
+            vout_Flush( p_vout, VLC_TS_INVALID+1 );
+    }
 }
 
 static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
@@ -1153,9 +1186,11 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
 
         if( p_owner->i_preroll_end > VLC_TS_INVALID )
         {
+            audio_output_t *p_aout = DecoderGetAout( p_dec );
+
             msg_Dbg( p_dec, "End of audio preroll" );
-            if( p_owner->p_aout )
-                aout_DecFlush( p_owner->p_aout, false );
+            if( p_aout )
+                aout_DecFlush( p_aout, false );
             /* */
             p_owner->i_preroll_end = VLC_TS_INVALID;
         }
@@ -1220,8 +1255,13 @@ static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block, bool b_flus
         DecoderDecodeAudio( p_dec, p_block );
     }
 
-    if( b_flush && p_owner->p_aout )
-        aout_DecFlush( p_owner->p_aout, false );
+    if( b_flush )
+    {
+        audio_output_t *p_aout = DecoderGetAout( p_dec );
+
+        if( p_aout )
+            aout_DecFlush( p_aout, false );
+    }
 }
 
 static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic )
@@ -1453,8 +1493,10 @@ static void *DecoderThread( void *p_data )
         if( p_block == NULL )
         {   /* Draining: the decoder is drained and all decoded buffers are
              * queued to the output at this point. Now drain the output. */
-            if( p_owner->p_aout != NULL )
-                aout_DecFlush( p_owner->p_aout, true );
+            audio_output_t *p_aout = DecoderGetAout( p_dec );
+
+            if( p_aout != NULL )
+                aout_DecFlush( p_aout, true );
         }
         vlc_mutex_lock( &p_owner->lock );
         p_owner->b_drained = (p_block == NULL);
@@ -2161,9 +2203,11 @@ void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
     {
         if( p_owner->b_paused && p_owner->p_vout )
         {
+            vout_thread_t *p_vout = p_owner->p_vout;
+
             vlc_mutex_unlock( &p_owner->lock );
 
-            vout_NextPicture( p_owner->p_vout, pi_duration );
+            vout_NextPicture( p_vout, pi_duration );
 
             vlc_mutex_lock( &p_owner->lock );
             p_owner->pause.i_ignore++;
-- 
2.1.3




More information about the vlc-devel mailing list