[vlc-devel] [WIP/PATCH v2] Audio decoder: output buffered decoded frames on EOF

Rafaël Carré funman at videolan.org
Wed Oct 16 20:15:49 CEST 2013


If EOF happens during buffering, the buffered frames will be flushed
and never played back.
This should only be visible for very short files such as:
http://streams.videolan.org/issues/9195/73ms-VLC-KO.wav

Note, pulse will lose the audio for such short files, alsa and afile work better

Closes: #3152
---
v2: fix a crash on EOF when there's no buffered audio anymore
 src/input/decoder.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/src/input/decoder.c b/src/input/decoder.c
index b7e2ff9..020c0e9 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -63,7 +63,7 @@ static void       DecoderProcess( decoder_t *, block_t * );
 static void       DecoderError( decoder_t *p_dec, block_t *p_block );
 static void       DecoderOutputChangePause( decoder_t *, bool b_paused, mtime_t i_date );
 static void       DecoderFlush( decoder_t * );
-static void       DecoderSignalBuffering( decoder_t *, bool );
+static void       DecoderSignalBuffering( decoder_t * );
 static void       DecoderFlushBuffering( decoder_t * );
 
 static void       DecoderUnsupportedCodec( decoder_t *, vlc_fourcc_t );
@@ -422,6 +422,9 @@ bool input_DecoderIsEmpty( decoder_t * p_dec )
     assert( !p_owner->b_buffering );
 
     bool b_empty = block_FifoCount( p_dec->p_owner->p_fifo ) <= 0;
+    if (p_owner->buffer.i_count) /* buffered frames */
+        b_empty = false;
+
     if( b_empty )
     {
         vlc_mutex_lock( &p_owner->lock );
@@ -923,7 +926,11 @@ static void *DecoderThread( void *p_data )
 
         /* Make sure there is no cancellation point other than this one^^.
          * If you need one, be sure to push cleanup of p_block. */
-        DecoderSignalBuffering( p_dec, p_block == NULL );
+        if (p_block == NULL || p_block->i_flags & BLOCK_FLAG_CORE_EOS) {
+            /* Stop buffering if we're at end of stream */
+            DecoderSignalBuffering( p_dec );
+            input_DecoderStopBuffering( p_dec );
+        }
 
         if( p_block )
         {
@@ -986,7 +993,7 @@ static void DecoderFlush( decoder_t *p_dec )
         vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
 }
 
-static void DecoderSignalBuffering( decoder_t *p_dec, bool b_full )
+static void DecoderSignalBuffering( decoder_t *p_dec )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
 
@@ -994,8 +1001,7 @@ static void DecoderSignalBuffering( decoder_t *p_dec, bool b_full )
 
     if( p_owner->b_buffering )
     {
-        if( b_full )
-            p_owner->buffer.b_full = true;
+        p_owner->buffer.b_full = true;
         vlc_cond_signal( &p_owner->wait_acknowledge );
     }
 
@@ -1164,7 +1170,7 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
     audio_output_t *p_aout = p_owner->p_aout;
 
     /* */
-    if( p_audio->i_pts <= VLC_TS_INVALID ) // FIXME --VLC_TS_INVALID verify audio_output/*
+    if( p_audio && p_audio->i_pts <= VLC_TS_INVALID ) // FIXME --VLC_TS_INVALID verify audio_output/*
     {
         msg_Warn( p_dec, "non-dated audio buffer received" );
         *pi_lost_sum += 1;
@@ -1175,7 +1181,7 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
     /* */
     vlc_mutex_lock( &p_owner->lock );
 
-    if( p_owner->b_buffering || p_owner->buffer.p_audio )
+    if( p_audio && (p_owner->b_buffering || p_owner->buffer.p_audio) )
     {
         p_audio->p_next = NULL;
 
@@ -1214,6 +1220,9 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
                 p_owner->buffer.pp_audio_next = &p_owner->buffer.p_audio;
         }
 
+        if (!p_audio)
+            break;
+
         /* */
         int i_rate = INPUT_RATE_DEFAULT;
 
@@ -1263,7 +1272,11 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
     int i_lost = 0;
     int i_played = 0;
 
-    while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
+    if (!p_block) {
+        /* Play a NULL block to output buffered frames */
+        DecoderPlayAudio( p_dec, NULL, &i_played, &i_lost );
+    }
+    else while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
     {
         if( DecoderIsExitRequested( p_dec ) )
         {
@@ -1889,7 +1902,7 @@ static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block, bool b_flus
                 DecoderDecodeAudio( p_dec, p_null );
         }
     }
-    else if( p_block )
+    else
     {
         DecoderDecodeAudio( p_dec, p_block );
     }
@@ -2411,7 +2424,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
             return NULL;
 
         /* */
-        DecoderSignalBuffering( p_dec, true );
+        DecoderSignalBuffering( p_dec );
 
         /* Check the decoder doesn't leak pictures */
         vout_FixLeaks( p_owner->p_vout );
-- 
1.8.3.2




More information about the vlc-devel mailing list