Refactor: Refine interpolation_filter_search

1. Extract function interpolation_filter_rd to
calculate the rdcost of a given interpolation_filter
2. Reorder the conditions in interpolation_filter_search

Change-Id: If282f545a1564544796611e2a737039f897f2b2c
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index db9a8a2..08adfec 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -64,9 +64,10 @@
 #endif
 
 #define DUAL_FILTER_SET_SIZE (SWITCHABLE_FILTERS * SWITCHABLE_FILTERS)
-static const int filter_sets[DUAL_FILTER_SET_SIZE][2] = {
-  { 0, 0 }, { 0, 1 }, { 0, 2 }, { 1, 0 }, { 1, 1 },
-  { 1, 2 }, { 2, 0 }, { 2, 1 }, { 2, 2 },
+static const InterpFilters filter_sets[DUAL_FILTER_SET_SIZE] = {
+  0x00000000, 0x00010000, 0x00020000,  // y = 0
+  0x00000001, 0x00010001, 0x00020001,  // y = 1
+  0x00000002, 0x00010002, 0x00020002,  // y = 2
 };
 
 #define SECOND_REF_FRAME_MASK                                         \
@@ -7412,6 +7413,46 @@
   return 0;
 }
 
+static INLINE void swap_dst_buf(MACROBLOCKD *xd, const BUFFER_SET *dst_bufs[2],
+                                int num_planes) {
+  const BUFFER_SET *buf0 = dst_bufs[0];
+  dst_bufs[0] = dst_bufs[1];
+  dst_bufs[1] = buf0;
+  restore_dst_buf(xd, *dst_bufs[0], num_planes);
+}
+
+// calculate the rdcost of given interpolation_filter
+static INLINE int64_t interpolation_filter_rd(
+    MACROBLOCK *const x, const AV1_COMP *const cpi, BLOCK_SIZE bsize,
+    int mi_row, int mi_col, BUFFER_SET *const orig_dst, int64_t *const rd,
+    int *const switchable_rate, int *const skip_txfm_sb,
+    int64_t *const skip_sse_sb, const BUFFER_SET *dst_bufs[2], int filter_idx) {
+  const AV1_COMMON *cm = &cpi->common;
+  const int num_planes = av1_num_planes(cm);
+  MACROBLOCKD *const xd = &x->e_mbd;
+  MB_MODE_INFO *const mbmi = xd->mi[0];
+  int tmp_rate, tmp_skip_sb = 0;
+  int64_t tmp_dist, tmp_skip_sse = INT64_MAX;
+
+  const InterpFilters last_best = mbmi->interp_filters;
+  mbmi->interp_filters = filter_sets[filter_idx];
+  const int tmp_rs = av1_get_switchable_rate(cm, x, xd);
+  av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
+  model_rd_for_sb(cpi, bsize, x, xd, 0, num_planes - 1, &tmp_rate, &tmp_dist,
+                  &tmp_skip_sb, &tmp_skip_sse, NULL, NULL, NULL);
+  int64_t tmp_rd = RDCOST(x->rdmult, tmp_rs + tmp_rate, tmp_dist);
+  if (tmp_rd < *rd) {
+    *rd = tmp_rd;
+    *switchable_rate = tmp_rs;
+    *skip_txfm_sb = tmp_skip_sb;
+    *skip_sse_sb = tmp_skip_sse;
+    swap_dst_buf(xd, dst_bufs, num_planes);
+    return 1;
+  }
+  mbmi->interp_filters = last_best;
+  return 0;
+}
+
 static int64_t interpolation_filter_search(
     MACROBLOCK *const x, const AV1_COMP *const cpi, BLOCK_SIZE bsize,
     int mi_row, int mi_col, const BUFFER_SET *const tmp_dst,
@@ -7422,16 +7463,12 @@
   const int num_planes = av1_num_planes(cm);
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = xd->mi[0];
-  int i;
-  int tmp_rate;
+  int i, tmp_rate;
   int64_t tmp_dist;
 
   (void)single_filter;
 
-  InterpFilter assign_filter = SWITCHABLE;
-
-  if (cm->interp_filter != SWITCHABLE) assign_filter = cm->interp_filter;
-
+  const InterpFilter assign_filter = cm->interp_filter;
   set_default_interp_filters(mbmi, assign_filter);
 
   *switchable_rate = av1_get_switchable_rate(cm, x, xd);
@@ -7440,136 +7477,52 @@
                   skip_txfm_sb, skip_sse_sb, NULL, NULL, NULL);
   *rd = RDCOST(x->rdmult, *switchable_rate + tmp_rate, tmp_dist);
 
-  if (assign_filter == SWITCHABLE) {
-    // do interp_filter search
-    if (av1_is_interp_needed(xd) && av1_is_interp_search_needed(xd)) {
-      const int filter_set_size = DUAL_FILTER_SET_SIZE;
-      int best_in_temp = 0;
-      InterpFilters best_filters = mbmi->interp_filters;
-      restore_dst_buf(xd, *tmp_dst, num_planes);
-
-      if (cpi->sf.use_fast_interpolation_filter_search &&
-          cm->seq_params.enable_dual_filter) {
-        int tmp_skip_sb = 0;
-        int64_t tmp_skip_sse = INT64_MAX;
-        int tmp_rs;
-        int64_t tmp_rd;
-
-        // default to (R,R): EIGHTTAP_REGULARxEIGHTTAP_REGULAR
-        int best_dual_mode = 0;
-        // Find best of {R}x{R,Sm,Sh}
-        // EIGHTTAP_REGULAR mode is calculated beforehand
-        for (i = 1; i < SWITCHABLE_FILTERS; ++i) {
-          tmp_skip_sb = 0;
-          tmp_skip_sse = INT64_MAX;
-
-          mbmi->interp_filters =
-              av1_make_interp_filters(filter_sets[i][0], filter_sets[i][1]);
-
-          tmp_rs = av1_get_switchable_rate(cm, x, xd);
-          av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst,
-                                        bsize);
-          model_rd_for_sb(cpi, bsize, x, xd, 0, num_planes - 1, &tmp_rate,
-                          &tmp_dist, &tmp_skip_sb, &tmp_skip_sse, NULL, NULL,
-                          NULL);
-          tmp_rd = RDCOST(x->rdmult, tmp_rs + tmp_rate, tmp_dist);
-
-          if (tmp_rd < *rd) {
-            best_dual_mode = i;
-
-            *rd = tmp_rd;
-            *switchable_rate = tmp_rs;
-            best_filters = mbmi->interp_filters;
-            *skip_txfm_sb = tmp_skip_sb;
-            *skip_sse_sb = tmp_skip_sse;
-            best_in_temp = !best_in_temp;
-            if (best_in_temp) {
-              restore_dst_buf(xd, *orig_dst, num_planes);
-            } else {
-              restore_dst_buf(xd, *tmp_dst, num_planes);
-            }
-          }
-        }
-
-        // From best of horizontal EIGHTTAP_REGULAR modes, check vertical modes
-        for (i = best_dual_mode + SWITCHABLE_FILTERS; i < filter_set_size;
-             i += SWITCHABLE_FILTERS) {
-          tmp_skip_sb = 0;
-          tmp_skip_sse = INT64_MAX;
-
-          mbmi->interp_filters =
-              av1_make_interp_filters(filter_sets[i][0], filter_sets[i][1]);
-
-          tmp_rs = av1_get_switchable_rate(cm, x, xd);
-          av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst,
-                                        bsize);
-          model_rd_for_sb(cpi, bsize, x, xd, 0, num_planes - 1, &tmp_rate,
-                          &tmp_dist, &tmp_skip_sb, &tmp_skip_sse, NULL, NULL,
-                          NULL);
-          tmp_rd = RDCOST(x->rdmult, tmp_rs + tmp_rate, tmp_dist);
-
-          if (tmp_rd < *rd) {
-            *rd = tmp_rd;
-            *switchable_rate = tmp_rs;
-            best_filters = mbmi->interp_filters;
-            *skip_txfm_sb = tmp_skip_sb;
-            *skip_sse_sb = tmp_skip_sse;
-            best_in_temp = !best_in_temp;
-            if (best_in_temp) {
-              restore_dst_buf(xd, *orig_dst, num_planes);
-            } else {
-              restore_dst_buf(xd, *tmp_dst, num_planes);
-            }
-          }
-        }
-      } else {
-        // EIGHTTAP_REGULAR mode is calculated beforehand
-        for (i = 1; i < filter_set_size; ++i) {
-          int tmp_skip_sb = 0;
-          int64_t tmp_skip_sse = INT64_MAX;
-          int tmp_rs;
-          int64_t tmp_rd;
-
-          if (cm->seq_params.enable_dual_filter == 0)
-            if (filter_sets[i][0] != filter_sets[i][1]) continue;
-
-          mbmi->interp_filters =
-              av1_make_interp_filters(filter_sets[i][0], filter_sets[i][1]);
-          tmp_rs = av1_get_switchable_rate(cm, x, xd);
-          av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst,
-                                        bsize);
-          model_rd_for_sb(cpi, bsize, x, xd, 0, num_planes - 1, &tmp_rate,
-                          &tmp_dist, &tmp_skip_sb, &tmp_skip_sse, NULL, NULL,
-                          NULL);
-          tmp_rd = RDCOST(x->rdmult, tmp_rs + tmp_rate, tmp_dist);
-
-          if (tmp_rd < *rd) {
-            *rd = tmp_rd;
-            *switchable_rate = tmp_rs;
-            best_filters = mbmi->interp_filters;
-            *skip_txfm_sb = tmp_skip_sb;
-            *skip_sse_sb = tmp_skip_sse;
-            best_in_temp = !best_in_temp;
-            if (best_in_temp) {
-              restore_dst_buf(xd, *orig_dst, num_planes);
-            } else {
-              restore_dst_buf(xd, *tmp_dst, num_planes);
-            }
-          }
-        }
+  if (assign_filter != SWITCHABLE) {
+    return 0;
+  }
+  if (!av1_is_interp_needed(xd) || !av1_is_interp_search_needed(xd)) {
+    assert(mbmi->interp_filters ==
+           av1_broadcast_interp_filter(EIGHTTAP_REGULAR));
+    return 0;
+  }
+  // do interp_filter search
+  const int filter_set_size = DUAL_FILTER_SET_SIZE;
+  restore_dst_buf(xd, *tmp_dst, num_planes);
+  const BUFFER_SET *dst_bufs[2] = { tmp_dst, orig_dst };
+  if (cpi->sf.use_fast_interpolation_filter_search &&
+      cm->seq_params.enable_dual_filter) {
+    // default to (R,R): EIGHTTAP_REGULARxEIGHTTAP_REGULAR
+    int best_dual_mode = 0;
+    // Find best of {R}x{R,Sm,Sh}
+    // EIGHTTAP_REGULAR mode is calculated beforehand
+    for (i = 1; i < SWITCHABLE_FILTERS; ++i) {
+      if (interpolation_filter_rd(x, cpi, bsize, mi_row, mi_col, orig_dst, rd,
+                                  switchable_rate, skip_txfm_sb, skip_sse_sb,
+                                  dst_bufs, i)) {
+        best_dual_mode = i;
       }
-
-      if (best_in_temp) {
-        restore_dst_buf(xd, *tmp_dst, num_planes);
-      } else {
-        restore_dst_buf(xd, *orig_dst, num_planes);
+    }
+    // From best of horizontal EIGHTTAP_REGULAR modes, check vertical modes
+    for (i = best_dual_mode + SWITCHABLE_FILTERS; i < filter_set_size;
+         i += SWITCHABLE_FILTERS) {
+      interpolation_filter_rd(x, cpi, bsize, mi_row, mi_col, orig_dst, rd,
+                              switchable_rate, skip_txfm_sb, skip_sse_sb,
+                              dst_bufs, i);
+    }
+  } else {
+    // EIGHTTAP_REGULAR mode is calculated beforehand
+    for (i = 1; i < filter_set_size; ++i) {
+      if (cm->seq_params.enable_dual_filter == 0) {
+        const int16_t filter_y = filter_sets[i] & 0xffff;
+        const int16_t filter_x = filter_sets[i] >> 16;
+        if (filter_x != filter_y) continue;
       }
-      mbmi->interp_filters = best_filters;
-    } else {
-      assert(mbmi->interp_filters ==
-             av1_broadcast_interp_filter(EIGHTTAP_REGULAR));
+      interpolation_filter_rd(x, cpi, bsize, mi_row, mi_col, orig_dst, rd,
+                              switchable_rate, skip_txfm_sb, skip_sse_sb,
+                              dst_bufs, i);
     }
   }
+  swap_dst_buf(xd, dst_bufs, num_planes);
   return 0;
 }