summaryrefslogtreecommitdiff
path: root/libavcodec/qsv.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/qsv.c')
-rw-r--r--libavcodec/qsv.c226
1 files changed, 208 insertions, 18 deletions
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index be553c8c26..3449789a2c 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -45,6 +45,12 @@
#include <mfxplugin.h>
#endif
+#if QSV_ONEVPL
+#include <mfxdispatcher.h>
+#else
+#define MFXUnload(a) do { } while(0)
+#endif
+
int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
{
switch (codec_id) {
@@ -425,6 +431,193 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
}
#endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
+#if QSV_ONEVPL
+static int qsv_new_mfx_loader(AVCodecContext *avctx,
+ mfxIMPL implementation,
+ mfxVersion *pver,
+ void **ploader)
+{
+ mfxStatus sts;
+ mfxLoader loader = NULL;
+ mfxConfig cfg;
+ mfxVariant impl_value;
+
+ 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;
+ }
+
+ *ploader = loader;
+
+ return 0;
+
+fail:
+ if (loader)
+ MFXUnload(loader);
+
+ *ploader = NULL;
+ return AVERROR_UNKNOWN;
+}
+
+static int qsv_create_mfx_session_from_loader(void *ctx, mfxLoader loader, mfxSession *psession)
+{
+ mfxStatus sts;
+ mfxSession session = NULL;
+ uint32_t impl_idx = 0;
+
+ 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;
+ }
+
+ *psession = session;
+
+ return 0;
+
+fail:
+ if (session)
+ MFXClose(session);
+
+ *psession = NULL;
+ return AVERROR_UNKNOWN;
+}
+
+static int qsv_create_mfx_session(AVCodecContext *avctx,
+ mfxIMPL implementation,
+ mfxVersion *pver,
+ int gpu_copy,
+ mfxSession *psession,
+ void **ploader)
+{
+ mfxLoader loader = 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);
+
+ if (qsv_new_mfx_loader(avctx, implementation, pver, (void **)&loader))
+ goto fail;
+
+ av_assert0(loader);
+ } else {
+ av_log(avctx, AV_LOG_VERBOSE,
+ "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
+
+ loader = *ploader;
+ }
+
+ if (qsv_create_mfx_session_from_loader(avctx, loader, psession))
+ goto fail;
+
+ 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,
+ void **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;
+
+ init_par.GPUCopy = gpu_copy;
+ 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)
{
@@ -434,18 +627,12 @@ 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;
-
- init_par.GPUCopy = gpu_copy;
- 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");
+ int ret = qsv_create_mfx_session(avctx, impl, &ver, gpu_copy, &qs->session,
+ &qs->loader);
+ if (ret)
+ return ret;
#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
ret = ff_qsv_set_display_handle(avctx, qs);
@@ -749,7 +936,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 };
+ void *loader = device_hwctx->loader;
mfxHDL handle = NULL;
int hw_handle_supported = 0;
@@ -790,13 +977,10 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
"from the session\n");
}
- init_par.GPUCopy = gpu_copy;
- 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);
@@ -875,6 +1059,12 @@ int ff_qsv_close_internal_session(QSVSession *qs)
MFXClose(qs->session);
qs->session = NULL;
}
+
+ if (qs->loader) {
+ MFXUnload(qs->loader);
+ qs->loader = NULL;
+ }
+
#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
av_buffer_unref(&qs->va_device_ref);
#endif