PR #24442 opened by DmitriiGershenkop URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24442 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24442.patch
AMF implementation in ffmpeg has a lot of dead code related to DirectX 12 support. This patch makes the code at least somewhat useful by fixing DX12 derive for AMF. >From 715fb2811b95764563add81d50a6660849bf1338 Mon Sep 17 00:00:00 2001 From: Dmitrii Gershenkop <[email protected]> Date: Wed, 9 Sep 2026 18:16:29 +0200 Subject: [PATCH] av{codec, util}/hwcontext_amf: Fix DX12 => AMF Derive AMF implementation in ffmpeg has a lot of dead code related to DirectX 12 support. This patch makes the code at least somewhat useful. --- libavcodec/amfenc.c | 30 ++++++++++++++++++ libavutil/hwcontext_amf.c | 65 +++++++++++++++++++++++++++++++-------- 2 files changed, 82 insertions(+), 13 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 3ffca750d8..71db6d7725 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -22,6 +22,11 @@ #include "libavutil/imgutils.h" #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_amf.h" +#include "libavutil/hwcontext_amf_internal.h" + +#if CONFIG_D3D12VA +#include "libavutil/hwcontext_d3d12va.h" +#endif #if CONFIG_D3D11VA #include "libavutil/hwcontext_d3d11va.h" #endif @@ -55,6 +60,9 @@ const enum AVPixelFormat ff_amf_pix_fmts[] = { AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, +#if CONFIG_D3D12VA + AV_PIX_FMT_D3D12, +#endif #if CONFIG_D3D11VA AV_PIX_FMT_D3D11, #endif @@ -402,6 +410,24 @@ static int amf_submit_frame(AVCodecContext *avctx, AVFrame *frame, AMFSurface // prepare surface from frame switch (frame->format) { +#if CONFIG_D3D12VA + case AV_PIX_FMT_D3D12: + { + AVD3D12VAFrame *frame_dx12 = (AVD3D12VAFrame *)frame->data[0]; + AMFGuid guid = IID_AMFContext2(); + AMFContext2 *context2 = NULL; + + res = AMF_IFACE_CALL(amf_device_ctx->context, QueryInterface, &guid, (void**)&context2); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext2() failed with error %d\n", res); + + res = AMF_IFACE_CALL(context2, CreateSurfaceFromDX12Native, frame_dx12->texture, &surface, NULL); + AMF_IFACE_CALL(context2, Release); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateSurfaceFromDX12Native() failed with error %d\n", res); + + hw_surface = 1; + } + break; +#endif #if CONFIG_D3D11VA case AV_PIX_FMT_D3D11: { @@ -712,6 +738,10 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) } const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[] = { +#if CONFIG_D3D12VA + HW_CONFIG_ENCODER_FRAMES(D3D12, D3D12VA), + HW_CONFIG_ENCODER_DEVICE(NONE, D3D12VA), +#endif #if CONFIG_D3D11VA HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11VA), HW_CONFIG_ENCODER_DEVICE(NONE, D3D11VA), diff --git a/libavutil/hwcontext_amf.c b/libavutil/hwcontext_amf.c index 505424af74..32fde79f40 100644 --- a/libavutil/hwcontext_amf.c +++ b/libavutil/hwcontext_amf.c @@ -562,12 +562,24 @@ enum AMF_MEMORY_TYPE av_amf_get_memory_type(AVAMFDeviceContext *amf_ctx) { AMFContext *context = amf_ctx->context; AMFContext1 *context1 = NULL; + AMFContext2 *context2 = NULL; AMFGuid guid1 = IID_AMFContext1(); + AMFGuid guid2 = IID_AMFContext2(); + void * device = NULL; if (!amf_ctx) return AMF_MEMORY_UNKNOWN; #ifdef _WIN32 + if (AMF_IFACE_CALL(context, QueryInterface, &guid2, (void**)&context2) == AMF_OK) + { + device = AMF_IFACE_CALL(context2, GetDX12Device, AMF_DX12); + AMF_IFACE_CALL(context2, Release); + + if (device) + return AMF_MEMORY_DX12; + } + if (AMF_IFACE_CALL(context, GetDX11Device, AMF_DX11_1)) return AMF_MEMORY_DX11; @@ -578,10 +590,10 @@ enum AMF_MEMORY_TYPE av_amf_get_memory_type(AVAMFDeviceContext *amf_ctx) if (AMF_IFACE_CALL(context, QueryInterface, &guid1, (void**)&context1) != AMF_OK) return AMF_MEMORY_UNKNOWN; - if (AMF_IFACE_CALL(context1, GetVulkanDevice)) { - context1->pVtbl->Release(context1); + device = AMF_IFACE_CALL(context1, GetVulkanDevice); + AMF_IFACE_CALL(context1, Release); + if (device) return AMF_MEMORY_VULKAN; - } return AMF_MEMORY_UNKNOWN; } @@ -589,9 +601,11 @@ enum AMF_MEMORY_TYPE av_amf_get_memory_type(AVAMFDeviceContext *amf_ctx) static int amf_device_init(AVHWDeviceContext *ctx) { AVAMFDeviceContext *amf_ctx = ctx->hwctx; - AMFContext *context = amf_ctx->context; + AMFContext *context = amf_ctx->context; AMFContext1 *context1 = NULL; + AMFContext2 *context2 = NULL; AMFGuid guid1 = IID_AMFContext1(); + AMFGuid guid2 = IID_AMFContext2(); AMF_RESULT res; if (!amf_ctx->lock) { @@ -610,6 +624,18 @@ static int amf_device_init(AVHWDeviceContext *ctx) } #ifdef _WIN32 + res = AMF_IFACE_CALL(context, QueryInterface, &guid2, (void**)&context2); + if (res == AMF_OK) { + res = AMF_IFACE_CALL(context2, InitDX12, NULL, AMF_DX12); + AMF_IFACE_CALL(context2, Release); + if (res == AMF_OK) { + av_log(ctx, AV_LOG_VERBOSE, "Sucessfully initialized AMF via D3D12.\n"); + return 0; + } + } else { + av_log(ctx, AV_LOG_VERBOSE, "CreateContext2() failed with error %d, trying older D3D APIs...\n", res); + } + res = AMF_IFACE_CALL(context, InitDX11, NULL, AMF_DX11_1); if (res == AMF_OK) { av_log(ctx, AV_LOG_VERBOSE, "Successfully initialized AMF via D3D11.\n"); @@ -626,23 +652,36 @@ static int amf_device_init(AVHWDeviceContext *ctx) #endif res = AMF_IFACE_CALL(context, QueryInterface, &guid1, (void**)&context1); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res); + if (res != AMF_OK) { + av_log(ctx, AV_LOG_ERROR, "CreateContext1() failed with error %d\n", res); + return res; + } res = AMF_IFACE_CALL(context1, InitVulkan, NULL); AMF_IFACE_CALL(context1, Release); - if (res == AMF_OK) + if (res == AMF_OK) { av_log(ctx, AV_LOG_VERBOSE, "Successfully initialized AMF via Vulkan.\n"); - else { - if (res == AMF_NOT_SUPPORTED) + return 0; + } else { + if (res == AMF_NOT_SUPPORTED) { av_log(ctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n"); - else + return AVERROR(ENOTSUP); + } + else { av_log(ctx, AV_LOG_ERROR, "Failed to initialize AMF via Vulkan, error %d\n", res); - - return AVERROR(ENOSYS); + return AVERROR(ENOSYS); + } } - return 0; + // Shouldn't get here under normal circumstances. + if (context1) + AMF_IFACE_CALL(context1, Release); + + if (context2) + AMF_IFACE_CALL(context2, Release); + + return AVERROR_BUG; } static int amf_load_library(AVAMFDeviceContext* amf_ctx, void* avcl) @@ -829,7 +868,7 @@ static int amf_device_derive(AVHWDeviceContext *device_ctx, AVHWDeviceContext *child_device_ctx, AVDictionary *opts, int flags) { -#if CONFIG_DXVA2 || CONFIG_D3D11VA +#if CONFIG_DXVA2 || CONFIG_D3D11VA || CONFIG_D3D12VA AVAMFDeviceContext *amf_ctx = device_ctx->hwctx; #endif int ret; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
