Refactor kf and gfu boost calculation in LAP

Moved the projection of kf_boost and gfu_boost
to pass2_strategy.c to ensure consistent max
and min clips of the boost values.

STATS_CHANGED

Change-Id: I6f95f406d8041e08349284a7bc17cee692a5286e
(cherry picked from commit 93f76853492e2f913084d165ec3767b1d03985cf)
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 42bf1e7..c47a6c2 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -4012,11 +4012,8 @@
 }
 
 #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 av1_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);
@@ -4026,13 +4023,13 @@
 
 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);
+  double factor = av1_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 av1_get_kf_boost_projection_factor(int frame_count) {
   double factor = sqrt((double)frame_count);
   factor = AOMMIN(factor, 10.0);
   factor = AOMMAX(factor, 4.0);
@@ -4041,54 +4038,10 @@
 }
 
 static int get_kf_boost_from_r0(double r0, int frames_to_key) {
-  double factor = get_kf_boost_projection_factor(frames_to_key);
+  double factor = av1_get_kf_boost_projection_factor(frames_to_key);
   const int boost = (int)rint(factor / r0);
   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
-   * all stats needed for prior boost calculation are available.
-   * Hence projecting the prior boost is not needed in this cases.
-   */
-  if (cpi->rc.num_stats_used_for_kf_boost >= cpi->rc.frames_to_key)
-    return cpi->rc.kf_boost;
-
-  // Get the current tpl factor (number of frames = frames_to_key).
-  double tpl_factor = get_kf_boost_projection_factor(cpi->rc.frames_to_key);
-  // Get the tpl factor when number of frames = num_stats_used_for_kf_boost.
-  double tpl_factor_num_stats =
-      get_kf_boost_projection_factor(cpi->rc.num_stats_used_for_kf_boost);
-  int projected_kf_boost =
-      (int)rint((tpl_factor * cpi->rc.kf_boost) / tpl_factor_num_stats);
-  return projected_kf_boost;
-}
 #endif
 
 #define MIN_BOOST_COMBINE_FACTOR 4.0
@@ -4157,11 +4110,10 @@
           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,
+          // printf("old boost %d new boost %d\n", cpi->rc.gfu_boost,
           //        gfu_boost);
           cpi->rc.gfu_boost = combine_prior_with_tpl_boost(
-              min_boost_factor, MAX_BOOST_COMBINE_FACTOR, prior_boost,
+              min_boost_factor, MAX_BOOST_COMBINE_FACTOR, cpi->rc.gfu_boost,
               gfu_boost, cpi->rc.num_stats_used_for_gfu_boost);
         } else {
           const int gfu_boost = (int)(200.0 / cpi->rd.r0);
@@ -4177,10 +4129,9 @@
           const int kf_boost =
               get_kf_boost_from_r0(cpi->rd.r0, cpi->rc.frames_to_key);
           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.kf_boost, kf_boost,
                 cpi->rc.num_stats_used_for_kf_boost);
           } else {
             cpi->rc.kf_boost = combine_prior_with_tpl_boost(
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index b36b186..6248e86 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -1636,6 +1636,12 @@
 // field.
 aom_fixed_buf_t *av1_get_global_headers(AV1_COMP *cpi);
 
+#define MAX_GFUBOOST_FACTOR 10.0
+#define MIN_GFUBOOST_FACTOR 4.0
+double av1_get_gfu_boost_projection_factor(double min_factor, double max_factor,
+                                           int frame_count);
+double av1_get_kf_boost_projection_factor(int frame_count);
+
 #define ENABLE_KF_TPL 1
 #define MAX_PYR_LEVEL_FROMTOP_DELTAQ 0
 
diff --git a/av1/encoder/gop_structure.c b/av1/encoder/gop_structure.c
index 210e894..b8ade1d 100644
--- a/av1/encoder/gop_structure.c
+++ b/av1/encoder/gop_structure.c
@@ -48,7 +48,7 @@
       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, NULL);
+          twopass, rc, frame_info, start, end - start, 0, NULL, NULL);
       gf_group->max_layer_depth =
           AOMMAX(gf_group->max_layer_depth, layer_depth);
       ++(*frame_ind);
@@ -65,7 +65,7 @@
 
     // 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, NULL);
+        twopass, rc, frame_info, m, end - m, m - start, NULL, NULL);
     ++(*frame_ind);
 
     // Frames displayed before this internal ARF.
diff --git a/av1/encoder/gop_structure.h b/av1/encoder/gop_structure.h
index e76ba21..5cfe30d 100644
--- a/av1/encoder/gop_structure.h
+++ b/av1/encoder/gop_structure.h
@@ -34,7 +34,8 @@
 
 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 *num_fpstats_used);
+                       int b_frames, int *num_fpstats_used,
+                       int *num_fpstats_required);
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 7bcd125..847f4b9 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -458,11 +458,35 @@
   return AOMMIN(frame_boost, max_boost * boost_q_correction);
 }
 
+static int get_projected_gfu_boost(const RATE_CONTROL *rc, int gfu_boost,
+                                   int frames_to_project,
+                                   int num_stats_used_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 gfu_boost;
+
+  double min_boost_factor = sqrt(rc->baseline_gf_interval);
+  // Get the current tpl factor (number of frames = frames_to_project).
+  double tpl_factor = av1_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 = av1_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 * gfu_boost) / tpl_factor_num_stats);
+  return projected_gfu_boost;
+}
+
 #define GF_MAX_BOOST 90.0
 #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 *num_fpstats_used) {
+                       int b_frames, int *num_fpstats_used,
+                       int *num_fpstats_required) {
   int i;
   double boost_score = (double)NORMAL_BOOST;
   double mv_ratio_accumulator = 0.0;
@@ -543,6 +567,14 @@
   }
   arf_boost += (int)boost_score;
 
+  if (num_fpstats_required) {
+    *num_fpstats_required = f_frames + b_frames;
+    if (num_fpstats_used) {
+      arf_boost = get_projected_gfu_boost(rc, arf_boost, *num_fpstats_required,
+                                          *num_fpstats_used);
+    }
+  }
+
   if (arf_boost < ((b_frames + f_frames) * 50))
     arf_boost = ((b_frames + f_frames) * 50);
 
@@ -1298,6 +1330,43 @@
   }
 }
 
+static INLINE void set_baseline_gf_interval(AV1_COMP *cpi, int arf_position,
+                                            int active_max_gf_interval,
+                                            int use_alt_ref,
+                                            int is_final_pass) {
+  RATE_CONTROL *const rc = &cpi->rc;
+  TWO_PASS *const twopass = &cpi->twopass;
+  // Set the interval until the next gf.
+  // If forward keyframes are enabled, ensure the final gf group obeys the
+  // MIN_FWD_KF_INTERVAL.
+  if (cpi->oxcf.fwd_kf_enabled && use_alt_ref &&
+      ((twopass->stats_in - arf_position + rc->frames_to_key) <
+       twopass->stats_buf_ctx->stats_in_end) &&
+      cpi->rc.next_is_fwd_key) {
+    if (arf_position == rc->frames_to_key) {
+      rc->baseline_gf_interval = arf_position;
+      // if the last gf group will be smaller than MIN_FWD_KF_INTERVAL
+    } else if ((rc->frames_to_key - arf_position <
+                AOMMAX(MIN_FWD_KF_INTERVAL, rc->min_gf_interval)) &&
+               (rc->frames_to_key != arf_position)) {
+      // if possible, merge the last two gf groups
+      if (rc->frames_to_key <= active_max_gf_interval) {
+        rc->baseline_gf_interval = rc->frames_to_key;
+        if (is_final_pass) rc->intervals_till_gf_calculate_due = 0;
+        // if merging the last two gf groups creates a group that is too long,
+        // split them and force the last gf group to be the MIN_FWD_KF_INTERVAL
+      } else {
+        rc->baseline_gf_interval = rc->frames_to_key - MIN_FWD_KF_INTERVAL;
+        if (is_final_pass) rc->intervals_till_gf_calculate_due = 0;
+      }
+    } else {
+      rc->baseline_gf_interval = arf_position - rc->source_alt_ref_pending;
+    }
+  } else {
+    rc->baseline_gf_interval = arf_position - rc->source_alt_ref_pending;
+  }
+}
+
 // Analyse and define a gf/arf group.
 #define MAX_GF_BOOST 5400
 static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame,
@@ -1598,57 +1667,35 @@
 
   // Should we use the alternate reference frame.
   if (use_alt_ref) {
+    rc->source_alt_ref_pending = 1;
+    gf_group->max_layer_depth_allowed = cpi->oxcf.gf_max_pyr_height;
+    set_baseline_gf_interval(cpi, i, active_max_gf_interval, use_alt_ref,
+                             is_final_pass);
+
     const int forward_frames = (rc->frames_to_key - i >= i - 1)
                                    ? i - 1
                                    : 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->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;
+    rc->gfu_boost = av1_calc_arf_boost(
+        twopass, rc, frame_info, alt_offset, forward_frames, (i - 1),
+        cpi->lap_enabled ? &rc->num_stats_used_for_gfu_boost : NULL,
+        cpi->lap_enabled ? &rc->num_stats_required_for_gfu_boost : NULL);
   } 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->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;
+    set_baseline_gf_interval(cpi, i, active_max_gf_interval, use_alt_ref,
+                             is_final_pass);
+
+    rc->gfu_boost = AOMMIN(
+        MAX_GF_BOOST,
+        av1_calc_arf_boost(
+            twopass, rc, frame_info, alt_offset, (i - 1), 0,
+            cpi->lap_enabled ? &rc->num_stats_used_for_gfu_boost : NULL,
+            cpi->lap_enabled ? &rc->num_stats_required_for_gfu_boost : NULL));
   }
 
-  // Set the interval until the next gf.
-  // If forward keyframes are enabled, ensure the final gf group obeys the
-  // MIN_FWD_KF_INTERVAL.
-  if (cpi->oxcf.fwd_kf_enabled && use_alt_ref &&
-      ((twopass->stats_in - i + rc->frames_to_key) <
-       twopass->stats_buf_ctx->stats_in_end) &&
-      cpi->rc.next_is_fwd_key) {
-    if (i == rc->frames_to_key) {
-      rc->baseline_gf_interval = i;
-      // if the last gf group will be smaller than MIN_FWD_KF_INTERVAL
-    } else if ((rc->frames_to_key - i <
-                AOMMAX(MIN_FWD_KF_INTERVAL, rc->min_gf_interval)) &&
-               (rc->frames_to_key != i)) {
-      // if possible, merge the last two gf groups
-      if (rc->frames_to_key <= active_max_gf_interval) {
-        rc->baseline_gf_interval = rc->frames_to_key;
-        if (is_final_pass) rc->intervals_till_gf_calculate_due = 0;
-        // if merging the last two gf groups creates a group that is too long,
-        // split them and force the last gf group to be the MIN_FWD_KF_INTERVAL
-      } else {
-        rc->baseline_gf_interval = rc->frames_to_key - MIN_FWD_KF_INTERVAL;
-        if (is_final_pass) rc->intervals_till_gf_calculate_due = 0;
-      }
-    } else {
-      rc->baseline_gf_interval = i - rc->source_alt_ref_pending;
-    }
-  } else {
-    rc->baseline_gf_interval = i - rc->source_alt_ref_pending;
-  }
   // rc->gf_intervals assumes the usage of alt_ref, therefore adding one overlay
   // frame to the next gf. If no alt_ref is used, should substract 1 frame from
   // the next gf group.
@@ -1897,6 +1944,25 @@
   return num_frames_to_app_forced_key;
 }
 
+static int get_projected_kf_boost(AV1_COMP *cpi) {
+  /*
+   * If num_stats_used_for_kf_boost >= frames_to_key, then
+   * all stats needed for prior boost calculation are available.
+   * Hence projecting the prior boost is not needed in this cases.
+   */
+  if (cpi->rc.num_stats_used_for_kf_boost >= cpi->rc.frames_to_key)
+    return cpi->rc.kf_boost;
+
+  // Get the current tpl factor (number of frames = frames_to_key).
+  double tpl_factor = av1_get_kf_boost_projection_factor(cpi->rc.frames_to_key);
+  // Get the tpl factor when number of frames = num_stats_used_for_kf_boost.
+  double tpl_factor_num_stats =
+      av1_get_kf_boost_projection_factor(cpi->rc.num_stats_used_for_kf_boost);
+  int projected_kf_boost =
+      (int)rint((tpl_factor * cpi->rc.kf_boost) / tpl_factor_num_stats);
+  return projected_kf_boost;
+}
+
 static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) {
   RATE_CONTROL *const rc = &cpi->rc;
   TWO_PASS *const twopass = &cpi->twopass;
@@ -2144,6 +2210,10 @@
 
   rc->kf_boost = (int)boost_score;
 
+  if (cpi->lap_enabled) {
+    rc->kf_boost = get_projected_kf_boost(cpi);
+  }
+
   // Special case for static / slide show content but don't apply
   // if the kf group is very short.
   if ((zero_motion_accumulator > STATIC_KF_GROUP_FLOAT_THRESH) &&