Initial WebM release
[platform/upstream/libvpx.git] / vp8 / common / filter_c.c
1 /*
2  *  Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license and patent
5  *  grant that can be found in the LICENSE file in the root of the source
6  *  tree. All contributing project authors may be found in the AUTHORS
7  *  file in the root of the source tree.
8  */
9
10
11 #include <stdlib.h>
12
13 #define BLOCK_HEIGHT_WIDTH 4
14 #define VP8_FILTER_WEIGHT 128
15 #define VP8_FILTER_SHIFT  7
16
17
18 static const int bilinear_filters[8][2] =
19 {
20     { 128,   0 },
21     { 112,  16 },
22     {  96,  32 },
23     {  80,  48 },
24     {  64,  64 },
25     {  48,  80 },
26     {  32,  96 },
27     {  16, 112 }
28 };
29
30
31 static const short sub_pel_filters[8][6] =
32 {
33
34     { 0,  0,  128,    0,   0,  0 },         // note that 1/8 pel positions are just as per alpha -0.5 bicubic
35     { 0, -6,  123,   12,  -1,  0 },
36     { 2, -11, 108,   36,  -8,  1 },         // New 1/4 pel 6 tap filter
37     { 0, -9,   93,   50,  -6,  0 },
38     { 3, -16,  77,   77, -16,  3 },         // New 1/2 pel 6 tap filter
39     { 0, -6,   50,   93,  -9,  0 },
40     { 1, -8,   36,  108, -11,  2 },         // New 1/4 pel 6 tap filter
41     { 0, -1,   12,  123,  -6,  0 },
42
43
44
45 };
46
47 void vp8_filter_block2d_first_pass
48 (
49     unsigned char *src_ptr,
50     int *output_ptr,
51     unsigned int src_pixels_per_line,
52     unsigned int pixel_step,
53     unsigned int output_height,
54     unsigned int output_width,
55     const short *vp8_filter
56 )
57 {
58     unsigned int i, j;
59     int  Temp;
60
61     for (i = 0; i < output_height; i++)
62     {
63         for (j = 0; j < output_width; j++)
64         {
65             Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
66                    ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
67                    ((int)src_ptr[0]                 * vp8_filter[2]) +
68                    ((int)src_ptr[pixel_step]         * vp8_filter[3]) +
69                    ((int)src_ptr[2*pixel_step]       * vp8_filter[4]) +
70                    ((int)src_ptr[3*pixel_step]       * vp8_filter[5]) +
71                    (VP8_FILTER_WEIGHT >> 1);      // Rounding
72
73             // Normalize back to 0-255
74             Temp = Temp >> VP8_FILTER_SHIFT;
75
76             if (Temp < 0)
77                 Temp = 0;
78             else if (Temp > 255)
79                 Temp = 255;
80
81             output_ptr[j] = Temp;
82             src_ptr++;
83         }
84
85         // Next row...
86         src_ptr    += src_pixels_per_line - output_width;
87         output_ptr += output_width;
88     }
89 }
90
91 void vp8_filter_block2d_second_pass
92 (
93     int *src_ptr,
94     unsigned char *output_ptr,
95     int output_pitch,
96     unsigned int src_pixels_per_line,
97     unsigned int pixel_step,
98     unsigned int output_height,
99     unsigned int output_width,
100     const short *vp8_filter
101 )
102 {
103     unsigned int i, j;
104     int  Temp;
105
106     for (i = 0; i < output_height; i++)
107     {
108         for (j = 0; j < output_width; j++)
109         {
110             // Apply filter
111             Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
112                    ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
113                    ((int)src_ptr[0]                 * vp8_filter[2]) +
114                    ((int)src_ptr[pixel_step]         * vp8_filter[3]) +
115                    ((int)src_ptr[2*pixel_step]       * vp8_filter[4]) +
116                    ((int)src_ptr[3*pixel_step]       * vp8_filter[5]) +
117                    (VP8_FILTER_WEIGHT >> 1);   // Rounding
118
119             // Normalize back to 0-255
120             Temp = Temp >> VP8_FILTER_SHIFT;
121
122             if (Temp < 0)
123                 Temp = 0;
124             else if (Temp > 255)
125                 Temp = 255;
126
127             output_ptr[j] = (unsigned char)Temp;
128             src_ptr++;
129         }
130
131         // Start next row
132         src_ptr    += src_pixels_per_line - output_width;
133         output_ptr += output_pitch;
134     }
135 }
136
137
138 void vp8_filter_block2d
139 (
140     unsigned char  *src_ptr,
141     unsigned char  *output_ptr,
142     unsigned int src_pixels_per_line,
143     int output_pitch,
144     const short  *HFilter,
145     const short  *VFilter
146 )
147 {
148     int FData[9*4]; // Temp data bufffer used in filtering
149
150     // First filter 1-D horizontally...
151     vp8_filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 9, 4, HFilter);
152
153     // then filter verticaly...
154     vp8_filter_block2d_second_pass(FData + 8, output_ptr, output_pitch, 4, 4, 4, 4, VFilter);
155 }
156
157
158 void vp8_block_variation_c
159 (
160     unsigned char  *src_ptr,
161     int   src_pixels_per_line,
162     int *HVar,
163     int *VVar
164 )
165 {
166     int i, j;
167     unsigned char *Ptr = src_ptr;
168
169     for (i = 0; i < 4; i++)
170     {
171         for (j = 0; j < 4; j++)
172         {
173             *HVar += abs((int)Ptr[j] - (int)Ptr[j+1]);
174             *VVar += abs((int)Ptr[j] - (int)Ptr[j+src_pixels_per_line]);
175         }
176
177         Ptr += src_pixels_per_line;
178     }
179 }
180
181
182
183
184 void vp8_sixtap_predict_c
185 (
186     unsigned char  *src_ptr,
187     int   src_pixels_per_line,
188     int  xoffset,
189     int  yoffset,
190     unsigned char *dst_ptr,
191     int dst_pitch
192 )
193 {
194     const short  *HFilter;
195     const short  *VFilter;
196
197     HFilter = sub_pel_filters[xoffset];   // 6 tap
198     VFilter = sub_pel_filters[yoffset];   // 6 tap
199
200     vp8_filter_block2d(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter);
201 }
202 void vp8_sixtap_predict8x8_c
203 (
204     unsigned char  *src_ptr,
205     int  src_pixels_per_line,
206     int  xoffset,
207     int  yoffset,
208     unsigned char *dst_ptr,
209     int  dst_pitch
210 )
211 {
212     const short  *HFilter;
213     const short  *VFilter;
214     int FData[13*16];   // Temp data bufffer used in filtering
215
216     HFilter = sub_pel_filters[xoffset];   // 6 tap
217     VFilter = sub_pel_filters[yoffset];   // 6 tap
218
219     // First filter 1-D horizontally...
220     vp8_filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 13, 8, HFilter);
221
222
223     // then filter verticaly...
224     vp8_filter_block2d_second_pass(FData + 16, dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
225
226 }
227
228 void vp8_sixtap_predict8x4_c
229 (
230     unsigned char  *src_ptr,
231     int  src_pixels_per_line,
232     int  xoffset,
233     int  yoffset,
234     unsigned char *dst_ptr,
235     int  dst_pitch
236 )
237 {
238     const short  *HFilter;
239     const short  *VFilter;
240     int FData[13*16];   // Temp data bufffer used in filtering
241
242     HFilter = sub_pel_filters[xoffset];   // 6 tap
243     VFilter = sub_pel_filters[yoffset];   // 6 tap
244
245     // First filter 1-D horizontally...
246     vp8_filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 9, 8, HFilter);
247
248
249     // then filter verticaly...
250     vp8_filter_block2d_second_pass(FData + 16, dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
251
252 }
253
254 void vp8_sixtap_predict16x16_c
255 (
256     unsigned char  *src_ptr,
257     int  src_pixels_per_line,
258     int  xoffset,
259     int  yoffset,
260     unsigned char *dst_ptr,
261     int  dst_pitch
262 )
263 {
264     const short  *HFilter;
265     const short  *VFilter;
266     int FData[21*24];   // Temp data bufffer used in filtering
267
268
269     HFilter = sub_pel_filters[xoffset];   // 6 tap
270     VFilter = sub_pel_filters[yoffset];   // 6 tap
271
272     // First filter 1-D horizontally...
273     vp8_filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 21, 16, HFilter);
274
275     // then filter verticaly...
276     vp8_filter_block2d_second_pass(FData + 32, dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
277
278 }
279
280
281 /****************************************************************************
282  *
283  *  ROUTINE       : filter_block2d_bil_first_pass
284  *
285  *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
286  *                  UINT32 src_pixels_per_line : Stride of input block.
287  *                  UINT32 pixel_step        : Offset between filter input samples (see notes).
288  *                  UINT32 output_height     : Input block height.
289  *                  UINT32 output_width      : Input block width.
290  *                  INT32  *vp8_filter          : Array of 2 bi-linear filter taps.
291  *
292  *  OUTPUTS       : INT32 *output_ptr        : Pointer to filtered block.
293  *
294  *  RETURNS       : void
295  *
296  *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block in
297  *                  either horizontal or vertical direction to produce the
298  *                  filtered output block. Used to implement first-pass
299  *                  of 2-D separable filter.
300  *
301  *  SPECIAL NOTES : Produces INT32 output to retain precision for next pass.
302  *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
303  *                  pixel_step defines whether the filter is applied
304  *                  horizontally (pixel_step=1) or vertically (pixel_step=stride).
305  *                  It defines the offset required to move from one input
306  *                  to the next.
307  *
308  ****************************************************************************/
309 void vp8_filter_block2d_bil_first_pass
310 (
311     unsigned char *src_ptr,
312     unsigned short *output_ptr,
313     unsigned int src_pixels_per_line,
314     int pixel_step,
315     unsigned int output_height,
316     unsigned int output_width,
317     const int *vp8_filter
318 )
319 {
320     unsigned int i, j;
321
322     for (i = 0; i < output_height; i++)
323     {
324         for (j = 0; j < output_width; j++)
325         {
326             // Apply bilinear filter
327             output_ptr[j] = (((int)src_ptr[0]          * vp8_filter[0]) +
328                              ((int)src_ptr[pixel_step] * vp8_filter[1]) +
329                              (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
330             src_ptr++;
331         }
332
333         // Next row...
334         src_ptr    += src_pixels_per_line - output_width;
335         output_ptr += output_width;
336     }
337 }
338
339 /****************************************************************************
340  *
341  *  ROUTINE       : filter_block2d_bil_second_pass
342  *
343  *  INPUTS        : INT32  *src_ptr          : Pointer to source block.
344  *                  UINT32 src_pixels_per_line : Stride of input block.
345  *                  UINT32 pixel_step        : Offset between filter input samples (see notes).
346  *                  UINT32 output_height     : Input block height.
347  *                  UINT32 output_width      : Input block width.
348  *                  INT32  *vp8_filter          : Array of 2 bi-linear filter taps.
349  *
350  *  OUTPUTS       : UINT16 *output_ptr       : Pointer to filtered block.
351  *
352  *  RETURNS       : void
353  *
354  *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block in
355  *                  either horizontal or vertical direction to produce the
356  *                  filtered output block. Used to implement second-pass
357  *                  of 2-D separable filter.
358  *
359  *  SPECIAL NOTES : Requires 32-bit input as produced by filter_block2d_bil_first_pass.
360  *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
361  *                  pixel_step defines whether the filter is applied
362  *                  horizontally (pixel_step=1) or vertically (pixel_step=stride).
363  *                  It defines the offset required to move from one input
364  *                  to the next.
365  *
366  ****************************************************************************/
367 void vp8_filter_block2d_bil_second_pass
368 (
369     unsigned short *src_ptr,
370     unsigned char  *output_ptr,
371     int output_pitch,
372     unsigned int  src_pixels_per_line,
373     unsigned int  pixel_step,
374     unsigned int  output_height,
375     unsigned int  output_width,
376     const int *vp8_filter
377 )
378 {
379     unsigned int  i, j;
380     int  Temp;
381
382     for (i = 0; i < output_height; i++)
383     {
384         for (j = 0; j < output_width; j++)
385         {
386             // Apply filter
387             Temp = ((int)src_ptr[0]         * vp8_filter[0]) +
388                    ((int)src_ptr[pixel_step] * vp8_filter[1]) +
389                    (VP8_FILTER_WEIGHT / 2);
390             output_ptr[j] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
391             src_ptr++;
392         }
393
394         // Next row...
395         src_ptr    += src_pixels_per_line - output_width;
396         output_ptr += output_pitch;
397     }
398 }
399
400
401 /****************************************************************************
402  *
403  *  ROUTINE       : filter_block2d_bil
404  *
405  *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
406  *                  UINT32 src_pixels_per_line : Stride of input block.
407  *                  INT32  *HFilter         : Array of 2 horizontal filter taps.
408  *                  INT32  *VFilter         : Array of 2 vertical filter taps.
409  *
410  *  OUTPUTS       : UINT16 *output_ptr       : Pointer to filtered block.
411  *
412  *  RETURNS       : void
413  *
414  *  FUNCTION      : 2-D filters an input block by applying a 2-tap
415  *                  bi-linear filter horizontally followed by a 2-tap
416  *                  bi-linear filter vertically on the result.
417  *
418  *  SPECIAL NOTES : The largest block size can be handled here is 16x16
419  *
420  ****************************************************************************/
421 void vp8_filter_block2d_bil
422 (
423     unsigned char *src_ptr,
424     unsigned char *output_ptr,
425     unsigned int   src_pixels_per_line,
426     unsigned int   dst_pitch,
427     const int      *HFilter,
428     const int      *VFilter,
429     int            Width,
430     int            Height
431 )
432 {
433
434     unsigned short FData[17*16];    // Temp data bufffer used in filtering
435
436     // First filter 1-D horizontally...
437     vp8_filter_block2d_bil_first_pass(src_ptr, FData, src_pixels_per_line, 1, Height + 1, Width, HFilter);
438
439     // then 1-D vertically...
440     vp8_filter_block2d_bil_second_pass(FData, output_ptr, dst_pitch, Width, Width, Height, Width, VFilter);
441 }
442
443
444 void vp8_bilinear_predict4x4_c
445 (
446     unsigned char  *src_ptr,
447     int   src_pixels_per_line,
448     int  xoffset,
449     int  yoffset,
450     unsigned char *dst_ptr,
451     int dst_pitch
452 )
453 {
454     const int  *HFilter;
455     const int  *VFilter;
456
457     HFilter = bilinear_filters[xoffset];
458     VFilter = bilinear_filters[yoffset];
459 #if 0
460     {
461         int i;
462         unsigned char temp1[16];
463         unsigned char temp2[16];
464
465         bilinear_predict4x4_mmx(src_ptr, src_pixels_per_line, xoffset, yoffset, temp1, 4);
466         vp8_filter_block2d_bil(src_ptr, temp2, src_pixels_per_line, 4, HFilter, VFilter, 4, 4);
467
468         for (i = 0; i < 16; i++)
469         {
470             if (temp1[i] != temp2[i])
471             {
472                 bilinear_predict4x4_mmx(src_ptr, src_pixels_per_line, xoffset, yoffset, temp1, 4);
473                 vp8_filter_block2d_bil(src_ptr, temp2, src_pixels_per_line, 4, HFilter, VFilter, 4, 4);
474             }
475         }
476     }
477 #endif
478     vp8_filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 4, 4);
479
480 }
481
482 void vp8_bilinear_predict8x8_c
483 (
484     unsigned char  *src_ptr,
485     int  src_pixels_per_line,
486     int  xoffset,
487     int  yoffset,
488     unsigned char *dst_ptr,
489     int  dst_pitch
490 )
491 {
492     const int  *HFilter;
493     const int  *VFilter;
494
495     HFilter = bilinear_filters[xoffset];
496     VFilter = bilinear_filters[yoffset];
497
498     vp8_filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 8);
499
500 }
501
502 void vp8_bilinear_predict8x4_c
503 (
504     unsigned char  *src_ptr,
505     int  src_pixels_per_line,
506     int  xoffset,
507     int  yoffset,
508     unsigned char *dst_ptr,
509     int  dst_pitch
510 )
511 {
512     const int  *HFilter;
513     const int  *VFilter;
514
515     HFilter = bilinear_filters[xoffset];
516     VFilter = bilinear_filters[yoffset];
517
518     vp8_filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 4);
519
520 }
521
522 void vp8_bilinear_predict16x16_c
523 (
524     unsigned char  *src_ptr,
525     int  src_pixels_per_line,
526     int  xoffset,
527     int  yoffset,
528     unsigned char *dst_ptr,
529     int  dst_pitch
530 )
531 {
532     const int  *HFilter;
533     const int  *VFilter;
534
535     HFilter = bilinear_filters[xoffset];
536     VFilter = bilinear_filters[yoffset];
537
538     vp8_filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 16, 16);
539 }