[PR] avutil/hwcontext_amf: Fix double init for derived devices. (PR #24077)

DmitriiGershenkop via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178644972580.59.2346527116618507315@29965ddac10e>
PR #24077 opened by DmitriiGershenkop
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24077
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24077.patch

Right after device_derive, FFmpeg also calls device_init. And in device_init (amf_device_init), the fact that AMF might be already initialized with, for example, Vulkan, is ignored and gets initialized again with DX11. This patch fixes that, and introduces the av_amf_get_memory_type to be used in the future patches.


>From 098fd6e7191cf73d65a82b02d1dd10f5609d8f92 Mon Sep 17 00:00:00 2001
From: Dmitrii Gershenkop <[email protected]>
Date: Tue, 11 Aug 2026 13:52:05 +0200
Subject: [PATCH] avutil/hwcontext_amf: Fix double init for derived devices.

Right after device_derive, FFmpeg also calls device_init. And in device_init (amf_device_init), the fact that AMF might be already initialized with, for example, Vulkan, is ignored and gets initialized again with DX11.
---
 libavutil/hwcontext_amf.c | 86 +++++++++++++++++++++++++++------------
 libavutil/hwcontext_amf.h |  2 +
 2 files changed, 63 insertions(+), 25 deletions(-)

diff --git a/libavutil/hwcontext_amf.c b/libavutil/hwcontext_amf.c
index 7d877683b4..2438aab768 100644
--- a/libavutil/hwcontext_amf.c
+++ b/libavutil/hwcontext_amf.c
@@ -558,10 +558,37 @@ static void amf_device_uninit(AVHWDeviceContext *device_ctx)
     amf_ctx->version = 0;
 }
 
+enum AMF_MEMORY_TYPE av_amf_get_memory_type(AVAMFDeviceContext *amf_ctx)
+{
+    AMFContext  *context = amf_ctx->context;
+    AMFContext1 *context1 = NULL;
+    AMFGuid guid1 = IID_AMFContext1();
+
+#ifdef _WIN32
+    if (AMF_IFACE_CALL(context, GetDX11Device, AMF_DX11_1))
+        return AMF_MEMORY_DX11;
+
+    if (AMF_IFACE_CALL(context, GetDX9Device, AMF_DX9))
+        return AMF_MEMORY_DX9;
+#endif
+
+    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);
+        return AMF_MEMORY_VULKAN;
+    }
+
+    return AMF_MEMORY_UNKNOWN;
+}
+
 static int amf_device_init(AVHWDeviceContext *ctx)
 {
     AVAMFDeviceContext *amf_ctx = ctx->hwctx;
+    AMFContext  *context = amf_ctx->context;
     AMFContext1 *context1 = NULL;
+    AMFGuid guid1 = IID_AMFContext1();
     AMF_RESULT res;
 
     if (!amf_ctx->lock) {
@@ -574,35 +601,44 @@ static int amf_device_init(AVHWDeviceContext *ctx)
         amf_ctx->unlock = amf_unlock_default;
     }
 
-#ifdef _WIN32
-    res = amf_ctx->context->pVtbl->InitDX11(amf_ctx->context, NULL, AMF_DX11_1);
-    if (res == AMF_OK || res == AMF_ALREADY_INITIALIZED) {
-        av_log(ctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D11.\n");
-    } else {
-        res = amf_ctx->context->pVtbl->InitDX9(amf_ctx->context, NULL);
-        if (res == AMF_OK) {
-            av_log(ctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n");
-        } else {
-#endif
-            AMFGuid guid = IID_AMFContext1();
-            res = amf_ctx->context->pVtbl->QueryInterface(amf_ctx->context, &guid, (void**)&context1);
-            AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res);
+    if (av_amf_get_memory_type(amf_ctx) != AMF_MEMORY_UNKNOWN) {
+        av_log(ctx, AV_LOG_VERBOSE, "AMF is already initialized, skipping init.\n");
+        return 0;
+    }
 
-            res = context1->pVtbl->InitVulkan(context1, NULL);
-            context1->pVtbl->Release(context1);
-            if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
-                if (res == AMF_NOT_SUPPORTED)
-                    av_log(ctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n");
-                else
-                    av_log(ctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res);
-                 return AVERROR(ENOSYS);
-            }
-            av_log(ctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n");
 #ifdef _WIN32
-        }
-     }
+    res = AMF_IFACE_CALL(context, InitDX11, NULL, AMF_DX11_1);
+    if (res == AMF_OK) {
+        av_log(ctx, AV_LOG_VERBOSE, "Sucessfully initialized AMF via D3D11.\n");
+        return 0;
+    }
+
+    res = AMF_IFACE_CALL(context, InitDX9, NULL);
+    if (res == AMF_OK) {
+        av_log(ctx, AV_LOG_VERBOSE, "Sucessfully initialized AMF via D3D9.\n");
+        return 0;
+    }
+
+    av_log(ctx, AV_LOG_WARNING, "AMF failed to initialize with any of supported versions of DirectX, trying Vulkan instead...\n");
 #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);
+
+    res = AMF_IFACE_CALL(context1, InitVulkan, NULL);
+    AMF_IFACE_CALL(context1, Release);
+
+    if (res == AMF_OK)
+        av_log(ctx, AV_LOG_VERBOSE, "Sucessfully initialized AMF via Vulkan.\n");
+    else {
+        if (res == AMF_NOT_SUPPORTED)
+            av_log(ctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n");
+        else
+            av_log(ctx, AV_LOG_ERROR, "Failed to initialize AMF via Vulkan, error %d\n", res);
+
+        return AVERROR(ENOSYS);
+    }
+
     return 0;
 }
 
diff --git a/libavutil/hwcontext_amf.h b/libavutil/hwcontext_amf.h
index 918eec97b8..d2bbb41891 100644
--- a/libavutil/hwcontext_amf.h
+++ b/libavutil/hwcontext_amf.h
@@ -46,6 +46,8 @@ typedef struct AVAMFDeviceContext {
     void *lock_ctx;
 } AVAMFDeviceContext;
 
+enum AMF_MEMORY_TYPE av_amf_get_memory_type(AVAMFDeviceContext *amf_ctx);
+
 enum AMF_SURFACE_FORMAT av_av_to_amf_format(enum AVPixelFormat fmt);
 enum AVPixelFormat av_amf_to_av_format(enum AMF_SURFACE_FORMAT fmt);
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.