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