From d54127c41a81cf2078a3504f78e0e4232cfe11b7 Mon Sep 17 00:00:00 2001 From: Sil Vilerino Date: Fri, 14 Apr 2023 10:39:04 -0400 Subject: [PATCH] lavu/hwcontext_vaapi: Add Windows/VAAPI support with vaGetDisplayWin32 Libva 2.17+ adds a new libva-win32 node and Mesa 22.3 adds a VAAPI driver based on Direct3D 12 for Windows. Both of them are available at: https://www.nuget.org/packages/Microsoft.Direct3D.VideoAccelerationCompatibilityPack Initial review at https://github.com/intel-media-ci/ffmpeg/pull/619/ Signed-off-by: Sil Vilerino Reviewed-by: Dmitry Rogozhkin Reviewed-by: Wu, Tong1 --- Changelog | 1 + configure | 27 ++++++++++++- libavutil/hwcontext_vaapi.c | 78 ++++++++++++++++++++++++++++++++++++- libavutil/tests/hwdevice.c | 2 +- 4 files changed, 103 insertions(+), 5 deletions(-) diff --git a/Changelog b/Changelog index 4284a250a2..8268e42cbc 100644 --- a/Changelog +++ b/Changelog @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. version : - libaribcaption decoder - Playdate video decoder and demuxer +- Extend VAAPI support for libva-win32 on Windows version 6.0: - Radiance HDR image support diff --git a/configure b/configure index 549ed1401c..bb7be67676 100755 --- a/configure +++ b/configure @@ -2316,6 +2316,7 @@ SYSTEM_LIBRARIES=" bcrypt vaapi_drm vaapi_x11 + vaapi_win32 vdpau_x11 " @@ -3827,7 +3828,7 @@ swscale_suggest="libm stdatomic" avcodec_extralibs="pthreads_extralibs iconv_extralibs dxva2_extralibs lcms2_extralibs" avfilter_extralibs="pthreads_extralibs" -avutil_extralibs="d3d11va_extralibs mediacodec_extralibs nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs" +avutil_extralibs="d3d11va_extralibs mediacodec_extralibs nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vaapi_win32_extralibs vdpau_x11_extralibs" # programs ffmpeg_deps="avcodec avfilter avformat threads" @@ -6948,6 +6949,21 @@ test_cpp < +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#error desktop, not uwp +#else +// WINAPI_FAMILY_APP, WINAPI_FAMILY_PHONE_APP => UWP +#endif +#else +#error no family set +#endif +EOF + # mediafoundation requires linking directly to mfplat if building for uwp target enabled uwp && mediafoundation_extralibs="-lmfplat -lmfuuid -lole32 -lstrmiids" || mediafoundation_extralibs="-lmfuuid -lole32 -lstrmiids" @@ -6958,7 +6974,14 @@ enabled vaapi && check_pkg_config vaapi "libva >= 0.35.0" "va/va.h" vaInitialize if enabled vaapi; then - check_pkg_config vaapi_drm "libva-drm" "va/va_drm.h" vaGetDisplayDRM + case $target_os in + mingw32*|mingw64*|win32|win64) + check_pkg_config vaapi_win32 "libva-win32" "va/va_win32.h" vaGetDisplayWin32 + ;; + *) + check_pkg_config vaapi_drm "libva-drm" "va/va_drm.h" vaGetDisplayDRM + ;; + esac if enabled xlib_x11; then check_pkg_config vaapi_x11 "libva-x11" "va/va_x11.h" vaGetDisplay diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 90c2c191d9..6c3a227ddd 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -18,6 +18,15 @@ #include "config.h" +#if HAVE_VAAPI_WIN32 +# include +#define COBJMACROS +# include +# include +# include "compat/w32dlfcn.h" +# include +typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory); +#endif #if HAVE_VAAPI_X11 # include #endif @@ -1663,7 +1672,7 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, VAAPIDevicePriv *priv; VADisplay display = NULL; const AVDictionaryEntry *ent; - int try_drm, try_x11, try_all; + int try_drm, try_x11, try_win32, try_all; priv = av_mallocz(sizeof(*priv)); if (!priv) @@ -1676,11 +1685,13 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, ent = av_dict_get(opts, "connection_type", NULL, 0); if (ent) { - try_all = try_drm = try_x11 = 0; + try_all = try_drm = try_x11 = try_win32 = 0; if (!strcmp(ent->value, "drm")) { try_drm = 1; } else if (!strcmp(ent->value, "x11")) { try_x11 = 1; + } else if (!strcmp(ent->value, "win32")) { + try_win32 = 1; } else { av_log(ctx, AV_LOG_ERROR, "Invalid connection type %s.\n", ent->value); @@ -1690,6 +1701,7 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, try_all = 1; try_drm = HAVE_VAAPI_DRM; try_x11 = HAVE_VAAPI_X11; + try_win32 = HAVE_VAAPI_WIN32; } #if HAVE_VAAPI_DRM @@ -1797,6 +1809,68 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, } #endif +#if HAVE_VAAPI_WIN32 + if (!display && try_win32) { + // Try to create a display from the specified device, if any. + if (!device) { + display = vaGetDisplayWin32(NULL); + } else { + IDXGIFactory2 *pDXGIFactory = NULL; + IDXGIAdapter *pAdapter = NULL; +#if !HAVE_UWP + HANDLE dxgi = dlopen("dxgi.dll", 0); + if (!dxgi) { + av_log(ctx, AV_LOG_ERROR, "Failed to load dxgi.dll\n"); + return AVERROR_UNKNOWN; + } + PFN_CREATE_DXGI_FACTORY pfnCreateDXGIFactory = + (PFN_CREATE_DXGI_FACTORY)dlsym(dxgi, "CreateDXGIFactory"); + if (!pfnCreateDXGIFactory) { + av_log(ctx, AV_LOG_ERROR, "CreateDXGIFactory load failed\n"); + dlclose(dxgi); + return AVERROR_UNKNOWN; + } +#else + // In UWP (which lacks LoadLibrary), CreateDXGIFactory isn't + // available, only CreateDXGIFactory1 + PFN_CREATE_DXGI_FACTORY pfnCreateDXGIFactory = + (PFN_CREATE_DXGI_FACTORY)CreateDXGIFactory1; +#endif + if (SUCCEEDED(pfnCreateDXGIFactory(&IID_IDXGIFactory2, + (void **)&pDXGIFactory))) { + int adapter = atoi(device); + if (SUCCEEDED(IDXGIFactory2_EnumAdapters(pDXGIFactory, + adapter, + &pAdapter))) { + DXGI_ADAPTER_DESC desc; + if (SUCCEEDED(IDXGIAdapter2_GetDesc(pAdapter, &desc))) { + av_log(ctx, AV_LOG_INFO, + "Using device %04x:%04x (%ls) - LUID %lu %ld.\n", + desc.VendorId, desc.DeviceId, desc.Description, + desc.AdapterLuid.LowPart, + desc.AdapterLuid.HighPart); + display = vaGetDisplayWin32(&desc.AdapterLuid); + } + IDXGIAdapter_Release(pAdapter); + } + IDXGIFactory2_Release(pDXGIFactory); + } +#if !HAVE_UWP + dlclose(dxgi); +#endif + } + + if (!display) { + av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display " + "from Win32 display.\n"); + return AVERROR_UNKNOWN; + } + + av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via " + "Win32 display.\n"); + } +#endif + if (!display) { if (device) av_log(ctx, AV_LOG_ERROR, "No VA display found for " diff --git a/libavutil/tests/hwdevice.c b/libavutil/tests/hwdevice.c index 7eb355c988..c57586613a 100644 --- a/libavutil/tests/hwdevice.c +++ b/libavutil/tests/hwdevice.c @@ -140,7 +140,7 @@ static const struct { { AV_HWDEVICE_TYPE_OPENCL, { "0.0", "0.1", "1.0", "1.1" } }, { AV_HWDEVICE_TYPE_VAAPI, - { "/dev/dri/renderD128", "/dev/dri/renderD129", ":0" } }, + { "/dev/dri/renderD128", "/dev/dri/renderD129", ":0", "0", "1" } }, }; static int test_device_type(enum AVHWDeviceType type)