ref: 67bfbcfbf706766c841ac900b6cd2165c651983c
parent: eebc5cd487a89c51ba148f6d6ac45779970f72d7
author: Marco Paniconi <marpan@google.com>
date: Thu Jun 24 19:34:36 EDT 2021
vp9-rtc: Extract content dependency in cyclic refresh For usage in the external RC. When content_mode = 0, the cyclic refresh has no dependency on the content (motion, spatial variance, motion vectors, etc,). The content_mode = 0, when compared to content_mode = 1, on rtc set for speed 7: has some regression on some clips (~3-5%), but overall/average bdrate loss is about ~1-2%. Comparing aq_mode=3 with content_mode = 0, vs aq_mode=3: about ~14% avg/overall bdrate gain, but has ~3-7% regression on some hard motion clip (e.g.m street). Change-Id: I93117fabb8f7f89032c15baf1292b201e8c07362
--- a/vp9/encoder/vp9_aq_cyclicrefresh.c
+++ b/vp9/encoder/vp9_aq_cyclicrefresh.c
@@ -48,6 +48,7 @@
assert(MAXQ <= 255);
memset(cr->last_coded_q_map, MAXQ, last_coded_q_map_size);
cr->counter_encode_maxq_scene_change = 0;
+ cr->content_mode = 1;
return cr;
}
@@ -326,7 +327,8 @@
else
rc->baseline_gf_interval = 40;
if (cpi->oxcf.rc_mode == VPX_VBR) rc->baseline_gf_interval = 20;
- if (rc->avg_frame_low_motion < 50 && rc->frames_since_key > 40)
+ if (rc->avg_frame_low_motion < 50 && rc->frames_since_key > 40 &&
+ cr->content_mode)
rc->baseline_gf_interval = 10;
}
@@ -388,7 +390,8 @@
? vp9_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST2, cm->base_qindex)
: vp9_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST1, cm->base_qindex);
// More aggressive settings for noisy content.
- if (cpi->noise_estimate.enabled && cpi->noise_estimate.level >= kMedium) {
+ if (cpi->noise_estimate.enabled && cpi->noise_estimate.level >= kMedium &&
+ cr->content_mode) {
consec_zero_mv_thresh = 60;
qindex_thresh =
VPXMAX(vp9_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST1, cm->base_qindex),
@@ -409,7 +412,7 @@
#if CONFIG_VP9_HIGHBITDEPTH
if (cpi->common.use_highbitdepth) compute_content = 0;
#endif
- if (cpi->Last_Source == NULL ||
+ if (cr->content_mode == 0 || cpi->Last_Source == NULL ||
cpi->Last_Source->y_width != cpi->Source->y_width ||
cpi->Last_Source->y_height != cpi->Source->y_height)
compute_content = 0;
@@ -430,7 +433,8 @@
// reset to 0 later depending on the coding mode.
if (cr->map[bl_index2] == 0) {
count_tot++;
- if (cr->last_coded_q_map[bl_index2] > qindex_thresh ||
+ if (cr->content_mode == 0 ||
+ cr->last_coded_q_map[bl_index2] > qindex_thresh ||
cpi->consec_zero_mv[bl_index2] < consec_zero_mv_thresh_block) {
sum_map++;
count_sel++;
@@ -489,7 +493,8 @@
rc->avg_frame_qindex[INTER_FRAME] < qp_thresh ||
(cpi->use_svc &&
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame) ||
- (!cpi->use_svc && rc->avg_frame_low_motion < thresh_low_motion &&
+ (!cpi->use_svc && cr->content_mode &&
+ rc->avg_frame_low_motion < thresh_low_motion &&
rc->frames_since_key > 40) ||
(!cpi->use_svc && rc->avg_frame_qindex[INTER_FRAME] > qp_max_thresh &&
rc->frames_since_key > 20)) {
@@ -528,7 +533,7 @@
cr->percent_refresh = (cr->skip_flat_static_blocks) ? 5 : 10;
// Increase the amount of refresh on scene change that is encoded at max Q,
// increase for a few cycles of the refresh period (~100 / percent_refresh).
- if (cr->counter_encode_maxq_scene_change < 30)
+ if (cr->content_mode && cr->counter_encode_maxq_scene_change < 30)
cr->percent_refresh = (cr->skip_flat_static_blocks) ? 10 : 15;
cr->rate_ratio_qdelta = 2.0;
cr->rate_boost_fac = 10;
@@ -575,6 +580,12 @@
(double)(cr->actual_num_seg1_blocks + cr->actual_num_seg2_blocks) /
num8x8bl;
cr->weight_segment = weight_segment;
+ if (cr->content_mode == 0) {
+ cr->actual_num_seg1_blocks =
+ cr->percent_refresh * cm->mi_rows * cm->mi_cols / 100;
+ cr->actual_num_seg2_blocks = 0;
+ cr->weight_segment = (double)(cr->actual_num_seg1_blocks) / num8x8bl;
+ }
}
// Setup cyclic background refresh: set delta q and segmentation map.
--- a/vp9/encoder/vp9_aq_cyclicrefresh.h
+++ b/vp9/encoder/vp9_aq_cyclicrefresh.h
@@ -70,6 +70,7 @@
int apply_cyclic_refresh;
int counter_encode_maxq_scene_change;
int skip_flat_static_blocks;
+ int content_mode;
};
struct VP9_COMP;
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1842,7 +1842,8 @@
}
// Else for cyclic refresh mode update the segment map, set the segment id
// and then update the quantizer.
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
+ if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
+ cpi->cyclic_refresh->content_mode) {
vp9_cyclic_refresh_update_segment(cpi, xd->mi[0], mi_row, mi_col, bsize,
ctx->rate, ctx->dist, x->skip, p);
}
@@ -2539,7 +2540,8 @@
if (seg->enabled && (cpi->oxcf.aq_mode != NO_AQ || cpi->roi.enabled)) {
// Setting segmentation map for cyclic_refresh.
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
+ if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
+ cpi->cyclic_refresh->content_mode) {
vp9_cyclic_refresh_update_segment(cpi, mi, mi_row, mi_col, bsize,
ctx->rate, ctx->dist, x->skip, p);
} else {
@@ -6716,7 +6718,8 @@
++td->counts->tx.tx_totals[mi->tx_size];
++td->counts->tx.tx_totals[get_uv_tx_size(mi, &xd->plane[1])];
- if (cm->seg.enabled && cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
+ if (cm->seg.enabled && cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
+ cpi->cyclic_refresh->content_mode)
vp9_cyclic_refresh_update_sb_postencode(cpi, mi, mi_row, mi_col, bsize);
if (cpi->oxcf.pass == 0 && cpi->svc.temporal_layer_id == 0 &&
(!cpi->use_svc ||
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -4208,7 +4208,7 @@
// Update some stats from cyclic refresh, and check for golden frame update.
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled &&
- !frame_is_intra_only(cm))
+ !frame_is_intra_only(cm) && cpi->cyclic_refresh->content_mode)
vp9_cyclic_refresh_postencode(cpi);
// Update the skip mb flag probabilities based on the distribution