PR #24635 opened by Kacper Michajłow (kasper93)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24635
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24635.patch


From 19d860b3a412c0d62edb947da357c81ea55bf1a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Tue, 22 Sep 2026 11:39:11 +0200
Subject: [PATCH 1/3] avcodec/dxva2: derive the DXVA2 decoder format from the
 frames context
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

dxva2_create_decoder picked the D3D9 surface format from sw_pix_fmt with
a hardcoded choice between NV12 and P010, while the surfaces it decodes
into come from the frames context, whose format is chosen separately in
ff_dxva2_common_frame_params. Map frames_ctx->sw_format to the D3DFORMAT
instead, like the D3D11 path already does, so the two cannot drift
apart.

DXVA2 is only offered for 4:2:0 8-bit and 10-bit streams, so this code
path only ever sees NV12 and P010. But it's nicer to be explicit here,
and return D3DFMT_UNKNOWN for any unexpected format, if ever added.

Signed-off-by: Kacper Michajłow <[email protected]>
---
 libavcodec/dxva2.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index c761f8eebb..3ad80dfaad 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -352,22 +352,31 @@ static int dxva2_get_decoder_configuration(AVCodecContext 
*avctx, const GUID *de
     return ret;
 }
 
+static D3DFORMAT dxva2_map_sw_to_hw_format(enum AVPixelFormat pix_fmt)
+{
+    switch (pix_fmt) {
+    case AV_PIX_FMT_NV12:       return MKTAG('N', 'V', '1', '2');
+    case AV_PIX_FMT_P010:       return MKTAG('P', '0', '1', '0');
+    case AV_PIX_FMT_P012:       return MKTAG('P', '0', '1', '6');
+    default:                    return D3DFMT_UNKNOWN;
+    }
+}
+
 static int dxva2_create_decoder(AVCodecContext *avctx)
 {
     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
     GUID *guid_list;
     unsigned guid_count;
     GUID device_guid;
-    D3DFORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
-                               MKTAG('P', '0', '1', '0') : MKTAG('N', 'V', 
'1', '2');
+    AVHWFramesContext *frames_ctx = 
(AVHWFramesContext*)avctx->hw_frames_ctx->data;
+    AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
+    AVDXVA2DeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
+    D3DFORMAT surface_format = 
dxva2_map_sw_to_hw_format(frames_ctx->sw_format);
     DXVA2_VideoDesc desc = { 0 };
     DXVA2_ConfigPictureDecode config;
     HRESULT hr;
     int ret;
     HANDLE device_handle;
-    AVHWFramesContext *frames_ctx = 
(AVHWFramesContext*)avctx->hw_frames_ctx->data;
-    AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
-    AVDXVA2DeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
 
     hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr,
                                                   &device_handle);
-- 
2.52.0


From 7c6410061d7a6eca4982a3695bd1c4b57f8235af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Tue, 22 Sep 2026 11:39:11 +0200
Subject: [PATCH 2/3] avcodec/dxva2: map 4:2:2 and 4:4:4 surface formats for
 hwcontext use
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Since 586c392bc7 av1dec offers AV_PIX_FMT_D3D11 for 8-bit and 10-bit
4:2:2 and 4:4:4 streams, but only the legacy hwaccel_context path could
use it. With hw_device_ctx or hw_frames_ctx the shared
ff_dxva2_common_frame_params mapped these streams to NV12 and
d3d11va_map_sw_to_hw_format had no entry for the packed formats, so the
decoder either failed the render target check or was created over
surfaces of the wrong format.

Map the 4:2:2 and 4:4:4 software formats to YUY2, Y210, Y216, AYUV, Y410
and Y416 as the DXVA specifications define them, so the D3D11 path now
works for such streams.

Signed-off-by: Kacper Michajłow <[email protected]>
---
 libavcodec/dxva2.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index 3ad80dfaad..052474e612 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -357,7 +357,16 @@ static D3DFORMAT dxva2_map_sw_to_hw_format(enum 
AVPixelFormat pix_fmt)
     switch (pix_fmt) {
     case AV_PIX_FMT_NV12:       return MKTAG('N', 'V', '1', '2');
     case AV_PIX_FMT_P010:       return MKTAG('P', '0', '1', '0');
-    case AV_PIX_FMT_P012:       return MKTAG('P', '0', '1', '6');
+    case AV_PIX_FMT_P012:
+    case AV_PIX_FMT_P016:       return MKTAG('P', '0', '1', '6');
+    case AV_PIX_FMT_YUYV422:    return MKTAG('Y', 'U', 'Y', '2');
+    case AV_PIX_FMT_Y210:       return MKTAG('Y', '2', '1', '0');
+    case AV_PIX_FMT_Y212:
+    case AV_PIX_FMT_Y216:       return MKTAG('Y', '2', '1', '6');
+    case AV_PIX_FMT_VUYX:       return MKTAG('A', 'Y', 'U', 'V');
+    case AV_PIX_FMT_XV30:       return MKTAG('Y', '4', '1', '0');
+    case AV_PIX_FMT_XV36:
+    case AV_PIX_FMT_XV48:       return MKTAG('Y', '4', '1', '6');
     default:                    return D3DFMT_UNKNOWN;
     }
 }
@@ -479,7 +488,16 @@ static DXGI_FORMAT d3d11va_map_sw_to_hw_format(enum 
AVPixelFormat pix_fmt)
     switch (pix_fmt) {
     case AV_PIX_FMT_NV12:       return DXGI_FORMAT_NV12;
     case AV_PIX_FMT_P010:       return DXGI_FORMAT_P010;
-    case AV_PIX_FMT_P012:       return DXGI_FORMAT_P016;
+    case AV_PIX_FMT_P012:
+    case AV_PIX_FMT_P016:       return DXGI_FORMAT_P016;
+    case AV_PIX_FMT_YUYV422:    return DXGI_FORMAT_YUY2;
+    case AV_PIX_FMT_Y210:       return DXGI_FORMAT_Y210;
+    case AV_PIX_FMT_Y212:
+    case AV_PIX_FMT_Y216:       return DXGI_FORMAT_Y216;
+    case AV_PIX_FMT_VUYX:       return DXGI_FORMAT_AYUV;
+    case AV_PIX_FMT_XV30:       return DXGI_FORMAT_Y410;
+    case AV_PIX_FMT_XV36:
+    case AV_PIX_FMT_XV48:       return DXGI_FORMAT_Y416;
     case AV_PIX_FMT_YUV420P:    return DXGI_FORMAT_420_OPAQUE;
     default:                    return DXGI_FORMAT_UNKNOWN;
     }
@@ -652,6 +670,12 @@ int ff_dxva2_common_frame_params(AVCodecContext *avctx,
     switch (avctx->sw_pix_fmt) {
     case AV_PIX_FMT_YUV420P10: frames_ctx->sw_format = AV_PIX_FMT_P010; break;
     case AV_PIX_FMT_YUV420P12: frames_ctx->sw_format = AV_PIX_FMT_P012; break;
+    case AV_PIX_FMT_YUV422P:   frames_ctx->sw_format = AV_PIX_FMT_YUYV422; 
break;
+    case AV_PIX_FMT_YUV422P10: frames_ctx->sw_format = AV_PIX_FMT_Y210; break;
+    case AV_PIX_FMT_YUV422P12: frames_ctx->sw_format = AV_PIX_FMT_Y212; break;
+    case AV_PIX_FMT_YUV444P:   frames_ctx->sw_format = AV_PIX_FMT_VUYX; break;
+    case AV_PIX_FMT_YUV444P10: frames_ctx->sw_format = AV_PIX_FMT_XV30; break;
+    case AV_PIX_FMT_YUV444P12: frames_ctx->sw_format = AV_PIX_FMT_XV36; break;
     default:                   frames_ctx->sw_format = AV_PIX_FMT_NV12; break;
     }
     frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment);
-- 
2.52.0


From 4201172253c6e094a47cf9b6391971a86bcdbaf9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Tue, 22 Sep 2026 11:39:12 +0200
Subject: [PATCH 3/3] avcodec: offer AV_PIX_FMT_D3D11 only when the d3d11va2
 hwaccel is built
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

I don't know why CONFIG_<codec>_D3D11VA2_HWACCEL was ignored before, but
clearly it should be checked here.

Signed-off-by: Kacper Michajłow <[email protected]>
---
 libavcodec/av1dec.c       | 17 ++++++++++++++++-
 libavcodec/h264_slice.c   |  5 ++++-
 libavcodec/hevc/hevcdec.c |  7 ++++++-
 libavcodec/mpeg12dec.c    |  2 ++
 libavcodec/vc1dec.c       |  2 ++
 libavcodec/vp9.c          |  5 ++++-
 6 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c
index d7ccebfbd5..24d7b87dde 100644
--- a/libavcodec/av1dec.c
+++ b/libavcodec/av1dec.c
@@ -540,7 +540,8 @@ static int get_pixel_format(AVCodecContext *avctx)
     int ret;
     enum AVPixelFormat pix_fmt = get_sw_pixel_format(avctx, seq);
 #define HWACCEL_MAX (CONFIG_AV1_DXVA2_HWACCEL + \
-                     CONFIG_AV1_D3D11VA_HWACCEL * 2 + \
+                     CONFIG_AV1_D3D11VA_HWACCEL + \
+                     CONFIG_AV1_D3D11VA2_HWACCEL + \
                      CONFIG_AV1_D3D12VA_HWACCEL + \
                      CONFIG_AV1_NVDEC_HWACCEL + \
                      CONFIG_AV1_NVDEC_CUARRAY_HWACCEL + \
@@ -560,6 +561,8 @@ static int get_pixel_format(AVCodecContext *avctx)
 #endif
 #if CONFIG_AV1_D3D11VA_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_AV1_D3D11VA2_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_AV1_D3D12VA_HWACCEL
@@ -590,6 +593,8 @@ static int get_pixel_format(AVCodecContext *avctx)
 #endif
 #if CONFIG_AV1_D3D11VA_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_AV1_D3D11VA2_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_AV1_D3D12VA_HWACCEL
@@ -617,6 +622,8 @@ static int get_pixel_format(AVCodecContext *avctx)
     case AV_PIX_FMT_YUV420P12:
 #if CONFIG_AV1_D3D11VA_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_AV1_D3D11VA2_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_AV1_D3D12VA_HWACCEL
@@ -629,6 +636,8 @@ static int get_pixel_format(AVCodecContext *avctx)
     case AV_PIX_FMT_YUV422P:
 #if CONFIG_AV1_D3D11VA_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_AV1_D3D11VA2_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_AV1_VULKAN_HWACCEL
@@ -638,6 +647,8 @@ static int get_pixel_format(AVCodecContext *avctx)
     case AV_PIX_FMT_YUV422P10:
 #if CONFIG_AV1_D3D11VA_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_AV1_D3D11VA2_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_AV1_VULKAN_HWACCEL
@@ -652,6 +663,8 @@ static int get_pixel_format(AVCodecContext *avctx)
     case AV_PIX_FMT_YUV444P:
 #if CONFIG_AV1_D3D11VA_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_AV1_D3D11VA2_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_AV1_VULKAN_HWACCEL
@@ -661,6 +674,8 @@ static int get_pixel_format(AVCodecContext *avctx)
     case AV_PIX_FMT_YUV444P10:
 #if CONFIG_AV1_D3D11VA_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_AV1_D3D11VA2_HWACCEL
         *fmtp++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_AV1_VULKAN_HWACCEL
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 2bcb64378d..c2f54ecc96 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -790,7 +790,8 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, 
int force_callback,
                                            int data_partitioning)
 {
 #define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \
-                     (CONFIG_H264_D3D11VA_HWACCEL * 2) + \
+                     CONFIG_H264_D3D11VA_HWACCEL + \
+                     CONFIG_H264_D3D11VA2_HWACCEL + \
                      CONFIG_H264_D3D12VA_HWACCEL + \
                      CONFIG_H264_NVDEC_HWACCEL + \
                      CONFIG_H264_NVDEC_CUARRAY_HWACCEL + \
@@ -903,6 +904,8 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, 
int force_callback,
 #endif
 #if CONFIG_H264_D3D11VA_HWACCEL
             *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_H264_D3D11VA2_HWACCEL
             *fmt++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_H264_D3D12VA_HWACCEL
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index b6234a6c34..bbfbe8294d 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -580,7 +580,8 @@ static enum AVPixelFormat map_to_alpha_format(HEVCContext 
*s,
 static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
 {
 #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + \
-                     CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \
+                     CONFIG_HEVC_D3D11VA_HWACCEL + \
+                     CONFIG_HEVC_D3D11VA2_HWACCEL + \
                      CONFIG_HEVC_D3D12VA_HWACCEL + \
                      CONFIG_HEVC_NVDEC_HWACCEL + \
                      CONFIG_HEVC_NVDEC_CUARRAY_HWACCEL + \
@@ -603,6 +604,8 @@ static enum AVPixelFormat get_format(HEVCContext *s, const 
HEVCSPS *sps)
 #endif
 #if CONFIG_HEVC_D3D11VA_HWACCEL
         *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_HEVC_D3D11VA2_HWACCEL
         *fmt++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_HEVC_D3D12VA_HWACCEL
@@ -633,6 +636,8 @@ static enum AVPixelFormat get_format(HEVCContext *s, const 
HEVCSPS *sps)
 #endif
 #if CONFIG_HEVC_D3D11VA_HWACCEL
         *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_HEVC_D3D11VA2_HWACCEL
         *fmt++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_HEVC_D3D12VA_HWACCEL
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index bef003704a..f1e621ce4f 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -816,6 +816,8 @@ static const enum AVPixelFormat 
mpeg2_hwaccel_pixfmt_list_420[] = {
 #endif
 #if CONFIG_MPEG2_D3D11VA_HWACCEL
     AV_PIX_FMT_D3D11VA_VLD,
+#endif
+#if CONFIG_MPEG2_D3D11VA2_HWACCEL
     AV_PIX_FMT_D3D11,
 #endif
 #if CONFIG_MPEG2_D3D12VA_HWACCEL
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index 1102e8123e..5fa7987bc5 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -58,6 +58,8 @@ static const enum AVPixelFormat vc1_hwaccel_pixfmt_list_420[] 
= {
 #endif
 #if CONFIG_VC1_D3D11VA_HWACCEL
     AV_PIX_FMT_D3D11VA_VLD,
+#endif
+#if CONFIG_VC1_D3D11VA2_HWACCEL
     AV_PIX_FMT_D3D11,
 #endif
 #if CONFIG_VC1_D3D12VA_HWACCEL
diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
index ce4e197c9d..8a8a3a1061 100644
--- a/libavcodec/vp9.c
+++ b/libavcodec/vp9.c
@@ -166,7 +166,8 @@ static void vp9_frame_replace(VP9Frame *dst, const VP9Frame 
*src)
 static int update_size(AVCodecContext *avctx, int w, int h)
 {
 #define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + \
-                     CONFIG_VP9_D3D11VA_HWACCEL * 2 + \
+                     CONFIG_VP9_D3D11VA_HWACCEL + \
+                     CONFIG_VP9_D3D11VA2_HWACCEL + \
                      CONFIG_VP9_D3D12VA_HWACCEL + \
                      CONFIG_VP9_NVDEC_HWACCEL + \
                      CONFIG_VP9_NVDEC_CUARRAY_HWACCEL + \
@@ -196,6 +197,8 @@ static int update_size(AVCodecContext *avctx, int w, int h)
 #endif
 #if CONFIG_VP9_D3D11VA_HWACCEL
             *fmtp++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+#if CONFIG_VP9_D3D11VA2_HWACCEL
             *fmtp++ = AV_PIX_FMT_D3D11;
 #endif
 #if CONFIG_VP9_D3D12VA_HWACCEL
-- 
2.52.0

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

Reply via email to