Commit 502046abcf for ffmpeg
commit 502046abcfcbd4148fd60b442cc96a1bcad62fae
Author: Daniel Campos Ramos <Capitain_Jack@yahoo.com>
Date: Fri Oct 23 04:47:50 2026 +0000
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.
Fixes: #25379
Signed-off-by: Daniel Campos Ramos <Capitain_Jack@yahoo.com>
Assisted-by: gpt-6-astra via Codex
diff --git a/libavcodec/vvc/dec.c b/libavcodec/vvc/dec.c
index c1326fe17c..8ed9e1e4b8 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;
+ /* Do not abort the current picture when outputting an earlier one
+ * fails: decode and submit it, then report the error afterwards. */
+ 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 bfb8a2e20d..7ea88c19f4 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;