[FFmpeg-cvslog] avfilter/vsrc_ddagrab: dynamically load SetThreadDpiAwarenessContext

Timo Rothenpieler git at videolan.org
Tue Jul 19 02:38:47 EEST 2022


ffmpeg | branch: master | Timo Rothenpieler <timo at rothenpieler.org> | Tue Jul 19 00:51:18 2022 +0200| [61c151a09892d7f70c51c18110a1edf8796d7568] | committer: Timo Rothenpieler

avfilter/vsrc_ddagrab: dynamically load SetThreadDpiAwarenessContext

It's a Windows 10 only function, and its presence alone prevents the
binary from loading on older Windows versions.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=61c151a09892d7f70c51c18110a1edf8796d7568
---

 configure                  |  2 --
 libavfilter/vsrc_ddagrab.c | 41 +++++++++++++++++++++++++++++++++--------
 2 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/configure b/configure
index 18d9b61a99..91444cdc53 100755
--- a/configure
+++ b/configure
@@ -2309,7 +2309,6 @@ SYSTEM_FUNCS="
     SetDllDirectory
     setmode
     setrlimit
-    SetThreadDpiAwarenessContext
     Sleep
     strerror_r
     sysconf
@@ -6401,7 +6400,6 @@ check_type "windows.h d3d11.h" "ID3D11VideoDecoder"
 check_type "windows.h d3d11.h" "ID3D11VideoContext"
 check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602
 check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat
-check_func_headers windows.h SetThreadDpiAwarenessContext -D_WIN32_WINNT=0x0A00
 
 check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC"
 check_type "vdpau/vdpau.h" "VdpPictureInfoVP9"
diff --git a/libavfilter/vsrc_ddagrab.c b/libavfilter/vsrc_ddagrab.c
index 4a90ad7a02..5668eda051 100644
--- a/libavfilter/vsrc_ddagrab.c
+++ b/libavfilter/vsrc_ddagrab.c
@@ -18,9 +18,9 @@
 
 #include "config.h"
 
-#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0A00
+#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
 #undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0A00
+#define _WIN32_WINNT 0x0602
 #endif
 #define WIN32_LEAN_AND_MEAN
 
@@ -41,6 +41,7 @@
 #include "libavutil/avassert.h"
 #include "libavutil/hwcontext.h"
 #include "libavutil/hwcontext_d3d11va.h"
+#include "compat/w32dlfcn.h"
 #include "avfilter.h"
 #include "internal.h"
 #include "formats.h"
@@ -150,8 +151,12 @@ static av_cold int init_dxgi_dda(AVFilterContext *avctx)
     IDXGIAdapter *dxgi_adapter = NULL;
     IDXGIOutput *dxgi_output = NULL;
     IDXGIOutput1 *dxgi_output1 = NULL;
-#if HAVE_IDXGIOUTPUT5 && HAVE_SETTHREADDPIAWARENESSCONTEXT
+#if HAVE_IDXGIOUTPUT5
     IDXGIOutput5 *dxgi_output5 = NULL;
+
+    typedef DPI_AWARENESS_CONTEXT (*set_thread_dpi_t)(DPI_AWARENESS_CONTEXT);
+    set_thread_dpi_t set_thread_dpi;
+    HMODULE user32_module;
 #endif
     int w, h;
     HRESULT hr;
@@ -185,9 +190,19 @@ static av_cold int init_dxgi_dda(AVFilterContext *avctx)
         return AVERROR_EXTERNAL;
     }
 
-#if HAVE_IDXGIOUTPUT5 && HAVE_SETTHREADDPIAWARENESSCONTEXT
-    hr = IDXGIOutput_QueryInterface(dxgi_output, &IID_IDXGIOutput5, (void**)&dxgi_output5);
-    if (SUCCEEDED(hr)) {
+#if HAVE_IDXGIOUTPUT5
+    user32_module = dlopen("user32.dll", 0);
+    if (!user32_module) {
+        av_log(avctx, AV_LOG_ERROR, "Failed loading user32.dll\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    set_thread_dpi = (set_thread_dpi_t)dlsym(user32_module, "SetThreadDpiAwarenessContext");
+
+    if (set_thread_dpi)
+        hr = IDXGIOutput_QueryInterface(dxgi_output, &IID_IDXGIOutput5, (void**)&dxgi_output5);
+
+    if (set_thread_dpi && SUCCEEDED(hr)) {
         DPI_AWARENESS_CONTEXT prev_dpi_ctx;
         DXGI_FORMAT formats[] = {
             DXGI_FORMAT_R10G10B10A2_UNORM,
@@ -197,7 +212,7 @@ static av_cold int init_dxgi_dda(AVFilterContext *avctx)
         IDXGIOutput_Release(dxgi_output);
         dxgi_output = NULL;
 
-        prev_dpi_ctx = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
+        prev_dpi_ctx = set_thread_dpi(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
         if (!prev_dpi_ctx)
             av_log(avctx, AV_LOG_WARNING, "Failed enabling DPI awareness for DDA\n");
 
@@ -211,8 +226,18 @@ static av_cold int init_dxgi_dda(AVFilterContext *avctx)
         dxgi_output5 = NULL;
 
         if (prev_dpi_ctx)
-            SetThreadDpiAwarenessContext(prev_dpi_ctx);
+            set_thread_dpi(prev_dpi_ctx);
+
+        dlclose(user32_module);
+        user32_module = NULL;
+        set_thread_dpi = NULL;
+
+        av_log(avctx, AV_LOG_DEBUG, "Using IDXGIOutput5 interface\n");
     } else {
+        dlclose(user32_module);
+        user32_module = NULL;
+        set_thread_dpi = NULL;
+
         av_log(avctx, AV_LOG_DEBUG, "Falling back to IDXGIOutput1\n");
 #else
     {



More information about the ffmpeg-cvslog mailing list