---
Well, I hate to do this... but I found a weird situation where my 
previous patch did not work. Some audio decoders (e.g. shorten) buffer 
input data internally. When that happens they will consume all input 
data but sometimes not output any frames. With the previous patch this 
made it look like the decoder was done decoding when it really was not. 
The updated patch checks that the packet that was sent was really empty.

There are not any audio codecs that do this and also set 
CODEC_CAP_DELAY, but there will be after I send some patches later to 
make the shorten decoder flush its internal buffer, making it actually 
lossless. Right now it sometimes cuts off samples at the end.

 avplay.c |   29 +++++++++++++++++++++++------
 1 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/avplay.c b/avplay.c
index 198dce1..b95cba7 100644
--- a/avplay.c
+++ b/avplay.c
@@ -2008,10 +2008,15 @@ static int audio_decode_frame(VideoState *is, double 
*pts_ptr)
     AVCodecContext *dec= is->audio_st->codec;
     int n, len1, data_size;
     double pts;
+    int new_packet = 0;
+    int flush_complete = 0;
 
     for(;;) {
         /* NOTE: the audio packet can contain several frames */
-        while (pkt_temp->size > 0) {
+        while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) {
+            if (flush_complete)
+                break;
+            new_packet = 0;
             data_size = sizeof(is->audio_buf1);
             len1 = avcodec_decode_audio3(dec,
                                         (int16_t *)is->audio_buf1, &data_size,
@@ -2024,8 +2029,13 @@ static int audio_decode_frame(VideoState *is, double 
*pts_ptr)
 
             pkt_temp->data += len1;
             pkt_temp->size -= len1;
-            if (data_size <= 0)
+
+            if (data_size <= 0) {
+                /* stop sending empty packets if the decoder is finished */
+                if (!pkt_temp->data && dec->codec->capabilities & 
CODEC_CAP_DELAY)
+                    flush_complete = 1;
                 continue;
+            }
 
             if (dec->sample_fmt != is->audio_src_fmt) {
                 if (is->reformat_ctx)
@@ -2086,12 +2096,11 @@ static int audio_decode_frame(VideoState *is, double 
*pts_ptr)
         }
 
         /* read next packet */
-        if (packet_queue_get(&is->audioq, pkt, 1) < 0)
+        if ((new_packet = packet_queue_get(&is->audioq, pkt, 1)) < 0)
             return -1;
-        if(pkt->data == flush_pkt.data){
+
+        if (pkt->data == flush_pkt.data)
             avcodec_flush_buffers(dec);
-            continue;
-        }
 
         pkt_temp->data = pkt->data;
         pkt_temp->size = pkt->size;
@@ -2508,6 +2517,14 @@ static int decode_thread(void *arg)
                 pkt->stream_index= is->video_stream;
                 packet_queue_put(&is->videoq, pkt);
             }
+            if (is->audio_stream >= 0 &&
+                is->audio_st->codec->codec->capabilities & CODEC_CAP_DELAY) {
+                av_init_packet(pkt);
+                pkt->data = NULL;
+                pkt->size = 0;
+                pkt->stream_index = is->audio_stream;
+                packet_queue_put(&is->audioq, pkt);
+            }
             SDL_Delay(10);
             if(is->audioq.size + is->videoq.size + is->subtitleq.size ==0){
                 if(loop!=1 && (!loop || --loop)){
-- 
1.7.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to