Add encoder support to ALTREF2
This CL adds the use of ALTREF2_FRAME to both single / comp reference
prediction at the encoder side. In particular, the encoder keeps the
distant altref as ALTREF, and uses the internal extra altrefs to
refresh ALTREF2.
Compared with the baseline (ext_tx and global_motion disabled simply
for speed concern):
(a) lowres: avg_psnr -0.395% ovr_psnr -0.393% ssim -0.329%
(b) midres: avg_psnr -0.419% ovr_psnr -0.431% ssim -0.444%
(c) AWCY High Latency:
PSNR | PSNR Cb | PSNR Cr | PSNR HVS | SSIM | MS SSIM | CIEDE 2000
-0.6661 | -0.5988 | -0.6669 | -0.6993 | -0.6988 | -0.7303 | -0.6051
(d) AWCY Low Latency:
PSNR | PSNR Cb | PSNR Cr | PSNR HVS | SSIM | MS SSIM | CIEDE 2000
0.0720 | -0.0505 | 0.1501 | 0.0670 | 0.0842 | 0.0517 | 0.0158
TODO list:
(1) To have altref2 incorporated with ext-comp-refs;
(2) To have altref2 fully work with new-multisymbol;
(3) To re-collect the initial default probs/cdfs;
(4) To tune the encoder gf group structure design for altref2.
Change-Id: I6ad63fd65afa903d3bba20acdb68e3b67acf7fdf
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index b546fdf..a1f53b7 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -579,8 +579,11 @@
active_worst_quality =
curr_frame == 0 ? rc->worst_quality : rc->last_q[KEY_FRAME] * 2;
} else {
- if (!rc->is_src_frame_alt_ref &&
- (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+ if (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+ cpi->refresh_alt2_ref_frame ||
+#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
+ cpi->refresh_alt_ref_frame)) {
active_worst_quality = curr_frame == 1 ? rc->last_q[KEY_FRAME] * 5 / 4
: rc->last_q[INTER_FRAME];
} else {
@@ -1005,8 +1008,11 @@
active_best_quality +=
av1_compute_qdelta(rc, q_val, q_val * q_adj_factor, cm->bit_depth);
}
- } else if (!rc->is_src_frame_alt_ref &&
- (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+ } else if (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+ cpi->refresh_alt2_ref_frame ||
+#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
+ cpi->refresh_alt_ref_frame)) {
// Use the lower of active_worst_quality and recent
// average Q as basis for GF/ARF best Q limit unless last frame was
// a key frame.
@@ -1026,7 +1032,11 @@
active_best_quality = active_best_quality * 15 / 16;
} else if (oxcf->rc_mode == AOM_Q) {
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+ if (!cpi->refresh_alt_ref_frame && !cpi->refresh_alt2_ref_frame) {
+#else
if (!cpi->refresh_alt_ref_frame) {
+#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
active_best_quality = cq_level;
} else {
active_best_quality = get_gf_active_quality(rc, q, cm->bit_depth);
@@ -1058,8 +1068,11 @@
if ((cpi->oxcf.rc_mode != AOM_Q) &&
(cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD)) {
if (frame_is_intra_only(cm) ||
- (!rc->is_src_frame_alt_ref &&
- (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame))) {
+ (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+ cpi->refresh_alt2_ref_frame ||
+#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
+ cpi->refresh_alt_ref_frame))) {
active_best_quality -=
(cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast);
active_worst_quality += (cpi->twopass.extend_maxq / 2);
@@ -1194,7 +1207,7 @@
// only the virtual indices for the reference frame will be
// updated and cpi->refresh_golden_frame will still be zero.
if (cpi->refresh_golden_frame || rc->is_src_frame_alt_ref) {
-#else
+#else // !CONFIG_EXT_REFS
// Update the Golden frame usage counts.
if (cpi->refresh_golden_frame) {
#endif // CONFIG_EXT_REFS
@@ -1219,7 +1232,11 @@
// Decrement count down till next gf
if (rc->frames_till_gf_update_due > 0) rc->frames_till_gf_update_due--;
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+ } else if (!cpi->refresh_alt_ref_frame && !cpi->refresh_alt2_ref_frame) {
+#else
} else if (!cpi->refresh_alt_ref_frame) {
+#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
// Decrement count down till next gf
if (rc->frames_till_gf_update_due > 0) rc->frames_till_gf_update_due--;
@@ -1249,7 +1266,11 @@
ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[KEY_FRAME] + qindex, 2);
} else {
if (!rc->is_src_frame_alt_ref &&
- !(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+ !(cpi->refresh_golden_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+ cpi->refresh_alt2_ref_frame ||
+#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
+ cpi->refresh_alt_ref_frame)) {
rc->last_q[INTER_FRAME] = qindex;
rc->avg_frame_qindex[INTER_FRAME] =
ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[INTER_FRAME] + qindex, 2);
@@ -1271,6 +1292,9 @@
if ((qindex < rc->last_boosted_qindex) || (cm->frame_type == KEY_FRAME) ||
(!rc->constrained_gf_group &&
(cpi->refresh_alt_ref_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+ cpi->refresh_alt2_ref_frame ||
+#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
(cpi->refresh_golden_frame && !rc->is_src_frame_alt_ref)))) {
rc->last_boosted_qindex = qindex;
}
@@ -1294,6 +1318,8 @@
// Actual bits spent
rc->total_actual_bits += rc->projected_frame_size;
#if CONFIG_EXT_REFS
+ // TODO(zoeliu): To investigate whether we should treat BWDREF_FRAME
+ // differently here for rc->avg_frame_bandwidth.
rc->total_target_bits +=
(cm->show_frame || rc->is_bwd_ref_frame) ? rc->avg_frame_bandwidth : 0;
#else
@@ -1313,6 +1339,8 @@
if (cm->frame_type == KEY_FRAME) rc->frames_since_key = 0;
#if CONFIG_EXT_REFS
+ // TODO(zoeliu): To investigate whether we should treat BWDREF_FRAME
+ // differently here for rc->avg_frame_bandwidth.
if (cm->show_frame || rc->is_bwd_ref_frame) {
#else
if (cm->show_frame) {