rtc: Avoid Q adjustment if frame_avg_sad is zero
Add parameter for the frame level average sad,
computed in the scene detection. Use this to
avoid the source_sad/content adjustment to Q if
frame_avg_sad is 0, because it can cause Q to
decrease too fast after scene change.
Also fix bug where cyclic refresh was not turned
off on scene change.
Reduces overshoot/big frames after scene change,
and average encoded bitrate is ~10% closer to target
for 500k on some screen clips. Small speedup (~2-3%)
and average psnr drops ~0.3dB.
Change-Id: I4fc93c9801bad5d8234779a7bfb81632f2f47b17
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c
index 9d95788..bab95e1 100644
--- a/av1/encoder/aq_cyclicrefresh.c
+++ b/av1/encoder/aq_cyclicrefresh.c
@@ -404,6 +404,9 @@
double weight_segment = 0;
int qp_thresh = AOMMIN(20, rc->best_quality << 1);
int qp_max_thresh = 118 * MAXQ >> 7;
+ const int scene_change_detected =
+ cpi->rc.high_source_sad ||
+ (cpi->ppi->use_svc && cpi->svc.high_source_sad_superframe);
// Although this segment feature for RTC is only used for
// blocks >= 8X8, for more efficient coding of the seg map
// cur_frame->seg_map needs to set at 4x4 along with the
@@ -415,7 +418,7 @@
cr->skip_over4x4 = (cpi->oxcf.speed > 9) ? 1 : 0;
cr->apply_cyclic_refresh = 1;
if (frame_is_intra_only(cm) || is_lossless_requested(&cpi->oxcf.rc_cfg) ||
- cpi->svc.temporal_layer_id > 0 ||
+ scene_change_detected || cpi->svc.temporal_layer_id > 0 ||
p_rc->avg_frame_qindex[INTER_FRAME] < qp_thresh ||
(cpi->svc.number_spatial_layers > 1 &&
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame) ||
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index b272599..66606b8 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -477,7 +477,8 @@
}
// Adjust Q base on source content change from scene detection.
if (cpi->sf.rt_sf.check_scene_detection && rc->prev_avg_source_sad > 0 &&
- rc->frames_since_key > 10 && !cpi->ppi->use_svc) {
+ rc->frames_since_key > 10 && rc->frame_source_sad > 0 &&
+ !cpi->ppi->use_svc) {
const int bit_depth = cm->seq_params->bit_depth;
double delta =
(double)rc->avg_source_sad / (double)rc->prev_avg_source_sad - 1.0;
@@ -2742,6 +2743,7 @@
else
rc->high_source_sad = 0;
rc->avg_source_sad = (3 * rc->avg_source_sad + avg_sad) >> 2;
+ rc->frame_source_sad = avg_sad;
}
cpi->svc.high_source_sad_superframe = rc->high_source_sad;
}
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index f8c578c..c47348c 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -182,6 +182,7 @@
int high_source_sad;
uint64_t avg_source_sad;
uint64_t prev_avg_source_sad;
+ uint64_t frame_source_sad;
int avg_frame_bandwidth; // Average frame size target for clip
int min_frame_bandwidth; // Minimum allocation used for any frame