filter.c 43.7 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5 6
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS.  All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
John Koleszar's avatar
John Koleszar committed
9 10 11 12
 */


#include <stdlib.h>
Johann's avatar
Johann committed
13 14
#include "filter.h"
#include "vpx_ports/mem.h"
15
#include "vpx_rtcd.h"
John Koleszar's avatar
John Koleszar committed
16

17
DECLARE_ALIGNED(16, const short, vp9_bilinear_filters[SUBPEL_SHIFTS][2]) = {
John Koleszar's avatar
John Koleszar committed
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
  { 128,   0 },
  { 120,   8 },
  { 112,  16 },
  { 104,  24 },
  {  96,  32 },
  {  88,  40 },
  {  80,  48 },
  {  72,  56 },
  {  64,  64 },
  {  56,  72 },
  {  48,  80 },
  {  40,  88 },
  {  32,  96 },
  {  24, 104 },
  {  16, 112 },
  {   8, 120 }
John Koleszar's avatar
John Koleszar committed
34 35
};

36
#define FILTER_ALPHA       0
37
#define FILTER_ALPHA_SHARP 1
38
DECLARE_ALIGNED(16, const short, vp9_sub_pel_filters_8[SUBPEL_SHIFTS][8]) = {
39
#if FILTER_ALPHA == 0
John Koleszar's avatar
John Koleszar committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
  /* 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}
57
#elif FILTER_ALPHA == 50
John Koleszar's avatar
John Koleszar committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
  /* Generated using MATLAB:
   * alpha = 0.5;
   * b=intfilt(8,4,alpha);
   * bi=round(128*b);
   * ba=flipud(reshape([bi 0], 8, 8));
   * disp(num2str(ba, '%d,'))
   */
  { 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}
81 82 83
#endif  /* FILTER_ALPHA */
};

84
DECLARE_ALIGNED(16, const short, vp9_sub_pel_filters_8s[SUBPEL_SHIFTS][8]) = {
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
#if FILTER_ALPHA_SHARP == 1
  /* dct based filter */
  {0,   0,   0, 128,   0,   0,   0, 0},
  {-1,   3,  -7, 127,   8,  -3,   1, 0},
  {-2,   5, -13, 125,  17,  -6,   3, -1},
  {-3,   7, -17, 121,  27, -10,   5, -2},
  {-4,   9, -20, 115,  37, -13,   6, -2},
  {-4,  10, -23, 108,  48, -16,   8, -3},
  {-4,  10, -24, 100,  59, -19,   9, -3},
  {-4,  11, -24,  90,  70, -21,  10, -4},
  {-4,  11, -23,  80,  80, -23,  11, -4},
  {-4,  10, -21,  70,  90, -24,  11, -4},
  {-3,   9, -19,  59, 100, -24,  10, -4},
  {-3,   8, -16,  48, 108, -23,  10, -4},
  {-2,   6, -13,  37, 115, -20,   9, -4},
  {-2,   5, -10,  27, 121, -17,   7, -3},
  {-1,   3,  -6,  17, 125, -13,   5, -2},
  {0,   1,  -3,   8, 127,  -7,   3, -1}
#elif FILTER_ALPHA_SHARP == 75
104
  /* alpha = 0.75 */
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
  {0,   0,   0, 128,   0,   0,   0, 0},
  {-1,   2,  -6, 126,   9,  -3,   2, -1},
  {-1,   4, -11, 123,  18,  -7,   3, -1},
  {-2,   6, -16, 119,  28, -10,   5, -2},
  {-2,   7, -19, 113,  38, -13,   6, -2},
  {-3,   8, -21, 106,  49, -16,   7, -2},
  {-3,   9, -22,  99,  59, -19,   8, -3},
  {-3,   9, -23,  90,  70, -21,   9, -3},
  {-3,   9, -22,  80,  80, -22,   9, -3},
  {-3,   9, -21,  70,  90, -23,   9, -3},
  {-3,   8, -19,  59,  99, -22,   9, -3},
  {-2,   7, -16,  49, 106, -21,   8, -3},
  {-2,   6, -13,  38, 113, -19,   7, -2},
  {-2,   5, -10,  28, 119, -16,   6, -2},
  {-1,   3,  -7,  18, 123, -11,   4, -1},
  {-1,   2,  -3,   9, 126,  -6,   2, -1}
121
#endif  /* FILTER_ALPHA_SHARP */
122
};
123

124
DECLARE_ALIGNED(16, const short, vp9_sub_pel_filters_6[SUBPEL_SHIFTS][6]) = {
John Koleszar's avatar
John Koleszar committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
  {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}
John Koleszar's avatar
John Koleszar committed
141
};
142

143 144 145 146 147 148 149
static void filter_block2d_first_pass_6(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 *vp9_filter) {
John Koleszar's avatar
John Koleszar committed
150 151 152 153 154
  unsigned int i, j;
  int  Temp;

  for (i = 0; i < output_height; i++) {
    for (j = 0; j < output_width; j++) {
155 156 157 158 159 160 161
      Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp9_filter[0]) +
             ((int)src_ptr[-1 * (int)pixel_step] * vp9_filter[1]) +
             ((int)src_ptr[0]                    * vp9_filter[2]) +
             ((int)src_ptr[pixel_step]           * vp9_filter[3]) +
             ((int)src_ptr[2 * pixel_step]       * vp9_filter[4]) +
             ((int)src_ptr[3 * pixel_step]       * vp9_filter[5]) +
             (VP9_FILTER_WEIGHT >> 1);      /* Rounding */
John Koleszar's avatar
John Koleszar committed
162 163

      /* Normalize back to 0-255 */
164
      Temp = Temp >> VP9_FILTER_SHIFT;
John Koleszar's avatar
John Koleszar committed
165 166 167 168 169 170 171 172

      if (Temp < 0)
        Temp = 0;
      else if (Temp > 255)
        Temp = 255;

      output_ptr[j] = Temp;
      src_ptr++;
John Koleszar's avatar
John Koleszar committed
173
    }
John Koleszar's avatar
John Koleszar committed
174 175 176 177 178

    /* Next row... */
    src_ptr    += src_pixels_per_line - output_width;
    output_ptr += output_width;
  }
John Koleszar's avatar
John Koleszar committed
179 180
}

181 182 183 184 185 186 187 188
static void filter_block2d_second_pass_6(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 *vp9_filter) {
John Koleszar's avatar
John Koleszar committed
189 190 191 192 193 194
  unsigned int i, j;
  int  Temp;

  for (i = 0; i < output_height; i++) {
    for (j = 0; j < output_width; j++) {
      /* Apply filter */
195 196 197 198 199 200 201
      Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp9_filter[0]) +
             ((int)src_ptr[-1 * (int)pixel_step] * vp9_filter[1]) +
             ((int)src_ptr[0]                    * vp9_filter[2]) +
             ((int)src_ptr[pixel_step]           * vp9_filter[3]) +
             ((int)src_ptr[2 * pixel_step]         * vp9_filter[4]) +
             ((int)src_ptr[3 * pixel_step]         * vp9_filter[5]) +
             (VP9_FILTER_WEIGHT >> 1);   /* Rounding */
John Koleszar's avatar
John Koleszar committed
202 203

      /* Normalize back to 0-255 */
204
      Temp = Temp >> VP9_FILTER_SHIFT;
John Koleszar's avatar
John Koleszar committed
205 206 207 208 209 210 211 212

      if (Temp < 0)
        Temp = 0;
      else if (Temp > 255)
        Temp = 255;

      output_ptr[j] = (unsigned char)Temp;
      src_ptr++;
John Koleszar's avatar
John Koleszar committed
213
    }
John Koleszar's avatar
John Koleszar committed
214 215 216 217 218

    /* Start next row */
    src_ptr    += src_pixels_per_line - output_width;
    output_ptr += output_pitch;
  }
John Koleszar's avatar
John Koleszar committed
219 220
}

221 222 223 224 225 226 227 228
/*
 * 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.
 */
229 230 231 232 233 234 235 236
static void filter_block2d_second_pass_avg_6(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 *vp9_filter) {
John Koleszar's avatar
John Koleszar committed
237 238 239 240 241 242
  unsigned int i, j;
  int  Temp;

  for (i = 0; i < output_height; i++) {
    for (j = 0; j < output_width; j++) {
      /* Apply filter */
243 244 245 246 247 248 249
      Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp9_filter[0]) +
             ((int)src_ptr[-1 * (int)pixel_step] * vp9_filter[1]) +
             ((int)src_ptr[0]                    * vp9_filter[2]) +
             ((int)src_ptr[pixel_step]           * vp9_filter[3]) +
             ((int)src_ptr[2 * pixel_step]         * vp9_filter[4]) +
             ((int)src_ptr[3 * pixel_step]         * vp9_filter[5]) +
             (VP9_FILTER_WEIGHT >> 1);   /* Rounding */
John Koleszar's avatar
John Koleszar committed
250 251

      /* Normalize back to 0-255 */
252
      Temp = Temp >> VP9_FILTER_SHIFT;
John Koleszar's avatar
John Koleszar committed
253 254 255 256 257 258 259 260

      if (Temp < 0)
        Temp = 0;
      else if (Temp > 255)
        Temp = 255;

      output_ptr[j] = (unsigned char)((output_ptr[j] + Temp + 1) >> 1);
      src_ptr++;
261
    }
John Koleszar's avatar
John Koleszar committed
262 263 264 265 266

    /* Start next row */
    src_ptr    += src_pixels_per_line - output_width;
    output_ptr += output_pitch;
  }
267
}
John Koleszar's avatar
John Koleszar committed
268

269
#define Interp_Extend 3
270 271 272 273 274 275
static void filter_block2d_6(unsigned char  *src_ptr,
                             unsigned char  *output_ptr,
                             unsigned int src_pixels_per_line,
                             int output_pitch,
                             const short  *HFilter,
                             const short  *VFilter) {
John Koleszar's avatar
John Koleszar committed
276 277 278 279 280 281 282 283
  int FData[(3 + Interp_Extend * 2) * 4]; /* Temp data buffer used in filtering */

  /* First filter 1-D horizontally... */
  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_6(FData + 4 * (Interp_Extend - 1), output_ptr, output_pitch, 4, 4, 4, 4, VFilter);
John Koleszar's avatar
John Koleszar committed
284 285 286
}


287 288 289 290 291 292
void vp9_sixtap_predict_c(unsigned char  *src_ptr,
                          int   src_pixels_per_line,
                          int  xoffset,
                          int  yoffset,
                          unsigned char *dst_ptr,
                          int dst_pitch) {
John Koleszar's avatar
John Koleszar committed
293 294 295
  const short  *HFilter;
  const short  *VFilter;

296 297
  HFilter = vp9_sub_pel_filters_6[xoffset];   /* 6 tap */
  VFilter = vp9_sub_pel_filters_6[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
298 299

  filter_block2d_6(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter);
John Koleszar's avatar
John Koleszar committed
300
}
301 302 303 304 305 306 307 308

/*
 * The difference between filter_block2d_6() and filter_block2d_avg_6 is
 * that filter_block2d_6() does a 6-tap filter and stores it in the output
 * buffer, whereas filter_block2d_avg_6() does the same 6-tap filter, and
 * then averages that with the content already present in the output
 * ((filter_result + dest + 1) >> 1) and stores that in the output.
 */
309 310 311 312 313 314
static void filter_block2d_avg_6(unsigned char  *src_ptr,
                                 unsigned char  *output_ptr,
                                 unsigned int src_pixels_per_line,
                                 int output_pitch,
                                 const short  *HFilter,
                                 const short  *VFilter) {
John Koleszar's avatar
John Koleszar committed
315 316 317 318 319 320 321 322 323 324
  int FData[(3 + Interp_Extend * 2) * 4]; /* Temp data buffer used in filtering */

  /* First filter 1-D horizontally... */
  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_avg_6(FData + 4 * (Interp_Extend - 1), output_ptr,
                                   output_pitch, 4, 4, 4, 4, VFilter);
325 326
}

327
void vp9_sixtap_predict_avg_c
328
(
John Koleszar's avatar
John Koleszar committed
329 330 331 332 333 334 335 336 337 338
  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;

339 340
  HFilter = vp9_sub_pel_filters_6[xoffset];   /* 6 tap */
  VFilter = vp9_sub_pel_filters_6[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
341 342 343

  filter_block2d_avg_6(src_ptr, dst_ptr, src_pixels_per_line,
                       dst_pitch, HFilter, VFilter);
344 345
}

346
void vp9_sixtap_predict8x8_c
John Koleszar's avatar
John Koleszar committed
347
(
John Koleszar's avatar
John Koleszar committed
348 349 350 351 352 353 354 355 356 357 358 359
  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 */

360 361
  HFilter = vp9_sub_pel_filters_6[xoffset];   /* 6 tap */
  VFilter = vp9_sub_pel_filters_6[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
362 363 364 365 366 367 368 369

  /* First filter 1-D horizontally... */
  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_6(FData + 8 * (Interp_Extend - 1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
John Koleszar's avatar
John Koleszar committed
370 371 372

}

373
void vp9_sixtap_predict_avg8x8_c
374
(
John Koleszar's avatar
John Koleszar committed
375 376 377 378 379 380 381 382 383 384 385 386
  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 */

387 388
  HFilter = vp9_sub_pel_filters_6[xoffset];   /* 6 tap */
  VFilter = vp9_sub_pel_filters_6[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
389 390 391 392 393 394 395

  /* First filter 1-D horizontally... */
  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_6(FData + 8 * (Interp_Extend - 1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
396 397
}

398
void vp9_sixtap_predict8x4_c
John Koleszar's avatar
John Koleszar committed
399
(
John Koleszar's avatar
John Koleszar committed
400 401 402 403 404 405 406 407 408 409 410 411
  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 */

412 413
  HFilter = vp9_sub_pel_filters_6[xoffset];   /* 6 tap */
  VFilter = vp9_sub_pel_filters_6[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
414 415 416 417 418 419 420 421

  /* First filter 1-D horizontally... */
  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_6(FData + 8 * (Interp_Extend - 1), dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
John Koleszar's avatar
John Koleszar committed
422 423 424

}

425
void vp9_sixtap_predict16x16_c
John Koleszar's avatar
John Koleszar committed
426
(
John Koleszar's avatar
John Koleszar committed
427 428 429 430 431 432 433 434 435 436 437 438 439
  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 */


440 441
  HFilter = vp9_sub_pel_filters_6[xoffset];   /* 6 tap */
  VFilter = vp9_sub_pel_filters_6[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
442 443 444 445 446 447 448

  /* First filter 1-D horizontally... */
  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_6(FData + 16 * (Interp_Extend - 1), dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
John Koleszar's avatar
John Koleszar committed
449 450 451

}

452
void vp9_sixtap_predict_avg16x16_c
453
(
John Koleszar's avatar
John Koleszar committed
454 455 456 457 458 459 460 461 462 463 464 465
  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 */

466 467
  HFilter = vp9_sub_pel_filters_6[xoffset];   /* 6 tap */
  VFilter = vp9_sub_pel_filters_6[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
468 469 470 471 472 473 474

  /* First filter 1-D horizontally... */
  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_6(FData + 16 * (Interp_Extend - 1), dst_ptr, dst_pitch,
475 476
                                   16, 16, 16, 16, VFilter);
}
John Koleszar's avatar
John Koleszar committed
477

478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
typedef enum {
  VPX_FILTER_4x4 = 0,
  VPX_FILTER_8x8 = 1,
  VPX_FILTER_8x4 = 2,
  VPX_FILTER_16x16 = 3,
} filter_size_t;

static const unsigned int filter_size_to_wh[][2] = {
  {4, 4},
  {8, 8},
  {8, 4},
  {16,16},
};

static const unsigned int filter_max_height = 16;
static const unsigned int filter_max_width = 16;
494

495 496 497 498 499 500 501
static void filter_block2d_8_c(const unsigned char *src_ptr,
                               const unsigned int   src_stride,
                               const short *HFilter,
                               const short *VFilter,
                               const filter_size_t filter_size,
                               unsigned char *dst_ptr,
                               unsigned int   dst_stride) {
502 503 504 505 506 507 508 509 510 511 512 513
  const unsigned int output_width = filter_size_to_wh[filter_size][0];
  const unsigned int output_height = filter_size_to_wh[filter_size][1];

  // Between passes, we use an intermediate buffer whose height is extended to
  // have enough horizontally filtered values as input for the vertical pass.
  // This buffer is allocated to be big enough for the largest block type we
  // support.
  const int kInterp_Extend = 4;
  const unsigned int intermediate_height =
    (kInterp_Extend - 1) +     output_height + kInterp_Extend;
  const unsigned int max_intermediate_height =
    (kInterp_Extend - 1) + filter_max_height + kInterp_Extend;
Yaowu Xu's avatar
Yaowu Xu committed
514 515 516 517
#ifdef _MSC_VER
  // MSVC does not support C99 style declaration
  unsigned char intermediate_buffer[23 * 16];
#else
518
  unsigned char intermediate_buffer[max_intermediate_height * filter_max_width];
Yaowu Xu's avatar
Yaowu Xu committed
519
#endif
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
  const int intermediate_next_stride = 1 - intermediate_height * output_width;

  // Horizontal pass (src -> transposed intermediate).
  {
    unsigned char *output_ptr = intermediate_buffer;
    const int src_next_row_stride = src_stride - output_width;
    unsigned int i, j;
    src_ptr -= (kInterp_Extend - 1) * src_stride + (kInterp_Extend - 1);
    for (i = 0; i < intermediate_height; i++) {
      for (j = 0; j < output_width; j++) {
        // Apply filter...
        int temp = ((int)src_ptr[0] * HFilter[0]) +
                   ((int)src_ptr[1] * HFilter[1]) +
                   ((int)src_ptr[2] * HFilter[2]) +
                   ((int)src_ptr[3] * HFilter[3]) +
                   ((int)src_ptr[4] * HFilter[4]) +
                   ((int)src_ptr[5] * HFilter[5]) +
                   ((int)src_ptr[6] * HFilter[6]) +
                   ((int)src_ptr[7] * HFilter[7]) +
539
                   (VP9_FILTER_WEIGHT >> 1); // Rounding
540 541

        // Normalize back to 0-255...
542
        temp >>= VP9_FILTER_SHIFT;
543 544 545 546 547 548 549 550 551 552 553
        if (temp < 0) {
          temp = 0;
        } else if (temp > 255) {
          temp = 255;
        }
        src_ptr++;
        *output_ptr = temp;
        output_ptr += intermediate_height;
      }
      src_ptr += src_next_row_stride;
      output_ptr += intermediate_next_stride;
554
    }
John Koleszar's avatar
John Koleszar committed
555 556
  }

557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
  // Vertical pass (transposed intermediate -> dst).
  {
    unsigned char *src_ptr = intermediate_buffer;
    const int dst_next_row_stride = dst_stride - output_width;
    unsigned int i, j;
    for (i = 0; i < output_height; i++) {
      for (j = 0; j < output_width; j++) {
        // Apply filter...
        int temp = ((int)src_ptr[0] * VFilter[0]) +
                   ((int)src_ptr[1] * VFilter[1]) +
                   ((int)src_ptr[2] * VFilter[2]) +
                   ((int)src_ptr[3] * VFilter[3]) +
                   ((int)src_ptr[4] * VFilter[4]) +
                   ((int)src_ptr[5] * VFilter[5]) +
                   ((int)src_ptr[6] * VFilter[6]) +
                   ((int)src_ptr[7] * VFilter[7]) +
573
                   (VP9_FILTER_WEIGHT >> 1); // Rounding
574 575

        // Normalize back to 0-255...
576
        temp >>= VP9_FILTER_SHIFT;
577 578 579 580 581 582 583 584 585 586 587
        if (temp < 0) {
          temp = 0;
        } else if (temp > 255) {
          temp = 255;
        }

        src_ptr += intermediate_height;
        *dst_ptr++ = (unsigned char)temp;
      }
      src_ptr += intermediate_next_stride;
      dst_ptr += dst_next_row_stride;
588
    }
John Koleszar's avatar
John Koleszar committed
589
  }
590 591
}

592 593 594 595 596 597 598 599 600
void vp9_filter_block2d_4x4_8_c(const unsigned char *src_ptr,
                                const unsigned int src_stride,
                                const short *HFilter_aligned16,
                                const short *VFilter_aligned16,
                                unsigned char *dst_ptr,
                                unsigned int dst_stride) {
  filter_block2d_8_c(src_ptr, src_stride,
                     HFilter_aligned16, VFilter_aligned16,
                     VPX_FILTER_4x4, dst_ptr, dst_stride);
601 602
}

603 604 605 606 607 608 609 610 611
void vp9_filter_block2d_8x4_8_c(const unsigned char *src_ptr,
                                const unsigned int src_stride,
                                const short *HFilter_aligned16,
                                const short *VFilter_aligned16,
                                unsigned char *dst_ptr,
                                unsigned int dst_stride) {
  filter_block2d_8_c(src_ptr, src_stride,
                     HFilter_aligned16, VFilter_aligned16,
                     VPX_FILTER_8x4, dst_ptr, dst_stride);
612 613
}

614 615 616 617 618 619 620 621 622
void vp9_filter_block2d_8x8_8_c(const unsigned char *src_ptr,
                                const unsigned int src_stride,
                                const short *HFilter_aligned16,
                                const short *VFilter_aligned16,
                                unsigned char *dst_ptr,
                                unsigned int dst_stride) {
  filter_block2d_8_c(src_ptr, src_stride,
                     HFilter_aligned16, VFilter_aligned16,
                     VPX_FILTER_8x8, dst_ptr, dst_stride);
623 624
}

625 626 627 628 629 630 631 632 633
void vp9_filter_block2d_16x16_8_c(const unsigned char *src_ptr,
                                  const unsigned int src_stride,
                                  const short *HFilter_aligned16,
                                  const short *VFilter_aligned16,
                                  unsigned char *dst_ptr,
                                  unsigned int dst_stride) {
  filter_block2d_8_c(src_ptr, src_stride,
                     HFilter_aligned16, VFilter_aligned16,
                     VPX_FILTER_16x16, dst_ptr, dst_stride);
634 635
}

636 637 638 639 640
static void block2d_average_c(unsigned char *src,
                              unsigned int   src_stride,
                              unsigned char *output_ptr,
                              unsigned int output_stride,
                              const filter_size_t filter_size) {
641 642
  const unsigned int output_width = filter_size_to_wh[filter_size][0];
  const unsigned int output_height = filter_size_to_wh[filter_size][1];
John Koleszar's avatar
John Koleszar committed
643

644
  unsigned int i, j;
John Koleszar's avatar
John Koleszar committed
645 646
  for (i = 0; i < output_height; i++) {
    for (j = 0; j < output_width; j++) {
647
      output_ptr[j] = (output_ptr[j] + src[i * src_stride + j] + 1) >> 1;
648
    }
649
    output_ptr += output_stride;
John Koleszar's avatar
John Koleszar committed
650
  }
651 652
}

653
#define block2d_average block2d_average_c
654

655 656 657 658 659 660
void vp9_eighttap_predict_c(unsigned char  *src_ptr,
                            int   src_pixels_per_line,
                            int  xoffset,
                            int  yoffset,
                            unsigned char *dst_ptr,
                            int dst_pitch) {
John Koleszar's avatar
John Koleszar committed
661 662 663
  const short  *HFilter;
  const short  *VFilter;

664 665
  HFilter = vp9_sub_pel_filters_8[xoffset];
  VFilter = vp9_sub_pel_filters_8[yoffset];
John Koleszar's avatar
John Koleszar committed
666

667
  vp9_filter_block2d_4x4_8(src_ptr, src_pixels_per_line,
668 669
                           HFilter, VFilter,
                           dst_ptr, dst_pitch);
670 671
}

672 673 674 675 676 677
void vp9_eighttap_predict_avg4x4_c(unsigned char  *src_ptr,
                                   int   src_pixels_per_line,
                                   int  xoffset,
                                   int  yoffset,
                                   unsigned char *dst_ptr,
                                   int dst_pitch) {
678 679
  const short  *HFilter = vp9_sub_pel_filters_8[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8[yoffset];
680 681
  unsigned char tmp[4 * 4];

682
  vp9_filter_block2d_4x4_8(src_ptr, src_pixels_per_line,
683 684
                           HFilter, VFilter,
                           tmp, 4);
685
  block2d_average(tmp, 4, dst_ptr, dst_pitch, VPX_FILTER_4x4);
686 687
}

688 689 690 691 692 693
void vp9_eighttap_predict_sharp_c(unsigned char  *src_ptr,
                                  int   src_pixels_per_line,
                                  int  xoffset,
                                  int  yoffset,
                                  unsigned char *dst_ptr,
                                  int dst_pitch) {
John Koleszar's avatar
John Koleszar committed
694 695 696
  const short  *HFilter;
  const short  *VFilter;

697 698
  HFilter = vp9_sub_pel_filters_8s[xoffset];
  VFilter = vp9_sub_pel_filters_8s[yoffset];
John Koleszar's avatar
John Koleszar committed
699

700
  vp9_filter_block2d_4x4_8(src_ptr, src_pixels_per_line,
701 702
                           HFilter, VFilter,
                           dst_ptr, dst_pitch);
703 704
}

705 706 707 708 709 710
void vp9_eighttap_predict_avg4x4_sharp_c(unsigned char  *src_ptr,
                                         int   src_pixels_per_line,
                                         int  xoffset,
                                         int  yoffset,
                                         unsigned char *dst_ptr,
                                         int dst_pitch) {
711 712
  const short  *HFilter = vp9_sub_pel_filters_8s[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8s[yoffset];
713 714
  unsigned char tmp[4 * 4];

715
  vp9_filter_block2d_4x4_8(src_ptr, src_pixels_per_line,
716 717
                           HFilter, VFilter,
                           tmp, 4);
718
  block2d_average(tmp, 4, dst_ptr, dst_pitch, VPX_FILTER_4x4);
719 720
}

721 722 723 724 725 726
void vp9_eighttap_predict8x8_c(unsigned char  *src_ptr,
                               int  src_pixels_per_line,
                               int  xoffset,
                               int  yoffset,
                               unsigned char *dst_ptr,
                               int  dst_pitch) {
727 728
  const short  *HFilter = vp9_sub_pel_filters_8[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8[yoffset];
John Koleszar's avatar
John Koleszar committed
729

730
  vp9_filter_block2d_8x8_8(src_ptr, src_pixels_per_line,
731 732
                           HFilter, VFilter,
                           dst_ptr, dst_pitch);
733 734
}

735 736 737 738 739 740
void vp9_eighttap_predict8x8_sharp_c(unsigned char  *src_ptr,
                                     int  src_pixels_per_line,
                                     int  xoffset,
                                     int  yoffset,
                                     unsigned char *dst_ptr,
                                     int  dst_pitch) {
741 742
  const short  *HFilter = vp9_sub_pel_filters_8s[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8s[yoffset];
John Koleszar's avatar
John Koleszar committed
743

744
  vp9_filter_block2d_8x8_8(src_ptr, src_pixels_per_line,
745 746
                           HFilter, VFilter,
                           dst_ptr, dst_pitch);
747 748
}

749 750 751 752 753 754
void vp9_eighttap_predict_avg8x8_c(unsigned char  *src_ptr,
                                   int  src_pixels_per_line,
                                   int  xoffset,
                                   int  yoffset,
                                   unsigned char *dst_ptr,
                                   int  dst_pitch) {
755
  unsigned char tmp[8 * 8];
756 757
  const short  *HFilter = vp9_sub_pel_filters_8[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8[yoffset];
758

759
  vp9_filter_block2d_8x8_8(src_ptr, src_pixels_per_line,
760 761
                           HFilter, VFilter,
                           tmp, 8);
762
  block2d_average(tmp, 8, dst_ptr, dst_pitch, VPX_FILTER_8x8);
763 764
}

765 766 767 768 769 770
void vp9_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) {
771
  unsigned char tmp[8 * 8];
772 773
  const short  *HFilter = vp9_sub_pel_filters_8s[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8s[yoffset];
774

775
  vp9_filter_block2d_8x8_8(src_ptr, src_pixels_per_line,
776 777
                           HFilter, VFilter,
                           tmp, 8);
778
  block2d_average(tmp, 8, dst_ptr, dst_pitch, VPX_FILTER_8x8);
779 780
}

781 782 783 784 785 786
void vp9_eighttap_predict8x4_c(unsigned char  *src_ptr,
                               int  src_pixels_per_line,
                               int  xoffset,
                               int  yoffset,
                               unsigned char *dst_ptr,
                               int  dst_pitch) {
787 788
  const short  *HFilter = vp9_sub_pel_filters_8[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8[yoffset];
789

790
  vp9_filter_block2d_8x4_8(src_ptr, src_pixels_per_line,
791 792
                           HFilter, VFilter,
                           dst_ptr, dst_pitch);
793 794
}

795 796 797 798 799 800
void vp9_eighttap_predict8x4_sharp_c(unsigned char  *src_ptr,
                                     int  src_pixels_per_line,
                                     int  xoffset,
                                     int  yoffset,
                                     unsigned char *dst_ptr,
                                     int  dst_pitch) {
801 802
  const short  *HFilter = vp9_sub_pel_filters_8s[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8s[yoffset];
803

804
  vp9_filter_block2d_8x4_8(src_ptr, src_pixels_per_line,
805 806
                           HFilter, VFilter,
                           dst_ptr, dst_pitch);
807 808
}

809 810 811 812 813 814
void vp9_eighttap_predict16x16_c(unsigned char  *src_ptr,
                                 int  src_pixels_per_line,
                                 int  xoffset,
                                 int  yoffset,
                                 unsigned char *dst_ptr,
                                 int  dst_pitch) {
815 816
  const short  *HFilter = vp9_sub_pel_filters_8[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8[yoffset];
817

818
  vp9_filter_block2d_16x16_8(src_ptr, src_pixels_per_line,
819
                       HFilter, VFilter,
820
                       dst_ptr, dst_pitch);
821 822
}

823 824 825 826 827 828
void vp9_eighttap_predict16x16_sharp_c(unsigned char  *src_ptr,
                                       int  src_pixels_per_line,
                                       int  xoffset,
                                       int  yoffset,
                                       unsigned char *dst_ptr,
                                       int  dst_pitch) {
829 830
  const short  *HFilter = vp9_sub_pel_filters_8s[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8s[yoffset];
831

832
  vp9_filter_block2d_16x16_8(src_ptr, src_pixels_per_line,
833
                       HFilter, VFilter,
834
                       dst_ptr, dst_pitch);
835 836
}

837 838 839 840 841 842
void vp9_eighttap_predict_avg16x16_c(unsigned char  *src_ptr,
                                     int  src_pixels_per_line,
                                     int  xoffset,
                                     int  yoffset,
                                     unsigned char *dst_ptr,
                                     int  dst_pitch) {
Scott LaVarnway's avatar
Scott LaVarnway committed
843
  DECLARE_ALIGNED_ARRAY(16, unsigned char, tmp, 16 * 16);
844 845
  const short  *HFilter = vp9_sub_pel_filters_8[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8[yoffset];
John Koleszar's avatar
John Koleszar committed
846

847
  vp9_filter_block2d_16x16_8(src_ptr, src_pixels_per_line,
848
                       HFilter, VFilter,
849
                       tmp, 16);
850
  block2d_average(tmp, 16, dst_ptr, dst_pitch, VPX_FILTER_16x16);
851 852
}

853 854 855 856 857 858
void vp9_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) {
Scott LaVarnway's avatar
Scott LaVarnway committed
859
  DECLARE_ALIGNED_ARRAY(16, unsigned char, tmp, 16 * 16);
860 861
  const short  *HFilter = vp9_sub_pel_filters_8s[xoffset];
  const short  *VFilter = vp9_sub_pel_filters_8s[yoffset];
862

863
  vp9_filter_block2d_16x16_8(src_ptr, src_pixels_per_line,
864
                       HFilter, VFilter,
865
                       tmp, 16);
866
  block2d_average(tmp, 16, dst_ptr, dst_pitch, VPX_FILTER_16x16);
867 868
}

John Koleszar's avatar
John Koleszar committed
869 870 871 872
/****************************************************************************
 *
 *  ROUTINE       : filter_block2d_bil_first_pass
 *
Johann's avatar
Johann committed
873 874 875 876
 *  INPUTS        : UINT8  *src_ptr    : Pointer to source block.
 *                  UINT32  src_stride : Stride of source block.
 *                  UINT32  height     : Block height.
 *                  UINT32  width      : Block width.
877
 *                  INT32  *vp9_filter : Array of 2 bi-linear filter taps.
John Koleszar's avatar
John Koleszar committed
878
 *
Johann's avatar
Johann committed
879
 *  OUTPUTS       : INT32  *dst_ptr    : Pointer to filtered block.
John Koleszar's avatar
John Koleszar committed
880 881 882
 *
 *  RETURNS       : void
 *
Johann's avatar
Johann committed
883 884 885
 *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block
 *                  in the horizontal direction to produce the filtered output
 *                  block. Used to implement first-pass of 2-D separable filter.
John Koleszar's avatar
John Koleszar committed
886 887
 *
 *  SPECIAL NOTES : Produces INT32 output to retain precision for next pass.
888
 *                  Two filter taps should sum to VP9_FILTER_WEIGHT.
John Koleszar's avatar
John Koleszar committed
889 890
 *
 ****************************************************************************/
891 892 893 894 895 896
static void filter_block2d_bil_first_pass(unsigned char  *src_ptr,
                                          unsigned short *dst_ptr,
                                          unsigned int    src_stride,
                                          unsigned int    height,
                                          unsigned int    width,
                                          const short    *vp9_filter) {
John Koleszar's avatar
John Koleszar committed
897 898 899 900 901
  unsigned int i, j;

  for (i = 0; i < height; i++) {
    for (j = 0; j < width; j++) {
      /* Apply bilinear filter */
902 903 904
      dst_ptr[j] = (((int)src_ptr[0] * vp9_filter[0]) +
                    ((int)src_ptr[1] * vp9_filter[1]) +
                    (VP9_FILTER_WEIGHT / 2)) >> VP9_FILTER_SHIFT;
John Koleszar's avatar
John Koleszar committed
905
      src_ptr++;
John Koleszar's avatar
John Koleszar committed
906
    }
John Koleszar's avatar
John Koleszar committed
907 908 909 910 911

    /* Next row... */
    src_ptr += src_stride - width;
    dst_ptr += width;
  }
John Koleszar's avatar
John Koleszar committed
912 913 914 915 916 917
}

/****************************************************************************
 *
 *  ROUTINE       : filter_block2d_bil_second_pass
 *
Johann's avatar
Johann committed
918 919 920 921
 *  INPUTS        : INT32  *src_ptr    : Pointer to source block.
 *                  UINT32  dst_pitch  : Destination block pitch.
 *                  UINT32  height     : Block height.
 *                  UINT32  width      : Block width.
922
 *                  INT32  *vp9_filter : Array of 2 bi-linear filter taps.
John Koleszar's avatar
John Koleszar committed
923
 *
Johann's avatar
Johann committed
924
 *  OUTPUTS       : UINT16 *dst_ptr    : Pointer to filtered block.
John Koleszar's avatar
John Koleszar committed
925 926 927
 *
 *  RETURNS       : void
 *
Johann's avatar
Johann committed
928 929 930
 *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block
 *                  in the vertical direction to produce the filtered output
 *                  block. Used to implement second-pass of 2-D separable filter.
John Koleszar's avatar
John Koleszar committed
931 932
 *
 *  SPECIAL NOTES : Requires 32-bit input as produced by filter_block2d_bil_first_pass.
933
 *                  Two filter taps should sum to VP9_FILTER_WEIGHT.
John Koleszar's avatar
John Koleszar committed
934 935
 *
 ****************************************************************************/
936 937 938 939 940 941
static void filter_block2d_bil_second_pass(unsigned short *src_ptr,
                                           unsigned char  *dst_ptr,
                                           int             dst_pitch,
                                           unsigned int    height,
                                           unsigned int    width,
                                           const short    *vp9_filter) {
John Koleszar's avatar
John Koleszar committed
942 943 944 945 946 947
  unsigned int  i, j;
  int  Temp;

  for (i = 0; i < height; i++) {
    for (j = 0; j < width; j++) {
      /* Apply filter */
948 949 950 951
      Temp = ((int)src_ptr[0]     * vp9_filter[0]) +
             ((int)src_ptr[width] * vp9_filter[1]) +
             (VP9_FILTER_WEIGHT / 2);
      dst_ptr[j] = (unsigned int)(Temp >> VP9_FILTER_SHIFT);
John Koleszar's avatar
John Koleszar committed
952
      src_ptr++;
John Koleszar's avatar
John Koleszar committed
953
    }
John Koleszar's avatar
John Koleszar committed
954 955 956 957

    /* Next row... */
    dst_ptr += dst_pitch;
  }
John Koleszar's avatar
John Koleszar committed
958 959
}

960 961 962 963 964 965 966 967 968
/*
 * As before for filter_block2d_second_pass_avg(), the functional difference
 * between filter_block2d_bil_second_pass() and filter_block2d_bil_second_pass_avg()
 * is that filter_block2d_bil_second_pass() does a bilinear filter on input
 * and stores the result in output; filter_block2d_bil_second_pass_avg(),
 * instead, does a bilinear filter on input, averages the resulting value
 * with the values already present in the output and stores the result of
 * that back into the output ((filter_result + dest + 1) >> 1).
 */
969 970 971 972 973 974
static void filter_block2d_bil_second_pass_avg(unsigned short *src_ptr,
                                               unsigned char  *dst_ptr,
                                               int             dst_pitch,
                                               unsigned int    height,
                                               unsigned int    width,
                                               const short    *vp9_filter) {
John Koleszar's avatar
John Koleszar committed
975 976 977 978 979 980
  unsigned int  i, j;
  int  Temp;

  for (i = 0; i < height; i++) {
    for (j = 0; j < width; j++) {
      /* Apply filter */
981 982 983 984
      Temp = ((int)src_ptr[0]     * vp9_filter[0]) +
             ((int)src_ptr[width] * vp9_filter[1]) +
             (VP9_FILTER_WEIGHT / 2);
      dst_ptr[j] = (unsigned int)(((Temp >> VP9_FILTER_SHIFT) + dst_ptr[j] + 1) >> 1);
John Koleszar's avatar
John Koleszar committed
985
      src_ptr++;
986
    }
John Koleszar's avatar
John Koleszar committed
987 988 989 990

    /* Next row... */
    dst_ptr += dst_pitch;
  }
991
}
John Koleszar's avatar
John Koleszar committed
992 993 994 995 996 997

/****************************************************************************
 *
 *  ROUTINE       : filter_block2d_bil
 *
 *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
Johann's avatar
Johann committed
998 999 1000 1001 1002 1003
 *                  UINT32  src_pitch        : Stride of source block.
 *                  UINT32  dst_pitch        : Stride of destination block.
 *                  INT32  *HFilter          : Array of 2 horizontal filter taps.
 *                  INT32  *VFilter          : Array of 2 vertical filter taps.
 *                  INT32  Width             : Block width
 *                  INT32  Height            : Block height
John Koleszar's avatar
John Koleszar committed
1004
 *
Johann's avatar
Johann committed
1005
 *  OUTPUTS       : UINT16 *dst_ptr       : Pointer to filtered block.
John Koleszar's avatar
John Koleszar committed
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
 *
 *  RETURNS       : void
 *
 *  FUNCTION      : 2-D filters an input block by applying a 2-tap
 *                  bi-linear filter horizontally followed by a 2-tap
 *                  bi-linear filter vertically on the result.
 *
 *  SPECIAL NOTES : The largest block size can be handled here is 16x16
 *
 ****************************************************************************/
1016 1017 1018 1019 1020 1021 1022 1023
static void filter_block2d_bil(unsigned char *src_ptr,
                               unsigned char *dst_ptr,
                               unsigned int   src_pitch,
                               unsigned int   dst_pitch,
                               const short   *HFilter,
                               const short   *VFilter,
                               int            Width,
                               int            Height) {
John Koleszar's avatar
John Koleszar committed
1024 1025 1026 1027 1028 1029 1030 1031

  unsigned short FData[17 * 16];  /* Temp data buffer used in filtering */

  /* First filter 1-D horizontally... */
  filter_block2d_bil_first_pass(src_ptr, FData, src_pitch, Height + 1, Width, HFilter);

  /* then 1-D vertically... */
  filter_block2d_bil_second_pass(FData, dst_ptr, dst_pitch, Height, Width, VFilter);
John Koleszar's avatar
John Koleszar committed
1032 1033
}

1034 1035 1036 1037 1038 1039 1040 1041
static void filter_block2d_bil_avg(unsigned char *src_ptr,
                                   unsigned char *dst_ptr,
                                   unsigned int   src_pitch,
                                   unsigned int   dst_pitch,
                                   const short   *HFilter,
                                   const short   *VFilter,
                                   int            Width,
                                   int            Height) {
John Koleszar's avatar
John Koleszar committed
1042 1043 1044 1045 1046 1047 1048
  unsigned short FData[17 * 16];  /* Temp data buffer used in filtering */

  /* First filter 1-D horizontally... */
  filter_block2d_bil_first_pass(src_ptr, FData, src_pitch, Height + 1, Width, HFilter);

  /* then 1-D vertically... */
  filter_block2d_bil_second_pass_avg(FData, dst_ptr, dst_pitch, Height, Width, VFilter);
1049
}
John Koleszar's avatar
John Koleszar committed
1050

1051 1052 1053 1054 1055 1056
void vp9_bilinear_predict4x4_c(unsigned char  *src_ptr,
                               int   src_pixels_per_line,
                               int  xoffset,
                               int  yoffset,
                               unsigned char *dst_ptr,
                               int dst_pitch) {
John Koleszar's avatar
John Koleszar committed
1057 1058 1059
  const short *HFilter;
  const short *VFilter;

1060 1061
  HFilter = vp9_bilinear_filters[xoffset];
  VFilter = vp9_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
1062

John Koleszar's avatar
John Koleszar committed
1063
  filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 4, 4);
John Koleszar's avatar
John Koleszar committed
1064 1065
}

1066 1067 1068 1069 1070 1071
void vp9_bilinear_predict_avg4x4_c(unsigned char  *src_ptr,
                                   int   src_pixels_per_line,
                                   int  xoffset,
                                   int  yoffset,
                                   unsigned char *dst_ptr,
                                   int dst_pitch) {
John Koleszar's avatar
John Koleszar committed
1072 1073 1074
  const short *HFilter;
  const short *VFilter;

1075 1076
  HFilter = vp9_bilinear_filters[xoffset];
  VFilter = vp9_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
1077 1078 1079

  filter_block2d_bil_avg(src_ptr, dst_ptr, src_pixels_per_line,
                         dst_pitch, HFilter, VFilter, 4, 4);
1080 1081
}

1082 1083 1084 1085 1086 1087
void vp9_bilinear_predict8x8_c(unsigned char  *src_ptr,
                               int  src_pixels_per_line,
                               int  xoffset,
                               int  yoffset,
                               unsigned char *dst_ptr,
                               int  dst_pitch) {
John Koleszar's avatar
John Koleszar committed
1088 1089 1090
  const short *HFilter;
  const short *VFilter;

1091 1092
  HFilter = vp9_bilinear_filters[xoffset];
  VFilter = vp9_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
1093 1094

  filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 8);
John Koleszar's avatar
John Koleszar committed
1095 1096 1097

}

1098 1099 1100 1101 1102 1103
void vp9_bilinear_predict_avg8x8_c(unsigned char  *src_ptr,
                                   int  src_pixels_per_line,
                                   int  xoffset,
                                   int  yoffset,
                                   unsigned char *dst_ptr,
                                   int  dst_pitch) {
John Koleszar's avatar
John Koleszar committed
1104 1105 1106
  const short *HFilter;
  const short *VFilter;

1107 1108
  HFilter = vp9_bilinear_filters[xoffset];
  VFilter = vp9_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
1109 1110 1111

  filter_block2d_bil_avg(src_ptr, dst_ptr, src_pixels_per_line,
                         dst_pitch, HFilter, VFilter, 8, 8);
1112 1113
}

1114 1115 1116 1117 1118 1119
void vp9_bilinear_predict8x4_c(unsigned char  *src_ptr,
                               int  src_pixels_per_line,
                               int  xoffset,
                               int  yoffset,
                               unsigned char *dst_ptr,
                               int  dst_pitch) {
John Koleszar's avatar
John Koleszar committed
1120 1121 1122
  const short *HFilter;
  const short *VFilter;

1123 1124
  HFilter = vp9_bilinear_filters[xoffset];
  VFilter = vp9_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
1125 1126

  filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 4);
John Koleszar's avatar
John Koleszar committed
1127 1128 1129

}

1130 1131 1132 1133 1134 1135
void vp9_bilinear_predict16x16_c(unsigned char  *src_ptr,
                                 int  src_pixels_per_line,
                                 int  xoffset,
                                 int  yoffset,
                                 unsigned char *dst_ptr,
                                 int  dst_pitch) {
John Koleszar's avatar
John Koleszar committed
1136 1137 1138
  const short *HFilter;
  const short *VFilter;

1139 1140
  HFilter = vp9_bilinear_filters[xoffset];
  VFilter = vp9_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
1141 1142

  filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 16, 16);
John Koleszar's avatar
John Koleszar committed
1143
}
1144

1145 1146 1147 1148 1149 1150
void vp9_bilinear_predict_avg16x16_c(unsigned char  *src_ptr,
                                     int  src_pixels_per_line,
                                     int  xoffset,
                                     int  yoffset,
                                     unsigned char *dst_ptr,
                                     int  dst_pitch) {
John Koleszar's avatar
John Koleszar committed
1151 1152 1153
  const short *HFilter;
  const short *VFilter;