rtc: Fixes to rate control under bandwidth change Reset buffer level when there is significant change in bandwidth via change_config, for both 1 layer and svc. Also clamp the buffer_level to maximum_buffer_size in set_rc_buffer_sizes(). This allows better response in rate control for CBR mode when the application changes the bitrate on the fly. Change-Id: I9ddb889c4a0ca3eb60484b127734a14b91f4c269
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index b668ebf..9e69f89 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -735,7 +735,7 @@ av1_set_high_precision_mv(cpi, 1, 0); - set_rc_buffer_sizes(p_rc, rc_cfg); + set_rc_buffer_sizes(cpi); // Under a configuration change, where maximum_buffer_size may change, // keep buffer level clipped to the maximum allowed buffer size. @@ -815,6 +815,8 @@ if (cpi->ppi->use_svc) av1_update_layer_context_change_config(cpi, rc_cfg->target_bandwidth); + check_reset_rc_flag(cpi); + // restore the value of lag_in_frame for LAP stage. if (lap_lag_in_frames != -1) { cpi->oxcf.gf_cfg.lag_in_frames = lap_lag_in_frames;
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index b5b9158..7c5e76e 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c
@@ -1882,6 +1882,7 @@ cpi->rc.frames_to_key--; cpi->rc.rc_2_frame = 0; cpi->rc.rc_1_frame = 0; + cpi->rc.prev_avg_frame_bandwidth = cpi->rc.avg_frame_bandwidth; } int av1_find_qindex(double desired_q, aom_bit_depth_t bit_depth,
diff --git a/av1/encoder/rc_utils.h b/av1/encoder/rc_utils.h index df77357..0a9d02d 100644 --- a/av1/encoder/rc_utils.h +++ b/av1/encoder/rc_utils.h
@@ -19,8 +19,30 @@ extern "C" { #endif -static AOM_INLINE void set_rc_buffer_sizes(PRIMARY_RATE_CONTROL *p_rc, - const RateControlCfg *rc_cfg) { +static AOM_INLINE void check_reset_rc_flag(AV1_COMP *cpi) { + RATE_CONTROL *rc = &cpi->rc; + PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; + if (cpi->common.current_frame.frame_number > + (unsigned int)cpi->svc.number_spatial_layers) { + if (cpi->ppi->use_svc) { + av1_svc_check_reset_layer_rc_flag(cpi); + } else { + if (rc->avg_frame_bandwidth > (3 * rc->prev_avg_frame_bandwidth >> 1) || + rc->avg_frame_bandwidth < (rc->prev_avg_frame_bandwidth >> 1)) { + rc->rc_1_frame = 0; + rc->rc_2_frame = 0; + rc->bits_off_target = p_rc->optimal_buffer_level; + rc->buffer_level = p_rc->optimal_buffer_level; + } + } + } +} + +static AOM_INLINE void set_rc_buffer_sizes(AV1_COMP *cpi) { + RATE_CONTROL *rc = &cpi->rc; + PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; + const RateControlCfg *const rc_cfg = &cpi->oxcf.rc_cfg; + const int64_t bandwidth = rc_cfg->target_bandwidth; const int64_t starting = rc_cfg->starting_buffer_level_ms; const int64_t optimal = rc_cfg->optimal_buffer_level_ms; @@ -31,6 +53,11 @@ (optimal == 0) ? bandwidth / 8 : optimal * bandwidth / 1000; p_rc->maximum_buffer_size = (maximum == 0) ? bandwidth / 8 : maximum * bandwidth / 1000; + + // Under a configuration change, where maximum_buffer_size may change, + // keep buffer level clipped to the maximum allowed buffer size. + rc->bits_off_target = AOMMIN(rc->bits_off_target, p_rc->maximum_buffer_size); + rc->buffer_level = AOMMIN(rc->buffer_level, p_rc->maximum_buffer_size); } static AOM_INLINE void config_target_level(AV1_COMP *const cpi,
diff --git a/av1/encoder/svc_layercontext.c b/av1/encoder/svc_layercontext.c index 0ad0cf6..5cff958 100644 --- a/av1/encoder/svc_layercontext.c +++ b/av1/encoder/svc_layercontext.c
@@ -488,3 +488,28 @@ } } } + +void av1_svc_check_reset_layer_rc_flag(AV1_COMP *const cpi) { + SVC *const svc = &cpi->svc; + for (int sl = 0; sl < svc->number_spatial_layers; ++sl) { + // Check for reset based on avg_frame_bandwidth for spatial layer sl. + int layer = LAYER_IDS_TO_IDX(sl, svc->number_temporal_layers - 1, + svc->number_temporal_layers); + LAYER_CONTEXT *lc = &svc->layer_context[layer]; + RATE_CONTROL *lrc = &lc->rc; + if (lrc->avg_frame_bandwidth > (3 * lrc->prev_avg_frame_bandwidth >> 1) || + lrc->avg_frame_bandwidth < (lrc->prev_avg_frame_bandwidth >> 1)) { + // Reset for all temporal layers with spatial layer sl. + for (int tl = 0; tl < svc->number_temporal_layers; ++tl) { + int layer2 = LAYER_IDS_TO_IDX(sl, tl, svc->number_temporal_layers); + LAYER_CONTEXT *lc2 = &svc->layer_context[layer2]; + RATE_CONTROL *lrc2 = &lc2->rc; + PRIMARY_RATE_CONTROL *const lp_rc = &lc2->p_rc; + lrc2->rc_1_frame = 0; + lrc2->rc_2_frame = 0; + lrc2->bits_off_target = lp_rc->optimal_buffer_level; + lrc2->buffer_level = lp_rc->optimal_buffer_level; + } + } + } +}
diff --git a/av1/encoder/svc_layercontext.h b/av1/encoder/svc_layercontext.h index 5ceaf0f..817e362 100644 --- a/av1/encoder/svc_layercontext.h +++ b/av1/encoder/svc_layercontext.h
@@ -277,6 +277,8 @@ void av1_set_svc_fixed_mode(struct AV1_COMP *const cpi); +void av1_svc_check_reset_layer_rc_flag(struct AV1_COMP *const cpi); + #ifdef __cplusplus } // extern "C" #endif