Adjust gop decision for realtime lookahead mode
For the realtime with lookahead encoding mode:
constrain the gop length on scene cuts, and
allow for disabling the arf frame for high motion
content.
Change-Id: I63b02871058d9286735aeda7d49fc888d23c5ae0
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 0dec565..06905b3 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -2216,10 +2216,15 @@
// Rare case when the look-ahead is less than the target GOP length, can't
// generate ARF frame.
+ // Also disable ARF frame if the motion content (source_sad) is high in
+ // lookahead buffer.
+ const uint64_t thresh_sad = 8 * 64 * 64;
if (p_rc->baseline_gf_interval > gf_cfg->lag_in_frames ||
!is_altref_enabled(gf_cfg->lag_in_frames, gf_cfg->enable_auto_arf) ||
- p_rc->baseline_gf_interval < rc->min_gf_interval)
+ p_rc->baseline_gf_interval < rc->min_gf_interval ||
+ rc->frame_source_sad_lag[0] > thresh_sad) {
gf_group->max_layer_depth_allowed = 0;
+ }
// Set up the structure of this Group-Of-Pictures (same as GF_GROUP)
av1_gop_setup_structure(cpi, is_final_pass);
@@ -3812,6 +3817,10 @@
max_gop_length = AOMMIN(max_gop_length, rc->frames_to_key);
// Go through source frames in lookahead buffer and compute source metrics:
// scene change, frame average source sad, etc.
+ int num_frames = 1;
+ int scene_change_gop_frame_index = 0;
+ rc->frame_source_sad_lag[0] = 0;
+ rc->avg_source_sad = 0;
for (int i = 1; i < max_gop_length; i++) {
EncodeFrameInput frame_input;
memset(&frame_input, 0, sizeof(frame_input));
@@ -3824,22 +3833,30 @@
frame_input.last_source = &e_prev->img;
rc->high_source_sad_lag[i] = -1;
rc->frame_source_sad_lag[i] = 0;
- rc->avg_source_sad = 0;
av1_rc_scene_detection_onepass_rt(cpi, &frame_input);
rc->high_source_sad_lag[i] = rc->high_source_sad;
rc->frame_source_sad_lag[i] = rc->frame_source_sad;
- // Use rc->high_source_sad_lag[i] and frame_source_sad_lag[i] to
- // adjust/adapt the gop parameters. Reset the parameters for the
- // encoding.
- rc->high_source_sad = 0;
- rc->frame_source_sad = UINT64_MAX;
+ if (rc->high_source_sad_lag[i] == 1 && i > 1) {
+ // Scene change, so exit and constrain the gop to this frame.
+ scene_change_gop_frame_index = i;
+ break;
+ }
+ num_frames++;
+ rc->frame_source_sad_lag[0] += rc->frame_source_sad_lag[i];
}
}
+ if (scene_change_gop_frame_index > 0)
+ max_gop_length = AOMMIN(max_gop_length, scene_change_gop_frame_index);
+ rc->frame_source_sad_lag[0] = rc->frame_source_sad_lag[0] / num_frames;
calculate_gf_length(cpi, max_gop_length, MAX_NUM_GF_INTERVALS);
define_gf_group(cpi, frame_params, 0);
rc->frames_till_gf_update_due = p_rc->baseline_gf_interval;
frame_params->frame_type = gf_group->frame_type[cpi->gf_frame_index];
av1_setup_target_rate(cpi);
+ // Reset the source_sad parameters for the encoding.
+ rc->high_source_sad = 0;
+ rc->frame_source_sad = UINT64_MAX;
+ rc->avg_source_sad = 0;
}
}