Pack InterpFilters into a single integer

Before this patch, if CONFIG_DUAL_FILTER was true then an MB_MODE_INFO
stored its filter choices as an array of four numbers, each of which
was between 0 and 10. It also seems that elements 2 and 3 of the array
were always the same as elements 0 and 1 when used.

This patch defines a new type(def) called InterpFilters together with
constructor and extractor functions. When CONFIG_DUAL_FILTER is zero,
InterpFilters is a synonym for InterpFilter and the constructor and
extractor functions should compile away to nothing. When it is
nonzero, InterpFilters is a uint32_t which stores the x filter in the
high part and the y filter in the low part (this looks strange, but
matches the old numbering).

Making this change allows us to get rid of lots of special case code
that was dependent on CONFIG_DUAL_FILTER. The uniform
extract/make/broadcast interface also actually shortens code in
general.

Change-Id: I6b24a61bac3e4b220d8d46d0b27cfe865dcfba81
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index eadd4eb..86fcd57 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -378,12 +378,8 @@
   uint8_t use_intrabc;
 #endif  // CONFIG_INTRABC
 
-// Only for INTER blocks
-#if CONFIG_DUAL_FILTER
-  InterpFilter interp_filter[4];
-#else
-  InterpFilter interp_filter;
-#endif
+  // Only for INTER blocks
+  InterpFilters interp_filters;
   MV_REFERENCE_FRAME ref_frame[2];
   TX_TYPE tx_type;
 #if CONFIG_TXK_SEL
diff --git a/av1/common/convolve.c b/av1/common/convolve.c
index 40234ad..5476f59 100644
--- a/av1/common/convolve.c
+++ b/av1/common/convolve.c
@@ -557,34 +557,17 @@
 
 void av1_convolve_2d_facade(const uint8_t *src, int src_stride, uint8_t *dst,
                             int dst_stride, int w, int h,
-                            const InterpFilter *interp_filter,
-                            const int subpel_x_q4, int x_step_q4,
-                            const int subpel_y_q4, int y_step_q4, int scaled,
-                            ConvolveParams *conv_params) {
+                            InterpFilters interp_filters, const int subpel_x_q4,
+                            int x_step_q4, const int subpel_y_q4, int y_step_q4,
+                            int scaled, ConvolveParams *conv_params) {
   (void)x_step_q4;
   (void)y_step_q4;
   (void)dst;
   (void)dst_stride;
-#if CONFIG_DUAL_FILTER
-  InterpFilterParams filter_params_x =
-      av1_get_interp_filter_params(interp_filter[1 + 2 * conv_params->ref]);
-  InterpFilterParams filter_params_y =
-      av1_get_interp_filter_params(interp_filter[0 + 2 * conv_params->ref]);
 
-#if USE_EXTRA_FILTER
-  if (filter_params_x.interp_filter == MULTITAP_SHARP &&
-      filter_params_y.interp_filter == MULTITAP_SHARP) {
-    // Avoid two directions both using 12-tap filter.
-    // This will reduce hardware implementation cost.
-    filter_params_y = av1_get_interp_filter_params(EIGHTTAP_SHARP);
-  }
-#endif  // USE_EXTRA_FILTER
-#else
-  InterpFilterParams filter_params_x =
-      av1_get_interp_filter_params(*interp_filter);
-  InterpFilterParams filter_params_y =
-      av1_get_interp_filter_params(*interp_filter);
-#endif
+  InterpFilterParams filter_params_x, filter_params_y;
+  av1_get_convolve_filter_params(interp_filters, 1, &filter_params_x,
+                                 &filter_params_y);
 
   if (filter_params_y.taps < filter_params_x.taps) {
     uint8_t tr_src[(MAX_SB_SIZE + MAX_FILTER_TAP - 1) *
@@ -871,7 +854,7 @@
 
 void av1_highbd_convolve_2d_facade(const uint8_t *src8, int src_stride,
                                    uint8_t *dst, int dst_stride, int w, int h,
-                                   const InterpFilter *interp_filter,
+                                   InterpFilters interp_filters,
                                    const int subpel_x_q4, int x_step_q4,
                                    const int subpel_y_q4, int y_step_q4,
                                    int scaled, ConvolveParams *conv_params,
@@ -880,26 +863,11 @@
   (void)y_step_q4;
   (void)dst;
   (void)dst_stride;
-#if CONFIG_DUAL_FILTER
-  InterpFilterParams filter_params_x =
-      av1_get_interp_filter_params(interp_filter[1 + 2 * conv_params->ref]);
-  InterpFilterParams filter_params_y =
-      av1_get_interp_filter_params(interp_filter[0 + 2 * conv_params->ref]);
 
-#if USE_EXTRA_FILTER
-  if (filter_params_x.interp_filter == MULTITAP_SHARP &&
-      filter_params_y.interp_filter == MULTITAP_SHARP) {
-    // Avoid two directions both using 12-tap filter.
-    // This will reduce hardware implementation cost.
-    filter_params_y = av1_get_interp_filter_params(EIGHTTAP_SHARP);
-  }
-#endif
-#else
-  InterpFilterParams filter_params_x =
-      av1_get_interp_filter_params(*interp_filter);
-  InterpFilterParams filter_params_y =
-      av1_get_interp_filter_params(*interp_filter);
-#endif
+  InterpFilterParams filter_params_x, filter_params_y;
+  av1_get_convolve_filter_params(interp_filters, 1, &filter_params_x,
+                                 &filter_params_y);
+
   const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
   if (filter_params_y.taps < filter_params_x.taps) {
     uint16_t tr_src[(MAX_SB_SIZE + MAX_FILTER_TAP - 1) *
@@ -942,66 +910,6 @@
                              conv_params, bd);
   }
 }
-
-void av1_highbd_convolve_2d_facade_scale(const uint8_t *src8, int src_stride,
-                                         uint8_t *dst, int dst_stride, int w,
-                                         int h,
-                                         const InterpFilter *interp_filter,
-                                         const int subpel_x_qn, int x_step_qn,
-                                         const int subpel_y_qn, int y_step_qn,
-                                         ConvolveParams *conv_params, int bd) {
-  (void)dst;
-  (void)dst_stride;
-#if CONFIG_DUAL_FILTER
-  InterpFilterParams filter_params_x =
-      av1_get_interp_filter_params(interp_filter[1 + 2 * conv_params->ref]);
-  InterpFilterParams filter_params_y =
-      av1_get_interp_filter_params(interp_filter[0 + 2 * conv_params->ref]);
-
-#if USE_EXTRA_FILTER
-  if (filter_params_x.interp_filter == MULTITAP_SHARP &&
-      filter_params_y.interp_filter == MULTITAP_SHARP) {
-    // Avoid two directions both using 12-tap filter.
-    // This will reduce hardware implementation cost.
-    filter_params_y = av1_get_interp_filter_params(EIGHTTAP_SHARP);
-  }
-#endif
-#else
-  InterpFilterParams filter_params_x =
-      av1_get_interp_filter_params(*interp_filter);
-  InterpFilterParams filter_params_y =
-      av1_get_interp_filter_params(*interp_filter);
-#endif
-  const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
-  if (filter_params_y.taps < filter_params_x.taps) {
-    uint16_t tr_src[(MAX_SB_SIZE + MAX_FILTER_TAP - 1) *
-                    (MAX_SB_SIZE + MAX_FILTER_TAP - 1)];
-    int tr_src_stride = MAX_SB_SIZE + MAX_FILTER_TAP - 1;
-    CONV_BUF_TYPE tr_dst[MAX_SB_SIZE * MAX_SB_SIZE];
-    int tr_dst_stride = MAX_SB_SIZE;
-    int fo_vert = filter_params_y.taps / 2 - 1;
-    int fo_horiz = filter_params_x.taps / 2 - 1;
-
-    transpose_uint16(
-        tr_src, tr_src_stride, src - fo_vert * src_stride - fo_horiz,
-        src_stride, w + filter_params_x.taps - 1, h + filter_params_y.taps - 1);
-    transpose_int32(tr_dst, tr_dst_stride, conv_params->dst,
-                    conv_params->dst_stride, w, h);
-
-    // horizontal and vertical parameters are swapped because of the transpose
-    av1_highbd_convolve_2d_scale(
-        tr_src + fo_horiz * tr_src_stride + fo_vert, tr_src_stride, tr_dst,
-        tr_dst_stride, h, w, &filter_params_y, &filter_params_x, subpel_y_qn,
-        y_step_qn, subpel_x_qn, x_step_qn, conv_params, bd);
-    transpose_int32(conv_params->dst, conv_params->dst_stride, tr_dst,
-                    tr_dst_stride, h, w);
-  } else {
-    av1_highbd_convolve_2d_scale(
-        src, src_stride, conv_params->dst, conv_params->dst_stride, w, h,
-        &filter_params_x, &filter_params_y, subpel_x_qn, x_step_qn, subpel_y_qn,
-        y_step_qn, conv_params, bd);
-  }
-}
 #endif  // CONFIG_HIGHBITDEPTH
 
 #endif  // CONFIG_CONVOLVE_ROUND
@@ -1014,11 +922,7 @@
 
 static void convolve_helper(const uint8_t *src, int src_stride, uint8_t *dst,
                             int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                            const InterpFilter *interp_filter,
-#else
-                            const InterpFilter interp_filter,
-#endif
+                            const InterpFilters interp_filters,
                             const int subpel_x_q4, int x_step_q4,
                             const int subpel_y_q4, int y_step_q4,
                             ConvolveParams *conv_params,
@@ -1026,16 +930,11 @@
                             ConvolveFunc convolve_vert) {
   int ignore_horiz = x_step_q4 == SUBPEL_SHIFTS && subpel_x_q4 == 0;
   int ignore_vert = y_step_q4 == SUBPEL_SHIFTS && subpel_y_q4 == 0;
-#if CONFIG_DUAL_FILTER
-  InterpFilterParams filter_params_x =
-      av1_get_interp_filter_params(interp_filter[1 + 2 * conv_params->ref]);
-  InterpFilterParams filter_params_y =
-      av1_get_interp_filter_params(interp_filter[0 + 2 * conv_params->ref]);
-  InterpFilterParams filter_params;
-#else
-  InterpFilterParams filter_params =
-      av1_get_interp_filter_params(interp_filter);
-#endif
+
+  InterpFilterParams filter_params_x, filter_params_y;
+  av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x,
+                                 &filter_params_y);
+
   assert(conv_params->round == CONVOLVE_OPT_ROUND);
 
   assert(w <= MAX_BLOCK_WIDTH);
@@ -1046,18 +945,12 @@
   if (ignore_horiz && ignore_vert) {
     convolve_copy(src, src_stride, dst, dst_stride, w, h, conv_params);
   } else if (ignore_vert) {
-#if CONFIG_DUAL_FILTER
-    filter_params = filter_params_x;
-#endif
-    assert(filter_params.taps <= MAX_FILTER_TAP);
-    convolve_horiz(src, src_stride, dst, dst_stride, w, h, filter_params,
+    assert(filter_params_x.taps <= MAX_FILTER_TAP);
+    convolve_horiz(src, src_stride, dst, dst_stride, w, h, filter_params_x,
                    subpel_x_q4, x_step_q4, conv_params);
   } else if (ignore_horiz) {
-#if CONFIG_DUAL_FILTER
-    filter_params = filter_params_y;
-#endif
-    assert(filter_params.taps <= MAX_FILTER_TAP);
-    convolve_vert(src, src_stride, dst, dst_stride, w, h, filter_params,
+    assert(filter_params_y.taps <= MAX_FILTER_TAP);
+    convolve_vert(src, src_stride, dst, dst_stride, w, h, filter_params_y,
                   subpel_y_q4, y_step_q4, conv_params);
   } else {
     // temp's size is set to a 256 aligned value to facilitate SIMD
@@ -1068,12 +961,7 @@
     int max_intermediate_size = ((MAX_SB_SIZE * 2 + 16) + 16);
     int filter_size;
 #if CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
-    if (interp_filter[0 + 2 * conv_params->ref] == MULTITAP_SHARP &&
-        interp_filter[1 + 2 * conv_params->ref] == MULTITAP_SHARP) {
-      // Avoid two directions both using 12-tap filter.
-      // This will reduce hardware implementation cost.
-      filter_params_y = av1_get_interp_filter_params(EIGHTTAP_SHARP);
-    }
+    av1_convolve_filter_params_fixup_1212(&filter_params_x, &filter_params_y);
 
     // we do filter with fewer taps first to reduce hardware implementation
     // complexity
@@ -1084,22 +972,21 @@
       temp_conv_params.ref = 0;
       temp_conv_params.do_average = 0;
       temp_conv_params.round = CONVOLVE_OPT_ROUND;
-      filter_params = filter_params_y;
       filter_size = filter_params_x.taps;
       intermediate_width =
           (((w - 1) * x_step_q4 + subpel_x_q4) >> SUBPEL_BITS) + filter_size;
       assert(intermediate_width <= max_intermediate_size);
 
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_y.taps <= MAX_FILTER_TAP);
 
       convolve_vert(src - (filter_size / 2 - 1), src_stride, temp, temp_stride,
-                    intermediate_width, h, filter_params, subpel_y_q4,
+                    intermediate_width, h, filter_params_y, subpel_y_q4,
                     y_step_q4, &temp_conv_params);
 
-      filter_params = filter_params_x;
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_x.taps <= MAX_FILTER_TAP);
       convolve_horiz(temp + (filter_size / 2 - 1), temp_stride, dst, dst_stride,
-                     w, h, filter_params, subpel_x_q4, x_step_q4, conv_params);
+                     w, h, filter_params_x, subpel_x_q4, x_step_q4,
+                     conv_params);
     } else
 #endif  // CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
     {
@@ -1109,30 +996,22 @@
       temp_conv_params.ref = 0;
       temp_conv_params.do_average = 0;
       temp_conv_params.round = CONVOLVE_OPT_ROUND;
-#if CONFIG_DUAL_FILTER
-      filter_params = filter_params_x;
       filter_size = filter_params_y.taps;
-#else
-      filter_size = filter_params.taps;
-#endif
       intermediate_height =
           (((h - 1) * y_step_q4 + subpel_y_q4) >> SUBPEL_BITS) + filter_size;
       assert(intermediate_height <= max_intermediate_size);
       (void)max_intermediate_size;
 
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_x.taps <= MAX_FILTER_TAP);
 
       convolve_horiz(src - src_stride * (filter_size / 2 - 1), src_stride, temp,
-                     temp_stride, w, intermediate_height, filter_params,
+                     temp_stride, w, intermediate_height, filter_params_x,
                      subpel_x_q4, x_step_q4, &temp_conv_params);
 
-#if CONFIG_DUAL_FILTER
-      filter_params = filter_params_y;
-#endif
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_y.taps <= MAX_FILTER_TAP);
 
       convolve_vert(temp + temp_stride * (filter_size / 2 - 1), temp_stride,
-                    dst, dst_stride, w, h, filter_params, subpel_y_q4,
+                    dst, dst_stride, w, h, filter_params_y, subpel_y_q4,
                     y_step_q4, conv_params);
     }
   }
@@ -1140,11 +1019,7 @@
 
 static void convolve_scale_helper(const uint8_t *src, int src_stride,
                                   uint8_t *dst, int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                                  const InterpFilter *interp_filter,
-#else
-                                  const InterpFilter interp_filter,
-#endif
+                                  const InterpFilters interp_filters,
                                   const int subpel_x_qn, int x_step_qn,
                                   const int subpel_y_qn, int y_step_qn,
                                   ConvolveParams *conv_params,
@@ -1152,16 +1027,11 @@
                                   ConvolveFunc convolve_vert) {
   int ignore_horiz = x_step_qn == SCALE_SUBPEL_SHIFTS && subpel_x_qn == 0;
   int ignore_vert = y_step_qn == SCALE_SUBPEL_SHIFTS && subpel_y_qn == 0;
-#if CONFIG_DUAL_FILTER
-  InterpFilterParams filter_params_x =
-      av1_get_interp_filter_params(interp_filter[1 + 2 * conv_params->ref]);
-  InterpFilterParams filter_params_y =
-      av1_get_interp_filter_params(interp_filter[0 + 2 * conv_params->ref]);
-  InterpFilterParams filter_params;
-#else
-  InterpFilterParams filter_params =
-      av1_get_interp_filter_params(interp_filter);
-#endif
+
+  InterpFilterParams filter_params_x, filter_params_y;
+  av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x,
+                                 &filter_params_y);
+
   assert(conv_params->round == CONVOLVE_OPT_ROUND);
 
   assert(w <= MAX_BLOCK_WIDTH);
@@ -1172,18 +1042,12 @@
   if (ignore_horiz && ignore_vert) {
     convolve_copy(src, src_stride, dst, dst_stride, w, h, conv_params);
   } else if (ignore_vert) {
-#if CONFIG_DUAL_FILTER
-    filter_params = filter_params_x;
-#endif
-    assert(filter_params.taps <= MAX_FILTER_TAP);
-    convolve_horiz(src, src_stride, dst, dst_stride, w, h, filter_params,
+    assert(filter_params_x.taps <= MAX_FILTER_TAP);
+    convolve_horiz(src, src_stride, dst, dst_stride, w, h, filter_params_x,
                    subpel_x_qn, x_step_qn, conv_params);
   } else if (ignore_horiz) {
-#if CONFIG_DUAL_FILTER
-    filter_params = filter_params_y;
-#endif
-    assert(filter_params.taps <= MAX_FILTER_TAP);
-    convolve_vert(src, src_stride, dst, dst_stride, w, h, filter_params,
+    assert(filter_params_y.taps <= MAX_FILTER_TAP);
+    convolve_vert(src, src_stride, dst, dst_stride, w, h, filter_params_y,
                   subpel_y_qn, y_step_qn, conv_params);
   } else {
     // temp's size is set to a 256 aligned value to facilitate SIMD
@@ -1194,12 +1058,7 @@
     int max_intermediate_size = ((MAX_SB_SIZE * 2 + 16) + 16);
     int filter_size;
 #if CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
-    if (interp_filter[0 + 2 * conv_params->ref] == MULTITAP_SHARP &&
-        interp_filter[1 + 2 * conv_params->ref] == MULTITAP_SHARP) {
-      // Avoid two directions both using 12-tap filter.
-      // This will reduce hardware implementation cost.
-      filter_params_y = av1_get_interp_filter_params(EIGHTTAP_SHARP);
-    }
+    av1_convolve_filter_params_fixup_1212(&filter_params_x, &filter_params_y);
 
     // we do filter with fewer taps first to reduce hardware implementation
     // complexity
@@ -1210,23 +1069,22 @@
       temp_conv_params.ref = 0;
       temp_conv_params.do_average = 0;
       temp_conv_params.round = CONVOLVE_OPT_ROUND;
-      filter_params = filter_params_y;
       filter_size = filter_params_x.taps;
       intermediate_width =
           (((w - 1) * x_step_qn + subpel_x_qn) >> SCALE_SUBPEL_BITS) +
           filter_size;
       assert(intermediate_width <= max_intermediate_size);
 
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_y.taps <= MAX_FILTER_TAP);
 
       convolve_vert(src - (filter_size / 2 - 1), src_stride, temp, temp_stride,
-                    intermediate_width, h, filter_params, subpel_y_qn,
+                    intermediate_width, h, filter_params_y, subpel_y_qn,
                     y_step_qn, &temp_conv_params);
 
-      filter_params = filter_params_x;
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_x.taps <= MAX_FILTER_TAP);
       convolve_horiz(temp + (filter_size / 2 - 1), temp_stride, dst, dst_stride,
-                     w, h, filter_params, subpel_x_qn, x_step_qn, conv_params);
+                     w, h, filter_params_x, subpel_x_qn, x_step_qn,
+                     conv_params);
     } else {
 #endif  // CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
       int intermediate_height;
@@ -1235,31 +1093,23 @@
       temp_conv_params.ref = 0;
       temp_conv_params.do_average = 0;
       temp_conv_params.round = CONVOLVE_OPT_ROUND;
-#if CONFIG_DUAL_FILTER
-      filter_params = filter_params_x;
       filter_size = filter_params_y.taps;
-#else
-    filter_size = filter_params.taps;
-#endif
       intermediate_height =
           (((h - 1) * y_step_qn + subpel_y_qn) >> SCALE_SUBPEL_BITS) +
           filter_size;
       assert(intermediate_height <= max_intermediate_size);
       (void)max_intermediate_size;
 
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_x.taps <= MAX_FILTER_TAP);
 
       convolve_horiz(src - src_stride * (filter_size / 2 - 1), src_stride, temp,
-                     temp_stride, w, intermediate_height, filter_params,
+                     temp_stride, w, intermediate_height, filter_params_x,
                      subpel_x_qn, x_step_qn, &temp_conv_params);
 
-#if CONFIG_DUAL_FILTER
-      filter_params = filter_params_y;
-#endif
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_y.taps <= MAX_FILTER_TAP);
 
       convolve_vert(temp + temp_stride * (filter_size / 2 - 1), temp_stride,
-                    dst, dst_stride, w, h, filter_params, subpel_y_qn,
+                    dst, dst_stride, w, h, filter_params_y, subpel_y_qn,
                     y_step_qn, conv_params);
 #if CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
     }
@@ -1268,44 +1118,29 @@
 }
 
 void av1_convolve(const uint8_t *src, int src_stride, uint8_t *dst,
-                  int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                  const InterpFilter *interp_filter,
-#else
-                  const InterpFilter interp_filter,
-#endif
+                  int dst_stride, int w, int h, InterpFilters interp_filters,
                   const int subpel_x_q4, int x_step_q4, const int subpel_y_q4,
                   int y_step_q4, ConvolveParams *conv_params) {
-  convolve_helper(src, src_stride, dst, dst_stride, w, h, interp_filter,
+  convolve_helper(src, src_stride, dst, dst_stride, w, h, interp_filters,
                   subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, conv_params,
                   av1_convolve_horiz_facade, av1_convolve_vert_facade);
 }
 
 void av1_convolve_c(const uint8_t *src, int src_stride, uint8_t *dst,
-                    int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                    const InterpFilter *interp_filter,
-#else
-                    const InterpFilter interp_filter,
-#endif
+                    int dst_stride, int w, int h, InterpFilters interp_filters,
                     const int subpel_x_q4, int x_step_q4, const int subpel_y_q4,
                     int y_step_q4, ConvolveParams *conv_params) {
-  convolve_helper(src, src_stride, dst, dst_stride, w, h, interp_filter,
+  convolve_helper(src, src_stride, dst, dst_stride, w, h, interp_filters,
                   subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, conv_params,
                   av1_convolve_horiz_facade_c, av1_convolve_vert_facade_c);
 }
 
 void av1_convolve_scale(const uint8_t *src, int src_stride, uint8_t *dst,
                         int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                        const InterpFilter *interp_filter,
-#else
-                        const InterpFilter interp_filter,
-#endif
-                        const int subpel_x_qn, int x_step_qn,
-                        const int subpel_y_qn, int y_step_qn,
+                        InterpFilters interp_filters, const int subpel_x_qn,
+                        int x_step_qn, const int subpel_y_qn, int y_step_qn,
                         ConvolveParams *conv_params) {
-  convolve_scale_helper(src, src_stride, dst, dst_stride, w, h, interp_filter,
+  convolve_scale_helper(src, src_stride, dst, dst_stride, w, h, interp_filters,
                         subpel_x_qn, x_step_qn, subpel_y_qn, y_step_qn,
                         conv_params, av1_convolve_horiz_facade_scale,
                         av1_convolve_vert_facade_scale);
@@ -1567,14 +1402,9 @@
 
 void av1_highbd_convolve(const uint8_t *src8, int src_stride, uint8_t *dst8,
                          int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                         const InterpFilter *interp_filter,
-#else
-                         const InterpFilter interp_filter,
-#endif
-                         const int subpel_x_q4, int x_step_q4,
-                         const int subpel_y_q4, int y_step_q4, int ref_idx,
-                         int bd) {
+                         InterpFilters interp_filters, const int subpel_x_q4,
+                         int x_step_q4, const int subpel_y_q4, int y_step_q4,
+                         int ref_idx, int bd) {
   uint16_t *src = CONVERT_TO_SHORTPTR(src8);
   uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
   int ignore_horiz = x_step_q4 == SUBPEL_SHIFTS && subpel_x_q4 == 0;
@@ -1587,27 +1417,20 @@
 
   if (ignore_horiz && ignore_vert) {
     highbd_convolve_copy(src, src_stride, dst, dst_stride, w, h, ref_idx, bd);
-  } else if (ignore_vert) {
-#if CONFIG_DUAL_FILTER
-    InterpFilterParams filter_params =
-        av1_get_interp_filter_params(interp_filter[1 + 2 * ref_idx]);
-#else
-    InterpFilterParams filter_params =
-        av1_get_interp_filter_params(interp_filter);
-#endif
+    return;
+  }
+
+  InterpFilterParams filter_params_x, filter_params_y;
+  av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x,
+                                 &filter_params_y);
+
+  if (ignore_vert) {
     av1_highbd_convolve_horiz_facade(src8, src_stride, dst8, dst_stride, w, h,
-                                     filter_params, subpel_x_q4, x_step_q4,
+                                     filter_params_x, subpel_x_q4, x_step_q4,
                                      ref_idx, bd);
   } else if (ignore_horiz) {
-#if CONFIG_DUAL_FILTER
-    InterpFilterParams filter_params =
-        av1_get_interp_filter_params(interp_filter[0 + 2 * ref_idx]);
-#else
-    InterpFilterParams filter_params =
-        av1_get_interp_filter_params(interp_filter);
-#endif
     av1_highbd_convolve_vert_facade(src8, src_stride, dst8, dst_stride, w, h,
-                                    filter_params, subpel_y_q4, y_step_q4,
+                                    filter_params_y, subpel_y_q4, y_step_q4,
                                     ref_idx, bd);
   } else {
     // temp's size is set to a 256 aligned value to facilitate SIMD
@@ -1618,54 +1441,37 @@
     uint8_t *temp8 = CONVERT_TO_BYTEPTR(temp);
     int max_intermediate_size = ((MAX_SB_SIZE * 2 + 16) + 16);
     int filter_size;
-    InterpFilterParams filter_params;
-#if CONFIG_DUAL_FILTER
-    InterpFilterParams filter_params_x =
-        av1_get_interp_filter_params(interp_filter[1 + 2 * ref_idx]);
-    InterpFilterParams filter_params_y =
-        av1_get_interp_filter_params(interp_filter[0 + 2 * ref_idx]);
-#endif
 
 #if CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
-    if (interp_filter[0 + 2 * ref_idx] == MULTITAP_SHARP &&
-        interp_filter[1 + 2 * ref_idx] == MULTITAP_SHARP) {
-      // Avoid two directions both using 12-tap filter.
-      // This will reduce hardware implementation cost.
-      filter_params_y = av1_get_interp_filter_params(EIGHTTAP_SHARP);
-    }
+    av1_convolve_filter_params_fixup_1212(&filter_params_x, &filter_params_y);
+
     if (filter_params_y.taps < filter_params_x.taps) {
       int intermediate_width;
       int temp_stride = max_intermediate_size;
-      filter_params = filter_params_y;
       filter_size = filter_params_x.taps;
       intermediate_width =
           (((w - 1) * x_step_q4 + subpel_x_q4) >> SUBPEL_BITS) + filter_size;
       assert(intermediate_width <= max_intermediate_size);
 
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_y.taps <= MAX_FILTER_TAP);
 
-      av1_highbd_convolve_vert_facade(
-          src8 - (filter_size / 2 - 1), src_stride, temp8, temp_stride,
-          intermediate_width, h, filter_params, subpel_y_q4, y_step_q4, 0, bd);
+      av1_highbd_convolve_vert_facade(src8 - (filter_size / 2 - 1), src_stride,
+                                      temp8, temp_stride, intermediate_width, h,
+                                      filter_params_y, subpel_y_q4, y_step_q4,
+                                      0, bd);
 
-      filter_params = filter_params_x;
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_x.taps <= MAX_FILTER_TAP);
 
       av1_highbd_convolve_horiz_facade(
           temp8 + (filter_size / 2 - 1), temp_stride, dst8, dst_stride, w, h,
-          filter_params, subpel_x_q4, x_step_q4, ref_idx, bd);
+          filter_params_x, subpel_x_q4, x_step_q4, ref_idx, bd);
     } else
 #endif  // CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
     {
       int intermediate_height;
       int temp_stride = MAX_SB_SIZE;
-#if CONFIG_DUAL_FILTER
-      filter_params = filter_params_x;
       filter_size = filter_params_y.taps;
-#else
-      filter_params = av1_get_interp_filter_params(interp_filter);
-      filter_size = filter_params.taps;
-#endif
+
       intermediate_height =
           (((h - 1) * y_step_q4 + subpel_y_q4) >> SUBPEL_BITS) + filter_size;
       assert(intermediate_height <= max_intermediate_size);
@@ -1673,29 +1479,23 @@
 
       av1_highbd_convolve_horiz_facade(
           src8 - src_stride * (filter_size / 2 - 1), src_stride, temp8,
-          temp_stride, w, intermediate_height, filter_params, subpel_x_q4,
+          temp_stride, w, intermediate_height, filter_params_x, subpel_x_q4,
           x_step_q4, 0, bd);
 
-#if CONFIG_DUAL_FILTER
-      filter_params = filter_params_y;
-#endif
-      filter_size = filter_params.taps;
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      filter_size = filter_params_y.taps;
+      assert(filter_params_y.taps <= MAX_FILTER_TAP);
 
       av1_highbd_convolve_vert_facade(
           temp8 + temp_stride * (filter_size / 2 - 1), temp_stride, dst8,
-          dst_stride, w, h, filter_params, subpel_y_q4, y_step_q4, ref_idx, bd);
+          dst_stride, w, h, filter_params_y, subpel_y_q4, y_step_q4, ref_idx,
+          bd);
     }
   }
 }
 
 void av1_highbd_convolve_scale(const uint8_t *src8, int src_stride,
                                uint8_t *dst8, int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                               const InterpFilter *interp_filter,
-#else
-                               const InterpFilter interp_filter,
-#endif
+                               InterpFilters interp_filters,
                                const int subpel_x_qn, int x_step_qn,
                                const int subpel_y_qn, int y_step_qn,
                                int ref_idx, int bd) {
@@ -1711,27 +1511,20 @@
 
   if (ignore_horiz && ignore_vert) {
     highbd_convolve_copy(src, src_stride, dst, dst_stride, w, h, ref_idx, bd);
-  } else if (ignore_vert) {
-#if CONFIG_DUAL_FILTER
-    InterpFilterParams filter_params =
-        av1_get_interp_filter_params(interp_filter[1 + 2 * ref_idx]);
-#else
-    InterpFilterParams filter_params =
-        av1_get_interp_filter_params(interp_filter);
-#endif
+    return;
+  }
+
+  InterpFilterParams filter_params_x, filter_params_y;
+  av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x,
+                                 &filter_params_y);
+
+  if (ignore_vert) {
     av1_highbd_convolve_horiz_facade_scale(src8, src_stride, dst8, dst_stride,
-                                           w, h, filter_params, subpel_x_qn,
+                                           w, h, filter_params_x, subpel_x_qn,
                                            x_step_qn, ref_idx, bd);
   } else if (ignore_horiz) {
-#if CONFIG_DUAL_FILTER
-    InterpFilterParams filter_params =
-        av1_get_interp_filter_params(interp_filter[0 + 2 * ref_idx]);
-#else
-    InterpFilterParams filter_params =
-        av1_get_interp_filter_params(interp_filter);
-#endif
     av1_highbd_convolve_vert_facade_scale(src8, src_stride, dst8, dst_stride, w,
-                                          h, filter_params, subpel_y_qn,
+                                          h, filter_params_y, subpel_y_qn,
                                           y_step_qn, ref_idx, bd);
   } else {
     // temp's size is set to a 256 aligned value to facilitate SIMD
@@ -1742,54 +1535,36 @@
     uint8_t *temp8 = CONVERT_TO_BYTEPTR(temp);
     int max_intermediate_size = ((MAX_SB_SIZE * 2 + 16) + 16);
     int filter_size;
-    InterpFilterParams filter_params;
-#if CONFIG_DUAL_FILTER
-    InterpFilterParams filter_params_x =
-        av1_get_interp_filter_params(interp_filter[1 + 2 * ref_idx]);
-    InterpFilterParams filter_params_y =
-        av1_get_interp_filter_params(interp_filter[0 + 2 * ref_idx]);
-#endif
 
 #if CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
-    if (interp_filter[0 + 2 * ref_idx] == MULTITAP_SHARP &&
-        interp_filter[1 + 2 * ref_idx] == MULTITAP_SHARP) {
-      // Avoid two directions both using 12-tap filter.
-      // This will reduce hardware implementation cost.
-      filter_params_y = av1_get_interp_filter_params(EIGHTTAP_SHARP);
-    }
+    av1_convolve_filter_params_fixup_1212(&filter_params_x, &filter_params_y);
+
     if (filter_params_y.taps < filter_params_x.taps) {
       int intermediate_width;
       int temp_stride = max_intermediate_size;
-      filter_params = filter_params_y;
       filter_size = filter_params_x.taps;
       intermediate_width =
           (((w - 1) * x_step_qn + subpel_x_qn) >> SCALE_SUBPEL_BITS) +
           filter_size;
       assert(intermediate_width <= max_intermediate_size);
 
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_y.taps <= MAX_FILTER_TAP);
 
       av1_highbd_convolve_vert_facade_scale(
           src8 - (filter_size / 2 - 1), src_stride, temp8, temp_stride,
-          intermediate_width, h, filter_params, subpel_y_qn, y_step_qn, 0, bd);
+          intermediate_width, h, filter_params_y, subpel_y_qn, y_step_qn, 0,
+          bd);
 
-      filter_params = filter_params_x;
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      assert(filter_params_x.taps <= MAX_FILTER_TAP);
 
       av1_highbd_convolve_horiz_facade_scale(
           temp8 + (filter_size / 2 - 1), temp_stride, dst8, dst_stride, w, h,
-          filter_params, subpel_x_qn, x_step_qn, ref_idx, bd);
+          filter_params_x, subpel_x_qn, x_step_qn, ref_idx, bd);
     } else {
 #endif  // CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
       int intermediate_height;
       int temp_stride = MAX_SB_SIZE;
-#if CONFIG_DUAL_FILTER
-      filter_params = filter_params_x;
       filter_size = filter_params_y.taps;
-#else
-    filter_params = av1_get_interp_filter_params(interp_filter);
-    filter_size = filter_params.taps;
-#endif
       intermediate_height =
           (((h - 1) * y_step_qn + subpel_y_qn) >> SCALE_SUBPEL_BITS) +
           filter_size;
@@ -1798,18 +1573,16 @@
 
       av1_highbd_convolve_horiz_facade_scale(
           src8 - src_stride * (filter_size / 2 - 1), src_stride, temp8,
-          temp_stride, w, intermediate_height, filter_params, subpel_x_qn,
+          temp_stride, w, intermediate_height, filter_params_x, subpel_x_qn,
           x_step_qn, 0, bd);
 
-#if CONFIG_DUAL_FILTER
-      filter_params = filter_params_y;
-#endif
-      filter_size = filter_params.taps;
-      assert(filter_params.taps <= MAX_FILTER_TAP);
+      filter_size = filter_params_y.taps;
+      assert(filter_params_y.taps <= MAX_FILTER_TAP);
 
       av1_highbd_convolve_vert_facade_scale(
           temp8 + temp_stride * (filter_size / 2 - 1), temp_stride, dst8,
-          dst_stride, w, h, filter_params, subpel_y_qn, y_step_qn, ref_idx, bd);
+          dst_stride, w, h, filter_params_y, subpel_y_qn, y_step_qn, ref_idx,
+          bd);
 #if CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
     }
 #endif  // CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
diff --git a/av1/common/convolve.h b/av1/common/convolve.h
index 99ef1aed..c43f649 100644
--- a/av1/common/convolve.h
+++ b/av1/common/convolve.h
@@ -47,15 +47,49 @@
   conv_params.do_post_rounding = 0;
   return conv_params;
 }
+
+#if CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
+static INLINE void av1_convolve_filter_params_fixup_1212(
+    const InterpFilterParams *params_x, InterpFilterParams *params_y) {
+  if (params_x->interp_filter == MULTITAP_SHARP &&
+      params_y->interp_filter == MULTITAP_SHARP) {
+    // Avoid two directions both using 12-tap filter.
+    // This will reduce hardware implementation cost.
+    *params_y = av1_get_interp_filter_params(EIGHTTAP_SHARP);
+  }
+}
+#endif
+
+static INLINE void av1_get_convolve_filter_params(
+    InterpFilters interp_filters, int avoid_1212, InterpFilterParams *params_x,
+    InterpFilterParams *params_y) {
+#if CONFIG_DUAL_FILTER
+  InterpFilter filter_x = av1_extract_interp_filter(interp_filters, 1);
+  InterpFilter filter_y = av1_extract_interp_filter(interp_filters, 0);
+#else
+  InterpFilter filter_x = av1_extract_interp_filter(interp_filters, 0);
+  InterpFilter filter_y = av1_extract_interp_filter(interp_filters, 0);
+#endif
+
+  *params_x = av1_get_interp_filter_params(filter_x);
+  *params_y = av1_get_interp_filter_params(filter_y);
+
+  if (avoid_1212) {
+#if CONFIG_DUAL_FILTER && USE_EXTRA_FILTER
+    convolve_filter_params_fixup_1212(params_x, params_y);
+#endif
+  }
+}
+
 struct AV1Common;
 void av1_convolve_init(struct AV1Common *cm);
+
 #if CONFIG_CONVOLVE_ROUND
 void av1_convolve_2d_facade(const uint8_t *src, int src_stride, uint8_t *dst,
                             int dst_stride, int w, int h,
-                            const InterpFilter *interp_filter,
-                            const int subpel_x_q4, int x_step_q4,
-                            const int subpel_y_q4, int y_step_q4, int scaled,
-                            ConvolveParams *conv_params);
+                            InterpFilters interp_filters, const int subpel_x_q4,
+                            int x_step_q4, const int subpel_y_q4, int y_step_q4,
+                            int scaled, ConvolveParams *conv_params);
 
 static INLINE ConvolveParams get_conv_params_no_round(int ref, int do_average,
                                                       int plane, int32_t *dst,
@@ -80,7 +114,7 @@
 #if CONFIG_HIGHBITDEPTH
 void av1_highbd_convolve_2d_facade(const uint8_t *src8, int src_stride,
                                    uint8_t *dst, int dst_stride, int w, int h,
-                                   const InterpFilter *interp_filter,
+                                   InterpFilters interp_filters,
                                    const int subpel_x_q4, int x_step_q4,
                                    const int subpel_y_q4, int y_step_q4,
                                    int scaled, ConvolveParams *conv_params,
@@ -89,55 +123,33 @@
 #endif  // CONFIG_CONVOLVE_ROUND
 
 void av1_convolve(const uint8_t *src, int src_stride, uint8_t *dst,
-                  int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                  const InterpFilter *interp_filter,
-#else
-                  const InterpFilter interp_filter,
-#endif
+                  int dst_stride, int w, int h, InterpFilters interp_filters,
                   const int subpel_x, int xstep, const int subpel_y, int ystep,
                   ConvolveParams *conv_params);
 
 void av1_convolve_c(const uint8_t *src, int src_stride, uint8_t *dst,
-                    int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                    const InterpFilter *interp_filter,
-#else
-                    const InterpFilter interp_filter,
-#endif
+                    int dst_stride, int w, int h, InterpFilters interp_filters,
                     const int subpel_x, int xstep, const int subpel_y,
                     int ystep, ConvolveParams *conv_params);
 
 void av1_convolve_scale(const uint8_t *src, int src_stride, uint8_t *dst,
                         int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                        const InterpFilter *interp_filter,
-#else
-                        const InterpFilter interp_filter,
-#endif
-                        const int subpel_x, int xstep, const int subpel_y,
-                        int ystep, ConvolveParams *conv_params);
+                        InterpFilters interp_filters, const int subpel_x,
+                        int xstep, const int subpel_y, int ystep,
+                        ConvolveParams *conv_params);
 
 #if CONFIG_HIGHBITDEPTH
 void av1_highbd_convolve(const uint8_t *src, int src_stride, uint8_t *dst,
                          int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                         const InterpFilter *interp_filter,
-#else
-                         const InterpFilter interp_filter,
-#endif
-                         const int subpel_x, int xstep, const int subpel_y,
-                         int ystep, int avg, int bd);
+                         InterpFilters interp_filters, const int subpel_x,
+                         int xstep, const int subpel_y, int ystep, int avg,
+                         int bd);
 
 void av1_highbd_convolve_scale(const uint8_t *src, int src_stride, uint8_t *dst,
                                int dst_stride, int w, int h,
-#if CONFIG_DUAL_FILTER
-                               const InterpFilter *interp_filter,
-#else
-                               const InterpFilter interp_filter,
-#endif  // CONFIG_DUAL_FILTER
-                               const int subpel_x, int xstep,
-                               const int subpel_y, int ystep, int avg, int bd);
+                               InterpFilters interp_filters, const int subpel_x,
+                               int xstep, const int subpel_y, int ystep,
+                               int avg, int bd);
 #endif  // CONFIG_HIGHBITDEPTH
 
 #ifdef __cplusplus
diff --git a/av1/common/filter.h b/av1/common/filter.h
index e2b1663..01b340f 100644
--- a/av1/common/filter.h
+++ b/av1/common/filter.h
@@ -12,6 +12,8 @@
 #ifndef AV1_COMMON_FILTER_H_
 #define AV1_COMMON_FILTER_H_
 
+#include <assert.h>
+
 #include "./aom_config.h"
 #include "aom/aom_integer.h"
 #include "aom_dsp/aom_filter.h"
@@ -51,6 +53,46 @@
 #endif
 } InterpFilter;
 
+// With CONFIG_DUAL_FILTER, pack two InterpFilter's into a uint32_t: since
+// there are at most 10 filters, we can use 16 bits for each and have more than
+// enough space. This reduces argument passing and unifies the operation of
+// setting a (pair of) filters.
+//
+// Without CONFIG_DUAL_FILTER,
+#if CONFIG_DUAL_FILTER
+typedef uint32_t InterpFilters;
+static INLINE InterpFilter av1_extract_interp_filter(InterpFilters filters,
+                                                     int x_filter) {
+  return (InterpFilter)((filters >> (x_filter ? 16 : 0)) & 0xffff);
+}
+
+static INLINE InterpFilters av1_make_interp_filters(InterpFilter y_filter,
+                                                    InterpFilter x_filter) {
+  uint16_t y16 = y_filter & 0xffff;
+  uint16_t x16 = x_filter & 0xffff;
+  return y16 | ((uint32_t)x16 << 16);
+}
+
+static INLINE InterpFilters av1_broadcast_interp_filter(InterpFilter filter) {
+  return av1_make_interp_filters(filter, filter);
+}
+#else
+typedef InterpFilter InterpFilters;
+static INLINE InterpFilter av1_extract_interp_filter(InterpFilters filters,
+                                                     int x_filter) {
+  assert(!x_filter);
+  return filters;
+}
+
+static INLINE InterpFilters av1_broadcast_interp_filter(InterpFilter filter) {
+  return filter;
+}
+#endif
+
+static INLINE InterpFilter av1_unswitchable_filter(InterpFilter filter) {
+  return filter == SWITCHABLE ? EIGHTTAP_REGULAR : filter;
+}
+
 #if USE_EXTRA_FILTER
 #define LOG_SWITCHABLE_FILTERS \
   3 /* (1 << LOG_SWITCHABLE_FILTERS) > SWITCHABLE_FILTERS */
diff --git a/av1/common/pred_common.c b/av1/common/pred_common.c
index b8dda61..b68bc34 100644
--- a/av1/common/pred_common.c
+++ b/av1/common/pred_common.c
@@ -22,19 +22,16 @@
 static InterpFilter get_ref_filter_type(const MODE_INFO *mi,
                                         const MACROBLOCKD *xd, int dir,
                                         MV_REFERENCE_FRAME ref_frame) {
-  InterpFilter ref_type = SWITCHABLE_FILTERS;
   const MB_MODE_INFO *ref_mbmi = &mi->mbmi;
   int use_subpel[2] = {
     has_subpel_mv_component(mi, xd, dir),
     has_subpel_mv_component(mi, xd, dir + 2),
   };
 
-  if (ref_mbmi->ref_frame[0] == ref_frame && use_subpel[0])
-    ref_type = ref_mbmi->interp_filter[(dir & 0x01)];
-  else if (ref_mbmi->ref_frame[1] == ref_frame && use_subpel[1])
-    ref_type = ref_mbmi->interp_filter[(dir & 0x01) + 2];
-
-  return ref_type;
+  return (((ref_mbmi->ref_frame[0] == ref_frame && use_subpel[0]) ||
+           (ref_mbmi->ref_frame[1] == ref_frame && use_subpel[1]))
+              ? av1_extract_interp_filter(ref_mbmi->interp_filters, dir & 0x01)
+              : SWITCHABLE_FILTERS);
 }
 
 int av1_get_pred_context_switchable_interp(const MACROBLOCKD *xd, int dir) {
@@ -79,13 +76,15 @@
   // left of the entries corresponding to real macroblocks.
   // The prediction flags in these dummy entries are initialized to 0.
   const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
-  const int left_type = xd->left_available && is_inter_block(left_mbmi)
-                            ? left_mbmi->interp_filter
-                            : SWITCHABLE_FILTERS;
+  const int left_type =
+      xd->left_available && is_inter_block(left_mbmi)
+          ? av1_extract_interp_filter(left_mbmi->interp_filters, 0)
+          : SWITCHABLE_FILTERS;
   const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
-  const int above_type = xd->up_available && is_inter_block(above_mbmi)
-                             ? above_mbmi->interp_filter
-                             : SWITCHABLE_FILTERS;
+  const int above_type =
+      xd->up_available && is_inter_block(above_mbmi)
+          ? av1_extract_interp_filter(above_mbmi->interp_filters, 0)
+          : SWITCHABLE_FILTERS;
 
   if (left_type == above_type) {
     return left_type;
@@ -110,11 +109,7 @@
   if (ref_mbmi->sb_type >= BLOCK_8X8) {
     const PREDICTION_MODE mode = ref_mbmi->mode;
     if (is_inter_block(ref_mbmi)) {
-#if CONFIG_DUAL_FILTER
-      switch (ref_mbmi->interp_filter[0]) {
-#else
-      switch (ref_mbmi->interp_filter) {
-#endif
+      switch (av1_extract_interp_filter(ref_mbmi->interp_filters, 0)) {
         case EIGHTTAP_REGULAR: ref_type = INTRA_FILTER_8TAP; break;
         case EIGHTTAP_SMOOTH: ref_type = INTRA_FILTER_8TAP_SMOOTH; break;
         case MULTITAP_SHARP: ref_type = INTRA_FILTER_8TAP_SHARP; break;
diff --git a/av1/common/reconinter.c b/av1/common/reconinter.c
index 953570d..0a6cb49 100644
--- a/av1/common/reconinter.c
+++ b/av1/common/reconinter.c
@@ -130,12 +130,7 @@
 static INLINE void av1_make_inter_predictor(
     const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride,
     const int subpel_x, const int subpel_y, const struct scale_factors *sf,
-    int w, int h, ConvolveParams *conv_params,
-#if CONFIG_DUAL_FILTER
-    const InterpFilter *interp_filter,
-#else
-    const InterpFilter interp_filter,
-#endif
+    int w, int h, ConvolveParams *conv_params, InterpFilters interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
     const WarpTypesAllowed *warp_types, int p_col, int p_row, int plane,
     int ref,
@@ -202,13 +197,13 @@
 #if CONFIG_HIGHBITDEPTH
   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
     highbd_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y,
-                           sf, w, h, conv_params, interp_filter, xs, ys,
+                           sf, w, h, conv_params, interp_filters, xs, ys,
                            xd->bd);
     return;
   }
 #endif  // CONFIG_HIGHBITDEPTH
   inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, sf, w,
-                  h, conv_params, interp_filter, xs, ys);
+                  h, conv_params, interp_filters, xs, ys);
 }
 
 #define NSMOOTHERS 1
@@ -946,26 +941,19 @@
 #endif  // CONFIG_HIGHBITDEPTH
 #endif  // CONFIG_SUPERTX
 
-void av1_make_masked_inter_predictor(const uint8_t *pre, int pre_stride,
-                                     uint8_t *dst, int dst_stride,
-                                     const int subpel_x, const int subpel_y,
-                                     const struct scale_factors *sf, int w,
-                                     int h, ConvolveParams *conv_params,
-#if CONFIG_DUAL_FILTER
-                                     const InterpFilter *interp_filter,
-#else
-                                     const InterpFilter interp_filter,
-#endif
-                                     int xs, int ys,
+void av1_make_masked_inter_predictor(
+    const uint8_t *pre, int pre_stride, uint8_t *dst, int dst_stride,
+    const int subpel_x, const int subpel_y, const struct scale_factors *sf,
+    int w, int h, ConvolveParams *conv_params, InterpFilters interp_filters,
+    int xs, int ys,
 #if CONFIG_SUPERTX
-                                     int wedge_offset_x, int wedge_offset_y,
+    int wedge_offset_x, int wedge_offset_y,
 #endif  // CONFIG_SUPERTX
-                                     int plane,
+    int plane,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
-                                     const WarpTypesAllowed *warp_types,
-                                     int p_col, int p_row, int ref,
+    const WarpTypesAllowed *warp_types, int p_col, int p_row, int ref,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
-                                     MACROBLOCKD *xd) {
+    MACROBLOCKD *xd) {
   const MODE_INFO *mi = xd->mi[0];
 
   const INTERINTER_COMPOUND_DATA comp_data = {
@@ -1024,7 +1012,7 @@
 
   // This will generate a prediction in tmp_buf for the second reference
   av1_make_inter_predictor(pre, pre_stride, tmp_dst, MAX_SB_SIZE, subpel_x,
-                           subpel_y, sf, w, h, conv_params, interp_filter,
+                           subpel_y, sf, w, h, conv_params, interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                            warp_types, p_col, p_row, plane, ref,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -1103,7 +1091,6 @@
 #endif  // CONFIG_HIGHBITDEPTH
       build_masked_compound(dst, dst_stride, dst, dst_stride, tmp_dst,
                             MAX_SB_SIZE, &comp_data, mi->mbmi.sb_type, h, w);
-
 #if CONFIG_CONVOLVE_ROUND
   }
 #endif  // CONFIG_CONVOLVE_ROUND
@@ -1121,11 +1108,7 @@
 void av1_highbd_build_inter_predictor(
     const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride,
     const MV *src_mv, const struct scale_factors *sf, int w, int h, int ref,
-#if CONFIG_DUAL_FILTER
-    const InterpFilter *interp_filter,
-#else
-    const InterpFilter interp_filter,
-#endif
+    InterpFilters interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
     const WarpTypesAllowed *warp_types, int p_col, int p_row,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -1145,7 +1128,7 @@
          (mv.col >> SCALE_SUBPEL_BITS);
 
   av1_make_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y,
-                           sf, w, h, &conv_params, interp_filter,
+                           sf, w, h, &conv_params, interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                            warp_types, p_col, p_row, plane, ref,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -1160,11 +1143,7 @@
                                int dst_stride, const MV *src_mv,
                                const struct scale_factors *sf, int w, int h,
                                ConvolveParams *conv_params,
-#if CONFIG_DUAL_FILTER
-                               const InterpFilter *interp_filter,
-#else
-                               const InterpFilter interp_filter,
-#endif
+                               InterpFilters interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                                const WarpTypesAllowed *warp_types, int p_col,
                                int p_row, int plane, int ref,
@@ -1184,7 +1163,7 @@
          (mv.col >> SCALE_SUBPEL_BITS);
 
   av1_make_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y,
-                           sf, w, h, conv_params, interp_filter,
+                           sf, w, h, conv_params, interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                            warp_types, p_col, p_row, plane, ref,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -1391,7 +1370,7 @@
           if (ref && is_masked_compound_type(mi->mbmi.interinter_compound_type))
             av1_make_masked_inter_predictor(
                 pre, pre_buf->stride, dst, dst_buf->stride, subpel_x, subpel_y,
-                sf, b4_w, b4_h, &conv_params, mi->mbmi.interp_filter, xs, ys,
+                sf, b4_w, b4_h, &conv_params, mi->mbmi.interp_filters, xs, ys,
 #if CONFIG_SUPERTX
                 wedge_offset_x, wedge_offset_y,
 #endif  // CONFIG_SUPERTX
@@ -1404,7 +1383,7 @@
           else
             av1_make_inter_predictor(
                 pre, pre_buf->stride, dst, dst_buf->stride, subpel_x, subpel_y,
-                sf, b4_w, b4_h, &conv_params, this_mbmi->interp_filter,
+                sf, b4_w, b4_h, &conv_params, this_mbmi->interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                 &warp_types, (mi_x >> pd->subsampling_x) + x,
                 (mi_y >> pd->subsampling_y) + y, plane, ref,
@@ -1585,7 +1564,7 @@
         av1_make_masked_inter_predictor(
             pre[ref], pre_buf->stride, dst, dst_buf->stride,
             subpel_params[ref].subpel_x, subpel_params[ref].subpel_y, sf, w, h,
-            &conv_params, mi->mbmi.interp_filter, subpel_params[ref].xs,
+            &conv_params, mi->mbmi.interp_filters, subpel_params[ref].xs,
             subpel_params[ref].ys,
 #if CONFIG_SUPERTX
             wedge_offset_x, wedge_offset_y,
@@ -1600,7 +1579,7 @@
         av1_make_inter_predictor(
             pre[ref], pre_buf->stride, dst, dst_buf->stride,
             subpel_params[ref].subpel_x, subpel_params[ref].subpel_y, sf, w, h,
-            &conv_params, mi->mbmi.interp_filter,
+            &conv_params, mi->mbmi.interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
             &warp_types, (mi_x >> pd->subsampling_x) + x,
             (mi_y >> pd->subsampling_y) + y, plane, ref,
@@ -3267,7 +3246,7 @@
 
   av1_make_inter_predictor(pre, pre_buf->stride, dst, ext_dst_stride, subpel_x,
                            subpel_y, sf, w, h, &conv_params,
-                           mi->mbmi.interp_filter,
+                           mi->mbmi.interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                            &warp_types, (mi_x >> pd->subsampling_x) + x,
                            (mi_y >> pd->subsampling_y) + y, plane, ref,
diff --git a/av1/common/reconinter.h b/av1/common/reconinter.h
index 26a48fd..fd69f9d 100644
--- a/av1/common/reconinter.h
+++ b/av1/common/reconinter.h
@@ -40,27 +40,8 @@
                                    uint8_t *dst, int dst_stride, int subpel_x,
                                    int subpel_y, const struct scale_factors *sf,
                                    int w, int h, ConvolveParams *conv_params,
-#if CONFIG_DUAL_FILTER
-                                   const InterpFilter *interp_filter,
-#else
-                                   const InterpFilter interp_filter,
-#endif
-                                   int xs, int ys) {
-#if CONFIG_DUAL_FILTER
-  const InterpFilter filter_x = av1_get_plane_interp_filter(
-      interp_filter[1 + 2 * conv_params->ref], conv_params->plane);
-  const InterpFilter filter_y = av1_get_plane_interp_filter(
-      interp_filter[0 + 2 * conv_params->ref], conv_params->plane);
-  const InterpFilterParams interp_filter_params_x =
-      av1_get_interp_filter_params(filter_x);
-  const InterpFilterParams interp_filter_params_y =
-      av1_get_interp_filter_params(filter_y);
-#else
-  const InterpFilterParams interp_filter_params_x =
-      av1_get_interp_filter_params(interp_filter);
-  const InterpFilterParams interp_filter_params_y = interp_filter_params_x;
-#endif
-
+                                   InterpFilters interp_filters, int xs,
+                                   int ys) {
   assert(conv_params->do_average == 0 || conv_params->do_average == 1);
   assert(sf);
   if (has_scale(xs, ys)) {
@@ -69,19 +50,15 @@
     if (conv_params->round == CONVOLVE_OPT_NO_ROUND) {
 #if CONFIG_CONVOLVE_ROUND
       av1_convolve_2d_facade(src, src_stride, dst, dst_stride, w, h,
-#if CONFIG_DUAL_FILTER
-                             interp_filter,
-#else   // CONFIG_DUAL_FILTER
-                             &interp_filter,
-#endif  // CONFIG_DUAL_FILTER
-                             subpel_x, xs, subpel_y, ys, 1, conv_params);
+                             interp_filters, subpel_x, xs, subpel_y, ys, 1,
+                             conv_params);
       conv_params->do_post_rounding = 1;
 #else
       assert(0);
 #endif  // CONFIG_CONVOLVE_ROUND
     } else {
       assert(conv_params->round == CONVOLVE_OPT_ROUND);
-      av1_convolve_scale(src, src_stride, dst, dst_stride, w, h, interp_filter,
+      av1_convolve_scale(src, src_stride, dst, dst_stride, w, h, interp_filters,
                          subpel_x, xs, subpel_y, ys, conv_params);
     }
   } else {
@@ -96,31 +73,32 @@
     if (conv_params->round == CONVOLVE_OPT_NO_ROUND) {
 #if CONFIG_CONVOLVE_ROUND
       av1_convolve_2d_facade(src, src_stride, dst, dst_stride, w, h,
-#if CONFIG_DUAL_FILTER
-                             interp_filter,
-#else   // CONFIG_DUAL_FILTER
-                             &interp_filter,
-#endif  // CONFIG_DUAL_FILTER
-                             subpel_x, xs, subpel_y, ys, 0, conv_params);
+                             interp_filters, subpel_x, xs, subpel_y, ys, 0,
+                             conv_params);
       conv_params->do_post_rounding = 1;
 #else
       assert(0);
 #endif  // CONFIG_CONVOLVE_ROUND
     } else {
       assert(conv_params->round == CONVOLVE_OPT_ROUND);
+
+      InterpFilterParams filter_params_x, filter_params_y;
+      av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x,
+                                     &filter_params_y);
+
       if (w <= 2 || h <= 2) {
-        av1_convolve_c(src, src_stride, dst, dst_stride, w, h, interp_filter,
+        av1_convolve_c(src, src_stride, dst, dst_stride, w, h, interp_filters,
                        subpel_x, xs, subpel_y, ys, conv_params);
-      } else if (interp_filter_params_x.taps == SUBPEL_TAPS &&
-                 interp_filter_params_y.taps == SUBPEL_TAPS) {
-        const int16_t *kernel_x = av1_get_interp_filter_subpel_kernel(
-            interp_filter_params_x, subpel_x);
-        const int16_t *kernel_y = av1_get_interp_filter_subpel_kernel(
-            interp_filter_params_y, subpel_y);
+      } else if (filter_params_x.taps == SUBPEL_TAPS &&
+                 filter_params_y.taps == SUBPEL_TAPS) {
+        const int16_t *kernel_x =
+            av1_get_interp_filter_subpel_kernel(filter_params_x, subpel_x);
+        const int16_t *kernel_y =
+            av1_get_interp_filter_subpel_kernel(filter_params_y, subpel_y);
         sf->predict[subpel_x != 0][subpel_y != 0][conv_params->do_average](
             src, src_stride, dst, dst_stride, kernel_x, xs, kernel_y, ys, w, h);
       } else {
-        av1_convolve(src, src_stride, dst, dst_stride, w, h, interp_filter,
+        av1_convolve(src, src_stride, dst, dst_stride, w, h, interp_filters,
                      subpel_x, xs, subpel_y, ys, conv_params);
       }
     }
@@ -133,44 +111,24 @@
                                           int subpel_x, int subpel_y,
                                           const struct scale_factors *sf, int w,
                                           int h, ConvolveParams *conv_params,
-#if CONFIG_DUAL_FILTER
-                                          const InterpFilter *interp_filter,
-#else
-                                          const InterpFilter interp_filter,
-#endif
-                                          int xs, int ys, int bd) {
+                                          InterpFilters interp_filters, int xs,
+                                          int ys, int bd) {
   const int avg = conv_params->do_average;
   assert(avg == 0 || avg == 1);
-#if CONFIG_DUAL_FILTER
-  const int ref = conv_params->ref;
-  const InterpFilterParams interp_filter_params_x =
-      av1_get_interp_filter_params(interp_filter[1 + 2 * ref]);
-  const InterpFilterParams interp_filter_params_y =
-      av1_get_interp_filter_params(interp_filter[0 + 2 * ref]);
-#else
-  const InterpFilterParams interp_filter_params_x =
-      av1_get_interp_filter_params(interp_filter);
-  const InterpFilterParams interp_filter_params_y = interp_filter_params_x;
-#endif
 
   if (has_scale(xs, ys)) {
     if (conv_params->round == CONVOLVE_OPT_NO_ROUND) {
 #if CONFIG_CONVOLVE_ROUND
       av1_highbd_convolve_2d_facade(src, src_stride, dst, dst_stride, w, h,
-#if CONFIG_DUAL_FILTER
-                                    interp_filter,
-#else  // CONFIG_DUAL_FILTER
-                                    &interp_filter,
-#endif  // CONFIG_DUAL_FILTER
-                                    subpel_x, xs, subpel_y, ys, 1, conv_params,
-                                    bd);
+                                    interp_filters, subpel_x, xs, subpel_y, ys,
+                                    1, conv_params, bd);
       conv_params->do_post_rounding = 1;
 #else
       assert(0);
 #endif  // CONFIG_CONVOLVE_ROUND
     } else {
       av1_highbd_convolve_scale(src, src_stride, dst, dst_stride, w, h,
-                                interp_filter, subpel_x, xs, subpel_y, ys, avg,
+                                interp_filters, subpel_x, xs, subpel_y, ys, avg,
                                 bd);
     }
   } else {
@@ -185,30 +143,30 @@
     if (conv_params->round == CONVOLVE_OPT_NO_ROUND) {
 #if CONFIG_CONVOLVE_ROUND
       av1_highbd_convolve_2d_facade(src, src_stride, dst, dst_stride, w, h,
-#if CONFIG_DUAL_FILTER
-                                    interp_filter,
-#else  // CONFIG_DUAL_FILTER
-                                    &interp_filter,
-#endif  // CONFIG_DUAL_FILTER
-                                    subpel_x, xs, subpel_y, ys, 0, conv_params,
-                                    bd);
+                                    interp_filters, subpel_x, xs, subpel_y, ys,
+                                    0, conv_params, bd);
       conv_params->do_post_rounding = 1;
 #else
       assert(0);
 #endif  // CONFIG_CONVOLVE_ROUND
     } else {
-      if (interp_filter_params_x.taps == SUBPEL_TAPS &&
-          interp_filter_params_y.taps == SUBPEL_TAPS && w > 2 && h > 2) {
-        const int16_t *kernel_x = av1_get_interp_filter_subpel_kernel(
-            interp_filter_params_x, subpel_x);
-        const int16_t *kernel_y = av1_get_interp_filter_subpel_kernel(
-            interp_filter_params_y, subpel_y);
+      InterpFilterParams filter_params_x, filter_params_y;
+      av1_get_convolve_filter_params(interp_filters, 0, &filter_params_x,
+                                     &filter_params_y);
+
+      if (filter_params_x.taps == SUBPEL_TAPS &&
+          filter_params_y.taps == SUBPEL_TAPS && w > 2 && h > 2) {
+        const int16_t *kernel_x =
+            av1_get_interp_filter_subpel_kernel(filter_params_x, subpel_x);
+        const int16_t *kernel_y =
+            av1_get_interp_filter_subpel_kernel(filter_params_y, subpel_y);
         sf->highbd_predict[subpel_x != 0][subpel_y != 0][avg](
             src, src_stride, dst, dst_stride, kernel_x, xs, kernel_y, ys, w, h,
             bd);
       } else {
         av1_highbd_convolve(src, src_stride, dst, dst_stride, w, h,
-                            interp_filter, subpel_x, xs, subpel_y, ys, avg, bd);
+                            interp_filters, subpel_x, xs, subpel_y, ys, avg,
+                            bd);
       }
     }
   }
@@ -320,26 +278,19 @@
 #endif  // CONFIG_HIGHBITDEPTH
 #endif  // CONFIG_COMPOUND_SEGMENT
 
-void av1_make_masked_inter_predictor(const uint8_t *pre, int pre_stride,
-                                     uint8_t *dst, int dst_stride,
-                                     const int subpel_x, const int subpel_y,
-                                     const struct scale_factors *sf, int w,
-                                     int h, ConvolveParams *conv_params,
-#if CONFIG_DUAL_FILTER
-                                     const InterpFilter *interp_filter,
-#else
-                                     const InterpFilter interp_filter,
-#endif
-                                     int xs, int ys,
+void av1_make_masked_inter_predictor(
+    const uint8_t *pre, int pre_stride, uint8_t *dst, int dst_stride,
+    const int subpel_x, const int subpel_y, const struct scale_factors *sf,
+    int w, int h, ConvolveParams *conv_params, InterpFilters interp_filters,
+    int xs, int ys,
 #if CONFIG_SUPERTX
-                                     int wedge_offset_x, int wedge_offset_y,
+    int wedge_offset_x, int wedge_offset_y,
 #endif  // CONFIG_SUPERTX
-                                     int plane,
+    int plane,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
-                                     const WarpTypesAllowed *warp_types,
-                                     int p_col, int p_row, int ref,
+    const WarpTypesAllowed *warp_types, int p_col, int p_row, int ref,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
-                                     MACROBLOCKD *xd);
+    MACROBLOCKD *xd);
 
 static INLINE int round_mv_comp_q4(int value) {
   return (value < 0 ? value - 2 : value + 2) / 4;
@@ -442,11 +393,7 @@
                                int dst_stride, const MV *src_mv,
                                const struct scale_factors *sf, int w, int h,
                                ConvolveParams *conv_params,
-#if CONFIG_DUAL_FILTER
-                               const InterpFilter *interp_filter,
-#else
-                               const InterpFilter interp_filter,
-#endif
+                               InterpFilters interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                                const WarpTypesAllowed *warp_types, int p_col,
                                int p_row, int plane, int ref,
@@ -458,11 +405,7 @@
 void av1_highbd_build_inter_predictor(
     const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride,
     const MV *mv_q3, const struct scale_factors *sf, int w, int h, int do_avg,
-#if CONFIG_DUAL_FILTER
-    const InterpFilter *interp_filter,
-#else
-    const InterpFilter interp_filter,
-#endif
+    InterpFilters interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
     const WarpTypesAllowed *warp_types, int p_col, int p_row,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -568,16 +511,8 @@
 
 static INLINE void set_default_interp_filters(
     MB_MODE_INFO *const mbmi, InterpFilter frame_interp_filter) {
-#if CONFIG_DUAL_FILTER
-  int dir;
-  for (dir = 0; dir < 4; ++dir)
-    mbmi->interp_filter[dir] = frame_interp_filter == SWITCHABLE
-                                   ? EIGHTTAP_REGULAR
-                                   : frame_interp_filter;
-#else
-  mbmi->interp_filter = frame_interp_filter == SWITCHABLE ? EIGHTTAP_REGULAR
-                                                          : frame_interp_filter;
-#endif  // CONFIG_DUAL_FILTER
+  mbmi->interp_filters =
+      av1_broadcast_interp_filter(av1_unswitchable_filter(frame_interp_filter));
 }
 
 static INLINE int av1_is_interp_needed(const MACROBLOCKD *const xd) {
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index 53795b4..9503dc8 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -1161,11 +1161,7 @@
     if (mbmi->use_intrabc) {
       mbmi->tx_size = read_tx_size(cm, xd, 1, !mbmi->skip, r);
       mbmi->mode = mbmi->uv_mode = UV_DC_PRED;
-#if CONFIG_DUAL_FILTER
-      for (int idx = 0; idx < 4; ++idx) mbmi->interp_filter[idx] = BILINEAR;
-#else
-      mbmi->interp_filter = BILINEAR;
-#endif
+      mbmi->interp_filters = av1_broadcast_interp_filter(BILINEAR);
 
       int16_t inter_mode_ctx[MODE_CTX_REF_FRAMES];
       int_mv ref_mvs[MAX_MV_REF_CANDIDATES];
@@ -1750,43 +1746,33 @@
     return;
   }
 
-#if CONFIG_DUAL_FILTER
   if (cm->interp_filter != SWITCHABLE) {
-    int dir;
-
-    for (dir = 0; dir < 4; ++dir) mbmi->interp_filter[dir] = cm->interp_filter;
+    mbmi->interp_filters = av1_broadcast_interp_filter(cm->interp_filter);
   } else {
-    int dir;
-
-    for (dir = 0; dir < 2; ++dir) {
-      const int ctx = av1_get_pred_context_switchable_interp(xd, dir);
-      mbmi->interp_filter[dir] = EIGHTTAP_REGULAR;
-
+#if CONFIG_DUAL_FILTER
+    InterpFilter ref0_filter[2] = { EIGHTTAP_REGULAR, EIGHTTAP_REGULAR };
+    for (int dir = 0; dir < 2; ++dir) {
       if (has_subpel_mv_component(xd->mi[0], xd, dir) ||
           (mbmi->ref_frame[1] > INTRA_FRAME &&
            has_subpel_mv_component(xd->mi[0], xd, dir + 2))) {
-        mbmi->interp_filter[dir] =
+        const int ctx = av1_get_pred_context_switchable_interp(xd, dir);
+        ref0_filter[dir] =
             (InterpFilter)aom_read_symbol(r, ec_ctx->switchable_interp_cdf[ctx],
                                           SWITCHABLE_FILTERS, ACCT_STR);
-        if (counts) ++counts->switchable_interp[ctx][mbmi->interp_filter[dir]];
+        if (counts) ++counts->switchable_interp[ctx][ref0_filter[dir]];
       }
     }
-    // The index system works as:
-    // (0, 1) -> (vertical, horizontal) filter types for the first ref frame.
-    // (2, 3) -> (vertical, horizontal) filter types for the second ref frame.
-    mbmi->interp_filter[2] = mbmi->interp_filter[0];
-    mbmi->interp_filter[3] = mbmi->interp_filter[1];
-  }
+    // The index system works as: (0, 1) -> (vertical, horizontal) filter types
+    mbmi->interp_filters =
+        av1_make_interp_filters(ref0_filter[0], ref0_filter[1]);
 #else   // CONFIG_DUAL_FILTER
-  if (cm->interp_filter != SWITCHABLE) {
-    mbmi->interp_filter = cm->interp_filter;
-  } else {
     const int ctx = av1_get_pred_context_switchable_interp(xd);
-    mbmi->interp_filter = (InterpFilter)aom_read_symbol(
+    InterpFilter filter = (InterpFilter)aom_read_symbol(
         r, ec_ctx->switchable_interp_cdf[ctx], SWITCHABLE_FILTERS, ACCT_STR);
-    if (counts) ++counts->switchable_interp[ctx][mbmi->interp_filter];
-  }
+    mbmi->interp_filters = av1_broadcast_interp_filter(filter);
+    if (counts) ++counts->switchable_interp[ctx][filter];
 #endif  // CONFIG_DUAL_FILTER
+  }
 }
 
 static void read_intra_block_mode_info(AV1_COMMON *const cm, const int mi_row,
diff --git a/av1/decoder/inspection.c b/av1/decoder/inspection.c
index 1728333..98c51d4 100644
--- a/av1/decoder/inspection.c
+++ b/av1/decoder/inspection.c
@@ -91,10 +91,10 @@
       // Skip Flag
       mi->skip = mbmi->skip;
 #if CONFIG_DUAL_FILTER
-      mi->filter[0] = mbmi->interp_filter[0];
-      mi->filter[1] = mbmi->interp_filter[1];
+      mi->filter[0] = av1_extract_interp_filter(mbmi->interp_filters, 0);
+      mi->filter[1] = av1_extract_interp_filter(mbmi->interp_filters, 1);
 #else
-      mi->filter = mbmi->interp_filter;
+      mi->filter = av1_extract_interp_filter(mbmi->interp_filters, 0);
 #endif
       // Transform
       mi->tx_type = mbmi->tx_type;
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 0662273..7cc83b6 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -1305,16 +1305,9 @@
   FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
 
   if (!av1_is_interp_needed(xd)) {
-#if CONFIG_DUAL_FILTER
-    for (int i = 0; i < 4; ++i)
-      assert(mbmi->interp_filter[i] == (cm->interp_filter == SWITCHABLE
-                                            ? EIGHTTAP_REGULAR
-                                            : cm->interp_filter));
-#else
-    assert(mbmi->interp_filter == (cm->interp_filter == SWITCHABLE
-                                       ? EIGHTTAP_REGULAR
-                                       : cm->interp_filter));
-#endif  // CONFIG_DUAL_FILTER
+    assert(mbmi->interp_filters ==
+           av1_broadcast_interp_filter(
+               av1_unswitchable_filter(cm->interp_filter)));
     return;
   }
   if (cm->interp_filter == SWITCHABLE) {
@@ -1325,20 +1318,23 @@
           (mbmi->ref_frame[1] > INTRA_FRAME &&
            has_subpel_mv_component(xd->mi[0], xd, dir + 2))) {
         const int ctx = av1_get_pred_context_switchable_interp(xd, dir);
-        aom_write_symbol(w, mbmi->interp_filter[dir],
-                         ec_ctx->switchable_interp_cdf[ctx],
+        InterpFilter filter =
+            av1_extract_interp_filter(mbmi->interp_filters, dir);
+        aom_write_symbol(w, filter, ec_ctx->switchable_interp_cdf[ctx],
                          SWITCHABLE_FILTERS);
-        ++cpi->interp_filter_selected[0][mbmi->interp_filter[dir]];
+        ++cpi->interp_filter_selected[0][filter];
       } else {
-        assert(mbmi->interp_filter[dir] == EIGHTTAP_REGULAR);
+        assert(av1_extract_interp_filter(mbmi->interp_filters, dir) ==
+               EIGHTTAP_REGULAR);
       }
     }
 #else
     {
       const int ctx = av1_get_pred_context_switchable_interp(xd);
-      aom_write_symbol(w, mbmi->interp_filter,
-                       ec_ctx->switchable_interp_cdf[ctx], SWITCHABLE_FILTERS);
-      ++cpi->interp_filter_selected[0][mbmi->interp_filter];
+      InterpFilter filter = av1_extract_interp_filter(mbmi->interp_filters, 0);
+      aom_write_symbol(w, filter, ec_ctx->switchable_interp_cdf[ctx],
+                       SWITCHABLE_FILTERS);
+      ++cpi->interp_filter_selected[0][filter];
     }
 #endif  // CONFIG_DUAL_FILTER
   }
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 51d1c72..2913e73 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -454,16 +454,17 @@
 #if CONFIG_DUAL_FILTER
 static void reset_intmv_filter_type(const AV1_COMMON *const cm, MACROBLOCKD *xd,
                                     MB_MODE_INFO *mbmi) {
-  int dir;
-  for (dir = 0; dir < 2; ++dir) {
-    if (!has_subpel_mv_component(xd->mi[0], xd, dir) &&
-        (mbmi->ref_frame[1] == NONE_FRAME ||
-         !has_subpel_mv_component(xd->mi[0], xd, dir + 2)))
-      mbmi->interp_filter[dir] = (cm->interp_filter == SWITCHABLE)
-                                     ? EIGHTTAP_REGULAR
-                                     : cm->interp_filter;
-    mbmi->interp_filter[dir + 2] = mbmi->interp_filter[dir];
+  InterpFilter filters[2];
+  InterpFilter default_filter = av1_unswitchable_filter(cm->interp_filter);
+
+  for (int dir = 0; dir < 2; ++dir) {
+    filters[dir] = ((!has_subpel_mv_component(xd->mi[0], xd, dir) &&
+                     (mbmi->ref_frame[1] == NONE_FRAME ||
+                      !has_subpel_mv_component(xd->mi[0], xd, dir + 2)))
+                        ? default_filter
+                        : av1_extract_interp_filter(mbmi->interp_filters, dir));
   }
+  mbmi->interp_filters = av1_make_interp_filters(filters[0], filters[1]);
 }
 
 static void update_filter_type_count(FRAME_COUNTS *counts,
@@ -475,9 +476,11 @@
         (mbmi->ref_frame[1] > INTRA_FRAME &&
          has_subpel_mv_component(xd->mi[0], xd, dir + 2))) {
       const int ctx = av1_get_pred_context_switchable_interp(xd, dir);
-      ++counts->switchable_interp[ctx][mbmi->interp_filter[dir]];
-      update_cdf(xd->tile_ctx->switchable_interp_cdf[ctx],
-                 mbmi->interp_filter[dir], SWITCHABLE_FILTERS);
+      InterpFilter filter =
+          av1_extract_interp_filter(mbmi->interp_filters, dir);
+      ++counts->switchable_interp[ctx][filter];
+      update_cdf(xd->tile_ctx->switchable_interp_cdf[ctx], filter,
+                 SWITCHABLE_FILTERS);
     }
   }
 }
@@ -736,7 +739,9 @@
         update_filter_type_count(td->counts, xd, mbmi);
 #else
         const int switchable_ctx = av1_get_pred_context_switchable_interp(xd);
-        ++td->counts->switchable_interp[switchable_ctx][mbmi->interp_filter];
+        const InterpFilter filter =
+            av1_extract_interp_filter(mbmi->interp_filters, 0);
+        ++td->counts->switchable_interp[switchable_ctx][filter];
 #endif
       }
     }
@@ -3856,11 +3861,7 @@
     if (bsize == BLOCK_8X8 && !unify_bsize) {
       if (cpi->sf.adaptive_pred_interp_filter && partition_none_allowed)
         pc_tree->leaf_split[0]->pred_interp_filter =
-#if CONFIG_DUAL_FILTER
-            ctx_none->mic.mbmi.interp_filter[0];
-#else
-            ctx_none->mic.mbmi.interp_filter;
-#endif
+            av1_extract_interp_filter(ctx_none->mic.mbmi.interp_filters, 0);
 
       rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc,
 #if CONFIG_SUPERTX
@@ -4048,11 +4049,8 @@
     if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
         partition_none_allowed)
       pc_tree->horizontal[0].pred_interp_filter =
-#if CONFIG_DUAL_FILTER
-          ctx_none->mic.mbmi.interp_filter[0];
-#else
-          ctx_none->mic.mbmi.interp_filter;
-#endif
+          av1_extract_interp_filter(ctx_none->mic.mbmi.interp_filters, 0);
+
     rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc,
 #if CONFIG_SUPERTX
                      &sum_rate_nocoef,
@@ -4079,11 +4077,8 @@
       if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
           partition_none_allowed)
         pc_tree->horizontal[1].pred_interp_filter =
-#if CONFIG_DUAL_FILTER
-            ctx_h->mic.mbmi.interp_filter[0];
-#else
-            ctx_none->mic.mbmi.interp_filter;
-#endif
+            av1_extract_interp_filter(ctx_h->mic.mbmi.interp_filters, 0);
+
 #if CONFIG_SUPERTX
       rd_pick_sb_modes(cpi, tile_data, x, mi_row + mi_step, mi_col, &this_rdc,
                        &this_rate_nocoef,
@@ -4210,11 +4205,8 @@
     if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
         partition_none_allowed)
       pc_tree->vertical[0].pred_interp_filter =
-#if CONFIG_DUAL_FILTER
-          ctx_none->mic.mbmi.interp_filter[0];
-#else
-          ctx_none->mic.mbmi.interp_filter;
-#endif
+          av1_extract_interp_filter(ctx_none->mic.mbmi.interp_filters, 0);
+
     rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc,
 #if CONFIG_SUPERTX
                      &sum_rate_nocoef,
@@ -4241,11 +4233,8 @@
       if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
           partition_none_allowed)
         pc_tree->vertical[1].pred_interp_filter =
-#if CONFIG_DUAL_FILTER
-            ctx_none->mic.mbmi.interp_filter[0];
-#else
-            ctx_none->mic.mbmi.interp_filter;
-#endif
+            av1_extract_interp_filter(ctx_none->mic.mbmi.interp_filters, 0);
+
 #if CONFIG_SUPERTX
       rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col + mi_step, &this_rdc,
                        &this_rate_nocoef,
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index c9ed9ce..6115e84 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -1205,8 +1205,9 @@
           (mbmi->ref_frame[1] > INTRA_FRAME &&
            has_subpel_mv_component(xd->mi[0], xd, dir + 2))) {
         const int ctx = av1_get_pred_context_switchable_interp(xd, dir);
-        inter_filter_cost +=
-            x->switchable_interp_costs[ctx][mbmi->interp_filter[dir]];
+        const InterpFilter filter =
+            av1_extract_interp_filter(mbmi->interp_filters, dir);
+        inter_filter_cost += x->switchable_interp_costs[ctx][filter];
       }
     }
     return SWITCHABLE_INTERP_RATE_FACTOR * inter_filter_cost;
@@ -1220,8 +1221,10 @@
   if (cm->interp_filter == SWITCHABLE) {
     const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
     const int ctx = av1_get_pred_context_switchable_interp(xd);
+    const InterpFilter filter =
+        av1_extract_interp_filter(mbmi->interp_filters, 0);
     return SWITCHABLE_INTERP_RATE_FACTOR *
-           x->switchable_interp_costs[ctx][mbmi->interp_filter];
+           x->switchable_interp_costs[ctx][filter];
   }
   return 0;
 }
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 955f4de..f3d0f61 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -6432,7 +6432,7 @@
 #else   // !(CONFIG_COMPOUND_SINGLEREF)
           &frame_mv[refs[!id]].as_mv,
 #endif  // CONFIG_COMPOUND_SINGLEREF
-          &sf, pw, ph, 0, mbmi->interp_filter,
+          &sf, pw, ph, 0, mbmi->interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
           &warp_types, p_col, p_row,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -6447,7 +6447,7 @@
 #else   // !(CONFIG_COMPOUND_SINGLEREF)
         &frame_mv[refs[!id]].as_mv,
 #endif  // CONFIG_COMPOUND_SINGLEREF
-          &sf, pw, ph, &conv_params, mbmi->interp_filter,
+          &sf, pw, ph, &conv_params, mbmi->interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
           &warp_types, p_col, p_row, plane, !id,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -7224,7 +7224,7 @@
   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
     av1_highbd_build_inter_predictor(
         ref_yv12.buf, ref_yv12.stride, second_pred, pw, other_mv, &sf, pw, ph,
-        0, mbmi->interp_filter,
+        0, mbmi->interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
         &warp_types, p_col, p_row,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -7233,7 +7233,7 @@
 #endif  // CONFIG_HIGHBITDEPTH
     av1_build_inter_predictor(
         ref_yv12.buf, ref_yv12.stride, second_pred, pw, other_mv, &sf, pw, ph,
-        &conv_params, mbmi->interp_filter,
+        &conv_params, mbmi->interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
         &warp_types, p_col, p_row, plane, !ref_idx,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -7590,8 +7590,11 @@
                   (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
   if (pred_filter_search) {
     InterpFilter af = SWITCHABLE, lf = SWITCHABLE;
-    if (xd->up_available) af = xd->mi[-xd->mi_stride]->mbmi.interp_filter;
-    if (xd->left_available) lf = xd->mi[-1]->mbmi.interp_filter;
+    if (xd->up_available)
+      af = av1_extract_interp_filter(
+          xd->mi[-xd->mi_stride]->mbmi.interp_filters, 0);
+    if (xd->left_available)
+      lf = av1_extract_interp_filter(xd->mi[-1]->mbmi.interp_filters, 0);
 
     if ((this_mode != NEWMV && this_mode != NEW_NEWMV) || (af == lf))
       best_filter = af;
@@ -8275,12 +8278,7 @@
       const int filter_set_size = SWITCHABLE_FILTERS;
 #endif  // CONFIG_DUAL_FILTER
       int best_in_temp = 0;
-#if CONFIG_DUAL_FILTER
-      InterpFilter best_filter[4];
-      av1_copy(best_filter, mbmi->interp_filter);
-#else
-      InterpFilter best_filter = mbmi->interp_filter;
-#endif  // CONFIG_DUAL_FILTER
+      InterpFilters best_filters = mbmi->interp_filters;
       restore_dst_buf(xd, *tmp_dst);
       // EIGHTTAP_REGULAR mode is calculated beforehand
       for (i = 1; i < filter_set_size; ++i) {
@@ -8289,12 +8287,10 @@
         int tmp_rs;
         int64_t tmp_rd;
 #if CONFIG_DUAL_FILTER
-        mbmi->interp_filter[0] = filter_sets[i][0];
-        mbmi->interp_filter[1] = filter_sets[i][1];
-        mbmi->interp_filter[2] = filter_sets[i][0];
-        mbmi->interp_filter[3] = filter_sets[i][1];
+        mbmi->interp_filters =
+            av1_make_interp_filters(filter_sets[i][0], filter_sets[i][1]);
 #else
-        mbmi->interp_filter = (InterpFilter)i;
+        mbmi->interp_filters = av1_broadcast_interp_filter((InterpFilter)i);
 #endif  // CONFIG_DUAL_FILTER
         tmp_rs = av1_get_switchable_rate(cm, x, xd);
         av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
@@ -8305,11 +8301,7 @@
         if (tmp_rd < *rd) {
           *rd = tmp_rd;
           *switchable_rate = av1_get_switchable_rate(cm, x, xd);
-#if CONFIG_DUAL_FILTER
-          av1_copy(best_filter, mbmi->interp_filter);
-#else
-          best_filter = mbmi->interp_filter;
-#endif  // CONFIG_DUAL_FILTER
+          best_filters = mbmi->interp_filters;
           *skip_txfm_sb = tmp_skip_sb;
           *skip_sse_sb = tmp_skip_sse;
           best_in_temp = !best_in_temp;
@@ -8325,24 +8317,29 @@
       } else {
         restore_dst_buf(xd, *orig_dst);
       }
-#if CONFIG_DUAL_FILTER
-      av1_copy(mbmi->interp_filter, best_filter);
-#else
-      mbmi->interp_filter = best_filter;
-#endif  // CONFIG_DUAL_FILTER
+      mbmi->interp_filters = best_filters;
     } else {
-#if CONFIG_DUAL_FILTER
-      for (i = 0; i < 4; ++i)
-        assert(mbmi->interp_filter[i] == EIGHTTAP_REGULAR);
-#else
-      assert(mbmi->interp_filter == EIGHTTAP_REGULAR);
-#endif  // CONFIG_DUAL_FILTER
+      assert(mbmi->interp_filters ==
+             av1_broadcast_interp_filter(EIGHTTAP_REGULAR));
     }
   }
 
   return 0;
 }
 
+#if CONFIG_DUAL_FILTER
+static InterpFilters condition_interp_filters_on_mv(
+    InterpFilters interp_filters, const MACROBLOCKD *xd) {
+  InterpFilter filters[2];
+  for (int i = 0; i < 2; ++i)
+    filters[i] = (has_subpel_mv_component(xd->mi[0], xd, i))
+                     ? av1_extract_interp_filter(interp_filters, i)
+                     : EIGHTTAP_REGULAR;
+
+  return av1_make_interp_filters(filters[0], filters[1]);
+}
+#endif
+
 // TODO(afergs): Refactor the MBMI references in here - there's four
 // TODO(afergs): Refactor optional args - add them to a struct or remove
 static int64_t motion_mode_rd(
@@ -8464,10 +8461,8 @@
         }
         tmp_rate2 = rate2_bmc_nocoeff - rate_mv_bmc + tmp_rate_mv;
 #if CONFIG_DUAL_FILTER
-        if (!has_subpel_mv_component(xd->mi[0], xd, 0))
-          mbmi->interp_filter[0] = EIGHTTAP_REGULAR;
-        if (!has_subpel_mv_component(xd->mi[0], xd, 1))
-          mbmi->interp_filter[1] = EIGHTTAP_REGULAR;
+        mbmi->interp_filters =
+            condition_interp_filters_on_mv(mbmi->interp_filters, xd);
 #endif  // CONFIG_DUAL_FILTER
         av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
       } else {
@@ -8489,15 +8484,8 @@
       *mbmi = *best_bmc_mbmi;
       mbmi->motion_mode = WARPED_CAUSAL;
       mbmi->wm_params[0].wmtype = DEFAULT_WMTYPE;
-#if CONFIG_DUAL_FILTER
-      for (int dir = 0; dir < 4; ++dir)
-        mbmi->interp_filter[dir] = cm->interp_filter == SWITCHABLE
-                                       ? EIGHTTAP_REGULAR
-                                       : cm->interp_filter;
-#else
-      mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP_REGULAR
-                                                            : cm->interp_filter;
-#endif  // CONFIG_DUAL_FILTER
+      mbmi->interp_filters = av1_broadcast_interp_filter(
+          av1_unswitchable_filter(cm->interp_filter));
 
 #if WARPED_MOTION_SORT_SAMPLES
       memcpy(pts, pts0, total_samples * 2 * sizeof(*pts0));
@@ -8552,10 +8540,8 @@
 #endif  // WARPED_MOTION_SORT_SAMPLES
             tmp_rate2 = rate2_bmc_nocoeff - rate_mv_bmc + tmp_rate_mv;
 #if CONFIG_DUAL_FILTER
-            if (!has_subpel_mv_component(xd->mi[0], xd, 0))
-              mbmi->interp_filter[0] = EIGHTTAP_REGULAR;
-            if (!has_subpel_mv_component(xd->mi[0], xd, 1))
-              mbmi->interp_filter[1] = EIGHTTAP_REGULAR;
+            mbmi->interp_filters =
+                condition_interp_filters_on_mv(mbmi->interp_filters, xd);
 #endif  // CONFIG_DUAL_FILTER
           } else {
             // Restore the old MV and WM parameters.
@@ -8714,18 +8700,8 @@
     if (this_mode == ZEROMV || this_mode == ZERO_ZEROMV) {
       if (is_nontrans_global_motion(xd)) {
         rd_stats->rate -= rs;
-#if CONFIG_DUAL_FILTER
-        mbmi->interp_filter[0] = cm->interp_filter == SWITCHABLE
-                                     ? EIGHTTAP_REGULAR
-                                     : cm->interp_filter;
-        mbmi->interp_filter[1] = cm->interp_filter == SWITCHABLE
-                                     ? EIGHTTAP_REGULAR
-                                     : cm->interp_filter;
-#else
-        mbmi->interp_filter = cm->interp_filter == SWITCHABLE
-                                  ? EIGHTTAP_REGULAR
-                                  : cm->interp_filter;
-#endif  // CONFIG_DUAL_FILTER
+        mbmi->interp_filters = av1_broadcast_interp_filter(
+            av1_unswitchable_filter(cm->interp_filter));
       }
     }
 #endif  // CONFIG_GLOBAL_MOTION
@@ -9394,11 +9370,8 @@
   }
 
   if (!is_comp_pred)
-#if CONFIG_DUAL_FILTER
-    args->single_filter[this_mode][refs[0]] = mbmi->interp_filter[0];
-#else
-    args->single_filter[this_mode][refs[0]] = mbmi->interp_filter;
-#endif  // CONFIG_DUAL_FILTER
+    args->single_filter[this_mode][refs[0]] =
+        av1_extract_interp_filter(mbmi->interp_filters, 0);
 
   if (args->modelled_rd != NULL) {
     if (is_comp_pred) {
@@ -9558,11 +9531,7 @@
     mbmi->mode = DC_PRED;
     mbmi->uv_mode = UV_DC_PRED;
     mbmi->mv[0].as_mv = dv;
-#if CONFIG_DUAL_FILTER
-    for (int idx = 0; idx < 4; ++idx) mbmi->interp_filter[idx] = BILINEAR;
-#else
-    mbmi->interp_filter = BILINEAR;
-#endif
+    mbmi->interp_filters = av1_broadcast_interp_filter(BILINEAR);
     mbmi->skip = 0;
     x->skip = 0;
     av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
@@ -11744,24 +11713,14 @@
     return;
   }
 
+  assert((cm->interp_filter == SWITCHABLE) ||
+         (cm->interp_filter ==
+          av1_extract_interp_filter(best_mbmode.interp_filters, 0)) ||
+         !is_inter_block(&best_mbmode));
 #if CONFIG_DUAL_FILTER
   assert((cm->interp_filter == SWITCHABLE) ||
-         (cm->interp_filter == best_mbmode.interp_filter[0]) ||
-         !is_inter_block(&best_mbmode));
-  assert((cm->interp_filter == SWITCHABLE) ||
-         (cm->interp_filter == best_mbmode.interp_filter[1]) ||
-         !is_inter_block(&best_mbmode));
-  if (best_mbmode.ref_frame[1] > INTRA_FRAME) {
-    assert((cm->interp_filter == SWITCHABLE) ||
-           (cm->interp_filter == best_mbmode.interp_filter[2]) ||
-           !is_inter_block(&best_mbmode));
-    assert((cm->interp_filter == SWITCHABLE) ||
-           (cm->interp_filter == best_mbmode.interp_filter[3]) ||
-           !is_inter_block(&best_mbmode));
-  }
-#else
-  assert((cm->interp_filter == SWITCHABLE) ||
-         (cm->interp_filter == best_mbmode.interp_filter) ||
+         (cm->interp_filter ==
+          av1_extract_interp_filter(best_mbmode.interp_filters, 1)) ||
          !is_inter_block(&best_mbmode));
 #endif  // CONFIG_DUAL_FILTER
 
@@ -11791,17 +11750,8 @@
 
     // Correct the interpolation filter for ZEROMV
     if (is_nontrans_global_motion(xd)) {
-#if CONFIG_DUAL_FILTER
-      mbmi->interp_filter[0] = cm->interp_filter == SWITCHABLE
-                                   ? EIGHTTAP_REGULAR
-                                   : cm->interp_filter;
-      mbmi->interp_filter[1] = cm->interp_filter == SWITCHABLE
-                                   ? EIGHTTAP_REGULAR
-                                   : cm->interp_filter;
-#else
-      mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP_REGULAR
-                                                            : cm->interp_filter;
-#endif  // CONFIG_DUAL_FILTER
+      mbmi->interp_filters = av1_broadcast_interp_filter(
+          av1_unswitchable_filter(cm->interp_filter));
     }
   }
 #endif  // CONFIG_GLOBAL_MOTION
@@ -11934,30 +11884,17 @@
       int rs;
       int best_rs = INT_MAX;
       for (i = 0; i < SWITCHABLE_FILTERS; ++i) {
-#if CONFIG_DUAL_FILTER
-        int k;
-        for (k = 0; k < 4; ++k) mbmi->interp_filter[k] = i;
-#else
-        mbmi->interp_filter = i;
-#endif  // CONFIG_DUAL_FILTER
+        mbmi->interp_filters = av1_broadcast_interp_filter(i);
         rs = av1_get_switchable_rate(cm, x, xd);
         if (rs < best_rs) {
           best_rs = rs;
-#if CONFIG_DUAL_FILTER
-          best_filter = mbmi->interp_filter[0];
-#else
-          best_filter = mbmi->interp_filter;
-#endif  // CONFIG_DUAL_FILTER
+          best_filter = av1_extract_interp_filter(mbmi->interp_filters, 0);
         }
       }
     }
   }
-// Set the appropriate filter
-#if CONFIG_DUAL_FILTER
-  for (i = 0; i < 4; ++i) mbmi->interp_filter[i] = best_filter;
-#else
-  mbmi->interp_filter = best_filter;
-#endif  // CONFIG_DUAL_FILTER
+  // Set the appropriate filter
+  mbmi->interp_filters = av1_broadcast_interp_filter(best_filter);
   rate2 += av1_get_switchable_rate(cm, x, xd);
 
   if (cm->reference_mode == REFERENCE_MODE_SELECT)
@@ -11978,13 +11915,9 @@
     return;
   }
 
-#if CONFIG_DUAL_FILTER
   assert((cm->interp_filter == SWITCHABLE) ||
-         (cm->interp_filter == mbmi->interp_filter[0]));
-#else
-  assert((cm->interp_filter == SWITCHABLE) ||
-         (cm->interp_filter == mbmi->interp_filter));
-#endif  // CONFIG_DUAL_FILTER
+         (cm->interp_filter ==
+          av1_extract_interp_filter(mbmi->interp_filters, 0)));
 
   av1_update_rd_thresh_fact(cm, tile_data->thresh_freq_fact,
                             cpi->sf.adaptive_rd_thresh, bsize, THR_ZEROMV);
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index 8fa0362..daa6476 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -44,18 +44,13 @@
   ConvolveParams conv_params = get_conv_params(which_mv, which_mv, 0);
 
 #if USE_TEMPORALFILTER_12TAP
-#if CONFIG_DUAL_FILTER
-  const InterpFilter interp_filter[4] = { TEMPORALFILTER_12TAP,
-                                          TEMPORALFILTER_12TAP,
-                                          TEMPORALFILTER_12TAP,
-                                          TEMPORALFILTER_12TAP };
-#else
-  const InterpFilter interp_filter = TEMPORALFILTER_12TAP;
-#endif
+  const InterpFilters interp_filters =
+      av1_broadcast_interp_filter(TEMPORALFILTER_12TAP);
   (void)xd;
 #else
-  const InterpFilter interp_filter = xd->mi[0]->mbmi.interp_filter;
+  const InterpFilters interp_filters = xd->mi[0]->mbmi.interp_filters;
 #endif  // USE_TEMPORALFILTER_12TAP
+
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
   WarpTypesAllowed warp_types;
   memset(&warp_types, 0, sizeof(WarpTypesAllowed));
@@ -72,7 +67,7 @@
 #if CONFIG_HIGHBITDEPTH
   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
     av1_highbd_build_inter_predictor(y_mb_ptr, stride, &pred[0], 16, &mv, scale,
-                                     16, 16, which_mv, interp_filter,
+                                     16, 16, which_mv, interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                                      &warp_types, x, y,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -80,7 +75,7 @@
 
     av1_highbd_build_inter_predictor(u_mb_ptr, uv_stride, &pred[256],
                                      uv_block_width, &mv, scale, uv_block_width,
-                                     uv_block_height, which_mv, interp_filter,
+                                     uv_block_height, which_mv, interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                                      &warp_types, x, y,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -88,7 +83,7 @@
 
     av1_highbd_build_inter_predictor(v_mb_ptr, uv_stride, &pred[512],
                                      uv_block_width, &mv, scale, uv_block_width,
-                                     uv_block_height, which_mv, interp_filter,
+                                     uv_block_height, which_mv, interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                                      &warp_types, x, y,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -97,7 +92,7 @@
   }
 #endif  // CONFIG_HIGHBITDEPTH
   av1_build_inter_predictor(y_mb_ptr, stride, &pred[0], 16, &mv, scale, 16, 16,
-                            &conv_params, interp_filter,
+                            &conv_params, interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                             &warp_types, x, y, 0, 0,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -105,7 +100,7 @@
 
   av1_build_inter_predictor(u_mb_ptr, uv_stride, &pred[256], uv_block_width,
                             &mv, scale, uv_block_width, uv_block_height,
-                            &conv_params, interp_filter,
+                            &conv_params, interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                             &warp_types, x, y, 1, 0,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
@@ -113,7 +108,7 @@
 
   av1_build_inter_predictor(v_mb_ptr, uv_stride, &pred[512], uv_block_width,
                             &mv, scale, uv_block_width, uv_block_height,
-                            &conv_params, interp_filter,
+                            &conv_params, interp_filters,
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
                             &warp_types, x, y, 2, 0,
 #endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
diff --git a/test/av1_convolve_test.cc b/test/av1_convolve_test.cc
index 3947c71..aaef7cf 100644
--- a/test/av1_convolve_test.cc
+++ b/test/av1_convolve_test.cc
@@ -269,16 +269,9 @@
 #ifndef __clang_analyzer__
 TEST(AV1ConvolveTest, av1_highbd_convolve) {
   ACMRandom rnd(ACMRandom::DeterministicSeed());
-#if CONFIG_DUAL_FILTER
-  InterpFilter interp_filter[4] = { EIGHTTAP_REGULAR, EIGHTTAP_REGULAR,
-                                    EIGHTTAP_REGULAR, EIGHTTAP_REGULAR };
+  InterpFilters interp_filters = av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
   InterpFilterParams filter_params =
-      av1_get_interp_filter_params(interp_filter[0]);
-#else
-  InterpFilter interp_filter = EIGHTTAP_REGULAR;
-  InterpFilterParams filter_params =
-      av1_get_interp_filter_params(interp_filter);
-#endif
+      av1_get_interp_filter_params(EIGHTTAP_REGULAR);
   int filter_size = filter_params.taps;
   int filter_center = filter_size / 2 - 1;
   uint16_t src[12 * 12];
@@ -303,7 +296,7 @@
     for (subpel_y_q4 = 0; subpel_y_q4 < SUBPEL_SHIFTS; subpel_y_q4++) {
       av1_highbd_convolve(
           CONVERT_TO_BYTEPTR(src + src_stride * filter_center + filter_center),
-          src_stride, CONVERT_TO_BYTEPTR(dst), dst_stride, w, h, interp_filter,
+          src_stride, CONVERT_TO_BYTEPTR(dst), dst_stride, w, h, interp_filters,
           subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg, bd);
 
       const int16_t *x_filter =
@@ -331,16 +324,9 @@
 
 TEST(AV1ConvolveTest, av1_highbd_convolve_avg) {
   ACMRandom rnd(ACMRandom::DeterministicSeed());
-#if CONFIG_DUAL_FILTER
-  InterpFilter interp_filter[4] = { EIGHTTAP_REGULAR, EIGHTTAP_REGULAR,
-                                    EIGHTTAP_REGULAR, EIGHTTAP_REGULAR };
+  InterpFilters interp_filters = av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
   InterpFilterParams filter_params =
-      av1_get_interp_filter_params(interp_filter[0]);
-#else
-  InterpFilter interp_filter = EIGHTTAP_REGULAR;
-  InterpFilterParams filter_params =
-      av1_get_interp_filter_params(interp_filter);
-#endif
+      av1_get_interp_filter_params(EIGHTTAP_REGULAR);
   int filter_size = filter_params.taps;
   int filter_center = filter_size / 2 - 1;
   uint16_t src0[12 * 12];
@@ -373,23 +359,23 @@
       avg = 0;
       av1_highbd_convolve(CONVERT_TO_BYTEPTR(src0 + offset), src_stride,
                           CONVERT_TO_BYTEPTR(dst0), dst_stride, w, h,
-                          interp_filter, subpel_x_q4, x_step_q4, subpel_y_q4,
+                          interp_filters, subpel_x_q4, x_step_q4, subpel_y_q4,
                           y_step_q4, avg, bd);
       avg = 0;
       av1_highbd_convolve(CONVERT_TO_BYTEPTR(src1 + offset), src_stride,
                           CONVERT_TO_BYTEPTR(dst1), dst_stride, w, h,
-                          interp_filter, subpel_x_q4, x_step_q4, subpel_y_q4,
+                          interp_filters, subpel_x_q4, x_step_q4, subpel_y_q4,
                           y_step_q4, avg, bd);
 
       avg = 0;
       av1_highbd_convolve(CONVERT_TO_BYTEPTR(src0 + offset), src_stride,
                           CONVERT_TO_BYTEPTR(dst), dst_stride, w, h,
-                          interp_filter, subpel_x_q4, x_step_q4, subpel_y_q4,
+                          interp_filters, subpel_x_q4, x_step_q4, subpel_y_q4,
                           y_step_q4, avg, bd);
       avg = 1;
       av1_highbd_convolve(CONVERT_TO_BYTEPTR(src1 + offset), src_stride,
                           CONVERT_TO_BYTEPTR(dst), dst_stride, w, h,
-                          interp_filter, subpel_x_q4, x_step_q4, subpel_y_q4,
+                          interp_filters, subpel_x_q4, x_step_q4, subpel_y_q4,
                           y_step_q4, avg, bd);
 
       EXPECT_EQ(dst[0], ROUND_POWER_OF_TWO(dst0[0] + dst1[0], 1));