Temporal filter 1 more alt ref frame

Temporal filter the second alt ref frame if its distance >= 7. This
second alt ref frame is always a show existing frame. Finally, use
conditions to decide if or not to accept this filtered alt ref.

This change is controlled by a speed feature.
At speed 1, borg test result:
       avg_psnr:  ovr_psnr:  ssim:  vmaf:
lowres: -0.112    -0.189    -0.064  -0.477
midres: -0.052    -0.139    -0.068  -0.196

STATS_CHANGED

Change-Id: I9608a0586073d44b60bc4fe3e8eeec97f9fa7df2
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 33f073a..fa90d88 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -458,6 +458,7 @@
     sf->lpf_sf.prune_sgr_based_on_wiener =
         cm->allow_screen_content_tools ? 0 : 2;
     sf->lpf_sf.reduce_wiener_window_size = is_boosted_arf2_bwd_type ? 0 : 1;
+    sf->hl_sf.second_alt_ref_filtering = 0;
   }
 
   if (speed >= 4) {
@@ -834,11 +835,11 @@
   hl_sf->frame_parameter_update = 1;
   hl_sf->recode_loop = ALLOW_RECODE;
   hl_sf->disable_overlay_frames = 0;
-  // TODO(yunqing): turn it on for speed 0 if there is gain.
   hl_sf->adaptive_overlay_encoding = 1;
   // Recode loop tolerance %.
   hl_sf->recode_tolerance = 25;
   hl_sf->high_precision_mv_usage = CURRENT_Q;
+  hl_sf->second_alt_ref_filtering = 1;
 }
 
 static AOM_INLINE void init_tpl_sf(TPL_SPEED_FEATURES *tpl_sf) {
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index e9b5ffc..84066ff 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -297,6 +297,9 @@
   // backgrounds very to cheap to encode, and the segmentation we have
   // adds overhead.
   int static_segmentation;
+
+  // Enable/disable second_alt_ref temporal filtering.
+  int second_alt_ref_filtering;
 } HIGH_LEVEL_SPEED_FEATURES;
 
 typedef struct TPL_SPEED_FEATURES {
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index 6ba08d0..5d6b916 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -1006,7 +1006,7 @@
 static FRAME_DIFF temporal_filter_iterate_c(
     AV1_COMP *cpi, YV12_BUFFER_CONFIG **frames, int frame_count,
     int alt_ref_index, int strength, double sigma, int is_key_frame,
-    struct scale_factors *ref_scale_factors) {
+    struct scale_factors *ref_scale_factors, int second_alt_ref) {
   const AV1_COMMON *cm = &cpi->common;
   const int num_planes = av1_num_planes(cm);
   const int mb_cols = get_cols(frames[alt_ref_index]->y_crop_width);
@@ -1117,14 +1117,15 @@
         blk_mvs[3] = kZeroMv;
 
         if (frame == alt_ref_index) {
-          blk_fw[0] = blk_fw[1] = blk_fw[2] = blk_fw[3] = 2;
+          const int weight = second_alt_ref ? 4 : 2;
+          blk_fw[0] = blk_fw[1] = blk_fw[2] = blk_fw[3] = weight;
           use_32x32 = 1;
           // Change ref_mv sign for following frames.
           best_ref_mv1.row *= -1;
           best_ref_mv1.col *= -1;
         } else {
-          int thresh_low = 10000;
-          int thresh_high = 20000;
+          int thresh_low = 10000 >> second_alt_ref;
+          int thresh_high = 20000 >> second_alt_ref;
           int blk_bestsme[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX };
 
           // Find best match in this frame by MC
@@ -1505,9 +1506,13 @@
 // Apply buffer limits and context specific adjustments to arnr filter.
 static void adjust_arnr_filter(AV1_COMP *cpi, int distance, int group_boost,
                                int *arnr_frames, int *arnr_strength,
-                               double *sigma, int *frm_bwd, int *frm_fwd) {
+                               double *sigma, int *frm_bwd, int *frm_fwd,
+                               int second_alt_ref) {
   int frames = cpi->oxcf.arnr_max_frames;
 
+  // Only use the 2 nearest frames in second alt ref's temporal filtering.
+  if (second_alt_ref) frames = AOMMIN(frames, 3);
+
   // Adjust number of frames in filter and strength based on gf boost level.
   if (frames > group_boost / 150) {
     frames = group_boost / 150;
@@ -1548,6 +1553,12 @@
   int rdmult = 0;
   double sigma = 0;
 
+  // Temporal filter 1 more alt ref if its distance >= 7. This frame is always
+  // a show existing frame.
+  const int second_alt_ref =
+      (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE) &&
+      (distance >= 7) && cpi->sf.hl_sf.second_alt_ref_filtering;
+
   // TODO(yunqing): For INTNL_ARF_UPDATE type, the following me initialization
   // is used somewhere unexpectedly. Should be resolved later.
   // Initialize errorperbit, sadperbit16 and sadperbit4.
@@ -1558,7 +1569,8 @@
                     cpi->common.allow_high_precision_mv, &cpi->td.mb);
 
   // Apply context specific adjustments to the arnr filter parameters.
-  if (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE) {
+  if (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE &&
+      !second_alt_ref) {
     // TODO(weitinglin): Currently, we enforce the filtering strength on
     // internal ARFs to be zeros. We should investigate in which case it is more
     // beneficial to use non-zero strength filtering.
@@ -1588,10 +1600,11 @@
   } else {
     adjust_arnr_filter(cpi, distance, rc->gfu_boost, &frames_to_blur, &strength,
                        &sigma, &frames_to_blur_backward,
-                       &frames_to_blur_forward);
+                       &frames_to_blur_forward, second_alt_ref);
     start_frame = distance + frames_to_blur_forward;
+
     cpi->common.showable_frame =
-        (strength == 0 && frames_to_blur == 1) ||
+        (strength == 0 && frames_to_blur == 1) || second_alt_ref ||
         (cpi->oxcf.enable_overlay == 0 || cpi->sf.hl_sf.disable_overlay_frames);
   }
 
@@ -1616,14 +1629,15 @@
         frames[0]->y_crop_width, frames[0]->y_crop_height);
   }
 
-  FRAME_DIFF diff = temporal_filter_iterate_c(cpi, frames, frames_to_blur,
-                                              frames_to_blur_backward, strength,
-                                              sigma, distance < 0, &sf);
+  FRAME_DIFF diff = temporal_filter_iterate_c(
+      cpi, frames, frames_to_blur, frames_to_blur_backward, strength, sigma,
+      distance < 0, &sf, second_alt_ref);
 
   if (distance < 0) return 1;
 
-  if (show_existing_alt_ref != NULL &&
-      cpi->sf.hl_sf.adaptive_overlay_encoding) {
+  if ((show_existing_alt_ref != NULL &&
+       cpi->sf.hl_sf.adaptive_overlay_encoding) ||
+      second_alt_ref) {
     AV1_COMMON *const cm = &cpi->common;
     int top_index = 0, bottom_index = 0;
 
@@ -1644,10 +1658,15 @@
     const float std = (float)sqrt((float)diff.sse / mbs - mean * mean);
     const float threshold = 0.7f;
 
-    *show_existing_alt_ref = 0;
-    if (mean / ac_q_2 < threshold && std < mean * 1.2)
-      *show_existing_alt_ref = 1;
-    cpi->common.showable_frame |= *show_existing_alt_ref;
+    if (!second_alt_ref) {
+      *show_existing_alt_ref = 0;
+      if (mean / ac_q_2 < threshold && std < mean * 1.2)
+        *show_existing_alt_ref = 1;
+      cpi->common.showable_frame |= *show_existing_alt_ref;
+    } else {
+      // Use source frame if the filtered frame becomes very different.
+      if (!(mean / ac_q_2 < threshold && std < mean * 1.2)) return 0;
+    }
   }
 
   return 1;