From patchwork Mon Apr 6 11:14:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Fu, Linjie" X-Patchwork-Id: 18708 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 5A95A449D1E for ; Mon, 6 Apr 2020 14:22:27 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 40D6468B3F8; Mon, 6 Apr 2020 14:22:27 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2673768B2FB for ; Mon, 6 Apr 2020 14:22:16 +0300 (EEST) IronPort-SDR: IIKrllJvmrvXZoBgK1ecJczirDlS7A3soJzxk+xB2Wo29ZUG4RM6bP8zwMgNfu/uk20T5ISwhs 5HWcLHnSXRgg== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Apr 2020 04:22:14 -0700 IronPort-SDR: CsAd5qKb1czSrD63Nhh9K6kevQjyZKkcTnFiYbd6TfYn+q3e2pdo4AaK7qiVq0cmqAS6AjTRYN 5m6ppjavJKng== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,350,1580803200"; d="scan'208";a="450799899" Received: from icl-dev.sh.intel.com ([10.239.158.73]) by fmsmga005.fm.intel.com with ESMTP; 06 Apr 2020 04:22:13 -0700 From: Linjie Fu To: ffmpeg-devel@ffmpeg.org Date: Mon, 6 Apr 2020 19:14:50 +0800 Message-Id: <1586171693-7836-8-git-send-email-linjie.fu@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1586171693-7836-1-git-send-email-linjie.fu@intel.com> References: <1586171693-7836-1-git-send-email-linjie.fu@intel.com> Subject: [FFmpeg-devel] [PATCH 07/10] lavc/libopenh264enc: separate svc_encode_init() into several functions 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" Separate the initialization procedure into different functions. Make it more readable and easier to be extended. Signed-off-by: Linjie Fu --- libavcodec/libopenh264enc.c | 283 +++++++++++++++++++++++++++----------------- 1 file changed, 174 insertions(+), 109 deletions(-) diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index e89cedf..f02c5fd 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -103,120 +103,51 @@ static av_cold int svc_encode_close(AVCodecContext *avctx) return 0; } -static av_cold int svc_encode_init(AVCodecContext *avctx) +static av_cold int svc_encode_init_profile(AVCodecContext *avctx, SEncParamExt *param) { SVCContext *s = avctx->priv_data; - SEncParamExt param = { 0 }; - int err; - int log_level; - WelsTraceCallback callback_function; - AVCPBProperties *props; - if ((err = ff_libopenh264_check_version(avctx)) < 0) - return err; + if (s->profile && !strcmp(s->profile, "main")) + param->iEntropyCodingModeFlag = 1; //< 0:CAVLC 1:CABAC + else if (!s->profile && s->cabac) + param->iEntropyCodingModeFlag = 1; + else + param->iEntropyCodingModeFlag = 0; - if (WelsCreateSVCEncoder(&s->encoder)) { - av_log(avctx, AV_LOG_ERROR, "Unable to create encoder\n"); - return AVERROR_UNKNOWN; - } + return 0; +} - // Pass all libopenh264 messages to our callback, to allow ourselves to filter them. - log_level = WELS_LOG_DETAIL; - (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_LEVEL, &log_level); +static av_cold int svc_encode_init_rate_control(AVCodecContext *avctx, SEncParamExt *param) +{ + SVCContext *s = avctx->priv_data; - // Set the logging callback function to one that uses av_log() (see implementation above). - callback_function = (WelsTraceCallback) ff_libopenh264_trace_callback; - (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK, &callback_function); + /* Rate Control */ + param->iRCMode = s->rc_mode; - // Set the AVCodecContext as the libopenh264 callback context so that it can be passed to av_log(). - (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &avctx); + param->iTargetBitrate = avctx->bit_rate; + param->iMaxBitrate = FFMAX(avctx->rc_max_rate, avctx->bit_rate); + param->bEnableFrameSkip = s->skip_frames; - (*s->encoder)->GetDefaultParams(s->encoder, ¶m); + // QP = 0 is not well supported, so default to (1, 51) + param->iMaxQp = avctx->qmax >= 0 ? av_clip(avctx->qmax, 1, 51) : 51; + param->iMinQp = avctx->qmin >= 0 ? av_clip(avctx->qmin, 1, param->iMaxQp) : 1; + param->bEnableAdaptiveQuant = 1; -#if FF_API_CODER_TYPE -FF_DISABLE_DEPRECATION_WARNINGS - if (!s->cabac) - s->cabac = avctx->coder_type == FF_CODER_TYPE_AC; -FF_ENABLE_DEPRECATION_WARNINGS -#endif + param->iSpatialLayerNum = 1; // Number of dependency(Spatial/CGS) layers used to be encoded + param->iTemporalLayerNum = 1; // Number of temporal layer specified - param.fMaxFrameRate = 1/av_q2d(avctx->time_base); - param.iPicWidth = avctx->width; - param.iPicHeight = avctx->height; - param.iTargetBitrate = avctx->bit_rate; - param.iMaxBitrate = FFMAX(avctx->rc_max_rate, avctx->bit_rate); - param.iRCMode = s->rc_mode; - // QP = 0 is not well supported, so default to (1, 51) - param.iMaxQp = avctx->qmax >= 0 ? av_clip(avctx->qmax, 1, 51) : 51; - param.iMinQp = avctx->qmin >= 0 ? av_clip(avctx->qmin, 1, param.iMaxQp) : 1; - param.iTemporalLayerNum = 1; - param.iSpatialLayerNum = 1; - param.bEnableDenoise = 0; - param.bEnableBackgroundDetection = 1; - param.bEnableAdaptiveQuant = 1; - param.bEnableFrameSkip = s->skip_frames; - param.bEnableLongTermReference = 0; - param.iLtrMarkPeriod = 30; - param.uiIntraPeriod = avctx->gop_size; -#if OPENH264_VER_AT_LEAST(1, 4) - param.eSpsPpsIdStrategy = CONSTANT_ID; -#else - param.bEnableSpsPpsIdAddition = 0; -#endif - param.bPrefixNalAddingCtrl = 0; - param.iLoopFilterDisableIdc = !s->loopfilter; - param.iEntropyCodingModeFlag = 0; - param.iMultipleThreadIdc = avctx->thread_count; - if (s->profile && !strcmp(s->profile, "main")) - param.iEntropyCodingModeFlag = 1; - else if (!s->profile && s->cabac) - param.iEntropyCodingModeFlag = 1; + param->bEnableDenoise = 0; // Denoise control + param->bEnableBackgroundDetection = 1; // Background detection control - param.sSpatialLayers[0].iVideoWidth = param.iPicWidth; - param.sSpatialLayers[0].iVideoHeight = param.iPicHeight; - param.sSpatialLayers[0].fFrameRate = param.fMaxFrameRate; - param.sSpatialLayers[0].iSpatialBitrate = param.iTargetBitrate; - param.sSpatialLayers[0].iMaxSpatialBitrate = param.iMaxBitrate; + param->bEnableLongTermReference = 0; // Long term reference control + param->iLtrMarkPeriod = 30; // the min distance of two int32_t references -#if OPENH264_VER_AT_LEAST(1, 7) - if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den) { - // Table E-1. - static const AVRational sar_idc[] = { - { 0, 0 }, // Unspecified (never written here). - { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, - { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, - { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, - { 160, 99 }, // Last 3 are unknown to openh264: { 4, 3 }, { 3, 2 }, { 2, 1 }, - }; - static const ESampleAspectRatio asp_idc[] = { - ASP_UNSPECIFIED, - ASP_1x1, ASP_12x11, ASP_10x11, ASP_16x11, - ASP_40x33, ASP_24x11, ASP_20x11, ASP_32x11, - ASP_80x33, ASP_18x11, ASP_15x11, ASP_64x33, - ASP_160x99, - }; - int num, den, i; - - av_reduce(&num, &den, avctx->sample_aspect_ratio.num, - avctx->sample_aspect_ratio.den, 65535); - - for (i = 1; i < FF_ARRAY_ELEMS(sar_idc); i++) { - if (num == sar_idc[i].num && - den == sar_idc[i].den) - break; - } - if (i == FF_ARRAY_ELEMS(sar_idc)) { - param.sSpatialLayers[0].eAspectRatio = ASP_EXT_SAR; - param.sSpatialLayers[0].sAspectRatioExtWidth = num; - param.sSpatialLayers[0].sAspectRatioExtHeight = den; - } else { - param.sSpatialLayers[0].eAspectRatio = asp_idc[i]; - } - param.sSpatialLayers[0].bAspectRatioPresent = true; - } else { - param.sSpatialLayers[0].bAspectRatioPresent = false; - } -#endif + return 0; +} + +static av_cold int svc_encode_init_slice(AVCodecContext *avctx, SEncParamExt *param, int iLayer) +{ + SVCContext *s = avctx->priv_data; if ((avctx->slices > 1) && (s->max_nal_size)) { av_log(avctx, AV_LOG_ERROR, @@ -232,11 +163,11 @@ FF_ENABLE_DEPRECATION_WARNINGS s->slice_mode = SM_SIZELIMITED_SLICE; #if OPENH264_VER_AT_LEAST(1, 6) - param.sSpatialLayers[0].sSliceArgument.uiSliceMode = s->slice_mode; - param.sSpatialLayers[0].sSliceArgument.uiSliceNum = avctx->slices; + param->sSpatialLayers[iLayer].sSliceArgument.uiSliceMode = s->slice_mode; + param->sSpatialLayers[iLayer].sSliceArgument.uiSliceNum = avctx->slices; #else - param.sSpatialLayers[0].sSliceCfg.uiSliceMode = s->slice_mode; - param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = avctx->slices; + param->sSpatialLayers[iLayer].sSliceCfg.uiSliceMode = s->slice_mode; + param->sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceNum = avctx->slices; #endif if (avctx->slices == 0 && s->slice_mode == SM_FIXEDSLCNUM_SLICE) av_log(avctx, AV_LOG_WARNING, "Auto slice number, " @@ -244,11 +175,11 @@ FF_ENABLE_DEPRECATION_WARNINGS if (s->slice_mode == SM_SIZELIMITED_SLICE) { if (s->max_nal_size) { - param.uiMaxNalSize = s->max_nal_size; + param->uiMaxNalSize = s->max_nal_size; #if OPENH264_VER_AT_LEAST(1, 6) - param.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = s->max_nal_size; + param->sSpatialLayers[iLayer].sSliceArgument.uiSliceSizeConstraint = s->max_nal_size; #else - param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = s->max_nal_size; + param->sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = s->max_nal_size; #endif } else { av_log(avctx, AV_LOG_ERROR, "Invalid -max_nal_size, " @@ -257,6 +188,140 @@ FF_ENABLE_DEPRECATION_WARNINGS } } + return 0; +} + +static av_cold int svc_encode_init_spatial_layer(AVCodecContext *avctx, SEncParamExt *param) +{ + int iLayer, err; + + // Default iSpatialLayerNum = 1, should be extended to support MAX_SPATIAL_LAYER_NUM = 4 + for (iLayer = 0; iLayer < param->iSpatialLayerNum; iLayer++) { + param->sSpatialLayers[iLayer].iVideoWidth = param->iPicWidth; + param->sSpatialLayers[iLayer].iVideoHeight = param->iPicHeight; + param->sSpatialLayers[iLayer].fFrameRate = param->fMaxFrameRate; + param->sSpatialLayers[iLayer].iSpatialBitrate = param->iTargetBitrate; + param->sSpatialLayers[iLayer].iMaxSpatialBitrate = param->iMaxBitrate; + + if (err = svc_encode_init_slice(avctx, param, iLayer) < 0) + return err; + +#if OPENH264_VER_AT_LEAST(1, 7) + if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den) { + // Table E-1. + static const AVRational sar_idc[] = { + { 0, 0 }, // Unspecified (never written here). + { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, + { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, + { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, + { 160, 99 }, // Last 3 are unknown to openh264: { 4, 3 }, { 3, 2 }, { 2, 1 }, + }; + static const ESampleAspectRatio asp_idc[] = { + ASP_UNSPECIFIED, + ASP_1x1, ASP_12x11, ASP_10x11, ASP_16x11, + ASP_40x33, ASP_24x11, ASP_20x11, ASP_32x11, + ASP_80x33, ASP_18x11, ASP_15x11, ASP_64x33, + ASP_160x99, + }; + int num, den, i; + + av_reduce(&num, &den, avctx->sample_aspect_ratio.num, + avctx->sample_aspect_ratio.den, 65535); + + for (i = 1; i < FF_ARRAY_ELEMS(sar_idc); i++) { + if (num == sar_idc[i].num && + den == sar_idc[i].den) + break; + } + if (i == FF_ARRAY_ELEMS(sar_idc)) { + param->sSpatialLayers[iLayer].eAspectRatio = ASP_EXT_SAR; + param->sSpatialLayers[iLayer].sAspectRatioExtWidth = num; + param->sSpatialLayers[iLayer].sAspectRatioExtHeight = den; + } else { + param->sSpatialLayers[iLayer].eAspectRatio = asp_idc[i]; + } + param->sSpatialLayers[iLayer].bAspectRatioPresent = true; + } else { + param->sSpatialLayers[iLayer].bAspectRatioPresent = false; + } +#endif + } + + return 0; +} + +static av_cold int svc_encode_init_params(AVCodecContext *avctx, SEncParamExt *param) +{ + SVCContext *s = avctx->priv_data; + int err; + + // The default parameters would be got by FillDefault() in codec/encoder/core/inc/param_svc.h + param->iPicWidth = avctx->width; + param->iPicHeight = avctx->height; + param->uiIntraPeriod = avctx->gop_size; + param->fMaxFrameRate = 1/av_q2d(avctx->time_base); + param->iMultipleThreadIdc = avctx->thread_count; + param->iLoopFilterDisableIdc = !s->loopfilter; + // Nal unit control +#if OPENH264_VER_AT_LEAST(1, 4) + param->eSpsPpsIdStrategy = CONSTANT_ID; +#else + param->bEnableSpsPpsIdAddition = 0; +#endif + param->bPrefixNalAddingCtrl = 0; + + if (err = svc_encode_init_profile(avctx, param) < 0) + return err; + + if (err = svc_encode_init_rate_control(avctx, param) < 0) + return err; + + if (err = svc_encode_init_spatial_layer(avctx, param) < 0) + return err; + + return 0; +} + +static av_cold int svc_encode_init(AVCodecContext *avctx) +{ + SVCContext *s = avctx->priv_data; + SEncParamExt param = { 0 }; + int err; + int log_level; + WelsTraceCallback callback_function; + AVCPBProperties *props; + + if ((err = ff_libopenh264_check_version(avctx)) < 0) + return err; + + if (WelsCreateSVCEncoder(&s->encoder)) { + av_log(avctx, AV_LOG_ERROR, "Unable to create encoder\n"); + return AVERROR_UNKNOWN; + } + + // Pass all libopenh264 messages to our callback, to allow ourselves to filter them. + log_level = WELS_LOG_DETAIL; + (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_LEVEL, &log_level); + + // Set the logging callback function to one that uses av_log() (see implementation above). + callback_function = (WelsTraceCallback) ff_libopenh264_trace_callback; + (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK, &callback_function); + + // Set the AVCodecContext as the libopenh264 callback context so that it can be passed to av_log(). + (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &avctx); + + (*s->encoder)->GetDefaultParams(s->encoder, ¶m); + +#if FF_API_CODER_TYPE +FF_DISABLE_DEPRECATION_WARNINGS + if (!s->cabac) + s->cabac = avctx->coder_type == FF_CODER_TYPE_AC; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (err = svc_encode_init_params(avctx, ¶m) < 0) + return err; + if ((*s->encoder)->InitializeExt(s->encoder, ¶m) != cmResultSuccess) { av_log(avctx, AV_LOG_ERROR, "Initialize failed\n"); return AVERROR_UNKNOWN;