From 61c151a09892d7f70c51c18110a1edf8796d7568 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Tue, 19 Jul 2022 00:51:18 +0200 Subject: [PATCH] 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. --- 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 {