From patchwork Mon Aug 16 07:33:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xiang, Haihao" X-Patchwork-Id: 29554 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6602:2a4a:0:0:0:0 with SMTP id k10csp1800275iov; Mon, 16 Aug 2021 00:35:21 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzGF9OFK8Acg+BOfZwecfn61NFdZt6EdImmASewhMTcL1qMgFsmTiKdNYRKgZsDSnbum0Nk X-Received: by 2002:aa7:da8c:: with SMTP id q12mr18496401eds.304.1629099321228; Mon, 16 Aug 2021 00:35:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629099321; cv=none; d=google.com; s=arc-20160816; b=dpkQnaDkMCGogAF9BZhLQ4MseOcipQmdDhNnBkxcHHp7aytvImWxcXLyrSph6+t7q+ GU9cZxry3yU2wWgYP2+8bZfWHDj6qZpO72nIGV4ve3k/uZ4J9WbPfKukrzmRJ+xJxcg5 0hpXtlOebIQ5VF6Sy77ivr0I7WJ5Jq/SFFAxL7+qkERgXHivDJMbvRlSQ2PE7LNYQr6H TaKfQF9/ADZRTGkkrRQXRd953SbHk388mE24rmf70Ud0+twpGzAdL+aYll5KLqKrsM3u RooSRJGTv2yiZJtcUaxid0vkOXweT5VNsBF+oppQlA98M4sxdkP3Q861EqOi9IkU3LKf NfuA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:delivered-to; bh=7ps33u2VSm4Lhkz9SuvGh6iPygMyI/KhF3jOsgbJ4e4=; b=YMR4XPbbwFwnhj5o9xBp8D6cpnRNRqyzdqOsZaK6wiSiH4svDlKz7mPeTgJWSOyu/Y 6H/2jockUYZb9ToOg8oF/7smtA4BmQIRJsD1vGsjSj5ck66GC4ONgtyA+Eym7QUMq/W3 wlH6CSfmuPqc6M+wsjcyjCuvl+8Scr8+P4EFWEyqohBR80InMRL6/Tpj83uylvB7688y qvhgZX6yrDebnY1kGf7geXf54F0BHD6zpVWFU/XHSP3Ul4/tulvuf8ioeE2oEEOtW4AO M/vIuYlf12xTDwYUNkdLxnlZ+EJq15elgfk90nVwF4Kr5zqqvUe9a1V5V53P1IBs72bM 3vcg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id o23si10202836edt.314.2021.08.16.00.35.20; Mon, 16 Aug 2021 00:35:21 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4972D68A5D1; Mon, 16 Aug 2021 10:34:03 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6F87E68A5AA for ; Mon, 16 Aug 2021 10:33:56 +0300 (EEST) X-IronPort-AV: E=McAfee;i="6200,9189,10077"; a="279553925" X-IronPort-AV: E=Sophos;i="5.84,324,1620716400"; d="scan'208";a="279553925" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Aug 2021 00:33:54 -0700 X-IronPort-AV: E=Sophos;i="5.84,324,1620716400"; d="scan'208";a="519461892" Received: from xhh-dg164.sh.intel.com ([10.239.159.167]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Aug 2021 00:33:48 -0700 From: Haihao Xiang To: ffmpeg-devel@ffmpeg.org Date: Mon, 16 Aug 2021 15:33:24 +0800 Message-Id: <20210816073325.27020-10-haihao.xiang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210816073325.27020-1-haihao.xiang@intel.com> References: <20210816073325.27020-1-haihao.xiang@intel.com> Subject: [FFmpeg-devel] [PATCH v2 09/10] qsv: use a new method to create mfx session when using the oneVPL SDK X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Haihao Xiang , galinart MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: Bd0P77r1lUIB In oneVPL, MFXLoad() and MFXCreateSession() are required to create a workable mfx session[1] Add AccelerationMode config filter for D3D9 session (galinart) 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 --- 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 | 300 ++++++++++++++++++++++++++----- libavutil/hwcontext_qsv.h | 16 ++ 15 files changed, 569 insertions(+), 89 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 98fc6a92b6..bfa9cad8a2 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -383,25 +383,176 @@ 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 the Intel oneVPL SDK 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 the Intel oneVPL SDK 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 the Intel 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) { mfxIMPL impl = MFX_IMPL_AUTO_ANY; 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); @@ -701,7 +852,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; mfxSession session; @@ -732,15 +883,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); @@ -817,7 +964,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 2afb46167d..83a4495325 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 +#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 b3adfb9296..63990f5df3 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" @@ -604,13 +602,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); @@ -909,3 +905,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 the Intel oneVPL SDK 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 the Intel 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 57efa1a791..bb27cca63a 100644 --- a/libavfilter/vf_deinterlace_qsv.c +++ b/libavfilter/vf_deinterlace_qsv.c @@ -170,7 +170,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); @@ -201,13 +201,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 9bb5906141..ac0c58388b 100644 --- a/libavfilter/vf_scale_qsv.c +++ b/libavfilter/vf_scale_qsv.c @@ -289,7 +289,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); @@ -322,11 +322,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 5a93d7f3bf..cbff9916e1 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -51,6 +51,8 @@ #define QSV_ONEVPL QSV_VERSION_ATLEAST(2, 0) #define QSV_HAVE_OPAQUE !QSV_ONEVPL +#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) + typedef struct QSVDevicePriv { AVBufferRef *child_device_ctx; } QSVDevicePriv; @@ -67,8 +69,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; @@ -173,15 +177,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 @@ -450,8 +458,218 @@ 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 the Intel oneVPL 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); + } + + *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 + impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_D3D9; + + 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 the Intel 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; @@ -468,29 +686,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)); @@ -526,11 +750,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) @@ -595,6 +830,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; @@ -850,7 +1088,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; } @@ -924,7 +1163,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; } @@ -1121,6 +1361,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); } @@ -1194,34 +1435,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) { @@ -1236,6 +1454,8 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx, fail: if (hwctx->session) MFXClose(hwctx->session); + + MFXUnload(hwctx->loader); return ret; } 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 #include +#if (MFX_VERSION_MAJOR < 2) + +typedef void * mfxLoader; + +static av_always_inline void MFXUnload (mfxLoader mfxloader) +{ +} + +#else + +#include + +#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;