From 6900feef0683a9fbad3f1106e0dbd5de243d71e0 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 4 Jan 2021 10:46:14 +0800 Subject: lavc/qsv: create mfx session using oneVPL for decoding/encoding If qsv hwdevice is available, use the mfxLoader handle in qsv hwdevice to create mfx session. Otherwise create mfx session with a new mfxLoader handle. This is in preparation for oneVPL support --- libavcodec/qsv.c | 226 ++++++++++++++++++++++++++++++++++++++++++---- libavcodec/qsv_internal.h | 1 + libavcodec/qsvdec.c | 11 +++ 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 - 9 files changed, 223 insertions(+), 23 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 #endif +#if QSV_ONEVPL +#include +#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 diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index d52f0dcd15..f914956596 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -103,6 +103,7 @@ typedef struct QSVSession { AVBufferRef *va_device_ref; AVHWDeviceContext *va_device_ctx; #endif + void *loader; } QSVSession; typedef struct QSVFramesContext { diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 8b718a08ff..89ec5dcee8 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -50,6 +50,12 @@ #include "qsv.h" #include "qsv_internal.h" +#if QSV_ONEVPL +#include +#else +#define MFXUnload(a) do { } while(0) +#endif + static const AVRational mfx_tb = { 1, 90000 }; #define PTS_TO_MFX_PTS(pts, pts_tb) ((pts) == AV_NOPTS_VALUE ? \ @@ -231,6 +237,11 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses q->internal_qs.session = NULL; } + if (q->internal_qs.loader) { + MFXUnload(q->internal_qs.loader); + q->internal_qs.loader = NULL; + } + return AVERROR_EXTERNAL; } diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index c2def19658..d35a1318f2 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -28,6 +28,9 @@ #include +#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 64c22852d2..ad9cf629df 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -32,7 +32,6 @@ #include "avcodec.h" #include "codec_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 1d92b8ec13..e11f5dec4a 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -35,7 +35,6 @@ #include "hevcdec.h" #include "h2645_parse.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 582886c7c0..6d17d896eb 100644 --- a/libavcodec/qsvenc_jpeg.c +++ b/libavcodec/qsvenc_jpeg.c @@ -30,7 +30,6 @@ #include "avcodec.h" #include "codec_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 8ed578c396..5666b3e6e2 100644 --- a/libavcodec/qsvenc_mpeg2.c +++ b/libavcodec/qsvenc_mpeg2.c @@ -30,7 +30,6 @@ #include "avcodec.h" #include "codec_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 7ae392da75..c738da3904 100644 --- a/libavcodec/qsvenc_vp9.c +++ b/libavcodec/qsvenc_vp9.c @@ -30,7 +30,6 @@ #include "avcodec.h" #include "codec_internal.h" #include "qsv.h" -#include "qsv_internal.h" #include "qsvenc.h" typedef struct QSVVP9EncContext { -- cgit v1.2.3