ref: ff38b8dfaed089cb36d651dcdc6c1fb74acab657
parent: 7f31bfeddbe4a0309b2a79129c1d526ba5725864
author: Marco <marpan@google.com>
date: Mon Oct 17 10:32:28 EDT 2016
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
--- a/test/datarate_test.cc
+++ b/test/datarate_test.cc
@@ -43,6 +43,7 @@
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 @@
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 @@
int denoiser_offon_test_;
int denoiser_offon_period_;
int set_cpu_used_;
+ int gf_boost_;
};
#if CONFIG_TEMPORAL_DENOISING
@@ -424,6 +427,29 @@
<< " The datarate for the file missed the target!";
}
#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,
--- a/vp8/common/onyx.h
+++ b/vp8/common/onyx.h
@@ -110,6 +110,8 @@
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 ->
--- a/vp8/encoder/ratectrl.c
+++ b/vp8/encoder/ratectrl.c
@@ -1005,9 +1005,14 @@
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))
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -40,6 +40,7 @@
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 @@
0, /* tuning*/
10, /* cq_level */
0, /* rc_max_intra_bitrate_pct */
+ 0, /* gf_cbr_boost_pct */
0, /* screen_content_mode */
};
@@ -315,6 +317,7 @@
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 @@
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 @@
{ 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 },
};
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -561,7 +561,22 @@
*
* 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
@@ -768,6 +783,9 @@
#define VPX_CTRL_VP8E_SET_MAX_INTRA_BITRATE_PCT
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
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -355,6 +355,8 @@
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 @@
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 @@
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 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(