[vlc-commits] decoder: handle flush "before" pause/resume
Rémi Denis-Courmont
git at videolan.org
Sat Nov 7 12:56:48 CET 2015
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Nov 7 13:16:34 2015 +0200| [e925a9e241c79290983c612c2d0016638a20f049] | committer: Rémi Denis-Courmont
decoder: handle flush "before" pause/resume
This restores the ability to flush the decoder while it is paused.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=e925a9e241c79290983c612c2d0016638a20f049
---
src/input/decoder.c | 77 +++++++++++++++++++++++++++++++--------------------
1 file changed, 47 insertions(+), 30 deletions(-)
diff --git a/src/input/decoder.c b/src/input/decoder.c
index 339da52..8206dee 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -108,6 +108,8 @@ struct decoder_owner_sys_t
bool b_has_data;
/* Flushing */
+ bool flushing;
+ bool flushed;
bool b_flushing;
bool b_draining;
bool b_drained;
@@ -1430,6 +1432,36 @@ static void *DecoderThread( void *p_data )
for( ;; )
{
+ if( p_owner->flushing )
+ { /* Flush before/regardless of pause. We do not want to resume just
+ * for the sake of flushing (glitches could otherwise happen). */
+ int canc = vlc_savecancel();
+
+ /* TODO: add a flush callback to decoder, do not depend on an
+ * allocated block */
+ block_t *dummy = DecoderBlockFlushNew();
+ if( unlikely(dummy == NULL) )
+ msg_Err( p_dec, "cannot flush" );
+
+ /* Owner is buggy if it queues data while flushing */
+ assert( vlc_fifo_IsEmpty( p_owner->p_fifo ) );
+ p_owner->flushing = false;
+ vlc_fifo_Unlock( p_owner->p_fifo );
+
+ /* Flush the decoder (and the output) */
+ DecoderProcess( p_dec, dummy );
+
+ vlc_fifo_Lock( p_owner->p_fifo );
+ vlc_restorecancel( canc );
+
+ /* Owner is supposed to wait for flush to complete.
+ * TODO: It might be possible to remove this restriction. */
+ assert( vlc_fifo_IsEmpty( p_owner->p_fifo ) );
+ p_owner->flushed = true;
+ vlc_cond_signal( &p_owner->wait_fifo );
+ continue;
+ }
+
if( paused != p_owner->paused )
{ /* Update playing/paused status of the output */
int canc = vlc_savecancel();
@@ -1552,6 +1584,8 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
p_owner->b_first = true;
p_owner->b_has_data = false;
+ p_owner->flushing = false;
+ p_owner->flushed = true;
p_owner->b_flushing = false;
p_owner->b_draining = false;
p_owner->b_drained = false;
@@ -1885,6 +1919,7 @@ void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace )
vlc_fifo_WaitCond( p_owner->p_fifo, &p_owner->wait_fifo );
}
+ p_owner->flushed = false;
vlc_fifo_QueueUnlocked( p_owner->p_fifo, p_block );
vlc_fifo_Unlock( p_owner->p_fifo );
}
@@ -1930,44 +1965,26 @@ void input_DecoderDrain( decoder_t *p_dec )
vlc_fifo_Unlock( p_owner->p_fifo );
}
-static void DecoderFlush( decoder_t *p_dec )
+/**
+ * Requests that the decoder immediately discard all pending buffers.
+ * This is useful when seeking or when deselecting a stream.
+ */
+void input_DecoderFlush( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- vlc_assert_locked( &p_owner->lock );
-
vlc_fifo_Lock( p_owner->p_fifo );
/* Empty the fifo */
block_ChainRelease( vlc_fifo_DequeueAllUnlocked( p_owner->p_fifo ) );
- p_owner->b_draining = false; /* flush supersedes drain */
- vlc_fifo_Unlock( p_owner->p_fifo );
-
- /* Monitor for flush end */
- p_owner->b_flushing = true;
- vlc_cond_signal( &p_owner->wait_request );
-
- /* Send a special block */
- block_t *p_null = DecoderBlockFlushNew();
- if( !p_null )
- return;
- input_DecoderDecode( p_dec, p_null, false );
+ p_owner->flushing = true;
- /* */
- while( p_owner->b_flushing )
- vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
-}
+ vlc_fifo_Signal( p_owner->p_fifo );
-/**
- * Requests that the decoder immediately discard all pending buffers.
- * This is useful when seeking or when deselecting a stream.
- */
-void input_DecoderFlush( decoder_t *p_dec )
-{
- decoder_owner_sys_t *p_owner = p_dec->p_owner;
+ /* Monitor for flush end */
+ while( !p_owner->flushed )
+ vlc_fifo_WaitCond( p_owner->p_fifo, &p_owner->wait_fifo );
- vlc_mutex_lock( &p_owner->lock );
- DecoderFlush( p_dec );
- vlc_mutex_unlock( &p_owner->lock );
+ vlc_fifo_Unlock( p_owner->p_fifo );
}
void input_DecoderIsCcPresent( decoder_t *p_dec, bool pb_present[4] )
@@ -2147,7 +2164,7 @@ void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
{
/* TODO subtitle should not be flushed */
p_owner->b_waiting = false;
- DecoderFlush( p_dec );
+ input_DecoderFlush( p_dec );
}
vlc_mutex_unlock( &p_owner->lock );
}
More information about the vlc-commits
mailing list