[FFmpeg-devel] [PATCH v3 09/10] qsv: use a new method to create mfx session when using oneVPL
Haihao Xiang
haihao.xiang at intel.com
Sat Sep 18 05:30:04 EEST 2021
In oneVPL, MFXLoad() and MFXCreateSession() are required to create a
workable mfx session[1]
Add AccelerationMode config filter for D3D9/D3D11 session (galinart)
The default device is changed to d3d11va for oneVPL when both d3d11va
and dxva2 are enabled on Microsoft Windows
This is in preparation for oneVPL support
[1] https://spec.oneapi.io/versions/latest/elements/oneVPL/source/programming_guide/VPL_prg_session.html#onevpl-dispatcher
Signed-off-by: galinart <artem.galin at intel.com>
---
libavcodec/qsv.c | 191 ++++++++++++++++--
libavcodec/qsv_internal.h | 1 +
libavcodec/qsvdec.c | 4 +
libavcodec/qsvenc.h | 3 +
libavcodec/qsvenc_h264.c | 1 -
libavcodec/qsvenc_hevc.c | 1 -
libavcodec/qsvenc_jpeg.c | 1 -
libavcodec/qsvenc_mpeg2.c | 1 -
libavcodec/qsvenc_vp9.c | 1 -
libavfilter/qsvvpp.c | 107 +++++++++-
libavfilter/qsvvpp.h | 5 +
libavfilter/vf_deinterlace_qsv.c | 14 +-
libavfilter/vf_scale_qsv.c | 12 +-
libavutil/hwcontext_qsv.c | 322 +++++++++++++++++++++++++++----
libavutil/hwcontext_qsv.h | 16 ++
15 files changed, 591 insertions(+), 89 deletions(-)
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index 780bc3c4ec..92a59457ea 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -387,6 +387,164 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
}
#endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
+#if QSV_ONEVPL
+
+static int qsv_create_mfx_session(AVCodecContext *avctx,
+ mfxIMPL implementation,
+ mfxVersion *pver,
+ int gpu_copy,
+ mfxSession *psession,
+ mfxLoader *ploader)
+{
+ mfxStatus sts;
+ mfxLoader loader = NULL;
+ mfxSession session = NULL;
+ mfxConfig cfg;
+ mfxVariant impl_value;
+ uint32_t impl_idx = 0;
+
+ *psession = NULL;
+
+ /* Don't create a new MFX loader if the input loader is valid */
+ if (*ploader == NULL) {
+ av_log(avctx, AV_LOG_VERBOSE,
+ "Use Intel(R) oneVPL to create MFX session, the required "
+ "implementation version is %d.%d\n",
+ pver->Major, pver->Minor);
+
+ loader = MFXLoad();
+
+ if (!loader) {
+ av_log(avctx, AV_LOG_ERROR, "Error creating a MFX loader\n");
+ goto fail;
+ }
+
+ /* Create configurations for implementation */
+ cfg = MFXCreateConfig(loader);
+
+ if (!cfg) {
+ av_log(avctx, AV_LOG_ERROR, "Error creating a MFX configurations\n");
+ goto fail;
+ }
+
+ impl_value.Type = MFX_VARIANT_TYPE_U32;
+ impl_value.Data.U32 = (implementation == MFX_IMPL_SOFTWARE) ?
+ MFX_IMPL_TYPE_SOFTWARE : MFX_IMPL_TYPE_HARDWARE;
+ sts = MFXSetConfigFilterProperty(cfg,
+ (const mfxU8 *)"mfxImplDescription.Impl", impl_value);
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(avctx, AV_LOG_ERROR, "Error adding a MFX configuration "
+ "property: %d\n", sts);
+ goto fail;
+ }
+
+ impl_value.Type = MFX_VARIANT_TYPE_U32;
+ impl_value.Data.U32 = pver->Version;
+ sts = MFXSetConfigFilterProperty(cfg,
+ (const mfxU8 *)"mfxImplDescription.ApiVersion.Version",
+ impl_value);
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(avctx, AV_LOG_ERROR, "Error adding a MFX configuration "
+ "property: %d\n", sts);
+ goto fail;
+ }
+ } else {
+ av_log(avctx, AV_LOG_VERBOSE,
+ "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
+
+ loader = *ploader;
+ }
+
+ while (1) {
+ /* Enumerate all implementations */
+ mfxImplDescription *impl_desc;
+
+ sts = MFXEnumImplementations(loader, impl_idx,
+ MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
+ (mfxHDL *)&impl_desc);
+
+ /* Failed to find an available implementation */
+ if (sts == MFX_ERR_NOT_FOUND)
+ break;
+ else if (sts != MFX_ERR_NONE) {
+ impl_idx++;
+ continue;
+ }
+
+ sts = MFXCreateSession(loader, impl_idx, &session);
+ MFXDispReleaseImplDescription(loader, impl_desc);
+
+ if (sts == MFX_ERR_NONE)
+ break;
+
+ impl_idx++;
+ }
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(avctx, AV_LOG_ERROR, "Error creating a MFX session: %d.\n", sts);
+ goto fail;
+ }
+
+ *psession = session;
+
+ if (!*ploader)
+ *ploader = loader;
+
+ return 0;
+
+fail:
+ if (!*ploader && loader)
+ MFXUnload(loader);
+
+ return AVERROR_UNKNOWN;
+}
+
+#else
+
+static int qsv_create_mfx_session(AVCodecContext *avctx,
+ mfxIMPL implementation,
+ mfxVersion *pver,
+ int gpu_copy,
+ mfxSession *psession,
+ mfxLoader *ploader)
+{
+ mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
+ mfxSession session = NULL;
+ mfxStatus sts;
+
+ av_log(avctx, AV_LOG_VERBOSE,
+ "Use Intel(R) Media SDK to create MFX session, the required "
+ "implementation version is %d.%d\n",
+ pver->Major, pver->Minor);
+
+ *psession = NULL;
+ *ploader = NULL;
+
+#if QSV_VERSION_ATLEAST(1, 16)
+ init_par.GPUCopy = gpu_copy;
+#endif
+ init_par.Implementation = implementation;
+ init_par.Version = *pver;
+ sts = MFXInitEx(init_par, &session);
+
+ if (sts < 0)
+ return ff_qsv_print_error(avctx, sts,
+ "Error initializing a MFX session");
+ else if (sts > 0) {
+ ff_qsv_print_warning(avctx, sts,
+ "Warning in MFX initialization");
+ return AVERROR_UNKNOWN;
+ }
+
+ *psession = session;
+
+ return 0;
+}
+
+#endif
+
int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
const char *load_plugins, int gpu_copy)
{
@@ -396,20 +554,13 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
mfxIMPL impl = MFX_IMPL_AUTO_ANY;
#endif
mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
- mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
const char *desc;
- int ret;
+ int ret = qsv_create_mfx_session(avctx, impl, &ver, gpu_copy, &qs->session,
+ &qs->loader);
-#if QSV_VERSION_ATLEAST(1, 16)
- init_par.GPUCopy = gpu_copy;
-#endif
- init_par.Implementation = impl;
- init_par.Version = ver;
- ret = MFXInitEx(init_par, &qs->session);
- if (ret < 0)
- return ff_qsv_print_error(avctx, ret,
- "Error initializing an internal MFX session");
+ if (ret)
+ return ret;
#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
ret = ff_qsv_set_display_handle(avctx, qs);
@@ -710,7 +861,7 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
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 };
+ mfxLoader loader = device_hwctx->loader;
mfxHDL handle = NULL;
int hw_handle_supported = 0;
@@ -751,15 +902,11 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
"from the session\n");
}
-#if QSV_VERSION_ATLEAST(1, 16)
- init_par.GPUCopy = gpu_copy;
-#endif
- init_par.Implementation = impl;
- init_par.Version = ver;
- err = MFXInitEx(init_par, &session);
- if (err != MFX_ERR_NONE)
- return ff_qsv_print_error(avctx, err,
- "Error initializing a child MFX session");
+ ret = qsv_create_mfx_session(avctx, impl, &ver, gpu_copy, &session,
+ &loader);
+
+ if (ret)
+ return ret;
if (handle) {
err = MFXVideoCORE_SetHandle(session, handle_type, handle);
@@ -836,7 +983,9 @@ int ff_qsv_close_internal_session(QSVSession *qs)
{
if (qs->session) {
MFXClose(qs->session);
+ MFXUnload(qs->loader);
qs->session = NULL;
+ qs->loader = NULL;
}
#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
av_buffer_unref(&qs->va_device_ref);
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index ff50b41de8..aea1441c7f 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -87,6 +87,7 @@ typedef struct QSVFrame {
typedef struct QSVSession {
mfxSession session;
+ mfxLoader loader;
#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
AVBufferRef *va_device_ref;
AVHWDeviceContext *va_device_ctx;
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index 9395a1fd9a..c4daa44c1c 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -161,7 +161,9 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses
} else if (hw_frames_ref) {
if (q->internal_qs.session) {
MFXClose(q->internal_qs.session);
+ MFXUnload(q->internal_qs.loader);
q->internal_qs.session = NULL;
+ q->internal_qs.loader = NULL;
}
av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
@@ -186,7 +188,9 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses
} else if (hw_device_ref) {
if (q->internal_qs.session) {
MFXClose(q->internal_qs.session);
+ MFXUnload(q->internal_qs.loader);
q->internal_qs.session = NULL;
+ q->internal_qs.loader = NULL;
}
ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session,
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index 320ad6db2b..7a7eaea156 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -28,6 +28,9 @@
#include <mfxvideo.h>
+#include "libavutil/common.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_qsv.h"
#include "libavutil/avutil.h"
#include "libavutil/fifo.h"
diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c
index 9134e6a68c..5ed5e1ed0d 100644
--- a/libavcodec/qsvenc_h264.c
+++ b/libavcodec/qsvenc_h264.c
@@ -32,7 +32,6 @@
#include "avcodec.h"
#include "internal.h"
#include "qsv.h"
-#include "qsv_internal.h"
#include "qsvenc.h"
#include "atsc_a53.h"
diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
index a268a002d6..7519b7b436 100644
--- a/libavcodec/qsvenc_hevc.c
+++ b/libavcodec/qsvenc_hevc.c
@@ -35,7 +35,6 @@
#include "h2645_parse.h"
#include "internal.h"
#include "qsv.h"
-#include "qsv_internal.h"
#include "qsvenc.h"
enum LoadPlugin {
diff --git a/libavcodec/qsvenc_jpeg.c b/libavcodec/qsvenc_jpeg.c
index ad8f09befe..f473b1ddbc 100644
--- a/libavcodec/qsvenc_jpeg.c
+++ b/libavcodec/qsvenc_jpeg.c
@@ -30,7 +30,6 @@
#include "avcodec.h"
#include "internal.h"
#include "qsv.h"
-#include "qsv_internal.h"
#include "qsvenc.h"
typedef struct QSVMJPEGEncContext {
diff --git a/libavcodec/qsvenc_mpeg2.c b/libavcodec/qsvenc_mpeg2.c
index 610bbf79c1..0e2a51811c 100644
--- a/libavcodec/qsvenc_mpeg2.c
+++ b/libavcodec/qsvenc_mpeg2.c
@@ -30,7 +30,6 @@
#include "avcodec.h"
#include "internal.h"
#include "qsv.h"
-#include "qsv_internal.h"
#include "qsvenc.h"
typedef struct QSVMpeg2EncContext {
diff --git a/libavcodec/qsvenc_vp9.c b/libavcodec/qsvenc_vp9.c
index 0a382eb76d..9d88b03bbf 100644
--- a/libavcodec/qsvenc_vp9.c
+++ b/libavcodec/qsvenc_vp9.c
@@ -30,7 +30,6 @@
#include "avcodec.h"
#include "internal.h"
#include "qsv.h"
-#include "qsv_internal.h"
#include "qsvenc.h"
typedef struct QSVVP9EncContext {
diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c
index bd3a50c070..3c8b3d0390 100644
--- a/libavfilter/qsvvpp.c
+++ b/libavfilter/qsvvpp.c
@@ -23,8 +23,6 @@
#include "libavutil/common.h"
#include "libavutil/mathematics.h"
-#include "libavutil/hwcontext.h"
-#include "libavutil/hwcontext_qsv.h"
#include "libavutil/time.h"
#include "libavutil/pixdesc.h"
@@ -609,13 +607,11 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
}
/* create a "slave" session with those same properties, to be used for vpp */
- ret = MFXInit(impl, &ver, &s->session);
- if (ret < 0)
- return ff_qsvvpp_print_error(avctx, ret, "Error initializing a session");
- else if (ret > 0) {
- ff_qsvvpp_print_warning(avctx, ret, "Warning in session initialization");
- return AVERROR_UNKNOWN;
- }
+ ret = ff_qsvvpp_create_mfx_session(avctx, device_hwctx->loader, impl, &ver,
+ &s->session);
+
+ if (ret)
+ return ret;
if (handle) {
ret = MFXVideoCORE_SetHandle(s->session, handle_type, handle);
@@ -914,3 +910,96 @@ int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picr
return 0;
}
+
+#if QSV_ONEVPL
+
+int ff_qsvvpp_create_mfx_session(void *ctx,
+ mfxLoader loader,
+ mfxIMPL implementation,
+ mfxVersion *pver,
+ mfxSession *psession)
+{
+ mfxStatus sts;
+ mfxSession session = NULL;
+ uint32_t impl_idx = 0;
+
+ av_log(ctx, AV_LOG_VERBOSE,
+ "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
+
+ if (!loader) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid MFX Loader handle\n");
+ return AVERROR(EINVAL);
+ }
+
+ while (1) {
+ /* Enumerate all implementations */
+ mfxImplDescription *impl_desc;
+
+ sts = MFXEnumImplementations(loader, impl_idx,
+ MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
+ (mfxHDL *)&impl_desc);
+
+ /* Failed to find an available implementation */
+ if (sts == MFX_ERR_NOT_FOUND)
+ break;
+ else if (sts != MFX_ERR_NONE) {
+ impl_idx++;
+ continue;
+ }
+
+ sts = MFXCreateSession(loader, impl_idx, &session);
+ MFXDispReleaseImplDescription(loader, impl_desc);
+
+ if (sts == MFX_ERR_NONE)
+ break;
+
+ impl_idx++;
+ }
+
+ if (sts < 0)
+ return ff_qsvvpp_print_error(ctx, sts,
+ "Error creating a MFX session");
+ else if (sts > 0) {
+ ff_qsvvpp_print_warning(ctx, sts,
+ "Warning in MFX session creation");
+ return AVERROR_UNKNOWN;
+ }
+
+ *psession = session;
+
+ return 0;
+}
+
+#else
+
+int ff_qsvvpp_create_mfx_session(void *ctx,
+ mfxLoader loader,
+ mfxIMPL implementation,
+ mfxVersion *pver,
+ mfxSession *psession)
+{
+ mfxSession session = NULL;
+ mfxStatus sts;
+
+ av_log(ctx, AV_LOG_VERBOSE,
+ "Use Intel(R) Media SDK to create MFX session, API version is "
+ "%d.%d, the required implementation version is %d.%d\n",
+ MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
+
+ *psession = NULL;
+ sts = MFXInit(implementation, pver, &session);
+
+ if (sts < 0)
+ return ff_qsvvpp_print_error(ctx, sts,
+ "Error initializing an MFX session");
+ else if (sts > 0) {
+ ff_qsvvpp_print_warning(ctx, sts, "Warning in MFX session initialization");
+ return AVERROR_UNKNOWN;
+ }
+
+ *psession = session;
+
+ return 0;
+}
+
+#endif
diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h
index 67c351f297..d1c12be25b 100644
--- a/libavfilter/qsvvpp.h
+++ b/libavfilter/qsvvpp.h
@@ -28,6 +28,8 @@
#include "avfilter.h"
#include "libavutil/fifo.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_qsv.h"
#define FF_INLINK_IDX(link) ((int)((link)->dstpad - (link)->dst->input_pads))
#define FF_OUTLINK_IDX(link) ((int)((link)->srcpad - (link)->src->output_pads))
@@ -122,4 +124,7 @@ int ff_qsvvpp_print_error(void *log_ctx, mfxStatus err,
int ff_qsvvpp_print_warning(void *log_ctx, mfxStatus err,
const char *warning_string);
+int ff_qsvvpp_create_mfx_session(void *ctx, mfxLoader loader, mfxIMPL implementation,
+ mfxVersion *pver, mfxSession *psession);
+
#endif /* AVFILTER_QSVVPP_H */
diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c
index 84b3ec5a7c..90dac86e3a 100644
--- a/libavfilter/vf_deinterlace_qsv.c
+++ b/libavfilter/vf_deinterlace_qsv.c
@@ -172,7 +172,7 @@ static int init_out_session(AVFilterContext *ctx)
mfxIMPL impl;
mfxVideoParam par;
mfxStatus err;
- int i;
+ int i, ret;
#if QSV_HAVE_OPAQUE
opaque = !!(hw_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
@@ -207,13 +207,11 @@ static int init_out_session(AVFilterContext *ctx)
/* create a "slave" session with those same properties, to be used for
* actual deinterlacing */
- err = MFXInit(impl, &ver, &s->session);
- if (err < 0)
- return ff_qsvvpp_print_error(ctx, err, "Error initializing a session for deinterlacing");
- else if (err > 0) {
- ff_qsvvpp_print_warning(ctx, err, "Warning in session initialization");
- return AVERROR_UNKNOWN;
- }
+ ret = ff_qsvvpp_create_mfx_session(ctx, device_hwctx->loader, impl, &ver,
+ &s->session);
+
+ if (ret)
+ return ret;
if (handle) {
err = MFXVideoCORE_SetHandle(s->session, handle_type, handle);
diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c
index bbdca3660f..c2aac1b980 100644
--- a/libavfilter/vf_scale_qsv.c
+++ b/libavfilter/vf_scale_qsv.c
@@ -290,7 +290,7 @@ static int init_out_session(AVFilterContext *ctx)
mfxIMPL impl;
mfxVideoParam par;
mfxStatus err;
- int i;
+ int i, ret;
#if QSV_HAVE_OPAQUE
opaque = !!(in_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
@@ -327,11 +327,11 @@ static int init_out_session(AVFilterContext *ctx)
/* create a "slave" session with those same properties, to be used for
* actual scaling */
- err = MFXInit(impl, &ver, &s->session);
- if (err != MFX_ERR_NONE) {
- av_log(ctx, AV_LOG_ERROR, "Error initializing a session for scaling\n");
- return AVERROR_UNKNOWN;
- }
+ ret = ff_qsvvpp_create_mfx_session(ctx, device_hwctx->loader, impl, &ver,
+ &s->session);
+
+ if (ret)
+ return ret;
if (handle) {
err = MFXVideoCORE_SetHandle(s->session, handle_type, handle);
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index fd6703cd38..deed24f08f 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -72,8 +72,10 @@ typedef struct QSVDeviceContext {
typedef struct QSVFramesContext {
mfxSession session_download;
+ mfxLoader loader_download;
int session_download_init;
mfxSession session_upload;
+ mfxLoader loader_upload;
int session_upload_init;
#if HAVE_PTHREADS
pthread_mutex_t session_lock;
@@ -204,15 +206,19 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx)
if (s->session_download) {
MFXVideoVPP_Close(s->session_download);
MFXClose(s->session_download);
+ MFXUnload(s->loader_download);
}
s->session_download = NULL;
+ s->loader_download = NULL;
s->session_download_init = 0;
if (s->session_upload) {
MFXVideoVPP_Close(s->session_upload);
MFXClose(s->session_upload);
+ MFXUnload(s->loader_upload);
}
s->session_upload = NULL;
+ s->loader_upload = NULL;
s->session_upload_init = 0;
#if HAVE_PTHREADS
@@ -537,8 +543,221 @@ static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
return MFX_ERR_NONE;
}
+#if QSV_ONEVPL
+
+static int qsv_create_mfx_session(void *ctx,
+ mfxHandleType handle_type,
+ mfxIMPL implementation,
+ mfxVersion *pver,
+ mfxSession *psession,
+ mfxLoader *ploader)
+{
+ mfxStatus sts;
+ mfxLoader loader = NULL;
+ mfxSession session = NULL;
+ mfxConfig cfg;
+ mfxVersion ver;
+ mfxVariant impl_value;
+ uint32_t impl_idx = 0;
+
+ av_log(ctx, AV_LOG_VERBOSE,
+ "Use Intel(R) oneVPL to create MFX session, API version is "
+ "%d.%d, the required implementation version is %d.%d\n",
+ MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
+
+ if (handle_type != MFX_HANDLE_VA_DISPLAY &&
+ handle_type != MFX_HANDLE_D3D9_DEVICE_MANAGER &&
+ handle_type != MFX_HANDLE_D3D11_DEVICE) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Invalid MFX device handle\n");
+ return AVERROR(EXDEV);
+ }
+
+ *psession = NULL;
+ *ploader = NULL;
+ loader = MFXLoad();
+
+ if (!loader) {
+ av_log(ctx, AV_LOG_ERROR, "Error creating a MFX loader\n");
+ goto fail;
+ }
+
+ /* Create configurations for implementation */
+ cfg = MFXCreateConfig(loader);
+
+ if (!cfg) {
+ av_log(ctx, AV_LOG_ERROR, "Error creating a MFX configuration\n");
+ goto fail;
+ }
+
+ impl_value.Type = MFX_VARIANT_TYPE_U32;
+ impl_value.Data.U32 = (implementation == MFX_IMPL_SOFTWARE) ?
+ MFX_IMPL_TYPE_SOFTWARE : MFX_IMPL_TYPE_HARDWARE;
+ sts = MFXSetConfigFilterProperty(cfg,
+ (const mfxU8 *)"mfxImplDescription.Impl", impl_value);
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration "
+ "property: %d.\n", sts);
+ goto fail;
+ }
+
+ impl_value.Type = MFX_VARIANT_TYPE_U32;
+
+ if (MFX_HANDLE_VA_DISPLAY == handle_type)
+ impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_VAAPI;
+ else if (MFX_HANDLE_D3D9_DEVICE_MANAGER == handle_type)
+ impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_D3D9;
+ else
+ impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_D3D11;
+
+ sts = MFXSetConfigFilterProperty(cfg,
+ (const mfxU8 *)"mfxImplDescription.AccelerationMode", impl_value);
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
+ "MFX_ACCEL_MODE_VIA_D3D9 property: %d.\n", sts);
+ goto fail;
+ }
+
+ impl_value.Type = MFX_VARIANT_TYPE_U32;
+ impl_value.Data.U32 = pver->Version;
+ sts = MFXSetConfigFilterProperty(cfg,
+ (const mfxU8 *)"mfxImplDescription.ApiVersion.Version",
+ impl_value);
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration "
+ "property: %d.\n", sts);
+ goto fail;
+ }
+
+ while (1) {
+ /* Enumerate all implementations */
+ mfxImplDescription *impl_desc;
+
+ sts = MFXEnumImplementations(loader, impl_idx,
+ MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
+ (mfxHDL *)&impl_desc);
+
+ /* Failed to find an available implementation */
+ if (sts == MFX_ERR_NOT_FOUND)
+ break;
+ else if (sts != MFX_ERR_NONE) {
+ impl_idx++;
+ continue;
+ }
+
+ sts = MFXCreateSession(loader, impl_idx, &session);
+ MFXDispReleaseImplDescription(loader, impl_desc);
+
+ if (sts == MFX_ERR_NONE)
+ break;
+
+ impl_idx++;
+ }
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error creating a MFX session: %d.\n", sts);
+ goto fail;
+ }
+
+ sts = MFXQueryVersion(session, &ver);
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error querying a MFX session: %d.\n", sts);
+ goto fail;
+ }
+
+ av_log(ctx, AV_LOG_VERBOSE, "Initialize MFX session: implementation "
+ "version is %d.%d\n", ver.Major, ver.Minor);
+
+ *psession = session;
+ *ploader = loader;
+
+ return 0;
+
+fail:
+ if (session)
+ MFXClose(session);
+
+ MFXUnload(loader);
+
+ return AVERROR_UNKNOWN;
+}
+
+#else
+
+static int qsv_create_mfx_session(void *ctx,
+ mfxHandleType handle_type,
+ mfxIMPL implementation,
+ mfxVersion *pver,
+ mfxSession *psession,
+ mfxLoader *ploader)
+{
+ mfxVersion ver;
+ mfxStatus sts;
+ mfxSession session = NULL;
+
+ av_log(ctx, AV_LOG_VERBOSE,
+ "Use Intel(R) Media SDK to create MFX session, API version is "
+ "%d.%d, the required implementation version is %d.%d\n",
+ MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
+
+ if (handle_type != MFX_HANDLE_VA_DISPLAY &&
+ handle_type != MFX_HANDLE_D3D9_DEVICE_MANAGER) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Invalid MFX device handle\n");
+ return AVERROR(EXDEV);
+ }
+
+ *ploader = NULL;
+ *psession = NULL;
+ ver = *pver;
+ sts = MFXInit(implementation, &ver, &session);
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
+ "%d.\n", sts);
+ goto fail;
+ }
+
+ sts = MFXQueryVersion(session, &ver);
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error querying an MFX session: "
+ "%d.\n", sts);
+ goto fail;
+ }
+
+ av_log(ctx, AV_LOG_VERBOSE, "Initialize MFX session: implementation "
+ "version is %d.%d\n", ver.Major, ver.Minor);
+
+ MFXClose(session);
+ sts = MFXInit(implementation, &ver, &session);
+
+ if (sts != MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
+ "%d.\n", sts);
+ goto fail;
+ }
+
+ *psession = session;
+
+ return 0;
+
+fail:
+ if (session)
+ MFXClose(session);
+
+ return AVERROR_UNKNOWN;
+}
+
+#endif
+
static int qsv_init_internal_session(AVHWFramesContext *ctx,
- mfxSession *session, int upload)
+ mfxSession *session, mfxLoader *loader,
+ int upload)
{
AVQSVFramesContext *frames_hwctx = ctx->hwctx;
QSVDeviceContext *device_priv = ctx->device_ctx->internal->priv;
@@ -555,29 +774,35 @@ static int qsv_init_internal_session(AVHWFramesContext *ctx,
mfxVideoParam par;
mfxStatus err;
+ int ret = AVERROR_UNKNOWN;
#if QSV_HAVE_OPAQUE
QSVFramesContext *s = ctx->internal->priv;
opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
#endif
- err = MFXInit(device_priv->impl, &device_priv->ver, session);
- if (err != MFX_ERR_NONE) {
- av_log(ctx, AV_LOG_ERROR, "Error initializing an internal session\n");
- return AVERROR_UNKNOWN;
- }
+ ret = qsv_create_mfx_session(ctx, device_priv->handle_type,
+ device_priv->impl, &device_priv->ver, session,
+ loader);
+
+ if (ret)
+ goto fail;
if (device_priv->handle) {
err = MFXVideoCORE_SetHandle(*session, device_priv->handle_type,
device_priv->handle);
- if (err != MFX_ERR_NONE)
- return AVERROR_UNKNOWN;
+ if (err != MFX_ERR_NONE) {
+ ret = AVERROR_UNKNOWN;
+ goto fail;
+ }
}
if (!opaque) {
err = MFXVideoCORE_SetFrameAllocator(*session, &frame_allocator);
- if (err != MFX_ERR_NONE)
- return AVERROR_UNKNOWN;
+ if (err != MFX_ERR_NONE) {
+ ret = AVERROR_UNKNOWN;
+ goto fail;
+ }
}
memset(&par, 0, sizeof(par));
@@ -613,11 +838,22 @@ static int qsv_init_internal_session(AVHWFramesContext *ctx,
if (err != MFX_ERR_NONE) {
av_log(ctx, AV_LOG_VERBOSE, "Error opening the internal VPP session."
"Surface upload/download will not be possible\n");
- MFXClose(*session);
- *session = NULL;
+
+ ret = AVERROR_UNKNOWN;
+ goto fail;
}
return 0;
+
+fail:
+ if (*session)
+ MFXClose(*session);
+
+ MFXUnload(*loader);
+ *session = NULL;
+ *loader = NULL;
+
+ return ret;
}
static int qsv_frames_init(AVHWFramesContext *ctx)
@@ -682,6 +918,9 @@ static int qsv_frames_init(AVHWFramesContext *ctx)
s->session_download = NULL;
s->session_upload = NULL;
+ s->loader_download = NULL;
+ s->loader_upload = NULL;
+
s->session_download_init = 0;
s->session_upload_init = 0;
@@ -979,7 +1218,8 @@ static int qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst,
if (pthread_mutex_trylock(&s->session_lock) == 0) {
#endif
if (!s->session_download_init) {
- ret = qsv_init_internal_session(ctx, &s->session_download, 0);
+ ret = qsv_init_internal_session(ctx, &s->session_download,
+ &s->loader_download, 0);
if (s->session_download)
s->session_download_init = 1;
}
@@ -1053,7 +1293,8 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
if (pthread_mutex_trylock(&s->session_lock) == 0) {
#endif
if (!s->session_upload_init) {
- ret = qsv_init_internal_session(ctx, &s->session_upload, 1);
+ ret = qsv_init_internal_session(ctx, &s->session_upload,
+ &s->loader_upload, 1);
if (s->session_upload)
s->session_upload_init = 1;
}
@@ -1319,6 +1560,7 @@ static void qsv_device_free(AVHWDeviceContext *ctx)
if (hwctx->session)
MFXClose(hwctx->session);
+ MFXUnload(hwctx->loader);
av_buffer_unref(&priv->child_device_ctx);
av_freep(&priv);
}
@@ -1408,34 +1650,11 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx,
goto fail;
}
- err = MFXInit(implementation, &ver, &hwctx->session);
- if (err != MFX_ERR_NONE) {
- av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
- "%d.\n", err);
- ret = AVERROR_UNKNOWN;
- goto fail;
- }
+ ret = qsv_create_mfx_session(ctx, handle_type, implementation, &ver,
+ &hwctx->session, &hwctx->loader);
- err = MFXQueryVersion(hwctx->session, &ver);
- if (err != MFX_ERR_NONE) {
- av_log(ctx, AV_LOG_ERROR, "Error querying an MFX session: %d.\n", err);
- ret = AVERROR_UNKNOWN;
+ if (ret)
goto fail;
- }
-
- av_log(ctx, AV_LOG_VERBOSE,
- "Initialize MFX session: API version is %d.%d, implementation version is %d.%d\n",
- MFX_VERSION_MAJOR, MFX_VERSION_MINOR, ver.Major, ver.Minor);
-
- MFXClose(hwctx->session);
-
- err = MFXInit(implementation, &ver, &hwctx->session);
- if (err != MFX_ERR_NONE) {
- av_log(ctx, AV_LOG_ERROR,
- "Error initializing an MFX session: %d.\n", err);
- ret = AVERROR_UNKNOWN;
- goto fail;
- }
err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle);
if (err != MFX_ERR_NONE) {
@@ -1450,6 +1669,8 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx,
fail:
if (hwctx->session)
MFXClose(hwctx->session);
+
+ MFXUnload(hwctx->loader);
return ret;
}
@@ -1492,6 +1713,16 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
}
} else if (CONFIG_VAAPI) {
child_device_type = AV_HWDEVICE_TYPE_VAAPI;
+#if QSV_ONEVPL
+ } else if (CONFIG_D3D11VA) { // Use D3D11 by default if d3d11va is enabled
+ av_log(NULL, AV_LOG_WARNING,
+ "WARNING: defaulting child_device_type to AV_HWDEVICE_TYPE_D3D11VA for "
+ "oneVPL. Please explicitly set child device type via \"-init_hw_device\" "
+ "option if needed.\n");
+ child_device_type = AV_HWDEVICE_TYPE_D3D11VA;
+ } else if (CONFIG_DXVA2) {
+ child_device_type = AV_HWDEVICE_TYPE_DXVA2;
+#else
} else if (CONFIG_DXVA2) {
av_log(NULL, AV_LOG_WARNING,
"WARNING: defaulting child_device_type to AV_HWDEVICE_TYPE_DXVA2 for compatibility "
@@ -1500,6 +1731,7 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
child_device_type = AV_HWDEVICE_TYPE_DXVA2;
} else if (CONFIG_D3D11VA) {
child_device_type = AV_HWDEVICE_TYPE_D3D11VA;
+#endif
} else {
av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n");
return AVERROR(ENOSYS);
@@ -1526,6 +1758,16 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
#endif
#if CONFIG_DXVA2
case AV_HWDEVICE_TYPE_DXVA2:
+#if QSV_ONEVPL
+ {
+ av_log(NULL, AV_LOG_WARNING,
+ "WARNING: d3d11va is not available or child device type is "
+ "set to dxva2 explicitly for oneVPL. Note dxva2 is supported "
+ "only in compatibility mode and new oneVPL features may not "
+ "be supported. Please stick with Intel(R) Media SDK if dxva2 "
+ "is desired.\n"
+ }
+#endif
break;
#endif
default:
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
index 42e34d0dda..65415d3d8c 100644
--- a/libavutil/hwcontext_qsv.h
+++ b/libavutil/hwcontext_qsv.h
@@ -19,8 +19,23 @@
#ifndef AVUTIL_HWCONTEXT_QSV_H
#define AVUTIL_HWCONTEXT_QSV_H
+#include <mfxdefs.h>
#include <mfxvideo.h>
+#if (MFX_VERSION_MAJOR < 2)
+
+typedef void * mfxLoader;
+
+static av_always_inline void MFXUnload (mfxLoader mfxloader)
+{
+}
+
+#else
+
+#include <mfxdispatcher.h>
+
+#endif
+
/**
* @file
* An API-specific header for AV_HWDEVICE_TYPE_QSV.
@@ -33,6 +48,7 @@
* This struct is allocated as AVHWDeviceContext.hwctx
*/
typedef struct AVQSVDeviceContext {
+ mfxLoader loader;
mfxSession session;
} AVQSVDeviceContext;
--
2.17.1
More information about the ffmpeg-devel
mailing list