rtc: Fixes for temporal layers
Use better motion search for base temporal layer
TL0 (and also on TL1 for 3 temporal layers for now)
on speed 6 (this moves the logic up from speed 7).
And rate control fix to allow the QP to go down faster
after a key frame for temporal layers.
This improves performance: ~3-4% bdrate gain for sp 6
on rtc_set for 3TL (with lm=2), and reduces visual
artifacts observed after key frame.
Change-Id: I5f19be97f93772e72f4b54f0f8faa6691f799f44
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 48ee11a..292bdeb 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -879,6 +879,8 @@
const AV1_COMMON *const cm = &cpi->common;
const RATE_CONTROL *rc = &cpi->rc;
const PRIMARY_RATE_CONTROL *p_rc = &cpi->ppi->p_rc;
+ const SVC *const svc = &cpi->svc;
+ unsigned int num_frames_weight_key = 5 * cpi->svc.number_temporal_layers;
// Buffer level below which we push active_worst to worst_quality.
int64_t critical_level = p_rc->optimal_buffer_level >> 3;
int64_t buff_lvl_step = 0;
@@ -890,10 +892,20 @@
// for the first few frames following key frame. These are both initialized
// to worst_quality and updated with (3/4, 1/4) average in postencode_update.
// So for first few frames following key, the qp of that key frame is weighted
- // into the active_worst_quality setting.
- ambient_qp = (cm->current_frame.frame_number < 5)
- ? AOMMIN(p_rc->avg_frame_qindex[INTER_FRAME],
- p_rc->avg_frame_qindex[KEY_FRAME])
+ // into the active_worst_quality setting. For SVC the key frame should
+ // correspond to layer (0, 0), so use that for layer context.
+ int avg_qindex_key = p_rc->avg_frame_qindex[KEY_FRAME];
+ if (svc->number_temporal_layers > 1) {
+ int layer = LAYER_IDS_TO_IDX(0, 0, svc->number_temporal_layers);
+ const LAYER_CONTEXT *lc = &svc->layer_context[layer];
+ const PRIMARY_RATE_CONTROL *const lp_rc = &lc->p_rc;
+ avg_qindex_key = lp_rc->avg_frame_qindex[KEY_FRAME];
+ if (svc->temporal_layer_id == 0)
+ avg_qindex_key =
+ AOMMIN(lp_rc->avg_frame_qindex[KEY_FRAME], lp_rc->last_q[KEY_FRAME]);
+ }
+ ambient_qp = (cm->current_frame.frame_number < num_frames_weight_key)
+ ? AOMMIN(p_rc->avg_frame_qindex[INTER_FRAME], avg_qindex_key)
: p_rc->avg_frame_qindex[INTER_FRAME];
active_worst_quality = AOMMIN(rc->worst_quality, ambient_qp * 5 / 4);
if (p_rc->buffer_level > p_rc->optimal_buffer_level) {
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 4665621..d1bb672 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1417,6 +1417,18 @@
cm->width * cm->height > 640 * 480)
sf->rt_sf.use_temporal_noise_estimate = 1;
sf->rt_sf.skip_tx_no_split_var_based_partition = 1;
+
+ // For SVC: use better mv search on base temporal layers, and only
+ // on base spatial layer if highest resolution is above 640x360.
+ if (cpi->svc.number_temporal_layers > 1 &&
+ cpi->svc.temporal_layer_id < cpi->svc.number_temporal_layers - 1 &&
+ (cpi->svc.spatial_layer_id == 0 ||
+ cpi->oxcf.frm_dim_cfg.width * cpi->oxcf.frm_dim_cfg.height <=
+ 640 * 360)) {
+ sf->mv_sf.search_method = NSTEP;
+ sf->mv_sf.subpel_search_method = SUBPEL_TREE;
+ sf->rt_sf.fullpel_search_step_param = 6;
+ }
}
if (speed >= 6) {
@@ -1464,9 +1476,10 @@
sf->rt_sf.nonrd_check_partition_merge_mode = 1;
sf->rt_sf.nonrd_check_partition_split = 0;
sf->rt_sf.skip_intra_pred_if_tx_skip = 1;
- // For SVC: use better mv search on lower temporal layers, and only
+ // For SVC: use better mv search on base temporal layers, and only
// on base spatial layer if highest resolution is above 640x360.
- if (cpi->svc.temporal_layer_id < cpi->svc.number_temporal_layers - 1 &&
+ if (cpi->svc.number_temporal_layers > 1 &&
+ cpi->svc.temporal_layer_id < cpi->svc.number_temporal_layers - 1 &&
(cpi->svc.spatial_layer_id == 0 ||
cpi->oxcf.frm_dim_cfg.width * cpi->oxcf.frm_dim_cfg.height <=
640 * 360)) {