rtc: Allow QP to decrease more aggressively for static content For RTC static content, with stable buffer level, relax the limit on how much QP can change frame-to-frame and allow for a delta bias. This allows for faster quality ramp-up and QP convergence on static content following scene change. Added feature to control it, enabled for screen content at the higher speed settings. Bug: 362936830 Change-Id: I751ebde7295b1e70851aeec00406674fa112d2e6
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index 4fd5ec6..df948e8 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c
@@ -624,6 +624,26 @@ ? AOMMIN(8, AOMMAX(1, rc->q_1_frame / 16)) : AOMMIN(16, AOMMAX(1, rc->q_1_frame / 8)); } + // For screen static content with stable buffer level: relax the + // limit on max_delta_down and apply bias qp, based on buffer fullness. + // Only for high speeds levels for now to avoid bdrate regression. + if (cpi->sf.rt_sf.rc_faster_convergence_static == 1 && + cpi->sf.rt_sf.check_scene_detection && rc->frame_source_sad == 0 && + rc->static_since_last_scene_change && + p_rc->buffer_level > (p_rc->optimal_buffer_level >> 1) && + cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ && + cpi->cyclic_refresh->counter_encode_maxq_scene_change > 4) { + int qp_delta = 32; + int qp_bias = 16; + if (p_rc->buffer_level > p_rc->optimal_buffer_level) { + qp_delta = 60; + qp_bias = 32; + } + if (cpi->rc.rc_1_frame == 1) q = q - qp_bias; + max_delta_down = AOMMAX(max_delta_down, qp_delta); + max_delta_up = AOMMIN(max_delta_up, 4); + } + // If resolution changes or avg_frame_bandwidth significantly changed, // then set this flag to indicate change in target bits per macroblock. const int change_target_bits_mb = @@ -3307,7 +3327,11 @@ if (num_samples > 0) rc->percent_blocks_with_motion = ((num_samples - num_zero_temp_sad) * 100) / num_samples; - if (rc->high_source_sad) cpi->rc.frames_since_scene_change = 0; + if (rc->frame_source_sad > 0) rc->static_since_last_scene_change = 0; + if (rc->high_source_sad) { + cpi->rc.frames_since_scene_change = 0; + rc->static_since_last_scene_change = 1; + } // Update the high_motion_content_screen_rtc flag on TL0. Avoid the update // if too many consecutive frame drops occurred. const uint64_t thresh_high_motion = 9 * 64 * 64; @@ -3706,6 +3730,7 @@ } rc->frame_number_encoded = 0; cpi->ppi->rtc_ref.non_reference_frame = 0; + rc->static_since_last_scene_change = 0; } else { *frame_type = INTER_FRAME; gf_group->update_type[cpi->gf_frame_index] = LF_UPDATE;
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h index 1d159ae..356023b 100644 --- a/av1/encoder/ratectrl.h +++ b/av1/encoder/ratectrl.h
@@ -195,6 +195,7 @@ uint64_t prev_avg_source_sad; uint64_t frame_source_sad; uint64_t spatial_variance_keyframe; + int static_since_last_scene_change; int last_encoded_size_keyframe; int last_target_size_keyframe; int frames_since_scene_change;
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c index 2cc0659..ea340a9 100644 --- a/av1/encoder/speed_features.c +++ b/av1/encoder/speed_features.c
@@ -1580,6 +1580,7 @@ sf->rt_sf.dct_only_palette_nonrd = 1; sf->rt_sf.prune_palette_search_nonrd = 1; sf->rt_sf.prune_intra_mode_using_best_sad_so_far = true; + sf->rt_sf.rc_faster_convergence_static = 1; } if (speed >= 11) { sf->rt_sf.skip_lf_screen = 2; @@ -2327,6 +2328,7 @@ rt_sf->higher_thresh_scene_detection = 1; rt_sf->skip_newmv_flat_blocks_screen = 0; rt_sf->skip_encoding_non_reference_slide_change = 0; + rt_sf->rc_faster_convergence_static = 0; } static fractional_mv_step_fp
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h index 5aec86f..00b415f 100644 --- a/av1/encoder/speed_features.h +++ b/av1/encoder/speed_features.h
@@ -1922,6 +1922,10 @@ // Flag to force skip encoding for non_reference_frame on slide/scene changes. int skip_encoding_non_reference_slide_change; + + // Flag to indicate more aggressive QP downward adjustment for screen static + // content, to make convergence to min_qp faster. + int rc_faster_convergence_static; } REAL_TIME_SPEED_FEATURES; /*!\endcond */
diff --git a/av1/encoder/svc_layercontext.c b/av1/encoder/svc_layercontext.c index 5b2e2d8..52c0500 100644 --- a/av1/encoder/svc_layercontext.c +++ b/av1/encoder/svc_layercontext.c
@@ -230,6 +230,8 @@ const int last_target_size_keyframe = cpi->rc.last_target_size_keyframe; const int max_consec_drop = cpi->rc.max_consec_drop; const int postencode_drop = cpi->rc.postencode_drop; + const int static_since_last_scene_change = + cpi->rc.static_since_last_scene_change; // Restore layer rate control. cpi->rc = lc->rc; cpi->ppi->p_rc = lc->p_rc; @@ -247,6 +249,7 @@ cpi->rc.last_target_size_keyframe = last_target_size_keyframe; cpi->rc.max_consec_drop = max_consec_drop; cpi->rc.postencode_drop = postencode_drop; + cpi->rc.static_since_last_scene_change = static_since_last_scene_change; // For spatial-svc, allow cyclic-refresh to be applied on the spatial layers, // for the base temporal layer. if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&