[vlc-devel] [PATCH 1/3] decoder: unblock input thread when interrupted
Thomas Guillem
thomas at gllm.fr
Mon Feb 12 18:13:24 CET 2018
When not paced, input_DecoderDecode() called from
(input_thread_t->demux->es_out) can wait for the DecoderThread to empty its
FIFO. This can take a very long time with inputs that need a big buffering (cf.
ACCESS/DEMUX PTS_DELAY) or if sout inputs are blocked in IO.
I also took the opportunity to unblock input_DecoderWait(), not sure if really
needed. I didn't saw any deadlock in that part but I guess it can happen too.
---
src/input/decoder.c | 56 ++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 45 insertions(+), 11 deletions(-)
diff --git a/src/input/decoder.c b/src/input/decoder.c
index 98817e6f39..8ec8ee4131 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -129,6 +129,8 @@ struct decoder_owner_sys_t
atomic_bool drained;
bool b_idle;
+ bool interrupted;
+
/* CC */
#define MAX_CC_DECODERS 64 /* The es_out only creates one type of es */
struct
@@ -1695,6 +1697,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
p_owner->drained = false;
atomic_init( &p_owner->reload, RELOAD_NO_REQUEST );
p_owner->b_idle = false;
+ p_owner->interrupted = false;
es_format_Init( &p_owner->fmt, fmt->i_cat, 0 );
@@ -2031,6 +2034,19 @@ void input_DecoderDelete( decoder_t *p_dec )
DeleteDecoder( p_dec );
}
+static void interrupted_cb(void *data)
+{
+ decoder_t *p_dec = data;
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+ vlc_fifo_Lock( p_owner->p_fifo );
+ p_owner->interrupted = true;
+ vlc_fifo_Unlock( p_owner->p_fifo );
+
+ vlc_cond_signal( &p_owner->wait_fifo );
+ vlc_cond_signal( &p_owner->wait_acknowledge );
+}
+
/**
* Put a block_t in the decoder's fifo.
* Thread-safe w.r.t. the decoder. May be a cancellation point.
@@ -2042,9 +2058,9 @@ void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- vlc_fifo_Lock( p_owner->p_fifo );
if( !b_do_pace )
{
+ vlc_fifo_Lock( p_owner->p_fifo );
/* FIXME: ideally we would check the time amount of data
* in the FIFO instead of its size. */
/* 400 MiB, i.e. ~ 50mb/s for 60s */
@@ -2055,18 +2071,31 @@ void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace )
block_ChainRelease( vlc_fifo_DequeueAllUnlocked( p_owner->p_fifo ) );
p_block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
}
+
+ vlc_fifo_QueueUnlocked( p_owner->p_fifo, p_block );
+ vlc_fifo_Unlock( p_owner->p_fifo );
}
else
- if( !p_owner->b_waiting )
- { /* The FIFO is not consumed when waiting, so pacing would deadlock VLC.
- * Locking is not necessary as b_waiting is only read, not written by
- * the decoder thread. */
- while( vlc_fifo_GetCount( p_owner->p_fifo ) >= 10 )
- vlc_fifo_WaitCond( p_owner->p_fifo, &p_owner->wait_fifo );
- }
+ {
+ vlc_interrupt_register( interrupted_cb, p_dec );
+ vlc_fifo_Lock( p_owner->p_fifo );
- vlc_fifo_QueueUnlocked( p_owner->p_fifo, p_block );
- vlc_fifo_Unlock( p_owner->p_fifo );
+ if( !p_owner->b_waiting )
+ { /* The FIFO is not consumed when waiting, so pacing would deadlock VLC.
+ * Locking is not necessary as b_waiting is only read, not written by
+ * the decoder thread. */
+ while( !p_owner->interrupted && vlc_fifo_GetCount( p_owner->p_fifo ) >= 10 )
+ vlc_fifo_WaitCond( p_owner->p_fifo, &p_owner->wait_fifo );
+ }
+
+ if( p_owner->interrupted )
+ block_Release( p_block );
+ else
+ vlc_fifo_QueueUnlocked( p_owner->p_fifo, p_block );
+
+ vlc_fifo_Unlock( p_owner->p_fifo );
+ vlc_interrupt_unregister();
+ }
}
bool input_DecoderIsEmpty( decoder_t * p_dec )
@@ -2308,6 +2337,8 @@ void input_DecoderWait( decoder_t *p_dec )
assert( p_owner->b_waiting );
+ vlc_interrupt_register(interrupted_cb, p_dec);
+
vlc_mutex_lock( &p_owner->lock );
while( !p_owner->b_has_data )
{
@@ -2316,7 +2347,8 @@ void input_DecoderWait( decoder_t *p_dec )
if( p_owner->paused )
break;
vlc_fifo_Lock( p_owner->p_fifo );
- if( p_owner->b_idle && vlc_fifo_IsEmpty( p_owner->p_fifo ) )
+ if( p_owner->interrupted
+ || ( p_owner->b_idle && vlc_fifo_IsEmpty( p_owner->p_fifo ) ) )
{
msg_Err( p_dec, "buffer deadlock prevented" );
vlc_fifo_Unlock( p_owner->p_fifo );
@@ -2326,6 +2358,8 @@ void input_DecoderWait( decoder_t *p_dec )
vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
}
vlc_mutex_unlock( &p_owner->lock );
+
+ vlc_interrupt_unregister();
}
void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
--
2.11.0
More information about the vlc-devel
mailing list