From patchwork Tue Jan 26 02:32:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wenbin Chen X-Patchwork-Id: 25187 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 15D5C44BD9F for ; Tue, 26 Jan 2021 04:36:18 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id EF78468A2B1; Tue, 26 Jan 2021 04:36:17 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id B1CA268A1D4 for ; Tue, 26 Jan 2021 04:36:09 +0200 (EET) IronPort-SDR: RXqPDqspkG5P5bj+wj1is3AcfKLi2qdPj+AUr4ilW2s2RxZ51L0syy4aH+Ut3QI/fN4qGreEsM xEBgDE2UpSfg== X-IronPort-AV: E=McAfee;i="6000,8403,9875"; a="159015226" X-IronPort-AV: E=Sophos;i="5.79,375,1602572400"; d="scan'208";a="159015226" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jan 2021 18:36:08 -0800 IronPort-SDR: vBtLia5WpPJY/CH4aXvqUfgwtfFq1oYsG852cFUHBvgSkQr2WFbZS7XNK+3vY03lp9rS3pL4ya WpfQ5hAcYaUw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,375,1602572400"; d="scan'208";a="361797117" Received: from chenwenbin-z390-aorus-ultra.sh.intel.com ([10.239.35.3]) by fmsmga008.fm.intel.com with ESMTP; 25 Jan 2021 18:36:07 -0800 From: wenbin.chen@intel.com To: ffmpeg-devel@ffmpeg.org Date: Tue, 26 Jan 2021 10:32:09 +0800 Message-Id: <20210126023213.146185-6-wenbin.chen@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210126023213.146185-1-wenbin.chen@intel.com> References: <20210126023213.146185-1-wenbin.chen@intel.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 06/10] libavcodec/qsvenc.c: add ROI support to qsv encoder X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 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: Wenbinc-Bin Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Wenbinc-Bin Use the mfxEncoderCtrl parameter to enable ROI. Get side data "AVRegionOfInterest" from filter "addroi" and use it to configure "mfxExtEncoderROI" which is the MediaSDK's ROI configuration. It is the first time to use encoderCtrl feature in ffmpeg-qsv, so add allocate and free process as well. Sigend-off-by: Wenbin Chen --- libavcodec/qsv_internal.h | 3 ++ libavcodec/qsvenc.c | 74 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index aa3da97c99..d846a2741a 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -51,6 +51,9 @@ #define ASYNC_DEPTH_DEFAULT 4 // internal parallelism #define QSV_MAX_ENC_PAYLOAD 2 // # of mfxEncodeCtrl payloads supported +#define QSV_MAX_ENC_EXTPARAM 2 + +#define QSV_MAX_ROI_NUM 256 #define QSV_PAYLOAD_SIZE 1024 diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index f2fcd09ae0..addc61bf89 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1291,6 +1291,13 @@ static void clear_unused_frames(QSVEncContext *q) QSVFrame *cur = q->work_frames; while (cur) { if (cur->used && !cur->surface.Data.Locked) { + + for (int i = 0; i < cur->enc_ctrl.NumExtParam; i++) { + if (cur->enc_ctrl.ExtParam[i]) + av_freep(&(cur->enc_ctrl.ExtParam[i])); + } + cur->enc_ctrl.NumExtParam = 0; + free_encoder_ctrl_payloads(&cur->enc_ctrl); if (cur->frame->format == AV_PIX_FMT_QSV) { av_frame_unref(cur->frame); @@ -1333,6 +1340,12 @@ static int get_free_frame(QSVEncContext *q, QSVFrame **f) av_freep(&frame); return AVERROR(ENOMEM); } + frame->enc_ctrl.ExtParam = av_mallocz(sizeof(mfxExtBuffer*) * QSV_MAX_ENC_EXTPARAM); + if (!frame->enc_ctrl.ExtParam) { + av_free(frame->enc_ctrl.Payload); + av_freep(&frame); + return AVERROR(ENOMEM); + } *last = frame; *f = frame; @@ -1436,6 +1449,7 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { AVPacket new_pkt = { 0 }; + AVFrameSideData *sd; mfxBitstream *bs; #if QSV_VERSION_ATLEAST(1, 26) mfxExtAVCEncodedFrameInfo *enc_info; @@ -1446,6 +1460,7 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, mfxSyncPoint *sync = NULL; QSVFrame *qsv_frame = NULL; mfxEncodeCtrl* enc_ctrl = NULL; + mfxExtEncoderROI *enc_roi = NULL; int ret; if (frame) { @@ -1480,6 +1495,8 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, bs->Data = new_pkt.data; bs->MaxLength = new_pkt.size; + enc_info = NULL; + enc_buf = NULL; #if QSV_VERSION_ATLEAST(1, 26) if (avctx->codec_id == AV_CODEC_ID_H264) { enc_info = av_mallocz(sizeof(*enc_info)); @@ -1502,6 +1519,62 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, q->set_encode_ctrl_cb(avctx, frame, &qsv_frame->enc_ctrl); } +#if QSV_VERSION_ATLEAST(1, 22) + sd = NULL; + if (frame) { + sd = av_frame_get_side_data(frame, + AV_FRAME_DATA_REGIONS_OF_INTEREST); + } + if (sd) { + AVRegionOfInterest *roi; + uint32_t roi_size; + int nb_roi, i; + + enc_roi = (mfxExtEncoderROI *)av_mallocz(sizeof(*enc_roi)); + if (!enc_roi) { + av_packet_unref(&new_pkt); + if (bs) + av_freep(bs); + if (enc_info) + av_freep(&enc_info); + if (enc_buf) + av_freep(&enc_buf); + return AVERROR(ENOMEM); + } + roi = (AVRegionOfInterest *)sd->data; + roi_size = roi->self_size; + av_assert0(roi_size && sd->size % roi_size == 0); + nb_roi = sd->size / roi_size; + if (nb_roi > QSV_MAX_ROI_NUM) { + av_log(avctx, AV_LOG_WARNING, "More ROIs set than " + "supported by driver (%d > %d).\n", + nb_roi, QSV_MAX_ROI_NUM); + nb_roi = QSV_MAX_ROI_NUM; + } + enc_roi->Header.BufferId = MFX_EXTBUFF_ENCODER_ROI; + enc_roi->Header.BufferSz = sizeof(*enc_roi); + enc_roi->NumROI = nb_roi; + enc_roi->ROIMode = MFX_ROI_MODE_QP_DELTA; + // For overlapping regions, the first in the array takes priority. + for (i = 0; i < nb_roi; i++) { + roi = (AVRegionOfInterest*)(sd->data + roi_size * i); + av_assert0(roi->qoffset.den != 0); + + enc_roi->ROI[i].Top = roi->top & 0xfffffff0; + enc_roi->ROI[i].Bottom = roi->bottom & 0xfffffff0; + enc_roi->ROI[i].Left = (roi->left & 0xfffffff0) + 0x10; + enc_roi->ROI[i].Right = (roi->right & 0xfffffff0) + 0x10; + enc_roi->ROI[i].DeltaQP = + roi->qoffset.num * 51 / roi->qoffset.den; + av_log(avctx, AV_LOG_DEBUG, "ROI: (%d,%d)-(%d,%d) -> %+d.\n", + roi->top, roi->left, roi->bottom, roi->right, + enc_roi->ROI[i].DeltaQP); + } + enc_ctrl->ExtParam[enc_ctrl->NumExtParam] = (mfxExtBuffer *)enc_roi; + enc_ctrl->NumExtParam += 1; + } +#endif + sync = av_mallocz(sizeof(*sync)); if (!sync) { av_freep(&bs); @@ -1670,6 +1743,7 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) q->work_frames = cur->next; av_frame_free(&cur->frame); av_free(cur->enc_ctrl.Payload); + av_free(cur->enc_ctrl.ExtParam); av_freep(&cur); cur = q->work_frames; }