summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoragalin89 <[email protected]>2020-07-31 05:03:18 -0700
committerBradley Sepos <[email protected]>2020-08-22 17:20:35 -0400
commit350ab4509e124e02cc601cb07260eb9817045836 (patch)
treeff5a19424674b69324345211aac92cee7e795850
parentf51882f39b3143899f10b1485e767bcac8a37890 (diff)
qsv: update dx11 patch for ffmpeg 4.3.1
-rw-r--r--contrib/ffmpeg/A00-qsv-dx11-ffmpeg43.patch1231
-rw-r--r--libhb/cropscale.c5
-rw-r--r--libhb/enc_qsv.c19
-rw-r--r--libhb/handbrake/qsv_common.h2
-rw-r--r--libhb/handbrake/qsv_libav.h4
-rw-r--r--libhb/hbavfilter.c16
-rw-r--r--libhb/qsv_common.c71
7 files changed, 1005 insertions, 343 deletions
diff --git a/contrib/ffmpeg/A00-qsv-dx11-ffmpeg43.patch b/contrib/ffmpeg/A00-qsv-dx11-ffmpeg43.patch
index b92346095..688467d36 100644
--- a/contrib/ffmpeg/A00-qsv-dx11-ffmpeg43.patch
+++ b/contrib/ffmpeg/A00-qsv-dx11-ffmpeg43.patch
@@ -1,161 +1,504 @@
-diff -ur ffmpeg-4.3.orig/fftools/ffmpeg_opt.c ffmpeg-4.3/fftools/ffmpeg_opt.c
---- ffmpeg-4.3.orig/fftools/ffmpeg_opt.c 2020-06-15 14:54:23.000000000 -0400
-+++ ffmpeg-4.3/fftools/ffmpeg_opt.c 2020-07-14 09:17:52.000000000 -0400
-@@ -559,7 +559,17 @@
+diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
+index 2eb4e1c973..c40f3b7450 100644
+--- a/fftools/ffmpeg_opt.c
++++ b/fftools/ffmpeg_opt.c
+@@ -559,7 +559,11 @@ static int opt_init_hw_device(void *optctx, const char *opt, const char *arg)
printf("\n");
exit_program(0);
} else {
- return hw_device_init_from_string(arg, NULL);
-+ HWDevice *dev;
+ int err;
+ if (!arg)
+ return AVERROR(ENOMEM);
-+ err = hw_device_init_from_string(arg, &dev);
-+ if (err < 0)
-+ return err;
-+ hw_device_ctx = av_buffer_ref(dev->device_ref);
-+ if (!hw_device_ctx)
-+ return AVERROR(ENOMEM);
-+ return 0;
++ err = hw_device_init_from_string(arg, NULL);
++ return err;
+ }
+ }
+
+diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
+index 17720070f1..1c9b649c10 100644
+--- a/libavcodec/qsv.c
++++ b/libavcodec/qsv.c
+@@ -36,6 +36,8 @@
+ #include "avcodec.h"
+ #include "qsv_internal.h"
+
++#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
++
+ #if QSV_VERSION_ATLEAST(1, 12)
+ #include "mfx/mfxvp8.h"
+ #endif
+@@ -239,7 +241,9 @@ int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame)
+ int i;
+ for (i = 0; i < ctx->nb_mids; i++) {
+ QSVMid *mid = &ctx->mids[i];
+- if (mid->handle == frame->surface.Data.MemId)
++ mfxHDLPair *pair = (mfxHDLPair*)frame->surface.Data.MemId;
++ if ((mid->handle_pair->first == pair->first) &&
++ (mid->handle_pair->second == pair->second))
+ return i;
+ }
+ return AVERROR_BUG;
+@@ -380,7 +384,11 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
+ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
+ const char *load_plugins, int gpu_copy)
+ {
++#if CONFIG_D3D11VA
++ mfxIMPL impl = MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11;
++#else
+ mfxIMPL impl = MFX_IMPL_AUTO_ANY;
++#endif
+ mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
+ mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
+
+@@ -469,7 +477,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->handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[i].Data.MemId;
+ mid->hw_frames_ref = hw_frames_ref1;
}
+
+@@ -646,7 +654,7 @@ static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
+ goto fail;
+
+ qsv_mid->surf.Info = hw_frames_hwctx->surfaces[0].Info;
+- qsv_mid->surf.Data.MemId = qsv_mid->handle;
++ qsv_mid->surf.Data.MemId = qsv_mid->handle_pair;
+
+ /* map the data to the system memory */
+ ret = av_hwframe_map(qsv_mid->locked_frame, qsv_mid->hw_frame,
+@@ -679,7 +687,13 @@ 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;
++ mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
++ mfxHDLPair *pair_src = (mfxHDLPair*)qsv_mid->handle_pair;
++
++ pair_dst->first = pair_src->first;
++
++ if (pair_src->second != (mfxMemId)MFX_INFINITE)
++ pair_dst->second = pair_src->second;
+ return MFX_ERR_NONE;
}
-Only in ffmpeg-4.3/fftools: ffmpeg_opt.c.orig
-diff -ur ffmpeg-4.3.orig/libavcodec/qsv_internal.h ffmpeg-4.3/libavcodec/qsv_internal.h
---- ffmpeg-4.3.orig/libavcodec/qsv_internal.h 2020-06-15 14:54:24.000000000 -0400
-+++ ffmpeg-4.3/libavcodec/qsv_internal.h 2020-07-14 09:17:52.000000000 -0400
-@@ -65,6 +65,11 @@
+@@ -687,24 +701,19 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
+ AVBufferRef *device_ref, const char *load_plugins,
+ int gpu_copy)
+ {
+- static const mfxHandleType handle_types[] = {
+- MFX_HANDLE_VA_DISPLAY,
+- MFX_HANDLE_D3D9_DEVICE_MANAGER,
+- MFX_HANDLE_D3D11_DEVICE,
+- };
+ AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref->data;
+ AVQSVDeviceContext *device_hwctx = device_ctx->hwctx;
+ mfxSession parent_session = device_hwctx->session;
+ mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
+ mfxHDL handle = NULL;
++ int hw_handle_supported = 0;
+
+ mfxSession session;
+ mfxVersion ver;
+ mfxIMPL impl;
+ mfxHandleType handle_type;
+ mfxStatus err;
+-
+- int i, ret;
++ int ret;
+
+ err = MFXQueryIMPL(parent_session, &impl);
+ if (err == MFX_ERR_NONE)
+@@ -713,13 +722,23 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
+ return ff_qsv_print_error(avctx, err,
+ "Error querying the session attributes");
+
+- for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) {
+- err = MFXVideoCORE_GetHandle(parent_session, handle_types[i], &handle);
+- if (err == MFX_ERR_NONE) {
+- handle_type = handle_types[i];
+- break;
++ if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) {
++ handle_type = MFX_HANDLE_VA_DISPLAY;
++ hw_handle_supported = 1;
++ } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) {
++ handle_type = MFX_HANDLE_D3D11_DEVICE;
++ hw_handle_supported = 1;
++ } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) {
++ handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
++ hw_handle_supported = 1;
++ }
++
++ if (hw_handle_supported) {
++ err = MFXVideoCORE_GetHandle(parent_session, handle_type, &handle);
++ if (err != MFX_ERR_NONE) {
++ return ff_qsv_print_error(avctx, err,
++ "Error getting handle session");
+ }
+- handle = NULL;
+ }
+ if (!handle) {
+ av_log(avctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved "
+diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
+index 6489836a67..1b5f5a5c99 100644
+--- a/libavcodec/qsv_internal.h
++++ b/libavcodec/qsv_internal.h
+@@ -60,7 +60,7 @@
+
+ typedef struct QSVMid {
+ AVBufferRef *hw_frames_ref;
+- mfxHDL handle;
++ mfxHDLPair *handle_pair;
+
AVFrame *locked_frame;
AVFrame *hw_frame;
- mfxFrameSurface1 surf;
-+ /**
-+ * ID3D11Texture2D texture in which the frame is located for D3D11VA device.
-+ * Null in case of DXVA2 device.
-+ */
-+ void *texture;
- } QSVMid;
+diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c
+index 8d5ff2eb65..c89d4180d0 100644
+--- a/libavfilter/qsvvpp.c
++++ b/libavfilter/qsvvpp.c
+@@ -36,6 +36,7 @@
+ MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
+ #define IS_OPAQUE_MEMORY(mode) (mode & MFX_MEMTYPE_OPAQUE_FRAME)
+ #define IS_SYSTEM_MEMORY(mode) (mode & MFX_MEMTYPE_SYSTEM_MEMORY)
++#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
typedef struct QSVFrame {
-Only in ffmpeg-4.3/libavcodec: qsv_internal.h.orig
-diff -ur ffmpeg-4.3.orig/libavfilter/qsvvpp.c ffmpeg-4.3/libavfilter/qsvvpp.c
---- ffmpeg-4.3.orig/libavfilter/qsvvpp.c 2020-05-21 11:55:31.000000000 -0400
-+++ ffmpeg-4.3/libavfilter/qsvvpp.c 2020-07-14 09:17:52.000000000 -0400
-@@ -32,10 +32,11 @@
- #include "qsvvpp.h"
+ AVFrame *frame;
+@@ -68,12 +69,6 @@ struct QSVVPPContext {
+ int nb_ext_buffers;
+ };
+
+-static const mfxHandleType handle_types[] = {
+- MFX_HANDLE_VA_DISPLAY,
+- MFX_HANDLE_D3D9_DEVICE_MANAGER,
+- MFX_HANDLE_D3D11_DEVICE,
+-};
+-
+ static const AVRational default_tb = { 1, 90000 };
+
+ /* functions for frameAlloc */
+@@ -129,7 +124,13 @@ static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
+
+ static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
+ {
+- *hdl = mid;
++ mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
++ mfxHDLPair *pair_src = (mfxHDLPair*)mid;
++
++ pair_dst->first = pair_src->first;
++
++ if (pair_src->second != (mfxMemId)MFX_INFINITE)
++ pair_dst->second = pair_src->second;
+ return MFX_ERR_NONE;
+ }
+
+@@ -451,7 +452,7 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
+
+ s->out_mem_mode = IS_OPAQUE_MEMORY(s->in_mem_mode) ?
+ MFX_MEMTYPE_OPAQUE_FRAME :
+- MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
++ MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
+
+ out_frames_ctx = (AVHWFramesContext *)out_frames_ref->data;
+ out_frames_hwctx = out_frames_ctx->hwctx;
+@@ -497,14 +498,18 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
+ return AVERROR_UNKNOWN;
+ }
+
+- for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) {
+- ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle);
+- if (ret == MFX_ERR_NONE) {
+- handle_type = handle_types[i];
+- break;
+- }
++ if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) {
++ handle_type = MFX_HANDLE_VA_DISPLAY;
++ } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) {
++ handle_type = MFX_HANDLE_D3D11_DEVICE;
++ } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) {
++ handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
++ } else {
++ av_log(avctx, AV_LOG_ERROR, "Error unsupported handle type\n");
++ return AVERROR_UNKNOWN;
+ }
+
++ ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle);
+ if (ret != MFX_ERR_NONE) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting the session handle\n");
+ return AVERROR_UNKNOWN;
+diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c
+index 80217c8419..f7f9d916db 100644
+--- a/libavfilter/vf_deinterlace_qsv.c
++++ b/libavfilter/vf_deinterlace_qsv.c
+@@ -42,6 +42,8 @@
+ #include "internal.h"
#include "video.h"
--#define IS_VIDEO_MEMORY(mode) (mode & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | \
-+#define IS_VIDEO_MEMORY(mode) (mode & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | \
- MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
--#define IS_OPAQUE_MEMORY(mode) (mode & MFX_MEMTYPE_OPAQUE_FRAME)
--#define IS_SYSTEM_MEMORY(mode) (mode & MFX_MEMTYPE_SYSTEM_MEMORY)
-+#define IS_OPAQUE_MEMORY(mode) (mode & MFX_MEMTYPE_OPAQUE_FRAME)
-+#define IS_SYSTEM_MEMORY(mode) (mode & MFX_MEMTYPE_SYSTEM_MEMORY)
+#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
++
+ enum {
+ QSVDEINT_MORE_OUTPUT = 1,
+ QSVDEINT_MORE_INPUT,
+@@ -157,16 +159,16 @@ static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
- typedef struct QSVFrame {
- AVFrame *frame;
-@@ -405,12 +406,12 @@
- AVFilterLink *outlink = avctx->outputs[0];
- AVQSVFramesContext *in_frames_hwctx = NULL;
- AVQSVFramesContext *out_frames_hwctx = NULL;
-+ mfxHandleType handle_type = MFX_IMPL_AUTO;
-
- AVBufferRef *device_ref;
- AVHWDeviceContext *device_ctx;
- AVQSVDeviceContext *device_hwctx;
- mfxHDL handle;
-- mfxHandleType handle_type;
- mfxVersion ver;
+ static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
+ {
+- *hdl = mid;
++ mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
++ mfxHDLPair *pair_src = (mfxHDLPair*)mid;
++
++ pair_dst->first = pair_src->first;
++
++ if (pair_src->second != (mfxMemId)MFX_INFINITE)
++ pair_dst->second = pair_src->second;
+ return MFX_ERR_NONE;
+ }
+
+-static const mfxHandleType handle_types[] = {
+- MFX_HANDLE_VA_DISPLAY,
+- MFX_HANDLE_D3D9_DEVICE_MANAGER,
+- MFX_HANDLE_D3D11_DEVICE,
+-};
+-
+ static int init_out_session(AVFilterContext *ctx)
+ {
+
+@@ -183,26 +185,30 @@ static int init_out_session(AVFilterContext *ctx)
mfxIMPL impl;
- int ret, i;
-@@ -497,15 +498,30 @@
+ mfxVideoParam par;
+ mfxStatus err;
+- int i;
++ int ret, i;
+
+ /* extract the properties of the "master" session given to us */
+- err = MFXQueryIMPL(device_hwctx->session, &impl);
+- if (err == MFX_ERR_NONE)
+- err = MFXQueryVersion(device_hwctx->session, &ver);
+- if (err != MFX_ERR_NONE) {
++ ret = MFXQueryIMPL(device_hwctx->session, &impl);
++ if (ret == MFX_ERR_NONE)
++ ret = MFXQueryVersion(device_hwctx->session, &ver);
++ if (ret != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n");
return AVERROR_UNKNOWN;
}
-+ if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl))
-+ {
+- for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) {
+- err = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle);
+- if (err == MFX_ERR_NONE) {
+- handle_type = handle_types[i];
+- break;
+- }
++ if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) {
++ handle_type = MFX_HANDLE_VA_DISPLAY;
++ } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) {
+ handle_type = MFX_HANDLE_D3D11_DEVICE;
-+ }
-+ else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl))
-+ {
++ } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) {
+ handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
++ } else {
++ av_log(ctx, AV_LOG_ERROR, "Error unsupported handle type\n");
++ return AVERROR_UNKNOWN;
+ }
+
+- if (err != MFX_ERR_NONE) {
++ ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle);
++ if (ret != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error getting the session handle\n");
+ return AVERROR_UNKNOWN;
+ }
+diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c
+index 5064dcbb60..82bb64eb42 100644
+--- a/libavfilter/vf_scale_qsv.c
++++ b/libavfilter/vf_scale_qsv.c
+@@ -70,6 +70,7 @@ enum var_name {
+ };
+
+ #define QSV_HAVE_SCALING_CONFIG QSV_VERSION_ATLEAST(1, 19)
++#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
+
+ typedef struct QSVScaleContext {
+ const AVClass *class;
+@@ -181,7 +182,7 @@ static int init_out_pool(AVFilterContext *ctx,
+ AVQSVFramesContext *out_frames_hwctx;
+ enum AVPixelFormat in_format;
+ enum AVPixelFormat out_format;
+- int i, ret;
++ int i, ret, out_alignment;
+
+ /* check that we have a hw context */
+ if (!ctx->inputs[0]->hw_frames_ctx) {
+@@ -200,13 +201,18 @@ static int init_out_pool(AVFilterContext *ctx,
+ out_frames_ctx = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
+ out_frames_hwctx = out_frames_ctx->hwctx;
+
++ out_alignment = 16;
++ // TODO: select correct alignment for the output frame based on encoder in the pipeline
++ if (ctx->graph->opaque) {
++ out_alignment = (int)ctx->graph->opaque;
+ }
-+ else if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl))
-+ {
-+ handle_type = MFX_HANDLE_VA_DISPLAY;
-+ }
+ out_frames_ctx->format = AV_PIX_FMT_QSV;
+- out_frames_ctx->width = FFALIGN(out_width, 16);
+- out_frames_ctx->height = FFALIGN(out_height, 16);
++ out_frames_ctx->width = FFALIGN(out_width, out_alignment);
++ out_frames_ctx->height = FFALIGN(out_height, out_alignment);
+ out_frames_ctx->sw_format = out_format;
+ out_frames_ctx->initial_pool_size = 4;
+
+- out_frames_hwctx->frame_type = in_frames_hwctx->frame_type;
++ out_frames_hwctx->frame_type = in_frames_hwctx->frame_type | MFX_MEMTYPE_FROM_VPPOUT;
+
+ ret = ff_filter_init_hw_frames(ctx, outlink, 32);
+ if (ret < 0)
+@@ -264,16 +270,16 @@ static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
+
+ static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
+ {
+- *hdl = mid;
++ mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
++ mfxHDLPair *pair_src = (mfxHDLPair*)mid;
+
- for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) {
-- ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle);
-- if (ret == MFX_ERR_NONE) {
++ pair_dst->first = pair_src->first;
++
++ if (pair_src->second != (mfxMemId)MFX_INFINITE)
++ pair_dst->second = pair_src->second;
+ return MFX_ERR_NONE;
+ }
+
+-static const mfxHandleType handle_types[] = {
+- MFX_HANDLE_VA_DISPLAY,
+- MFX_HANDLE_D3D9_DEVICE_MANAGER,
+- MFX_HANDLE_D3D11_DEVICE,
+-};
+-
+ static int init_out_session(AVFilterContext *ctx)
+ {
+
+@@ -292,28 +298,32 @@ static int init_out_session(AVFilterContext *ctx)
+ mfxIMPL impl;
+ mfxVideoParam par;
+ mfxStatus err;
+- int i;
++ int ret, i;
+
+ s->num_ext_buf = 0;
+
+ /* extract the properties of the "master" session given to us */
+- err = MFXQueryIMPL(device_hwctx->session, &impl);
+- if (err == MFX_ERR_NONE)
+- err = MFXQueryVersion(device_hwctx->session, &ver);
+- if (err != MFX_ERR_NONE) {
++ ret = MFXQueryIMPL(device_hwctx->session, &impl);
++ if (ret == MFX_ERR_NONE)
++ ret = MFXQueryVersion(device_hwctx->session, &ver);
++ if (ret != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n");
+ return AVERROR_UNKNOWN;
+ }
+
+- for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) {
+- err = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle);
+- if (err == MFX_ERR_NONE) {
- handle_type = handle_types[i];
- break;
-+ if (handle_types[i] == handle_type)
-+ {
-+ ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle);
-+ if (ret == MFX_ERR_NONE) {
-+ break;
-+ }
- }
-+ handle = NULL;
+- }
++ if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) {
++ handle_type = MFX_HANDLE_VA_DISPLAY;
++ } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) {
++ handle_type = MFX_HANDLE_D3D11_DEVICE;
++ } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) {
++ handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
++ } else {
++ av_log(ctx, AV_LOG_ERROR, "Error unsupported handle type\n");
++ return AVERROR_UNKNOWN;
}
--
-- if (ret != MFX_ERR_NONE) {
-+ if (!handle) {
- av_log(avctx, AV_LOG_ERROR, "Error getting the session handle\n");
+
+- if (err != MFX_ERR_NONE) {
++ ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle);
++ if (ret != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error getting the session handle\n");
return AVERROR_UNKNOWN;
}
-diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_d3d11va.c ffmpeg-4.3/libavutil/hwcontext_d3d11va.c
---- ffmpeg-4.3.orig/libavutil/hwcontext_d3d11va.c 2020-06-15 14:54:24.000000000 -0400
-+++ ffmpeg-4.3/libavutil/hwcontext_d3d11va.c 2020-07-14 09:17:52.000000000 -0400
-@@ -511,15 +511,57 @@
- }
+diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c
+index c8ae58f908..499c6b709b 100644
+--- a/libavutil/hwcontext_d3d11va.c
++++ b/libavutil/hwcontext_d3d11va.c
+@@ -72,7 +72,8 @@ static av_cold void load_functions(void)
}
-+static int d3d11va_device_find_adapter_by_vendor_id(AVHWDeviceContext *ctx, UINT creationFlags, char *vendor)
-+{
-+ HRESULT hr;
-+ IDXGIAdapter *adapter = NULL;
-+ int adapter_id = 0;
-+ IDXGIFactory2 *factory;
-+ long int vendor_id = strtol(vendor, NULL, 0);
-+ hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&factory);
-+ while (IDXGIFactory2_EnumAdapters(factory, adapter_id++, &adapter) != DXGI_ERROR_NOT_FOUND)
-+ {
-+ ID3D11Device* device = NULL;
-+ DXGI_ADAPTER_DESC adapter_desc;
-+
-+ hr = mD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, creationFlags, NULL, 0, D3D11_SDK_VERSION, &device, NULL, NULL);
-+ if (FAILED(hr)) {
-+ av_log(ctx, AV_LOG_ERROR, "D3D11CreateDevice returned error\n");
-+ continue;
-+ }
+ typedef struct D3D11VAFramesContext {
+- int nb_surfaces_used;
++ size_t nb_surfaces;
++ size_t nb_surfaces_used;
+
+ DXGI_FORMAT format;
+
+@@ -112,6 +113,8 @@ static void d3d11va_frames_uninit(AVHWFramesContext *ctx)
+ if (s->staging_texture)
+ ID3D11Texture2D_Release(s->staging_texture);
+ s->staging_texture = NULL;
+
-+ hr = IDXGIAdapter2_GetDesc(adapter, &adapter_desc);
-+ if (FAILED(hr)) {
-+ av_log(ctx, AV_LOG_ERROR, "IDXGIAdapter2_GetDesc returned error\n");
-+ continue;
-+ }
++ av_freep(&frames_hwctx->texture_infos);
+ }
+
+ static int d3d11va_frames_get_constraints(AVHWDeviceContext *ctx,
+@@ -152,8 +155,11 @@ static void free_texture(void *opaque, uint8_t *data)
+ av_free(data);
+ }
+
+-static AVBufferRef *wrap_texture_buf(ID3D11Texture2D *tex, int index)
++static AVBufferRef *wrap_texture_buf(AVHWFramesContext *ctx, ID3D11Texture2D *tex, int index)
+ {
++ D3D11VAFramesContext *s = ctx->internal->priv;
++ AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
+
-+ if (device)
-+ ID3D11Device_Release(device);
+ AVBufferRef *buf;
+ AVD3D11FrameDescriptor *desc = av_mallocz(sizeof(*desc));
+ if (!desc) {
+@@ -161,6 +167,10 @@ static AVBufferRef *wrap_texture_buf(ID3D11Texture2D *tex, int index)
+ return NULL;
+ }
+
++ frames_hwctx->texture_infos[s->nb_surfaces_used].texture = tex;
++ frames_hwctx->texture_infos[s->nb_surfaces_used].index = index;
++ s->nb_surfaces_used++;
+
-+ if (adapter)
-+ IDXGIAdapter_Release(adapter);
+ desc->texture = tex;
+ desc->index = index;
+
+@@ -199,7 +209,7 @@ static AVBufferRef *d3d11va_alloc_single(AVHWFramesContext *ctx)
+ return NULL;
+ }
+
+- return wrap_texture_buf(tex, 0);
++ return wrap_texture_buf(ctx, tex, 0);
+ }
+
+ static AVBufferRef *d3d11va_pool_alloc(void *opaque, int size)
+@@ -220,7 +230,7 @@ static AVBufferRef *d3d11va_pool_alloc(void *opaque, int size)
+ }
+
+ ID3D11Texture2D_AddRef(hwctx->texture);
+- return wrap_texture_buf(hwctx->texture, s->nb_surfaces_used++);
++ return wrap_texture_buf(ctx, hwctx->texture, s->nb_surfaces_used);
+ }
+
+ static int d3d11va_frames_init(AVHWFramesContext *ctx)
+@@ -275,6 +285,12 @@ static int d3d11va_frames_init(AVHWFramesContext *ctx)
+ }
+ }
+
++ hwctx->texture_infos = av_mallocz_array(ctx->initial_pool_size, sizeof(*hwctx->texture_infos));
++ if (!hwctx->texture_infos)
++ return AVERROR(ENOMEM);
+
-+ if (adapter_desc.VendorId == vendor_id) {
-+ IDXGIFactory2_Release(factory);
-+ return adapter_id - 1;
-+ }
-+ }
-+ IDXGIFactory2_Release(factory);
-+ return -1;
-+}
++ s->nb_surfaces = ctx->initial_pool_size;
+
- static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
- AVDictionary *opts, int flags)
- {
+ ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor),
+ ctx, d3d11va_pool_alloc, NULL);
+ if (!ctx->internal->pool_internal)
+@@ -517,9 +533,12 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
HRESULT hr;
@@ -164,38 +507,82 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_d3d11va.c ffmpeg-4.3/libavutil/hwco
ID3D10Multithread *pMultithread;
UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
+ int adapter = -1;
++ long int vendor_id = -1;
int is_debug = !!av_dict_get(opts, "debug", NULL, 0);
int ret;
-@@ -539,11 +581,23 @@
+@@ -539,13 +558,45 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
return AVERROR_UNKNOWN;
}
+ e = av_dict_get(opts, "vendor", NULL, 0);
+ if (e) {
-+ adapter = d3d11va_device_find_adapter_by_vendor_id(ctx, creationFlags, e ? e->value : NULL);
-+ if (adapter < 0) {
-+ av_log(ctx, AV_LOG_ERROR, "Failed to find d3d11va adapter by vendor id\n");
-+ return AVERROR_UNKNOWN;
-+ }
++ vendor_id = strtol(e->value, NULL, 0);
+ }
+
if (device) {
+ adapter = atoi(device);
+ }
+
-+ if (adapter >= 0) {
++ if (adapter >= 0 || vendor_id != -1) {
IDXGIFactory2 *pDXGIFactory;
hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory);
if (SUCCEEDED(hr)) {
- int adapter = atoi(device);
- if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter)))
+- if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter)))
++ if (adapter < 0) {
++ int adapter_cnt = 0;
++ while (IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter_cnt++, &pAdapter) != DXGI_ERROR_NOT_FOUND) {
++ DXGI_ADAPTER_DESC adapter_desc;
++ hr = IDXGIAdapter2_GetDesc(pAdapter, &adapter_desc);
++ if (FAILED(hr)) {
++ av_log(ctx, AV_LOG_ERROR, "IDXGIAdapter2_GetDesc returned error with adapter id %d\n", adapter_cnt);
++ continue;
++ }
++
++ if (adapter_desc.VendorId == vendor_id) {
++ break;
++ }
++
++ if (adapter)
++ IDXGIAdapter_Release(pAdapter);
++ }
++ if (adapter_cnt < 0) {
++ av_log(ctx, AV_LOG_ERROR, "Failed to find d3d11va adapter by vendor id %ld\n", vendor_id);
++ IDXGIFactory2_Release(pDXGIFactory);
++ return AVERROR_UNKNOWN;
++ }
++ } else {
++ if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter)))
pAdapter = NULL;
++ }
IDXGIFactory2_Release(pDXGIFactory);
-Only in ffmpeg-4.3/libavutil: hwcontext_d3d11va.c.orig
-diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontext_qsv.c
---- ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c 2020-06-15 14:54:24.000000000 -0400
-+++ ffmpeg-4.3/libavutil/hwcontext_qsv.c 2020-07-14 09:17:52.000000000 -0400
+ }
+ }
+diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
+index 9f91e9b1b6..295bdcd90d 100644
+--- a/libavutil/hwcontext_d3d11va.h
++++ b/libavutil/hwcontext_d3d11va.h
+@@ -164,6 +164,15 @@ typedef struct AVD3D11VAFramesContext {
+ * This field is ignored/invalid if a user-allocated texture is provided.
+ */
+ UINT MiscFlags;
++
++ /**
++ * In case if texture structure member above is not NULL contains the same texture
++ * pointer for all elements and different indexes into the array texture.
++ * In case if texture structure member above is NULL, all elements contains
++ * pointers to separate non-array textures and 0 indexes.
++ * This field is ignored/invalid if a user-allocated texture is provided.
++ */
++ AVD3D11FrameDescriptor *texture_infos;
+ } AVD3D11VAFramesContext;
+
+ #endif /* AVUTIL_HWCONTEXT_D3D11VA_H */
+diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
+index 35a944f8f8..7d04f909fb 100644
+--- a/libavutil/hwcontext_qsv.c
++++ b/libavutil/hwcontext_qsv.c
@@ -27,9 +27,13 @@
#include <pthread.h>
#endif
@@ -219,25 +606,68 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
typedef struct QSVDevicePriv {
AVBufferRef *child_device_ctx;
} QSVDevicePriv;
-@@ -93,6 +99,9 @@
- #if CONFIG_VAAPI
- { MFX_HANDLE_VA_DISPLAY, AV_HWDEVICE_TYPE_VAAPI, AV_PIX_FMT_VAAPI },
- #endif
+@@ -74,6 +80,7 @@ typedef struct QSVFramesContext {
+
+ AVBufferRef *child_frames_ref;
+ mfxFrameSurface1 *surfaces_internal;
++ mfxHDLPair *handle_pairs_internal;
+ int nb_surfaces_used;
+
+ // used in the frame allocator for non-opaque surfaces
+@@ -85,20 +92,6 @@ typedef struct QSVFramesContext {
+ mfxExtBuffer *ext_buffers[1];
+ } QSVFramesContext;
+
+-static const struct {
+- mfxHandleType handle_type;
+- enum AVHWDeviceType device_type;
+- enum AVPixelFormat pix_fmt;
+-} supported_handle_types[] = {
+-#if CONFIG_VAAPI
+- { MFX_HANDLE_VA_DISPLAY, AV_HWDEVICE_TYPE_VAAPI, AV_PIX_FMT_VAAPI },
+-#endif
+-#if CONFIG_DXVA2
+- { MFX_HANDLE_D3D9_DEVICE_MANAGER, AV_HWDEVICE_TYPE_DXVA2, AV_PIX_FMT_DXVA2_VLD },
+-#endif
+- { 0 },
+-};
+-
+ static const struct {
+ enum AVPixelFormat pix_fmt;
+ uint32_t fourcc;
+@@ -127,28 +120,32 @@ static uint32_t qsv_fourcc_from_pix_fmt(enum AVPixelFormat pix_fmt)
+ return 0;
+ }
+
+#if CONFIG_D3D11VA
-+ { MFX_HANDLE_D3D11_DEVICE, AV_HWDEVICE_TYPE_D3D11VA, AV_PIX_FMT_D3D11 },
++static uint32_t qsv_get_d3d11va_bind_flags(int mem_type)
++{
++ uint32_t bind_flags = 0;
++
++ if ((mem_type & MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET) && (mem_type & MFX_MEMTYPE_INTERNAL_FRAME))
++ bind_flags = D3D11_BIND_DECODER | D3D11_BIND_VIDEO_ENCODER;
++ else
++ bind_flags = D3D11_BIND_DECODER;
++
++ if ((MFX_MEMTYPE_FROM_VPPOUT & mem_type) || (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & mem_type))
++ bind_flags = D3D11_BIND_RENDER_TARGET;
++
++ return bind_flags;
++}
+#endif
- #if CONFIG_DXVA2
- { MFX_HANDLE_D3D9_DEVICE_MANAGER, AV_HWDEVICE_TYPE_DXVA2, AV_PIX_FMT_DXVA2_VLD },
- #endif
-@@ -131,25 +140,11 @@
++
+ static int qsv_device_init(AVHWDeviceContext *ctx)
{
AVQSVDeviceContext *hwctx = ctx->hwctx;
QSVDeviceContext *s = ctx->internal->priv;
-+ mfxHandleType handle_type = MFX_IMPL_AUTO;
-
+-
++ int hw_handle_supported = 0;
++ mfxHandleType handle_type;
++ enum AVHWDeviceType device_type;
++ enum AVPixelFormat pix_fmt;
mfxStatus err;
- int i;
-
+- int i;
+-
- for (i = 0; supported_handle_types[i].handle_type; i++) {
- err = MFXVideoCORE_GetHandle(hwctx->session, supported_handle_types[i].handle_type,
- &s->handle);
@@ -252,55 +682,69 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
- av_log(ctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved "
- "from the session\n");
- }
--
+
err = MFXQueryIMPL(hwctx->session, &s->impl);
if (err == MFX_ERR_NONE)
- err = MFXQueryVersion(hwctx->session, &s->ver);
-@@ -158,6 +153,36 @@
+@@ -158,6 +155,41 @@ static int qsv_device_init(AVHWDeviceContext *ctx)
return AVERROR_UNKNOWN;
}
-+ if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(s->impl))
-+ {
++ if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(s->impl)) {
++#if CONFIG_VAAPI
++ handle_type = MFX_HANDLE_VA_DISPLAY;
++ device_type = AV_HWDEVICE_TYPE_VAAPI;
++ pix_fmt = AV_PIX_FMT_VAAPI;
++ hw_handle_supported = 1;
++#endif
++ } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(s->impl)) {
++#if CONFIG_D3D11VA
+ handle_type = MFX_HANDLE_D3D11_DEVICE;
-+ }
-+ else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(s->impl))
-+ {
++ device_type = AV_HWDEVICE_TYPE_D3D11VA;
++ pix_fmt = AV_PIX_FMT_D3D11;
++ hw_handle_supported = 1;
++#endif
++ } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(s->impl)) {
++#if CONFIG_DXVA2
+ handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
-+ }
-+ else if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(s->impl))
-+ {
-+ handle_type = MFX_HANDLE_VA_DISPLAY;
++ device_type = AV_HWDEVICE_TYPE_DXVA2;
++ pix_fmt = AV_PIX_FMT_DXVA2_VLD;
++ hw_handle_supported = 1;
++#endif
+ }
+
-+ for (i = 0; supported_handle_types[i].handle_type; i++) {
-+ if (supported_handle_types[i].handle_type == handle_type) {
-+ err = MFXVideoCORE_GetHandle(hwctx->session, supported_handle_types[i].handle_type,
-+ &s->handle);
-+ if (err == MFX_ERR_NONE) {
-+ s->handle_type = supported_handle_types[i].handle_type;
-+ s->child_device_type = supported_handle_types[i].device_type;
-+ s->child_pix_fmt = supported_handle_types[i].pix_fmt;
-+ break;
-+ }
++ if (hw_handle_supported) {
++ err = MFXVideoCORE_GetHandle(hwctx->session, handle_type, &s->handle);
++ if (err == MFX_ERR_NONE) {
++ s->handle_type = handle_type;
++ s->child_device_type = device_type;
++ s->child_pix_fmt = pix_fmt;
+ }
+ }
+ if (!s->handle) {
+ av_log(ctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved "
+ "from the session\n");
+ }
-+
return 0;
}
-@@ -234,13 +259,19 @@
- if (!child_device_ref)
- return AVERROR(ENOMEM);
- child_device_ctx = (AVHWDeviceContext*)child_device_ref->data;
--
- #if CONFIG_VAAPI
- if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) {
- AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx;
+@@ -187,6 +219,7 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx)
+ av_freep(&s->mem_ids);
+ av_freep(&s->surface_ptrs);
+ av_freep(&s->surfaces_internal);
++ av_freep(&s->handle_pairs_internal);
+ av_buffer_unref(&s->child_frames_ref);
+ }
+
+@@ -202,6 +235,8 @@ static AVBufferRef *qsv_pool_alloc(void *opaque, int size)
+
+ if (s->nb_surfaces_used < hwctx->nb_surfaces) {
+ s->nb_surfaces_used++;
++ av_buffer_create((uint8_t*)(s->handle_pairs_internal + s->nb_surfaces_used - 1),
++ sizeof(*s->handle_pairs_internal), qsv_pool_release_dummy, NULL, 0);
+ return av_buffer_create((uint8_t*)(s->surfaces_internal + s->nb_surfaces_used - 1),
+ sizeof(*hwctx->surfaces), qsv_pool_release_dummy, NULL, 0);
+ }
+@@ -241,6 +276,13 @@ static int qsv_init_child_ctx(AVHWFramesContext *ctx)
child_device_hwctx->display = (VADisplay)device_priv->handle;
}
#endif
@@ -314,73 +758,233 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
#if CONFIG_DXVA2
if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx;
-@@ -267,6 +298,16 @@
+@@ -267,6 +309,16 @@ 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;
-+ child_frames_hwctx->MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
-+ 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;
++ if (hwctx->frame_type == 0)
++ hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
++ if (hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
++ child_frames_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
++ child_frames_hwctx->BindFlags = qsv_get_d3d11va_bind_flags(hwctx->frame_type);
+ }
+#endif
#if CONFIG_DXVA2
if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
-@@ -291,6 +332,18 @@
+@@ -286,16 +338,41 @@ static int qsv_init_child_ctx(AVHWFramesContext *ctx)
+ #if CONFIG_VAAPI
+ if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) {
+ AVVAAPIFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
+- for (i = 0; i < ctx->initial_pool_size; i++)
+- s->surfaces_internal[i].Data.MemId = child_frames_hwctx->surface_ids + i;
++ for (i = 0; i < ctx->initial_pool_size; i++) {
++ s->handle_pairs_internal[i].first = child_frames_hwctx->surface_ids + i;
++ s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
++ s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
++ }
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)(int64_t)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;
++ for (i = 0; i < ctx->initial_pool_size; i++) {
++ s->handle_pairs_internal[i].first = (mfxMemId)child_frames_hwctx->texture_infos[i].texture;
++ if(child_frames_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
++ s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
++ } else {
++ s->handle_pairs_internal[i].second = (mfxMemId)child_frames_hwctx->texture_infos[i].index;
++ }
++ s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
++ }
++ if (child_frames_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
++ hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
++ } else {
++ hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
++ }
+ }
+#endif
#if CONFIG_DXVA2
if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
-@@ -433,7 +486,16 @@
+- for (i = 0; i < ctx->initial_pool_size; i++)
+- s->surfaces_internal[i].Data.MemId = (mfxMemId)child_frames_hwctx->surfaces[i];
++ for (i = 0; i < ctx->initial_pool_size; i++) {
++ s->handle_pairs_internal[i].first = (mfxMemId)child_frames_hwctx->surfaces[i];
++ s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
++ s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
++ }
+ if (child_frames_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget)
+ hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
+ else
+@@ -360,6 +437,11 @@ static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc)
+ return AVERROR(EINVAL);
+ }
+
++ s->handle_pairs_internal = av_mallocz_array(ctx->initial_pool_size,
++ sizeof(*s->handle_pairs_internal));
++ if (!s->handle_pairs_internal)
++ return AVERROR(ENOMEM);
++
+ s->surfaces_internal = av_mallocz_array(ctx->initial_pool_size,
+ sizeof(*s->surfaces_internal));
+ if (!s->surfaces_internal)
+@@ -433,7 +515,13 @@ static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
{
- *hdl = mid;
-+ AVHWFramesContext *ctx = pthis;
-+ AVQSVFramesContext *hwctx = ctx->hwctx;
++ mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
++ mfxHDLPair *pair_src = (mfxHDLPair*)mid;
+
-+ if (hwctx->texture) {
-+ mfxHDLPair *pair = (mfxHDLPair*)hdl;
-+ pair->first = hwctx->texture;
-+ pair->second = mid;
-+ } else {
-+ *hdl = mid;
-+ }
++ pair_dst->first = pair_src->first;
++
++ if (pair_src->second != (mfxMemId)MFX_INFINITE)
++ pair_dst->second = pair_src->second;
return MFX_ERR_NONE;
}
-@@ -680,6 +742,11 @@
- child_data = (uint8_t*)(intptr_t)*(VASurfaceID*)surf->Data.MemId;
+@@ -626,13 +714,26 @@ static int qsv_frames_derive_from(AVHWFramesContext *dst_ctx,
+ sizeof(*dst_hwctx->surface_ids));
+ if (!dst_hwctx->surface_ids)
+ return AVERROR(ENOMEM);
+- for (i = 0; i < src_hwctx->nb_surfaces; i++)
+- dst_hwctx->surface_ids[i] =
+- *(VASurfaceID*)src_hwctx->surfaces[i].Data.MemId;
++ for (i = 0; i < src_hwctx->nb_surfaces; i++) {
++ mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->surfaces[i].Data.MemId;
++ dst_hwctx->surface_ids[i] = *(VASurfaceID*)pair->first;
++ }
+ dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
+ }
break;
#endif
+#if CONFIG_D3D11VA
+ case AV_HWDEVICE_TYPE_D3D11VA:
-+ child_data = surf->Data.MemId;
++ {
++ AVD3D11VAFramesContext *dst_hwctx = dst_ctx->hwctx;
++ mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->surfaces[i].Data.MemId;
++ dst_hwctx->texture = (ID3D11Texture2D*)pair->first;
++ if (src_hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
++ dst_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
++ dst_hwctx->BindFlags = qsv_get_d3d11va_bind_flags(src_hwctx->frame_type);
++ }
+ break;
+#endif
#if CONFIG_DXVA2
case AV_HWDEVICE_TYPE_DXVA2:
- child_data = surf->Data.MemId;
-@@ -996,6 +1063,27 @@
+ {
+@@ -641,9 +742,10 @@ static int qsv_frames_derive_from(AVHWFramesContext *dst_ctx,
+ sizeof(*dst_hwctx->surfaces));
+ if (!dst_hwctx->surfaces)
+ return AVERROR(ENOMEM);
+- for (i = 0; i < src_hwctx->nb_surfaces; i++)
+- dst_hwctx->surfaces[i] =
+- (IDirect3DSurface9*)src_hwctx->surfaces[i].Data.MemId;
++ for (i = 0; i < src_hwctx->nb_surfaces; i++) {
++ mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->surfaces[i].Data.MemId;
++ dst_hwctx->surfaces[i] = (IDirect3DSurface9*)pair->first;
++ }
+ dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
+ if (src_hwctx->frame_type == MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
+ dst_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
+@@ -677,13 +779,27 @@ static int qsv_map_from(AVHWFramesContext *ctx,
+ switch (child_frames_ctx->device_ctx->type) {
+ #if CONFIG_VAAPI
+ case AV_HWDEVICE_TYPE_VAAPI:
+- child_data = (uint8_t*)(intptr_t)*(VASurfaceID*)surf->Data.MemId;
++ {
++ mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
++ child_data = pair->first;
+ break;
++ }
++#endif
++#if CONFIG_D3D11VA
++ case AV_HWDEVICE_TYPE_D3D11VA:
++ {
++ mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
++ child_data = pair->first;
++ break;
++ }
+ #endif
+ #if CONFIG_DXVA2
+ case AV_HWDEVICE_TYPE_DXVA2:
+- child_data = surf->Data.MemId;
++ {
++ mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
++ child_data = pair->first;
+ break;
++ }
+ #endif
+ default:
+ return AVERROR(ENOSYS);
+@@ -697,7 +813,14 @@ static int qsv_map_from(AVHWFramesContext *ctx,
+
+ dst->width = src->width;
+ dst->height = src->height;
+- dst->data[3] = child_data;
++
++ if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
++ mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
++ dst->data[0] = pair->first;
++ dst->data[1] = pair->second;
++ } else {
++ dst->data[3] = child_data;
++ }
+
+ return 0;
+ }
+@@ -720,7 +843,14 @@ static int qsv_map_from(AVHWFramesContext *ctx,
+ dummy->format = child_frames_ctx->format;
+ dummy->width = src->width;
+ dummy->height = src->height;
+- dummy->data[3] = child_data;
++
++ if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
++ mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
++ dummy->data[0] = pair->first;
++ dummy->data[1] = pair->second;
++ } else {
++ dummy->data[3] = child_data;
++ }
+
+ ret = av_hwframe_map(dst, dummy, flags);
+
+@@ -978,35 +1108,81 @@ static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx,
+ AVQSVFramesContext *dst_hwctx = dst_ctx->hwctx;
+ int i;
+
++ if (src_ctx->initial_pool_size == 0) {
++ av_log(dst_ctx, AV_LOG_ERROR, "Only fixed-size pools can be "
++ "mapped to QSV frames.\n");
++ return AVERROR(EINVAL);
++ }
++
+ switch (src_ctx->device_ctx->type) {
+ #if CONFIG_VAAPI
+ case AV_HWDEVICE_TYPE_VAAPI:
+ {
+ AVVAAPIFramesContext *src_hwctx = src_ctx->hwctx;
++ s->handle_pairs_internal = av_mallocz_array(src_ctx->initial_pool_size, sizeof(*s->handle_pairs_internal));
++ if (!s->handle_pairs_internal)
++ return AVERROR(ENOMEM);
+ s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces,
+ sizeof(*s->surfaces_internal));
+ if (!s->surfaces_internal)
+ return AVERROR(ENOMEM);
+ for (i = 0; i < src_hwctx->nb_surfaces; i++) {
+ qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
+- s->surfaces_internal[i].Data.MemId = src_hwctx->surface_ids + i;
++ s->handle_pairs_internal[i].first = src_hwctx->surface_ids + i;
++ s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
++ s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
+ }
+ dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
+ dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
}
break;
#endif
@@ -388,60 +992,116 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
+ case AV_HWDEVICE_TYPE_D3D11VA:
+ {
+ AVD3D11VAFramesContext *src_hwctx = src_ctx->hwctx;
++ s->handle_pairs_internal = av_mallocz_array(src_ctx->initial_pool_size, sizeof(*s->handle_pairs_internal));
++ if (!s->handle_pairs_internal)
++ return AVERROR(ENOMEM);
+ s->surfaces_internal = av_mallocz_array(src_ctx->initial_pool_size,
+ sizeof(*s->surfaces_internal));
+ if (!s->surfaces_internal)
+ return AVERROR(ENOMEM);
-+ dst_hwctx->texture = src_hwctx->texture;
+ for (i = 0; i < src_ctx->initial_pool_size; i++) {
+ qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
-+ s->surfaces_internal[i].Data.MemId = (mfxMemId)(int64_t)i;
++ s->handle_pairs_internal[i].first = (mfxMemId)src_hwctx->texture_infos[i].texture;
++ if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
++ s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
++ } else {
++ s->handle_pairs_internal[i].second = (mfxMemId)src_hwctx->texture_infos[i].index;
++ }
++ s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
+ }
+ dst_hwctx->nb_surfaces = src_ctx->initial_pool_size;
-+ if (src_hwctx->BindFlags == D3D11_BIND_DECODER)
-+ dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
-+ else
-+ dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
++ if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
++ dst_hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
++ } else {
++ dst_hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
++ }
+ }
+ break;
+#endif
#if CONFIG_DXVA2
case AV_HWDEVICE_TYPE_DXVA2:
{
-@@ -1033,14 +1121,26 @@
+ AVDXVA2FramesContext *src_hwctx = src_ctx->hwctx;
++ s->handle_pairs_internal = av_mallocz_array(src_ctx->initial_pool_size, sizeof(*s->handle_pairs_internal));
++ if (!s->handle_pairs_internal)
++ return AVERROR(ENOMEM);
+ s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces,
+ sizeof(*s->surfaces_internal));
+ if (!s->surfaces_internal)
+ return AVERROR(ENOMEM);
+ for (i = 0; i < src_hwctx->nb_surfaces; i++) {
+ qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
+- s->surfaces_internal[i].Data.MemId = (mfxMemId)src_hwctx->surfaces[i];
++ s->handle_pairs_internal[i].first = (mfxMemId)src_hwctx->surfaces[i];
++ s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
++ s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
+ }
+ dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
+ if (src_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget)
+@@ -1029,21 +1205,44 @@ static int qsv_map_to(AVHWFramesContext *dst_ctx,
+ AVFrame *dst, const AVFrame *src, int flags)
+ {
+ AVQSVFramesContext *hwctx = dst_ctx->hwctx;
+- int i, err;
++ int i, err, index = -1;
- for (i = 0; i < hwctx->nb_surfaces; i++) {
+- for (i = 0; i < hwctx->nb_surfaces; i++) {
++ for (i = 0; i < hwctx->nb_surfaces && index < 0; i++) {
++ switch(src->format) {
#if CONFIG_VAAPI
- if (*(VASurfaceID*)hwctx->surfaces[i].Data.MemId ==
- (VASurfaceID)(uintptr_t)src->data[3])
- break;
-+ if (AV_PIX_FMT_VAAPI == src->format) {
-+ if (*(VASurfaceID*)hwctx->surfaces[i].Data.MemId ==
-+ (VASurfaceID)(uintptr_t)src->data[3])
++ case AV_PIX_FMT_VAAPI:
++ {
++ mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId;
++ if (pair->first == src->data[3]) {
++ index = i;
+ break;
++ }
+ }
+#endif
+#if CONFIG_D3D11VA
-+ if (AV_PIX_FMT_D3D11 == src->format) {
-+ if ((hwctx->texture == (ID3D11Texture2D*)(uintptr_t)src->data[0]) &&
-+ ((ID3D11Texture2D*)hwctx->surfaces[i].Data.MemId ==
-+ (ID3D11Texture2D*)(uintptr_t)src->data[1]))
++ case AV_PIX_FMT_D3D11:
++ {
++ mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId;
++ if (pair->first == src->data[0]
++ && pair->second == src->data[1]) {
++ index = i;
+ break;
++ }
+ }
#endif
#if CONFIG_DXVA2
- if ((IDirect3DSurface9*)hwctx->surfaces[i].Data.MemId ==
- (IDirect3DSurface9*)(uintptr_t)src->data[3])
- break;
-+ if (AV_PIX_FMT_DXVA2_VLD == src->format) {
-+ if ((IDirect3DSurface9*)hwctx->surfaces[i].Data.MemId ==
-+ (IDirect3DSurface9*)(uintptr_t)src->data[3])
++ case AV_PIX_FMT_DXVA2_VLD:
++ {
++ mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId;
++ if (pair->first == src->data[3]) {
++ index = i;
+ break;
++ }
+ }
#endif
++ }
}
- if (i >= hwctx->nb_surfaces) {
-@@ -1098,7 +1198,7 @@
+- if (i >= hwctx->nb_surfaces) {
++ if (index < 0) {
+ av_log(dst_ctx, AV_LOG_ERROR, "Trying to map from a surface which "
+ "is not in the mapped frames context.\n");
+ return AVERROR(EINVAL);
+@@ -1056,7 +1255,7 @@ static int qsv_map_to(AVHWFramesContext *dst_ctx,
+
+ dst->width = src->width;
+ dst->height = src->height;
+- dst->data[3] = (uint8_t*)&hwctx->surfaces[i];
++ dst->data[3] = (uint8_t*)&hwctx->surfaces[index];
+
+ return 0;
+ }
+@@ -1098,7 +1297,7 @@ static void qsv_device_free(AVHWDeviceContext *ctx)
av_freep(&priv);
}
@@ -450,7 +1110,7 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
{
static const struct {
const char *name;
-@@ -1127,6 +1227,10 @@
+@@ -1127,6 +1326,10 @@ static mfxIMPL choose_implementation(const char *device)
impl = strtol(device, NULL, 0);
}
@@ -461,7 +1121,7 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
return impl;
}
-@@ -1153,6 +1257,15 @@
+@@ -1153,6 +1356,15 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx,
}
break;
#endif
@@ -477,37 +1137,59 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
#if CONFIG_DXVA2
case AV_HWDEVICE_TYPE_DXVA2:
{
-@@ -1216,8 +1329,10 @@
+@@ -1216,10 +1428,16 @@ static int qsv_device_derive(AVHWDeviceContext *ctx,
AVHWDeviceContext *child_device_ctx,
AVDictionary *opts, int flags)
{
- return qsv_device_derive_from_child(ctx, MFX_IMPL_HARDWARE_ANY,
-- child_device_ctx, flags);
+ mfxIMPL impl;
+ impl = choose_implementation("hw_any", child_device_ctx->type);
+ return qsv_device_derive_from_child(ctx, impl,
-+ child_device_ctx, flags);
+ child_device_ctx, flags);
}
++// TODO: fix global, need to pass somehow child device type
++// Mix of device types
++enum AVHWDeviceType g_child_device_type = AV_HWDEVICE_TYPE_NONE;
++
static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
-@@ -1239,25 +1354,63 @@
+ AVDictionary *opts, int flags)
+ {
+@@ -1239,35 +1457,79 @@ 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);
++ if(g_child_device_type == AV_HWDEVICE_TYPE_NONE)
++ {
++ 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;
++ } else if (CONFIG_D3D11VA) {
++ child_device_type = AV_HWDEVICE_TYPE_D3D11VA;
++ } else if (CONFIG_DXVA2) {
++ child_device_type = AV_HWDEVICE_TYPE_DXVA2;
++ } else {
++ av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n");
++ return AVERROR(ENOSYS);
+ }
-+ } else if (CONFIG_VAAPI) {
- child_device_type = AV_HWDEVICE_TYPE_VAAPI;
++ }
++ else
++ {
++ child_device_type = g_child_device_type;
++ }
++ g_child_device_type = child_device_type;
+
+ child_device_opts = NULL;
+- 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
@@ -516,17 +1198,10 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
- 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) {
- child_device_type = AV_HWDEVICE_TYPE_DXVA2;
+- 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;
+- av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n");
+- return AVERROR(ENOSYS);
+ switch (child_device_type) {
+#if CONFIG_VAAPI
+ case AV_HWDEVICE_TYPE_VAAPI:
@@ -544,15 +1219,14 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
+#if CONFIG_D3D11VA
+ case AV_HWDEVICE_TYPE_D3D11VA:
+ {
-+ av_log(ctx, AV_LOG_VERBOSE,"AV_HWDEVICE_TYPE_D3D11VA has been selected\n");
++ e = av_dict_get(opts, "vendor", NULL, 0);
++ if(e)
++ av_dict_set(&child_device_opts, "vendor", e->value, 0);
+ }
+ break;
+#endif
+#if CONFIG_DXVA2
+ case AV_HWDEVICE_TYPE_DXVA2:
-+ {
-+ av_log(ctx, AV_LOG_VERBOSE,"AV_HWDEVICE_TYPE_DXVA2 has been selected\n");
-+ }
+ break;
+#endif
+ default:
@@ -561,13 +1235,15 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
+ 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);
-
-@@ -1267,7 +1420,7 @@
+-
+ av_dict_free(&child_device_opts);
+ if (ret < 0)
+ return ret;
child_device = (AVHWDeviceContext*)priv->child_device_ctx->data;
@@ -576,36 +1252,3 @@ diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.c ffmpeg-4.3/libavutil/hwcontex
return qsv_device_derive_from_child(ctx, impl, child_device, 0);
}
-Only in ffmpeg-4.3/libavutil: hwcontext_qsv.c.orig
-diff -ur ffmpeg-4.3.orig/libavutil/hwcontext_qsv.h ffmpeg-4.3/libavutil/hwcontext_qsv.h
---- ffmpeg-4.3.orig/libavutil/hwcontext_qsv.h 2020-05-21 11:55:31.000000000 -0400
-+++ ffmpeg-4.3/libavutil/hwcontext_qsv.h 2020-07-14 09:17:52.000000000 -0400
-@@ -34,6 +34,15 @@
- */
- typedef struct AVQSVDeviceContext {
- mfxSession session;
-+ /**
-+ * Need to store actual handle type that session uses
-+ * MFXVideoCORE_GetHandle() function returns mfxHandleType
-+ * always equal to MFX_HANDLE_D3D9_DEVICE_MANAGER
-+ * even when MFX_HANDLE_D3D11_DEVICE was set as handle before by
-+ * MFXVideoCORE_SetHandle() to mfx session.
-+ * Fixed already but will be available only with latest driver.
-+ */
-+ //mfxHandleType handle_type;
- } AVQSVDeviceContext;
-
- /**
-@@ -42,11 +51,11 @@
- typedef struct AVQSVFramesContext {
- mfxFrameSurface1 *surfaces;
- int nb_surfaces;
--
- /**
- * A combination of MFX_MEMTYPE_* describing the frame pool.
- */
- int frame_type;
-+ void *texture;
- } AVQSVFramesContext;
-
- #endif /* AVUTIL_HWCONTEXT_QSV_H */
diff --git a/libhb/cropscale.c b/libhb/cropscale.c
index 6bc9f6d5a..4006a271c 100644
--- a/libhb/cropscale.c
+++ b/libhb/cropscale.c
@@ -111,8 +111,9 @@ static int crop_scale_init(hb_filter_object_t * filter, hb_filter_init_t * init)
hw_frames_ctx = init->job->qsv.ctx->hb_vpp_qsv_frames_ctx->hw_frames_ctx;
frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
frames_hwctx = frames_ctx->hwctx;
- init->job->qsv.ctx->hb_vpp_qsv_frames_ctx->input_texture = frames_hwctx->texture;
-
+ mfxHDLPair* handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[0].Data.MemId;
+ init->job->qsv.ctx->hb_vpp_qsv_frames_ctx->input_texture = ((size_t)handle_pair->second != MFX_INFINITE) ? handle_pair->first : NULL;
+
/* allocate the memory ids for the external frames */
av_buffer_unref(&init->job->qsv.ctx->hb_vpp_qsv_frames_ctx->mids_buf);
init->job->qsv.ctx->hb_vpp_qsv_frames_ctx->mids_buf = hb_qsv_create_mids(init->job->qsv.ctx->hb_vpp_qsv_frames_ctx->hw_frames_ctx);
diff --git a/libhb/enc_qsv.c b/libhb/enc_qsv.c
index 49eeca6bc..c55e6acc5 100644
--- a/libhb/enc_qsv.c
+++ b/libhb/enc_qsv.c
@@ -504,8 +504,7 @@ AVBufferRef *hb_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->handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[i].Data.MemId;
mid->hw_frames_ref = hw_frames_ref1;
}
@@ -679,7 +678,7 @@ static mfxStatus hb_qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr
goto fail;
qsv_mid->surf.Info = hw_frames_hwctx->surfaces[0].Info;
- qsv_mid->surf.Data.MemId = qsv_mid->handle;
+ qsv_mid->surf.Data.MemId = qsv_mid->handle_pair;
/* map the data to the system memory */
ret = av_hwframe_map(qsv_mid->locked_frame, qsv_mid->hw_frame,
@@ -712,14 +711,12 @@ static mfxStatus hb_qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *p
static mfxStatus hb_qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
{
QSVMid *qsv_mid = (QSVMid*)mid;
+ mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
+ mfxHDLPair *pair_src = (mfxHDLPair*)qsv_mid->handle_pair;
- if (qsv_mid->texture) {
- mfxHDLPair *pPair = (mfxHDLPair*)hdl;
- pPair->first = qsv_mid->texture;
- pPair->second = qsv_mid->handle;
- } else {
- *hdl = qsv_mid->handle;
- }
+ pair_dst->first = pair_src->first;
+ if (pair_src->second != (mfxMemId)MFX_INFINITE)
+ pair_dst->second = pair_src->second;
return MFX_ERR_NONE;
}
@@ -1052,7 +1049,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
hb_value_t *value = hb_dict_iter_value(iter);
char *str = hb_value_get_string_xform(value);
- switch (hb_qsv_param_parse(&pv->param, pv->qsv_info, key, str))
+ switch (hb_qsv_param_parse(&pv->param, pv->qsv_info, pv->job, key, str))
{
case HB_QSV_PARAM_OK:
break;
diff --git a/libhb/handbrake/qsv_common.h b/libhb/handbrake/qsv_common.h
index dd6ffd3ee..e6ac93fc4 100644
--- a/libhb/handbrake/qsv_common.h
+++ b/libhb/handbrake/qsv_common.h
@@ -196,7 +196,7 @@ float hb_qsv_atof (const char *str, int *err);
int hb_qsv_param_default_async_depth();
int hb_qsv_param_default_preset (hb_qsv_param_t *param, mfxVideoParam *videoParam, hb_qsv_info_t *info, const char *preset);
int hb_qsv_param_default (hb_qsv_param_t *param, mfxVideoParam *videoParam, hb_qsv_info_t *info);
-int hb_qsv_param_parse (hb_qsv_param_t *param, hb_qsv_info_t *info, const char *key, const char *value);
+int hb_qsv_param_parse (hb_qsv_param_t *param, hb_qsv_info_t *info, hb_job_t *job, const char *key, const char *value);
int hb_qsv_profile_parse (hb_qsv_param_t *param, hb_qsv_info_t *info, const char *profile_key, const int codec);
int hb_qsv_level_parse (hb_qsv_param_t *param, hb_qsv_info_t *info, const char *level_key);
diff --git a/libhb/handbrake/qsv_libav.h b/libhb/handbrake/qsv_libav.h
index 0fef06a36..d12bd3cb5 100644
--- a/libhb/handbrake/qsv_libav.h
+++ b/libhb/handbrake/qsv_libav.h
@@ -190,9 +190,7 @@ typedef enum HB_QSV_STAGE_TYPE {
typedef struct QSVMid {
AVBufferRef *hw_frames_ref;
- mfxHDL handle;
-
- void *texture;
+ mfxHDLPair *handle_pair;
AVFrame *locked_frame;
AVFrame *hw_frame;
diff --git a/libhb/hbavfilter.c b/libhb/hbavfilter.c
index a8e6ee304..f78fcaf95 100644
--- a/libhb/hbavfilter.c
+++ b/libhb/hbavfilter.c
@@ -135,6 +135,22 @@ hb_avfilter_graph_init(hb_value_t * settings, hb_filter_init_t * init)
goto fail;
}
par->hw_frames_ctx = hb_hw_frames_ctx;
+ // TODO: need to pass correct alignment for the scale_qsv output frame
+ int out_alignment = 0;
+ switch (graph->job->vcodec)
+ {
+ case HB_VCODEC_QSV_H264:
+ out_alignment = 16;
+ break;
+ case HB_VCODEC_QSV_H265_10BIT:
+ case HB_VCODEC_QSV_H265:
+ out_alignment = 32;
+ break;
+ default:
+ out_alignment = 0;
+ break;
+ }
+ graph->avgraph->opaque = (void*)(intptr_t)out_alignment;
}
else
#endif
diff --git a/libhb/qsv_common.c b/libhb/qsv_common.c
index a4eb3ea83..225486db7 100644
--- a/libhb/qsv_common.c
+++ b/libhb/qsv_common.c
@@ -1135,7 +1135,7 @@ float hb_qsv_atof(const char *str, int *err)
return v;
}
-int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info,
+int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info, hb_job_t *job,
const char *key, const char *value)
{
float fvalue;
@@ -1620,7 +1620,7 @@ int hb_qsv_param_parse(hb_qsv_param_t *param, hb_qsv_info_t *info,
return HB_QSV_PARAM_UNSUPPORTED;
}
}
- else
+ else
{
/*
* TODO:
@@ -2539,13 +2539,13 @@ static HRESULT unlock_device(
static int hb_qsv_find_surface_idx(const QSVMid *mids, const int nb_mids, const QSVMid *mid)
{
- if(mids)
+ if (mids)
{
- const QSVMid *m = &mids[0];
int i;
for (i = 0; i < nb_mids; i++) {
- m = &mids[i];
- if ( (m->texture == mid->texture) && (m->handle == mid->handle) )
+ const QSVMid *m = &mids[i];
+ if ((m->handle_pair->first == mid->handle_pair->first) &&
+ (m->handle_pair->second == mid->handle_pair->second))
return i;
}
}
@@ -2656,7 +2656,7 @@ int hb_qsv_get_free_surface_from_pool(HBQSVFramesContext* hb_enc_qsv_frames_ctx,
mfxFrameSurface1* cur_surface = &frames_hwctx->surfaces[i];
if(cur_surface == output_surface)
{
- if((hb_enc_qsv_frames_ctx->pool[i]) == 0 && (output_surface->Data.Locked == 0))
+ if((hb_enc_qsv_frames_ctx->pool[i] == 0) && (output_surface->Data.Locked == 0))
{
*out_mid = mid;
ff_qsv_atomic_inc(&hb_enc_qsv_frames_ctx->pool[i]);
@@ -2675,14 +2675,14 @@ int hb_qsv_get_free_surface_from_pool(HBQSVFramesContext* hb_enc_qsv_frames_ctx,
}
}
-static int hb_qsv_allocate_dx11_encoder_pool(HBQSVFramesContext* hb_enc_qsv_frames_ctx, ID3D11Device *device, ID3D11Texture2D* input_texture)
+static int hb_qsv_allocate_dx11_encoder_pool(HBQSVFramesContext* frames_ctx, ID3D11Device *device, ID3D11Texture2D* input_texture)
{
D3D11_TEXTURE2D_DESC desc = { 0 };
ID3D11Texture2D_GetDesc(input_texture, &desc);
desc.ArraySize = 1;
- desc.BindFlags = D3D10_BIND_RENDER_TARGET;
+ desc.BindFlags = D3D11_BIND_RENDER_TARGET;
- for (size_t i = 0; i < hb_enc_qsv_frames_ctx->nb_mids; i++)
+ for (size_t i = 0; i < frames_ctx->nb_mids; i++)
{
ID3D11Texture2D* texture;
HRESULT hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture);
@@ -2692,9 +2692,9 @@ static int hb_qsv_allocate_dx11_encoder_pool(HBQSVFramesContext* hb_enc_qsv_fram
return -1;
}
- QSVMid *mid = &hb_enc_qsv_frames_ctx->mids[i];
- mid->handle = 0;
- mid->texture = texture;
+ QSVMid *mid = &frames_ctx->mids[i];
+ mid->handle_pair->first = texture;
+ mid->handle_pair->second = 0;
}
return 0;
}
@@ -2774,17 +2774,12 @@ void hb_qsv_get_free_surface_from_pool_with_range(HBQSVFramesContext* hb_enc_qsv
for (int i = start_index; i < end_index; i++)
{
- if ((hb_enc_qsv_frames_ctx->pool[i]) == 0)
+ if ((hb_enc_qsv_frames_ctx->pool[i] == 0) && (frames_hwctx->surfaces[i].Data.Locked == 0))
{
- QSVMid* mid = &hb_enc_qsv_frames_ctx->mids[i];
- mfxFrameSurface1* cur_surface = &frames_hwctx->surfaces[i];
- if (cur_surface->Data.Locked == 0)
- {
- *out_mid = mid;
- *out_surface = cur_surface;
- ff_qsv_atomic_inc(&hb_enc_qsv_frames_ctx->pool[i]);
- return;
- }
+ *out_mid = &hb_enc_qsv_frames_ctx->mids[i];
+ *out_surface = &frames_hwctx->surfaces[i];
+ ff_qsv_atomic_inc(&hb_enc_qsv_frames_ctx->pool[i]);
+ return;
}
}
count++;
@@ -2844,12 +2839,12 @@ hb_buffer_t* hb_qsv_copy_frame(hb_job_t *job, AVFrame *frame, int is_vpp)
if (device_manager_handle_type == MFX_HANDLE_D3D9_DEVICE_MANAGER)
{
mfxFrameSurface1* input_surface = (mfxFrameSurface1*)frame->data[3];
+ mfxHDLPair* input_pair = (mfxHDLPair*)input_surface->Data.MemId;
// copy all surface fields
+ *output_surface = *input_surface;
if (hb_qsv_hw_filters_are_enabled(job))
{
- mfxMemId mem = output_surface->Data.MemId;
- *output_surface = *input_surface;
- output_surface->Data.MemId = mem; // todo because get_hdl function in qsv scale filter is not implemented in the ffmpeg patch
+ output_surface->Data.MemId = mid->handle_pair;
}
else
{
@@ -2866,7 +2861,7 @@ hb_buffer_t* hb_qsv_copy_frame(hb_job_t *job, AVFrame *frame, int is_vpp)
hb_error("hb_qsv_copy_frame: lock_device failed %d", result);
return out;
}
- result = IDirect3DDevice9_StretchRect(pDevice, input_surface->Data.MemId, 0, mid->handle, 0, D3DTEXF_LINEAR);
+ result = IDirect3DDevice9_StretchRect(pDevice, input_pair->first, 0, mid->handle_pair->first, 0, D3DTEXF_LINEAR);
if (FAILED(result))
{
hb_error("hb_qsv_copy_frame: IDirect3DDevice9_StretchRect failed %d", result);
@@ -2882,13 +2877,24 @@ hb_buffer_t* hb_qsv_copy_frame(hb_job_t *job, AVFrame *frame, int is_vpp)
else if (device_manager_handle_type == MFX_HANDLE_D3D11_DEVICE)
{
mfxFrameSurface1* input_surface = (mfxFrameSurface1*)frame->data[3];
-
+ mfxHDLPair* input_pair = (mfxHDLPair*)input_surface->Data.MemId;
+ // Need to pass 0 instead of MFX_INFINITE to DirectX as index of surface
+ int input_index = (int)(intptr_t)input_pair->second == MFX_INFINITE ? 0 : (int)(intptr_t)input_pair->second;
+ int output_index = (int)(intptr_t)mid->handle_pair->second == MFX_INFINITE ? 0 : (int)(intptr_t)mid->handle_pair->second;
// copy all surface fields
*output_surface = *input_surface;
- // replace the mem id to mem id from the pool
- output_surface->Data.MemId = mid;
+ if (hb_qsv_hw_filters_are_enabled(job))
+ {
+ // Make sure that we pass handle_pair to scale_qsv
+ output_surface->Data.MemId = mid->handle_pair;
+ }
+ else
+ {
+ // Make sure that we pass QSVMid to QSV encoder
+ output_surface->Data.MemId = mid;
+ }
// copy input sufrace to sufrace from the pool
- ID3D11DeviceContext_CopySubresourceRegion(device_context, mid->texture, (uint64_t)mid->handle, 0, 0, 0, hb_qsv_frames_ctx->input_texture, (uint64_t)input_surface->Data.MemId, NULL);
+ ID3D11DeviceContext_CopySubresourceRegion(device_context, mid->handle_pair->first, output_index, 0, 0, 0, input_pair->first, input_index, NULL);
ID3D11DeviceContext_Flush(device_context);
}
else
@@ -3050,7 +3056,8 @@ int hb_qsv_hw_frames_init(AVCodecContext *s)
hw_frames_ctx = *out_hw_frames_ctx;
frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
frames_hwctx = frames_ctx->hwctx;
- hb_dec_qsv_frames_ctx->input_texture = frames_hwctx->texture;
+ mfxHDLPair* handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[0].Data.MemId;
+ hb_dec_qsv_frames_ctx->input_texture = ((size_t)handle_pair->second != MFX_INFINITE) ? handle_pair->first : NULL;
ret = hb_create_ffmpeg_pool(job, coded_width, coded_height, sw_pix_fmt, HB_QSV_POOL_SURFACE_SIZE, extra_hw_frames, &hb_dec_qsv_frames_ctx->hw_frames_ctx);
if (ret < 0) {