diff options
author | agalin89 <[email protected]> | 2020-07-31 05:03:18 -0700 |
---|---|---|
committer | Bradley Sepos <[email protected]> | 2020-08-22 17:20:35 -0400 |
commit | 350ab4509e124e02cc601cb07260eb9817045836 (patch) | |
tree | ff5a19424674b69324345211aac92cee7e795850 | |
parent | f51882f39b3143899f10b1485e767bcac8a37890 (diff) |
qsv: update dx11 patch for ffmpeg 4.3.1
-rw-r--r-- | contrib/ffmpeg/A00-qsv-dx11-ffmpeg43.patch | 1231 | ||||
-rw-r--r-- | libhb/cropscale.c | 5 | ||||
-rw-r--r-- | libhb/enc_qsv.c | 19 | ||||
-rw-r--r-- | libhb/handbrake/qsv_common.h | 2 | ||||
-rw-r--r-- | libhb/handbrake/qsv_libav.h | 4 | ||||
-rw-r--r-- | libhb/hbavfilter.c | 16 | ||||
-rw-r--r-- | libhb/qsv_common.c | 71 |
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) { |