[vlc-devel] [RFC PATCH 2/2] decoder: interruptible mwait

Thomas Guillem thomas at gllm.fr
Mon Nov 30 14:57:49 CET 2015


A recent error in srt parsing lead the SPU DecoderThread to wait for 160000sec
before displaying an spu. Therefore, you had to wait for that time when closing
or flushing this decoder.

mwait (called from Audio and SPU DecoderThread) can now be interrupted when
flushing or closing.

There is no check for this deadline. Maybe we should also test it in order to
not exceed a certain value (more than 3seconds ?).
---
 src/input/decoder.c | 40 +++++++++++++++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/src/input/decoder.c b/src/input/decoder.c
index 0f08198..f7f9d0c 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -107,6 +107,7 @@ struct decoder_owner_sys_t
     bool b_waiting;
     bool b_first;
     bool b_has_data;
+    mtime_t wait_deadline;
 
     /* Flushing */
     bool flushing;
@@ -619,6 +620,23 @@ static void DecoderWaitUnblock( decoder_t *p_dec )
     }
 }
 
+/* DecoderTimedWait: Interruptible wait
+ * Returns VLC_SUCCESS if wait was not interrupted, and VLC_EGENERIC otherwise */
+static int DecoderTimedWait( decoder_t *p_dec, mtime_t deadline )
+{
+    decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+    vlc_assert_locked( &p_owner->lock );
+    p_owner->wait_deadline = deadline;
+
+    int ret = 0;
+    while( p_owner->wait_deadline > 0 && ret != ETIMEDOUT )
+        ret = vlc_cond_timedwait( &p_owner->wait_request, &p_owner->lock,
+                                  p_owner->wait_deadline );
+
+    return ret == ETIMEDOUT ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
 static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
 {
     if( p->i_flags & (BLOCK_FLAG_PREROLL|BLOCK_FLAG_DISCONTINUITY) )
@@ -1016,21 +1034,21 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
     DecoderWaitUnblock( p_dec );
     DecoderFixTs( p_dec, &p_audio->i_pts, NULL, &p_audio->i_length,
                   &i_rate, AOUT_MAX_ADVANCE_TIME );
-    vlc_mutex_unlock( &p_owner->lock );
 
     audio_output_t *p_aout = p_owner->p_aout;
 
     if( p_aout == NULL || p_audio->i_pts <= VLC_TS_INVALID
      || i_rate < INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE
-     || i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE )
+     || i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE
+     || DecoderTimedWait( p_dec, p_audio->i_pts - AOUT_MAX_PREPARE_TIME ) )
     {
+        vlc_mutex_unlock( &p_owner->lock );
         msg_Dbg( p_dec, "discarded audio buffer" );
         *pi_lost_sum += 1;
         block_Release( p_audio );
         return;
     }
-
-    mwait( p_audio->i_pts - AOUT_MAX_PREPARE_TIME );
+    vlc_mutex_unlock( &p_owner->lock );
 
     if( aout_DecPlay( p_aout, p_audio, i_rate ) == 0 )
         *pi_played_sum += 1;
@@ -1154,15 +1172,16 @@ static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic )
     DecoderWaitUnblock( p_dec );
     DecoderFixTs( p_dec, &p_subpic->i_start, &p_subpic->i_stop, NULL,
                   NULL, INT64_MAX );
-    vlc_mutex_unlock( &p_owner->lock );
 
-    if( p_subpic->i_start <= VLC_TS_INVALID )
+    if( p_subpic->i_start <= VLC_TS_INVALID
+     || DecoderTimedWait( p_dec, p_subpic->i_start - SPU_MAX_PREPARE_TIME ) )
     {
+        vlc_mutex_unlock( &p_owner->lock );
         subpicture_Delete( p_subpic );
         return;
     }
+    vlc_mutex_unlock( &p_owner->lock );
 
-    mwait( p_subpic->i_start - SPU_MAX_PREPARE_TIME );
     vout_PutSubpicture( p_vout, p_subpic );
 }
 
@@ -1483,6 +1502,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     p_owner->b_draining = false;
     atomic_init( &p_owner->drained, false );
     p_owner->b_idle = false;
+    p_owner->wait_deadline = 0;
 
     es_format_Init( &p_owner->fmt, UNKNOWN_ES, 0 );
 
@@ -1760,6 +1780,7 @@ void input_DecoderDelete( decoder_t *p_dec )
     /* Make sure we aren't waiting/decoding anymore */
     vlc_mutex_lock( &p_owner->lock );
     p_owner->b_waiting = false;
+    p_owner->wait_deadline = 0;
     vlc_cond_signal( &p_owner->wait_request );
 
     /* If the video output is paused or too slow, the decoded picture FIFO may
@@ -1891,6 +1912,11 @@ void input_DecoderFlush( decoder_t *p_dec )
     vlc_fifo_Signal( p_owner->p_fifo );
 
     vlc_fifo_Unlock( p_owner->p_fifo );
+
+    vlc_mutex_lock( &p_owner->lock );
+    p_owner->wait_deadline = 0;
+    vlc_cond_signal( &p_owner->wait_request );
+    vlc_mutex_unlock( &p_owner->lock );
 }
 
 void input_DecoderIsCcPresent( decoder_t *p_dec, bool pb_present[4] )
-- 
2.1.4



More information about the vlc-devel mailing list