[vlc-devel] [RFC PATCH 2/2] decoder: interruptible mwait
Thomas Guillem
thomas at gllm.fr
Mon Nov 30 18:00:48 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 | 34 +++++++++++++++++++++++++++++-----
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/src/input/decoder.c b/src/input/decoder.c
index 0f08198..314b00f 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>
@@ -107,6 +108,7 @@ struct decoder_owner_sys_t
bool b_waiting;
bool b_first;
bool b_has_data;
+ bool b_abort_timedwait;
/* Flushing */
bool flushing;
@@ -619,6 +621,21 @@ 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_fifo_Lock( p_owner->p_fifo );
+ int ret = 0;
+ while( !p_owner->b_abort_timedwait && ret != ETIMEDOUT )
+ ret = vlc_fifo_TimedWait( p_owner->p_fifo, 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 +1039,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 +1048,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 +1172,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 );
}
@@ -1351,6 +1367,7 @@ static void *DecoderThread( void *p_data )
* is called again. This will avoid a second useless flush (but
* harmless). */
p_owner->flushing = false;
+ p_owner->b_abort_timedwait = false;
continue;
}
@@ -1483,6 +1500,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->b_abort_timedwait = false;
es_format_Init( &p_owner->fmt, UNKNOWN_ES, 0 );
@@ -1757,6 +1775,11 @@ void input_DecoderDelete( decoder_t *p_dec )
vlc_cancel( p_owner->thread );
+ vlc_fifo_Lock( p_owner->p_fifo );
+ p_owner->b_abort_timedwait = true;
+ vlc_fifo_Signal( p_owner->p_fifo );
+ 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;
@@ -1881,6 +1904,7 @@ void input_DecoderFlush( decoder_t *p_dec )
* dequeued by DecoderThread and there is no need to flush a second time in
* a row. */
p_owner->flushing = true;
+ p_owner->b_abort_timedwait = true;
/* Flushing video decoder when paused: increment frames_countdown in order
* to display one frame */
--
2.1.4
More information about the vlc-devel
mailing list