From f1cd1dc6ce72e1d9ba259a946b3c033223f0a4f8 Mon Sep 17 00:00:00 2001 From: Artem Galin Date: Fri, 20 Aug 2021 22:48:04 +0100 Subject: [PATCH] libavutil/hwcontext_qsv: add usage child_device_type argument to explicitly select d3d11va/DX11 device type UPD: Rebase of last patch set over current master and use DX9 as default device type. Makes selection of dxva2/DX9 device type by default as before with explicit d3d11va/DX11 usage to cover more HW configurations. Added warning message to expect changing default device type in the future. Fixes TGL / AV1 decode as requires DX11 with explicit DX11 type selection. Add headless/multi adapter support and fixes: https://trac.ffmpeg.org/ticket/7511 https://trac.ffmpeg.org/ticket/6827 http://ffmpeg.org/pipermail/ffmpeg-trac/2017-November/041901.html https://trac.ffmpeg.org/ticket/7933 https://github.com/InitialForce/FFmpeg/commit/338fbcd5bba1de0e1b3e3bad8985eee2fdfbeca1 https://github.com/jellyfin/jellyfin/issues/2626#issuecomment-602153952 Any other fixes are welcome including OpenCL interop patch since I don't have proper setup to validate this use case Decoding, encoding, transcoding have been validated. child_device_type option is responsible for d3d11va/dxva2 device selection Usage examples: DirectX 11: -init_hw_device qsv:hw,child_device_type=d3d11va -init_hw_device qsv:hw,child_device_type=d3d11va,child_device=0 OR -init_hw_device d3d11va=dx -init_hw_device qsv@dx DirectX 9 is still supported but requires explicit selection: -init_hw_device qsv:hw,child_device_type=dxva2 OR -init_hw_device dxva2=dx -init_hw_device qsv@dx Signed-off-by: Artem Galin --- doc/ffmpeg.texi | 20 ++++++++++++- libavutil/hwcontext_qsv.c | 62 +++++++++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 14 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index c896aede3b..62d9703b7a 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1104,6 +1104,9 @@ device type: @item dxva2 @var{device} is the number of the Direct3D 9 display adapter. +@item d3d11va +@var{device} is the number of the Direct3D 11 display adapter. + @item vaapi @var{device} is either an X11 display name or a DRM render node. If not specified, it will attempt to open the default X11 display (@emph{$DISPLAY}) @@ -1127,9 +1130,21 @@ If not specified, it will attempt to open the default X11 display (@emph{$DISPLA @end table If not specified, @samp{auto_any} is used. (Note that it may be easier to achieve the desired result for QSV by creating the -platform-appropriate subdevice (@samp{dxva2} or @samp{vaapi}) and then deriving a +platform-appropriate subdevice (@samp{dxva2} or @samp{d3d11va} or @samp{vaapi}) and then deriving a QSV device from that.) +Alternatively, @samp{child_device_type} helps to choose platform-appropriate subdevice type. +On Windows @samp{d3d11va} is used as default subdevice type. + +Examples: +@table @emph +@item -init_hw_device qsv:hw,child_device_type=d3d11va +Choose the GPU subdevice with type @samp{d3d11va} and create QSV device with @samp{MFX_IMPL_HARDWARE}. + +@item -init_hw_device qsv:hw,child_device_type=dxva2 +Choose the GPU subdevice with type @samp{dxva2} and create QSV device with @samp{MFX_IMPL_HARDWARE}. +@end table + @item opencl @var{device} selects the platform and device as @emph{platform_index.device_index}. @@ -1232,6 +1247,9 @@ Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration. @item dxva2 Use DXVA2 (DirectX Video Acceleration) hardware acceleration. +@item d3d11va +Use D3D11VA (DirectX Video Acceleration) hardware acceleration. + @item vaapi Use VAAPI (Video Acceleration API) hardware acceleration. diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 0ca805e277..77b540fef9 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -1443,25 +1443,61 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, ctx->user_opaque = priv; ctx->free = qsv_device_free; - e = av_dict_get(opts, "child_device", NULL, 0); - - child_device_opts = NULL; - if (CONFIG_VAAPI) { + e = av_dict_get(opts, "child_device_type", NULL, 0); + if (e) { + child_device_type = av_hwdevice_find_type_by_name(e ? e->value : NULL); + if (child_device_type == AV_HWDEVICE_TYPE_NONE) { + av_log(ctx, AV_LOG_ERROR, "Unknown child device type " + "\"%s\".\n", e ? e->value : NULL); + return AVERROR(EINVAL); + } + } else if (CONFIG_VAAPI) { child_device_type = AV_HWDEVICE_TYPE_VAAPI; - // libmfx does not actually implement VAAPI properly, rather it - // depends on the specific behaviour of a matching iHD driver when - // used on recent Intel hardware. Set options to the VAAPI device - // creation so that we should pick a usable setup by default if - // possible, even when multiple devices and drivers are available. - av_dict_set(&child_device_opts, "kernel_driver", "i915", 0); - av_dict_set(&child_device_opts, "driver", "iHD", 0); - } else if (CONFIG_DXVA2) + } else if (CONFIG_DXVA2) { + av_log(NULL, AV_LOG_WARNING, + "WARNING: defaulting child_device_type to AV_HWDEVICE_TYPE_DXVA2 for compatibility " + "with old commandlines. This behaviour will be removed " + "in the future. Please explicitly set device type via \"-init_hw_device\" option.\n"); child_device_type = AV_HWDEVICE_TYPE_DXVA2; - else { + } else if (CONFIG_D3D11VA) { + child_device_type = AV_HWDEVICE_TYPE_D3D11VA; + } else { av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n"); return AVERROR(ENOSYS); } + child_device_opts = NULL; + switch (child_device_type) { +#if CONFIG_VAAPI + case AV_HWDEVICE_TYPE_VAAPI: + { + // libmfx does not actually implement VAAPI properly, rather it + // depends on the specific behaviour of a matching iHD driver when + // used on recent Intel hardware. Set options to the VAAPI device + // creation so that we should pick a usable setup by default if + // possible, even when multiple devices and drivers are available. + av_dict_set(&child_device_opts, "kernel_driver", "i915", 0); + av_dict_set(&child_device_opts, "driver", "iHD", 0); + } + break; +#endif +#if CONFIG_D3D11VA + case AV_HWDEVICE_TYPE_D3D11VA: + break; +#endif +#if CONFIG_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + break; +#endif + default: + { + av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n"); + return AVERROR(ENOSYS); + } + break; + } + + e = av_dict_get(opts, "child_device", NULL, 0); ret = av_hwdevice_ctx_create(&priv->child_device_ctx, child_device_type, e ? e->value : NULL, child_device_opts, 0);