Correct tpl boost combination with gfu_boost in LAP As all stats may not be available for a lower lag_in_frames, using frames_to_key in process_tpl_stats_frame would be incorrect in case of LAP. Using number of stats actually used, for projection and combination of gfu_boost in LAP. STATS_CHANGED Change-Id: I3825a6329f1b6671f90c59597895d7d0667dbaa1 (cherry picked from commit 28742ee3c7331274da2827fa65d3852c6853650e)
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 04e2bb3..42bf1e7 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -4012,6 +4012,26 @@ } #if !CONFIG_REALTIME_ONLY +#define MAX_GFUBOOST_FACTOR 10.0 +#define MIN_GFUBOOST_FACTOR 4.0 +static double get_gfu_boost_projection_factor(double min_factor, + double max_factor, + int frame_count) { + double factor = sqrt((double)frame_count); + factor = AOMMIN(factor, max_factor); + factor = AOMMAX(factor, min_factor); + factor = (200.0 + 10.0 * factor); + return factor; +} + +static int get_gfu_boost_from_r0_lap(double min_factor, double max_factor, + double r0, int frames_to_key) { + double factor = + get_gfu_boost_projection_factor(min_factor, max_factor, frames_to_key); + const int boost = (int)rint(factor / r0); + return boost; +} + static double get_kf_boost_projection_factor(int frame_count) { double factor = sqrt((double)frame_count); factor = AOMMIN(factor, 10.0); @@ -4026,6 +4046,31 @@ return boost; } +static int get_projected_prior_gfu_boost(AV1_COMP *cpi) { + int num_stats_used_for_gfu_boost = cpi->rc.num_stats_used_for_gfu_boost; + int frames_to_project = cpi->rc.num_stats_required_for_gfu_boost; + + /* + * If frames_to_project is equal to num_stats_used_for_gfu_boost, + * it means that gfu_boost was calculated over frames_to_project to + * begin with(ie; all stats required were available), hence return + * the original boost. + */ + if (num_stats_used_for_gfu_boost >= frames_to_project) + return cpi->rc.gfu_boost; + + double min_boost_factor = sqrt(cpi->rc.baseline_gf_interval); + // Get the current tpl factor (number of frames = frames_to_project). + double tpl_factor = get_gfu_boost_projection_factor( + min_boost_factor, MAX_GFUBOOST_FACTOR, frames_to_project); + // Get the tpl factor when number of frames = num_stats_used_for_prior_boost. + double tpl_factor_num_stats = get_gfu_boost_projection_factor( + min_boost_factor, MAX_GFUBOOST_FACTOR, num_stats_used_for_gfu_boost); + int projected_gfu_boost = + (int)rint((tpl_factor * cpi->rc.gfu_boost) / tpl_factor_num_stats); + return projected_gfu_boost; +} + static int get_projected_prior_boost(AV1_COMP *cpi) { /* * If num_stats_used_for_kf_boost >= frames_to_key, then @@ -4046,13 +4091,18 @@ } #endif -int combine_prior_with_tpl_boost(int prior_boost, int tpl_boost, +#define MIN_BOOST_COMBINE_FACTOR 4.0 +#define MAX_BOOST_COMBINE_FACTOR 12.0 +int combine_prior_with_tpl_boost(double min_factor, double max_factor, + int prior_boost, int tpl_boost, int frames_to_key) { double factor = sqrt((double)frames_to_key); - factor = AOMMIN(factor, 12.0); - factor = AOMMAX(factor, 4.0); - factor -= 4.0; - int boost = (int)((factor * prior_boost + (8.0 - factor) * tpl_boost) / 8.0); + double range = max_factor - min_factor; + factor = AOMMIN(factor, max_factor); + factor = AOMMAX(factor, min_factor); + factor -= min_factor; + int boost = + (int)((factor * prior_boost + (range - factor) * tpl_boost) / range); return boost; } @@ -4102,9 +4152,23 @@ cpi->rd.r0 = (double)intra_cost_base / mc_dep_cost_base; if (is_frame_arf_and_tpl_eligible(gf_group)) { cpi->rd.arf_r0 = cpi->rd.r0; - const int gfu_boost = (int)(200.0 / cpi->rd.r0); - cpi->rc.gfu_boost = combine_prior_with_tpl_boost( - cpi->rc.gfu_boost, gfu_boost, cpi->rc.frames_to_key); + if (cpi->lap_enabled) { + double min_boost_factor = sqrt(cpi->rc.baseline_gf_interval); + const int gfu_boost = get_gfu_boost_from_r0_lap( + min_boost_factor, MAX_GFUBOOST_FACTOR, cpi->rd.arf_r0, + cpi->rc.num_stats_required_for_gfu_boost); + const int prior_boost = get_projected_prior_gfu_boost(cpi); + // printf("old boost %d new boost %d\n", prior_boost, + // gfu_boost); + cpi->rc.gfu_boost = combine_prior_with_tpl_boost( + min_boost_factor, MAX_BOOST_COMBINE_FACTOR, prior_boost, + gfu_boost, cpi->rc.num_stats_used_for_gfu_boost); + } else { + const int gfu_boost = (int)(200.0 / cpi->rd.r0); + cpi->rc.gfu_boost = combine_prior_with_tpl_boost( + MIN_BOOST_COMBINE_FACTOR, MAX_BOOST_COMBINE_FACTOR, + cpi->rc.gfu_boost, gfu_boost, cpi->rc.frames_to_key); + } } else if (frame_is_intra_only(cm)) { // TODO(debargha): Turn off q adjustment for kf temporarily to // reduce impact on speed of encoding. Need to investigate how @@ -4115,10 +4179,12 @@ if (cpi->lap_enabled) { const int projected_prior_boost = get_projected_prior_boost(cpi); cpi->rc.kf_boost = combine_prior_with_tpl_boost( + MIN_BOOST_COMBINE_FACTOR, MAX_BOOST_COMBINE_FACTOR, projected_prior_boost, kf_boost, cpi->rc.num_stats_used_for_kf_boost); } else { cpi->rc.kf_boost = combine_prior_with_tpl_boost( + MIN_BOOST_COMBINE_FACTOR, MAX_BOOST_COMBINE_FACTOR, cpi->rc.kf_boost, kf_boost, cpi->rc.frames_to_key); } }
diff --git a/av1/encoder/gop_structure.c b/av1/encoder/gop_structure.c index 6889c83..210e894 100644 --- a/av1/encoder/gop_structure.c +++ b/av1/encoder/gop_structure.c
@@ -47,8 +47,8 @@ gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx; gf_group->frame_disp_idx[*frame_ind] = start; gf_group->layer_depth[*frame_ind] = MAX_ARF_LAYERS; - gf_group->arf_boost[*frame_ind] = - av1_calc_arf_boost(twopass, rc, frame_info, start, end - start, 0); + gf_group->arf_boost[*frame_ind] = av1_calc_arf_boost( + twopass, rc, frame_info, start, end - start, 0, NULL); gf_group->max_layer_depth = AOMMAX(gf_group->max_layer_depth, layer_depth); ++(*frame_ind); @@ -64,8 +64,8 @@ gf_group->layer_depth[*frame_ind] = layer_depth; // Get the boost factor for intermediate ARF frames. - gf_group->arf_boost[*frame_ind] = - av1_calc_arf_boost(twopass, rc, frame_info, m, end - m, m - start); + gf_group->arf_boost[*frame_ind] = av1_calc_arf_boost( + twopass, rc, frame_info, m, end - m, m - start, NULL); ++(*frame_ind); // Frames displayed before this internal ARF.
diff --git a/av1/encoder/gop_structure.h b/av1/encoder/gop_structure.h index 4637930..e76ba21 100644 --- a/av1/encoder/gop_structure.h +++ b/av1/encoder/gop_structure.h
@@ -34,7 +34,7 @@ int av1_calc_arf_boost(const TWO_PASS *twopass, const RATE_CONTROL *rc, FRAME_INFO *frame_info, int offset, int f_frames, - int b_frames); + int b_frames, int *num_fpstats_used); #ifdef __cplusplus } // extern "C" #endif
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c index 67d19e8..195f578 100644 --- a/av1/encoder/pass2_strategy.c +++ b/av1/encoder/pass2_strategy.c
@@ -461,7 +461,7 @@ #define MIN_DECAY_FACTOR 0.01 int av1_calc_arf_boost(const TWO_PASS *twopass, const RATE_CONTROL *rc, FRAME_INFO *frame_info, int offset, int f_frames, - int b_frames) { + int b_frames, int *num_fpstats_used) { int i; double boost_score = (double)NORMAL_BOOST; double mv_ratio_accumulator = 0.0; @@ -471,6 +471,7 @@ double abs_mv_in_out_accumulator = 0.0; int arf_boost; int flash_detected = 0; + if (num_fpstats_used) *num_fpstats_used = 0; // Search forward from the proposed arf/next gf position. for (i = 0; i < f_frames; ++i) { @@ -498,6 +499,7 @@ boost_score += decay_accumulator * calc_frame_boost(rc, frame_info, this_frame, this_frame_mv_in_out, GF_MAX_BOOST); + if (num_fpstats_used) (*num_fpstats_used)++; } arf_boost = (int)boost_score; @@ -536,6 +538,7 @@ boost_score += decay_accumulator * calc_frame_boost(rc, frame_info, this_frame, this_frame_mv_in_out, GF_MAX_BOOST); + if (num_fpstats_used) (*num_fpstats_used)++; } arf_boost += (int)boost_score; @@ -1582,15 +1585,19 @@ : AOMMAX(0, rc->frames_to_key - i); // Calculate the boost for alt ref. - rc->gfu_boost = av1_calc_arf_boost(twopass, rc, frame_info, alt_offset, - forward_frames, (i - 1)); + rc->gfu_boost = + av1_calc_arf_boost(twopass, rc, frame_info, alt_offset, forward_frames, + (i - 1), &rc->num_stats_used_for_gfu_boost); + rc->num_stats_required_for_gfu_boost = (forward_frames + i - 1); rc->source_alt_ref_pending = 1; gf_group->max_layer_depth_allowed = cpi->oxcf.gf_max_pyr_height; } else { reset_fpf_position(twopass, start_pos); - rc->gfu_boost = AOMMIN( - MAX_GF_BOOST, - av1_calc_arf_boost(twopass, rc, frame_info, alt_offset, (i - 1), 0)); + rc->gfu_boost = + AOMMIN(MAX_GF_BOOST, + av1_calc_arf_boost(twopass, rc, frame_info, alt_offset, (i - 1), + 0, &rc->num_stats_used_for_gfu_boost)); + rc->num_stats_required_for_gfu_boost = (i - 1); rc->source_alt_ref_pending = 0; gf_group->max_layer_depth_allowed = 0; }
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h index 038eac8..05f11fb 100644 --- a/av1/encoder/ratectrl.h +++ b/av1/encoder/ratectrl.h
@@ -175,6 +175,10 @@ // Total number of stats used only for kf_boost calculation. int num_stats_used_for_kf_boost; + // Total number of stats used only for gfu_boost calculation. + int num_stats_used_for_gfu_boost; + // Total number of stats required by gfu_boost calculation. + int num_stats_required_for_gfu_boost; } RATE_CONTROL; struct AV1_COMP;