Making subpel filters switchable at frame level
authorDeb Mukherjee <debargha@google.com>
Mon, 19 Mar 2012 14:53:05 +0000 (07:53 -0700)
committerDeb Mukherjee <debargha@google.com>
Wed, 21 Mar 2012 16:17:22 +0000 (09:17 -0700)
Various refactoring to make the subpel motion compensation
filters switchable by a frame level field.
Two types of 8-tap filters are supported in addition to the existing
bilinar and sixtap filters. One is the default 8-tap and the
other has a sharper cut-off for use with frames with substantial
edge content.

Patch 2: Added a preliminary strategy for filter selection based on
edginess detecton. Also includes some filter changes.

Change-Id: I866085bda5ae143cfdf2ec88157feaabdf7bd63a

vp8/common/filter.c
vp8/common/filter.h
vp8/common/generic/systemdependent.c
vp8/common/onyxc_int.h
vp8/common/subpixel.h
vp8/decoder/decodframe.c
vp8/encoder/bitstream.c
vp8/encoder/encodeframe.c
vp8/encoder/onyx_if.c

index d1ef796..a949d7a 100644 (file)
@@ -45,36 +45,111 @@ DECLARE_ALIGNED(16, const short, vp8_bilinear_filters[SUBPEL_SHIFTS][2]) =
 };
 
 #if CONFIG_ENHANCED_INTERP
-#define FILTER_ALPHA 60
-DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[SUBPEL_SHIFTS][2*INTERP_EXTEND]) =
+
+#define FILTER_ALPHA       0
+#define FILTER_ALPHA_SHARP 60
+DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8[SUBPEL_SHIFTS][2*INTERP_EXTEND]) =
 {
+#if SUBPEL_SHIFTS==16
+#if FILTER_ALPHA == 0
+    /* Lagrangian interpolation filter */
+    { 0,   0,   0, 128,   0,   0,   0,  0},
+    { 0,   1,  -5, 126,   8,  -3,   1,  0},
+    {-1,   3, -10, 122,  18,  -6,   2,  0},
+    {-1,   4, -13, 118,  27,  -9,   3, -1},
+    {-1,   4, -16, 112,  37, -11,   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, -11,  37, 112, -16,   4, -1},
+    {-1,   3,  -9,  27, 118, -13,   4, -1},
+    { 0,   2,  -6,  18, 122, -10,   3, -1},
+    { 0,   1,  -3,   8, 126,  -5,   1,  0}
+#elif FILTER_ALPHA == 50
     /* Generated using MATLAB:
-     * alpha = 0.6;
+     * alpha = 0.5;
      * b=intfilt(8,4,alpha);
      * bi=round(128*b);
      * ba=flipud(reshape([bi 0], 8, 8));
      * disp(num2str(ba, '%d,'))
      */
-#if SUBPEL_SHIFTS==16
-#if FILTER_ALPHA == 70
-    /* alpha = 0.70 */
     { 0,   0,   0, 128,   0,   0,   0,  0},
-    { 0,   2,  -6, 126,   8,  -3,   1,  0},
-    {-1,   4, -11, 123,  18,  -7,   3, -1},
-    {-1,   5, -15, 119,  27, -10,   4, -1},
-    {-2,   6, -18, 113,  38, -13,   5, -1},
-    {-2,   7, -20, 106,  49, -16,   6, -2},
-    {-2,   8, -22,  98,  59, -18,   7, -2},
-    {-2,   8, -22,  89,  69, -20,   8, -2},
-    {-2,   8, -21,  79,  79, -21,   8, -2},
-    {-2,   8, -20,  69,  89, -22,   8, -2},
-    {-2,   7, -18,  59,  98, -22,   8, -2},
-    {-2,   6, -16,  49, 106, -20,   7, -2},
-    {-1,   5, -13,  38, 113, -18,   6, -2},
-    {-1,   4, -10,  27, 119, -15,   5, -1},
-    {-1,   3,  -7,  18, 123, -11,   4, -1},
-    { 0,   1,  -3,   8, 126,  -6,   2,  0}
-#elif FILTER_ALPHA == 65
+    { 0,   1,  -5, 126,   8,  -3,   1,  0},
+    { 0,   2, -10, 122,  18,  -6,   2,  0},
+    {-1,   3, -13, 118,  27,  -9,   3,  0},
+    {-1,   4, -16, 112,  37, -11,   3,  0},
+    {-1,   5, -17, 104,  48, -14,   4, -1},
+    {-1,   5, -18,  96,  58, -16,   5, -1},
+    {-1,   5, -19,  88,  68, -17,   5, -1},
+    {-1,   5, -18,  78,  78, -18,   5, -1},
+    {-1,   5, -17,  68,  88, -19,   5, -1},
+    {-1,   5, -16,  58,  96, -18,   5, -1},
+    {-1,   4, -14,  48, 104, -17,   5, -1},
+    { 0,   3, -11,  37, 112, -16,   4, -1},
+    { 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
+    { 0,   0,   0, 128,   0,   0,   0,   0},
+    {-1,   3, -10, 122,  18,  -6,   2,   0},
+    {-1,   4, -16, 112,  37, -11,   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, -11,  37, 112, -16,   4,  -1},
+    { 0,   2,  -6,  18, 122, -10,   3,  -1},
+#elif FILTER_ALPHA == 50
+    /* alpha = 0.50 */
+    { 0,   0,   0, 128,   0,   0,   0,  0},
+    { 0,   2, -10, 122,  18,  -6,   2,  0},
+    {-1,   4, -16, 112,  37, -11,   3,  0},
+    {-1,   5, -18,  96,  58, -16,   5, -1},
+    {-1,   5, -18,  78,  78, -18,   5, -1},
+    {-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
     /* alpha = 0.65 */
     { 0,   0,   0, 128,   0,   0,   0,  0},
     { 0,   2,  -6, 126,   8,  -3,   1,  0},
@@ -92,7 +167,7 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[SUBPEL_SHIFTS][2*INTERP_EXT
     {-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 == 60
+#elif FILTER_ALPHA_SHARP == 60
     /* alpha = 0.60 */
     { 0,   0,   0, 128,   0,   0,   0,  0},
     { 0,   2,  -6, 126,   8,  -3,   1,  0},
@@ -110,7 +185,7 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[SUBPEL_SHIFTS][2*INTERP_EXT
     {-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 == 55
+#elif FILTER_ALPHA_SHARP == 55
     /* alpha = 0.55 */
     { 0,   0,   0, 128,   0,   0,   0,  0},
     { 0,   1,  -5, 126,   8,  -3,   1,  0},
@@ -128,55 +203,9 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[SUBPEL_SHIFTS][2*INTERP_EXT
     {-1,   3,  -9,  27, 118, -13,   4, -1},
     { 0,   2,  -6,  18, 123, -10,   2, -1},
     { 0,   1,  -3,   8, 126,  -5,   1,  0}
-#elif FILTER_ALPHA == 50
-    /* alpha = 0.50 */
-    { 0,   0,   0, 128,   0,   0,   0,  0},
-    { 0,   1,  -5, 126,   8,  -3,   1,  0},
-    { 0,   2, -10, 122,  18,  -6,   2,  0},
-    {-1,   3, -13, 118,  27,  -9,   3,  0},
-    {-1,   4, -16, 112,  37, -11,   3,  0},
-    {-1,   5, -17, 104,  48, -14,   4, -1},
-    {-1,   5, -18,  96,  58, -16,   5, -1},
-    {-1,   5, -19,  88,  68, -17,   5, -1},
-    {-1,   5, -18,  78,  78, -18,   5, -1},
-    {-1,   5, -17,  68,  88, -19,   5, -1},
-    {-1,   5, -16,  58,  96, -18,   5, -1},
-    {-1,   4, -14,  48, 104, -17,   5, -1},
-    { 0,   3, -11,  37, 112, -16,   4, -1},
-    { 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 == 0
-    /* Lagrangian interpolation filter */
-    { 0,   0,   0, 128,   0,   0,   0,   0},
-    { 0,   1,  -5, 126,   8,  -3,   1,   0},
-    {-1,   3, -10, 122,  18,  -6,   2,   0},
-    {-1,   4, -13, 118,  27,  -9,   3,  -1},
-    {-1,   4, -16, 112,  37, -11,   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, -11,  37, 112, -16,   4,  -1},
-    {-1,   3,  -9,  27, 118, -13,   4,  -1},
-    { 0,   2,  -6,  18, 122, -10,   3,  -1},
-    { 0,   1,  -3,   8, 126,  -5,   1,   0}
-#endif  /* FILTER_ALPHA */
+#endif  /* FILTER_ALPHA_SHARP */
 #else   /* SUBPEL_SHIFTS==16 */
-#if FILTER_ALPHA == 70
-    /* alpha = 0.70 */
-    { 0,   0,   0, 128,   0,   0,   0,  0},
-    {-1,   4, -11, 123,  18,  -7,   3, -1},
-    {-2,   6, -18, 113,  38, -13,   5, -1},
-    {-2,   8, -22,  98,  59, -18,   7, -2},
-    {-2,   8, -21,  79,  79, -21,   8, -2},
-    {-2,   7, -18,  59,  98, -22,   8, -2},
-    {-1,   5, -13,  38, 113, -18,   6, -2},
-    {-1,   3,  -7,  18, 123, -11,   4, -1}
-#elif FILTER_ALPHA == 65
+#if FILTER_ALPHA_SHARP == 65
     /* alpha = 0.65 */
     { 0,   0,   0, 128,   0,   0,   0, 0},
     {-1,   3, -10, 123,  18,  -6,   2, -1},
@@ -186,7 +215,7 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[SUBPEL_SHIFTS][2*INTERP_EXT
     {-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 == 60
+#elif FILTER_ALPHA_SHARP == 60
     /* alpha = 0.60 */
     { 0,   0,   0, 128,   0,   0,   0, 0},
     {-1,   3, -10, 123,  18,  -6,   2, -1},
@@ -196,7 +225,7 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[SUBPEL_SHIFTS][2*INTERP_EXT
     {-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 == 55
+#elif FILTER_ALPHA_SHARP == 55
     /* alpha = 0.55 */
     { 0,   0,   0, 128,   0,   0,   0,  0},
     {-1,   2, -10, 123,  18,  -6,   2,  0},
@@ -206,35 +235,32 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[SUBPEL_SHIFTS][2*INTERP_EXT
     {-1,   5, -16,  58,  97, -19,   5, -1},
     {-1,   4, -12,  37, 112, -16,   5, -1},
     { 0,   2,  -6,  18, 123, -10,   2, -1}
-#elif FILTER_ALPHA == 50
-    /* alpha = 0.50 */
-    { 0,   0,   0, 128,   0,   0,   0,  0},
-    { 0,   2, -10, 122,  18,  -6,   2,  0},
-    {-1,   4, -16, 112,  37, -11,   3,  0},
-    {-1,   5, -18,  96,  58, -16,   5, -1},
-    {-1,   5, -18,  78,  78, -18,   5, -1},
-    {-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 == 0
-    /* Lagrangian interpolation filter */
-    { 0,   0,   0, 128,   0,   0,   0,   0},
-    {-1,   3, -10, 122,  18,  -6,   2,   0},
-    {-1,   4, -16, 112,  37, -11,   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, -11,  37, 112, -16,   4,  -1},
-    { 0,   2,  -6,  18, 122, -10,   3,  -1},
-#endif  /* FILTER_ALPHA */
+#endif  /* FILTER_ALPHA_SHARP */
 #endif  /* SUBPEL_SHIFTS==16 */
 };
 
-#else  // CONFIG_ENHANCED_INTERP
+#endif  // CONFIG_ENHANCED_INTERP
 
-DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[8][6]) =
+DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_6[SUBPEL_SHIFTS][6]) =
 {
-
+#if SUBPEL_SHIFTS==16
+    {0,   0, 128,   0,   0, 0},
+    {1,  -5, 125,   8,  -2, 1},
+    {1,  -8, 122,  17,  -5, 1},
+    {2, -11, 116,  27,  -8, 2},
+    {3, -14, 110,  37, -10, 2},
+    {3, -15, 103,  47, -12, 2},
+    {3, -16,  95,  57, -14, 3},
+    {3, -16,  86,  67, -15, 3},
+    {3, -16,  77,  77, -16, 3},
+    {3, -15,  67,  86, -16, 3},
+    {3, -14,  57,  95, -16, 3},
+    {2, -12,  47, 103, -15, 3},
+    {2, -10,  37, 110, -14, 3},
+    {2,  -8,  27, 116, -11, 2},
+    {1,  -5,  17, 122,  -8, 1},
+    {1,  -2,   8, 125,  -5, 1}
+#else
     { 0,  0,  128,    0,   0,  0 },         /* note that 1/8 pel positions are just as per alpha -0.5 bicubic */
     { 0, -6,  123,   12,  -1,  0 },
     { 2, -11, 108,   36,  -8,  1 },         /* New 1/4 pel 6 tap filter */
@@ -243,11 +269,10 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[8][6]) =
     { 0, -6,   50,   93,  -9,  0 },
     { 1, -8,   36,  108, -11,  2 },         /* New 1/4 pel 6 tap filter */
     { 0, -1,   12,  123,  -6,  0 },
+#endif  /* SUBPEL_SHIFTS==16 */
 };
 
-#endif  // CONFIG_ENHANCED_INTERP
-
-static void filter_block2d_first_pass
+static void filter_block2d_first_pass_6
 (
     unsigned char *src_ptr,
     int *output_ptr,
@@ -265,7 +290,6 @@ static void filter_block2d_first_pass
     {
         for (j = 0; j < output_width; j++)
         {
-#if INTERP_EXTEND == 3
             Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
                    ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
                    ((int)src_ptr[0]                    * vp8_filter[2]) +
@@ -273,29 +297,6 @@ static void filter_block2d_first_pass
                    ((int)src_ptr[2*pixel_step]         * vp8_filter[4]) +
                    ((int)src_ptr[3*pixel_step]         * vp8_filter[5]) +
                    (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
-#elif INTERP_EXTEND == 4
-            Temp = ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[0]) +
-                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[1]) +
-                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[2]) +
-                   ((int)src_ptr[0]                    * vp8_filter[3]) +
-                   ((int)src_ptr[pixel_step]           * vp8_filter[4]) +
-                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[5]) +
-                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[6]) +
-                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[7]) +
-                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
-#elif INTERP_EXTEND == 5
-            Temp = ((int)src_ptr[-4 * (int)pixel_step] * vp8_filter[0]) +
-                   ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[1]) +
-                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[2]) +
-                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[3]) +
-                   ((int)src_ptr[0]                    * vp8_filter[4]) +
-                   ((int)src_ptr[pixel_step]           * vp8_filter[5]) +
-                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[6]) +
-                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[7]) +
-                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[8]) +
-                   ((int)src_ptr[5 * pixel_step]       * vp8_filter[9]) +
-                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
-#endif
 
             /* Normalize back to 0-255 */
             Temp = Temp >> VP8_FILTER_SHIFT;
@@ -315,7 +316,7 @@ static void filter_block2d_first_pass
     }
 }
 
-static void filter_block2d_second_pass
+static void filter_block2d_second_pass_6
 (
     int *src_ptr,
     unsigned char *output_ptr,
@@ -335,7 +336,6 @@ static void filter_block2d_second_pass
         for (j = 0; j < output_width; j++)
         {
             /* Apply filter */
-#if INTERP_EXTEND == 3
             Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
                    ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
                    ((int)src_ptr[0]                    * vp8_filter[2]) +
@@ -343,29 +343,6 @@ static void filter_block2d_second_pass
                    ((int)src_ptr[2*pixel_step]         * vp8_filter[4]) +
                    ((int)src_ptr[3*pixel_step]         * vp8_filter[5]) +
                    (VP8_FILTER_WEIGHT >> 1);   /* Rounding */
-#elif INTERP_EXTEND == 4
-            Temp = ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[0]) +
-                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[1]) +
-                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[2]) +
-                   ((int)src_ptr[0]                    * vp8_filter[3]) +
-                   ((int)src_ptr[pixel_step]           * vp8_filter[4]) +
-                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[5]) +
-                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[6]) +
-                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[7]) +
-                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
-#elif INTERP_EXTEND == 5
-            Temp = ((int)src_ptr[-4 * (int)pixel_step] * vp8_filter[0]) +
-                   ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[1]) +
-                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[2]) +
-                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[3]) +
-                   ((int)src_ptr[0]                    * vp8_filter[4]) +
-                   ((int)src_ptr[pixel_step]           * vp8_filter[5]) +
-                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[6]) +
-                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[7]) +
-                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[8]) +
-                   ((int)src_ptr[5 * pixel_step]       * vp8_filter[9]) +
-                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
-#endif
 
             /* Normalize back to 0-255 */
             Temp = Temp >> VP8_FILTER_SHIFT;
@@ -393,7 +370,7 @@ static void filter_block2d_second_pass
  * and then averages that with the content already present in the output
  * ((filter_result + dest + 1) >> 1) and stores that in the output.
  */
-static void filter_block2d_second_pass_avg
+static void filter_block2d_second_pass_avg_6
 (
     int *src_ptr,
     unsigned char *output_ptr,
@@ -413,7 +390,6 @@ static void filter_block2d_second_pass_avg
         for (j = 0; j < output_width; j++)
         {
             /* Apply filter */
-#if INTERP_EXTEND == 3
             Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
                    ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
                    ((int)src_ptr[0]                    * vp8_filter[2]) +
@@ -421,29 +397,6 @@ static void filter_block2d_second_pass_avg
                    ((int)src_ptr[2*pixel_step]         * vp8_filter[4]) +
                    ((int)src_ptr[3*pixel_step]         * vp8_filter[5]) +
                    (VP8_FILTER_WEIGHT >> 1);   /* Rounding */
-#elif INTERP_EXTEND == 4
-            Temp = ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[0]) +
-                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[1]) +
-                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[2]) +
-                   ((int)src_ptr[0]                    * vp8_filter[3]) +
-                   ((int)src_ptr[pixel_step]           * vp8_filter[4]) +
-                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[5]) +
-                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[6]) +
-                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[7]) +
-                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
-#elif INTERP_EXTEND == 5
-            Temp = ((int)src_ptr[-4 * (int)pixel_step] * vp8_filter[0]) +
-                   ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[1]) +
-                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[2]) +
-                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[3]) +
-                   ((int)src_ptr[0]                    * vp8_filter[4]) +
-                   ((int)src_ptr[pixel_step]           * vp8_filter[5]) +
-                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[6]) +
-                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[7]) +
-                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[8]) +
-                   ((int)src_ptr[5 * pixel_step]       * vp8_filter[9]) +
-                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
-#endif
 
             /* Normalize back to 0-255 */
             Temp = Temp >> VP8_FILTER_SHIFT;
@@ -463,7 +416,8 @@ static void filter_block2d_second_pass_avg
     }
 }
 
-static void filter_block2d
+#define Interp_Extend 3
+static void filter_block2d_6
 (
     unsigned char  *src_ptr,
     unsigned char  *output_ptr,
@@ -473,14 +427,14 @@ static void filter_block2d
     const short  *VFilter
 )
 {
-    int FData[(3+INTERP_EXTEND*2)*4]; /* Temp data buffer used in filtering */
+    int FData[(3+Interp_Extend*2)*4]; /* Temp data buffer used in filtering */
 
     /* First filter 1-D horizontally... */
-    filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
-                              3+INTERP_EXTEND*2, 4, HFilter);
+    filter_block2d_first_pass_6(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              3+Interp_Extend*2, 4, HFilter);
 
     /* then filter verticaly... */
-    filter_block2d_second_pass(FData + 4*(INTERP_EXTEND-1), output_ptr, output_pitch, 4, 4, 4, 4, VFilter);
+    filter_block2d_second_pass_6(FData + 4*(Interp_Extend-1), output_ptr, output_pitch, 4, 4, 4, 4, VFilter);
 }
 
 
@@ -497,10 +451,10 @@ void vp8_sixtap_predict_c
     const short  *HFilter;
     const short  *VFilter;
 
-    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
-    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+    HFilter = vp8_sub_pel_filters_6[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_6[yoffset];   /* 6 tap */
 
-    filter_block2d(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter);
+    filter_block2d_6(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter);
 }
 void vp8_sixtap_predict8x8_c
 (
@@ -514,19 +468,19 @@ void vp8_sixtap_predict8x8_c
 {
     const short  *HFilter;
     const short  *VFilter;
-    // int FData[(7+INTERP_EXTEND*2)*16];   /* Temp data buffer used in filtering */
-    int FData[(7+INTERP_EXTEND*2)*8];   /* Temp data buffer used in filtering */
+    // int FData[(7+Interp_Extend*2)*16];   /* Temp data buffer used in filtering */
+    int FData[(7+Interp_Extend*2)*8];   /* Temp data buffer used in filtering */
 
-    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
-    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+    HFilter = vp8_sub_pel_filters_6[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_6[yoffset];   /* 6 tap */
 
     /* First filter 1-D horizontally... */
-    filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
-                              7+INTERP_EXTEND*2, 8, HFilter);
+    filter_block2d_first_pass_6(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              7+Interp_Extend*2, 8, HFilter);
 
 
     /* then filter verticaly... */
-    filter_block2d_second_pass(FData + 8*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
+    filter_block2d_second_pass_6(FData + 8*(Interp_Extend-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
 
 }
 
@@ -542,18 +496,18 @@ void vp8_sixtap_predict_avg8x8_c
 {
     const short  *HFilter;
     const short  *VFilter;
-    // int FData[(7+INTERP_EXTEND*2)*16];   /* Temp data buffer used in filtering */
-    int FData[(7+INTERP_EXTEND*2)*8];   /* Temp data buffer used in filtering */
+    // int FData[(7+Interp_Extend*2)*16];   /* Temp data buffer used in filtering */
+    int FData[(7+Interp_Extend*2)*8];   /* Temp data buffer used in filtering */
 
-    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
-    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+    HFilter = vp8_sub_pel_filters_6[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_6[yoffset];   /* 6 tap */
 
     /* First filter 1-D horizontally... */
-    filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
-                              7+INTERP_EXTEND*2, 8, HFilter);
+    filter_block2d_first_pass_6(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              7+Interp_Extend*2, 8, HFilter);
 
     /* then filter verticaly... */
-    filter_block2d_second_pass_avg(FData + 8*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
+    filter_block2d_second_pass_avg_6(FData + 8*(Interp_Extend-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
 }
 
 void vp8_sixtap_predict8x4_c
@@ -568,19 +522,19 @@ void vp8_sixtap_predict8x4_c
 {
     const short  *HFilter;
     const short  *VFilter;
-    // int FData[(7+INTERP_EXTEND*2)*16];   /* Temp data buffer used in filtering */
-    int FData[(3+INTERP_EXTEND*2)*8];   /* Temp data buffer used in filtering */
+    // int FData[(7+Interp_Extend*2)*16];   /* Temp data buffer used in filtering */
+    int FData[(3+Interp_Extend*2)*8];   /* Temp data buffer used in filtering */
 
-    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
-    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+    HFilter = vp8_sub_pel_filters_6[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_6[yoffset];   /* 6 tap */
 
     /* First filter 1-D horizontally... */
-    filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
-                              3+INTERP_EXTEND*2, 8, HFilter);
+    filter_block2d_first_pass_6(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              3+Interp_Extend*2, 8, HFilter);
 
 
     /* then filter verticaly... */
-    filter_block2d_second_pass(FData + 8*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
+    filter_block2d_second_pass_6(FData + 8*(Interp_Extend-1), dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
 
 }
 
@@ -596,19 +550,19 @@ void vp8_sixtap_predict16x16_c
 {
     const short  *HFilter;
     const short  *VFilter;
-    // int FData[(15+INTERP_EXTEND*2)*24];   /* Temp data buffer used in filtering */
-    int FData[(15+INTERP_EXTEND*2)*16];  /* Temp data buffer used in filtering */
+    // int FData[(15+Interp_Extend*2)*24];   /* Temp data buffer used in filtering */
+    int FData[(15+Interp_Extend*2)*16];  /* Temp data buffer used in filtering */
 
 
-    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
-    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+    HFilter = vp8_sub_pel_filters_6[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_6[yoffset];   /* 6 tap */
 
     /* First filter 1-D horizontally... */
-    filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
-                              15+INTERP_EXTEND*2, 16, HFilter);
+    filter_block2d_first_pass_6(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              15+Interp_Extend*2, 16, HFilter);
 
     /* then filter verticaly... */
-    filter_block2d_second_pass(FData + 16*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
+    filter_block2d_second_pass_6(FData + 16*(Interp_Extend-1), dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
 
 }
 
@@ -624,21 +578,548 @@ void vp8_sixtap_predict_avg16x16_c
 {
     const short  *HFilter;
     const short  *VFilter;
-    // int FData[(15+INTERP_EXTEND*2)*24];   /* Temp data buffer used in filtering */
-    int FData[(15+INTERP_EXTEND*2)*16];  /* Temp data buffer used in filtering */
+    // int FData[(15+Interp_Extend*2)*24];   /* Temp data buffer used in filtering */
+    int FData[(15+Interp_Extend*2)*16];  /* Temp data buffer used in filtering */
 
-    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
-    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+    HFilter = vp8_sub_pel_filters_6[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_6[yoffset];   /* 6 tap */
 
     /* First filter 1-D horizontally... */
-    filter_block2d_first_pass(src_ptr - ((INTERP_EXTEND-1) * src_pixels_per_line), FData,
-                              src_pixels_per_line, 1, 15+INTERP_EXTEND*2, 16, HFilter);
+    filter_block2d_first_pass_6(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData,
+                              src_pixels_per_line, 1, 15+Interp_Extend*2, 16, HFilter);
 
     /* then filter verticaly... */
-    filter_block2d_second_pass_avg(FData + 16*(INTERP_EXTEND-1), dst_ptr, dst_pitch,
+    filter_block2d_second_pass_avg_6(FData + 16*(Interp_Extend-1), dst_ptr, dst_pitch,
                                    16, 16, 16, 16, VFilter);
 }
 
+#if CONFIG_ENHANCED_INTERP
+
+#undef Interp_Extend
+#define Interp_Extend 4
+
+static void filter_block2d_first_pass_8
+(
+    unsigned char *src_ptr,
+    int *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int i, j;
+    int  Temp;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+#if Interp_Extend == 4
+            Temp = ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[0]) +
+                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[1]) +
+                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[2]) +
+                   ((int)src_ptr[0]                    * vp8_filter[3]) +
+                   ((int)src_ptr[pixel_step]           * vp8_filter[4]) +
+                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[5]) +
+                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[6]) +
+                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[7]) +
+                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
+#elif Interp_Extend == 5
+            Temp = ((int)src_ptr[-4 * (int)pixel_step] * vp8_filter[0]) +
+                   ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[1]) +
+                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[2]) +
+                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[3]) +
+                   ((int)src_ptr[0]                    * vp8_filter[4]) +
+                   ((int)src_ptr[pixel_step]           * vp8_filter[5]) +
+                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[6]) +
+                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[7]) +
+                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[8]) +
+                   ((int)src_ptr[5 * pixel_step]       * vp8_filter[9]) +
+                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
+#endif
+
+            /* Normalize back to 0-255 */
+            Temp = Temp >> VP8_FILTER_SHIFT;
+
+            if (Temp < 0)
+                Temp = 0;
+            else if (Temp > 255)
+                Temp = 255;
+
+            output_ptr[j] = Temp;
+            src_ptr++;
+        }
+
+        /* Next row... */
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_width;
+    }
+}
+
+static void filter_block2d_second_pass_8
+(
+    int *src_ptr,
+    unsigned char *output_ptr,
+    int output_pitch,
+    unsigned int src_pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int i, j;
+    int  Temp;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            /* Apply filter */
+#if Interp_Extend == 4
+            Temp = ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[0]) +
+                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[1]) +
+                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[2]) +
+                   ((int)src_ptr[0]                    * vp8_filter[3]) +
+                   ((int)src_ptr[pixel_step]           * vp8_filter[4]) +
+                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[5]) +
+                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[6]) +
+                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[7]) +
+                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
+#elif Interp_Extend == 5
+            Temp = ((int)src_ptr[-4 * (int)pixel_step] * vp8_filter[0]) +
+                   ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[1]) +
+                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[2]) +
+                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[3]) +
+                   ((int)src_ptr[0]                    * vp8_filter[4]) +
+                   ((int)src_ptr[pixel_step]           * vp8_filter[5]) +
+                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[6]) +
+                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[7]) +
+                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[8]) +
+                   ((int)src_ptr[5 * pixel_step]       * vp8_filter[9]) +
+                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
+#endif
+
+            /* Normalize back to 0-255 */
+            Temp = Temp >> VP8_FILTER_SHIFT;
+
+            if (Temp < 0)
+                Temp = 0;
+            else if (Temp > 255)
+                Temp = 255;
+
+            output_ptr[j] = (unsigned char)Temp;
+            src_ptr++;
+        }
+
+        /* Start next row */
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_pitch;
+    }
+}
+
+/*
+ * The only functional difference between filter_block2d_second_pass()
+ * and this function is that filter_block2d_second_pass() does a sixtap
+ * filter on the input and stores it in the output. This function
+ * (filter_block2d_second_pass_avg()) does a sixtap filter on the input,
+ * and then averages that with the content already present in the output
+ * ((filter_result + dest + 1) >> 1) and stores that in the output.
+ */
+static void filter_block2d_second_pass_avg_8
+(
+    int *src_ptr,
+    unsigned char *output_ptr,
+    int output_pitch,
+    unsigned int src_pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int i, j;
+    int  Temp;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            /* Apply filter */
+#if Interp_Extend == 4
+            Temp = ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[0]) +
+                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[1]) +
+                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[2]) +
+                   ((int)src_ptr[0]                    * vp8_filter[3]) +
+                   ((int)src_ptr[pixel_step]           * vp8_filter[4]) +
+                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[5]) +
+                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[6]) +
+                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[7]) +
+                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
+#elif Interp_Extend == 5
+            Temp = ((int)src_ptr[-4 * (int)pixel_step] * vp8_filter[0]) +
+                   ((int)src_ptr[-3 * (int)pixel_step] * vp8_filter[1]) +
+                   ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[2]) +
+                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[3]) +
+                   ((int)src_ptr[0]                    * vp8_filter[4]) +
+                   ((int)src_ptr[pixel_step]           * vp8_filter[5]) +
+                   ((int)src_ptr[2 * pixel_step]       * vp8_filter[6]) +
+                   ((int)src_ptr[3 * pixel_step]       * vp8_filter[7]) +
+                   ((int)src_ptr[4 * pixel_step]       * vp8_filter[8]) +
+                   ((int)src_ptr[5 * pixel_step]       * vp8_filter[9]) +
+                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
+#endif
+
+            /* Normalize back to 0-255 */
+            Temp = Temp >> VP8_FILTER_SHIFT;
+
+            if (Temp < 0)
+                Temp = 0;
+            else if (Temp > 255)
+                Temp = 255;
+
+            output_ptr[j] = (unsigned char) ((output_ptr[j] + Temp + 1) >> 1);
+            src_ptr++;
+        }
+
+        /* Start next row */
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_pitch;
+    }
+}
+
+static void filter_block2d_8
+(
+    unsigned char  *src_ptr,
+    unsigned char  *output_ptr,
+    unsigned int src_pixels_per_line,
+    int output_pitch,
+    const short  *HFilter,
+    const short  *VFilter
+)
+{
+    int FData[(3+Interp_Extend*2)*4]; /* Temp data buffer used in filtering */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              3+Interp_Extend*2, 4, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_8(FData + 4*(Interp_Extend-1), output_ptr, output_pitch, 4, 4, 4, 4, VFilter);
+}
+
+void vp8_eighttap_predict_c
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = vp8_sub_pel_filters_8[xoffset];   /* 8 tap */
+    VFilter = vp8_sub_pel_filters_8[yoffset];   /* 8 tap */
+
+    filter_block2d_8(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter);
+}
+
+void vp8_eighttap_predict_sharp_c
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = vp8_sub_pel_filters_8s[xoffset];   /* 8 tap */
+    VFilter = vp8_sub_pel_filters_8s[yoffset];   /* 8 tap */
+
+    filter_block2d_8(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter);
+}
+
+void vp8_eighttap_predict8x8_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    // int FData[(7+Interp_Extend*2)*16];   /* Temp data buffer used in filtering */
+    int FData[(7+Interp_Extend*2)*8];   /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters_8[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_8[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              7+Interp_Extend*2, 8, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_8(FData + 8*(Interp_Extend-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
+}
+
+void vp8_eighttap_predict8x8_sharp_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    // int FData[(7+Interp_Extend*2)*16];   /* Temp data buffer used in filtering */
+    int FData[(7+Interp_Extend*2)*8];   /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters_8s[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_8s[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              7+Interp_Extend*2, 8, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_8(FData + 8*(Interp_Extend-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
+}
+
+void vp8_eighttap_predict_avg8x8_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    // int FData[(7+Interp_Extend*2)*16];   /* Temp data buffer used in filtering */
+    int FData[(7+Interp_Extend*2)*8];   /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters_8[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_8[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              7+Interp_Extend*2, 8, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_avg_8(FData + 8*(Interp_Extend-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
+}
+
+void vp8_eighttap_predict_avg8x8_sharp_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    // int FData[(7+Interp_Extend*2)*16];   /* Temp data buffer used in filtering */
+    int FData[(7+Interp_Extend*2)*8];   /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters_8s[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_8s[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              7+Interp_Extend*2, 8, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_avg_8(FData + 8*(Interp_Extend-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
+}
+
+void vp8_eighttap_predict8x4_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    // int FData[(7+Interp_Extend*2)*16];   /* Temp data buffer used in filtering */
+    int FData[(3+Interp_Extend*2)*8];   /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters_8[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_8[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              3+Interp_Extend*2, 8, HFilter);
+
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_8(FData + 8*(Interp_Extend-1), dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
+
+}
+
+void vp8_eighttap_predict8x4_sharp_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    // int FData[(7+Interp_Extend*2)*16];   /* Temp data buffer used in filtering */
+    int FData[(3+Interp_Extend*2)*8];   /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters_8s[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_8s[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              3+Interp_Extend*2, 8, HFilter);
+
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_8(FData + 8*(Interp_Extend-1), dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
+
+}
+
+void vp8_eighttap_predict16x16_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    // int FData[(15+Interp_Extend*2)*24];   /* Temp data buffer used in filtering */
+    int FData[(15+Interp_Extend*2)*16];  /* Temp data buffer used in filtering */
+
+
+    HFilter = vp8_sub_pel_filters_8[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_8[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              15+Interp_Extend*2, 16, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_8(FData + 16*(Interp_Extend-1), dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
+
+}
+
+void vp8_eighttap_predict16x16_sharp_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    // int FData[(15+Interp_Extend*2)*24];   /* Temp data buffer used in filtering */
+    int FData[(15+Interp_Extend*2)*16];  /* Temp data buffer used in filtering */
+
+
+    HFilter = vp8_sub_pel_filters_8s[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_8s[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData, src_pixels_per_line, 1,
+                              15+Interp_Extend*2, 16, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_8(FData + 16*(Interp_Extend-1), dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
+
+}
+
+void vp8_eighttap_predict_avg16x16_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    // int FData[(15+Interp_Extend*2)*24];   /* Temp data buffer used in filtering */
+    int FData[(15+Interp_Extend*2)*16];  /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters_8[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_8[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData,
+                              src_pixels_per_line, 1, 15+Interp_Extend*2, 16, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_avg_8(FData + 16*(Interp_Extend-1), dst_ptr, dst_pitch,
+                                   16, 16, 16, 16, VFilter);
+}
+
+void vp8_eighttap_predict_avg16x16_sharp_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    // int FData[(15+Interp_Extend*2)*24];   /* Temp data buffer used in filtering */
+    int FData[(15+Interp_Extend*2)*16];  /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters_8s[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters_8s[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass_8(src_ptr - ((Interp_Extend-1) * src_pixels_per_line), FData,
+                              src_pixels_per_line, 1, 15+Interp_Extend*2, 16, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass_avg_8(FData + 16*(Interp_Extend-1), dst_ptr, dst_pitch,
+                                   16, 16, 16, 16, VFilter);
+}
+
+#endif  /* CONFIG_ENHANCED_INTERP */
+
 /****************************************************************************
  *
  *  ROUTINE       : filter_block2d_bil_first_pass
index d502216..d1be975 100644 (file)
@@ -25,6 +25,8 @@
 #endif
 
 extern const short vp8_bilinear_filters[SUBPEL_SHIFTS][2];
-extern const short vp8_sub_pel_filters[SUBPEL_SHIFTS][INTERP_EXTEND*2];
+extern const short vp8_sub_pel_filters_6[SUBPEL_SHIFTS][6];
+extern const short vp8_sub_pel_filters_8[SUBPEL_SHIFTS][8];
+extern const short vp8_sub_pel_filters_8s[SUBPEL_SHIFTS][8];
 
 #endif //FILTER_H
index 6168dc5..79c53a9 100644 (file)
@@ -79,6 +79,20 @@ void vp8_machine_specific_config(VP8_COMMON *ctx)
         vp8_comp_intra_uv4x4_predict;
 #endif
 
+#if CONFIG_ENHANCED_INTERP
+    rtcd->subpix.eighttap16x16       = vp8_eighttap_predict16x16_c;
+    rtcd->subpix.eighttap8x8         = vp8_eighttap_predict8x8_c;
+    rtcd->subpix.eighttap_avg16x16   = vp8_eighttap_predict_avg16x16_c;
+    rtcd->subpix.eighttap_avg8x8     = vp8_eighttap_predict_avg8x8_c;
+    rtcd->subpix.eighttap8x4         = vp8_eighttap_predict8x4_c;
+    rtcd->subpix.eighttap4x4         = vp8_eighttap_predict_c;
+    rtcd->subpix.eighttap16x16_sharp       = vp8_eighttap_predict16x16_sharp_c;
+    rtcd->subpix.eighttap8x8_sharp         = vp8_eighttap_predict8x8_sharp_c;
+    rtcd->subpix.eighttap_avg16x16_sharp   = vp8_eighttap_predict_avg16x16_sharp_c;
+    rtcd->subpix.eighttap_avg8x8_sharp     = vp8_eighttap_predict_avg8x8_sharp_c;
+    rtcd->subpix.eighttap8x4_sharp         = vp8_eighttap_predict8x4_sharp_c;
+    rtcd->subpix.eighttap4x4_sharp         = vp8_eighttap_predict_sharp_c;
+#endif
     rtcd->subpix.sixtap16x16       = vp8_sixtap_predict16x16_c;
     rtcd->subpix.sixtap8x8         = vp8_sixtap_predict8x8_c;
     rtcd->subpix.sixtap_avg16x16   = vp8_sixtap_predict_avg16x16_c;
index 68ebb67..9b253e9 100644 (file)
@@ -71,7 +71,11 @@ typedef enum
 typedef enum
 {
     SIXTAP   = 0,
-    BILINEAR = 1
+    BILINEAR = 1,
+#if CONFIG_ENHANCED_INTERP
+    EIGHTTAP = 2,
+    EIGHTTAP_SHARP = 3,
+#endif
 } INTERPOLATIONFILTERTYPE;
 
 typedef enum
index 0b1b72f..330b3c2 100644 (file)
@@ -53,6 +53,68 @@ extern prototype_subpixel_predict(vp8_subpix_sixtap8x4);
 #endif
 extern prototype_subpixel_predict(vp8_subpix_sixtap4x4);
 
+#if CONFIG_ENHANCED_INTERP
+#ifndef vp8_subpix_eighttap16x16
+#define vp8_subpix_eighttap16x16 vp8_eighttap_predict16x16_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap16x16);
+
+#ifndef vp8_subpix_eighttap8x8
+#define vp8_subpix_eighttap8x8 vp8_eighttap_predict8x8_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap8x8);
+
+#ifndef vp8_subpix_eighttap_avg16x16
+#define vp8_subpix_eighttap_avg16x16 vp8_eighttap_predict_avg16x16_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap_avg16x16);
+
+#ifndef vp8_subpix_eighttap_avg8x8
+#define vp8_subpix_eighttap_avg8x8 vp8_eighttap_predict_avg8x8_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap_avg8x8);
+
+#ifndef vp8_subpix_eighttap8x4
+#define vp8_subpix_eighttap8x4 vp8_eighttap_predict8x4_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap8x4);
+
+#ifndef vp8_subpix_eighttap4x4
+#define vp8_subpix_eighttap4x4 vp8_eighttap_predict_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap4x4);
+
+#ifndef vp8_subpix_eighttap16x16_sharp
+#define vp8_subpix_eighttap16x16_sharp vp8_eighttap_predict16x16_sharp_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap16x16_sharp);
+
+#ifndef vp8_subpix_eighttap8x8_sharp
+#define vp8_subpix_eighttap8x8_sharp vp8_eighttap_predict8x8_sharp_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap8x8_sharp);
+
+#ifndef vp8_subpix_eighttap_avg16x16_sharp
+#define vp8_subpix_eighttap_avg16x16_sharp vp8_eighttap_predict_avg16x16_sharp_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap_avg16x16_sharp);
+
+#ifndef vp8_subpix_eighttap_avg8x8_sharp
+#define vp8_subpix_eighttap_avg8x8_sharp vp8_eighttap_predict_avg8x8_sharp_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap_avg8x8_sharp);
+
+#ifndef vp8_subpix_eighttap8x4_sharp
+#define vp8_subpix_eighttap8x4_sharp vp8_eighttap_predict8x4_sharp_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap8x4_sharp);
+
+#ifndef vp8_subpix_eighttap4x4_sharp
+#define vp8_subpix_eighttap4x4_sharp vp8_eighttap_predict_sharp_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_eighttap4x4_sharp);
+#endif  /* CONFIG_ENAHNCED_INTERP */
+
 #ifndef vp8_subpix_bilinear16x16
 #define vp8_subpix_bilinear16x16 vp8_bilinear_predict16x16_c
 #endif
@@ -86,6 +148,20 @@ extern prototype_subpixel_predict(vp8_subpix_bilinear4x4);
 typedef prototype_subpixel_predict((*vp8_subpix_fn_t));
 typedef struct
 {
+#if CONFIG_ENHANCED_INTERP
+    vp8_subpix_fn_t  eighttap16x16;
+    vp8_subpix_fn_t  eighttap8x8;
+    vp8_subpix_fn_t  eighttap_avg16x16;
+    vp8_subpix_fn_t  eighttap_avg8x8;
+    vp8_subpix_fn_t  eighttap8x4;
+    vp8_subpix_fn_t  eighttap4x4;
+    vp8_subpix_fn_t  eighttap16x16_sharp;
+    vp8_subpix_fn_t  eighttap8x8_sharp;
+    vp8_subpix_fn_t  eighttap_avg16x16_sharp;
+    vp8_subpix_fn_t  eighttap_avg8x8_sharp;
+    vp8_subpix_fn_t  eighttap8x4_sharp;
+    vp8_subpix_fn_t  eighttap4x4_sharp;
+#endif
     vp8_subpix_fn_t  sixtap16x16;
     vp8_subpix_fn_t  sixtap8x8;
     vp8_subpix_fn_t  sixtap_avg16x16;
index 29b9e9b..9194826 100644 (file)
@@ -650,7 +650,11 @@ static void init_frame(VP8D_COMP *pbi)
     {
 
         if (!pc->use_bilinear_mc_filter)
+#if CONFIG_ENHANCED_INTERP
+            pc->mcomp_filter_type = EIGHTTAP;
+#else
             pc->mcomp_filter_type = SIXTAP;
+#endif
         else
             pc->mcomp_filter_type = BILINEAR;
 
@@ -664,6 +668,30 @@ static void init_frame(VP8D_COMP *pbi)
             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);
+        }
+        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_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);
@@ -1053,6 +1081,47 @@ int vp8_decode_frame(VP8D_COMP *pbi)
         /* Is high precision mv allowed */
         xd->allow_high_precision_mv = (unsigned char)vp8_read_bit(bc);
 #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_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_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_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_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg8x8);
+            xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg16x16);
+        }
+#endif
     }
 
     pc->refresh_entropy_probs = vp8_read_bit(bc);
index 95bf3c3..b698618 100644 (file)
@@ -2039,6 +2039,10 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
         // Signal whether to allow high MV precision
         vp8_write_bit(bc, (xd->allow_high_precision_mv) ? 1 : 0);
 #endif
+#if CONFIG_ENHANCED_INTERP
+        // Signal the type of subpel filter to use
+        vp8_write_literal(bc, (pc->mcomp_filter_type), 2);
+#endif
     }
 
     vp8_write_bit(bc, pc->refresh_entropy_probs);
index 639c1fa..fdc66c0 100644 (file)
@@ -672,6 +672,38 @@ static void encode_frame_internal(VP8_COMP *cpi)
         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_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_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(
index 455224c..6195c4c 100644 (file)
@@ -1434,7 +1434,11 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
     cpi->cq_target_quality = cpi->oxcf.cq_level;
 
     if (!cm->use_bilinear_mc_filter)
+#if CONFIG_ENHANCED_INTERP
+        cm->mcomp_filter_type = EIGHTTAP;
+#else
         cm->mcomp_filter_type = SIXTAP;
+#endif
     else
         cm->mcomp_filter_type = BILINEAR;
 
@@ -2552,6 +2556,36 @@ void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame)
 }
 #endif
 
+static double compute_edge_pixel_proportion(YV12_BUFFER_CONFIG *frame)
+{
+#define EDGE_THRESH 128
+    int i, j;
+    int num_edge_pels = 0;
+    int num_pels = (frame->y_height - 2) * (frame->y_width - 2);
+    unsigned char *prev = frame->y_buffer + 1;
+    unsigned char *curr = frame->y_buffer + 1 + frame->y_stride;
+    unsigned char *next = frame->y_buffer + 1 + 2*frame->y_stride;
+    for (i = 1; i < frame->y_height - 1; i++)
+    {
+        for (j = 1; j < frame->y_width - 1; j++)
+        {
+            /* Sobel hor and ver gradients */
+            int v = 2*(curr[1] - curr[-1]) + (prev[1] - prev[-1]) + (next[1] - next[-1]);
+            int h = 2*(prev[0] - next[0]) + (prev[1] - next[1]) + (prev[-1] - next[-1]);
+            h = (h < 0 ? -h : h);
+            v = (v < 0 ? -v : v);
+            if (h > EDGE_THRESH || v > EDGE_THRESH) num_edge_pels++;
+            curr++;
+            prev++;
+            next++;
+        }
+        curr += frame->y_stride - frame->y_width + 2;
+        prev += frame->y_stride - frame->y_width + 2;
+        next += frame->y_stride - frame->y_width + 2;
+    }
+    return (double)num_edge_pels/(double)num_pels;
+}
+
 // Function to test for conditions that indeicate we should loop
 // back and recode a frame.
 static BOOL recode_loop_test( VP8_COMP *cpi,
@@ -3070,11 +3104,18 @@ static void encode_frame_to_data_rate
 
     loop_count = 0;
 
-#if CONFIG_HIGH_PRECISION_MV
-    /* Decide this based on various factors */
+#if CONFIG_HIGH_PRECISION_MV || CONFIG_ENHANCED_INTERP
     if (cm->frame_type != KEY_FRAME)
     {
+        double e = compute_edge_pixel_proportion(cpi->Source);
+#if CONFIG_HIGH_PRECISION_MV
+        /* TODO: Decide this more intelligently */
         xd->allow_high_precision_mv = (Q < HIGH_PRECISION_MV_QTHRESH);
+#endif
+#if CONFIG_ENHANCED_INTERP
+        /* TODO: Decide this more intelligently */
+        cm->mcomp_filter_type = (e > 0.1 ? EIGHTTAP_SHARP : EIGHTTAP);
+#endif
     }
 #endif