Fix key frames forced by application.

(Cherry picked from b436ce7d60aa8114a59fcabf3e45a69194ecca98)

Change-Id: If1922e77550d1730af7cc8dc55f002ff2a794890
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index 1631bab..36eaa55 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -419,23 +419,23 @@
 }
 
 // Determine whether there is a forced keyframe pending in the lookahead buffer
-static int is_forced_keyframe_pending(struct lookahead_ctx *lookahead,
-                                      const int up_to_index,
-                                      const COMPRESSOR_STAGE compressor_stage) {
+int is_forced_keyframe_pending(struct lookahead_ctx *lookahead,
+                               const int up_to_index,
+                               const COMPRESSOR_STAGE compressor_stage) {
   for (int i = 0; i <= up_to_index; i++) {
     const struct lookahead_entry *e =
         av1_lookahead_peek(lookahead, i, compressor_stage);
     if (e == NULL) {
       // We have reached the end of the lookahead buffer and not early-returned
       // so there isn't a forced key-frame pending.
-      return 0;
+      return -1;
     } else if (e->flags == AOM_EFLAG_FORCE_KF) {
-      return 1;
+      return (i + 1);
     } else {
       continue;
     }
   }
-  return 0;  // Never reached
+  return -1;  // Never reached
 }
 
 // Check if we should encode an ARF or internal ARF.  If not, try a LAST
@@ -452,8 +452,11 @@
 
   // Should we encode an alt-ref frame.
   int arf_src_index = get_arf_src_index(&cpi->gf_group, cpi->oxcf.pass);
-  if (arf_src_index && is_forced_keyframe_pending(cpi->lookahead, arf_src_index,
-                                                  cpi->compressor_stage)) {
+  // TODO(Aasaipriya): Forced key frames need to be fixed when rc_mode != AOM_Q
+  if (arf_src_index &&
+      (is_forced_keyframe_pending(cpi->lookahead, arf_src_index,
+                                  cpi->compressor_stage) != -1) &&
+      cpi->oxcf.rc_mode != AOM_Q) {
     arf_src_index = 0;
     *flush = 1;
   }
diff --git a/av1/encoder/encode_strategy.h b/av1/encoder/encode_strategy.h
index 552b7e4..b05224b 100644
--- a/av1/encoder/encode_strategy.h
+++ b/av1/encoder/encode_strategy.h
@@ -54,6 +54,9 @@
 
 void av1_get_ref_frames(AV1_COMP *const cpi, RefBufferStack *ref_buffer_stack);
 
+int is_forced_keyframe_pending(struct lookahead_ctx *lookahead,
+                               const int up_to_index,
+                               const COMPRESSOR_STAGE compressor_stage);
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 99be5aa..149de63 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -28,6 +28,7 @@
 #include "av1/encoder/ratectrl.h"
 #include "av1/encoder/tpl_model.h"
 #include "av1/encoder/use_flat_gop_model_params.h"
+#include "av1/encoder/encode_strategy.h"
 
 #define DEFAULT_KF_BOOST 2300
 #define DEFAULT_GF_BOOST 2000
@@ -1607,7 +1608,8 @@
   // 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)) {
+       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
@@ -1870,6 +1872,14 @@
 #define MIN_KF_BOOST 600          // Minimum boost for non-static KF interval
 #define MIN_STATIC_KF_BOOST 5400  // Minimum boost for static KF interval
 
+static int detect_app_forced_key(AV1_COMP *cpi) {
+  if (cpi->oxcf.fwd_kf_enabled) cpi->rc.next_is_fwd_key = 1;
+  int num_frames_to_app_forced_key = is_forced_keyframe_pending(
+      cpi->lookahead, cpi->lookahead->max_sz, cpi->compressor_stage);
+  if (num_frames_to_app_forced_key != -1) cpi->rc.next_is_fwd_key = 0;
+  return num_frames_to_app_forced_key;
+}
+
 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;
@@ -1898,10 +1908,15 @@
 
   rc->frames_to_key = 1;
 
+  int num_frames_to_app_forced_key = detect_app_forced_key(cpi);
+
   if (has_no_stats_stage(cpi)) {
     rc->this_key_frame_forced =
         current_frame->frame_number != 0 && rc->frames_to_key == 0;
-    rc->frames_to_key = cpi->oxcf.key_freq;
+    if (num_frames_to_app_forced_key != -1)
+      rc->frames_to_key = num_frames_to_app_forced_key;
+    else
+      rc->frames_to_key = AOMMAX(1, cpi->oxcf.key_freq);
     rc->kf_boost = DEFAULT_KF_BOOST;
     rc->source_alt_ref_active = 0;
     gf_group->update_type[0] = KF_UPDATE;
@@ -1918,6 +1933,7 @@
   double kf_group_err = 0.0;
   double recent_loop_decay[FRAMES_TO_CHECK_DECAY];
   double sr_accumulator = 0.0;
+  int num_frames_to_check = cpi->oxcf.key_freq;
 
   rc->num_stats_used_for_kf_boost = 1;
   // Is this a forced key frame by interval.
@@ -1932,10 +1948,12 @@
   // Initialize the decay rates for the recent frames to check
   for (j = 0; j < FRAMES_TO_CHECK_DECAY; ++j) recent_loop_decay[j] = 1.0;
 
+  if (num_frames_to_app_forced_key != -1)
+    num_frames_to_check = num_frames_to_app_forced_key;
   // Find the next keyframe.
   i = 0;
   while (twopass->stats_in < twopass->stats_buf_ctx->stats_in_end &&
-         rc->frames_to_key < cpi->oxcf.key_freq) {
+         rc->frames_to_key < num_frames_to_check) {
     // Accumulate total number of stats available till next key frame
     rc->num_stats_used_for_kf_boost++;
 
@@ -1991,8 +2009,12 @@
    * When lap_enabled forcing frames_to_key as key_freq,
    * since all frame stats are not available.
    */
-  if (cpi->lap_enabled) rc->frames_to_key = cpi->oxcf.key_freq;
-
+  if (cpi->lap_enabled) {
+    if (num_frames_to_app_forced_key != -1)
+      rc->frames_to_key = num_frames_to_app_forced_key;
+    else
+      rc->frames_to_key = AOMMAX(1, cpi->oxcf.key_freq);
+  }
   // If there is a max kf interval set by the user we must obey it.
   // We already breakout of the loop above at 2x max.
   // This code centers the extra kf if the actual natural interval
@@ -2339,6 +2361,10 @@
   if (rc->frames_till_gf_update_due == 0) {
     assert(cpi->common.current_frame.frame_number == 0 ||
            gf_group->index == gf_group->size);
+    int num_frames_to_app_forced_key = detect_app_forced_key(cpi);
+    if (num_frames_to_app_forced_key != -1)
+      rc->frames_to_key = num_frames_to_app_forced_key;
+
     int max_gop_length = (cpi->oxcf.lag_in_frames >= 32) ? MAX_GF_INTERVAL : 16;
     if (rc->intervals_till_gf_calculate_due == 0) {
       calculate_gf_length(cpi, max_gop_length, MAX_NUM_GF_INTERVALS);
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 05f11fb..fca49ca 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -179,6 +179,7 @@
   int num_stats_used_for_gfu_boost;
   // Total number of stats required by gfu_boost calculation.
   int num_stats_required_for_gfu_boost;
+  int next_is_fwd_key;
 } RATE_CONTROL;
 
 struct AV1_COMP;