From patchwork Mon Sep 23 07:10:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wang, Fei W" X-Patchwork-Id: 51732 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a59:d154:0:b0:48e:c0f8:d0de with SMTP id bt20csp2302577vqb; Mon, 23 Sep 2024 01:24:18 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUzvDAAShciywlOayz7ykpR2MsBkDoZ2ox06ZIdbEOBQBdofdQwK8QPSj9kx2H0pfkAm1bnIX52M7ngRMuMUWxp@gmail.com X-Google-Smtp-Source: AGHT+IEn68ZOSmc3t0xbVFAVp4NoKxy82zYDtnHqYOSkQiV2OU60FozEepgnBtoNNrNpPi1zAYE5 X-Received: by 2002:a05:651c:1543:b0:2f7:c7f3:1d2e with SMTP id 38308e7fff4ca-2f7cb31c4e8mr59350581fa.19.1727079857767; Mon, 23 Sep 2024 01:24:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1727079857; cv=none; d=google.com; s=arc-20240605; b=EdiTu8ya7fnk7nHJiaifG9SCTeuhFA44OWhckgWyFOzFP/GJ3OFlw7/bvyvsYZc9IX tHwuHbpdL/MBM8bcrZJSbEe9KdgfpQaOQivrQCP9WqIkJRm8s7WoUZBItLJX5bc4H/4f fAmbxrVE09LhoStXV75O+jdgE45V9jtDdCROkCaAL70EDf6zQKSxXLTOcDJ/xGeROpWr X+lAFD0IyMluigh8CW5m/2h6XRjdSduK46+YjyyW4BJi4Ricz8ilml/m7bbLeoOorufS 4UicDTB+WJzIWF37XSddcGaFqI06X5KI4H3kG3zNYrznKoQd2gDfgwoxvVwFCtQi0++c a07A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=H9QqfF6zaUeISKOYqdAO9E1dCwr7qG4qdu6pScm5V1A=; fh=i4ESP4ZRFDcfYfwXKWpOXjc2YhmIGuOsCfZUnwNO0gc=; b=ZaDj26z1xmsMCBJsrxineEeo6rz81Vrd6Koth3yYDUFAb7gcXviVy1ZWuUkEvin4Sq Ai8BFrNX5ulVvTp/Z3RdUvB7qFELbpxSFkr2lbwUMIppoxUGWZGKdPeuxtHMauY22t7N BH0beYpiBsBUYVWqttPL+C5WtJeS1yXFnyadXZyjlhQtNm6t5U1S2+lkDHM86XhP11qz fECDbPERQuUJUJ5iMlo2LbPfdy4IPxxd2zWcXv1ian3Twl3Z33Lu8oOFlxMuvMuMv99Y VPrfJIWEJoNmmTchPmhIN29goxzMPeDvmLvQjc2Cn43MVhqELE32Y9EitSVYUBfXK3E8 T16w==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@intel.com header.s=Intel header.b=T+gLOYoQ; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id 38308e7fff4ca-2f79d2c80c9si61881961fa.47.2024.09.23.01.24.17; Mon, 23 Sep 2024 01:24:17 -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; dkim=neutral (body hash did not verify) header.i=@intel.com header.s=Intel header.b=T+gLOYoQ; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3188768DBA0; Mon, 23 Sep 2024 10:07:53 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 353B168D7CA for ; Mon, 23 Sep 2024 10:07:45 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1727075270; x=1758611270; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Yz9I+msC6VMnyYmvZCJIS6xBqcac2oRJKCNrGb0kGOM=; b=T+gLOYoQCUKa1Ug9Bz18zCJTJsXXUsdLjGvDoJgvuSqQilcJFPKjKBh8 p+YRJdhlJdt/yohKwReh1JIU+y096rTvKiEarIR+go+B2xy2AYBtz3f0t TiDsNBdwWVnSq6EPZJgW3qx8xDrKL+iGBqAyquLce1k22tuG0vEIhCWWS A4xjeNj1W3ES0dTgGzlGjvd6J46nfQuWzq+7bLiinIrDi01saVmf4Kwo5 2MFhfC7swddupt7QthpifHGEDFTMUVcKbXC0YM2sJqzVWjrULJUYCuDoh JpvDK7UHuj0lwxC2OkwfyL8zxLolxfoe2Ak6YE7+Nxi/mCXCKCBojCYjG Q==; X-CSE-ConnectionGUID: VzucUHEeRmeUAHwxCbXNuQ== X-CSE-MsgGUID: D6zzZpN8RtyGT7KUPVid2Q== X-IronPort-AV: E=McAfee;i="6700,10204,11202"; a="43525029" X-IronPort-AV: E=Sophos;i="6.10,250,1719903600"; d="scan'208";a="43525029" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Sep 2024 00:07:42 -0700 X-CSE-ConnectionGUID: GCha8a2vQhCmzZRSQ0/4lg== X-CSE-MsgGUID: XxC/l5A6TaKiEtu4n9TMog== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.10,250,1719903600"; d="scan'208";a="70560529" Received: from feiwan1-desk3.sh.intel.com ([10.238.208.39]) by fmviesa007.fm.intel.com with ESMTP; 23 Sep 2024 00:07:41 -0700 From: fei.w.wang-at-intel.com@ffmpeg.org To: ffmpeg-devel@ffmpeg.org Date: Mon, 23 Sep 2024 15:10:06 +0800 Message-Id: <20240923071008.1599696-3-fei.w.wang@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240923071008.1599696-1-fei.w.wang@intel.com> References: <20240923071008.1599696-1-fei.w.wang@intel.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/5] lavc/qsvenc: Support calculate encoded frame quality(MSE/PSNR) when encoding 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: fei.w.wang@intel.com Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: O8Y4AQW2ym6H From: Fei Wang Once the '-mse' option enabled, MSE/PSNR of each frame will be shown in VERBOSE debug level log. Signed-off-by: Fei Wang --- doc/encoders.texi | 4 + libavcodec/qsvenc.c | 162 +++++++++++++++++++++++++++++++++++---- libavcodec/qsvenc.h | 12 +++ libavcodec/qsvenc_av1.c | 3 + libavcodec/qsvenc_h264.c | 3 + libavcodec/qsvenc_hevc.c | 3 + 6 files changed, 173 insertions(+), 14 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index 85be976a46..7d1373e0e0 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3624,6 +3624,10 @@ ffmpeg -i input.mp4 -c:v h264_qsv -qsv_params "CodingOption1=1:CodingOption2=2" @end example This option allows fine-grained control over various encoder-specific settings provided by the QSV encoder. + +@item @var{mse} +Supported in h264_qsv, hevc_qsv, and av1_qsv on Windows. Output encoded +frame's quality(MSE/PSNR) information in VERBOSE log. @end table @subsection H264 options diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index dfef15fa5a..cd89656f74 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -95,6 +95,9 @@ typedef struct QSVPacket { AVPacket pkt; mfxSyncPoint *sync; mfxBitstream *bs; + int bs_buf_num; + int frameinfo_buf_idx; + int mse_buf_idx; } QSVPacket; static const char *print_profile(enum AVCodecID codec_id, mfxU16 profile) @@ -206,6 +209,9 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, #if QSV_HAVE_AC mfxExtAlphaChannelEncCtrl *extalphachannel = NULL; #endif +#if QSV_HAVE_MSE + mfxExtQualityInfoMode *extmse = NULL; +#endif const char *tmp_str = NULL; @@ -228,6 +234,11 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, extalphachannel = (mfxExtAlphaChannelEncCtrl *)coding_opts[q->extaplhachannel_idx]; #endif +#if QSV_HAVE_MSE + if (q->extmse_idx > 0) + extmse = (mfxExtQualityInfoMode *)coding_opts[q->extmse_idx]; +#endif + av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n", print_profile(avctx->codec_id, info->CodecProfile), info->CodecLevel); @@ -425,6 +436,22 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, av_log(avctx, AV_LOG_VERBOSE, "\n"); } #endif + +#if QSV_HAVE_MSE + if (extmse) { + av_log(avctx, AV_LOG_VERBOSE, "MSE: "); + + if (extmse->QualityInfoMode == MFX_QUALITY_INFO_LEVEL_FRAME) + av_log(avctx, AV_LOG_VERBOSE, "ON"); + else if (extmse->QualityInfoMode == MFX_QUALITY_INFO_DISABLE) + av_log(avctx, AV_LOG_VERBOSE, "OFF"); + else + av_log(avctx, AV_LOG_VERBOSE, "unknown"); + + av_log(avctx, AV_LOG_VERBOSE, "\n"); + } +#endif + } static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q, @@ -522,6 +549,9 @@ static void dump_video_av1_param(AVCodecContext *avctx, QSVEncContext *q, #if QSV_HAVE_EXT_AV1_SCC mfxExtAV1ScreenContentTools *scc = (mfxExtAV1ScreenContentTools*)coding_opts[4]; #endif +#if QSV_HAVE_MSE + mfxExtQualityInfoMode *mse = (mfxExtQualityInfoMode*)coding_opts[5]; +#endif av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n", print_profile(avctx->codec_id, info->CodecProfile), info->CodecLevel); @@ -602,6 +632,21 @@ static void dump_video_av1_param(AVCodecContext *avctx, QSVEncContext *q, print_threestate(scc->Palette), print_threestate(scc->IntraBlockCopy)); } #endif + +#if QSV_HAVE_MSE + if (mse) { + av_log(avctx, AV_LOG_VERBOSE, "MSE: "); + + if (mse->QualityInfoMode == MFX_QUALITY_INFO_LEVEL_FRAME) + av_log(avctx, AV_LOG_VERBOSE, "ON"); + else if (mse->QualityInfoMode == MFX_QUALITY_INFO_DISABLE) + av_log(avctx, AV_LOG_VERBOSE, "OFF"); + else + av_log(avctx, AV_LOG_VERBOSE, "unknown"); + + av_log(avctx, AV_LOG_VERBOSE, "\n"); + } +#endif } #endif @@ -1372,6 +1417,21 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) } #endif +#if QSV_HAVE_MSE + if (q->mse) { + if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 2, 13)) { + q->extmseparam.Header.BufferId = MFX_EXTBUFF_ENCODED_QUALITY_INFO_MODE; + q->extmseparam.Header.BufferSz = sizeof(q->extmseparam); + q->extmseparam.QualityInfoMode = MFX_QUALITY_INFO_LEVEL_FRAME; + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extmseparam; + } else { + av_log(avctx, AV_LOG_ERROR, + "This version of runtime doesn't support Mean Squared Error\n"); + return AVERROR_UNKNOWN; + } + } +#endif + if (!check_enc_param(avctx,q)) { av_log(avctx, AV_LOG_ERROR, "some encoding parameters are not supported by the QSV " @@ -1486,6 +1546,12 @@ static int qsv_retrieve_enc_av1_params(AVCodecContext *avctx, QSVEncContext *q) }; #endif +#if QSV_HAVE_MSE + mfxExtQualityInfoMode mse_buf = { + .Header.BufferId = MFX_EXTBUFF_ENCODED_QUALITY_INFO_MODE, + .Header.BufferSz = sizeof(mse_buf), + }; +#endif mfxExtBuffer *ext_buffers[] = { (mfxExtBuffer*)&av1_extend_tile_buf, (mfxExtBuffer*)&av1_bs_param, @@ -1493,6 +1559,9 @@ static int qsv_retrieve_enc_av1_params(AVCodecContext *avctx, QSVEncContext *q) (mfxExtBuffer*)&co3, #if QSV_HAVE_EXT_AV1_SCC (mfxExtBuffer*)&scc_buf, +#endif +#if QSV_HAVE_MSE + (mfxExtBuffer*)&mse_buf, #endif }; @@ -1570,7 +1639,14 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) }; #endif - mfxExtBuffer *ext_buffers[6 + QSV_HAVE_HE + QSV_HAVE_AC]; +#if QSV_HAVE_MSE + mfxExtQualityInfoMode mse_buf = { + .Header.BufferId = MFX_EXTBUFF_ENCODED_QUALITY_INFO_MODE, + .Header.BufferSz = sizeof(mse_buf), + }; +#endif + + mfxExtBuffer *ext_buffers[6 + QSV_HAVE_HE + QSV_HAVE_AC + QSV_HAVE_MSE]; int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO; int ret, ext_buf_num = 0, extradata_offset = 0; @@ -1613,6 +1689,13 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) } #endif +#if QSV_HAVE_MSE + if (q->mse && QSV_RUNTIME_VERSION_ATLEAST(q->ver, 2, 13)) { + q->extmse_idx = ext_buf_num; + ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&mse_buf; + } +#endif + q->param.ExtParam = ext_buffers; q->param.NumExtParam = ext_buf_num; @@ -2228,7 +2311,8 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, return ret; } } - qf->surface.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000}); + qf->surface.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000}); + qf->surface.Data.FrameOrder = MFX_FRAMEORDER_UNKNOWN; *new_frame = qf; @@ -2578,11 +2662,15 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, { QSVPacket pkt = { { 0 } }; mfxExtAVCEncodedFrameInfo *enc_info = NULL; +#if QSV_HAVE_MSE + mfxExtQualityInfoOutput *mse = NULL; +#endif mfxExtBuffer **enc_buf = NULL; mfxFrameSurface1 *surf = NULL; QSVFrame *qsv_frame = NULL; mfxEncodeCtrl* enc_ctrl = NULL; + mfxExtBuffer *bs_buf[2]; int ret; if (frame) { @@ -2622,13 +2710,30 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, enc_info->Header.BufferId = MFX_EXTBUFF_ENCODED_FRAME_INFO; enc_info->Header.BufferSz = sizeof (*enc_info); - pkt.bs->NumExtParam = 1; - enc_buf = av_mallocz(sizeof(mfxExtBuffer *)); - if (!enc_buf) + pkt.frameinfo_buf_idx = pkt.bs_buf_num; + bs_buf[pkt.bs_buf_num++] = (mfxExtBuffer *)enc_info; + } + +#if QSV_HAVE_MSE + if (q->mse) { + mse = av_mallocz(sizeof(*mse)); + if (!mse) goto nomem; - enc_buf[0] = (mfxExtBuffer *)enc_info; + mse->Header.BufferId = MFX_EXTBUFF_ENCODED_QUALITY_INFO_OUTPUT; + mse->Header.BufferSz = sizeof(*mse); + pkt.mse_buf_idx = pkt.bs_buf_num; + bs_buf[pkt.bs_buf_num++] = (mfxExtBuffer *)mse; + } +#endif + + if (pkt.bs_buf_num) { + enc_buf = av_mallocz(sizeof(mfxExtBuffer *) * pkt.bs_buf_num); + if (!enc_buf) + goto nomem; + memcpy(enc_buf, bs_buf, pkt.bs_buf_num * sizeof(mfxExtBuffer *)); pkt.bs->ExtParam = enc_buf; + pkt.bs->NumExtParam = pkt.bs_buf_num; } if (q->set_encode_ctrl_cb && enc_ctrl) { @@ -2683,8 +2788,13 @@ free: av_freep(&pkt.bs); if (avctx->codec_id == AV_CODEC_ID_H264) { av_freep(&enc_info); - av_freep(&enc_buf); } +#if QSV_HAVE_MSE + if (q->mse) + av_freep(&mse); +#endif + if (pkt.bs_buf_num) + av_freep(&enc_buf); } return ret; @@ -2770,7 +2880,7 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q, (!frame && av_fifo_can_read(q->async_fifo))) { QSVPacket qpkt; mfxExtAVCEncodedFrameInfo *enc_info; - mfxExtBuffer **enc_buf; + mfxExtBuffer *enc_buf; enum AVPictureType pict_type; av_fifo_read(q->async_fifo, &qpkt, 1); @@ -2803,13 +2913,29 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q, } if (avctx->codec_id == AV_CODEC_ID_H264) { - enc_buf = qpkt.bs->ExtParam; - enc_info = (mfxExtAVCEncodedFrameInfo *)(*enc_buf); + enc_buf = qpkt.bs->ExtParam[qpkt.frameinfo_buf_idx]; + enc_info = (mfxExtAVCEncodedFrameInfo *)enc_buf; ff_side_data_set_encoder_stats(&qpkt.pkt, enc_info->QP * FF_QP2LAMBDA, NULL, 0, pict_type); av_freep(&enc_info); - av_freep(&enc_buf); } +#if QSV_HAVE_MSE + if (q->mse) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + mfxExtQualityInfoOutput *mse; + enc_buf = qpkt.bs->ExtParam[qpkt.mse_buf_idx]; + mse = (mfxExtQualityInfoOutput *)enc_buf; + av_log(avctx, AV_LOG_VERBOSE, "Frame Display order:%d, MSE Y/U/V: %0.2f/%0.2f/%0.2f, " + "PSNR Y/U/V: %0.2f/%0.2f/%0.2f\n", + mse->FrameOrder, mse->MSE[0] / 256.0, mse->MSE[1] / 256.0, mse->MSE[2] / 256.0, + 10.0 * log10(pow(((1 << desc->comp[0].depth) -1), 2) / (mse->MSE[0] / 256.0)), + 10.0 * log10(pow(((1 << desc->comp[1].depth) -1), 2) / (mse->MSE[1] / 256.0)), + 10.0 * log10(pow(((1 << desc->comp[2].depth) -1), 2) / (mse->MSE[2] / 256.0))); + av_freep(&mse); + } +#endif + if (qpkt.bs_buf_num) + av_freep(&qpkt.bs->ExtParam); av_freep(&qpkt.bs); av_freep(&qpkt.sync); @@ -2847,11 +2973,19 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) QSVPacket pkt; while (av_fifo_read(q->async_fifo, &pkt, 1) >= 0) { if (avctx->codec_id == AV_CODEC_ID_H264) { - mfxExtBuffer **enc_buf = pkt.bs->ExtParam; - mfxExtAVCEncodedFrameInfo *enc_info = (mfxExtAVCEncodedFrameInfo *)(*enc_buf); + mfxExtBuffer *enc_buf = pkt.bs->ExtParam[pkt.frameinfo_buf_idx]; + mfxExtAVCEncodedFrameInfo *enc_info = (mfxExtAVCEncodedFrameInfo *)enc_buf; av_freep(&enc_info); - av_freep(&enc_buf); } +#if QSV_HAVE_MSE + if (q->mse) { + mfxExtBuffer *enc_buf = pkt.bs->ExtParam[pkt.mse_buf_idx]; + mfxExtQualityInfoOutput *mse = (mfxExtQualityInfoOutput *)enc_buf; + av_freep(&mse); + } +#endif + if (pkt.bs_buf_num) + av_freep(&pkt.bs->ExtParam); av_freep(&pkt.sync); av_freep(&pkt.bs); av_packet_unref(&pkt.pkt); diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 1e1474d37c..5aa0aae790 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -46,12 +46,14 @@ #define QSV_HAVE_MF 0 #define QSV_HAVE_HE QSV_VERSION_ATLEAST(2, 4) #define QSV_HAVE_AC QSV_VERSION_ATLEAST(2, 13) +#define QSV_HAVE_MSE QSV_VERSION_ATLEAST(2, 13) #else #define QSV_HAVE_AVBR 0 #define QSV_HAVE_VCM 0 #define QSV_HAVE_MF !QSV_ONEVPL #define QSV_HAVE_HE 0 #define QSV_HAVE_AC 0 +#define QSV_HAVE_MSE 0 #endif #define QSV_COMMON_OPTS \ @@ -151,6 +153,11 @@ { "brc_only", "skip_frame metadata indicates the number of missed frames before the current frame", \ 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SKIPFRAME_BRC_ONLY }, .flags = VE, .unit = "skip_frame" }, +#if QSV_HAVE_MSE +#define QSV_MSE_OPTIONS \ +{ "mse", "Enable output MSE(Mean Squared Error) of each frame", OFFSET(qsv.mse), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, +#endif + extern const AVCodecHWConfigInternal *const ff_qsv_enc_hw_configs[]; typedef int SetEncodeCtrlCB (AVCodecContext *avctx, @@ -197,6 +204,9 @@ typedef struct QSVEncContext { #if QSV_HAVE_EXT_AV1_SCC mfxExtAV1ScreenContentTools extsccparam; #endif +#if QSV_HAVE_MSE + mfxExtQualityInfoMode extmseparam; +#endif mfxExtVideoSignalInfo extvsi; @@ -282,6 +292,7 @@ typedef struct QSVEncContext { int extaplhachannel_idx; int exthevctiles_idx; int exthypermodeparam_idx; + int extmse_idx; int vp9_idx; int max_qp_i; @@ -333,6 +344,7 @@ typedef struct QSVEncContext { int alpha_encode; int palette_mode; int intrabc; + int mse; } QSVEncContext; int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); diff --git a/libavcodec/qsvenc_av1.c b/libavcodec/qsvenc_av1.c index 4f035f3d83..ee0617714a 100644 --- a/libavcodec/qsvenc_av1.c +++ b/libavcodec/qsvenc_av1.c @@ -183,6 +183,9 @@ static const AVOption options[] = { QSV_OPTION_EXTBRC QSV_OPTION_LOW_DELAY_BRC QSV_OPTION_MAX_FRAME_SIZE +#if QSV_HAVE_MSE + QSV_MSE_OPTIONS +#endif { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, .unit = "profile" }, { "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, .unit = "profile" }, { "main" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AV1_MAIN }, INT_MIN, INT_MAX, VE, .unit = "profile" }, diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 304d1e7dcb..0fc0c852ac 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -120,6 +120,9 @@ static const AVOption options[] = { #if QSV_HAVE_HE QSV_HE_OPTIONS #endif +#if QSV_HAVE_MSE + QSV_MSE_OPTIONS +#endif { "cavlc", "Enable CAVLC", OFFSET(qsv.cavlc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, #if QSV_HAVE_VCM diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 6ea9c4cdcb..8197e0958e 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -323,6 +323,9 @@ static const AVOption options[] = { #if QSV_HAVE_HE QSV_HE_OPTIONS #endif +#if QSV_HAVE_MSE + QSV_MSE_OPTIONS +#endif { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT_MAX, VE, .unit = "idr_interval" }, { "begin_only", "Output an IDR-frame only at the beginning of the stream", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, 0, 0, VE, .unit = "idr_interval" },