]> git.sesse.net Git - vlc/blobdiff - src/input/decoder.c
decoder: merge b_exit into b_flushing
[vlc] / src / input / decoder.c
index 7831647ac4e2efce21ff5c6a12a273b3580bc32f..d01b2576cef603658859cf7ba16673b789573219 100644 (file)
@@ -114,8 +114,6 @@ struct decoder_owner_sys_t
     vout_thread_t   *p_vout;
 
     /* -- Theses variables need locking on read *and* write -- */
-    bool b_exit;
-
     /* Pause */
     bool b_paused;
     struct
@@ -316,7 +314,6 @@ void input_DecoderDelete( decoder_t *p_dec )
     p_owner->b_paused = false;
     p_owner->b_waiting = false;
     p_owner->b_flushing = true;
-    p_owner->b_exit = true;
     vlc_cond_signal( &p_owner->wait_request );
     vlc_mutex_unlock( &p_owner->lock );
 
@@ -347,25 +344,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 );
-    }
-    else if( block_FifoSize( p_owner->p_fifo ) > 400*1024*1024 /* 400 MiB, ie ~ 50mb/s for 60s */ )
+    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 )
@@ -486,12 +488,12 @@ void input_DecoderChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date )
          * - for sout it is useless
          * - for subs, it is done by the vout
          */
-        if( p_dec->fmt_out.i_cat == AUDIO_ES )
+        if( p_owner->fmt.i_cat == AUDIO_ES )
         {
             if( p_owner->p_aout )
                 aout_DecChangePause( p_owner->p_aout, b_paused, i_date );
         }
-        else if( p_dec->fmt_out.i_cat == VIDEO_ES )
+        else if( p_owner->fmt.i_cat == VIDEO_ES )
         {
             if( p_owner->p_vout )
                 vout_ChangePause( p_owner->p_vout, b_paused, i_date );
@@ -509,6 +511,19 @@ void input_DecoderChangeDelay( decoder_t *p_dec, mtime_t i_delay )
     vlc_mutex_unlock( &p_owner->lock );
 }
 
+/**
+ * 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;
@@ -516,8 +531,6 @@ void input_DecoderStartWait( decoder_t *p_dec )
     assert( !p_owner->b_waiting );
 
     vlc_mutex_lock( &p_owner->lock );
-    DecoderFlush( p_dec );
-
     p_owner->b_first = true;
     p_owner->b_has_data = false;
     p_owner->b_waiting = true;
@@ -562,7 +575,7 @@ void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
     *pi_duration = 0;
 
     vlc_mutex_lock( &p_owner->lock );
-    if( p_dec->fmt_out.i_cat == VIDEO_ES )
+    if( p_owner->fmt.i_cat == VIDEO_ES )
     {
         if( p_owner->b_paused && p_owner->p_vout )
         {
@@ -574,6 +587,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 );
@@ -826,8 +840,6 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     p_owner->b_fmt_description = false;
     p_owner->p_description = NULL;
 
-    p_owner->b_exit = false;
-
     p_owner->b_paused = false;
     p_owner->pause.i_date = VLC_TS_INVALID;
     p_owner->pause.i_ignore = 0;
@@ -885,6 +897,9 @@ static void *DecoderThread( void *p_data )
         }
 
         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();
 
@@ -934,7 +949,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 );
@@ -1067,17 +1081,6 @@ static void DecoderFixTs( decoder_t *p_dec, mtime_t *pi_ts0, mtime_t *pi_ts1,
         *pi_rate = i_rate;
 }
 
-static bool DecoderIsExitRequested( decoder_t *p_dec )
-{
-    decoder_owner_sys_t *p_owner = p_dec->p_owner;
-
-    vlc_mutex_lock( &p_owner->lock );
-    bool b_exit = p_owner->b_exit;
-    vlc_mutex_unlock( &p_owner->lock );
-
-    return b_exit;
-}
-
 /**
  * If *pb_reject, it does nothing, otherwise it waits for the given
  * deadline or a flush request (in which case it set *pi_reject to true.
@@ -1094,7 +1097,7 @@ static void DecoderWaitDate( decoder_t *p_dec,
 
     do
     {
-        if( p_owner->b_flushing || p_owner->b_exit )
+        if( p_owner->b_flushing )
         {
             *pb_reject = true;
             break;
@@ -1191,7 +1194,7 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
     }
     else while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
     {
-        if( DecoderIsExitRequested( p_dec ) )
+        if( DecoderIsFlushing( p_dec ) )
         {
             /* It prevent freezing VLC in case of broken decoder */
             block_Release( p_aout_buf );
@@ -1360,9 +1363,8 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
     while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )
     {
         vout_thread_t  *p_vout = p_owner->p_vout;
-        if( DecoderIsExitRequested( p_dec ) )
-        {
-            /* It prevent freezing VLC in case of broken decoder */
+        if( DecoderIsFlushing( p_dec ) )
+        {   /* It prevent freezing VLC in case of broken decoder */
             picture_Release( p_pic );
             if( p_block )
                 block_Release( p_block );
@@ -2153,16 +2155,13 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
 
     for( ;; )
     {
-        if( DecoderIsExitRequested( p_dec ) || p_dec->b_error )
+        if( DecoderIsFlushing( p_dec ) || p_dec->b_error )
             return NULL;
 
         picture_t *p_picture = vout_GetPicture( p_owner->p_vout );
         if( p_picture )
             return p_picture;
 
-        if( DecoderIsFlushing( p_dec ) )
-            return NULL;
-
         /* */
         DecoderSignalWait( p_dec );
 
@@ -2184,7 +2183,7 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
 
     while( i_attempts-- )
     {
-        if( DecoderIsExitRequested( p_dec ) || p_dec->b_error )
+        if( DecoderIsFlushing( p_dec ) || p_dec->b_error )
             break;
 
         p_vout = input_resource_HoldVout( p_owner->p_resource );