From ff38b8dfaed089cb36d651dcdc6c1fb74acab657 Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 17 Oct 2016 14:32:28 -0700 Subject: [PATCH] vp8: Add control for gf boost for 1 pass cbr. Control already exists for vp9, adding it to vp8. Usage is only when error_resilient is off. Added a datarate unittest for non-zero boost. Change-Id: I4296055ebe2f4f048e8210f344531f6486ac9e35 --- test/datarate_test.cc | 26 ++++++++++++++++++++++++++ vp8/common/onyx.h | 2 ++ vp8/encoder/ratectrl.c | 9 +++++++-- vp8/vp8_cx_iface.c | 11 +++++++++++ vpx/vp8cx.h | 20 +++++++++++++++++++- vpxenc.c | 26 ++++++++++++++++++-------- 6 files changed, 83 insertions(+), 11 deletions(-) diff --git a/test/datarate_test.cc b/test/datarate_test.cc index 5fcbdec..06dee21 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc @@ -43,6 +43,7 @@ class DatarateTestLarge duration_ = 0.0; denoiser_offon_test_ = 0; denoiser_offon_period_ = -1; + gf_boost_ = 0; } virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, @@ -50,6 +51,7 @@ class DatarateTestLarge if (video->frame() == 0) { encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_); encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_); + encoder->Control(VP8E_SET_GF_CBR_BOOST_PCT, gf_boost_); } if (denoiser_offon_test_) { @@ -142,6 +144,7 @@ class DatarateTestLarge int denoiser_offon_test_; int denoiser_offon_period_; int set_cpu_used_; + int gf_boost_; }; #if CONFIG_TEMPORAL_DENOISING @@ -425,6 +428,29 @@ TEST_P(DatarateTestRealTime, DropFramesMultiThreads) { } #endif +TEST_P(DatarateTestRealTime, GFBoost) { + denoiser_on_ = 0; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_dropframe_thresh = 0; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_error_resilient = 0; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 300); + cfg_.rc_target_bitrate = 300; + ResetModel(); + // Apply a gf boost. + gf_boost_ = 50; + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) + << " The datarate for the file exceeds the target!"; + + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4) + << " The datarate for the file missed the target!"; +} + class DatarateTestVP9Large : public ::libvpx_test::EncoderTest, public ::libvpx_test::CodecTestWith2Params { diff --git a/vp8/common/onyx.h b/vp8/common/onyx.h index 43e3c29..72fba2e 100644 --- a/vp8/common/onyx.h +++ b/vp8/common/onyx.h @@ -110,6 +110,8 @@ typedef struct { int Sharpness; int cpu_used; unsigned int rc_max_intra_bitrate_pct; + /* percent of rate boost for golden frame in CBR mode. */ + unsigned int gf_cbr_boost_pct; unsigned int screen_content_mode; /* mode -> diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c index 4bab60c..ad670f2 100644 --- a/vp8/encoder/ratectrl.c +++ b/vp8/encoder/ratectrl.c @@ -1005,9 +1005,14 @@ static void calc_pframe_target_size(VP8_COMP *cpi) { cpi->current_gf_interval = cpi->frames_till_gf_update_due; } } else { - // Special case for 1 pass CBR: for now no boost and fixed gf period. + // Special case for 1 pass CBR: fixed gf period. // TODO(marpan): Adjust this boost/interval logic. - cpi->gf_noboost_onepass_cbr = 1; + // If gf_cbr_boost_pct is small (below threshold) set the flag + // gf_noboost_onepass_cbr = 1, which forces the gf to use the same + // rate correction factor as last. + cpi->gf_noboost_onepass_cbr = (cpi->oxcf.gf_cbr_boost_pct <= 50); + cpi->this_frame_target = + (cpi->this_frame_target * (100 + cpi->oxcf.gf_cbr_boost_pct)) / 100; cpi->baseline_gf_interval = cpi->gf_interval_onepass_cbr; // Skip this update if the zero_mvcount is low. if (cpi->zeromv_count > (cpi->common.MBs >> 1)) diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c index fac237e..f8475ed 100644 --- a/vp8/vp8_cx_iface.c +++ b/vp8/vp8_cx_iface.c @@ -40,6 +40,7 @@ struct vp8_extracfg { vp8e_tuning tuning; unsigned int cq_level; /* constrained quality level */ unsigned int rc_max_intra_bitrate_pct; + unsigned int gf_cbr_boost_pct; unsigned int screen_content_mode; }; @@ -65,6 +66,7 @@ static struct vp8_extracfg default_extracfg = { 0, /* tuning*/ 10, /* cq_level */ 0, /* rc_max_intra_bitrate_pct */ + 0, /* gf_cbr_boost_pct */ 0, /* screen_content_mode */ }; @@ -315,6 +317,7 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf, oxcf->target_bandwidth = cfg.rc_target_bitrate; oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct; + oxcf->gf_cbr_boost_pct = vp8_cfg.gf_cbr_boost_pct; oxcf->best_allowed_q = cfg.rc_min_quantizer; oxcf->worst_allowed_q = cfg.rc_max_quantizer; @@ -558,6 +561,13 @@ static vpx_codec_err_t set_rc_max_intra_bitrate_pct(vpx_codec_alg_priv_t *ctx, return update_extracfg(ctx, &extra_cfg); } +static vpx_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(vpx_codec_alg_priv_t *ctx, + va_list args) { + struct vp8_extracfg extra_cfg = ctx->vp8_cfg; + extra_cfg.gf_cbr_boost_pct = CAST(VP8E_SET_GF_CBR_BOOST_PCT, args); + return update_extracfg(ctx, &extra_cfg); +} + static vpx_codec_err_t set_screen_content_mode(vpx_codec_alg_priv_t *ctx, va_list args) { struct vp8_extracfg extra_cfg = ctx->vp8_cfg; @@ -1159,6 +1169,7 @@ static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] = { { VP8E_SET_CQ_LEVEL, set_cq_level }, { VP8E_SET_MAX_INTRA_BITRATE_PCT, set_rc_max_intra_bitrate_pct }, { VP8E_SET_SCREEN_CONTENT_MODE, set_screen_content_mode }, + { VP8E_SET_GF_CBR_BOOST_PCT, ctrl_set_rc_gf_cbr_boost_pct }, { -1, NULL }, }; diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h index 8fa25e8..cc90159 100644 --- a/vpx/vp8cx.h +++ b/vpx/vp8cx.h @@ -561,7 +561,22 @@ enum vp8e_enc_control_id { * * Supported in codecs: VP9 */ - VP9E_SET_ALT_REF_AQ + VP9E_SET_ALT_REF_AQ, + + /*!\brief Boost percentage for Golden Frame in CBR mode. + * + * This value controls the amount of boost given to Golden Frame in + * CBR mode. It is expressed as a percentage of the average + * per-frame bitrate, with the special (and default) value 0 meaning + * the feature is off, i.e., no golden frame boost in CBR mode and + * average bitrate target is used. + * + * For example, to allow 100% more bits, i.e, 2X, in a golden frame + * than average frame, set this to 100. + * + * Supported in codecs: VP8 + */ + VP8E_SET_GF_CBR_BOOST_PCT, }; /*!\brief vpx 1-D scaling mode @@ -769,6 +784,9 @@ VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTRA_BITRATE_PCT, unsigned int) VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTER_BITRATE_PCT, unsigned int) #define VPX_CTRL_VP8E_SET_MAX_INTER_BITRATE_PCT +VPX_CTRL_USE_TYPE(VP8E_SET_GF_CBR_BOOST_PCT, unsigned int) +#define VPX_CTRL_VP8E_SET_GF_CBR_BOOST_PCT + VPX_CTRL_USE_TYPE(VP8E_SET_SCREEN_CONTENT_MODE, unsigned int) #define VPX_CTRL_VP8E_SET_SCREEN_CONTENT_MODE diff --git a/vpxenc.c b/vpxenc.c index 6e0af57..a0f7605 100644 --- a/vpxenc.c +++ b/vpxenc.c @@ -355,6 +355,8 @@ static const arg_def_t cq_level = ARG_DEF(NULL, "cq-level", 1, "Constant/Constrained Quality level"); static const arg_def_t max_intra_rate_pct = ARG_DEF(NULL, "max-intra-rate", 1, "Max I-frame bitrate (pct)"); +static const arg_def_t gf_cbr_boost_pct = ARG_DEF( + NULL, "gf-cbr-boost", 1, "Boost for Golden Frame in CBR mode (pct)"); #if CONFIG_VP8_ENCODER static const arg_def_t cpu_used_vp8 = @@ -363,12 +365,21 @@ static const arg_def_t token_parts = ARG_DEF(NULL, "token-parts", 1, "Number of token partitions to use, log2"); static const arg_def_t screen_content_mode = ARG_DEF(NULL, "screen-content-mode", 1, "Screen content mode"); -static const arg_def_t *vp8_args[] = { - &cpu_used_vp8, &auto_altref, &noise_sens, &sharpness, - &static_thresh, &token_parts, &arnr_maxframes, &arnr_strength, - &arnr_type, &tune_ssim, &cq_level, &max_intra_rate_pct, - &screen_content_mode, NULL -}; +static const arg_def_t *vp8_args[] = { &cpu_used_vp8, + &auto_altref, + &noise_sens, + &sharpness, + &static_thresh, + &token_parts, + &arnr_maxframes, + &arnr_strength, + &arnr_type, + &tune_ssim, + &cq_level, + &max_intra_rate_pct, + &gf_cbr_boost_pct, + &screen_content_mode, + NULL }; static const int vp8_arg_ctrl_map[] = { VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF, VP8E_SET_NOISE_SENSITIVITY, @@ -381,6 +392,7 @@ static const int vp8_arg_ctrl_map[] = { VP8E_SET_CPUUSED, VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT, + VP8E_SET_GF_CBR_BOOST_PCT, VP8E_SET_SCREEN_CONTENT_MODE, 0 }; #endif @@ -407,8 +419,6 @@ static const arg_def_t alt_ref_aq = ARG_DEF(NULL, "alt-ref-aq", 1, static const arg_def_t frame_periodic_boost = ARG_DEF(NULL, "frame-boost", 1, "Enable frame periodic boost (0: off (default), 1: on)"); -static const arg_def_t gf_cbr_boost_pct = ARG_DEF( - NULL, "gf-cbr-boost", 1, "Boost for Golden Frame in CBR mode (pct)"); static const arg_def_t max_inter_rate_pct = ARG_DEF(NULL, "max-inter-rate", 1, "Max P-frame bitrate (pct)"); static const arg_def_t min_gf_interval = ARG_DEF( -- 2.7.4