AV1 RT: Use Golden Frame as reference
This gives 8% BDRate improvement (max is 18%) with about 15%
slowdown
Change-Id: Icf6e42b2c0cbda4d84aa765e522012f6aa37c8b2
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index e9bc4c6..8cffe15 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -821,7 +821,9 @@
oxcf->enable_global_motion = extra_cfg->enable_global_motion;
oxcf->enable_warped_motion = extra_cfg->enable_warped_motion;
oxcf->allow_warped_motion =
- extra_cfg->allow_warped_motion & extra_cfg->enable_warped_motion;
+ (cfg->g_usage == AOM_USAGE_REALTIME)
+ ? 0
+ : (extra_cfg->allow_warped_motion & extra_cfg->enable_warped_motion);
oxcf->enable_filter_intra = extra_cfg->enable_filter_intra;
oxcf->enable_smooth_intra = extra_cfg->enable_smooth_intra;
oxcf->enable_paeth_intra = extra_cfg->enable_paeth_intra;
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c
index b339c7f..9c57c49 100644
--- a/av1/encoder/aq_cyclicrefresh.c
+++ b/av1/encoder/aq_cyclicrefresh.c
@@ -273,9 +273,9 @@
// period. Depending on past encoding stats, GF flag may be reset and update
// may not occur until next baseline_gf_interval.
if (cr->percent_refresh > 0)
- rc->baseline_gf_interval = 4 * (100 / cr->percent_refresh);
+ rc->baseline_gf_interval = 2 * (100 / cr->percent_refresh);
else
- rc->baseline_gf_interval = 40;
+ rc->baseline_gf_interval = 20;
}
// Update the segmentation map, and related quantities: cyclic refresh map,
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index b157985..e894ad3 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -339,8 +339,13 @@
if (last3_is_last || last3_is_alt || last3_is_last2) flags &= ~AOM_LAST3_FLAG;
- if (gld_is_last || gld_is_alt || gld_is_last2 || gld_is_last3)
+ if (gld_is_last || gld_is_last2 || gld_is_last3) {
flags &= ~AOM_GOLD_FLAG;
+ }
+
+ if (!cpi->sf.use_fast_nonrd_pick_mode && gld_is_alt) {
+ flags &= ~AOM_GOLD_FLAG;
+ }
if ((bwd_is_last || bwd_is_alt || bwd_is_last2 || bwd_is_last3 || bwd_is_gld))
flags &= ~AOM_BWD_FLAG;
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index f1395fa..ebffd3e 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -223,6 +223,9 @@
if (tmp_sad + (num_pels_log2_lookup[bsize] << 4) > best_pred_sad) return -1;
frame_mv[NEWMV][ref_frame].as_int = mi->mv[0].as_int;
+ x->best_mv.as_int = mi->mv[0].as_int;
+ x->best_mv.as_mv.row >>= 3;
+ x->best_mv.as_mv.col >>= 3;
MV ref_mv = av1_get_ref_mv(x, 0).as_mv;
*rate_mv =
@@ -237,6 +240,7 @@
cpi->sf.mv.subpel_iters_per_step, cond_cost_list(cpi, cost_list),
x->nmv_vec_cost, x->mv_cost_stack, &dis, &x->pred_sse[ref_frame], NULL,
NULL, 0, 0, 0, 0, 0, 1);
+ frame_mv[NEWMV][ref_frame].as_int = x->best_mv.as_int;
} else if (!combined_motion_search(cpi, x, bsize, mi_row, mi_col,
&frame_mv[NEWMV][ref_frame], rate_mv,
best_rdc->rdcost, 0)) {
@@ -1057,6 +1061,8 @@
int use_golden_nonzeromv = 1;
int force_skip_low_temp_var = 0;
int skip_ref_find_pred[5] = { 0 };
+ unsigned int sse_zeromv_norm = UINT_MAX;
+ const unsigned int thresh_skip_golden = 500;
int64_t best_sse_sofar = INT64_MAX;
int gf_temporal_ref = 0;
const struct segmentation *const seg = &cm->seg;
@@ -1135,25 +1141,13 @@
mi->ref_frame[0] = NONE_FRAME;
mi->ref_frame[1] = NONE_FRAME;
-// TODO(kyslov) Refine logic of selecting REF FRAME SET.
-// For now only LAST_FRAME is used
-#if 0
if (cpi->rc.frames_since_golden == 0 && gf_temporal_ref) {
usable_ref_frame = LAST_FRAME;
} else {
usable_ref_frame = GOLDEN_FRAME;
}
- force_skip_low_temp_var = get_force_skip_low_temp_var(&x->variance_low[0],
- mi_row, mi_col, bsize);
- // If force_skip_low_temp_var is set, and for short circuit mode = 1 and 3,
- // skip golden reference.
- if (force_skip_low_temp_var) {
- usable_ref_frame = LAST_FRAME;
- }
-
- if (!((cpi->ref_frame_flags & flag_list[GOLDEN_FRAME]) &&
- !force_skip_low_temp_var))
+ if (!(cpi->ref_frame_flags & flag_list[GOLDEN_FRAME]))
use_golden_nonzeromv = 0;
// If the segment reference frame feature is enabled and it's set to GOLDEN
@@ -1164,8 +1158,6 @@
usable_ref_frame = GOLDEN_FRAME;
skip_ref_find_pred[GOLDEN_FRAME] = 0;
}
-#endif
- usable_ref_frame = LAST_FRAME;
for (MV_REFERENCE_FRAME ref_frame_iter = LAST_FRAME;
ref_frame_iter <= usable_ref_frame; ++ref_frame_iter) {
@@ -1185,7 +1177,6 @@
cpi->oxcf.rc_mode == AOM_CBR && large_block &&
!cyclic_refresh_segment_id_boosted(xd->mi[0]->segment_id) &&
cm->base_qindex;
-
for (int idx = 0; idx < num_inter_modes; ++idx) {
int rate_mv = 0;
int mode_rd_thresh;
@@ -1222,12 +1213,20 @@
get_segdata(seg, mi->segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame)
continue;
+ if (ref_frame == GOLDEN_FRAME && cpi->oxcf.rc_mode == AOM_CBR &&
+ sse_zeromv_norm < thresh_skip_golden && this_mode == NEWMV)
+ continue;
+
if (!(cpi->ref_frame_flags & flag_list[ref_frame])) continue;
if (!(inter_mode_mask[bsize] & (1 << this_mode))) continue;
if (const_motion[ref_frame] && this_mode == NEARMV) continue;
+ if (ref_frame == GOLDEN_FRAME && bsize > BLOCK_16X16) continue;
+
+ if (ref_frame == GOLDEN_FRAME && this_mode == NEARMV) continue;
+
// Skip non-zeromv mode search for golden frame if force_skip_low_temp_var
// is set. If nearestmv for golden frame is 0, zeromv mode will be skipped
// later.
@@ -1238,19 +1237,18 @@
}
// TODO(kyslov) Refine logic of pruning reference .
-// For now only LAST_FRAME is used
#if 0
if (x->content_state_sb != kVeryHighSad &&
- (cpi->sf.short_circuit_low_temp_var >= 2 ||
- (cpi->sf.short_circuit_low_temp_var == 1 && bsize == BLOCK_64X64))
- && force_skip_low_temp_var && ref_frame == LAST_FRAME && this_mode ==
- NEWMV) { continue;
+ (cpi->sf.short_circuit_low_temp_var >= 2 ||
+ (cpi->sf.short_circuit_low_temp_var == 1 && bsize == BLOCK_64X64))
+ && force_skip_low_temp_var && ref_frame == LAST_FRAME && this_mode ==
+ NEWMV) {
+ continue;
}
// Disable this drop out case if the ref frame segment level feature is
// enabled for this segment. This is to prevent the possibility that we
- end
- // up unable to pick any mode.
+ // end up unable to pick any mode.
if (!segfeature_active(seg, mi->segment_id, SEG_LVL_REF_FRAME)) {
if (sf->reference_masking &&
!(frame_mv[this_mode][ref_frame].as_int == 0 &&
@@ -1268,7 +1266,7 @@
int ref1 = (ref_frame == GOLDEN_FRAME) ? LAST_FRAME :
GOLDEN_FRAME; int ref2 = (ref_frame == ALTREF_FRAME) ? LAST_FRAME :
ALTREF_FRAME; if (((cpi->ref_frame_flags & flag_list[ref1]) &&
- (x->pred_mv_sad[ref_frame] > (x->pred_mv_sad[ref1] << 1))) ||
+ (x->pred_mv_sad[ref_frame] > (x->pred_mv_sad[ref1] << 1))) ||
((cpi->ref_frame_flags & flag_list[ref2]) &&
(x->pred_mv_sad[ref_frame] > (x->pred_mv_sad[ref2] << 1))))
ref_frame_skip_mask |= (1 << ref_frame);
@@ -1371,6 +1369,10 @@
#if !_TMP_USE_CURVFIT_
}
#endif
+ if (ref_frame == LAST_FRAME && frame_mv[this_mode][ref_frame].as_int == 0) {
+ sse_zeromv_norm =
+ sse_y >> (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]);
+ }
if (sse_y < best_sse_sofar) best_sse_sofar = sse_y;