rtc: Fixes and some adjustments to cyclic refresh
Correct the update to the actual_seg#_blocks for
skip blocks. Also avoid using the rate/dist threshold
at low-resoln or for lower speeds, as they need to be
better tuned/adjusted for those cases.
And adjust some parameters mainly for low-resoln case.
bdrate gains on rtc_derf for speed 6/7/9: ~1.1/0.4/0.27%
neutral/small loss on rtc set for speed 7/9/10: ~0.27/0.5/0.08
Change-Id: I4a5f82ace14f16798efbdc18c897e88de07c98b8
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c
index f780d3c..71393dc 100644
--- a/av1/encoder/aq_cyclicrefresh.c
+++ b/av1/encoder/aq_cyclicrefresh.c
@@ -159,35 +159,31 @@
const AV1_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = xd->mi[0];
- int sh = cpi->cyclic_refresh->skip_over4x4 ? 2 : 1;
const int prev_segment_id = mbmi->segment_id;
- mbmi->segment_id = av1_get_spatial_seg_pred(cm, xd, &cdf_num);
- if (prev_segment_id != mbmi->segment_id) {
- CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
- const int bw = mi_size_wide[bsize];
- const int bh = mi_size_high[bsize];
- const int xmis = AOMMIN(cm->mi_params.mi_cols - mi_col, bw);
- const int ymis = AOMMIN(cm->mi_params.mi_rows - mi_row, bh);
- const int block_index = mi_row * cm->mi_params.mi_cols + mi_col;
- for (int mi_y = 0; mi_y < ymis; mi_y += sh) {
- for (int mi_x = 0; mi_x < xmis; mi_x += sh) {
- const int map_offset =
- block_index + mi_y * cm->mi_params.mi_cols + mi_x;
- cr->map[map_offset] = 0;
- cpi->enc_seg.map[map_offset] = mbmi->segment_id;
- cm->cur_frame->seg_map[map_offset] = mbmi->segment_id;
+ CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
+ const int bw = mi_size_wide[bsize];
+ const int bh = mi_size_high[bsize];
+ const int xmis = AOMMIN(cm->mi_params.mi_cols - mi_col, bw);
+ const int ymis = AOMMIN(cm->mi_params.mi_rows - mi_row, bh);
+ if (!cr->skip_over4x4) {
+ mbmi->segment_id = av1_get_spatial_seg_pred(cm, xd, &cdf_num);
+ if (prev_segment_id != mbmi->segment_id) {
+ const int block_index = mi_row * cm->mi_params.mi_cols + mi_col;
+ for (int mi_y = 0; mi_y < ymis; mi_y++) {
+ for (int mi_x = 0; mi_x < xmis; mi_x++) {
+ const int map_offset =
+ block_index + mi_y * cm->mi_params.mi_cols + mi_x;
+ cr->map[map_offset] = 0;
+ cpi->enc_seg.map[map_offset] = mbmi->segment_id;
+ cm->cur_frame->seg_map[map_offset] = mbmi->segment_id;
+ }
}
}
- if (cyclic_refresh_segment_id(prev_segment_id) == CR_SEGMENT_ID_BOOST1)
- x->actual_num_seg1_blocks -= xmis * ymis;
- else if (cyclic_refresh_segment_id(prev_segment_id) == CR_SEGMENT_ID_BOOST2)
- x->actual_num_seg2_blocks -= xmis * ymis;
- if (cyclic_refresh_segment_id(mbmi->segment_id) == CR_SEGMENT_ID_BOOST1)
- x->actual_num_seg1_blocks += xmis * ymis;
- else if (cyclic_refresh_segment_id(mbmi->segment_id) ==
- CR_SEGMENT_ID_BOOST2)
- x->actual_num_seg2_blocks += xmis * ymis;
}
+ if (cyclic_refresh_segment_id(prev_segment_id) == CR_SEGMENT_ID_BOOST1)
+ x->actual_num_seg1_blocks -= xmis * ymis;
+ else if (cyclic_refresh_segment_id(prev_segment_id) == CR_SEGMENT_ID_BOOST2)
+ x->actual_num_seg2_blocks -= xmis * ymis;
}
void av1_cyclic_refresh_update_segment(const AV1_COMP *cpi, MACROBLOCK *const x,
@@ -424,7 +420,7 @@
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame) ||
(rc->frames_since_key > 20 &&
p_rc->avg_frame_qindex[INTER_FRAME] > qp_max_thresh) ||
- (rc->avg_frame_low_motion && rc->avg_frame_low_motion < 45 &&
+ (rc->avg_frame_low_motion && rc->avg_frame_low_motion < 30 &&
rc->frames_since_key > 40)) {
cr->apply_cyclic_refresh = 0;
return;
@@ -451,8 +447,8 @@
cr->motion_thresh = 16;
cr->rate_boost_fac = 13;
} else {
- cr->max_qdelta_perc = 70;
- cr->rate_ratio_qdelta = AOMMAX(cr->rate_ratio_qdelta, 2.5);
+ cr->max_qdelta_perc = 50;
+ cr->rate_ratio_qdelta = AOMMAX(cr->rate_ratio_qdelta, 2.0);
}
}
if (cpi->oxcf.rc_cfg.mode == AOM_VBR) {
@@ -518,7 +514,12 @@
// q will not exceed 457, so (q * q) is within 32bit; see:
// av1_convert_qindex_to_q(), av1_ac_quant(), ac_qlookup*[].
cr->thresh_dist_sb = ((int64_t)(q * q)) << 2;
-
+ // For low-resoln or lower speeds, the rate/dist thresholds need to be
+ // tuned/updated.
+ if (cpi->oxcf.speed <= 7 || (cm->width * cm->height < 640 * 360)) {
+ cr->thresh_dist_sb = 0;
+ cr->thresh_rate_sb = INT64_MAX;
+ }
// Set up segmentation.
// Clear down the segment map.
av1_enable_segmentation(&cm->seg);
diff --git a/av1/encoder/partition_search.c b/av1/encoder/partition_search.c
index c839019..529245b 100644
--- a/av1/encoder/partition_search.c
+++ b/av1/encoder/partition_search.c
@@ -2091,7 +2091,7 @@
if (tile_data->allow_update_cdf) update_stats(&cpi->common, td);
}
if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ && mbmi->skip_txfm &&
- !cpi->cyclic_refresh->skip_over4x4 && !cpi->rc.rtc_external_ratectrl)
+ !cpi->rc.rtc_external_ratectrl)
av1_cyclic_reset_segment_skip(cpi, x, mi_row, mi_col, bsize);
// TODO(Ravi/Remya): Move this copy function to a better logical place
// This function will copy the best mode information from block
diff --git a/test/loopfilter_control_test.cc b/test/loopfilter_control_test.cc
index a67e97b..2d0cc5a 100644
--- a/test/loopfilter_control_test.cc
+++ b/test/loopfilter_control_test.cc
@@ -31,8 +31,8 @@
std::unordered_map<std::string,
std::unordered_map<int, std::unordered_map<int, double>>>
kPsnrThreshold = { { "park_joy_90p_8_420.y4m",
- { { 0, { { 0, 35.0 }, { 3, 36.0 } } },
- { 1, { { 0, 35.1 }, { 3, 36.1 } } },
+ { { 0, { { 0, 35.0 }, { 3, 35.8 } } },
+ { 1, { { 0, 35.1 }, { 3, 35.9 } } },
{ 2, { { 0, 35.1 }, { 3, 36.1 } } },
{ 3, { { 0, 35.1 }, { 3, 36.1 } } } } },
{ "paris_352_288_30.y4m",