New interpolation filter selection algorithm

Old Scheme:
When SWITCHABLE filter selection is enabled the encoder
evaluates the use of each interpolation filter type and
selects the best one to use at the MB level. A frame-
level flag can be set to force the use of a particular
filter type for all MBs in a frame if it is more efficient
to encode that way. The logic here involved a Q dependent
threshold that assumed that the second 8-tap filter was
a high-pass filter. However, this requires a trip around
the recode loop. If the frame-level flag indicates use
of a particular filter, the other filters are not
evaluated in the pick_mode loop.

New Scheme:
Each filter type is evaluated at the MB level and a record
of the best filter is kept, irrespective of what filter
is signaled at the frame-level. Once all MBs have been
encoded, a decision is made as to what frame-level mode
to set for the *next* frame. If one filter is used by 80%
or more of the MBs, then this filter is forced since it
is assumed that this will be more efficient if the
next frame has similar characteristics. i.e. there is a
one-frame lag between measuring the filter selection and
setting the frame-level mode to use.

Change-Id: I6a7e7ced8f27e120fafb99db2dc9c6293f8d20f7
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index b7a5b80..3219e12 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -45,6 +45,8 @@
 int enc_debug = 0;
 #endif
 
+extern void select_interp_filter_type(VP9_COMP *cpi);
+
 static void encode_macroblock(VP9_COMP *cpi, MACROBLOCK *x,
                               TOKENEXTRA **t, int recon_yoffset,
                               int recon_uvoffset, int output_enabled,
@@ -1477,6 +1479,7 @@
   cpi->pred_filter_off_count = 0;
 #endif
   vp9_zero(cpi->switchable_interp_count);
+  vp9_zero(cpi->best_switchable_interp_count);
 
   xd->mode_info_context = cm->mi;
   xd->prev_mode_info_context = cm->prev_mi;
@@ -1828,6 +1831,10 @@
 #endif
       }
     }
+
+    // Update interpolation filter strategy for next frame.
+    if ((cpi->common.frame_type != KEY_FRAME) && (cpi->sf.search_best_filter))
+      select_interp_filter_type(cpi);
   } else {
     encode_frame_internal(cpi);
   }
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 5043bc4..9b186c2 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -2841,6 +2841,45 @@
 
 }
 
+void select_interp_filter_type(VP9_COMP *cpi) {
+  int i;
+  int high_filter_index;
+  unsigned int thresh;
+  unsigned int high_count = 0;
+  unsigned int count_sum = 0;
+  unsigned int *hist = cpi->best_switchable_interp_count;
+
+  if (DEFAULT_INTERP_FILTER != SWITCHABLE) {
+    cpi->common.mcomp_filter_type = DEFAULT_INTERP_FILTER;
+    return;
+  }
+
+  // TODO(agrange): Look at using RD criteria to select the interpolation
+  // filter to use for the next frame rather than this simpler counting scheme.
+
+  // Select the interpolation filter mode for the next frame
+  // based on the selection frequency seen in the current frame.
+  for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
+    unsigned int count = hist[i];
+    count_sum += count;
+    if (count > high_count) {
+      high_count = count;
+      high_filter_index = i;
+    }
+  }
+
+  thresh = (unsigned int)(0.80 * count_sum);
+
+  if (high_count > thresh) {
+    // One filter accounts for 80+% of cases so force the next
+    // frame to use this filter exclusively using frame-level flag.
+    cpi->common.mcomp_filter_type = vp9_switchable_interp[high_filter_index];
+  } else {
+    // Use a MB-level switchable filter selection strategy.
+    cpi->common.mcomp_filter_type = SWITCHABLE;
+  }
+}
+
 #if CONFIG_PRED_FILTER
 void select_pred_filter_mode(VP9_COMP *cpi) {
   VP9_COMMON *cm = &cpi->common;
@@ -3131,7 +3170,7 @@
   if (cpi->active_worst_quality < cpi->active_best_quality)
     cpi->active_worst_quality = cpi->active_best_quality;
 
-  // Specuial case code to try and match quality with forced key frames
+  // Special case code to try and match quality with forced key frames
   if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
     Q = cpi->last_boosted_qindex;
   } else {
@@ -3485,37 +3524,6 @@
     if (cpi->is_src_frame_alt_ref)
       Loop = FALSE;
 
-    if (cm->frame_type != KEY_FRAME &&
-        !sf->search_best_filter &&
-        cm->mcomp_filter_type == SWITCHABLE) {
-      int interp_factor = Q / 3;  /* denominator is 256 */
-      int count[VP9_SWITCHABLE_FILTERS];
-      int tot_count = 0, c = 0, thr;
-      int i, j;
-      for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
-        count[i] = 0;
-        for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j) {
-          count[i] += cpi->switchable_interp_count[j][i];
-        }
-        tot_count += count[i];
-      }
-
-      thr = ((tot_count * interp_factor + 128) >> 8);
-      for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
-        c += (count[i] >= thr);
-      }
-      if (c == 1) {
-        /* Mostly one filter is used. So set the filter at frame level */
-        for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
-          if (count[i]) {
-            cm->mcomp_filter_type = vp9_switchable_interp[i];
-            Loop = TRUE;  /* Make sure to loop since the filter changed */
-            break;
-          }
-        }
-      }
-    }
-
     if (Loop == FALSE && cm->frame_type != KEY_FRAME && sf->search_best_filter) {
       if (mcomp_filter_index < mcomp_filters) {
         int64_t err = vp9_calc_ss_err(cpi->Source,
@@ -3570,6 +3578,7 @@
 
     if (Loop == TRUE) {
       loop_count++;
+
 #if CONFIG_INTERNAL_STATS
       cpi->tot_recode_hits++;
 #endif
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 6452be3..7c9181b 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -799,6 +799,8 @@
 #endif
   unsigned int switchable_interp_count[VP9_SWITCHABLE_FILTERS + 1]
                                       [VP9_SWITCHABLE_FILTERS];
+  unsigned int best_switchable_interp_count[VP9_SWITCHABLE_FILTERS];
+
 #if CONFIG_NEW_MVREF
   unsigned int mb_mv_ref_count[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
 #endif
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index cba9094..d6d3fca 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -3498,14 +3498,16 @@
     }
   }
 
-  if (is_comp_pred) {
-    *mode_excluded = (cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY);
-  } else {
-    *mode_excluded = (cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY);
-  }
+  if (!(*mode_excluded)) {
+    if (is_comp_pred) {
+      *mode_excluded = (cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY);
+    } else {
+      *mode_excluded = (cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY);
+    }
 #if CONFIG_COMP_INTERINTRA_PRED
-  if (is_comp_interintra_pred && !cm->use_interintra) *mode_excluded = 1;
+    if (is_comp_interintra_pred && !cm->use_interintra) *mode_excluded = 1;
 #endif
+  }
 
   if (!x->skip) {
     if (block_size == BLOCK_16X16) {
@@ -3556,6 +3558,7 @@
   PARTITION_INFO best_partition;
   int_mv best_ref_mv, second_best_ref_mv;
   MB_PREDICTION_MODE this_mode;
+  MB_PREDICTION_MODE best_mode = DC_PRED;
   MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
   int i, best_mode_index = 0;
   int mode8x8[2][4];
@@ -3576,6 +3579,7 @@
   int best_intra16_mode = DC_PRED, best_intra16_uv_mode = DC_PRED;
 #endif
   int64_t best_overall_rd = LLONG_MAX;
+  INTERPOLATIONFILTERTYPE best_filter = SWITCHABLE;
   int uv_intra_rate, uv_intra_distortion, uv_intra_rate_tokenonly;
   int uv_intra_skippable = 0;
   int uv_intra_rate_8x8 = 0, uv_intra_distortion_8x8 = 0, uv_intra_rate_tokenonly_8x8 = 0;
@@ -3697,16 +3701,20 @@
 #if CONFIG_PRED_FILTER
     mbmi->pred_filter_enabled = 0;
 #endif
-    if (cpi->common.mcomp_filter_type == SWITCHABLE &&
-        this_mode >= NEARESTMV && this_mode <= SPLITMV) {
+
+    // Evaluate all sub-pel filters irrespective of whether we can use
+    // them for this frame.
+    if (this_mode >= NEARESTMV && this_mode <= SPLITMV) {
       mbmi->interp_filter =
           vp9_switchable_interp[switchable_filter_index++];
       if (switchable_filter_index == VP9_SWITCHABLE_FILTERS)
         switchable_filter_index = 0;
-    } else {
-      mbmi->interp_filter = cpi->common.mcomp_filter_type;
+      if ((cm->mcomp_filter_type != SWITCHABLE) &&
+          (cm->mcomp_filter_type != mbmi->interp_filter)) {
+        mode_excluded = 1;
+      }
+      vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
     }
-    vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
 
     // Test best rd so far against threshold for trying this mode.
     if (best_rd <= cpi->rd_threshes[mode_index])
@@ -3972,6 +3980,7 @@
         rate2 += SWITCHABLE_INTERP_RATE_FACTOR * x->switchable_interp_costs
             [vp9_get_pred_context(&cpi->common, xd, PRED_SWITCHABLE_INTERP)]
                 [vp9_switchable_interp_map[mbmi->interp_filter]];
+
       // If even the 'Y' rd value of split is higher than best so far
       // then dont bother looking at UV
       if (tmp_rd < best_yrd) {
@@ -3987,10 +3996,12 @@
         disable_skip = 1;
       }
 
-      if (is_comp_pred)
-        mode_excluded = cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY;
-      else
-        mode_excluded = cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY;
+      if (!mode_excluded) {
+        if (is_comp_pred)
+          mode_excluded = cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY;
+        else
+          mode_excluded = cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY;
+      }
 
       compmode_cost =
         vp9_cost_bit(vp9_get_pred_prob(cm, xd, PRED_COMP), is_comp_pred);
@@ -4103,13 +4114,14 @@
     }
 #endif
 
-
     if (!disable_skip && mbmi->ref_frame == INTRA_FRAME)
       for (i = 0; i < NB_PREDICTION_TYPES; ++i)
         best_pred_rd[i] = MIN(best_pred_rd[i], this_rd);
 
     if (this_rd < best_overall_rd) {
       best_overall_rd = this_rd;
+      best_filter = mbmi->interp_filter;
+      best_mode = this_mode;
 #if CONFIG_PRED_FILTER
       best_filter_state = mbmi->pred_filter_enabled;
 #endif
@@ -4125,117 +4137,121 @@
         (cm->pred_filter_mode ==
          mbmi->pred_filter_enabled)) {
 #endif
-      // Did this mode help.. i.e. is it the new best mode
-      if (this_rd < best_rd || x->skip) {
-        if (!mode_excluded) {
-          /*
-          if (mbmi->second_ref_frame == INTRA_FRAME) {
-            printf("rd %d best %d bestintra16 %d\n", this_rd, best_rd, best_intra16_rd);
-          }
-          */
-          // Note index of best mode so far
-          best_mode_index = mode_index;
+    // Did this mode help.. i.e. is it the new best mode
+    if (this_rd < best_rd || x->skip) {
+      if (!mode_excluded) {
+        /*
+        if (mbmi->second_ref_frame == INTRA_FRAME) {
+          printf("rd %d best %d bestintra16 %d\n", this_rd, best_rd, best_intra16_rd);
+        }
+        */
+        // Note index of best mode so far
+        best_mode_index = mode_index;
 
-          if (this_mode <= B_PRED) {
-            if (mbmi->txfm_size != TX_4X4
-                && this_mode != B_PRED
-                && this_mode != I8X8_PRED)
-              mbmi->uv_mode = uv_intra_mode_8x8;
-            else
-              mbmi->uv_mode = uv_intra_mode;
-            /* required for left and above block mv */
-            mbmi->mv[0].as_int = 0;
-          }
-
-          other_cost += ref_costs[mbmi->ref_frame];
-
-          /* Calculate the final y RD estimate for this mode */
-          best_yrd = RDCOST(x->rdmult, x->rddiv, (rate2 - rate_uv - other_cost),
-                            (distortion2 - distortion_uv));
-
-          *returnrate = rate2;
-          *returndistortion = distortion2;
-          best_rd = this_rd;
-          vpx_memcpy(&best_mbmode, mbmi, sizeof(MB_MODE_INFO));
-          vpx_memcpy(&best_partition, x->partition_info, sizeof(PARTITION_INFO));
-
-          if ((this_mode == B_PRED)
-              || (this_mode == I8X8_PRED)
-              || (this_mode == SPLITMV))
-            for (i = 0; i < 16; i++) {
-              best_bmodes[i] = xd->block[i].bmi;
-            }
+        if (this_mode <= B_PRED) {
+          if (mbmi->txfm_size != TX_4X4
+              && this_mode != B_PRED
+              && this_mode != I8X8_PRED)
+            mbmi->uv_mode = uv_intra_mode_8x8;
+          else
+            mbmi->uv_mode = uv_intra_mode;
+          /* required for left and above block mv */
+          mbmi->mv[0].as_int = 0;
         }
 
-        // Testing this mode gave rise to an improvement in best error score.
-        // Lower threshold a bit for next time
-        cpi->rd_thresh_mult[mode_index] =
-            (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ?
-            cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
-        cpi->rd_threshes[mode_index] =
-            (cpi->rd_baseline_thresh[mode_index] >> 7) *
-            cpi->rd_thresh_mult[mode_index];
+        other_cost += ref_costs[mbmi->ref_frame];
+
+        /* Calculate the final y RD estimate for this mode */
+        best_yrd = RDCOST(x->rdmult, x->rddiv, (rate2 - rate_uv - other_cost),
+                          (distortion2 - distortion_uv));
+
+        *returnrate = rate2;
+        *returndistortion = distortion2;
+        best_rd = this_rd;
+        vpx_memcpy(&best_mbmode, mbmi, sizeof(MB_MODE_INFO));
+        vpx_memcpy(&best_partition, x->partition_info, sizeof(PARTITION_INFO));
+
+        if ((this_mode == B_PRED)
+            || (this_mode == I8X8_PRED)
+            || (this_mode == SPLITMV))
+          for (i = 0; i < 16; i++) {
+            best_bmodes[i] = xd->block[i].bmi;
+          }
       }
+
+      // Testing this mode gave rise to an improvement in best error score.
+      // Lower threshold a bit for next time
+      cpi->rd_thresh_mult[mode_index] =
+          (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ?
+          cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
+      cpi->rd_threshes[mode_index] =
+          (cpi->rd_baseline_thresh[mode_index] >> 7) *
+          cpi->rd_thresh_mult[mode_index];
+    } else {
       // If the mode did not help improve the best error case then raise the
       // threshold for testing that mode next time around.
-      else {
-        cpi->rd_thresh_mult[mode_index] += 4;
+      cpi->rd_thresh_mult[mode_index] += 4;
 
-        if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
-          cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
+      if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
+        cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
 
-        cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+      cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7)
+          * cpi->rd_thresh_mult[mode_index];
+    }
+
+    /* keep record of best compound/single-only prediction */
+    if (!disable_skip && mbmi->ref_frame != INTRA_FRAME) {
+      int64_t single_rd, hybrid_rd;
+      int single_rate, hybrid_rate;
+
+      if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) {
+        single_rate = rate2 - compmode_cost;
+        hybrid_rate = rate2;
+      } else {
+        single_rate = rate2;
+        hybrid_rate = rate2 + compmode_cost;
       }
 
-      /* keep record of best compound/single-only prediction */
-      if (!disable_skip && mbmi->ref_frame != INTRA_FRAME) {
-        int64_t single_rd, hybrid_rd;
-        int single_rate, hybrid_rate;
+      single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2);
+      hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2);
 
-        if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) {
-          single_rate = rate2 - compmode_cost;
-          hybrid_rate = rate2;
+      if (mbmi->second_ref_frame <= INTRA_FRAME &&
+          single_rd < best_pred_rd[SINGLE_PREDICTION_ONLY]) {
+        best_pred_rd[SINGLE_PREDICTION_ONLY] = single_rd;
+      } else if (mbmi->second_ref_frame > INTRA_FRAME &&
+                 single_rd < best_pred_rd[COMP_PREDICTION_ONLY]) {
+        best_pred_rd[COMP_PREDICTION_ONLY] = single_rd;
+      }
+      if (hybrid_rd < best_pred_rd[HYBRID_PREDICTION])
+        best_pred_rd[HYBRID_PREDICTION] = hybrid_rd;
+    }
+
+    /* keep record of best txfm size */
+    if (!mode_excluded && this_rd != LLONG_MAX) {
+      for (i = 0; i < NB_TXFM_MODES; i++) {
+        int64_t adj_rd;
+        if (this_mode != B_PRED) {
+          const int64_t txfm_mode_diff =
+              txfm_cache[i] - txfm_cache[cm->txfm_mode];
+          adj_rd = this_rd + txfm_mode_diff;
         } else {
-          single_rate = rate2;
-          hybrid_rate = rate2 + compmode_cost;
+          adj_rd = this_rd;
         }
-
-        single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2);
-        hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2);
-
-        if (mbmi->second_ref_frame <= INTRA_FRAME &&
-            single_rd < best_pred_rd[SINGLE_PREDICTION_ONLY]) {
-          best_pred_rd[SINGLE_PREDICTION_ONLY] = single_rd;
-        } else if (mbmi->second_ref_frame > INTRA_FRAME &&
-                   single_rd < best_pred_rd[COMP_PREDICTION_ONLY]) {
-          best_pred_rd[COMP_PREDICTION_ONLY] = single_rd;
-        }
-        if (hybrid_rd < best_pred_rd[HYBRID_PREDICTION])
-          best_pred_rd[HYBRID_PREDICTION] = hybrid_rd;
+        if (adj_rd < best_txfm_rd[i])
+          best_txfm_rd[i] = adj_rd;
       }
+    }
 
-      /* keep record of best txfm size */
-      if (!mode_excluded && this_rd != LLONG_MAX) {
-        for (i = 0; i < NB_TXFM_MODES; i++) {
-          int64_t adj_rd;
-          if (this_mode != B_PRED) {
-            const int64_t txfm_mode_diff =
-                txfm_cache[i] - txfm_cache[cm->txfm_mode];
-            adj_rd = this_rd + txfm_mode_diff;
-          } else {
-            adj_rd = this_rd;
-          }
-          if (adj_rd < best_txfm_rd[i])
-            best_txfm_rd[i] = adj_rd;
-        }
-      }
+    if (x->skip && !mode_excluded)
+      break;
+    }
 #if CONFIG_PRED_FILTER
     }
 #endif
 
-    if (x->skip && !mode_excluded)
-      break;
-  }
+  assert((cm->mcomp_filter_type == SWITCHABLE) ||
+         (cm->mcomp_filter_type == best_mbmode.interp_filter) ||
+         (best_mbmode.mode <= B_PRED));
 
 #if CONFIG_PRED_FILTER
   // Update counts for prediction filter usage
@@ -4248,6 +4264,11 @@
   ++cpi->interintra_select_count[is_best_interintra];
 #endif
 
+  // Accumulate filter usage stats
+  // TODO(agrange): Use RD criteria to select interpolation filter mode.
+  if ((best_mode >= NEARESTMV) && (best_mode <= SPLITMV))
+    ++cpi->best_switchable_interp_count[vp9_switchable_interp_map[best_filter]];
+
   // Reduce the activation RD thresholds for the best choice mode
   if ((cpi->rd_baseline_thresh[best_mode_index] > 0) &&
       (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2))) {
@@ -4535,6 +4556,7 @@
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
   MB_PREDICTION_MODE this_mode;
+  MB_PREDICTION_MODE best_mode = DC_PRED;
   MV_REFERENCE_FRAME ref_frame;
   unsigned char segment_id = xd->mode_info_context->mbmi.segment_id;
   int comp_pred, i;
@@ -4565,6 +4587,7 @@
   int best_intra16_mode = DC_PRED, best_intra16_uv_mode = DC_PRED;
 #endif
   int64_t best_overall_rd = LLONG_MAX;
+  INTERPOLATIONFILTERTYPE best_filter = SWITCHABLE;
   int rate_uv_4x4 = 0, rate_uv_8x8 = 0, rate_uv_tokenonly_4x4 = 0,
       rate_uv_tokenonly_8x8 = 0;
   int dist_uv_4x4 = 0, dist_uv_8x8 = 0, uv_skip_4x4 = 0, uv_skip_8x8 = 0;
@@ -4659,16 +4682,19 @@
     mbmi->interintra_mode = (MB_PREDICTION_MODE)(DC_PRED - 1);
     mbmi->interintra_uv_mode = (MB_PREDICTION_MODE)(DC_PRED - 1);
 #endif
-    if (cpi->common.mcomp_filter_type == SWITCHABLE &&
-        this_mode >= NEARESTMV && this_mode <= SPLITMV) {
+    // Evaluate all sub-pel filters irrespective of whether we can use
+    // them for this frame.
+    if (this_mode >= NEARESTMV && this_mode <= SPLITMV) {
       mbmi->interp_filter =
           vp9_switchable_interp[switchable_filter_index++];
       if (switchable_filter_index == VP9_SWITCHABLE_FILTERS)
         switchable_filter_index = 0;
-    } else {
-      mbmi->interp_filter = cpi->common.mcomp_filter_type;
+      if ((cm->mcomp_filter_type != SWITCHABLE) &&
+          (cm->mcomp_filter_type != mbmi->interp_filter)) {
+        mode_excluded = 1;
+      }
+      vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
     }
-    vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
 
     // if (!(cpi->ref_frame_flags & flag_list[ref_frame]))
     //  continue;
@@ -4693,15 +4719,19 @@
       xd->second_pre.y_buffer = y_buffer[second_ref];
       xd->second_pre.u_buffer = u_buffer[second_ref];
       xd->second_pre.v_buffer = v_buffer[second_ref];
-      mode_excluded = cm->comp_pred_mode == SINGLE_PREDICTION_ONLY;
+      mode_excluded =
+          mode_excluded ?
+              mode_excluded : cm->comp_pred_mode == SINGLE_PREDICTION_ONLY;
     } else {
       // mbmi->second_ref_frame = vp9_mode_order[mode_index].second_ref_frame;
       if (ref_frame != INTRA_FRAME) {
         if (mbmi->second_ref_frame != INTRA_FRAME)
-          mode_excluded = cm->comp_pred_mode == COMP_PREDICTION_ONLY;
+          mode_excluded =
+              mode_excluded ?
+                  mode_excluded : cm->comp_pred_mode == COMP_PREDICTION_ONLY;
 #if CONFIG_COMP_INTERINTRA_PRED
         else
-          mode_excluded = !cm->use_interintra;
+          mode_excluded = mode_excluded ? mode_excluded : !cm->use_interintra;
 #endif
       }
     }
@@ -4872,6 +4902,8 @@
 
     if (this_rd < best_overall_rd) {
       best_overall_rd = this_rd;
+      best_filter = mbmi->interp_filter;
+      best_mode = this_mode;
 #if CONFIG_COMP_INTERINTRA_PRED
       is_best_interintra = (mbmi->second_ref_frame == INTRA_FRAME);
 #endif
@@ -4900,20 +4932,27 @@
         vpx_memcpy(&best_mbmode, mbmi, sizeof(MB_MODE_INFO));
       }
 #if 0
-      // Testing this mode gave rise to an improvement in best error score. Lower threshold a bit for next time
-      cpi->rd_thresh_mult[mode_index] = (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ? cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
-      cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+      // Testing this mode gave rise to an improvement in best error score.
+      // Lower threshold a bit for next time
+      cpi->rd_thresh_mult[mode_index] =
+          (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ?
+              cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
+      cpi->rd_threshes[mode_index] =
+          (cpi->rd_baseline_thresh[mode_index] >> 7)
+              * cpi->rd_thresh_mult[mode_index];
 #endif
-    }
-    // If the mode did not help improve the best error case then raise the threshold for testing that mode next time around.
-    else {
+    } else {
+      // If the mode did not help improve the best error case then
+      // raise the threshold for testing that mode next time around.
 #if 0
       cpi->rd_thresh_mult[mode_index] += 4;
 
       if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
         cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
 
-      cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+      cpi->rd_threshes[mode_index] =
+          (cpi->rd_baseline_thresh[mode_index] >> 7)
+              * cpi->rd_thresh_mult[mode_index];
 #endif
     }
 
@@ -4961,11 +5000,20 @@
       break;
   }
 
+  assert((cm->mcomp_filter_type == SWITCHABLE) ||
+         (cm->mcomp_filter_type == best_mbmode.interp_filter) ||
+         (best_mbmode.mode <= B_PRED));
+
 #if CONFIG_COMP_INTERINTRA_PRED
   ++cpi->interintra_select_count[is_best_interintra];
   // if (is_best_interintra)  printf("best_interintra\n");
 #endif
 
+  // Accumulate filter usage stats
+  // TODO(agrange): Use RD criteria to select interpolation filter mode.
+  if ((best_mode >= NEARESTMV) && (best_mode <= SPLITMV))
+    ++cpi->best_switchable_interp_count[vp9_switchable_interp_map[best_filter]];
+
   // TODO(rbultje) integrate with RD thresholding
 #if 0
   // Reduce the activation RD thresholds for the best choice mode