Home | History | Annotate | Download | only in arm
      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 "vpx_ports/config.h"
     13 #include <math.h>
     14 #include "subpixel.h"
     15 #include "vpx_ports/mem.h"
     16 
     17 #define BLOCK_HEIGHT_WIDTH 4
     18 #define VP8_FILTER_WEIGHT 128
     19 #define VP8_FILTER_SHIFT  7
     20 
     21 DECLARE_ALIGNED(16, static const short, sub_pel_filters[8][6]) =
     22 {
     23     { 0,  0,  128,    0,   0,  0 },         /* note that 1/8 pel positions are just as per alpha -0.5 bicubic */
     24     { 0, -6,  123,   12,  -1,  0 },
     25     { 2, -11, 108,   36,  -8,  1 },         /* New 1/4 pel 6 tap filter */
     26     { 0, -9,   93,   50,  -6,  0 },
     27     { 3, -16,  77,   77, -16,  3 },         /* New 1/2 pel 6 tap filter */
     28     { 0, -6,   50,   93,  -9,  0 },
     29     { 1, -8,   36,  108, -11,  2 },         /* New 1/4 pel 6 tap filter */
     30     { 0, -1,   12,  123,  -6,  0 },
     31 };
     32 
     33 
     34 extern void vp8_filter_block2d_first_pass_armv6
     35 (
     36     unsigned char *src_ptr,
     37     short         *output_ptr,
     38     unsigned int src_pixels_per_line,
     39     unsigned int output_width,
     40     unsigned int output_height,
     41     const short *vp8_filter
     42 );
     43 
     44 extern void vp8_filter_block2d_second_pass_armv6
     45 (
     46     short         *src_ptr,
     47     unsigned char *output_ptr,
     48     unsigned int output_pitch,
     49     unsigned int cnt,
     50     const short *vp8_filter
     51 );
     52 
     53 extern void vp8_filter4_block2d_second_pass_armv6
     54 (
     55     short         *src_ptr,
     56     unsigned char *output_ptr,
     57     unsigned int output_pitch,
     58     unsigned int cnt,
     59     const short *vp8_filter
     60 );
     61 
     62 extern void vp8_filter_block2d_first_pass_only_armv6
     63 (
     64     unsigned char *src_ptr,
     65     unsigned char *output_ptr,
     66     unsigned int src_pixels_per_line,
     67     unsigned int cnt,
     68     unsigned int output_pitch,
     69     const short *vp8_filter
     70 );
     71 
     72 
     73 extern void vp8_filter_block2d_second_pass_only_armv6
     74 (
     75     unsigned char *src_ptr,
     76     unsigned char *output_ptr,
     77     unsigned int src_pixels_per_line,
     78     unsigned int cnt,
     79     unsigned int output_pitch,
     80     const short *vp8_filter
     81 );
     82 
     83 #if HAVE_ARMV6
     84 void vp8_sixtap_predict_armv6
     85 (
     86     unsigned char  *src_ptr,
     87     int  src_pixels_per_line,
     88     int  xoffset,
     89     int  yoffset,
     90     unsigned char *dst_ptr,
     91     int  dst_pitch
     92 )
     93 {
     94     const short  *HFilter;
     95     const short  *VFilter;
     96     DECLARE_ALIGNED_ARRAY(4, short, FData, 12*4); /* Temp data bufffer used in filtering */
     97 
     98 
     99     HFilter = sub_pel_filters[xoffset];   /* 6 tap */
    100     VFilter = sub_pel_filters[yoffset];       /* 6 tap */
    101 
    102     /* Vfilter is null. First pass only */
    103     if (xoffset && !yoffset)
    104     {
    105         /*vp8_filter_block2d_first_pass_armv6 ( src_ptr, FData+2, src_pixels_per_line, 4, 4, HFilter );
    106         vp8_filter_block2d_second_pass_armv6 ( FData+2, dst_ptr, dst_pitch, 4, VFilter );*/
    107 
    108         vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 4, dst_pitch, HFilter);
    109     }
    110     /* Hfilter is null. Second pass only */
    111     else if (!xoffset && yoffset)
    112     {
    113         vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 4, dst_pitch, VFilter);
    114     }
    115     else
    116     {
    117         /* Vfilter is a 4 tap filter */
    118         if (yoffset & 0x1)
    119         {
    120             vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 4, 7, HFilter);
    121             vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 4, VFilter);
    122         }
    123         /* Vfilter is 6 tap filter */
    124         else
    125         {
    126             vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 4, 9, HFilter);
    127             vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 4, VFilter);
    128         }
    129     }
    130 }
    131 
    132 #if 0
    133 void vp8_sixtap_predict8x4_armv6
    134 (
    135     unsigned char  *src_ptr,
    136     int  src_pixels_per_line,
    137     int  xoffset,
    138     int  yoffset,
    139     unsigned char *dst_ptr,
    140     int  dst_pitch
    141 )
    142 {
    143     const short  *HFilter;
    144     const short  *VFilter;
    145     DECLARE_ALIGNED_ARRAY(4, short, FData, 16*8); /* Temp data bufffer used in filtering */
    146 
    147     HFilter = sub_pel_filters[xoffset];   /* 6 tap */
    148     VFilter = sub_pel_filters[yoffset];       /* 6 tap */
    149 
    150 
    151     /*if (xoffset && !yoffset)
    152     {
    153         vp8_filter_block2d_first_pass_only_armv6 (  src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, HFilter );
    154     }*/
    155     /* Hfilter is null. Second pass only */
    156     /*else if (!xoffset && yoffset)
    157     {
    158         vp8_filter_block2d_second_pass_only_armv6 ( src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, VFilter );
    159     }
    160     else
    161     {
    162         if (yoffset & 0x1)
    163             vp8_filter_block2d_first_pass_armv6 ( src_ptr-src_pixels_per_line, FData+1, src_pixels_per_line, 8, 7, HFilter );
    164         else*/
    165 
    166         vp8_filter_block2d_first_pass_armv6 ( src_ptr-(2*src_pixels_per_line), FData, src_pixels_per_line, 8, 9, HFilter );
    167 
    168         vp8_filter_block2d_second_pass_armv6 ( FData+2, dst_ptr, dst_pitch, 4, 8, VFilter );
    169     /*}*/
    170 }
    171 #endif
    172 
    173 void vp8_sixtap_predict8x8_armv6
    174 (
    175     unsigned char  *src_ptr,
    176     int  src_pixels_per_line,
    177     int  xoffset,
    178     int  yoffset,
    179     unsigned char *dst_ptr,
    180     int  dst_pitch
    181 )
    182 {
    183     const short  *HFilter;
    184     const short  *VFilter;
    185     DECLARE_ALIGNED_ARRAY(4, short, FData, 16*8); /* Temp data bufffer used in filtering */
    186 
    187     HFilter = sub_pel_filters[xoffset];   /* 6 tap */
    188     VFilter = sub_pel_filters[yoffset];       /* 6 tap */
    189 
    190     if (xoffset && !yoffset)
    191     {
    192         vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, HFilter);
    193     }
    194     /* Hfilter is null. Second pass only */
    195     else if (!xoffset && yoffset)
    196     {
    197         vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, VFilter);
    198     }
    199     else
    200     {
    201         if (yoffset & 0x1)
    202         {
    203             vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 8, 11, HFilter);
    204             vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 8, VFilter);
    205         }
    206         else
    207         {
    208             vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 8, 13, HFilter);
    209             vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 8, VFilter);
    210         }
    211     }
    212 }
    213 
    214 
    215 void vp8_sixtap_predict16x16_armv6
    216 (
    217     unsigned char  *src_ptr,
    218     int  src_pixels_per_line,
    219     int  xoffset,
    220     int  yoffset,
    221     unsigned char *dst_ptr,
    222     int  dst_pitch
    223 )
    224 {
    225     const short  *HFilter;
    226     const short  *VFilter;
    227     DECLARE_ALIGNED_ARRAY(4, short, FData, 24*16);    /* Temp data bufffer used in filtering */
    228 
    229     HFilter = sub_pel_filters[xoffset];   /* 6 tap */
    230     VFilter = sub_pel_filters[yoffset];       /* 6 tap */
    231 
    232     if (xoffset && !yoffset)
    233     {
    234         vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 16, dst_pitch, HFilter);
    235     }
    236     /* Hfilter is null. Second pass only */
    237     else if (!xoffset && yoffset)
    238     {
    239         vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 16, dst_pitch, VFilter);
    240     }
    241     else
    242     {
    243         if (yoffset & 0x1)
    244         {
    245             vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 16, 19, HFilter);
    246             vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 16, VFilter);
    247         }
    248         else
    249         {
    250             vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 16, 21, HFilter);
    251             vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 16, VFilter);
    252         }
    253     }
    254 
    255 }
    256 #endif
    257