[FFmpeg-devel] avcodec/decode: Fix missing PTS/DTS for decoders like wmapro

Submitted by fumoboy007 on July 14, 2019, 10:40 p.m.

Details

Message ID 20190714224035.39526-1-fumoboy007@me.com
State New
Headers show

Commit Message

fumoboy007 July 14, 2019, 10:40 p.m.
From: fumoboy007 <fumoboy007@me.com>

Added back comment (deleted in 061a0c14bb5767bca72e3a7227ca400de439ba09) explaining that some audio decoders like wmapro may consume partial data without returning a frame.

For these cases, `decode_simple_internal` will be called several times before the frame is complete. Due to a bug that this commit fixes, the PTS/DTS that was set on the first call would be reset to AV_NOPTS_VALUE on the subsequent calls.
---
 libavcodec/decode.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

Comments

Michael Niedermayer July 16, 2019, 8:40 p.m.
On Sun, Jul 14, 2019 at 06:40:35PM -0400, fumoboy007@me.com wrote:
> From: fumoboy007 <fumoboy007@me.com>
> 
> Added back comment (deleted in 061a0c14bb5767bca72e3a7227ca400de439ba09) explaining that some audio decoders like wmapro may consume partial data without returning a frame.
> 
> For these cases, `decode_simple_internal` will be called several times before the frame is complete. Due to a bug that this commit fixes, the PTS/DTS that was set on the first call would be reset to AV_NOPTS_VALUE on the subsequent calls.
> ---
>  libavcodec/decode.c | 23 ++++++++++++++++++-----
>  1 file changed, 18 insertions(+), 5 deletions(-)

this breaks fate-flcl1905

[...]

Patch hide | download patch | download mbox

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 6c31166ec2..c4722fa09b 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -603,16 +603,25 @@  FF_ENABLE_DEPRECATION_WARNINGS
 
     if (ret >= pkt->size || ret < 0) {
         av_packet_unref(pkt);
+        avci->last_pkt_props->pts = AV_NOPTS_VALUE;
+        avci->last_pkt_props->dts = AV_NOPTS_VALUE;
     } else {
         int consumed = ret;
-
         pkt->data                += consumed;
         pkt->size                -= consumed;
         avci->last_pkt_props->size -= consumed; // See extract_packet_props() comment.
-        pkt->pts                  = AV_NOPTS_VALUE;
-        pkt->dts                  = AV_NOPTS_VALUE;
-        avci->last_pkt_props->pts = AV_NOPTS_VALUE;
-        avci->last_pkt_props->dts = AV_NOPTS_VALUE;
+
+        if (got_frame) {
+            // TODO: Do the same for video and subtitles before introducing decoders of those types
+            // that have AV_CODEC_CAP_SUBFRAMES set. (We need a robust way to get the duration of a
+            // video or subtitle frame before we can do this.)
+            if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
+                int64_t frame_duration = av_rescale_q(frame->nb_samples,
+                                                      (AVRational){1, avctx->sample_rate},
+                                                      avctx->pkt_timebase);
+                avci->last_pkt_props->pts += frame_duration;
+            }
+        }
     }
 
     if (got_frame)
@@ -625,6 +634,10 @@  static int decode_simple_receive_frame(AVCodecContext *avctx, AVFrame *frame)
 {
     int ret;
 
+    // Some audio decoders may consume partial data without returning
+    // a frame (e.g. wmapro). There is no way to make the caller call
+    // avcodec_receive_frame() again without returning a frame, so try
+    // to decode more in these cases.
     while (!frame->buf[0]) {
         ret = decode_simple_internal(avctx, frame);
         if (ret < 0)