rtc-svc: Fixes for periodic key frames for SVC

Key frame should only be on base spatial layer
(which is 0 for 1 layer/non-SVC) and the period
check should be based on superframe counter.

Add unittest for SVC with auto key frame mode.

And disabled two features (tpl and deltaq) that
should not be used for RTC.

Change-Id: Iad81340033e777abb4b401c7b8572d4a91b2a2c9
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index e5454ed..45a090a 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -1817,7 +1817,8 @@
   // Handle fixed keyframe intervals
   if (ctx->cfg.kf_mode == AOM_KF_AUTO &&
       ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
-    if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
+    if (cpi->common.spatial_layer_id == 0 &&
+        ++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
       flags |= AOM_EFLAG_FORCE_KF;
       ctx->fixed_kf_cntr = 1;
     }
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index ef739b1..ed9ecec 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -1360,11 +1360,14 @@
   // Single thread case: use counts in common.
   cpi->td.counts = &cpi->counts;
 
+  // Set init SVC parameters.
   cpi->use_svc = 0;
   cpi->svc.external_ref_frame_config = 0;
   cpi->svc.non_reference_frame = 0;
   cm->number_spatial_layers = 1;
   cm->number_temporal_layers = 1;
+  cm->spatial_layer_id = 0;
+  cm->temporal_layer_id = 0;
 
   // change includes all joint functionality
   av1_change_config(cpi, oxcf);
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index d87e5ce..fda08a3 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -1874,7 +1874,10 @@
     av1_update_temporal_layer_framerate(cpi);
     av1_restore_layer_context(cpi);
   }
-  if (rc->frames_to_key == 0 || (frame_flags & FRAMEFLAGS_KEY)) {
+  if ((!cpi->use_svc && rc->frames_to_key == 0) ||
+      (cpi->use_svc && cpi->svc.spatial_layer_id == 0 &&
+       cpi->svc.current_superframe % cpi->oxcf.key_freq == 0) ||
+      (frame_flags & FRAMEFLAGS_KEY)) {
     frame_params->frame_type = KEY_FRAME;
     rc->this_key_frame_forced =
         cm->current_frame.frame_number != 0 && rc->frames_to_key == 0;
diff --git a/test/svc_datarate_test.cc b/test/svc_datarate_test.cc
index 9017f41..e1c95c8 100644
--- a/test/svc_datarate_test.cc
+++ b/test/svc_datarate_test.cc
@@ -65,6 +65,8 @@
                      &svc_params_);
       encoder->Control(AV1E_SET_SVC_PARAMS, &svc_params_);
       encoder->Control(AV1E_SET_ENABLE_ORDER_HINT, 0);
+      encoder->Control(AV1E_SET_ENABLE_TPL_MODEL, 0);
+      encoder->Control(AV1E_SET_DELTAQ_MODE, 0);
     }
     if (number_spatial_layers_ == 2) {
       spatial_layer_id = (layer_frame_cnt_ % 2 == 0) ? 0 : 1;
@@ -471,6 +473,51 @@
     }
   }
 
+  virtual void BasicRateTargetingSVC3TL3SLKfTest() {
+    cfg_.rc_buf_initial_sz = 500;
+    cfg_.rc_buf_optimal_sz = 500;
+    cfg_.rc_buf_sz = 1000;
+    cfg_.rc_dropframe_thresh = 0;
+    cfg_.rc_min_quantizer = 0;
+    cfg_.rc_max_quantizer = 63;
+    cfg_.rc_end_usage = AOM_CBR;
+    cfg_.g_lag_in_frames = 0;
+    cfg_.g_usage = AOM_USAGE_REALTIME;
+    cfg_.g_error_resilient = 1;
+    cfg_.kf_mode = AOM_KF_AUTO;
+    cfg_.kf_min_dist = cfg_.kf_max_dist = 100;
+
+    ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352,
+                                         288, 30, 1, 0, 300);
+    const int bitrate_array[2] = { 600, 1200 };
+    cfg_.rc_target_bitrate = bitrate_array[GET_PARAM(4)];
+    ResetModel();
+    number_temporal_layers_ = 3;
+    number_spatial_layers_ = 3;
+    // SL0
+    const int bitrate_sl0 = 1 * cfg_.rc_target_bitrate / 8;
+    target_layer_bitrate_[0] = 50 * bitrate_sl0 / 100;
+    target_layer_bitrate_[1] = 70 * bitrate_sl0 / 100;
+    target_layer_bitrate_[2] = bitrate_sl0;
+    // SL1
+    const int bitrate_sl1 = 3 * cfg_.rc_target_bitrate / 8;
+    target_layer_bitrate_[3] = 50 * bitrate_sl1 / 100;
+    target_layer_bitrate_[4] = 70 * bitrate_sl1 / 100;
+    target_layer_bitrate_[5] = bitrate_sl1;
+    // SL2
+    const int bitrate_sl2 = 4 * cfg_.rc_target_bitrate / 8;
+    target_layer_bitrate_[6] = 50 * bitrate_sl2 / 100;
+    target_layer_bitrate_[7] = 70 * bitrate_sl2 / 100;
+    target_layer_bitrate_[8] = bitrate_sl2;
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    for (int i = 0; i < number_temporal_layers_ * number_spatial_layers_; i++) {
+      ASSERT_GE(effective_datarate_tl[i], target_layer_bitrate_[i] * 0.75)
+          << " The datarate for the file is lower than target by too much!";
+      ASSERT_LE(effective_datarate_tl[i], target_layer_bitrate_[i] * 1.4)
+          << " The datarate for the file is greater than target by too much!";
+    }
+  }
+
   int layer_frame_cnt_;
   int superframe_cnt_;
   int number_temporal_layers_;
@@ -503,6 +550,12 @@
   BasicRateTargetingSVC3TL3SLTest();
 }
 
+// Check basic rate targeting for CBR, for 3 spatial, 3 temporal layers,
+// for auto key frame mode with short key frame period.
+TEST_P(DatarateTestSVC, BasicRateTargetingSVC3TL3SLKf) {
+  BasicRateTargetingSVC3TL3SLKfTest();
+}
+
 AV1_INSTANTIATE_TEST_CASE(DatarateTestSVC,
                           ::testing::Values(::libaom_test::kRealTime),
                           ::testing::Range(7, 9),