PR #25145 opened by JuliusBairaktaris
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25145
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25145.patch

av1dec and vp9 drop a frame that show_existing_frame outputs when the packet 
that coded it as a hidden frame carries AV_PKT_FLAG_DISCARD. MP4 edit lists and 
the trim bsf's preroll option produce such packets. libdav1d is not affected.

- `avcodec/av1dec: take the discard flag from the packet that shows a frame`
- `avcodec/vp9: take the discard flag from the packet that shows a frame` (adds 
`fate-vp9-trim-preroll`)

Not covered: Vulkan and non-AMD hwaccels; av1dec has no FATE test because it 
decodes only through a hwaccel.

AV1 1920x800 MP4 with an edit list, d3d11va and d3d12va: 2157 frames before 
(pts 1, 5 and 13 missing), 2160 after, pts and MD5 identical to libdav1d. 
`fate-vp9-trim-preroll` fails without the patch and passes with THREADS=4. 
Tested on Windows 11, RX 9070 XT, driver 32.0.31041.1004.

Written with Claude Opus 5.5 in Claude Code; `Assisted-by` trailers on the 
commits.



>From 257c805dcd41cee02db1520ce6d1a32a21dd86d0 Mon Sep 17 00:00:00 2001
From: Julius Bairaktaris <[email protected]>
Date: Mon, 28 Sep 2026 07:29:03 +0200
Subject: [PATCH 1/2] avcodec/av1dec: take the discard flag from the packet
 that shows a frame

A frame coded with show_frame=0 takes AV_FRAME_FLAG_DISCARD from the
packet that coded it. When show_existing_frame outputs it from a packet
that is not discarded, the frame is still dropped. Take the flag from
the showing packet, as is already done for pts and pkt_dts. MP4 edit
lists and the trim bsf's preroll option produce such discarded leading
packets.

Assisted-by: Claude Opus 5.5
Signed-off-by: Julius Bairaktaris <[email protected]>
---
 libavcodec/av1dec.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c
index 6e15590193..5f06dd1467 100644
--- a/libavcodec/av1dec.c
+++ b/libavcodec/av1dec.c
@@ -1171,6 +1171,10 @@ static int set_output_frame(AVCodecContext *avctx, 
AVFrame *frame)
 
     frame->pts = pkt->pts;
     frame->pkt_dts = pkt->dts;
+    if (pkt->flags & AV_PKT_FLAG_DISCARD)
+        frame->flags |= AV_FRAME_FLAG_DISCARD;
+    else
+        frame->flags &= ~AV_FRAME_FLAG_DISCARD;
 
     av_packet_unref(pkt);
 
-- 
2.54.0


>From fa9da8f584a76c26add30874362a22643fb89d35 Mon Sep 17 00:00:00 2001
From: Julius Bairaktaris <[email protected]>
Date: Mon, 28 Sep 2026 07:29:03 +0200
Subject: [PATCH 2/2] avcodec/vp9: take the discard flag from the packet that
 shows a frame

A show_existing_frame packet outputs a reference to an earlier frame,
whose AV_FRAME_FLAG_DISCARD comes from the packet that coded it. If that
packet was discarded, the shown frame is dropped too. Take the flag from
the showing packet, as is already done for pts and pkt_dts.
fate-vp9-trim-preroll covers this with the trim bsf's preroll option.

Assisted-by: Claude Opus 5.5
Signed-off-by: Julius Bairaktaris <[email protected]>
---
 libavcodec/vp9.c                |  4 ++++
 tests/fate/vpx.mak              |  3 +++
 tests/ref/fate/vp9-trim-preroll | 20 ++++++++++++++++++++
 3 files changed, 27 insertions(+)
 create mode 100644 tests/ref/fate/vp9-trim-preroll

diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
index ce4e197c9d..c20b1002c1 100644
--- a/libavcodec/vp9.c
+++ b/libavcodec/vp9.c
@@ -1649,6 +1649,10 @@ static int vp9_decode_frame(AVCodecContext *avctx, 
AVFrame *frame,
             return ret;
         frame->pts     = pkt->pts;
         frame->pkt_dts = pkt->dts;
+        if (pkt->flags & AV_PKT_FLAG_DISCARD)
+            frame->flags |= AV_FRAME_FLAG_DISCARD;
+        else
+            frame->flags &= ~AV_FRAME_FLAG_DISCARD;
         *got_frame = 1;
         return pkt->size;
     }
diff --git a/tests/fate/vpx.mak b/tests/fate/vpx.mak
index 9c52fc4898..764db4ce8b 100644
--- a/tests/fate/vpx.mak
+++ b/tests/fate/vpx.mak
@@ -141,6 +141,9 @@ FATE_VP9-$(call FRAMEMD5, IVF, VP9, SCALE_FILTER) += 
fate-vp9-05-resize
 fate-vp9-05-resize: CMD = framemd5 -i 
$(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-05-resize.ivf -s 352x288 -sws_flags 
bitexact+bilinear
 fate-vp9-05-resize: REF = $(SRC_PATH)/tests/ref/fate/vp9-05-resize
 
+FATE_VP9-$(call FRAMEMD5, MATROSKA, VP9, TRIM_BSF) += fate-vp9-trim-preroll
+fate-vp9-trim-preroll: CMD = framemd5 -bsf:v trim=start=133:preroll=1 -i 
$(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-10-show-existing-frame.webm
+
 fate-vp9-encparams: CMD = venc_data 
$(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-segmentation-aq-akiyo.webm 0 5
 FATE_SAMPLES_DUMP_DATA-$(call DEMDEC, MATROSKA, VP9) += fate-vp9-encparams
 
diff --git a/tests/ref/fate/vp9-trim-preroll b/tests/ref/fate/vp9-trim-preroll
new file mode 100644
index 0000000000..0d2b256b6a
--- /dev/null
+++ b/tests/ref/fate/vp9-trim-preroll
@@ -0,0 +1,20 @@
+#format: frame checksums
+#version: 2
+#hash: MD5
+#tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
+#stream#, dts,        pts, duration,     size, hash
+0,          4,          4,        1,   152064, 4ed58a0ba93a5d97a232a50c5876cda2
+0,          6,          6,        1,   152064, a41f00034923e56ba51a0b598acc2e3a
+0,          7,          7,        1,   152064, 63fa55ae9535ccdf06d44cce8065dda6
+0,          8,          8,        1,   152064, a41f00034923e56ba51a0b598acc2e3a
+0,          9,          9,        1,   152064, 0e4b08e14d919edee2bbff2ecd47de57
+0,         11,         11,        1,   152064, 0e4b08e14d919edee2bbff2ecd47de57
+0,         12,         12,        1,   152064, 5d4af03fc3d410413ef2b5a6275528b7
+0,         13,         13,        1,   152064, 9e932915c67a789f6877e6d3f76d3649
+0,         14,         14,        1,   152064, 12f2e975c217e7ffcf334524e8acec35
+0,         15,         15,        1,   152064, 9e932915c67a789f6877e6d3f76d3649
+0,         16,         16,        1,   152064, 12f2e975c217e7ffcf334524e8acec35
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to