Add two methods to reduce the boost on ALT0 for the last GF group
1) REDUCE_LAST_ALT_BOOST:
Reduce the boost on ALT0 if the last GF is too long.
2) REDUCE_LAST_GF_LENGTH:
Reduce the length of the last GF if it is too long,
i.e. split it into two shorter GF groups.
Perfromance gain for each strategy on overall psnr compared to
baseline with respect to different coding length (negative is coding gain):
Stretagy 1 / Stretagy 2 / not applying the strategy:
lowres midres
17 0.916/0.132/2.145 0.175/-0.791/2.03
30 -0.136/-0.491/0.647 -1.085/-1.168/0.107
33 -0.446/-0.802/0.523 -1.257/-1.152/0.328
60 -1.643/-1.894/-1.377 -2.074/-2.065/-1.729
Change-Id: I292c6bd29ed8b0a028b134ea5ed9556bc593ef8b
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index d376e3f..f009450 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -3030,12 +3030,31 @@
assert(num_mbs > 0);
if (i) avg_sr_coded_error /= i;
+#if REDUCE_LAST_GF_LENGTH
+ int alt_offset = 0;
+ // We are going to have an alt ref.
+ if (allow_alt_ref && (i < cpi->oxcf.lag_in_frames) &&
+ (i >= rc->min_gf_interval)) {
+ // If the last gf is too long, then we have to reduce
+ // the current gf length
+ if (rc->frames_to_key - i < 9 && i > 10) {
+ // too long, reduce the length by one
+ alt_offset = -1;
+ i -= 1;
+ }
+ }
+#endif
+
// Should we use the alternate reference frame.
if (allow_alt_ref && (i < cpi->oxcf.lag_in_frames) &&
(i >= rc->min_gf_interval)) {
// Calculate the boost for alt ref.
rc->gfu_boost =
+#if REDUCE_LAST_GF_LENGTH
+ calc_arf_boost(cpi, alt_offset, (i - 1), (i - 1), &f_boost, &b_boost);
+#else
calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost, &b_boost);
+#endif
rc->source_alt_ref_pending = 1;
} else {
rc->gfu_boost = AOMMAX((int)boost_score, MIN_ARF_GF_BOOST);
@@ -3055,6 +3074,18 @@
} else {
rc->baseline_gf_interval = i - (is_key_frame || rc->source_alt_ref_pending);
}
+
+#if REDUCE_LAST_ALT_BOOST
+ rc->arf_boost_factor = 1.0;
+ if (rc->source_alt_ref_pending) {
+ // If the last gf is too long, then we have to reduce
+ // the boost factor on current alt ref
+ if (rc->frames_to_key - i == 0 && i > 10) {
+ rc->arf_boost_factor = 0;
+ }
+ }
+#endif
+
if (non_zero_stdev_count) avg_raw_err_stdev /= non_zero_stdev_count;
// Disable extra altrefs and backward refs for "still" gf group:
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 08aa8a8..37bf4c4 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -556,6 +556,14 @@
arfgf_low_motion_minq, arfgf_high_motion_minq);
}
+#if REDUCE_LAST_ALT_BOOST
+static int get_gf_high_motion_quality(int q, aom_bit_depth_t bit_depth) {
+ int *arfgf_high_motion_minq;
+ ASSIGN_MINQ_TABLE(bit_depth, arfgf_high_motion_minq);
+ return arfgf_high_motion_minq[q];
+}
+#endif
+
static int calc_active_worst_quality_one_pass_vbr(const AV1_COMP *cpi) {
const RATE_CONTROL *const rc = &cpi->rc;
const unsigned int curr_frame = cpi->common.current_video_frame;
@@ -918,7 +926,7 @@
#define STATIC_MOTION_THRESH 95
static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width,
int height, int *bottom_index,
- int *top_index) {
+ int *top_index, int *arf_q) {
const AV1_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
@@ -1012,6 +1020,15 @@
} else {
if (gf_group->update_type[gf_group->index] == ARF_UPDATE) {
active_best_quality = get_gf_active_quality(rc, q, bit_depth);
+ *arf_q = active_best_quality;
+#if REDUCE_LAST_ALT_BOOST
+ int min_boost =
+ (get_gf_high_motion_quality(q, bit_depth) + active_best_quality) /
+ 2;
+ int boost = min_boost - active_best_quality;
+
+ active_best_quality = min_boost - (int)(boost * rc->arf_boost_factor);
+#endif
} else {
active_best_quality = rc->arf_q;
}
@@ -1147,12 +1164,13 @@
assert(cpi->oxcf.pass == 2 && "invalid encode pass");
GF_GROUP *gf_group = &cpi->twopass.gf_group;
+ int arf_q = 0;
q = rc_pick_q_and_bounds_two_pass(cpi, width, height, bottom_index,
- top_index);
+ top_index, &arf_q);
if (gf_group->update_type[gf_group->index] == ARF_UPDATE) {
- cpi->rc.arf_q = q;
+ cpi->rc.arf_q = arf_q;
}
}
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index e921c88..2696957 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -30,8 +30,12 @@
#if FIX_GF_INTERVAL_LENGTH
#define FIXED_GF_LENGTH 16
#define USE_SYMM_MULTI_LAYER 1
+#define REDUCE_LAST_ALT_BOOST 0
+#define REDUCE_LAST_GF_LENGTH 1
#else
#define USE_SYMM_MULTI_LAYER 0
+#define REDUCE_LAST_ALT_BOOST 0
+#define REDUCE_LAST_GF_LENGTH 0
#endif
#if USE_SYMM_MULTI_LAYER
@@ -159,6 +163,7 @@
// Auto frame-scaling variables.
int rf_level_maxq[RATE_FACTOR_LEVELS];
+ float_t arf_boost_factor;
// Q index used for ALT frame
int arf_q;
} RATE_CONTROL;