Prune warped motion search based on stats

Pruned warped motion search based on stats gathered from previous
frames. This was turned on for >=480p at speed 5.

        avg_psnr:  ovr_psnr:  ssim:  avg speedup over whole set:
midres:  0.091      0.102     0.088      0.9%
hdres:   0.033      0.034     0.028      0.8%

STATS_CHANGED

Change-Id: Id0ee6c5122acea35417044d934965d221a6d61c9
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index aa05d8d..b22adb3 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -1632,8 +1632,9 @@
       update_stats(&cpi->common, td, mi_row, mi_col);
     }
 
-    // Gather obmc count to update the probability.
-    if (!cpi->sf.disable_obmc && cpi->sf.prune_obmc_prob_thresh > 0) {
+    // Gather obmc and warped motion count to update the probability.
+    if ((!cpi->sf.disable_obmc && cpi->sf.prune_obmc_prob_thresh > 0) ||
+        (cm->allow_warped_motion && cpi->sf.prune_warped_prob_thresh > 0)) {
       const int inter_block = is_inter_block(mbmi);
       const int seg_ref_active =
           segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_REF_FRAME);
@@ -1643,9 +1644,14 @@
                 ? motion_mode_allowed(xd->global_motion, xd, mbmi,
                                       cm->allow_warped_motion)
                 : SIMPLE_TRANSLATION;
-        if (mbmi->ref_frame[1] != INTRA_FRAME &&
-            motion_allowed >= OBMC_CAUSAL) {
-          td->rd_counts.obmc_used[bsize][mbmi->motion_mode == OBMC_CAUSAL]++;
+
+        if (mbmi->ref_frame[1] != INTRA_FRAME) {
+          if (motion_allowed >= OBMC_CAUSAL) {
+            td->rd_counts.obmc_used[bsize][mbmi->motion_mode == OBMC_CAUSAL]++;
+          }
+          if (motion_allowed == WARPED_CAUSAL) {
+            td->rd_counts.warped_used[mbmi->motion_mode == WARPED_CAUSAL]++;
+          }
         }
       }
     }
@@ -5082,6 +5088,7 @@
   av1_zero(rdc->comp_pred_diff);
   av1_zero(rdc->tx_type_used);
   av1_zero(rdc->obmc_used);
+  av1_zero(rdc->warped_used);
 
   // Reset the flag.
   cpi->intrabc_used = 0;
@@ -5092,6 +5099,12 @@
 
   cm->allow_intrabc &= (cpi->oxcf.enable_intrabc);
 
+  if (cm->allow_warped_motion && cpi->sf.prune_warped_prob_thresh > 0) {
+    const FRAME_UPDATE_TYPE update_type = get_frame_update_type(&cpi->gf_group);
+    if (cpi->warped_probs[update_type] < cpi->sf.prune_warped_prob_thresh)
+      cm->allow_warped_motion = 0;
+  }
+
   if (!is_stat_generation_stage(cpi) && av1_use_hash_me(cpi) &&
       !cpi->sf.use_nonrd_pick_mode) {
     // add to hash table
@@ -5398,6 +5411,15 @@
           (cpi->obmc_probs[update_type][i] + new_prob) >> 1;
     }
   }
+
+  if (cm->allow_warped_motion && cpi->sf.prune_warped_prob_thresh > 0) {
+    const FRAME_UPDATE_TYPE update_type = get_frame_update_type(&cpi->gf_group);
+    int sum = 0;
+    for (i = 0; i < 2; i++) sum += cpi->td.rd_counts.warped_used[i];
+    const int new_prob = sum ? 128 * cpi->td.rd_counts.warped_used[1] / sum : 0;
+    cpi->warped_probs[update_type] =
+        (cpi->warped_probs[update_type] + new_prob) >> 1;
+  }
 }
 
 #define CHECK_PRECOMPUTED_REF_FRAME_MAP 0
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 4486dca..3174a1b 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -247,6 +247,9 @@
     35, 32, 19, 16,  16, 0,  0,  49, 55, 29, 19 }
 };
 
+const int default_warped_probs[FRAME_UPDATE_TYPES] = { 64, 64, 64, 64,
+                                                       64, 64, 64 };
+
 static INLINE void Scale2Ratio(AOM_SCALING mode, int *hr, int *hs) {
   switch (mode) {
     case NORMAL:
@@ -5045,6 +5048,10 @@
       cm->current_frame.frame_type == KEY_FRAME) {
     av1_copy(cpi->obmc_probs, default_obmc_probs);
   }
+  if (cpi->sf.prune_warped_prob_thresh > 0 &&
+      cm->current_frame.frame_type == KEY_FRAME) {
+    av1_copy(cpi->warped_probs, default_warped_probs);
+  }
 
   // Loop variables
   int loop_count = 0;
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index b07d918..898133e 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -610,6 +610,7 @@
   int skip_mode_used_flag;
   int tx_type_used[TX_SIZES_ALL][TX_TYPES];
   int obmc_used[BLOCK_SIZES_ALL][2];
+  int warped_used[2];
 } RD_COUNTS;
 
 typedef struct ThreadData {
@@ -986,6 +987,7 @@
   BLOCK_SIZE vbp_bsize_min;
 
   int obmc_probs[FRAME_UPDATE_TYPES][BLOCK_SIZES_ALL];
+  int warped_probs[FRAME_UPDATE_TYPES];
   int tx_type_probs[FRAME_UPDATE_TYPES][TX_SIZES_ALL][TX_TYPES];
   int tx_type_probs_thresh[FRAME_UPDATE_TYPES];
 
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index aeb0dec..f1a541c 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -38,6 +38,10 @@
       td->rd_counts.obmc_used[i][j] += td_t->rd_counts.obmc_used[i][j];
     }
   }
+
+  for (int i = 0; i < 2; i++) {
+    td->rd_counts.warped_used[i] += td_t->rd_counts.warped_used[i];
+  }
 }
 
 static AOM_INLINE void update_delta_lf_for_row_mt(AV1_COMP *cpi) {
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 90521fd..b5858ec 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -230,6 +230,14 @@
 
     sf->prune_obmc_prob_thresh = 16;
   }
+
+  if (speed >= 5) {
+    if (is_720p_or_larger) {
+      sf->prune_warped_prob_thresh = 16;
+    } else if (is_480p_or_larger) {
+      sf->prune_warped_prob_thresh = 8;
+    }
+  }
 }
 
 static void set_rt_speed_feature_framesize_dependent(const AV1_COMP *const cpi,
@@ -944,6 +952,7 @@
   sf->nonrd_merge_partition = 0;
   sf->disable_interinter_wedge = 0;
   sf->prune_ref_mv_idx_search = 0;
+  sf->prune_warped_prob_thresh = 0;
 
   if (oxcf->mode == GOOD)
     set_good_speed_features_framesize_independent(cpi, sf, speed);
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 622090e..5043382 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -566,6 +566,9 @@
   // TRANSLATION and AFFINE(based on number of warp neighbors)
   int prune_warp_using_wmtype;
 
+  // Prune warped motion search using previous frame stats.
+  int prune_warped_prob_thresh;
+
   // Enable/disable interintra wedge search.
   int disable_wedge_interintra_search;