]> git.sesse.net Git - vlc/blobdiff - src/input/decoder.c
es_out: do not start buffering when already buferring
[vlc] / src / input / decoder.c
index 451024bc6fe095cf12762b1484ad6c2f108aa62e..062a111b6520aa1d6cc7d5573b5905e4eeb09b8e 100644 (file)
@@ -61,7 +61,7 @@ static void       DeleteDecoder( decoder_t * );
 static void      *DecoderThread( void * );
 static void       DecoderProcess( decoder_t *, block_t * );
 static void       DecoderFlush( decoder_t * );
-static void       DecoderSignalWait( decoder_t *, bool );
+static void       DecoderSignalWait( decoder_t * );
 
 static void       DecoderUnsupportedCodec( decoder_t *, vlc_fourcc_t );
 
@@ -125,6 +125,7 @@ struct decoder_owner_sys_t
     } pause;
 
     /* Waiting */
+    bool b_woken;
     bool b_waiting;
     bool b_first;
     bool b_has_data;
@@ -346,29 +347,30 @@ 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;
 
-    if( b_do_pace )
-    {
-        /* The fifo is not consumed when waiting and so will
-         * deadlock vlc.
-         * There is no need to lock as b_waiting is never modified
-         * inside decoder thread. */
-        if( !p_owner->b_waiting )
-            block_FifoPace( p_owner->p_fifo, 10, SIZE_MAX );
-    }
-#ifdef __arm__
-    else if( block_FifoSize( p_owner->p_fifo ) > 50*1024*1024 /* 50 MiB */ )
-#else
-    else if( block_FifoSize( p_owner->p_fifo ) > 400*1024*1024 /* 400 MiB, ie ~ 50mb/s for 60s */ )
-#endif
+    vlc_fifo_Lock( p_owner->p_fifo );
+    if( !b_do_pace )
     {
         /* FIXME: ideally we would check the time amount of data
          * in the FIFO instead of its size. */
-        msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
-                  "consumed quickly enough), resetting fifo!" );
-        block_FifoEmpty( p_owner->p_fifo );
+        /* 400 MiB, i.e. ~ 50mb/s for 60s */
+        if( vlc_fifo_GetBytes( p_owner->p_fifo ) > 400*1024*1024 )
+        {
+            msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
+                      "consumed quickly enough), resetting fifo!" );
+            block_ChainRelease( vlc_fifo_DequeueAllUnlocked( 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_acknowledge );
     }
 
-    block_FifoPut( p_owner->p_fifo, p_block );
+    vlc_fifo_QueueUnlocked( p_owner->p_fifo, p_block );
+    vlc_fifo_Unlock( p_owner->p_fifo );
 }
 
 bool input_DecoderIsEmpty( decoder_t * p_dec )
@@ -382,9 +384,9 @@ bool input_DecoderIsEmpty( decoder_t * p_dec )
     {
         vlc_mutex_lock( &p_owner->lock );
         /* TODO subtitles support */
-        if( p_dec->fmt_out.i_cat == VIDEO_ES && p_owner->p_vout )
+        if( p_owner->fmt.i_cat == VIDEO_ES && p_owner->p_vout )
             b_empty = vout_IsEmpty( p_owner->p_vout );
-        else if( p_dec->fmt_out.i_cat == AUDIO_ES && p_owner->p_aout )
+        else if( p_owner->fmt.i_cat == AUDIO_ES && p_owner->p_aout )
             b_empty = aout_DecIsEmpty( p_owner->p_aout );
         vlc_mutex_unlock( &p_owner->lock );
     }
@@ -512,21 +514,30 @@ void input_DecoderChangeDelay( decoder_t *p_dec, mtime_t i_delay )
     vlc_mutex_unlock( &p_owner->lock );
 }
 
-void input_DecoderStartWait( decoder_t *p_dec )
+/**
+ * Requests that the decoder immediately discard all pending buffers.
+ * This is useful at end of stream, 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_mutex_lock( &p_owner->lock );
-
     DecoderFlush( p_dec );
+    vlc_mutex_unlock( &p_owner->lock );
+}
+
+void input_DecoderStartWait( decoder_t *p_dec )
+{
+    decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+    assert( !p_owner->b_waiting );
 
+    vlc_mutex_lock( &p_owner->lock );
     p_owner->b_first = true;
     p_owner->b_has_data = false;
-
     p_owner->b_waiting = true;
-
     vlc_cond_signal( &p_owner->wait_request );
-
     vlc_mutex_unlock( &p_owner->lock );
 }
 
@@ -534,12 +545,11 @@ void input_DecoderStopWait( decoder_t *p_dec )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
 
-    vlc_mutex_lock( &p_owner->lock );
+    assert( p_owner->b_waiting );
 
+    vlc_mutex_lock( &p_owner->lock );
     p_owner->b_waiting = false;
-
     vlc_cond_signal( &p_owner->wait_request );
-
     vlc_mutex_unlock( &p_owner->lock );
 }
 
@@ -547,14 +557,17 @@ void input_DecoderWait( decoder_t *p_dec )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
 
-    vlc_mutex_lock( &p_owner->lock );
+    assert( p_owner->b_waiting );
 
-    while( p_owner->b_waiting && !p_owner->b_has_data )
+    vlc_mutex_lock( &p_owner->lock );
+    while( !p_owner->b_has_data )
     {
-        block_FifoWake( p_owner->p_fifo );
+        vlc_fifo_Lock( p_owner->p_fifo );
+        p_owner->b_woken = true;
+        vlc_fifo_Signal( p_owner->p_fifo );
+        vlc_fifo_Unlock( p_owner->p_fifo );
         vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
     }
-
     vlc_mutex_unlock( &p_owner->lock );
 }
 
@@ -577,6 +590,7 @@ void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
     else
     {
         /* TODO subtitle should not be flushed */
+        p_owner->b_waiting = false;
         DecoderFlush( p_dec );
     }
     vlc_mutex_unlock( &p_owner->lock );
@@ -751,6 +765,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     es_format_Init( &p_owner->fmt, UNKNOWN_ES, 0 );
 
     /* decoder fifo */
+    p_owner->b_woken = false;
     p_owner->p_fifo = block_FifoNew();
     if( unlikely(p_owner->p_fifo == NULL) )
     {
@@ -872,14 +887,29 @@ static void *DecoderThread( void *p_data )
     /* The decoder's main loop */
     for( ;; )
     {
-        block_t *p_block = block_FifoGet( p_owner->p_fifo );
+        block_t *p_block;
+
+        vlc_fifo_Lock( p_owner->p_fifo );
+        vlc_fifo_CleanupPush( p_owner->p_fifo );
 
-        /* Make sure there is no cancellation point other than this one^^.
-         * If you need one, be sure to push cleanup of p_block. */
-        bool end_wait = !p_block || p_block->i_flags & BLOCK_FLAG_CORE_EOS;
-        DecoderSignalWait( p_dec, end_wait );
-        if (end_wait)
-            input_DecoderStopWait( p_dec );
+        while( vlc_fifo_IsEmpty( p_owner->p_fifo ) )
+        {
+            if( p_owner->b_woken )
+                break;
+            vlc_fifo_Wait( p_owner->p_fifo );
+            /* Make sure there is no cancellation point other than this one^^.
+             * If you need one, be sure to push cleanup of p_block. */
+        }
+
+        p_block = vlc_fifo_DequeueUnlocked( p_owner->p_fifo );
+        if( p_block != NULL )
+            vlc_cond_signal( &p_owner->wait_acknowledge );
+
+        p_owner->b_woken = false;
+        vlc_cleanup_run();
+
+        if( p_block == NULL || p_block->i_flags & BLOCK_FLAG_CORE_EOS )
+            DecoderSignalWait( p_dec );
 
         if( p_block )
         {
@@ -924,7 +954,6 @@ static void DecoderFlush( decoder_t *p_dec )
     /* Empty the fifo */
     block_FifoEmpty( p_owner->p_fifo );
 
-    p_owner->b_waiting = false;
     /* Monitor for flush end */
     p_owner->b_flushing = true;
     vlc_cond_signal( &p_owner->wait_request );
@@ -940,7 +969,7 @@ static void DecoderFlush( decoder_t *p_dec )
         vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
 }
 
-static void DecoderSignalWait( decoder_t *p_dec, bool b_has_data )
+static void DecoderSignalWait( decoder_t *p_dec )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
 
@@ -948,8 +977,7 @@ static void DecoderSignalWait( decoder_t *p_dec, bool b_has_data )
 
     if( p_owner->b_waiting )
     {
-        if( b_has_data )
-            p_owner->b_has_data = true;
+        p_owner->b_has_data = true;
         vlc_cond_signal( &p_owner->wait_acknowledge );
     }
 
@@ -1808,7 +1836,6 @@ static void DeleteDecoder( decoder_t * p_dec )
              (unsigned)block_FifoCount( p_owner->p_fifo ) );
 
     /* Free all packets still in the decoder fifo. */
-    block_FifoEmpty( p_owner->p_fifo );
     block_FifoRelease( p_owner->p_fifo );
 
     /* Cleanup */
@@ -2156,7 +2183,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
             return NULL;
 
         /* */
-        DecoderSignalWait( p_dec, true );
+        DecoderSignalWait( p_dec );
 
         /* Check the decoder doesn't leak pictures */
         vout_FixLeaks( p_owner->p_vout );
@@ -2176,7 +2203,8 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
 
     while( i_attempts-- )
     {
-        if( DecoderIsExitRequested( p_dec ) || p_dec->b_error )
+        if( DecoderIsExitRequested( p_dec ) || DecoderIsFlushing( p_dec )
+         || p_dec->b_error )
             break;
 
         p_vout = input_resource_HoldVout( p_owner->p_resource );