[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