diff --git a/configure b/configure
index 3cecfcd5723661c004b6abd1c3976a6c903287dd..525ccd168bee055e80c432bf5eeeca9cb17d3478 100755
--- a/configure
+++ b/configure
@@ -225,6 +225,7 @@ EXPERIMENT_LIST="
     pred_filter
     lossless
     hybridtransform
+    switchable_interp
 "
 CONFIG_LIST="
     external_build
diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h
index dc0639f8306ef6ce72c645901d9ffca80495a424..1bbaa642240643892b134bcd0b9dd3ffafc0bb70 100644
--- a/vp8/common/blockd.h
+++ b/vp8/common/blockd.h
@@ -76,7 +76,25 @@ typedef enum {
   INTER_FRAME = 1
 } FRAME_TYPE;
 
-typedef enum {
+typedef enum
+{
+  SIXTAP   = 0,
+  BILINEAR = 1,
+#if CONFIG_ENHANCED_INTERP
+  EIGHTTAP = 2,
+  EIGHTTAP_SHARP = 3,
+#if CONFIG_SWITCHABLE_INTERP
+  SWITCHABLE  /* should be the last one */
+#endif
+#endif
+} INTERPOLATIONFILTERTYPE;
+
+#if 0//CONFIG_SWITCHABLE_INTERP
+#define VP8_SWITCHABLE_FILTERS 2 /* number of switchable filters */
+#endif
+
+typedef enum
+{
   DC_PRED,            /* average of above and left pixels */
   V_PRED,             /* vertical prediction */
   H_PRED,             /* horizontal prediction */
@@ -226,6 +244,9 @@ typedef struct {
   // Flag to turn prediction signal filter on(1)/off(0 ) at the MB level
   unsigned int pred_filter_enabled;
 #endif
+#if CONFIG_SWITCHABLE_INTERP
+    INTERPOLATIONFILTERTYPE interp_filter;
+#endif
 
 } MB_MODE_INFO;
 
diff --git a/vp8/common/entropy.h b/vp8/common/entropy.h
index 8bb718a06967ee00e86f1e9432652038528eed12..9993741c8065f4fefd82e9c5f52cdd7a3730126b 100644
--- a/vp8/common/entropy.h
+++ b/vp8/common/entropy.h
@@ -18,8 +18,8 @@
 #include "coefupdateprobs.h"
 
 
-#define SUBMVREF_COUNT 5
-#define VP8_NUMMBSPLITS 4
+//#define SUBMVREF_COUNT 5
+//#define VP8_NUMMBSPLITS 4
 
 /* Coefficient token alphabet */
 
diff --git a/vp8/common/entropymode.c b/vp8/common/entropymode.c
index e48df3b36b2532bd640dfb03a003ce18962ba1c3..4500e9c11e7c6f781e2049f80f2fce982eb411d5 100644
--- a/vp8/common/entropymode.c
+++ b/vp8/common/entropymode.c
@@ -9,10 +9,8 @@
  */
 
 
+#include "onyxc_int.h"
 #include "modecont.h"
-#include "entropymode.h"
-#include "entropymv.h"
-#include "entropy.h"
 #include "vpx_mem/vpx_mem.h"
 
 
@@ -286,6 +284,10 @@ void vp8_init_mbmode_probs(VP8_COMMON *x) {
 
   vpx_memcpy(x->fc.sub_mv_ref_prob, vp8_sub_mv_ref_prob2, sizeof(vp8_sub_mv_ref_prob2));
   vpx_memcpy(x->fc.mbsplit_prob, vp8_mbsplit_probs, sizeof(vp8_mbsplit_probs));
+#if CONFIG_SWITCHABLE_INTERP
+  vpx_memcpy(x->fc.switchable_interp_prob, vp8_switchable_interp_prob,
+             sizeof(vp8_switchable_interp_prob));
+#endif
 
 }
 
@@ -323,6 +325,44 @@ void vp8_kf_default_bmode_probs(vp8_prob p [VP8_BINTRAMODES] [VP8_BINTRAMODES] [
   } while (++i < VP8_BINTRAMODES);
 }
 
+#if CONFIG_SWITCHABLE_INTERP
+#if VP8_SWITCHABLE_FILTERS == 3
+const vp8_tree_index vp8_switchable_interp_tree[VP8_SWITCHABLE_FILTERS*2-2] = {
+  -0, 2,
+  -1, -2
+};
+struct vp8_token_struct vp8_switchable_interp_encodings[VP8_SWITCHABLE_FILTERS];
+const INTERPOLATIONFILTERTYPE vp8_switchable_interp[VP8_SWITCHABLE_FILTERS] = {
+  EIGHTTAP, SIXTAP, EIGHTTAP_SHARP};
+const int vp8_switchable_interp_map[SWITCHABLE+1] = {1, -1, 0, 2, -1};
+const vp8_prob vp8_switchable_interp_prob [VP8_SWITCHABLE_FILTERS+1]
+                                          [VP8_SWITCHABLE_FILTERS-1] = {
+  {248, 192}, { 32, 248}, { 32,  32}, {192, 160}
+};
+#elif VP8_SWITCHABLE_FILTERS == 2
+const vp8_tree_index vp8_switchable_interp_tree[VP8_SWITCHABLE_FILTERS*2-2] = {
+  -0, -1,
+};
+struct vp8_token_struct vp8_switchable_interp_encodings[VP8_SWITCHABLE_FILTERS];
+const vp8_prob vp8_switchable_interp_prob [VP8_SWITCHABLE_FILTERS+1]
+                                          [VP8_SWITCHABLE_FILTERS-1] = {
+  {248},
+  { 64},
+  {192},
+};
+//#define SWITCHABLE_86
+#ifdef SWITCHABLE_86
+const INTERPOLATIONFILTERTYPE vp8_switchable_interp[VP8_SWITCHABLE_FILTERS] = {
+  EIGHTTAP, SIXTAP};
+const int vp8_switchable_interp_map[SWITCHABLE+1] = {1, -1, 0, -1, -1}; //8, 6
+#else
+const INTERPOLATIONFILTERTYPE vp8_switchable_interp[VP8_SWITCHABLE_FILTERS] = {
+  EIGHTTAP, EIGHTTAP_SHARP};
+const int vp8_switchable_interp_map[SWITCHABLE+1] = {-1, -1, 0, 1, -1}; //8, 8s
+#endif
+#endif
+#endif
+
 
 void vp8_entropy_mode_init() {
   vp8_tokens_from_tree(vp8_bmode_encodings,   vp8_bmode_tree);
@@ -331,6 +371,10 @@ void vp8_entropy_mode_init() {
   vp8_tokens_from_tree(vp8_uv_mode_encodings,  vp8_uv_mode_tree);
   vp8_tokens_from_tree(vp8_i8x8_mode_encodings,  vp8_i8x8_mode_tree);
   vp8_tokens_from_tree(vp8_mbsplit_encodings, vp8_mbsplit_tree);
+#if CONFIG_SWITCHABLE_INTERP
+  vp8_tokens_from_tree(vp8_switchable_interp_encodings,
+                       vp8_switchable_interp_tree);
+#endif
 
   vp8_tokens_from_tree_offset(vp8_mv_ref_encoding_array,
                               vp8_mv_ref_tree, NEARESTMV);
diff --git a/vp8/common/entropymode.h b/vp8/common/entropymode.h
index f66c1c85961478ed59758826dbef6b23a60de7d9..f9cc263b9e43a8896733797aa0cbba54d9a01a16 100644
--- a/vp8/common/entropymode.h
+++ b/vp8/common/entropymode.h
@@ -12,9 +12,12 @@
 #ifndef __INC_ENTROPYMODE_H
 #define __INC_ENTROPYMODE_H
 
-#include "onyxc_int.h"
+#include "blockd.h"
 #include "treecoder.h"
 
+#define SUBMVREF_COUNT 5
+#define VP8_NUMMBSPLITS 4
+
 typedef const int vp8_mbsplit[16];
 
 extern vp8_mbsplit vp8_mbsplits [VP8_NUMMBSPLITS];
@@ -56,10 +59,11 @@ extern struct vp8_token_struct vp8_sub_mv_ref_encoding_array [VP8_SUBMVREFS];
 
 void vp8_entropy_mode_init(void);
 
-void vp8_init_mbmode_probs(VP8_COMMON *x);
-extern void vp8_init_mode_contexts(VP8_COMMON *pc);
-extern void vp8_update_mode_context(VP8_COMMON *pc);;
-extern void vp8_accum_mv_refs(VP8_COMMON *pc,
+struct VP8Common;
+void vp8_init_mbmode_probs(struct VP8Common *x);
+extern void vp8_init_mode_contexts(struct VP8Common *pc);
+extern void vp8_update_mode_context(struct VP8Common *pc);;
+extern void vp8_accum_mv_refs(struct VP8Common *pc,
                               MB_PREDICTION_MODE m,
                               const int ct[4]);
 
@@ -67,4 +71,17 @@ void vp8_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES - 1]);
 void vp8_kf_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES - 1]);
 
 void vp8_adapt_mode_probs(struct VP8Common *);
+
+#if CONFIG_SWITCHABLE_INTERP
+#define VP8_SWITCHABLE_FILTERS 2 /* number of switchable filters */
+extern const  INTERPOLATIONFILTERTYPE vp8_switchable_interp
+                  [VP8_SWITCHABLE_FILTERS];
+extern const  int vp8_switchable_interp_map[SWITCHABLE+1];
+extern const  vp8_tree_index vp8_switchable_interp_tree
+                  [2*(VP8_SWITCHABLE_FILTERS-1)];
+extern struct vp8_token_struct vp8_switchable_interp_encodings
+                  [VP8_SWITCHABLE_FILTERS];
+extern const  vp8_prob vp8_switchable_interp_prob
+                  [VP8_SWITCHABLE_FILTERS+1][VP8_SWITCHABLE_FILTERS-1];
+#endif
 #endif
diff --git a/vp8/common/entropymv.c b/vp8/common/entropymv.c
index 3dd72cc76b24cdd3f3d7d77c432615f76570a81a..c1ea62d270b1841f2ad0a463c53e9476c74a2853 100644
--- a/vp8/common/entropymv.c
+++ b/vp8/common/entropymv.c
@@ -116,7 +116,6 @@ const vp8_tree_index vp8_small_mvtree [14] = {
 };
 struct vp8_token_struct vp8_small_mvencodings [8];
 
-
 __inline static void calc_prob(vp8_prob *p, const unsigned int ct[2], int pbits) {
   const unsigned int tot = ct[0] + ct[1];
   if (tot) {
diff --git a/vp8/common/entropymv.h b/vp8/common/entropymv.h
index 96ea7ffaea154d457e04fb0c6a24e37eb5882faf..c0726eceafc909874d291c7613eb711eafc51535 100644
--- a/vp8/common/entropymv.h
+++ b/vp8/common/entropymv.h
@@ -14,6 +14,7 @@
 
 #include "treecoder.h"
 #include "vpx_config.h"
+#include "blockd.h"
 
 enum {
   mv_max  = 1023,              /* max absolute value of a MV component */
@@ -78,5 +79,9 @@ extern struct vp8_token_struct vp8_small_mvencodings_hp [16];
 #endif
 
 void vp8_entropy_mv_init();
+#if CONFIG_ADAPTIVE_ENTROPY
+struct VP8Common;
+void vp8_adapt_mv_probs(struct VP8Common *cm);
+#endif
 
 #endif
diff --git a/vp8/common/filter.c b/vp8/common/filter.c
index 856bad5a6524b0a92534e97749b7e99ee657063d..78c2390804a8af35e9c365fab9fda233aaee791c 100644
--- a/vp8/common/filter.c
+++ b/vp8/common/filter.c
@@ -46,7 +46,7 @@ DECLARE_ALIGNED(16, const short, vp8_bilinear_filters[SUBPEL_SHIFTS][2]) = {
 #if CONFIG_ENHANCED_INTERP
 
 #define FILTER_ALPHA       0
-#define FILTER_ALPHA_SHARP 60
+#define FILTER_ALPHA_SHARP 1
 DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8[SUBPEL_SHIFTS][2 * INTERP_EXTEND]) = {
 #if SUBPEL_SHIFTS==16
 #if FILTER_ALPHA == 0
@@ -91,24 +91,6 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8[SUBPEL_SHIFTS][2 * INTERP
   { 0,   3,  -9,  27, 118, -13,   3, -1},
   { 0,   2,  -6,  18, 122, -10,   2,  0},
   { 0,   1,  -3,   8, 126,  -5,   1,  0}
-#elif FILTER_ALPHA == 45
-  /* alpha = 0.45 */
-  { 0,   0,   0, 128,   0,   0,   0,  0},
-  { 0,   1,  -5, 126,   8,  -3,   1,  0},
-  { 0,   2,  -9, 122,  17,  -6,   2,  0},
-  { 0,   3, -13, 117,  27,  -8,   2,  0},
-  { -1,   4, -15, 111,  37, -11,   3,  0},
-  { -1,   4, -17, 104,  47, -13,   4,  0},
-  { -1,   5, -18,  96,  58, -15,   4, -1},
-  { -1,   5, -18,  87,  68, -17,   5, -1},
-  { -1,   5, -18,  78,  78, -18,   5, -1},
-  { -1,   5, -17,  68,  87, -18,   5, -1},
-  { -1,   4, -15,  58,  96, -18,   5, -1},
-  { 0,   4, -13,  47, 104, -17,   4, -1},
-  { 0,   3, -11,  37, 111, -15,   4, -1},
-  { 0,   2,  -8,  27, 117, -13,   3,  0},
-  { 0,   2,  -6,  17, 122,  -9,   2,  0},
-  { 0,   1,  -3,   8, 126,  -5,   1,  0}
 #endif  /* FILTER_ALPHA */
 #else   /* SUBPEL_SHIFTS==16 */
 #if FILTER_ALPHA == 0
@@ -130,23 +112,48 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8[SUBPEL_SHIFTS][2 * INTERP
   { -1,   5, -16,  58,  96, -18,   5, -1},
   { 0,   3, -11,  37, 112, -16,   4, -1},
   { 0,   2,  -6,  18, 122, -10,   2,  0}
-#elif FILTER_ALPHA == 45
-  /* alpha = 0.45 */
-  { 0,   0,   0, 128,   0,   0,   0,  0},
-  { 0,   2,  -9, 122,  17,  -6,   2,  0},
-  { -1,   4, -15, 111,  37, -11,   3,  0},
-  { -1,   5, -18,  96,  58, -15,   4, -1},
-  { -1,   5, -18,  78,  78, -18,   5, -1},
-  { -1,   4, -15,  58,  96, -18,   5, -1},
-  { 0,   3, -11,  37, 111, -15,   4, -1},
-  { 0,   2,  -6,  17, 122,  -9,   2,  0},
 #endif  /* FILTER_ALPHA */
 #endif  /* SUBPEL_SHIFTS==16 */
 };
 
 DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8s[SUBPEL_SHIFTS][2 * INTERP_EXTEND]) = {
 #if SUBPEL_SHIFTS==16
-#if FILTER_ALPHA_SHARP == 65
+#if FILTER_ALPHA_SHARP == 1
+  /* dct based filter */
+  {0,   0,   0, 128,   0,   0,   0, 0},
+  {-1,   3,  -7, 127,   8,  -3,   1, 0},
+  {-2,   5, -13, 125,  17,  -6,   3, -1},
+  {-3,   7, -17, 121,  27, -10,   5, -2},
+  {-4,   9, -20, 115,  37, -13,   6, -2},
+  {-4,  10, -23, 108,  48, -16,   8, -3},
+  {-4,  10, -24, 100,  59, -19,   9, -3},
+  {-4,  11, -24,  90,  70, -21,  10, -4},
+  {-4,  11, -23,  80,  80, -23,  11, -4},
+  {-4,  10, -21,  70,  90, -24,  11, -4},
+  {-3,   9, -19,  59, 100, -24,  10, -4},
+  {-3,   8, -16,  48, 108, -23,  10, -4},
+  {-2,   6, -13,  37, 115, -20,   9, -4},
+  {-2,   5, -10,  27, 121, -17,   7, -3},
+  {-1,   3,  -6,  17, 125, -13,   5, -2},
+  {0,   1,  -3,   8, 127,  -7,   3, -1}
+#elif FILTER_ALPHA_SHARP == 75
+  {0,   0,   0, 128,   0,   0,   0, 0},
+  {-1,   2,  -6, 126,   9,  -3,   2, -1},
+  {-1,   4, -11, 123,  18,  -7,   3, -1},
+  {-2,   6, -16, 119,  28, -10,   5, -2},
+  {-2,   7, -19, 113,  38, -13,   6, -2},
+  {-3,   8, -21, 106,  49, -16,   7, -2},
+  {-3,   9, -22,  99,  59, -19,   8, -3},
+  {-3,   9, -23,  90,  70, -21,   9, -3},
+  {-3,   9, -22,  80,  80, -22,   9, -3},
+  {-3,   9, -21,  70,  90, -23,   9, -3},
+  {-3,   8, -19,  59,  99, -22,   9, -3},
+  {-2,   7, -16,  49, 106, -21,   8, -3},
+  {-2,   6, -13,  38, 113, -19,   7, -2},
+  {-2,   5, -10,  28, 119, -16,   6, -2},
+  {-1,   3,  -7,  18, 123, -11,   4, -1},
+  {-1,   2,  -3,   9, 126,  -6,   2, -1}
+#elif FILTER_ALPHA_SHARP == 65
   /* alpha = 0.65 */
   { 0,   0,   0, 128,   0,   0,   0,  0},
   { 0,   2,  -6, 126,   8,  -3,   1,  0},
@@ -164,45 +171,27 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8s[SUBPEL_SHIFTS][2 * INTER
   { -1,   4, -10,  27, 118, -14,   5, -1},
   { -1,   2,  -6,  18, 123, -10,   3, -1},
   { 0,   1,  -3,   8, 126,  -6,   2,  0}
-#elif FILTER_ALPHA_SHARP == 60
-  /* alpha = 0.60 */
-  { 0,   0,   0, 128,   0,   0,   0,  0},
-  { 0,   2,  -6, 126,   8,  -3,   1,  0},
-  { -1,   3, -10, 123,  18,  -6,   2, -1},
-  { -1,   4, -14, 118,  28,  -9,   3, -1},
-  { -1,   5, -17, 112,  38, -12,   4, -1},
-  { -1,   6, -19, 105,  48, -15,   5, -1},
-  { -1,   6, -20,  97,  58, -17,   6, -1},
-  { -1,   6, -20,  88,  69, -19,   6, -1},
-  { -1,   6, -20,  79,  79, -20,   6, -1},
-  { -1,   6, -19,  69,  88, -20,   6, -1},
-  { -1,   6, -17,  58,  97, -20,   6, -1},
-  { -1,   5, -15,  48, 105, -19,   6, -1},
-  { -1,   4, -12,  38, 112, -17,   5, -1},
-  { -1,   3,  -9,  28, 118, -14,   4, -1},
-  { -1,   2,  -6,  18, 123, -10,   3, -1},
-  { 0,   1,  -3,   8, 126,  -6,   2,  0}
-#elif FILTER_ALPHA_SHARP == 55
-  /* alpha = 0.55 */
-  { 0,   0,   0, 128,   0,   0,   0,  0},
-  { 0,   1,  -5, 126,   8,  -3,   1,  0},
-  { -1,   2, -10, 123,  18,  -6,   2,  0},
-  { -1,   4, -13, 118,  27,  -9,   3, -1},
-  { -1,   5, -16, 112,  37, -12,   4, -1},
-  { -1,   5, -18, 105,  48, -14,   4, -1},
-  { -1,   5, -19,  97,  58, -16,   5, -1},
-  { -1,   6, -19,  88,  68, -18,   5, -1},
-  { -1,   6, -19,  78,  78, -19,   6, -1},
-  { -1,   5, -18,  68,  88, -19,   6, -1},
-  { -1,   5, -16,  58,  97, -19,   5, -1},
-  { -1,   4, -14,  48, 105, -18,   5, -1},
-  { -1,   4, -12,  37, 112, -16,   5, -1},
-  { -1,   3,  -9,  27, 118, -13,   4, -1},
-  { 0,   2,  -6,  18, 123, -10,   2, -1},
-  { 0,   1,  -3,   8, 126,  -5,   1,  0}
 #endif  /* FILTER_ALPHA_SHARP */
 #else   /* SUBPEL_SHIFTS==16 */
-#if FILTER_ALPHA_SHARP == 65
+#if FILTER_ALPHA_SHARP == 1
+  {0,   0,   0, 128,   0,   0,   0, 0},
+  {-2,   5, -13, 125,  17,  -6,   3, -1},
+  {-4,   9, -20, 115,  37, -13,   6, -2},
+  {-4,  10, -24, 100,  59, -19,   9, -3},
+  {-4,  10, -23,  81,  81, -23,  10, -4},
+  {-3,   9, -19,  59, 100, -24,  10, -4},
+  {-2,   6, -13,  37, 115, -20,   9, -4},
+  {-1,   3,  -6,  17, 125, -13,   5, -2}
+#elif FILTER_ALPHA_SHARP == 75
+  {0,   0,   0, 128,   0,   0,   0, 0},
+  {-1,   4, -11, 123,  18,  -7,   3, -1},
+  {-2,   7, -19, 113,  38, -13,   6, -2},
+  {-3,   9, -22,  99,  59, -19,   8, -3},
+  {-3,   9, -22,  80,  80, -22,   9, -3},
+  {-3,   8, -19,  59,  99, -22,   9, -3},
+  {-2,   6, -13,  38, 113, -19,   7, -2},
+  {-1,   3,  -7,  18, 123, -11,   4, -1}
+#elif FILTER_ALPHA_SHARP == 65
   /* alpha = 0.65 */
   { 0,   0,   0, 128,   0,   0,   0, 0},
   { -1,   3, -10, 123,  18,  -6,   2, -1},
@@ -212,26 +201,6 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8s[SUBPEL_SHIFTS][2 * INTER
   { -2,   6, -17,  59,  98, -21,   7, -2},
   { -1,   5, -13,  38, 112, -17,   5, -1},
   { -1,   2,  -6,  18, 123, -10,   3, -1}
-#elif FILTER_ALPHA_SHARP == 60
-  /* alpha = 0.60 */
-  { 0,   0,   0, 128,   0,   0,   0, 0},
-  { -1,   3, -10, 123,  18,  -6,   2, -1},
-  { -1,   5, -17, 112,  38, -12,   4, -1},
-  { -1,   6, -20,  97,  58, -17,   6, -1},
-  { -1,   6, -20,  79,  79, -20,   6, -1},
-  { -1,   6, -17,  58,  97, -20,   6, -1},
-  { -1,   4, -12,  38, 112, -17,   5, -1},
-  { -1,   2,  -6,  18, 123, -10,   3, -1}
-#elif FILTER_ALPHA_SHARP == 55
-  /* alpha = 0.55 */
-  { 0,   0,   0, 128,   0,   0,   0,  0},
-  { -1,   2, -10, 123,  18,  -6,   2,  0},
-  { -1,   5, -16, 112,  37, -12,   4, -1},
-  { -1,   5, -19,  97,  58, -16,   5, -1},
-  { -1,   6, -19,  78,  78, -19,   6, -1},
-  { -1,   5, -16,  58,  97, -19,   5, -1},
-  { -1,   4, -12,  37, 112, -16,   5, -1},
-  { 0,   2,  -6,  18, 123, -10,   2, -1}
 #endif  /* FILTER_ALPHA_SHARP */
 #endif  /* SUBPEL_SHIFTS==16 */
 };
diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h
index 8f2417f66301fb7da57a69e7e28df5eb8944585f..ccecc49630bf71569c458939c5644d2ec8110562 100644
--- a/vp8/common/onyxc_int.h
+++ b/vp8/common/onyxc_int.h
@@ -17,6 +17,7 @@
 #include "loopfilter.h"
 #include "entropymv.h"
 #include "entropy.h"
+#include "entropymode.h"
 #include "idct.h"
 #include "recon.h"
 #if CONFIG_POSTPROC
@@ -82,6 +83,11 @@ typedef struct frame_contexts {
 #if CONFIG_HIGH_PRECISION_MV
   unsigned int MVcount_hp [2] [MVvals_hp];
 #endif
+#if CONFIG_SWITCHABLE_INTERP
+  vp8_prob switchable_interp_prob[VP8_SWITCHABLE_FILTERS+1]
+                                 [VP8_SWITCHABLE_FILTERS-1];
+#endif
+
   int mode_context[6][4];
   int mode_context_a[6][4];
   int vp8_mode_contexts[6][4];
@@ -94,15 +100,6 @@ typedef enum {
   RECON_CLAMP_NOTREQUIRED     = 1
 } CLAMP_TYPE;
 
-typedef enum {
-  SIXTAP   = 0,
-  BILINEAR = 1,
-#if CONFIG_ENHANCED_INTERP
-  EIGHTTAP = 2,
-  EIGHTTAP_SHARP = 3,
-#endif
-} INTERPOLATIONFILTERTYPE;
-
 typedef enum {
   SINGLE_PREDICTION_ONLY = 0,
   COMP_PREDICTION_ONLY   = 1,
diff --git a/vp8/common/pred_common.c b/vp8/common/pred_common.c
index 2d46496f1903674ee64d6970da2c0702df9a5b84..b7d52a54f5908b0d6ddbc2406f7f79c1effbc0dd 100644
--- a/vp8/common/pred_common.c
+++ b/vp8/common/pred_common.c
@@ -62,6 +62,38 @@ unsigned char get_pred_context(VP8_COMMON *const cm,
                      (m - cm->mode_info_stride)->mbmi.mb_skip_coeff;
       break;
 
+#if CONFIG_SWITCHABLE_INTERP
+    case PRED_SWITCHABLE_INTERP:
+      {
+        int left_in_image = (m - 1)->mbmi.mb_in_image;
+        int above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
+        int left_mode = (m - 1)->mbmi.mode;
+        int above_mode = (m - cm->mode_info_stride)->mbmi.mode;
+        int left_interp, above_interp;
+        if (left_in_image && left_mode >= NEARESTMV && left_mode <= SPLITMV)
+          left_interp = vp8_switchable_interp_map[(m - 1)->mbmi.interp_filter];
+        else
+          left_interp = VP8_SWITCHABLE_FILTERS;
+        if (above_in_image && above_mode >= NEARESTMV && above_mode <= SPLITMV)
+          above_interp = vp8_switchable_interp_map[
+              (m - cm->mode_info_stride)->mbmi.interp_filter];
+        else
+          above_interp = VP8_SWITCHABLE_FILTERS;
+
+        if (left_interp == above_interp)
+          pred_context = left_interp;
+        else if (left_interp == VP8_SWITCHABLE_FILTERS &&
+                 above_interp != VP8_SWITCHABLE_FILTERS)
+          pred_context = above_interp;
+        else if (left_interp != VP8_SWITCHABLE_FILTERS &&
+                 above_interp == VP8_SWITCHABLE_FILTERS)
+          pred_context = left_interp;
+        else
+          pred_context = VP8_SWITCHABLE_FILTERS;
+      }
+      break;
+#endif
+
     default:
       // TODO *** add error trap code.
       pred_context = 0;
@@ -111,6 +143,53 @@ vp8_prob get_pred_prob(VP8_COMMON *const cm,
   return pred_probability;
 }
 
+// This function returns a context probability ptr for coding a given
+// prediction signal
+vp8_prob *get_pred_probs(VP8_COMMON *const cm,
+                         MACROBLOCKD *const xd,
+                         PRED_ID pred_id) {
+  vp8_prob *pred_probability;
+  int pred_context;
+
+  // Get the appropriate prediction context
+  pred_context = get_pred_context(cm, xd, pred_id);
+
+  switch (pred_id) {
+    case PRED_SEG_ID:
+      pred_probability = &cm->segment_pred_probs[pred_context];
+      break;
+
+    case PRED_REF:
+      pred_probability = &cm->ref_pred_probs[pred_context];
+      break;
+
+    case PRED_COMP:
+      // In keeping with convention elsewhre the probability returned is
+      // the probability of a "0" outcome which in this case means the
+      // probability of comp pred off.
+      pred_probability = &cm->prob_comppred[pred_context];
+      break;
+
+#if CONFIG_NEWENTROPY
+    case PRED_MBSKIP:
+      pred_probability = &cm->mbskip_pred_probs[pred_context];
+      break;
+#endif
+
+#if CONFIG_SWITCHABLE_INTERP
+    case PRED_SWITCHABLE_INTERP:
+      pred_probability = &cm->fc.switchable_interp_prob[pred_context][0];
+      break;
+#endif
+    default:
+      // TODO *** add error trap code.
+      pred_probability = NULL;
+      break;
+  }
+
+  return pred_probability;
+}
+
 // This function returns the status of the given prediction signal.
 // I.e. is the predicted value for the given signal correct.
 unsigned char get_pred_flag(MACROBLOCKD *const xd,
diff --git a/vp8/common/pred_common.h b/vp8/common/pred_common.h
index a1b019fc6ecbb311291779ff934fe18a7019344b..f4992f55546f866894081aba476aafcf8278d3d3 100644
--- a/vp8/common/pred_common.h
+++ b/vp8/common/pred_common.h
@@ -22,6 +22,9 @@ typedef enum {
   PRED_REF = 1,
   PRED_COMP = 2,
   PRED_MBSKIP = 3,
+#if CONFIG_SWITCHABLE_INTERP
+  PRED_SWITCHABLE_INTERP = 4,
+#endif
 } PRED_ID;
 
 
@@ -33,6 +36,10 @@ extern vp8_prob get_pred_prob(VP8_COMMON *const cm,
                               MACROBLOCKD *const xd,
                               PRED_ID pred_id);
 
+extern vp8_prob *get_pred_probs(VP8_COMMON *const cm,
+                                MACROBLOCKD *const xd,
+                                PRED_ID pred_id);
+
 extern unsigned char get_pred_flag(MACROBLOCKD *const xd,
                                    PRED_ID pred_id);
 
diff --git a/vp8/common/reconinter.c b/vp8/common/reconinter.c
index d94ab4449f1b1fe94d78ecb45b76a18d2493eacf..6f7d963c6cc3364a0728047fb8cbd4cd1ae2c42b 100644
--- a/vp8/common/reconinter.c
+++ b/vp8/common/reconinter.c
@@ -19,6 +19,81 @@
 #include "onyxc_int.h"
 #endif
 
+void vp8_setup_interp_filters(MACROBLOCKD *xd,
+                              INTERPOLATIONFILTERTYPE mcomp_filter_type,
+                              VP8_COMMON *cm) {
+  if (mcomp_filter_type == SIXTAP) {
+    xd->subpixel_predict        = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, sixtap4x4);
+    xd->subpixel_predict8x4     = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, sixtap8x4);
+    xd->subpixel_predict8x8     = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, sixtap8x8);
+    xd->subpixel_predict16x16   = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, sixtap16x16);
+    xd->subpixel_predict_avg    = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, sixtap_avg4x4);
+    xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, sixtap_avg8x8);
+    xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, sixtap_avg16x16);
+  }
+#if CONFIG_ENHANCED_INTERP
+  else if (mcomp_filter_type == EIGHTTAP
+#if CONFIG_SWITCHABLE_INTERP
+           ||
+           mcomp_filter_type == SWITCHABLE
+#endif
+          ) {
+    xd->subpixel_predict        = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap4x4);
+    xd->subpixel_predict8x4     = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap8x4);
+    xd->subpixel_predict8x8     = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap8x8);
+    xd->subpixel_predict16x16   = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap16x16);
+    xd->subpixel_predict_avg    = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap_avg4x4);
+    xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap_avg8x8);
+    xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap_avg16x16);
+  } else if (mcomp_filter_type == EIGHTTAP_SHARP) {
+    xd->subpixel_predict        = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap4x4_sharp);
+    xd->subpixel_predict8x4     = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap8x4_sharp);
+    xd->subpixel_predict8x8     = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap8x8_sharp);
+    xd->subpixel_predict16x16   = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap16x16_sharp);
+    xd->subpixel_predict_avg    = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap_avg4x4_sharp);
+    xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap_avg8x8_sharp);
+    xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, eighttap_avg16x16_sharp);
+  }
+#endif
+  else {
+    xd->subpixel_predict        = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, bilinear4x4);
+    xd->subpixel_predict8x4     = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, bilinear8x4);
+    xd->subpixel_predict8x8     = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, bilinear8x8);
+    xd->subpixel_predict16x16   = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, bilinear16x16);
+    xd->subpixel_predict_avg    = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, bilinear_avg4x4);
+    xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, bilinear_avg8x8);
+    xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
+        &cm->rtcd.subpix, bilinear_avg16x16);
+  }
+}
+
 void vp8_copy_mem16x16_c(
   unsigned char *src,
   int src_stride,
diff --git a/vp8/common/reconinter.h b/vp8/common/reconinter.h
index 0f8b44f220c8cbfd29443f41fee88c0963496c2b..7755c526e7d34561a877172edf31e32f869d7bc1 100644
--- a/vp8/common/reconinter.h
+++ b/vp8/common/reconinter.h
@@ -12,6 +12,10 @@
 #ifndef __INC_RECONINTER_H
 #define __INC_RECONINTER_H
 
+#if CONFIG_RUNTIME_CPU_DETECT
+#include "onyxc_int.h"
+#endif
+
 extern void vp8_build_inter_predictors_mb(MACROBLOCKD *x);
 extern void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
                                                unsigned char *dst_y,
@@ -33,5 +37,6 @@ extern void vp8_build_2nd_inter_predictors_b(BLOCKD *d, int pitch, vp8_subpix_fn
 
 extern void vp8_build_inter16x16_predictors_mbuv(MACROBLOCKD *x);
 extern void vp8_build_inter4x4_predictors_mbuv(MACROBLOCKD *x);
+extern void vp8_setup_interp_filters(MACROBLOCKD *x, INTERPOLATIONFILTERTYPE filter, VP8_COMMON *cm);
 
 #endif
diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c
index 4b4ad919ebfad764fe797bee211456e22e4f80c7..3cfdbac0bf777c069e977f8756d0ce3e54b71016 100644
--- a/vp8/decoder/decodemv.c
+++ b/vp8/decoder/decodemv.c
@@ -427,7 +427,21 @@ static const unsigned char mbsplit_fill_offset[4][16] = {
   { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15}
 };
 
-
+#if CONFIG_SWITCHABLE_INTERP
+static void read_switchable_interp_probs(VP8D_COMP *pbi) {
+  VP8_COMMON *const cm = & pbi->common;
+  vp8_reader *const bc = & pbi->bc;
+  int i, j;
+  for (j = 0; j <= VP8_SWITCHABLE_FILTERS; ++j) {
+  //for (j = 0; j <= 0; ++j) {
+    for (i = 0; i < VP8_SWITCHABLE_FILTERS - 1; ++i) {
+      cm->fc.switchable_interp_prob[j][i] = vp8_read_literal(bc, 8);
+    }
+  }
+  //printf("DECODER: %d %d\n", cm->fc.switchable_interp_prob[0],
+  //cm->fc.switchable_interp_prob[1]);
+}
+#endif
 
 static void mb_mode_mv_init(VP8D_COMP *pbi) {
   VP8_COMMON *const cm = & pbi->common;
@@ -451,6 +465,10 @@ static void mb_mode_mv_init(VP8D_COMP *pbi) {
 
     if (cm->pred_filter_mode == 2)
       cm->prob_pred_filter_off = (vp8_prob)vp8_read_literal(bc, 8);
+#endif
+#if CONFIG_SWITCHABLE_INTERP
+    if (cm->mcomp_filter_type == SWITCHABLE)
+      read_switchable_interp_probs(pbi);
 #endif
     // Decode the baseline probabilities for decoding reference frame
     cm->prob_intra_coded = (vp8_prob)vp8_read_literal(bc, 8);
@@ -634,6 +652,19 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
         mbmi->pred_filter_enabled = cm->pred_filter_mode;
     }
 #endif
+#if CONFIG_SWITCHABLE_INTERP
+    if (mbmi->mode >= NEARESTMV && mbmi->mode <= SPLITMV)
+    {
+      if (cm->mcomp_filter_type == SWITCHABLE) {
+        mbmi->interp_filter = vp8_switchable_interp[
+            vp8_treed_read(bc, vp8_switchable_interp_tree,
+                           get_pred_probs(cm, xd, PRED_SWITCHABLE_INTERP))];
+        //printf("Reading: %d\n", mbmi->interp_filter);
+      } else {
+        mbmi->interp_filter = cm->mcomp_filter_type;
+      }
+    }
+#endif
 
     if (cm->comp_pred_mode == COMP_PREDICTION_ONLY ||
         (cm->comp_pred_mode == HYBRID_PREDICTION &&
@@ -928,8 +959,8 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
 #endif
       }
     } else {
-      mbmi->uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(bc,
-                                                           pbi->common.fc.uv_mode_prob[mbmi->mode]);
+      mbmi->uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(
+		      bc, pbi->common.fc.uv_mode_prob[mbmi->mode]);
       pbi->common.fc.uv_mode_counts[mbmi->mode][mbmi->uv_mode]++;
     }
 
diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c
index 8cd35143aceb586eed64ba4f1f36b1a52ad2eeec..c31595d59834b130973a7f07c0a7b0c7ea394e1f 100644
--- a/vp8/decoder/decodframe.c
+++ b/vp8/decoder/decodframe.c
@@ -261,6 +261,11 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
   }
 
   mode = xd->mode_info_context->mbmi.mode;
+#if CONFIG_SWITCHABLE_INTERP
+  if (pbi->common.frame_type != KEY_FRAME)
+    vp8_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter,
+                             &pbi->common);
+#endif
 
   if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV
       && mode != I8X8_PRED
@@ -750,47 +755,7 @@ static void init_frame(VP8D_COMP *pbi) {
       pc->mcomp_filter_type = BILINEAR;
 
     /* To enable choice of different interploation filters */
-    if (pc->mcomp_filter_type == SIXTAP) {
-      xd->subpixel_predict      = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap4x4);
-      xd->subpixel_predict8x4   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x4);
-      xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x8);
-      xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap16x16);
-      xd->subpixel_predict_avg  = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg4x4);
-      xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg8x8);
-      xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg16x16);
-    }
-#if CONFIG_ENHANCED_INTERP
-    else if (pc->mcomp_filter_type == EIGHTTAP) {
-      xd->subpixel_predict      = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4);
-      xd->subpixel_predict8x4   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4);
-      xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8);
-      xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16);
-      xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
-                                      RTCD_VTABLE(subpix), eighttap_avg8x8);
-      xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
-                                        RTCD_VTABLE(subpix), eighttap_avg16x16);
-      xd->subpixel_predict_avg  = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg4x4);
-    } else if (pc->mcomp_filter_type == EIGHTTAP_SHARP) {
-      xd->subpixel_predict      = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4_sharp);
-      xd->subpixel_predict8x4   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4_sharp);
-      xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8_sharp);
-      xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16_sharp);
-      xd->subpixel_predict_avg  = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg4x4_sharp);
-      xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
-                                      RTCD_VTABLE(subpix), eighttap_avg8x8_sharp);
-      xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
-                                        RTCD_VTABLE(subpix), eighttap_avg16x16_sharp);
-    }
-#endif
-    else {
-      xd->subpixel_predict      = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear4x4);
-      xd->subpixel_predict8x4   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x4);
-      xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
-      xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16);
-      xd->subpixel_predict_avg  = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg4x4);
-      xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg8x8);
-      xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg16x16);
-    }
+    vp8_setup_interp_filters(xd, pc->mcomp_filter_type, pc);
   }
 
   xd->left_context = &pc->left_context;
@@ -1263,41 +1228,16 @@ int vp8_decode_frame(VP8D_COMP *pbi) {
 #endif
 #if CONFIG_ENHANCED_INTERP
     // Read the type of subpel filter to use
-    pc->mcomp_filter_type = vp8_read_literal(bc, 2);
-    /* To enable choice of different interploation filters */
-    if (pc->mcomp_filter_type == SIXTAP) {
-      xd->subpixel_predict      = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap4x4);
-      xd->subpixel_predict8x4   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x4);
-      xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x8);
-      xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap16x16);
-      xd->subpixel_predict_avg  = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg4x4);
-      xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg8x8);
-      xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg16x16);
-    } else if (pc->mcomp_filter_type == EIGHTTAP) {
-      xd->subpixel_predict      = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4);
-      xd->subpixel_predict8x4   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4);
-      xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8);
-      xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16);
-      xd->subpixel_predict_avg  = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg4x4);
-      xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg8x8);
-      xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg16x16);
-    } else if (pc->mcomp_filter_type == EIGHTTAP_SHARP) {
-      xd->subpixel_predict      = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4_sharp);
-      xd->subpixel_predict8x4   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4_sharp);
-      xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8_sharp);
-      xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16_sharp);
-      xd->subpixel_predict_avg  = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg4x4_sharp);
-      xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg8x8_sharp);
-      xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg16x16_sharp);
-    } else {
-      xd->subpixel_predict      = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear4x4);
-      xd->subpixel_predict8x4   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x4);
-      xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
-      xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16);
-      xd->subpixel_predict_avg  = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg4x4);
-      xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg8x8);
-      xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg16x16);
+#if CONFIG_SWITCHABLE_INTERP
+    if (vp8_read_bit(bc)) {
+      pc->mcomp_filter_type = SWITCHABLE;
+    } else
+#endif
+    {
+      pc->mcomp_filter_type = vp8_read_literal(bc, 2);
     }
+    /* To enable choice of different interploation filters */
+    vp8_setup_interp_filters(xd, pc->mcomp_filter_type, pc);
 #endif
   }
 
diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c
index db3e309823998992f567b7f25a950a466087054a..97e791bc673b3414e0e489770dda1aecd0edb5ee 100644
--- a/vp8/encoder/bitstream.c
+++ b/vp8/encoder/bitstream.c
@@ -33,17 +33,15 @@ unsigned __int64 Sectionbits[500];
 #endif
 
 #ifdef ENTROPY_STATS
-int intra_mode_stats[VP8_BINTRAMODES]
-[VP8_BINTRAMODES]
-[VP8_BINTRAMODES];
+int intra_mode_stats [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES];
 unsigned int tree_update_hist [BLOCK_TYPES]
-[COEF_BANDS]
-[PREV_COEF_CONTEXTS]
-[ENTROPY_NODES][2];
+                              [COEF_BANDS]
+                              [PREV_COEF_CONTEXTS]
+                              [ENTROPY_NODES][2];
 unsigned int tree_update_hist_8x8 [BLOCK_TYPES_8X8]
-[COEF_BANDS]
-[PREV_COEF_CONTEXTS]
-[ENTROPY_NODES] [2];
+                                  [COEF_BANDS]
+                                  [PREV_COEF_CONTEXTS]
+                                  [ENTROPY_NODES] [2];
 
 extern unsigned int active_section;
 #endif
@@ -173,6 +171,59 @@ void update_skip_probs(VP8_COMP *cpi) {
   }
 }
 
+#if CONFIG_SWITCHABLE_INTERP
+void update_switchable_interp_probs(VP8_COMP *cpi) {
+  VP8_COMMON *const pc = & cpi->common;
+  vp8_writer *const w = & cpi->bc;
+  unsigned int branch_ct[32][2];
+  int i, j;
+  for (j = 0; j <= VP8_SWITCHABLE_FILTERS; ++j) {
+  //for (j = 0; j <= 0; ++j) {
+/*
+    if (!cpi->dummy_packing)
+#if VP8_SWITCHABLE_FILTERS == 3
+      printf("HELLO %d %d %d\n", cpi->switchable_interp_count[j][0],
+             cpi->switchable_interp_count[j][1], cpi->switchable_interp_count[j][2]);
+#else
+      printf("HELLO %d %d\n", cpi->switchable_interp_count[j][0],
+             cpi->switchable_interp_count[j][1]);
+#endif
+*/
+    vp8_tree_probs_from_distribution(
+        VP8_SWITCHABLE_FILTERS,
+        vp8_switchable_interp_encodings, vp8_switchable_interp_tree,
+        pc->fc.switchable_interp_prob[j], branch_ct, cpi->switchable_interp_count[j],
+        256, 1
+        );
+    for (i = 0; i < VP8_SWITCHABLE_FILTERS - 1; ++i) {
+      if (pc->fc.switchable_interp_prob[j][i] < 1)
+        pc->fc.switchable_interp_prob[j][i] = 1;
+      vp8_write_literal(w, pc->fc.switchable_interp_prob[j][i], 8);
+/*
+      if (!cpi->dummy_packing)
+#if VP8_SWITCHABLE_FILTERS == 3
+        printf("Probs %d %d [%d]\n",
+               pc->fc.switchable_interp_prob[j][0],
+               pc->fc.switchable_interp_prob[j][1], pc->frame_type);
+#else
+        printf("Probs %d [%d]\n", pc->fc.switchable_interp_prob[j][0],
+               pc->frame_type);
+#endif
+*/
+    }
+  }
+  /*
+  if (!cpi->dummy_packing)
+#if VP8_SWITCHABLE_FILTERS == 3
+    printf("Probs %d %d [%d]\n",
+           pc->fc.switchable_interp_prob[0], pc->fc.switchable_interp_prob[1], pc->frame_type);
+#else
+    printf("Probs %d [%d]\n", pc->fc.switchable_interp_prob[0], pc->frame_type);
+#endif
+  */
+}
+#endif
+
 // This function updates the reference frame prediction stats
 static void update_refpred_stats(VP8_COMP *cpi) {
   VP8_COMMON *const cm = & cpi->common;
@@ -710,6 +761,10 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) {
   // printf("pred_filter_mode:%d  prob_pred_filter_off:%d\n",
   //       pc->pred_filter_mode, pc->prob_pred_filter_off);
 #endif
+#if CONFIG_SWITCHABLE_INTERP
+  if (pc->mcomp_filter_type == SWITCHABLE)
+    update_switchable_interp_probs(cpi);
+#endif
 
   vp8_write_literal(w, pc->prob_intra_coded, 8);
   vp8_write_literal(w, pc->prob_last_coded, 8);
@@ -906,6 +961,21 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) {
               assert(mi->pred_filter_enabled ==
                      cpi->common.pred_filter_mode);
           }
+#endif
+#if CONFIG_SWITCHABLE_INTERP
+          if (mode >= NEARESTMV && mode <= SPLITMV)
+          {
+            if (cpi->common.mcomp_filter_type == SWITCHABLE) {
+              vp8_write_token(w, vp8_switchable_interp_tree,
+                              get_pred_probs(&cpi->common, xd, PRED_SWITCHABLE_INTERP),
+                              vp8_switchable_interp_encodings +
+                              vp8_switchable_interp_map[mi->interp_filter]);
+              //if (!cpi->dummy_packing) printf("Reading: %d\n", mi->interp_filter);
+            } else {
+              assert (mi->interp_filter ==
+                      cpi->common.mcomp_filter_type);
+            }
+          }
 #endif
           if (mi->second_ref_frame &&
               (mode == NEWMV || mode == SPLITMV)) {
@@ -2204,9 +2274,34 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
     vp8_write_bit(bc, (xd->allow_high_precision_mv) ? 1 : 0);
 #endif
 #if CONFIG_ENHANCED_INTERP
+#if CONFIG_SWITCHABLE_INTERP
+    if (pc->mcomp_filter_type == SWITCHABLE) {
+      /* Check to see if only one of the filters is actually used */
+      int count[VP8_SWITCHABLE_FILTERS];
+      int i, j, c = 0;
+      for (i = 0; i < VP8_SWITCHABLE_FILTERS; ++i) {
+        count[i] = 0;
+        for (j = 0; j <= VP8_SWITCHABLE_FILTERS; ++j) {
+          count[i] += cpi->switchable_interp_count[j][i];
+        }
+        c += (count[i] > 0);
+      }
+      if (c == 1) {
+        /* Only one filter is used. So set the filter at frame level */
+        for (i = 0; i < VP8_SWITCHABLE_FILTERS; ++i) {
+          if (count[i]) {
+            pc->mcomp_filter_type = vp8_switchable_interp[i];
+            break;
+          }
+        }
+      }
+    }
     // Signal the type of subpel filter to use
-    vp8_write_literal(bc, (pc->mcomp_filter_type), 2);
-#endif
+    vp8_write_bit(bc, (pc->mcomp_filter_type == SWITCHABLE));
+    if (pc->mcomp_filter_type != SWITCHABLE)
+#endif  /* CONFIG_SWITCHABLE_INTERP */
+      vp8_write_literal(bc, (pc->mcomp_filter_type), 2);
+#endif  /* CONFIG_ENHANCED_INTERP */
   }
 
   vp8_write_bit(bc, pc->refresh_entropy_probs);
diff --git a/vp8/encoder/block.h b/vp8/encoder/block.h
index 766e80776a6194f0ecae13150e03bd9d3635e43f..b69ffa94eeaac5c8e0ac48e2ae3e7fd41702d10d 100644
--- a/vp8/encoder/block.h
+++ b/vp8/encoder/block.h
@@ -13,10 +13,10 @@
 #define __INC_BLOCK_H
 
 #include "vp8/common/onyx.h"
-#include "vp8/common/blockd.h"
 #include "vp8/common/entropymv.h"
 #include "vp8/common/entropy.h"
 #include "vpx_ports/mem.h"
+#include "vp8/common/onyxc_int.h"
 
 // motion search site
 typedef struct {
@@ -122,6 +122,10 @@ typedef struct {
   int bmode_costs[VP8_BINTRAMODES][VP8_BINTRAMODES][VP8_BINTRAMODES];
   int i8x8_mode_costs[MB_MODE_COUNT];
   int inter_bmode_costs[B_MODE_COUNT];
+#if CONFIG_SWITCHABLE_INTERP
+  int switchable_interp_costs[VP8_SWITCHABLE_FILTERS+1]
+                             [VP8_SWITCHABLE_FILTERS];
+#endif
 
   // These define limits to motion vector components to prevent them from extending outside the UMV borders
   int mv_col_min;
diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c
index 737348ace8b1689b6ec128027fca36da53111b52..909d569616784699b62a91e9c55e7e10fe759800 100644
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -69,7 +69,6 @@ void vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x,
 static void adjust_act_zbin(VP8_COMP *cpi, MACROBLOCK *x);
 
 
-
 #ifdef MODE_STATS
 unsigned int inter_y_modes[MB_MODE_COUNT];
 unsigned int inter_uv_modes[VP8_UV_MODES];
@@ -1094,71 +1093,7 @@ static void encode_frame_internal(VP8_COMP *cpi) {
   totalrate = 0;
 
   // Functions setup for all frame types so we can use MC in AltRef
-  if (cm->mcomp_filter_type == SIXTAP) {
-    xd->subpixel_predict        = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, sixtap4x4);
-    xd->subpixel_predict8x4     = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, sixtap8x4);
-    xd->subpixel_predict8x8     = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, sixtap8x8);
-    xd->subpixel_predict16x16   = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, sixtap16x16);
-    xd->subpixel_predict_avg    = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, sixtap_avg4x4);
-    xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, sixtap_avg8x8);
-    xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
-                                      &cpi->common.rtcd.subpix, sixtap_avg16x16);
-  }
-#if CONFIG_ENHANCED_INTERP
-  else if (cm->mcomp_filter_type == EIGHTTAP) {
-    xd->subpixel_predict        = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap4x4);
-    xd->subpixel_predict8x4     = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap8x4);
-    xd->subpixel_predict8x8     = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap8x8);
-    xd->subpixel_predict16x16   = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap16x16);
-    xd->subpixel_predict_avg    = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap_avg4x4);
-    xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap_avg8x8);
-    xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
-                                      &cpi->common.rtcd.subpix, eighttap_avg16x16);
-  } else if (cm->mcomp_filter_type == EIGHTTAP_SHARP) {
-    xd->subpixel_predict        = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap4x4_sharp);
-    xd->subpixel_predict8x4     = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap8x4_sharp);
-    xd->subpixel_predict8x8     = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap8x8_sharp);
-    xd->subpixel_predict16x16   = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap16x16_sharp);
-    xd->subpixel_predict_avg    = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap_avg4x4_sharp);
-    xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, eighttap_avg8x8_sharp);
-    xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
-                                      &cpi->common.rtcd.subpix, eighttap_avg16x16_sharp);
-  }
-#endif
-  else {
-    xd->subpixel_predict        = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, bilinear4x4);
-    xd->subpixel_predict8x4     = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, bilinear8x4);
-    xd->subpixel_predict8x8     = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, bilinear8x8);
-    xd->subpixel_predict16x16   = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, bilinear16x16);
-    xd->subpixel_predict_avg    = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, bilinear_avg4x4);
-    xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(
-                                    &cpi->common.rtcd.subpix, bilinear_avg8x8);
-    xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(
-                                      &cpi->common.rtcd.subpix, bilinear_avg16x16);
-  }
+  vp8_setup_interp_filters(xd, cm->mcomp_filter_type, cm);
 
   // Reset frame count of inter 0,0 motion vector usage.
   cpi->inter_zz_count = 0;
@@ -1177,7 +1112,9 @@ static void encode_frame_internal(VP8_COMP *cpi) {
   }
   cpi->pred_filter_on_count = 0;
   cpi->pred_filter_off_count = 0;
-
+#endif
+#if CONFIG_SWITCHABLE_INTERP
+  vp8_zero(cpi->switchable_interp_count);
 #endif
 
 #if 0
@@ -1547,6 +1484,9 @@ void vp8cx_encode_inter_macroblock
 
   x->skip = 0;
 
+#if CONFIG_SWITCHABLE_INTERP
+  vp8_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter, cm);
+#endif
   if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
     // Adjust the zbin based on this MB rate.
     adjust_act_zbin(cpi, x);
diff --git a/vp8/encoder/modecosts.c b/vp8/encoder/modecosts.c
index 8752eead7c7c8cac8f53fc89dc3038733d8ac1ab..b1abd1e2a74d94720cb76276884e5e9f8fa49bc6 100644
--- a/vp8/encoder/modecosts.c
+++ b/vp8/encoder/modecosts.c
@@ -46,4 +46,14 @@ void vp8_init_mode_costs(VP8_COMP *c) {
   vp8_cost_tokens(c->mb.i8x8_mode_costs,
                   x->fc.i8x8_mode_prob, vp8_i8x8_mode_tree);
 
+#if CONFIG_SWITCHABLE_INTERP
+  {
+    int i;
+    for (i = 0; i <= VP8_SWITCHABLE_FILTERS; ++i)
+    //for (i = 0; i <= 0; ++i)
+      vp8_cost_tokens((int *)c->mb.switchable_interp_costs[i],
+                      x->fc.switchable_interp_prob[i],
+                      vp8_switchable_interp_tree);
+  }
+#endif
 }
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index 05fe0ff75dbeffc18699a4602b3a17a28f56775e..5b6684ac863108609b0f9c4c066b76dc9b21666e 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -82,16 +82,16 @@ static void set_default_lf_deltas(VP8_COMP *cpi);
 extern const int vp8_gf_interval_table[101];
 
 #if CONFIG_ENHANCED_INTERP
-#define SEARCH_BEST_FILTER 0            /* to search exhaustively for best filter */
+#define SEARCH_BEST_FILTER 0            /* to search for best filter */
 #define RESET_FOREACH_FILTER 0          /* whether to reset the encoder state
-before trying each new filter */
+                                         * before trying each new filter */
+#define SHARP_FILTER_QTHRESH 0         /* Q threshold for 8-tap sharp filter */
 #endif
 #if CONFIG_HIGH_PRECISION_MV
 #define ALTREF_HIGH_PRECISION_MV 1      /* whether to use high precision mv for altref computation */
-#define HIGH_PRECISION_MV_QTHRESH 200   /* Q threshold for use of high precision mv */
-/* Choose a very high value for now so
- * that HIGH_PRECISION is always chosen
- */
+#define HIGH_PRECISION_MV_QTHRESH 200   /* Q threshold for use of high precision mv
+                                         * Choose a very high value for now so
+                                         * that HIGH_PRECISION is always chosen */
 #endif
 
 #if CONFIG_INTERNAL_STATS
@@ -207,6 +207,7 @@ int calculate_minq_index(double maxq,
   }
   return QINDEX_RANGE - 1;
 }
+
 void init_minq_luts() {
   int i;
   double maxq;
@@ -706,6 +707,14 @@ void vp8_set_speed_features(VP8_COMP *cpi) {
 
       sf->thresh_mult[THR_V_PRED   ] = 1000;
       sf->thresh_mult[THR_H_PRED   ] = 1000;
+#if CONFIG_NEWINTRAMODES
+      sf->thresh_mult[THR_D45_PRED ] = 1000;
+      sf->thresh_mult[THR_D135_PRED] = 1000;
+      sf->thresh_mult[THR_D117_PRED] = 1000;
+      sf->thresh_mult[THR_D153_PRED] = 1000;
+      sf->thresh_mult[THR_D27_PRED ] = 1000;
+      sf->thresh_mult[THR_D63_PRED ] = 1000;
+#endif
       sf->thresh_mult[THR_B_PRED   ] = 2000;
       sf->thresh_mult[THR_I8X8_PRED] = 2000;
       sf->thresh_mult[THR_TM       ] = 1000;
@@ -2902,7 +2911,13 @@ static void encode_frame_to_data_rate
 #endif
 
   /* list of filters to search over */
-  int mcomp_filters_to_search[] = {EIGHTTAP, EIGHTTAP_SHARP, SIXTAP};
+  int mcomp_filters_to_search[] = {
+#if CONFIG_SWITCHABLE_INTERP
+    EIGHTTAP, EIGHTTAP_SHARP, SIXTAP, SWITCHABLE
+#else
+    EIGHTTAP, EIGHTTAP_SHARP, SIXTAP,
+#endif
+  };
   int mcomp_filters = sizeof(mcomp_filters_to_search) / sizeof(*mcomp_filters_to_search);
   int mcomp_filter_index = 0;
   INT64 mcomp_filter_cost[4];
@@ -3129,8 +3144,14 @@ static void encode_frame_to_data_rate
     if (sf->search_best_filter) {
       cm->mcomp_filter_type = mcomp_filters_to_search[0];
       mcomp_filter_index = 0;
-    } else
-      cm->mcomp_filter_type = EIGHTTAP;
+    } else {
+#if CONFIG_SWITCHABLE_INTERP
+      cm->mcomp_filter_type = SWITCHABLE;
+#else
+      cm->mcomp_filter_type =
+          (Q < SHARP_FILTER_QTHRESH ? EIGHTTAP_SHARP : EIGHTTAP);
+#endif
+    }
 #endif
 #if CONFIG_HIGH_PRECISION_MV
     /* TODO: Decide this more intelligently */
@@ -3434,7 +3455,9 @@ static void encode_frame_to_data_rate
         Q = q_low;
 
       // Clamp cpi->zbin_over_quant
-      cpi->zbin_over_quant = (cpi->zbin_over_quant < zbin_oq_low) ? zbin_oq_low : (cpi->zbin_over_quant > zbin_oq_high) ? zbin_oq_high : cpi->zbin_over_quant;
+      cpi->zbin_over_quant = (cpi->zbin_over_quant < zbin_oq_low) ?
+          zbin_oq_low : (cpi->zbin_over_quant > zbin_oq_high) ?
+          zbin_oq_high : cpi->zbin_over_quant;
 
       // Loop = ((Q != last_q) || (last_zbin_oq != cpi->zbin_over_quant)) ? TRUE : FALSE;
       Loop = ((Q != last_q)) ? TRUE : FALSE;
@@ -3445,6 +3468,40 @@ static void encode_frame_to_data_rate
     if (cpi->is_src_frame_alt_ref)
       Loop = FALSE;
 
+#if CONFIG_ENHANCED_INTERP && CONFIG_SWITCHABLE_INTERP
+    if (cm->frame_type != KEY_FRAME &&
+        !sf->search_best_filter &&
+        cm->mcomp_filter_type == SWITCHABLE) {
+      int interp_factor = Q / 3;  /* denominator is 256 */
+      int count[VP8_SWITCHABLE_FILTERS];
+      int tot_count = 0, c = 0, thr;
+      int i, j;
+      for (i = 0; i < VP8_SWITCHABLE_FILTERS; ++i) {
+        count[i] = 0;
+        for (j = 0; j <= VP8_SWITCHABLE_FILTERS; ++j) {
+          count[i] += cpi->switchable_interp_count[j][i];
+        }
+        tot_count += count[i];
+      }
+
+      thr = ((tot_count * interp_factor + 128) >> 8);
+      for (i = 0; i < VP8_SWITCHABLE_FILTERS; ++i) {
+        c += (count[i] >= thr);
+      }
+      if (c == 1) {
+        /* Mostly one filter is used. So set the filter at frame level */
+        for (i = 0; i < VP8_SWITCHABLE_FILTERS; ++i) {
+          if (count[i]) {
+            cm->mcomp_filter_type = vp8_switchable_interp[i];
+            Loop = TRUE;  /* Make sure to loop since the filter changed */
+            //loop_count = -1;
+            break;
+          }
+        }
+      }
+    }
+#endif
+
 #if CONFIG_ENHANCED_INTERP
     if (Loop == FALSE && cm->frame_type != KEY_FRAME && sf->search_best_filter) {
       if (mcomp_filter_index < mcomp_filters) {
@@ -3498,7 +3555,7 @@ static void encode_frame_to_data_rate
 #endif
       }
     }
-#endif
+#endif  /* CONFIG_ENHANCED_INTERP */
 
     if (Loop == TRUE) {
       loop_count++;
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
index cf7193324a34056e3883dca9585e164404923574..2821aadd0414b1741cb98e92c8a519f70fb05829 100644
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -102,6 +102,11 @@ typedef struct {
   vp8_prob sub_mv_ref_prob [SUBMVREF_COUNT][VP8_SUBMVREFS - 1];
   vp8_prob mbsplit_prob [VP8_NUMMBSPLITS - 1];
 
+#if CONFIG_SWITCHABLE_INTERP
+  vp8_prob switchable_interp_prob[VP8_SWITCHABLE_FILTERS + 1]
+                                 [VP8_SWITCHABLE_FILTERS - 1];
+#endif
+
   int mv_ref_ct[6][4][2];
   int mode_context[6][4];
   int mv_ref_ct_a[6][4][2];
@@ -724,6 +729,10 @@ typedef struct VP8_COMP {
   int pred_filter_on_count;
   int pred_filter_off_count;
 #endif
+#if CONFIG_SWITCHABLE_INTERP
+  unsigned int switchable_interp_count[VP8_SWITCHABLE_FILTERS+1]
+                                      [VP8_SWITCHABLE_FILTERS];
+#endif
 
 } VP8_COMP;
 
diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c
index 9885f874264a70251f3966eebd20518cb1cec50d..43f38568a9c8b9cc8d0619d01a4b0b4d3571fad7 100644
--- a/vp8/encoder/ratectrl.c
+++ b/vp8/encoder/ratectrl.c
@@ -174,6 +174,9 @@ void vp8_save_coding_context(VP8_COMP *cpi) {
 
   vp8_copy(cc->coef_probs, cm->fc.coef_probs);
   vp8_copy(cc->coef_probs_8x8, cm->fc.coef_probs_8x8);
+#if CONFIG_SWITCHABLE_INTERP
+  vp8_copy(cc->switchable_interp_prob, cm->fc.switchable_interp_prob);
+#endif
 }
 
 void vp8_restore_coding_context(VP8_COMP *cpi) {
@@ -227,6 +230,9 @@ void vp8_restore_coding_context(VP8_COMP *cpi) {
 
   vp8_copy(cm->fc.coef_probs, cc->coef_probs);
   vp8_copy(cm->fc.coef_probs_8x8, cc->coef_probs_8x8);
+#if CONFIG_SWITCHABLE_INTERP
+  vp8_copy(cm->fc.switchable_interp_prob, cc->switchable_interp_prob);
+#endif
 }
 
 
diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c
index cd45074b793fe5933a5ad3296819adc67e03401e..5fd92a5fac016abc4cbccefe71d9c7fb27ab2993 100644
--- a/vp8/encoder/rdopt.c
+++ b/vp8/encoder/rdopt.c
@@ -64,6 +64,11 @@ extern void vp8_ht_quantize_b(BLOCK *b, BLOCKD *d);
 
 #define INVALID_MV 0x80008000
 
+#if CONFIG_SWITCHABLE_INTERP
+/* Factor to weigh the rate for switchable interp filters */
+#define SWITCHABLE_INTERP_RATE_FACTOR 1
+#endif
+
 static const int auto_speed_thresh[17] = {
   1000,
   200,
@@ -2682,6 +2687,9 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
   // int all_rates[MAX_MODES];
   // int all_dist[MAX_MODES];
   // int intermodecost[MAX_MODES];
+#if CONFIG_SWITCHABLE_INTERP
+  int switchable_filter_index = 0;
+#endif
 
   MB_PREDICTION_MODE uv_intra_mode;
   MB_PREDICTION_MODE uv_intra_mode_8x8 = 0;
@@ -2792,18 +2800,18 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
   // that depend on the current prediction etc.
   vp8_estimate_ref_frame_costs(cpi, segment_id, ref_costs);
 
-  for (mode_index = 0; mode_index < MAX_MODES; mode_index++) {
+#if CONFIG_SWITCHABLE_INTERP
+  for (mode_index = 0; mode_index < MAX_MODES;
+       mode_index += (!switchable_filter_index)) {
+#else
+  for (mode_index = 0; mode_index < MAX_MODES; ++mode_index) {
+#endif
     int this_rd = INT_MAX;
     int disable_skip = 0;
     int other_cost = 0;
     int compmode_cost = 0;
     int mode_excluded = 0;
 
-    // Test best rd so far against threshold for trying this mode.
-    if (best_rd <= cpi->rd_threshes[mode_index]) {
-      continue;
-    }
-
     // These variables hold are rolling total cost and distortion for this mode
     rate2 = 0;
     distortion2 = 0;
@@ -2820,6 +2828,25 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
 #if CONFIG_PRED_FILTER
     xd->mode_info_context->mbmi.pred_filter_enabled = 0;
 #endif
+#if CONFIG_SWITCHABLE_INTERP
+    if (cpi->common.mcomp_filter_type == SWITCHABLE &&
+        this_mode >= NEARESTMV && this_mode <= SPLITMV) {
+      xd->mode_info_context->mbmi.interp_filter =
+          vp8_switchable_interp[switchable_filter_index++];
+      if (switchable_filter_index == VP8_SWITCHABLE_FILTERS)
+        switchable_filter_index = 0;
+        //printf("Searching %d (%d)\n", this_mode, switchable_filter_index);
+    } else {
+      xd->mode_info_context->mbmi.interp_filter = cpi->common.mcomp_filter_type;
+    }
+    vp8_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter,
+                             &cpi->common);
+#endif
+
+    // Test best rd so far against threshold for trying this mode.
+    if (best_rd <= cpi->rd_threshes[mode_index]) {
+      continue;
+    }
 
     // current coding mode under rate-distortion optimization test loop
 #if CONFIG_HYBRIDTRANSFORM
@@ -2906,7 +2933,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
     }
 
 
-    if (!x->e_mbd.mode_info_context->mbmi.second_ref_frame)
+    if (!x->e_mbd.mode_info_context->mbmi.second_ref_frame) {
       switch (this_mode) {
         case B_PRED: {
           int tmp_rd;
@@ -2934,7 +2961,8 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
         case I8X8_PRED: {
           int tmp_rd;
           tmp_rd = rd_pick_intra8x8mby_modes(cpi,
-                                             x, &rate, &rate_y, &distortion, best_yrd);
+                                             x, &rate, &rate_y, &distortion,
+                                             best_yrd);
           rate2 += rate;
           distortion2 += distortion;
 
@@ -2967,17 +2995,30 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
           int tmp_rd;
           int this_rd_thresh;
 
-          this_rd_thresh = (x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME) ? cpi->rd_threshes[THR_NEWMV] : cpi->rd_threshes[THR_NEWA];
-          this_rd_thresh = (x->e_mbd.mode_info_context->mbmi.ref_frame == GOLDEN_FRAME) ? cpi->rd_threshes[THR_NEWG] : this_rd_thresh;
+          this_rd_thresh =
+              (x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME) ?
+              cpi->rd_threshes[THR_NEWMV] : cpi->rd_threshes[THR_NEWA];
+          this_rd_thresh =
+              (x->e_mbd.mode_info_context->mbmi.ref_frame == GOLDEN_FRAME) ?
+              cpi->rd_threshes[THR_NEWG] : this_rd_thresh;
 
           tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv, NULL,
                                                    best_yrd, mdcounts,
-                                                   &rate, &rate_y, &distortion, this_rd_thresh, seg_mvs);
+                                                   &rate, &rate_y, &distortion,
+                                                   this_rd_thresh, seg_mvs);
 
           rate2 += rate;
           distortion2 += distortion;
 
-          // If even the 'Y' rd value of split is higher than best so far then dont bother looking at UV
+#if CONFIG_SWITCHABLE_INTERP
+          if (cpi->common.mcomp_filter_type == SWITCHABLE)
+            rate2 += SWITCHABLE_INTERP_RATE_FACTOR * x->switchable_interp_costs
+                [get_pred_context(&cpi->common, xd, PRED_SWITCHABLE_INTERP)]
+                [vp8_switchable_interp_map[
+                x->e_mbd.mode_info_context->mbmi.interp_filter]];
+#endif
+          // If even the 'Y' rd value of split is higher than best so far
+          // then dont bother looking at UV
           if (tmp_rd < best_yrd) {
             // Now work out UV cost and add it in
             rd_inter4x4_uv(cpi, x, &rate_uv, &distortion_uv, cpi->common.full_pixel);
@@ -3174,7 +3215,8 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
           vp8_clamp_mv2(&mode_mv[this_mode], xd);
 
           // Do not bother proceeding if the vector (from newmv,nearest or near) is 0,0 as this should then be coded using the zeromv mode.
-          if (((this_mode == NEARMV) || (this_mode == NEARESTMV)) && (mode_mv[this_mode].as_int == 0)) {
+          if (((this_mode == NEARMV) || (this_mode == NEARESTMV)) &&
+              (mode_mv[this_mode].as_int == 0)) {
             continue;
           }
 
@@ -3183,8 +3225,10 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
           // Trap vectors that reach beyond the UMV borders
           // Note that ALL New MV, Nearest MV Near MV and Zero MV code drops through to this point
           // because of the lack of break statements in the previous two cases.
-          if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
-              ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max)) {
+          if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) ||
+              ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
+              ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) ||
+              ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max)) {
             continue;
           }
 
@@ -3197,6 +3241,13 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
           rate2 += vp8_cost_bit(cpi->common.prob_pred_filter_off,
                                 xd->mode_info_context->mbmi.pred_filter_enabled);
 #endif
+#if CONFIG_SWITCHABLE_INTERP
+          if (cpi->common.mcomp_filter_type == SWITCHABLE)
+            rate2 += SWITCHABLE_INTERP_RATE_FACTOR * x->switchable_interp_costs
+                [get_pred_context(&cpi->common, xd, PRED_SWITCHABLE_INTERP)]
+                [vp8_switchable_interp_map[
+                x->e_mbd.mode_info_context->mbmi.interp_filter]];
+#endif
 
           vp8_build_inter16x16_predictors_mby(&x->e_mbd);
 
@@ -3278,7 +3329,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
         default:
           break;
       }
-    else { /* x->e_mbd.mode_info_context->mbmi.second_ref_frame != 0 */
+    } else { /* x->e_mbd.mode_info_context->mbmi.second_ref_frame != 0 */
       int ref1 = x->e_mbd.mode_info_context->mbmi.ref_frame;
       int ref2 = x->e_mbd.mode_info_context->mbmi.second_ref_frame;
 
@@ -3330,12 +3381,18 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
           int tmp_rd;
           int this_rd_thresh;
 
-          this_rd_thresh = (x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME) ? cpi->rd_threshes[THR_NEWMV] : cpi->rd_threshes[THR_NEWA];
-          this_rd_thresh = (x->e_mbd.mode_info_context->mbmi.ref_frame == GOLDEN_FRAME) ? cpi->rd_threshes[THR_NEWG] : this_rd_thresh;
+          this_rd_thresh =
+              (x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME) ?
+              cpi->rd_threshes[THR_NEWMV] : cpi->rd_threshes[THR_NEWA];
+          this_rd_thresh =
+              (x->e_mbd.mode_info_context->mbmi.ref_frame == GOLDEN_FRAME) ?
+              cpi->rd_threshes[THR_NEWG] : this_rd_thresh;
 
-          tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv, &second_best_ref_mv,
+          tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv,
+                                                   &second_best_ref_mv,
                                                    best_yrd, mdcounts,
-                                                   &rate, &rate_y, &distortion, this_rd_thresh, seg_mvs);
+                                                   &rate, &rate_y, &distortion,
+                                                   this_rd_thresh, seg_mvs);
 
           rate2 += rate;
           distortion2 += distortion;
@@ -3488,6 +3545,12 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
       this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
     }
 
+#if 0//CONFIG_SWITCHABLE_INTERP
+    if (this_mode >= NEARESTMV && this_mode <= SPLITMV &&
+        cm->mcomp_filter_type == SWITCHABLE)
+      printf("mode %d (%d): %d\n", this_mode, switchable_filter_index, this_rd);
+#endif
+
     // Experimental debug code.
     // all_rds[mode_index] = this_rd;
     // all_rates[mode_index] = rate2;
@@ -3560,11 +3623,17 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
             }
         }
 
-        // Testing this mode gave rise to an improvement in best error score. Lower threshold a bit for next time
-        cpi->rd_thresh_mult[mode_index] = (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ? cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
-        cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+        // Testing this mode gave rise to an improvement in best error score.
+        // Lower threshold a bit for next time
+        cpi->rd_thresh_mult[mode_index] =
+            (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ?
+            cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
+        cpi->rd_threshes[mode_index] =
+            (cpi->rd_baseline_thresh[mode_index] >> 7) *
+            cpi->rd_thresh_mult[mode_index];
       }
-      // If the mode did not help improve the best error case then raise the threshold for testing that mode next time around.
+      // If the mode did not help improve the best error case then raise the
+      // threshold for testing that mode next time around.
       else {
         cpi->rd_thresh_mult[mode_index] += 4;
 
@@ -3617,13 +3686,29 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
   else
     ++cpi->pred_filter_off_count;
 #endif
+#if CONFIG_SWITCHABLE_INTERP
+  //printf("Bestmode %d (%d): %d\n", best_mbmode.mode, best_mbmode.interp_filter, best_rd);
+  if (cpi->common.mcomp_filter_type == SWITCHABLE &&
+      best_mbmode.mode >= NEARESTMV &&
+      best_mbmode.mode <= SPLITMV) {
+    ++cpi->switchable_interp_count
+        [get_pred_context(&cpi->common, xd, PRED_SWITCHABLE_INTERP)]
+        [vp8_switchable_interp_map[best_mbmode.interp_filter]];
+  }
+#endif
 
   // Reduce the activation RD thresholds for the best choice mode
-  if ((cpi->rd_baseline_thresh[best_mode_index] > 0) && (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2))) {
+  if ((cpi->rd_baseline_thresh[best_mode_index] > 0) &&
+      (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2))) {
     int best_adjustment = (cpi->rd_thresh_mult[best_mode_index] >> 2);
 
-    cpi->rd_thresh_mult[best_mode_index] = (cpi->rd_thresh_mult[best_mode_index] >= (MIN_THRESHMULT + best_adjustment)) ? cpi->rd_thresh_mult[best_mode_index] - best_adjustment : MIN_THRESHMULT;
-    cpi->rd_threshes[best_mode_index] = (cpi->rd_baseline_thresh[best_mode_index] >> 7) * cpi->rd_thresh_mult[best_mode_index];
+    cpi->rd_thresh_mult[best_mode_index] =
+        (cpi->rd_thresh_mult[best_mode_index] >=
+         (MIN_THRESHMULT + best_adjustment)) ?
+        cpi->rd_thresh_mult[best_mode_index] - best_adjustment : MIN_THRESHMULT;
+    cpi->rd_threshes[best_mode_index] =
+        (cpi->rd_baseline_thresh[best_mode_index] >> 7) *
+        cpi->rd_thresh_mult[best_mode_index];
 
     // If we chose a split mode then reset the new MV thresholds as well
     /*if ( vp8_mode_order[best_mode_index].mode == SPLITMV )