From: Deb Mukherjee Date: Mon, 19 Mar 2012 14:53:05 +0000 (-0700) Subject: Making subpel filters switchable at frame level X-Git-Tag: v1.3.0~1217^2~379^2~81 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=475d5d5664916d0a61d200a58391a582d44b8c27;p=platform%2Fupstream%2Flibvpx.git Making subpel filters switchable at frame level 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 --- diff --git a/vp8/common/filter.c b/vp8/common/filter.c index d1ef796..a949d7a 100644 --- a/vp8/common/filter.c +++ b/vp8/common/filter.c @@ -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 diff --git a/vp8/common/filter.h b/vp8/common/filter.h index d502216..d1be975 100644 --- a/vp8/common/filter.h +++ b/vp8/common/filter.h @@ -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 diff --git a/vp8/common/generic/systemdependent.c b/vp8/common/generic/systemdependent.c index 6168dc5..79c53a9 100644 --- a/vp8/common/generic/systemdependent.c +++ b/vp8/common/generic/systemdependent.c @@ -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; diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h index 68ebb67..9b253e9 100644 --- a/vp8/common/onyxc_int.h +++ b/vp8/common/onyxc_int.h @@ -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 diff --git a/vp8/common/subpixel.h b/vp8/common/subpixel.h index 0b1b72f..330b3c2 100644 --- a/vp8/common/subpixel.h +++ b/vp8/common/subpixel.h @@ -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; diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index 29b9e9b..9194826 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -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); diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index 95bf3c3..b698618 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -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); diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c index 639c1fa..fdc66c0 100644 --- a/vp8/encoder/encodeframe.c +++ b/vp8/encoder/encodeframe.c @@ -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( diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 455224c..6195c4c 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -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