From patchwork Tue Apr 23 03:29:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Fu, Linjie" X-Patchwork-Id: 12871 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 2A669449A6B for ; Tue, 23 Apr 2019 06:29:29 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 01F1768833D; Tue, 23 Apr 2019 06:29:29 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5466368832F for ; Tue, 23 Apr 2019 06:29:21 +0300 (EEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Apr 2019 20:29:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,384,1549958400"; d="scan'208";a="151525531" Received: from media_lj_kbl.sh.intel.com ([10.239.13.2]) by FMSMGA003.fm.intel.com with ESMTP; 22 Apr 2019 20:29:18 -0700 From: Linjie Fu To: ffmpeg-devel@ffmpeg.org Date: Tue, 23 Apr 2019 11:29:17 +0800 Message-Id: <20190423032917.7471-1-linjie.fu@intel.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH] lavc/vaapi_encode_h264: add support for maxframesize 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: Linjie Fu MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Add support for max frame size: - max_frame_size (bytes) to indicate the allowed max frame size. - pass_num to indicate number of passes. - delta_qp to indicate adjust qp value. Currently only AVC encoder can support this settings in multiple pass case. If the frame size exceeds, the encoder will do more pak passes to adjust the QP value to control the frame size. Set Default num_passes to 4 (1~4), set delta_qp[4] = {1, 1, 1, 1}, use new_qp for encoder if frame size exceeds the limitation: new_qp = base_qp + delta_qp[0] + delta_qp[1] + ... ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -f rawvideo \ -v verbose -s:v 352x288 -i ./input.yuv -vf format=nv12,hwupload \ -c:v h264_vaapi -profile:v main -g 30 -bf 3 -max_frame_size 40000 \ -pass_num 2 -delta_qp 2 -vframes 100 -y ./max_frame_size.h264 Signed-off-by: Linjie Fu --- libavcodec/vaapi_encode.c | 46 ++++++++++++++++++++++++++++++++++ libavcodec/vaapi_encode.h | 11 ++++++++ libavcodec/vaapi_encode_h264.c | 15 +++++++++++ 3 files changed, 72 insertions(+) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 2dda451882..762c42ef13 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -236,6 +236,14 @@ static int vaapi_encode_issue(AVCodecContext *avctx, goto fail; } + if (ctx->max_frame_size) { + err = vaapi_encode_make_param_buffer(avctx, pic, VAEncMiscParameterBufferType, + (char*) &ctx->mfs_params.misc, + sizeof(ctx->mfs_params)); + if (err < 0) + goto fail; + } + if (pic->type == PICTURE_TYPE_IDR) { if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE && ctx->codec->write_sequence_header) { @@ -1630,6 +1638,38 @@ rc_mode_found: return 0; } +static av_cold int vaapi_encode_init_max_frame_size(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + + uint32_t max_frame_size = ctx->max_frame_size; + uint8_t num_passes = ctx->pass_num; + uint8_t *delta_qp = av_mallocz_array(num_passes, sizeof(uint8_t)); + int err = 0; + int i = 0; + + if (!delta_qp) { + err = AVERROR(ENOMEM); + return err; + } + for (i = 0; i delta_qp; + } + + + ctx->mfs_params.misc.type = VAEncMiscParameterTypeMultiPassFrameSize; + ctx->mfs_params.mfs.type = VAEncMiscParameterTypeMultiPassFrameSize; + ctx->mfs_params.mfs.max_frame_size = max_frame_size; + ctx->mfs_params.mfs.num_passes = num_passes; + ctx->mfs_params.mfs.delta_qp = delta_qp; + + av_log(avctx, AV_LOG_VERBOSE, "Max Frame Size: %d bytes, " + "num_passes: %d, delta_qp = %d.\n", + ctx->max_frame_size, num_passes, ctx->delta_qp); + + return 0; +} + static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -2095,6 +2135,12 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) goto fail; } + if (ctx->max_frame_size) { + err = vaapi_encode_init_max_frame_size(avctx); + if (err < 0) + goto fail; + } + vas = vaCreateConfig(ctx->hwctx->display, ctx->va_profile, ctx->va_entrypoint, ctx->config_attributes, ctx->nb_config_attributes, diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 44a8db566e..557476d226 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -176,6 +176,13 @@ typedef struct VAAPIEncodeContext { // Desired B frame reference depth. int desired_b_depth; + // Max Frame Size + int max_frame_size; + // Number Of Passes + int pass_num; + // Delta_qp For Each Pass + int delta_qp; + // Explicitly set RC mode (otherwise attempt to pick from // available modes). int explicit_rc_mode; @@ -268,6 +275,10 @@ typedef struct VAAPIEncodeContext { } quality_params; #endif + struct { + VAEncMiscParameterBuffer misc; + VAEncMiscParameterBufferMultiPassFrameSize mfs; + } __attribute__((packed)) mfs_params; // Per-sequence parameter structure (VAEncSequenceParameterBuffer*). void *codec_sequence_params; diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 4cf99d7c78..4d55dc2bac 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -72,6 +72,9 @@ typedef struct VAAPIEncodeH264Context { int sei; int profile; int level; + int max_frame_size; + int pass_num; + int delta_qp; // Derived settings. int mb_width; @@ -1233,6 +1236,12 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx) if (priv->qp > 0) ctx->explicit_qp = priv->qp; + if (priv->max_frame_size > 0) { + ctx->max_frame_size = priv->max_frame_size; + ctx->pass_num = priv->pass_num; + ctx->delta_qp = priv->delta_qp; + } + return ff_vaapi_encode_init(avctx); } @@ -1266,6 +1275,12 @@ static const AVOption vaapi_encode_h264_options[] = { { "aud", "Include AUD", OFFSET(aud), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + { "max_frame_size", "Maximum frame size (in bytes)", + OFFSET(max_frame_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "pass_num", "number of passes, every pass can have different QP, currently can support up to 4 passes", + OFFSET(pass_num), AV_OPT_TYPE_INT, { .i64 = 4 }, 0, 4, FLAGS }, + { "delta_qp", "delta QP for every pass", + OFFSET(delta_qp), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 51, FLAGS }, { "sei", "Set SEI to include", OFFSET(sei), AV_OPT_TYPE_FLAGS,