rtc: Adjust cyclic refresh for screen Reset the refresh on slide change and set larger refresh period for some frames after scene change that is encoded at high Q for faster cleanup. Also make sure source_sad speed feature is always on for screen mode. Visual quality improvement after scene change, average psnr increase of ~0.25dB on 1850x1110 slide change clip, with little/no change in speed/fps. Change-Id: If9d29a830a3f1b9483e112de65b3d650d7148fa1
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c index 71393dc..9d95788 100644 --- a/av1/encoder/aq_cyclicrefresh.c +++ b/av1/encoder/aq_cyclicrefresh.c
@@ -25,6 +25,7 @@ if (cr == NULL) return NULL; cr->map = aom_calloc(mi_rows * mi_cols, sizeof(*cr->map)); + cr->counter_encode_maxq_scene_change = 0; if (cr->map == NULL) { av1_cyclic_refresh_free(cr); return NULL; @@ -426,11 +427,18 @@ return; } cr->percent_refresh = 10; - if (cpi->svc.number_temporal_layers > 2) cr->percent_refresh = 15; + // Increase the amount of refresh for #temporal_layers > 2, and for some + // frames after scene change that is encoded at high Q. + if (cpi->svc.number_temporal_layers > 2) + cr->percent_refresh = 15; + else if (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN && + cr->counter_encode_maxq_scene_change < 20) + cr->percent_refresh = 20; cr->max_qdelta_perc = 60; cr->time_for_refresh = 0; cr->motion_thresh = 32; - cr->rate_boost_fac = 15; + cr->rate_boost_fac = + (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN) ? 10 : 15; // Use larger delta-qp (increase rate_ratio_qdelta) for first few (~4) // periods of the refresh cycle, after a key frame. // Account for larger interval on base layer for temporal layers. @@ -491,7 +499,10 @@ const RATE_CONTROL *const rc = &cpi->rc; CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; struct segmentation *const seg = &cm->seg; - int resolution_change = + const int scene_change_detected = + cpi->rc.high_source_sad || + (cpi->ppi->use_svc && cpi->svc.high_source_sad_superframe); + const int resolution_change = cm->prev_frame && (cm->width != cm->prev_frame->width || cm->height != cm->prev_frame->height); if (resolution_change) av1_cyclic_refresh_reset_resize(cpi); @@ -500,11 +511,13 @@ unsigned char *const seg_map = cpi->enc_seg.map; memset(seg_map, 0, cm->mi_params.mi_rows * cm->mi_params.mi_cols); av1_disable_segmentation(&cm->seg); - if (cm->current_frame.frame_type == KEY_FRAME) { + if (cm->current_frame.frame_type == KEY_FRAME || scene_change_detected) { cr->sb_index = 0; + cr->counter_encode_maxq_scene_change = 0; } return; } else { + cr->counter_encode_maxq_scene_change++; const double q = av1_convert_qindex_to_q(cm->quant_params.base_qindex, cm->seq_params->bit_depth); // Set rate threshold to some multiple (set to 2 for now) of the target @@ -578,4 +591,5 @@ cr->sb_index = 0; cpi->refresh_frame.golden_frame = true; cr->apply_cyclic_refresh = 0; + cr->counter_encode_maxq_scene_change = 0; }
diff --git a/av1/encoder/aq_cyclicrefresh.h b/av1/encoder/aq_cyclicrefresh.h index 4e4e1f2..484f88f 100644 --- a/av1/encoder/aq_cyclicrefresh.h +++ b/av1/encoder/aq_cyclicrefresh.h
@@ -108,6 +108,7 @@ double weight_segment; int apply_cyclic_refresh; int skip_over4x4; + int counter_encode_maxq_scene_change; /*!\endcond */ };
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index b5448d5..8b4abc9 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c
@@ -3084,6 +3084,7 @@ double q2; int enumerator; *q = (3 * cpi->rc.worst_quality + *q) >> 2; + cpi->cyclic_refresh->counter_encode_maxq_scene_change = 0; // Adjust avg_frame_qindex, buffer_level, and rate correction factors, as // these parameters will affect QP selection for subsequent frames. If they // have settled down to a very different (low QP) state, then not adjusting
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c index 8ab710c..7dbabbc 100644 --- a/av1/encoder/speed_features.c +++ b/av1/encoder/speed_features.c
@@ -1289,8 +1289,10 @@ cpi->svc.ref_frame_comp[2] && cpi->svc.reference[ALTREF_FRAME - 1]; } } - if (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN) + if (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN) { sf->rt_sf.use_comp_ref_nonrd = 0; + sf->rt_sf.source_metrics_sb_nonrd = 1; + } } // TODO(kyslov): now this is very similar to