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

With AMF-surface output (`-hwaccel amf -hwaccel_output_format amf`), 
`amf_decode_init()` creates the frames context from 
`AMF_VIDEO_DECODER_OUTPUT_FORMAT`. When the decoder has not detected a format 
yet, it falls back to NV12. The context is only re-created on 
`AMF_RESOLUTION_CHANGED`, so it stays NV12 when the decoder then outputs P010 
at the same size. The AV1 decoder doesn't report its format before decoding, 
even with a sequence header in the extradata, so every 10-bit AV1 stream comes 
out as P010 surfaces in an NV12 frames context, and `hwdownload,format=p010le` 
fails with `Failed to download frame: -22`.

This patch re-creates the frames context, keeping its size, when an output 
surface's format differs from its `sw_format`.

Tested on Windows 11, RX 9070 XT, driver 32.0.32015.7029:
- 10-bit AV1 (raw OBU and Matroska) with AMF-surface output and 
`hwdownload,format=p010le` now decodes, with the same framemd5 as software 
output from `av1_amf`. Before, it failed on the first frame.
- 8-bit AV1, `h264_amf`, `hevc_amf` (8 and 10 bit) and `vp9_amf` give unchanged 
framemd5 with software and AMF-surface output.

Independent of #25525, #25146, #25147 and #25560, and merges cleanly with each 
of them.

Written with Claude Opus 5.5 in Claude Code; `Assisted-by` trailer on the 
commit.



>From 99a013c7d288a14dfd7d507bc2fb870ba712068e Mon Sep 17 00:00:00 2001
From: Julius Bairaktaris <[email protected]>
Date: Wed, 28 Oct 2026 14:48:14 +0100
Subject: [PATCH] avcodec/amfdec: re-init the frames context when the surface
 format differs

With AMF-surface output, amf_decode_init() creates the frames context
from AMF_VIDEO_DECODER_OUTPUT_FORMAT, falling back to NV12 when the
decoder has not detected a format yet. The context is only re-created
on AMF_RESOLUTION_CHANGED, so it keeps NV12 when the decoder then
outputs P010 at the same size. The AV1 decoder does not report its
format before decoding, so every 10-bit AV1 stream is output as P010
surfaces in an NV12 frames context, and hwdownload to p010le fails with
EINVAL.

Re-create the frames context, keeping its size, when an output surface's
format differs from its sw_format.

Tested on Windows 11, RX 9070 XT, driver 32.0.32015.7029: 10-bit AV1
(raw OBU and Matroska) with -hwaccel amf -hwaccel_output_format amf and
hwdownload to p010le now decodes, with the same framemd5 as software
output from av1_amf; 8-bit AV1, h264_amf, hevc_amf (8 and 10 bit) and
vp9_amf are unchanged.

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

diff --git a/libavcodec/amfdec.c b/libavcodec/amfdec.c
index 00a17360f55..017327f6bcb 100644
--- a/libavcodec/amfdec.c
+++ b/libavcodec/amfdec.c
@@ -512,6 +512,19 @@ static int amf_amfsurface_to_avframe(AVCodecContext 
*avctx, AMFSurface* surface,
     int                 format_amf;
 
     if (avctx->hw_device_ctx && 
((AVHWDeviceContext*)avctx->hw_device_ctx->data)->type == AV_HWDEVICE_TYPE_AMF) 
{
+        AVHWFramesContext *frames_ctx;
+        enum AVPixelFormat sw_format;
+
+        if (!avctx->hw_frames_ctx)
+            return AVERROR(EINVAL);
+        frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
+        sw_format  = av_amf_to_av_format(surface->pVtbl->GetFormat(surface));
+        if (sw_format != frames_ctx->sw_format) {
+            ret = amf_reinit_frames_context(avctx, sw_format, 
frames_ctx->width, frames_ctx->height);
+            if (ret < 0)
+                return ret;
+        }
+
         // prepare frame similar to  ff_get_buffer(avctx, frame, 
AV_GET_BUFFER_FLAG_REF);
 
         ret = ff_decode_frame_props(avctx, frame);
-- 
2.54.0

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

Reply via email to