Add unit test to check the presence of forward key frame.

ForwardKeyEncodePresenceTest checks the presense of forward
key frame for multiple encode configurations.

Change-Id: I8d24a9190fcb73fbeac8d06ec14f3c92871a97ef
diff --git a/aom/aomdx.h b/aom/aomdx.h
index 1ec0db8..43fa85f 100644
--- a/aom/aomdx.h
+++ b/aom/aomdx.h
@@ -307,6 +307,8 @@
   AV1D_SET_SKIP_FILM_GRAIN,
 
   AOM_DECODER_CTRL_ID_MAX,
+
+  AOMD_GET_FWD_KF_PRESENT,
 };
 
 /*!\cond */
@@ -333,6 +335,9 @@
 AOM_CTRL_USE_TYPE(AOMD_GET_LAST_QUANTIZER, int *)
 #define AOM_CTRL_AOMD_GET_LAST_QUANTIZER
 
+AOM_CTRL_USE_TYPE(AOMD_GET_FWD_KF_PRESENT, int *)
+#define AOM_CTRL_AOMD_GET_FWD_KF_PRESENT
+
 AOM_CTRL_USE_TYPE(AV1D_GET_DISPLAY_SIZE, int *)
 #define AOM_CTRL_AV1D_GET_DISPLAY_SIZE
 
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c
index e621cd2..b3a09d5 100644
--- a/av1/av1_dx_iface.c
+++ b/av1/av1_dx_iface.c
@@ -467,7 +467,7 @@
   frame_worker_data->pbi->output_all_layers = ctx->output_all_layers;
   frame_worker_data->pbi->ext_tile_debug = ctx->ext_tile_debug;
   frame_worker_data->pbi->row_mt = ctx->row_mt;
-
+  frame_worker_data->pbi->is_fwd_kf_present = 0;
   worker->hook = frame_worker_hook;
 
   init_buffer_callbacks(ctx);
@@ -969,6 +969,14 @@
   return AOM_CODEC_OK;
 }
 
+static aom_codec_err_t ctrl_get_fwd_kf_value(aom_codec_alg_priv_t *ctx,
+                                             va_list args) {
+  int *const arg = va_arg(args, int *);
+  if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
+  *arg = ((FrameWorkerData *)ctx->frame_worker->data1)->pbi->is_fwd_kf_present;
+  return AOM_CODEC_OK;
+}
+
 static aom_codec_err_t ctrl_get_frame_corrupted(aom_codec_alg_priv_t *ctx,
                                                 va_list args) {
   int *corrupted = va_arg(args, int *);
@@ -1361,6 +1369,7 @@
   { AV1_GET_REFERENCE, ctrl_get_reference },
   { AV1D_GET_FRAME_HEADER_INFO, ctrl_get_frame_header_info },
   { AV1D_GET_TILE_DATA, ctrl_get_tile_data },
+  { AOMD_GET_FWD_KF_PRESENT, ctrl_get_fwd_kf_value },
 
   CTRL_MAP_END,
 };
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 8563c2d..98a4dc6 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -4545,6 +4545,8 @@
     }
 
     cm->show_frame = aom_rb_read_bit(rb);
+    if (cm->show_frame == 0 && cm->current_frame.frame_type == KEY_FRAME)
+      pbi->is_fwd_kf_present = 1;
     if (seq_params->still_picture &&
         (current_frame->frame_type != KEY_FRAME || !cm->show_frame)) {
       aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
diff --git a/av1/decoder/decoder.h b/av1/decoder/decoder.h
index a5e0f29..b756f62 100644
--- a/av1/decoder/decoder.h
+++ b/av1/decoder/decoder.h
@@ -326,6 +326,7 @@
   int skip_film_grain;
   int is_annexb;
   int valid_for_referencing[REF_FRAMES];
+  int is_fwd_kf_present;
 } AV1Decoder;
 
 // Returns 0 on success. Sets pbi->common.error.error_code to a nonzero error
diff --git a/test/fwd_kf_test.cc b/test/fwd_kf_test.cc
index 50c2f36..d26108d 100644
--- a/test/fwd_kf_test.cc
+++ b/test/fwd_kf_test.cc
@@ -113,4 +113,84 @@
 AV1_INSTANTIATE_TEST_CASE(ForwardKeyTest,
                           ::testing::Values(::libaom_test::kTwoPassGood),
                           ::testing::ValuesIn(kTestParams));
+
+typedef struct {
+  const unsigned int min_kf_dist;
+  const unsigned int max_kf_dist;
+} kfIntervalParam;
+
+const kfIntervalParam kfTestParams[] = {
+  { 0, 10 }, { 10, 10 }, { 0, 30 }, { 30, 30 }
+};
+
+std::ostream &operator<<(std::ostream &os, const kfIntervalParam &test_arg) {
+  return os << "kfIntervalParam { min_kf_dist:" << test_arg.min_kf_dist
+            << " max_kf_dist:" << test_arg.max_kf_dist << " }";
+}
+
+// This class is used to test the presence of forward key frame.
+class ForwardKeyPresenceTestLarge
+    : public ::libaom_test::CodecTestWith3Params<libaom_test::TestMode,
+                                                 kfIntervalParam, aom_rc_mode>,
+      public ::libaom_test::EncoderTest {
+ protected:
+  ForwardKeyPresenceTestLarge()
+      : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
+        kf_dist_param_(GET_PARAM(2)), end_usage_check_(GET_PARAM(3)) {}
+  virtual ~ForwardKeyPresenceTestLarge() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(encoding_mode_);
+    const aom_rational timebase = { 1, 30 };
+    cfg_.g_timebase = timebase;
+    cfg_.rc_end_usage = end_usage_check_;
+    cfg_.g_threads = 1;
+    cfg_.kf_min_dist = kf_dist_param_.min_kf_dist;
+    cfg_.kf_max_dist = kf_dist_param_.max_kf_dist;
+    cfg_.fwd_kf_enabled = 1;
+    cfg_.g_lag_in_frames = 19;
+  }
+
+  virtual bool DoDecode() const { return 1; }
+
+  virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video,
+                                  ::libaom_test::Encoder *encoder) {
+    if (video->frame() == 0) {
+      encoder->Control(AOME_SET_CPUUSED, 5);
+      encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
+    }
+  }
+
+  virtual bool HandleDecodeResult(const aom_codec_err_t res_dec,
+                                  libaom_test::Decoder *decoder) {
+    EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
+    if (is_fwd_kf_present_ != 1 && AOM_CODEC_OK == res_dec) {
+      aom_codec_ctx_t *ctx_dec = decoder->GetDecoder();
+      AOM_CODEC_CONTROL_TYPECHECKED(ctx_dec, AOMD_GET_FWD_KF_PRESENT,
+                                    &is_fwd_kf_present_);
+    }
+    return AOM_CODEC_OK == res_dec;
+  }
+
+  ::libaom_test::TestMode encoding_mode_;
+  const kfIntervalParam kf_dist_param_;
+  int is_fwd_kf_present_;
+  aom_rc_mode end_usage_check_;
+};
+
+TEST_P(ForwardKeyPresenceTestLarge, ForwardKeyEncodePresenceTest) {
+  is_fwd_kf_present_ = 0;
+  libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                     cfg_.g_timebase.den, cfg_.g_timebase.num,
+                                     0, 150);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  ASSERT_EQ(is_fwd_kf_present_, 1);
+}
+
+AV1_INSTANTIATE_TEST_CASE(ForwardKeyPresenceTestLarge,
+                          ::testing::Values(::libaom_test::kOnePassGood,
+                                            ::libaom_test::kTwoPassGood),
+                          ::testing::ValuesIn(kfTestParams),
+                          ::testing::Values(AOM_Q, AOM_VBR, AOM_CBR, AOM_CQ));
 }  // namespace
diff --git a/test/test.cmake b/test/test.cmake
index 5988bda..6c7d281 100644
--- a/test/test.cmake
+++ b/test/test.cmake
@@ -67,7 +67,6 @@
             "${AOM_ROOT}/test/encode_test_driver.cc"
             "${AOM_ROOT}/test/encode_test_driver.h"
             "${AOM_ROOT}/test/end_to_end_test.cc"
-            "${AOM_ROOT}/test/fwd_kf_test.cc"
             "${AOM_ROOT}/test/gf_pyr_height_test.cc"
             "${AOM_ROOT}/test/rt_end_to_end_test.cc"
             "${AOM_ROOT}/test/error_resilience_test.cc"
@@ -127,6 +126,7 @@
                 "${AOM_ROOT}/test/ec_test.cc"
                 "${AOM_ROOT}/test/ethread_test.cc"
                 "${AOM_ROOT}/test/film_grain_table_test.cc"
+                "${AOM_ROOT}/test/fwd_kf_test.cc"
                 "${AOM_ROOT}/test/sb_multipass_test.cc"
                 "${AOM_ROOT}/test/segment_binarization_sync.cc"
                 "${AOM_ROOT}/test/superframe_test.cc"