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_filter_block2d_first_pass_only_armv6
     54 (
     55     unsigned char *src_ptr,
     56     unsigned char *output_ptr,
     57     unsigned int src_pixels_per_line,
     58     unsigned int cnt,
     59     unsigned int output_pitch,
     60     const short *vp8_filter
     61 );
     62 
     63 
     64 extern void vp8_filter_block2d_second_pass_only_armv6
     65 (
     66     unsigned char *src_ptr,
     67     unsigned char *output_ptr,
     68     unsigned int src_pixels_per_line,
     69     unsigned int cnt,
     70     unsigned int output_pitch,
     71     const short *vp8_filter
     72 );
     73 
     74 #if HAVE_ARMV6
     75 void vp8_sixtap_predict_armv6
     76 (
     77     unsigned char  *src_ptr,
     78     int  src_pixels_per_line,
     79     int  xoffset,
     80     int  yoffset,
     81     unsigned char *dst_ptr,
     82     int  dst_pitch
     83 )
     84 {
     85     const short  *HFilter;
     86     const short  *VFilter;
     87     DECLARE_ALIGNED_ARRAY(4, short, FData, 12*4); // Temp data bufffer used in filtering
     88 
     89 
     90     HFilter = sub_pel_filters[xoffset];   // 6 tap
     91     VFilter = sub_pel_filters[yoffset];       // 6 tap
     92 
     93     // Vfilter is null. First pass only
     94     if (xoffset && !yoffset)
     95     {
     96         //vp8_filter_block2d_first_pass_armv6 ( src_ptr, FData+2, src_pixels_per_line, 4, 4, HFilter );
     97         //vp8_filter_block2d_second_pass_armv6 ( FData+2, dst_ptr, dst_pitch, 4, VFilter );
     98 
     99         vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 4, dst_pitch, HFilter);
    100     }
    101     // Hfilter is null. Second pass only
    102     else if (!xoffset && yoffset)
    103     {
    104         vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 4, dst_pitch, VFilter);
    105     }
    106     else
    107     {
    108         // Vfilter is a 4 tap filter
    109         if (yoffset & 0x1)
    110             vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 4, 7, HFilter);
    111         // Vfilter is 6 tap filter
    112         else
    113             vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 4, 9, HFilter);
    114 
    115         vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 4, VFilter);
    116     }
    117 }
    118 
    119 /*
    120 void vp8_sixtap_predict8x4_armv6
    121 (
    122     unsigned char  *src_ptr,
    123     int  src_pixels_per_line,
    124     int  xoffset,
    125     int  yoffset,
    126     unsigned char *dst_ptr,
    127     int  dst_pitch
    128 )
    129 {
    130     const short  *HFilter;
    131     const short  *VFilter;
    132     DECLARE_ALIGNED_ARRAY(4, short, FData, 16*8); // Temp data bufffer used in filtering
    133 
    134     HFilter = sub_pel_filters[xoffset];   // 6 tap
    135     VFilter = sub_pel_filters[yoffset];       // 6 tap
    136 
    137 
    138 //  if (xoffset && !yoffset)
    139 //  {
    140 //      vp8_filter_block2d_first_pass_only_armv6 (  src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, HFilter );
    141 //  }
    142     // Hfilter is null. Second pass only
    143 //  else if (!xoffset && yoffset)
    144 //  {
    145 //      vp8_filter_block2d_second_pass_only_armv6 ( src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, VFilter );
    146 //  }
    147 //  else
    148 //  {
    149 //      if (yoffset & 0x1)
    150     //      vp8_filter_block2d_first_pass_armv6 ( src_ptr-src_pixels_per_line, FData+1, src_pixels_per_line, 8, 7, HFilter );
    151     //  else
    152 
    153         vp8_filter_block2d_first_pass_armv6 ( src_ptr-(2*src_pixels_per_line), FData, src_pixels_per_line, 8, 9, HFilter );
    154 
    155         vp8_filter_block2d_second_pass_armv6 ( FData+2, dst_ptr, dst_pitch, 4, 8, VFilter );
    156 //  }
    157 }
    158 */
    159 
    160 void vp8_sixtap_predict8x8_armv6
    161 (
    162     unsigned char  *src_ptr,
    163     int  src_pixels_per_line,
    164     int  xoffset,
    165     int  yoffset,
    166     unsigned char *dst_ptr,
    167     int  dst_pitch
    168 )
    169 {
    170     const short  *HFilter;
    171     const short  *VFilter;
    172     DECLARE_ALIGNED_ARRAY(4, short, FData, 16*8); // Temp data bufffer used in filtering
    173 
    174     HFilter = sub_pel_filters[xoffset];   // 6 tap
    175     VFilter = sub_pel_filters[yoffset];       // 6 tap
    176 
    177     if (xoffset && !yoffset)
    178     {
    179         vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, HFilter);
    180     }
    181     // Hfilter is null. Second pass only
    182     else if (!xoffset && yoffset)
    183     {
    184         vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, VFilter);
    185     }
    186     else
    187     {
    188         if (yoffset & 0x1)
    189             vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 8, 11, HFilter);
    190         else
    191             vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 8, 13, HFilter);
    192 
    193         vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 8, VFilter);
    194     }
    195 }
    196 
    197 
    198 void vp8_sixtap_predict16x16_armv6
    199 (
    200     unsigned char  *src_ptr,
    201     int  src_pixels_per_line,
    202     int  xoffset,
    203     int  yoffset,
    204     unsigned char *dst_ptr,
    205     int  dst_pitch
    206 )
    207 {
    208     const short  *HFilter;
    209     const short  *VFilter;
    210     DECLARE_ALIGNED_ARRAY(4, short, FData, 24*16);    // Temp data bufffer used in filtering
    211 
    212     HFilter = sub_pel_filters[xoffset];   // 6 tap
    213     VFilter = sub_pel_filters[yoffset];       // 6 tap
    214 
    215     if (xoffset && !yoffset)
    216     {
    217         vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 16, dst_pitch, HFilter);
    218     }
    219     // Hfilter is null. Second pass only
    220     else if (!xoffset && yoffset)
    221     {
    222         vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 16, dst_pitch, VFilter);
    223     }
    224     else
    225     {
    226         if (yoffset & 0x1)
    227             vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 16, 19, HFilter);
    228         else
    229             vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 16, 21, HFilter);
    230 
    231         vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 16, VFilter);
    232     }
    233 
    234 }
    235 #endif
    236