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

Thomas Guillem thomas at gllm.fr
Tue Dec 1 11:43:52 CET 2015


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

This fixes a too long closing/flushing time when the next spu or audio block is
too distant.
---
 src/input/decoder.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/src/input/decoder.c b/src/input/decoder.c
index c4fb6a1..aa36aec 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -30,6 +30,7 @@
 # include "config.h"
 #endif
 #include <assert.h>
+#include <errno.h>
 
 #include <vlc_common.h>
 
@@ -91,6 +92,7 @@ struct decoder_owner_sys_t
     vlc_cond_t  wait_request;
     vlc_cond_t  wait_acknowledge;
     vlc_cond_t  wait_fifo; /* TODO: merge with wait_acknowledge */
+    vlc_cond_t  wait_timed;
 
     /* -- These variables need locking on write(only) -- */
     audio_output_t *p_aout;
@@ -619,6 +621,25 @@ 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;
+
+    if (deadline - mdate() <= 0)
+        return VLC_SUCCESS;
+
+    vlc_fifo_Lock( p_owner->p_fifo );
+    int ret = 0;
+    while( !p_owner->flushing && ret != ETIMEDOUT )
+        ret = vlc_fifo_TimedWaitCond( p_owner->p_fifo, &p_owner->wait_timed,
+                                      deadline );
+    vlc_fifo_Unlock( p_owner->p_fifo );
+
+    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) )
@@ -1022,7 +1043,8 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
 
     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 ) )
     {
         msg_Dbg( p_dec, "discarded audio buffer" );
         *pi_lost_sum += 1;
@@ -1030,8 +1052,6 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
         return;
     }
 
-    mwait( p_audio->i_pts - AOUT_MAX_PREPARE_TIME );
-
     if( aout_DecPlay( p_aout, p_audio, i_rate ) == 0 )
         *pi_played_sum += 1;
 
@@ -1156,13 +1176,13 @@ static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic )
                   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 ) )
     {
         subpicture_Delete( p_subpic );
         return;
     }
 
-    mwait( p_subpic->i_start - SPU_MAX_PREPARE_TIME );
     vout_PutSubpicture( p_vout, p_subpic );
 }
 
@@ -1499,6 +1519,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     vlc_cond_init( &p_owner->wait_request );
     vlc_cond_init( &p_owner->wait_acknowledge );
     vlc_cond_init( &p_owner->wait_fifo );
+    vlc_cond_init( &p_owner->wait_timed );
 
     /* Set buffers allocation callbacks for the decoders */
     p_dec->pf_aout_format_update = aout_update_format;
@@ -1642,6 +1663,7 @@ static void DeleteDecoder( decoder_t * p_dec )
         vlc_object_release( p_owner->p_packetizer );
     }
 
+    vlc_cond_destroy( &p_owner->wait_timed );
     vlc_cond_destroy( &p_owner->wait_fifo );
     vlc_cond_destroy( &p_owner->wait_acknowledge );
     vlc_cond_destroy( &p_owner->wait_request );
@@ -1757,6 +1779,12 @@ void input_DecoderDelete( decoder_t *p_dec )
 
     vlc_cancel( p_owner->thread );
 
+    vlc_fifo_Lock( p_owner->p_fifo );
+    /* Signal DecoderTimedWait */
+    p_owner->flushing = true;
+    vlc_cond_signal( &p_owner->wait_timed );
+    vlc_fifo_Unlock( p_owner->p_fifo );
+
     /* Make sure we aren't waiting/decoding anymore */
     vlc_mutex_lock( &p_owner->lock );
     p_owner->b_waiting = false;
@@ -1891,6 +1919,7 @@ void input_DecoderFlush( decoder_t *p_dec )
         p_owner->frames_countdown++;
 
     vlc_fifo_Signal( p_owner->p_fifo );
+    vlc_cond_signal( &p_owner->wait_timed );
 
     vlc_fifo_Unlock( p_owner->p_fifo );
 }
-- 
2.1.4



More information about the vlc-devel mailing list