filter.c 27.4 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"
John Koleszar's avatar
John Koleszar committed
15

Johann's avatar
Johann committed
16
DECLARE_ALIGNED(16, const short, vp8_bilinear_filters[8][2]) =
John Koleszar's avatar
John Koleszar committed
17
18
19
20
21
22
23
24
25
26
27
{
    { 128,   0 },
    { 112,  16 },
    {  96,  32 },
    {  80,  48 },
    {  64,  64 },
    {  48,  80 },
    {  32,  96 },
    {  16, 112 }
};

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#if CONFIG_ENHANCED_INTERP
#define FILTER_ALPHA 75
DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[8][2*INTERP_EXTEND]) =
{
    /* Generated using MATLAB:
     * alpha = 0.75;
     * b=intfilt(8,4,alpha);
     * bi=round(128*b);
     * ba=flipud(reshape([bi 0], 8, 8));
     * disp(num2str(ba, '%d,'))
     */
#if FILTER_ALPHA == 75
    /* alpha = 0.75 */
    { 0,   0,   0, 128,   0,   0,   0,   0},
    {-1,   4, -11, 123,  18,  -7,   3,  -1},
    {-2,   7, -19, 113,  38, -14,   6,  -2},
    {-3,   9, -22,  98,  59, -19,   8,  -3},
    {-3,   9, -22,  80,  80, -22,   9,  -3},
    {-3,   8, -19,  59,  98, -22,   9,  -3},
    {-2,   6, -14,  38, 113, -19,   7,  -2},
    {-1,   3,  -7,  18, 123, -11,   4,  -1}
#elif FILTER_ALPHA == 625
    /* alpha = 0.625 */
    { 0,   0,   0, 128,   0,   0,   0,   0},
    {-1,   3, -10, 123,  18,  -6,   2,  -1},
    {-1,   5, -17, 112,  38, -12,   4,  -1},
    {-1,   6, -20,  97,  58, -17,   6,  -1},
    {-2,   7, -20,  79,  79, -20,   7,  -2},
    {-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 == 50
    /* alpha = 0.5 */
    { 0,   0,   0, 128,   0,   0,   0,   0},
    { 0,   2, -10, 122,  18,  -6,   2,   0},
    {-1,   4, -16, 112,  37, -11,   3,  -1},
    {-1,   5, -18,  96,  58, -16,   4,  -1},
    {-1,   5, -18,  78,  78, -18,   5,  -1},
    {-1,   4, -16,  58,  96, -18,   5,  -1},
    {-1,   3, -11,  37, 112, -16,   4,  -1},
    { 0,   2,  -6,  18, 122, -10,   2,   0}
#endif
};
#else
Johann's avatar
Johann committed
72
DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[8][6]) =
John Koleszar's avatar
John Koleszar committed
73
74
{

75
    { 0,  0,  128,    0,   0,  0 },         /* note that 1/8 pel positions are just as per alpha -0.5 bicubic */
John Koleszar's avatar
John Koleszar committed
76
    { 0, -6,  123,   12,  -1,  0 },
77
    { 2, -11, 108,   36,  -8,  1 },         /* New 1/4 pel 6 tap filter */
John Koleszar's avatar
John Koleszar committed
78
    { 0, -9,   93,   50,  -6,  0 },
79
    { 3, -16,  77,   77, -16,  3 },         /* New 1/2 pel 6 tap filter */
John Koleszar's avatar
John Koleszar committed
80
    { 0, -6,   50,   93,  -9,  0 },
81
    { 1, -8,   36,  108, -11,  2 },         /* New 1/4 pel 6 tap filter */
John Koleszar's avatar
John Koleszar committed
82
83
    { 0, -1,   12,  123,  -6,  0 },
};
84
#endif
John Koleszar's avatar
John Koleszar committed
85

86
static void filter_block2d_first_pass
John Koleszar's avatar
John Koleszar committed
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
(
    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++)
        {
104
#if INTERP_EXTEND == 3
John Koleszar's avatar
John Koleszar committed
105
106
            Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
                   ((int)src_ptr[0]                    * vp8_filter[2]) +
                   ((int)src_ptr[pixel_step]           * vp8_filter[3]) +
                   ((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]) +
133
                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
134
#endif
John Koleszar's avatar
John Koleszar committed
135

136
            /* Normalize back to 0-255 */
John Koleszar's avatar
John Koleszar committed
137
138
139
140
141
142
143
144
145
146
147
            Temp = Temp >> VP8_FILTER_SHIFT;

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

            output_ptr[j] = Temp;
            src_ptr++;
        }

148
        /* Next row... */
John Koleszar's avatar
John Koleszar committed
149
150
151
152
153
        src_ptr    += src_pixels_per_line - output_width;
        output_ptr += output_width;
    }
}

154
static void filter_block2d_second_pass
John Koleszar's avatar
John Koleszar committed
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
(
    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++)
        {
173
            /* Apply filter */
174
#if INTERP_EXTEND == 3
John Koleszar's avatar
John Koleszar committed
175
176
            Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
177
178
179
180
                   ((int)src_ptr[0]                    * vp8_filter[2]) +
                   ((int)src_ptr[pixel_step]           * vp8_filter[3]) +
                   ((int)src_ptr[2*pixel_step]         * vp8_filter[4]) +
                   ((int)src_ptr[3*pixel_step]         * vp8_filter[5]) +
181
                   (VP8_FILTER_WEIGHT >> 1);   /* Rounding */
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#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
John Koleszar's avatar
John Koleszar committed
205

206
            /* Normalize back to 0-255 */
John Koleszar's avatar
John Koleszar committed
207
208
209
210
211
212
213
214
215
216
217
            Temp = Temp >> VP8_FILTER_SHIFT;

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

            output_ptr[j] = (unsigned char)Temp;
            src_ptr++;
        }

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

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#if CONFIG_DUALPRED
/*
 * 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
(
    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 */
253
#if INTERP_EXTEND == 3
254
255
            Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
256
257
258
259
                   ((int)src_ptr[0]                    * vp8_filter[2]) +
                   ((int)src_ptr[pixel_step]           * vp8_filter[3]) +
                   ((int)src_ptr[2*pixel_step]         * vp8_filter[4]) +
                   ((int)src_ptr[3*pixel_step]         * vp8_filter[5]) +
260
                   (VP8_FILTER_WEIGHT >> 1);   /* Rounding */
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302

            /* 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;
    }
}
#endif /* CONFIG_DUALPRED */
John Koleszar's avatar
John Koleszar committed
303

304
static void filter_block2d
John Koleszar's avatar
John Koleszar committed
305
306
307
308
309
310
311
312
313
(
    unsigned char  *src_ptr,
    unsigned char  *output_ptr,
    unsigned int src_pixels_per_line,
    int output_pitch,
    const short  *HFilter,
    const short  *VFilter
)
{
314
    int FData[(3+INTERP_EXTEND*2)*4]; /* Temp data buffer used in filtering */
John Koleszar's avatar
John Koleszar committed
315

316
    /* First filter 1-D horizontally... */
317
318
    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);
John Koleszar's avatar
John Koleszar committed
319

320
    /* then filter verticaly... */
321
    filter_block2d_second_pass(FData + 4*(INTERP_EXTEND-1), output_ptr, output_pitch, 4, 4, 4, 4, VFilter);
John Koleszar's avatar
John Koleszar committed
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
}


void vp8_sixtap_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;

Johann's avatar
Johann committed
338
339
    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
340

341
    filter_block2d(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter);
John Koleszar's avatar
John Koleszar committed
342
343
344
345
346
347
348
349
350
351
352
353
354
}
void vp8_sixtap_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;
355
356
    // 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 */
John Koleszar's avatar
John Koleszar committed
357

Johann's avatar
Johann committed
358
359
    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
360

361
    /* First filter 1-D horizontally... */
362
363
    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);
John Koleszar's avatar
John Koleszar committed
364
365


366
    /* then filter verticaly... */
367
    filter_block2d_second_pass(FData + 8*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
John Koleszar's avatar
John Koleszar committed
368
369
370

}

371
372
373
374
375
376
377
378
379
380
381
382
383
#if CONFIG_DUALPRED
void vp8_sixtap_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;
384
385
    // 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 */
386
387
388
389
390

    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */

    /* First filter 1-D horizontally... */
391
392
    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);
393
394

    /* then filter verticaly... */
395
    filter_block2d_second_pass_avg(FData + 8*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
396
397
398
}
#endif /* CONFIG_DUALPRED */

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

Johann's avatar
Johann committed
414
415
    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
416

417
    /* First filter 1-D horizontally... */
418
419
    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);
John Koleszar's avatar
John Koleszar committed
420
421


422
    /* then filter verticaly... */
423
    filter_block2d_second_pass(FData + 8*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
John Koleszar's avatar
John Koleszar committed
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

}

void vp8_sixtap_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;
439
440
    // 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 */
John Koleszar's avatar
John Koleszar committed
441
442


Johann's avatar
Johann committed
443
444
    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
John Koleszar's avatar
John Koleszar committed
445

446
    /* First filter 1-D horizontally... */
447
448
    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);
John Koleszar's avatar
John Koleszar committed
449

450
    /* then filter verticaly... */
451
    filter_block2d_second_pass(FData + 16*(INTERP_EXTEND-1), dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
John Koleszar's avatar
John Koleszar committed
452
453
454

}

455
456
457
458
459
460
461
462
463
464
465
466
467
#if CONFIG_DUALPRED
void vp8_sixtap_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;
468
469
    // 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 */
470
471
472
473
474

    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */

    /* First filter 1-D horizontally... */
475
476
    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);
477
478

    /* then filter verticaly... */
479
    filter_block2d_second_pass_avg(FData + 16*(INTERP_EXTEND-1), dst_ptr, dst_pitch,
480
481
482
                                   16, 16, 16, 16, VFilter);
}
#endif /* CONFIG_DUALPRED */
John Koleszar's avatar
John Koleszar committed
483
484
485
486
487

/****************************************************************************
 *
 *  ROUTINE       : filter_block2d_bil_first_pass
 *
Johann's avatar
Johann committed
488
489
490
491
492
 *  INPUTS        : UINT8  *src_ptr    : Pointer to source block.
 *                  UINT32  src_stride : Stride of source block.
 *                  UINT32  height     : Block height.
 *                  UINT32  width      : Block width.
 *                  INT32  *vp8_filter : Array of 2 bi-linear filter taps.
John Koleszar's avatar
John Koleszar committed
493
 *
Johann's avatar
Johann committed
494
 *  OUTPUTS       : INT32  *dst_ptr    : Pointer to filtered block.
John Koleszar's avatar
John Koleszar committed
495
496
497
 *
 *  RETURNS       : void
 *
Johann's avatar
Johann committed
498
499
500
 *  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
501
502
503
504
505
 *
 *  SPECIAL NOTES : Produces INT32 output to retain precision for next pass.
 *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
 *
 ****************************************************************************/
506
static void filter_block2d_bil_first_pass
John Koleszar's avatar
John Koleszar committed
507
(
Johann's avatar
Johann committed
508
509
510
511
512
513
    unsigned char  *src_ptr,
    unsigned short *dst_ptr,
    unsigned int    src_stride,
    unsigned int    height,
    unsigned int    width,
    const short    *vp8_filter
John Koleszar's avatar
John Koleszar committed
514
515
516
517
)
{
    unsigned int i, j;

Johann's avatar
Johann committed
518
    for (i = 0; i < height; i++)
John Koleszar's avatar
John Koleszar committed
519
    {
Johann's avatar
Johann committed
520
        for (j = 0; j < width; j++)
John Koleszar's avatar
John Koleszar committed
521
        {
522
            /* Apply bilinear filter */
Johann's avatar
Johann committed
523
524
525
            dst_ptr[j] = (((int)src_ptr[0] * vp8_filter[0]) +
                          ((int)src_ptr[1] * vp8_filter[1]) +
                          (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
John Koleszar's avatar
John Koleszar committed
526
527
528
            src_ptr++;
        }

529
        /* Next row... */
Johann's avatar
Johann committed
530
531
        src_ptr += src_stride - width;
        dst_ptr += width;
John Koleszar's avatar
John Koleszar committed
532
533
534
535
536
537
538
    }
}

/****************************************************************************
 *
 *  ROUTINE       : filter_block2d_bil_second_pass
 *
Johann's avatar
Johann committed
539
540
541
542
543
 *  INPUTS        : INT32  *src_ptr    : Pointer to source block.
 *                  UINT32  dst_pitch  : Destination block pitch.
 *                  UINT32  height     : Block height.
 *                  UINT32  width      : Block width.
 *                  INT32  *vp8_filter : Array of 2 bi-linear filter taps.
John Koleszar's avatar
John Koleszar committed
544
 *
Johann's avatar
Johann committed
545
 *  OUTPUTS       : UINT16 *dst_ptr    : Pointer to filtered block.
John Koleszar's avatar
John Koleszar committed
546
547
548
 *
 *  RETURNS       : void
 *
Johann's avatar
Johann committed
549
550
551
 *  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
552
553
554
555
556
 *
 *  SPECIAL NOTES : Requires 32-bit input as produced by filter_block2d_bil_first_pass.
 *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
 *
 ****************************************************************************/
557
static void filter_block2d_bil_second_pass
John Koleszar's avatar
John Koleszar committed
558
559
(
    unsigned short *src_ptr,
Johann's avatar
Johann committed
560
561
562
563
564
    unsigned char  *dst_ptr,
    int             dst_pitch,
    unsigned int    height,
    unsigned int    width,
    const short    *vp8_filter
John Koleszar's avatar
John Koleszar committed
565
566
567
568
569
)
{
    unsigned int  i, j;
    int  Temp;

Johann's avatar
Johann committed
570
    for (i = 0; i < height; i++)
John Koleszar's avatar
John Koleszar committed
571
    {
Johann's avatar
Johann committed
572
        for (j = 0; j < width; j++)
John Koleszar's avatar
John Koleszar committed
573
        {
574
            /* Apply filter */
Johann's avatar
Johann committed
575
576
            Temp = ((int)src_ptr[0]     * vp8_filter[0]) +
                   ((int)src_ptr[width] * vp8_filter[1]) +
John Koleszar's avatar
John Koleszar committed
577
                   (VP8_FILTER_WEIGHT / 2);
Johann's avatar
Johann committed
578
            dst_ptr[j] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
John Koleszar's avatar
John Koleszar committed
579
580
581
            src_ptr++;
        }

582
        /* Next row... */
Johann's avatar
Johann committed
583
        dst_ptr += dst_pitch;
John Koleszar's avatar
John Koleszar committed
584
585
586
    }
}

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
#if CONFIG_DUALPRED
/*
 * 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).
 */
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    *vp8_filter
)
{
    unsigned int  i, j;
    int  Temp;

    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            /* Apply filter */
            Temp = ((int)src_ptr[0]     * vp8_filter[0]) +
                   ((int)src_ptr[width] * vp8_filter[1]) +
                   (VP8_FILTER_WEIGHT / 2);
            dst_ptr[j] = (unsigned int)(((Temp >> VP8_FILTER_SHIFT) + dst_ptr[j] + 1) >> 1);
            src_ptr++;
        }

        /* Next row... */
        dst_ptr += dst_pitch;
    }
}
#endif /* CONFIG_DUALPRED */
John Koleszar's avatar
John Koleszar committed
627
628
629
630
631
632

/****************************************************************************
 *
 *  ROUTINE       : filter_block2d_bil
 *
 *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
Johann's avatar
Johann committed
633
634
635
636
637
638
 *                  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
639
 *
Johann's avatar
Johann committed
640
 *  OUTPUTS       : UINT16 *dst_ptr       : Pointer to filtered block.
John Koleszar's avatar
John Koleszar committed
641
642
643
644
645
646
647
648
649
650
 *
 *  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
 *
 ****************************************************************************/
651
static void filter_block2d_bil
John Koleszar's avatar
John Koleszar committed
652
653
(
    unsigned char *src_ptr,
Johann's avatar
Johann committed
654
655
    unsigned char *dst_ptr,
    unsigned int   src_pitch,
John Koleszar's avatar
John Koleszar committed
656
    unsigned int   dst_pitch,
Johann's avatar
Johann committed
657
658
    const short   *HFilter,
    const short   *VFilter,
John Koleszar's avatar
John Koleszar committed
659
660
661
662
663
    int            Width,
    int            Height
)
{

Johann's avatar
Johann committed
664
    unsigned short FData[17*16];    /* Temp data buffer used in filtering */
John Koleszar's avatar
John Koleszar committed
665

666
    /* First filter 1-D horizontally... */
667
    filter_block2d_bil_first_pass(src_ptr, FData, src_pitch, Height + 1, Width, HFilter);
John Koleszar's avatar
John Koleszar committed
668

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

673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
#if CONFIG_DUALPRED
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
)
{
    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);
}
#endif /* CONFIG_DUALPRED */
John Koleszar's avatar
John Koleszar committed
695
696
697
698
699
700
701
702
703
704
705

void vp8_bilinear_predict4x4_c
(
    unsigned char  *src_ptr,
    int   src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    unsigned char *dst_ptr,
    int dst_pitch
)
{
Johann's avatar
Johann committed
706
707
    const short *HFilter;
    const short *VFilter;
John Koleszar's avatar
John Koleszar committed
708

Johann's avatar
Johann committed
709
710
    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
711
712
713
714
715
716
717
#if 0
    {
        int i;
        unsigned char temp1[16];
        unsigned char temp2[16];

        bilinear_predict4x4_mmx(src_ptr, src_pixels_per_line, xoffset, yoffset, temp1, 4);
718
        filter_block2d_bil(src_ptr, temp2, src_pixels_per_line, 4, HFilter, VFilter, 4, 4);
John Koleszar's avatar
John Koleszar committed
719
720
721
722
723
724

        for (i = 0; i < 16; i++)
        {
            if (temp1[i] != temp2[i])
            {
                bilinear_predict4x4_mmx(src_ptr, src_pixels_per_line, xoffset, yoffset, temp1, 4);
725
                filter_block2d_bil(src_ptr, temp2, src_pixels_per_line, 4, HFilter, VFilter, 4, 4);
John Koleszar's avatar
John Koleszar committed
726
727
728
729
            }
        }
    }
#endif
730
    filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 4, 4);
John Koleszar's avatar
John Koleszar committed
731
732
733
734
735
736
737
738
739
740
741
742
743

}

void vp8_bilinear_predict8x8_c
(
    unsigned char  *src_ptr,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    unsigned char *dst_ptr,
    int  dst_pitch
)
{
Johann's avatar
Johann committed
744
745
    const short *HFilter;
    const short *VFilter;
John Koleszar's avatar
John Koleszar committed
746

Johann's avatar
Johann committed
747
748
    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
749

750
    filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 8);
John Koleszar's avatar
John Koleszar committed
751
752
753

}

754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
#if CONFIG_DUALPRED
void vp8_bilinear_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;

    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];

    filter_block2d_bil_avg(src_ptr, dst_ptr, src_pixels_per_line,
                           dst_pitch, HFilter, VFilter, 8, 8);
}
#endif /* CONFIG_DUALPRED */

John Koleszar's avatar
John Koleszar committed
776
777
778
779
780
781
782
783
784
785
void vp8_bilinear_predict8x4_c
(
    unsigned char  *src_ptr,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    unsigned char *dst_ptr,
    int  dst_pitch
)
{
Johann's avatar
Johann committed
786
787
    const short *HFilter;
    const short *VFilter;
John Koleszar's avatar
John Koleszar committed
788

Johann's avatar
Johann committed
789
790
    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
791

792
    filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 4);
John Koleszar's avatar
John Koleszar committed
793
794
795
796
797
798
799
800
801
802
803
804
805

}

void vp8_bilinear_predict16x16_c
(
    unsigned char  *src_ptr,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    unsigned char *dst_ptr,
    int  dst_pitch
)
{
Johann's avatar
Johann committed
806
807
    const short *HFilter;
    const short *VFilter;
John Koleszar's avatar
John Koleszar committed
808

Johann's avatar
Johann committed
809
810
    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];
John Koleszar's avatar
John Koleszar committed
811

812
    filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 16, 16);
John Koleszar's avatar
John Koleszar committed
813
}
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835

#if CONFIG_DUALPRED
void vp8_bilinear_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;

    HFilter = vp8_bilinear_filters[xoffset];
    VFilter = vp8_bilinear_filters[yoffset];

    filter_block2d_bil_avg(src_ptr, dst_ptr, src_pixels_per_line,
                           dst_pitch, HFilter, VFilter, 16, 16);
}
#endif /* CONFIG_DUALPRED */