[FFmpeg-devel] [PATCH] lavc/hevcdec: set output frame pkt_dts

Anton Khirnov anton at khirnov.net
Wed Sep 11 17:41:00 EEST 2024


pkt_dts needs to be set manually when using the receive_frame() callback, so
it was unset after 2fdecbb239714b6203e37067fda2521f80e19d47.

Fixes PTS guessing for certain files with broken timestamps. Cf.
https://github.com/mpv-player/mpv/issues/14806

Reported-by: llyyr <llyyr.public at gmail.com>
---
 libavcodec/hevc/hevcdec.c |  4 ++++
 libavcodec/hevc/hevcdec.h |  3 +++
 libavcodec/hevc/refs.c    | 10 ++++++----
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index c8c425fd71..d67730418b 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -3444,6 +3444,8 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
     uint8_t *sd;
     size_t sd_size;
 
+    s->pkt_dts = AV_NOPTS_VALUE;
+
     if (ff_container_fifo_can_read(s->output_fifo))
         goto do_output;
 
@@ -3457,6 +3459,8 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
     } else if (ret < 0)
         return ret;
 
+    s->pkt_dts = avpkt->dts;
+
     sd = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &sd_size);
     if (sd && sd_size > 0) {
         ret = hevc_decode_extradata(s, sd, sd_size, 0);
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index e43f2d0201..e3194fd87e 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -545,6 +545,9 @@ typedef struct HEVCContext {
 
     int film_grain_warning_shown;
 
+    // dts of the packet currently being decoded
+    int64_t pkt_dts;
+
     AVBufferRef *rpu_buf;       ///< 0 or 1 Dolby Vision RPUs.
     DOVIContext dovi_ctx;       ///< Dolby Vision decoding context
 } HEVCContext;
diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
index 09d759f936..20fdbb5794 100644
--- a/libavcodec/hevc/refs.c
+++ b/libavcodec/hevc/refs.c
@@ -182,7 +182,7 @@ int ff_hevc_output_frames(HEVCContext *s, HEVCLayerContext *l,
         int nb_dpb    = 0;
         int nb_output = 0;
         int min_poc   = INT_MAX;
-        int i, min_idx, ret;
+        int i, min_idx, ret = 0;
 
         for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
             HEVCFrame *frame = &l->DPB[i];
@@ -199,10 +199,12 @@ int ff_hevc_output_frames(HEVCContext *s, HEVCLayerContext *l,
         if (nb_output > max_output ||
             (nb_output && nb_dpb > max_dpb)) {
             HEVCFrame *frame = &l->DPB[min_idx];
+            AVFrame *f = frame->needs_fg ? frame->frame_grain : frame->f;
 
-            ret = discard ? 0 :
-                  ff_container_fifo_write(s->output_fifo,
-                                          frame->needs_fg ? frame->frame_grain : frame->f);
+            if (!discard) {
+                f->pkt_dts = s->pkt_dts;
+                ret = ff_container_fifo_write(s->output_fifo, f);
+            }
             ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT);
             if (ret < 0)
                 return ret;
-- 
2.43.0



More information about the ffmpeg-devel mailing list