summaryrefslogtreecommitdiffstats
path: root/contrib/ffmpeg/A13-qsv-dx11.patch
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ffmpeg/A13-qsv-dx11.patch')
-rw-r--r--contrib/ffmpeg/A13-qsv-dx11.patch309
1 files changed, 309 insertions, 0 deletions
diff --git a/contrib/ffmpeg/A13-qsv-dx11.patch b/contrib/ffmpeg/A13-qsv-dx11.patch
new file mode 100644
index 000000000..177f43bb7
--- /dev/null
+++ b/contrib/ffmpeg/A13-qsv-dx11.patch
@@ -0,0 +1,309 @@
+diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
+index 986d4f6022..35879834d8 100644
+--- a/libavcodec/qsv.c
++++ b/libavcodec/qsv.c
+@@ -328,7 +328,7 @@ load_plugin_fail:
+ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
+ const char *load_plugins)
+ {
+- mfxIMPL impl = MFX_IMPL_AUTO_ANY;
++ mfxIMPL impl = MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11;
+ mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
+
+ const char *desc;
+@@ -406,6 +406,7 @@ static AVBufferRef *qsv_create_mids(AVBufferRef *hw_frames_ref)
+ for (i = 0; i < nb_surfaces; i++) {
+ QSVMid *mid = &mids[i];
+ mid->handle = frames_hwctx->surfaces[i].Data.MemId;
++ mid->texture = frames_hwctx->texture;
+ mid->hw_frames_ref = hw_frames_ref1;
+ }
+
+@@ -615,7 +616,14 @@ static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
+ static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
+ {
+ QSVMid *qsv_mid = (QSVMid*)mid;
+- *hdl = qsv_mid->handle;
++
++ if (qsv_mid->texture) {
++ mfxHDLPair *pPair = (mfxHDLPair*)hdl;
++ pPair->first = qsv_mid->texture;
++ pPair->second = qsv_mid->handle;
++ } else {
++ *hdl = qsv_mid->handle;
++ }
+ return MFX_ERR_NONE;
+ }
+
+@@ -624,8 +632,8 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
+ {
+ static const mfxHandleType handle_types[] = {
+ MFX_HANDLE_VA_DISPLAY,
+- MFX_HANDLE_D3D9_DEVICE_MANAGER,
+ MFX_HANDLE_D3D11_DEVICE,
++ MFX_HANDLE_D3D9_DEVICE_MANAGER,
+ };
+ AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref->data;
+ AVQSVDeviceContext *device_hwctx = device_ctx->hwctx;
+diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
+index b63a7d6a31..e8a766d15e 100644
+--- a/libavcodec/qsv_internal.h
++++ b/libavcodec/qsv_internal.h
+@@ -46,6 +46,8 @@ typedef struct QSVMid {
+ AVBufferRef *hw_frames_ref;
+ mfxHDL handle;
+
++ void *texture;
++
+ AVFrame *locked_frame;
+ AVFrame *hw_frame;
+ mfxFrameSurface1 surf;
+diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c
+index 6670c47579..096770b9ce 100644
+--- a/libavutil/hwcontext_d3d11va.c
++++ b/libavutil/hwcontext_d3d11va.c
+@@ -494,12 +494,12 @@ static void d3d11va_device_uninit(AVHWDeviceContext *hwdev)
+ }
+
+ if (device_hwctx->video_device) {
+- ID3D11VideoDevice_Release(device_hwctx->video_device);
++ //ID3D11VideoDevice_Release(device_hwctx->video_device);
+ device_hwctx->video_device = NULL;
+ }
+
+ if (device_hwctx->video_context) {
+- ID3D11VideoContext_Release(device_hwctx->video_context);
++ //ID3D11VideoContext_Release(device_hwctx->video_context);
+ device_hwctx->video_context = NULL;
+ }
+
+@@ -510,6 +510,42 @@ static void d3d11va_device_uninit(AVHWDeviceContext *hwdev)
+ }
+ }
+
++static int d3d11va_device_find_qsv_adapter(AVHWDeviceContext *ctx, UINT creationFlags)
++{
++ HRESULT hr;
++ IDXGIAdapter *pAdapter = NULL;
++ int adapter_id = 0;
++ IDXGIFactory2 *pDXGIFactory;
++ hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory);
++ while (IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter_id++, &pAdapter) != DXGI_ERROR_NOT_FOUND)
++ {
++ ID3D11Device* g_pd3dDevice = NULL;
++ DXGI_ADAPTER_DESC adapterDesc;
++
++ hr = mD3D11CreateDevice(pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, creationFlags, NULL, 0, D3D11_SDK_VERSION, &g_pd3dDevice, NULL, NULL);
++ if (FAILED(hr)) {
++ av_log(ctx, AV_LOG_ERROR, "D3D11CreateDevice returned error\n");
++ continue;
++ }
++
++ hr = IDXGIAdapter2_GetDesc(pAdapter, &adapterDesc);
++ if (FAILED(hr)) {
++ av_log(ctx, AV_LOG_ERROR, "IDXGIAdapter2_GetDesc returned error\n");
++ continue;
++ }
++
++ if (pAdapter)
++ IDXGIAdapter_Release(pAdapter);
++
++ if (adapterDesc.VendorId == 0x8086) {
++ IDXGIFactory2_Release(pDXGIFactory);
++ return adapter_id - 1;
++ }
++ }
++ IDXGIFactory2_Release(pDXGIFactory);
++ return -1;
++}
++
+ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
+ AVDictionary *opts, int flags)
+ {
+@@ -519,7 +555,9 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
+ IDXGIAdapter *pAdapter = NULL;
+ ID3D10Multithread *pMultithread;
+ UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
++ int adapter = -1;
+ int is_debug = !!av_dict_get(opts, "debug", NULL, 0);
++ int is_qsv = !!av_dict_get(opts, "d3d11va_qsv", NULL, 0);
+ int ret;
+
+ // (On UWP we can't check this.)
+@@ -538,11 +576,22 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
+ return AVERROR_UNKNOWN;
+ }
+
++ if (is_qsv) {
++ adapter = d3d11va_device_find_qsv_adapter(ctx, creationFlags);
++ if (adapter < 0) {
++ av_log(ctx, AV_LOG_ERROR, "Failed to find DX11 adapter with QSV support\n");
++ return AVERROR_UNKNOWN;
++ }
++ }
++
+ if (device) {
++ adapter = atoi(device);
++ }
++
++ if (adapter >= 0) {
+ IDXGIFactory2 *pDXGIFactory;
+ hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory);
+ if (SUCCEEDED(hr)) {
+- int adapter = atoi(device);
+ if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter)))
+ pAdapter = NULL;
+ IDXGIFactory2_Release(pDXGIFactory);
+diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
+index 59e4ed9157..56f3ccc94a 100644
+--- a/libavutil/hwcontext_qsv.c
++++ b/libavutil/hwcontext_qsv.c
+@@ -30,6 +30,9 @@
+ #if CONFIG_VAAPI
+ #include "hwcontext_vaapi.h"
+ #endif
++#if CONFIG_D3D11VA
++#include "hwcontext_d3d11va.h"
++#endif
+ #if CONFIG_DXVA2
+ #include "hwcontext_dxva2.h"
+ #endif
+@@ -71,7 +74,7 @@ typedef struct QSVFramesContext {
+ AVBufferRef *child_frames_ref;
+ mfxFrameSurface1 *surfaces_internal;
+ int nb_surfaces_used;
+-
++ void *texture;
+ // used in the frame allocator for non-opaque surfaces
+ mfxMemId *mem_ids;
+ // used in the opaque alloc request for opaque surfaces
+@@ -89,6 +92,9 @@ static const struct {
+ #if CONFIG_VAAPI
+ { MFX_HANDLE_VA_DISPLAY, AV_HWDEVICE_TYPE_VAAPI, AV_PIX_FMT_VAAPI },
+ #endif
++#if CONFIG_D3D11VA
++ { MFX_HANDLE_D3D11_DEVICE, AV_HWDEVICE_TYPE_D3D11VA, AV_PIX_FMT_D3D11 },
++#endif
+ #if CONFIG_DXVA2
+ { MFX_HANDLE_D3D9_DEVICE_MANAGER, AV_HWDEVICE_TYPE_DXVA2, AV_PIX_FMT_DXVA2_VLD },
+ #endif
+@@ -229,6 +235,12 @@ static int qsv_init_child_ctx(AVHWFramesContext *ctx)
+ child_device_hwctx->display = (VADisplay)device_priv->handle;
+ }
+ #endif
++#if CONFIG_D3D11VA
++ if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
++ AVD3D11VADeviceContext *child_device_hwctx = child_device_ctx->hwctx;
++ child_device_hwctx->device = (ID3D11Device*)device_priv->handle;
++ }
++#endif
+ #if CONFIG_DXVA2
+ if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
+ AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx;
+@@ -255,6 +267,15 @@ static int qsv_init_child_ctx(AVHWFramesContext *ctx)
+ child_frames_ctx->width = FFALIGN(ctx->width, 16);
+ child_frames_ctx->height = FFALIGN(ctx->height, 16);
+
++#if CONFIG_D3D11VA
++ if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
++ AVD3D11VAFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
++ if (hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)
++ child_frames_hwctx->BindFlags = D3D11_BIND_RENDER_TARGET ;
++ else
++ child_frames_hwctx->BindFlags = D3D11_BIND_DECODER;
++ }
++#endif
+ #if CONFIG_DXVA2
+ if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
+ AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
+@@ -279,6 +300,18 @@ static int qsv_init_child_ctx(AVHWFramesContext *ctx)
+ hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
+ }
+ #endif
++#if CONFIG_D3D11VA
++ if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
++ AVD3D11VAFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
++ hwctx->texture = child_frames_hwctx->texture;
++ for (i = 0; i < ctx->initial_pool_size; i++)
++ s->surfaces_internal[i].Data.MemId = (mfxMemId)i;
++ if (child_frames_hwctx->BindFlags == D3D11_BIND_DECODER)
++ hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
++ else
++ hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
++ }
++#endif
+ #if CONFIG_DXVA2
+ if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
+ AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
+@@ -1074,7 +1107,7 @@ static void qsv_device_free(AVHWDeviceContext *ctx)
+ av_freep(&priv);
+ }
+
+-static mfxIMPL choose_implementation(const char *device)
++static mfxIMPL choose_implementation(const char *device, enum AVHWDeviceType child_device_type)
+ {
+ static const struct {
+ const char *name;
+@@ -1103,6 +1136,10 @@ static mfxIMPL choose_implementation(const char *device)
+ impl = strtol(device, NULL, 0);
+ }
+
++ if ( (child_device_type == AV_HWDEVICE_TYPE_D3D11VA) && (impl != MFX_IMPL_SOFTWARE) ) {
++ impl |= MFX_IMPL_VIA_D3D11;
++ }
++
+ return impl;
+ }
+
+@@ -1129,6 +1166,15 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx,
+ }
+ break;
+ #endif
++#if CONFIG_D3D11VA
++ case AV_HWDEVICE_TYPE_D3D11VA:
++ {
++ AVD3D11VADeviceContext *child_device_hwctx = child_device_ctx->hwctx;
++ handle_type = MFX_HANDLE_D3D11_DEVICE;
++ handle = (mfxHDL)child_device_hwctx->device;
++ }
++ break;
++#endif
+ #if CONFIG_DXVA2
+ case AV_HWDEVICE_TYPE_DXVA2:
+ {
+@@ -1231,9 +1277,12 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
+ // 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_D3D11VA) {
++ child_device_type = AV_HWDEVICE_TYPE_D3D11VA;
++ av_dict_set(&child_device_opts, "d3d11va_qsv", "enabled", 0);
++ } else if (CONFIG_DXVA2) {
+ child_device_type = AV_HWDEVICE_TYPE_DXVA2;
+- else {
++ } else {
+ av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n");
+ return AVERROR(ENOSYS);
+ }
+@@ -1245,7 +1294,7 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
+
+ child_device = (AVHWDeviceContext*)priv->child_device_ctx->data;
+
+- impl = choose_implementation(device);
++ impl = choose_implementation(device, child_device_type);
+
+ return qsv_device_derive_from_child(ctx, impl, child_device, 0);
+ }
+diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
+index b98d611cfc..f5a9691949 100644
+--- a/libavutil/hwcontext_qsv.h
++++ b/libavutil/hwcontext_qsv.h
+@@ -42,6 +42,7 @@ typedef struct AVQSVDeviceContext {
+ typedef struct AVQSVFramesContext {
+ mfxFrameSurface1 *surfaces;
+ int nb_surfaces;
++ void *texture;
+
+ /**
+ * A combination of MFX_MEMTYPE_* describing the frame pool.