PR #25380 opened by Daniel Campos Ramos (danielcamposramos)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25380
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25380.patch

Fixes #25379.

An allocation failure in `av_frame_ref()` during VVC output makes 
`frame_start()` abort before the current picture is submitted.
In low delay mode this loses both the failed output and the current picture.
With delayed frames, the next packet restores the earlier picture's output flag 
from the preceding frame context, while the current picture is still lost.

Keep the output error in the frame context and report it when that frame is 
collected.
This preserves the updated DPB and decodes the current picture, while dropping 
only the output whose reference allocation failed.
The change touches only the decoder and its internal frame context.

The attached regression fails the buffer reference allocation inside the real 
`av_frame_ref()` on plain master, with no stereo changes or SEI messages needed.
It checks the remaining picture hashes and timestamps with one and four 
threads, both with and without low delay, including failure during draining.
This is separate from #24628 and should land first, then that series will be 
rebased with its duplicate recovery commit removed.

Eight of the twelve regression cases fail before the fix, and all twelve pass 
after it on GCC and clang.
The full applicable FATE suite passes all 5,993 tests on both master and the 
fix with each compiler, with no changed output against the matching master.

AI partners helped produce this patch and its regression checks.



>From 88d7e79ddabad9ebd1650d0ca43fa74342d51fd2 Mon Sep 17 00:00:00 2001
From: Daniel Campos Ramos <[email protected]>
Date: Fri, 23 Oct 2026 04:47:50 +0000
Subject: [PATCH] avcodec/vvc: defer output errors until the current frame is
 submitted

An allocation failure in av_frame_ref() during output aborts frame_start()
before the current picture is submitted. In low delay mode this loses the
current picture as well as the output picture. With delayed frames the
next packet copies the preceding frame context's DPB, restoring the failed
picture's output flag while still losing the current picture.

Retain the output error in the frame context and report it when that frame
is collected. This preserves the updated DPB and decodes the current
picture, while dropping only the picture whose export failed.

Reproduced on unmodified master by failing the buffer-reference allocation
inside ff_vvc_output_frame(), then comparing the remaining picture hashes
against a successful decode, with one and four threads and both delay modes.

Signed-off-by: Daniel Campos Ramos <[email protected]>
Assisted-by: gpt-6-astra via Codex
---
 libavcodec/vvc/dec.c | 10 ++++++++--
 libavcodec/vvc/dec.h |  1 +
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/libavcodec/vvc/dec.c b/libavcodec/vvc/dec.c
index f7c51f01a1b..43f58d9153a 100644
--- a/libavcodec/vvc/dec.c
+++ b/libavcodec/vvc/dec.c
@@ -828,8 +828,12 @@ static int frame_start(VVCContext *s, VVCFrameContext *fc, 
SliceContext *sc)
 
     av_frame_unref(fc->output_frame);
 
-    if ((ret = ff_vvc_output_frame(s, fc, 
fc->output_frame,rsh->sh_no_output_of_prior_pics_flag, 0)) < 0)
-        goto fail;
+    /* Keep the updated DPB when exporting an earlier picture fails.
+     * Report the error after submitting the current picture. */
+    fc->output_error = ff_vvc_output_frame(s, fc, fc->output_frame,
+                                          
rsh->sh_no_output_of_prior_pics_flag, 0);
+    if (fc->output_error < 0)
+        av_frame_unref(fc->output_frame);
 
     if ((ret = ff_vvc_frame_rpl(s, fc, sc)) < 0)
         goto fail;
@@ -1130,6 +1134,8 @@ static int wait_delayed_frame(VVCContext *s, AVFrame 
*output, int *got_output)
 
     if (!ret) {
         ret = frame_end(s, delayed);
+        if (ret >= 0 && delayed->output_error < 0)
+            ret = delayed->output_error;
         if (ret >= 0 && delayed->output_frame->buf[0] && output) {
             av_frame_move_ref(output, delayed->output_frame);
             *got_output = 1;
diff --git a/libavcodec/vvc/dec.h b/libavcodec/vvc/dec.h
index bfb8a2e20da..7ea88c19f45 100644
--- a/libavcodec/vvc/dec.h
+++ b/libavcodec/vvc/dec.h
@@ -127,6 +127,7 @@ typedef struct VVCFrameContext {
 
     struct AVFrame *frame;
     struct AVFrame *output_frame;
+    int output_error;
 
     VVCFrameParamSets ps;
     VVCSEI sei;
-- 
2.54.0

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

Reply via email to