Home | History | Annotate | Download | only in neon
      1 /*
      2  *  Copyright (c) 2014 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 #include <arm_neon.h>
     12 #include <string.h>
     13 
     14 #include "./vpx_config.h"
     15 #include "./vp8_rtcd.h"
     16 #include "vpx_dsp/arm/mem_neon.h"
     17 
     18 static const uint8_t bifilter4_coeff[8][2] = { { 128, 0 }, { 112, 16 },
     19                                                { 96, 32 }, { 80, 48 },
     20                                                { 64, 64 }, { 48, 80 },
     21                                                { 32, 96 }, { 16, 112 } };
     22 
     23 static INLINE uint8x8_t load_and_shift(const unsigned char *a) {
     24   return vreinterpret_u8_u64(vshl_n_u64(vreinterpret_u64_u8(vld1_u8(a)), 32));
     25 }
     26 
     27 void vp8_bilinear_predict4x4_neon(unsigned char *src_ptr,
     28                                   int src_pixels_per_line, int xoffset,
     29                                   int yoffset, unsigned char *dst_ptr,
     30                                   int dst_pitch) {
     31   uint8x8_t e0, e1, e2;
     32 
     33   if (xoffset == 0) {  // skip_1stpass_filter
     34     uint8x8_t a0, a1, a2, a3, a4;
     35 
     36     a0 = load_and_shift(src_ptr);
     37     src_ptr += src_pixels_per_line;
     38     a1 = vld1_u8(src_ptr);
     39     src_ptr += src_pixels_per_line;
     40     a2 = load_and_shift(src_ptr);
     41     src_ptr += src_pixels_per_line;
     42     a3 = vld1_u8(src_ptr);
     43     src_ptr += src_pixels_per_line;
     44     a4 = vld1_u8(src_ptr);
     45 
     46     e0 = vext_u8(a0, a1, 4);
     47     e1 = vext_u8(a2, a3, 4);
     48     e2 = a4;
     49   } else {
     50     uint8x8_t a0, a1, a2, a3, a4, b4;
     51     uint8x16_t a01, a23;
     52     uint8x16_t b01, b23;
     53     uint32x2x2_t c0, c1, c2, c3;
     54     uint16x8_t d0, d1, d2;
     55     const uint8x8_t filter0 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
     56     const uint8x8_t filter1 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
     57 
     58     a0 = vld1_u8(src_ptr);
     59     src_ptr += src_pixels_per_line;
     60     a1 = vld1_u8(src_ptr);
     61     src_ptr += src_pixels_per_line;
     62     a2 = vld1_u8(src_ptr);
     63     src_ptr += src_pixels_per_line;
     64     a3 = vld1_u8(src_ptr);
     65     src_ptr += src_pixels_per_line;
     66     a4 = vld1_u8(src_ptr);
     67 
     68     a01 = vcombine_u8(a0, a1);
     69     a23 = vcombine_u8(a2, a3);
     70 
     71     b01 = vreinterpretq_u8_u64(vshrq_n_u64(vreinterpretq_u64_u8(a01), 8));
     72     b23 = vreinterpretq_u8_u64(vshrq_n_u64(vreinterpretq_u64_u8(a23), 8));
     73     b4 = vreinterpret_u8_u64(vshr_n_u64(vreinterpret_u64_u8(a4), 8));
     74 
     75     c0 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(a01)),
     76                   vreinterpret_u32_u8(vget_high_u8(a01)));
     77     c1 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(a23)),
     78                   vreinterpret_u32_u8(vget_high_u8(a23)));
     79     c2 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(b01)),
     80                   vreinterpret_u32_u8(vget_high_u8(b01)));
     81     c3 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(b23)),
     82                   vreinterpret_u32_u8(vget_high_u8(b23)));
     83 
     84     d0 = vmull_u8(vreinterpret_u8_u32(c0.val[0]), filter0);
     85     d1 = vmull_u8(vreinterpret_u8_u32(c1.val[0]), filter0);
     86     d2 = vmull_u8(a4, filter0);
     87 
     88     d0 = vmlal_u8(d0, vreinterpret_u8_u32(c2.val[0]), filter1);
     89     d1 = vmlal_u8(d1, vreinterpret_u8_u32(c3.val[0]), filter1);
     90     d2 = vmlal_u8(d2, b4, filter1);
     91 
     92     e0 = vqrshrn_n_u16(d0, 7);
     93     e1 = vqrshrn_n_u16(d1, 7);
     94     e2 = vqrshrn_n_u16(d2, 7);
     95   }
     96 
     97   // secondpass_filter
     98   if (yoffset == 0) {  // skip_2ndpass_filter
     99     store_unaligned_u8q(dst_ptr, dst_pitch, vcombine_u8(e0, e1));
    100   } else {
    101     uint8x8_t f0, f1;
    102     const uint8x8_t filter0 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
    103     const uint8x8_t filter1 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
    104 
    105     uint16x8_t b0 = vmull_u8(e0, filter0);
    106     uint16x8_t b1 = vmull_u8(e1, filter0);
    107 
    108     const uint8x8_t a0 = vext_u8(e0, e1, 4);
    109     const uint8x8_t a1 = vext_u8(e1, e2, 4);
    110 
    111     b0 = vmlal_u8(b0, a0, filter1);
    112     b1 = vmlal_u8(b1, a1, filter1);
    113 
    114     f0 = vqrshrn_n_u16(b0, 7);
    115     f1 = vqrshrn_n_u16(b1, 7);
    116 
    117     store_unaligned_u8q(dst_ptr, dst_pitch, vcombine_u8(f0, f1));
    118   }
    119 }
    120 
    121 void vp8_bilinear_predict8x4_neon(unsigned char *src_ptr,
    122                                   int src_pixels_per_line, int xoffset,
    123                                   int yoffset, unsigned char *dst_ptr,
    124                                   int dst_pitch) {
    125   uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8;
    126   uint8x8_t d7u8, d9u8, d11u8, d22u8, d23u8, d24u8, d25u8, d26u8;
    127   uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8;
    128   uint16x8_t q1u16, q2u16, q3u16, q4u16;
    129   uint16x8_t q6u16, q7u16, q8u16, q9u16, q10u16;
    130 
    131   if (xoffset == 0) {  // skip_1stpass_filter
    132     d22u8 = vld1_u8(src_ptr);
    133     src_ptr += src_pixels_per_line;
    134     d23u8 = vld1_u8(src_ptr);
    135     src_ptr += src_pixels_per_line;
    136     d24u8 = vld1_u8(src_ptr);
    137     src_ptr += src_pixels_per_line;
    138     d25u8 = vld1_u8(src_ptr);
    139     src_ptr += src_pixels_per_line;
    140     d26u8 = vld1_u8(src_ptr);
    141   } else {
    142     q1u8 = vld1q_u8(src_ptr);
    143     src_ptr += src_pixels_per_line;
    144     q2u8 = vld1q_u8(src_ptr);
    145     src_ptr += src_pixels_per_line;
    146     q3u8 = vld1q_u8(src_ptr);
    147     src_ptr += src_pixels_per_line;
    148     q4u8 = vld1q_u8(src_ptr);
    149     src_ptr += src_pixels_per_line;
    150     q5u8 = vld1q_u8(src_ptr);
    151 
    152     d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
    153     d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
    154 
    155     q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
    156     q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
    157     q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
    158     q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
    159     q10u16 = vmull_u8(vget_low_u8(q5u8), d0u8);
    160 
    161     d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
    162     d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
    163     d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
    164     d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
    165     d11u8 = vext_u8(vget_low_u8(q5u8), vget_high_u8(q5u8), 1);
    166 
    167     q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
    168     q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
    169     q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
    170     q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
    171     q10u16 = vmlal_u8(q10u16, d11u8, d1u8);
    172 
    173     d22u8 = vqrshrn_n_u16(q6u16, 7);
    174     d23u8 = vqrshrn_n_u16(q7u16, 7);
    175     d24u8 = vqrshrn_n_u16(q8u16, 7);
    176     d25u8 = vqrshrn_n_u16(q9u16, 7);
    177     d26u8 = vqrshrn_n_u16(q10u16, 7);
    178   }
    179 
    180   // secondpass_filter
    181   if (yoffset == 0) {  // skip_2ndpass_filter
    182     vst1_u8((uint8_t *)dst_ptr, d22u8);
    183     dst_ptr += dst_pitch;
    184     vst1_u8((uint8_t *)dst_ptr, d23u8);
    185     dst_ptr += dst_pitch;
    186     vst1_u8((uint8_t *)dst_ptr, d24u8);
    187     dst_ptr += dst_pitch;
    188     vst1_u8((uint8_t *)dst_ptr, d25u8);
    189   } else {
    190     d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
    191     d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
    192 
    193     q1u16 = vmull_u8(d22u8, d0u8);
    194     q2u16 = vmull_u8(d23u8, d0u8);
    195     q3u16 = vmull_u8(d24u8, d0u8);
    196     q4u16 = vmull_u8(d25u8, d0u8);
    197 
    198     q1u16 = vmlal_u8(q1u16, d23u8, d1u8);
    199     q2u16 = vmlal_u8(q2u16, d24u8, d1u8);
    200     q3u16 = vmlal_u8(q3u16, d25u8, d1u8);
    201     q4u16 = vmlal_u8(q4u16, d26u8, d1u8);
    202 
    203     d2u8 = vqrshrn_n_u16(q1u16, 7);
    204     d3u8 = vqrshrn_n_u16(q2u16, 7);
    205     d4u8 = vqrshrn_n_u16(q3u16, 7);
    206     d5u8 = vqrshrn_n_u16(q4u16, 7);
    207 
    208     vst1_u8((uint8_t *)dst_ptr, d2u8);
    209     dst_ptr += dst_pitch;
    210     vst1_u8((uint8_t *)dst_ptr, d3u8);
    211     dst_ptr += dst_pitch;
    212     vst1_u8((uint8_t *)dst_ptr, d4u8);
    213     dst_ptr += dst_pitch;
    214     vst1_u8((uint8_t *)dst_ptr, d5u8);
    215   }
    216   return;
    217 }
    218 
    219 void vp8_bilinear_predict8x8_neon(unsigned char *src_ptr,
    220                                   int src_pixels_per_line, int xoffset,
    221                                   int yoffset, unsigned char *dst_ptr,
    222                                   int dst_pitch) {
    223   uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8, d8u8, d9u8, d11u8;
    224   uint8x8_t d22u8, d23u8, d24u8, d25u8, d26u8, d27u8, d28u8, d29u8, d30u8;
    225   uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8;
    226   uint16x8_t q1u16, q2u16, q3u16, q4u16, q5u16;
    227   uint16x8_t q6u16, q7u16, q8u16, q9u16, q10u16;
    228 
    229   if (xoffset == 0) {  // skip_1stpass_filter
    230     d22u8 = vld1_u8(src_ptr);
    231     src_ptr += src_pixels_per_line;
    232     d23u8 = vld1_u8(src_ptr);
    233     src_ptr += src_pixels_per_line;
    234     d24u8 = vld1_u8(src_ptr);
    235     src_ptr += src_pixels_per_line;
    236     d25u8 = vld1_u8(src_ptr);
    237     src_ptr += src_pixels_per_line;
    238     d26u8 = vld1_u8(src_ptr);
    239     src_ptr += src_pixels_per_line;
    240     d27u8 = vld1_u8(src_ptr);
    241     src_ptr += src_pixels_per_line;
    242     d28u8 = vld1_u8(src_ptr);
    243     src_ptr += src_pixels_per_line;
    244     d29u8 = vld1_u8(src_ptr);
    245     src_ptr += src_pixels_per_line;
    246     d30u8 = vld1_u8(src_ptr);
    247   } else {
    248     q1u8 = vld1q_u8(src_ptr);
    249     src_ptr += src_pixels_per_line;
    250     q2u8 = vld1q_u8(src_ptr);
    251     src_ptr += src_pixels_per_line;
    252     q3u8 = vld1q_u8(src_ptr);
    253     src_ptr += src_pixels_per_line;
    254     q4u8 = vld1q_u8(src_ptr);
    255     src_ptr += src_pixels_per_line;
    256 
    257     d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
    258     d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
    259 
    260     q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
    261     q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
    262     q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
    263     q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
    264 
    265     d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
    266     d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
    267     d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
    268     d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
    269 
    270     q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
    271     q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
    272     q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
    273     q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
    274 
    275     d22u8 = vqrshrn_n_u16(q6u16, 7);
    276     d23u8 = vqrshrn_n_u16(q7u16, 7);
    277     d24u8 = vqrshrn_n_u16(q8u16, 7);
    278     d25u8 = vqrshrn_n_u16(q9u16, 7);
    279 
    280     // first_pass filtering on the rest 5-line data
    281     q1u8 = vld1q_u8(src_ptr);
    282     src_ptr += src_pixels_per_line;
    283     q2u8 = vld1q_u8(src_ptr);
    284     src_ptr += src_pixels_per_line;
    285     q3u8 = vld1q_u8(src_ptr);
    286     src_ptr += src_pixels_per_line;
    287     q4u8 = vld1q_u8(src_ptr);
    288     src_ptr += src_pixels_per_line;
    289     q5u8 = vld1q_u8(src_ptr);
    290 
    291     q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
    292     q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
    293     q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
    294     q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
    295     q10u16 = vmull_u8(vget_low_u8(q5u8), d0u8);
    296 
    297     d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
    298     d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
    299     d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
    300     d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
    301     d11u8 = vext_u8(vget_low_u8(q5u8), vget_high_u8(q5u8), 1);
    302 
    303     q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
    304     q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
    305     q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
    306     q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
    307     q10u16 = vmlal_u8(q10u16, d11u8, d1u8);
    308 
    309     d26u8 = vqrshrn_n_u16(q6u16, 7);
    310     d27u8 = vqrshrn_n_u16(q7u16, 7);
    311     d28u8 = vqrshrn_n_u16(q8u16, 7);
    312     d29u8 = vqrshrn_n_u16(q9u16, 7);
    313     d30u8 = vqrshrn_n_u16(q10u16, 7);
    314   }
    315 
    316   // secondpass_filter
    317   if (yoffset == 0) {  // skip_2ndpass_filter
    318     vst1_u8((uint8_t *)dst_ptr, d22u8);
    319     dst_ptr += dst_pitch;
    320     vst1_u8((uint8_t *)dst_ptr, d23u8);
    321     dst_ptr += dst_pitch;
    322     vst1_u8((uint8_t *)dst_ptr, d24u8);
    323     dst_ptr += dst_pitch;
    324     vst1_u8((uint8_t *)dst_ptr, d25u8);
    325     dst_ptr += dst_pitch;
    326     vst1_u8((uint8_t *)dst_ptr, d26u8);
    327     dst_ptr += dst_pitch;
    328     vst1_u8((uint8_t *)dst_ptr, d27u8);
    329     dst_ptr += dst_pitch;
    330     vst1_u8((uint8_t *)dst_ptr, d28u8);
    331     dst_ptr += dst_pitch;
    332     vst1_u8((uint8_t *)dst_ptr, d29u8);
    333   } else {
    334     d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
    335     d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
    336 
    337     q1u16 = vmull_u8(d22u8, d0u8);
    338     q2u16 = vmull_u8(d23u8, d0u8);
    339     q3u16 = vmull_u8(d24u8, d0u8);
    340     q4u16 = vmull_u8(d25u8, d0u8);
    341     q5u16 = vmull_u8(d26u8, d0u8);
    342     q6u16 = vmull_u8(d27u8, d0u8);
    343     q7u16 = vmull_u8(d28u8, d0u8);
    344     q8u16 = vmull_u8(d29u8, d0u8);
    345 
    346     q1u16 = vmlal_u8(q1u16, d23u8, d1u8);
    347     q2u16 = vmlal_u8(q2u16, d24u8, d1u8);
    348     q3u16 = vmlal_u8(q3u16, d25u8, d1u8);
    349     q4u16 = vmlal_u8(q4u16, d26u8, d1u8);
    350     q5u16 = vmlal_u8(q5u16, d27u8, d1u8);
    351     q6u16 = vmlal_u8(q6u16, d28u8, d1u8);
    352     q7u16 = vmlal_u8(q7u16, d29u8, d1u8);
    353     q8u16 = vmlal_u8(q8u16, d30u8, d1u8);
    354 
    355     d2u8 = vqrshrn_n_u16(q1u16, 7);
    356     d3u8 = vqrshrn_n_u16(q2u16, 7);
    357     d4u8 = vqrshrn_n_u16(q3u16, 7);
    358     d5u8 = vqrshrn_n_u16(q4u16, 7);
    359     d6u8 = vqrshrn_n_u16(q5u16, 7);
    360     d7u8 = vqrshrn_n_u16(q6u16, 7);
    361     d8u8 = vqrshrn_n_u16(q7u16, 7);
    362     d9u8 = vqrshrn_n_u16(q8u16, 7);
    363 
    364     vst1_u8((uint8_t *)dst_ptr, d2u8);
    365     dst_ptr += dst_pitch;
    366     vst1_u8((uint8_t *)dst_ptr, d3u8);
    367     dst_ptr += dst_pitch;
    368     vst1_u8((uint8_t *)dst_ptr, d4u8);
    369     dst_ptr += dst_pitch;
    370     vst1_u8((uint8_t *)dst_ptr, d5u8);
    371     dst_ptr += dst_pitch;
    372     vst1_u8((uint8_t *)dst_ptr, d6u8);
    373     dst_ptr += dst_pitch;
    374     vst1_u8((uint8_t *)dst_ptr, d7u8);
    375     dst_ptr += dst_pitch;
    376     vst1_u8((uint8_t *)dst_ptr, d8u8);
    377     dst_ptr += dst_pitch;
    378     vst1_u8((uint8_t *)dst_ptr, d9u8);
    379   }
    380   return;
    381 }
    382 
    383 void vp8_bilinear_predict16x16_neon(unsigned char *src_ptr,
    384                                     int src_pixels_per_line, int xoffset,
    385                                     int yoffset, unsigned char *dst_ptr,
    386                                     int dst_pitch) {
    387   int i;
    388   unsigned char tmp[272];
    389   unsigned char *tmpp;
    390   uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8, d8u8, d9u8;
    391   uint8x8_t d10u8, d11u8, d12u8, d13u8, d14u8, d15u8, d16u8, d17u8, d18u8;
    392   uint8x8_t d19u8, d20u8, d21u8;
    393   uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8, q6u8, q7u8, q8u8, q9u8, q10u8;
    394   uint8x16_t q11u8, q12u8, q13u8, q14u8, q15u8;
    395   uint16x8_t q1u16, q2u16, q3u16, q4u16, q5u16, q6u16, q7u16, q8u16;
    396   uint16x8_t q9u16, q10u16, q11u16, q12u16, q13u16, q14u16;
    397 
    398   if (xoffset == 0) {  // secondpass_bfilter16x16_only
    399     d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
    400     d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
    401 
    402     q11u8 = vld1q_u8(src_ptr);
    403     src_ptr += src_pixels_per_line;
    404     for (i = 4; i > 0; i--) {
    405       q12u8 = vld1q_u8(src_ptr);
    406       src_ptr += src_pixels_per_line;
    407       q13u8 = vld1q_u8(src_ptr);
    408       src_ptr += src_pixels_per_line;
    409       q14u8 = vld1q_u8(src_ptr);
    410       src_ptr += src_pixels_per_line;
    411       q15u8 = vld1q_u8(src_ptr);
    412       src_ptr += src_pixels_per_line;
    413 
    414       q1u16 = vmull_u8(vget_low_u8(q11u8), d0u8);
    415       q2u16 = vmull_u8(vget_high_u8(q11u8), d0u8);
    416       q3u16 = vmull_u8(vget_low_u8(q12u8), d0u8);
    417       q4u16 = vmull_u8(vget_high_u8(q12u8), d0u8);
    418       q5u16 = vmull_u8(vget_low_u8(q13u8), d0u8);
    419       q6u16 = vmull_u8(vget_high_u8(q13u8), d0u8);
    420       q7u16 = vmull_u8(vget_low_u8(q14u8), d0u8);
    421       q8u16 = vmull_u8(vget_high_u8(q14u8), d0u8);
    422 
    423       q1u16 = vmlal_u8(q1u16, vget_low_u8(q12u8), d1u8);
    424       q2u16 = vmlal_u8(q2u16, vget_high_u8(q12u8), d1u8);
    425       q3u16 = vmlal_u8(q3u16, vget_low_u8(q13u8), d1u8);
    426       q4u16 = vmlal_u8(q4u16, vget_high_u8(q13u8), d1u8);
    427       q5u16 = vmlal_u8(q5u16, vget_low_u8(q14u8), d1u8);
    428       q6u16 = vmlal_u8(q6u16, vget_high_u8(q14u8), d1u8);
    429       q7u16 = vmlal_u8(q7u16, vget_low_u8(q15u8), d1u8);
    430       q8u16 = vmlal_u8(q8u16, vget_high_u8(q15u8), d1u8);
    431 
    432       d2u8 = vqrshrn_n_u16(q1u16, 7);
    433       d3u8 = vqrshrn_n_u16(q2u16, 7);
    434       d4u8 = vqrshrn_n_u16(q3u16, 7);
    435       d5u8 = vqrshrn_n_u16(q4u16, 7);
    436       d6u8 = vqrshrn_n_u16(q5u16, 7);
    437       d7u8 = vqrshrn_n_u16(q6u16, 7);
    438       d8u8 = vqrshrn_n_u16(q7u16, 7);
    439       d9u8 = vqrshrn_n_u16(q8u16, 7);
    440 
    441       q1u8 = vcombine_u8(d2u8, d3u8);
    442       q2u8 = vcombine_u8(d4u8, d5u8);
    443       q3u8 = vcombine_u8(d6u8, d7u8);
    444       q4u8 = vcombine_u8(d8u8, d9u8);
    445 
    446       q11u8 = q15u8;
    447 
    448       vst1q_u8((uint8_t *)dst_ptr, q1u8);
    449       dst_ptr += dst_pitch;
    450       vst1q_u8((uint8_t *)dst_ptr, q2u8);
    451       dst_ptr += dst_pitch;
    452       vst1q_u8((uint8_t *)dst_ptr, q3u8);
    453       dst_ptr += dst_pitch;
    454       vst1q_u8((uint8_t *)dst_ptr, q4u8);
    455       dst_ptr += dst_pitch;
    456     }
    457     return;
    458   }
    459 
    460   if (yoffset == 0) {  // firstpass_bfilter16x16_only
    461     d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
    462     d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
    463 
    464     for (i = 4; i > 0; i--) {
    465       d2u8 = vld1_u8(src_ptr);
    466       d3u8 = vld1_u8(src_ptr + 8);
    467       d4u8 = vld1_u8(src_ptr + 16);
    468       src_ptr += src_pixels_per_line;
    469       d5u8 = vld1_u8(src_ptr);
    470       d6u8 = vld1_u8(src_ptr + 8);
    471       d7u8 = vld1_u8(src_ptr + 16);
    472       src_ptr += src_pixels_per_line;
    473       d8u8 = vld1_u8(src_ptr);
    474       d9u8 = vld1_u8(src_ptr + 8);
    475       d10u8 = vld1_u8(src_ptr + 16);
    476       src_ptr += src_pixels_per_line;
    477       d11u8 = vld1_u8(src_ptr);
    478       d12u8 = vld1_u8(src_ptr + 8);
    479       d13u8 = vld1_u8(src_ptr + 16);
    480       src_ptr += src_pixels_per_line;
    481 
    482       q7u16 = vmull_u8(d2u8, d0u8);
    483       q8u16 = vmull_u8(d3u8, d0u8);
    484       q9u16 = vmull_u8(d5u8, d0u8);
    485       q10u16 = vmull_u8(d6u8, d0u8);
    486       q11u16 = vmull_u8(d8u8, d0u8);
    487       q12u16 = vmull_u8(d9u8, d0u8);
    488       q13u16 = vmull_u8(d11u8, d0u8);
    489       q14u16 = vmull_u8(d12u8, d0u8);
    490 
    491       d2u8 = vext_u8(d2u8, d3u8, 1);
    492       d5u8 = vext_u8(d5u8, d6u8, 1);
    493       d8u8 = vext_u8(d8u8, d9u8, 1);
    494       d11u8 = vext_u8(d11u8, d12u8, 1);
    495 
    496       q7u16 = vmlal_u8(q7u16, d2u8, d1u8);
    497       q9u16 = vmlal_u8(q9u16, d5u8, d1u8);
    498       q11u16 = vmlal_u8(q11u16, d8u8, d1u8);
    499       q13u16 = vmlal_u8(q13u16, d11u8, d1u8);
    500 
    501       d3u8 = vext_u8(d3u8, d4u8, 1);
    502       d6u8 = vext_u8(d6u8, d7u8, 1);
    503       d9u8 = vext_u8(d9u8, d10u8, 1);
    504       d12u8 = vext_u8(d12u8, d13u8, 1);
    505 
    506       q8u16 = vmlal_u8(q8u16, d3u8, d1u8);
    507       q10u16 = vmlal_u8(q10u16, d6u8, d1u8);
    508       q12u16 = vmlal_u8(q12u16, d9u8, d1u8);
    509       q14u16 = vmlal_u8(q14u16, d12u8, d1u8);
    510 
    511       d14u8 = vqrshrn_n_u16(q7u16, 7);
    512       d15u8 = vqrshrn_n_u16(q8u16, 7);
    513       d16u8 = vqrshrn_n_u16(q9u16, 7);
    514       d17u8 = vqrshrn_n_u16(q10u16, 7);
    515       d18u8 = vqrshrn_n_u16(q11u16, 7);
    516       d19u8 = vqrshrn_n_u16(q12u16, 7);
    517       d20u8 = vqrshrn_n_u16(q13u16, 7);
    518       d21u8 = vqrshrn_n_u16(q14u16, 7);
    519 
    520       q7u8 = vcombine_u8(d14u8, d15u8);
    521       q8u8 = vcombine_u8(d16u8, d17u8);
    522       q9u8 = vcombine_u8(d18u8, d19u8);
    523       q10u8 = vcombine_u8(d20u8, d21u8);
    524 
    525       vst1q_u8((uint8_t *)dst_ptr, q7u8);
    526       dst_ptr += dst_pitch;
    527       vst1q_u8((uint8_t *)dst_ptr, q8u8);
    528       dst_ptr += dst_pitch;
    529       vst1q_u8((uint8_t *)dst_ptr, q9u8);
    530       dst_ptr += dst_pitch;
    531       vst1q_u8((uint8_t *)dst_ptr, q10u8);
    532       dst_ptr += dst_pitch;
    533     }
    534     return;
    535   }
    536 
    537   d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
    538   d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
    539 
    540   d2u8 = vld1_u8(src_ptr);
    541   d3u8 = vld1_u8(src_ptr + 8);
    542   d4u8 = vld1_u8(src_ptr + 16);
    543   src_ptr += src_pixels_per_line;
    544   d5u8 = vld1_u8(src_ptr);
    545   d6u8 = vld1_u8(src_ptr + 8);
    546   d7u8 = vld1_u8(src_ptr + 16);
    547   src_ptr += src_pixels_per_line;
    548   d8u8 = vld1_u8(src_ptr);
    549   d9u8 = vld1_u8(src_ptr + 8);
    550   d10u8 = vld1_u8(src_ptr + 16);
    551   src_ptr += src_pixels_per_line;
    552   d11u8 = vld1_u8(src_ptr);
    553   d12u8 = vld1_u8(src_ptr + 8);
    554   d13u8 = vld1_u8(src_ptr + 16);
    555   src_ptr += src_pixels_per_line;
    556 
    557   // First Pass: output_height lines x output_width columns (17x16)
    558   tmpp = tmp;
    559   for (i = 3; i > 0; i--) {
    560     q7u16 = vmull_u8(d2u8, d0u8);
    561     q8u16 = vmull_u8(d3u8, d0u8);
    562     q9u16 = vmull_u8(d5u8, d0u8);
    563     q10u16 = vmull_u8(d6u8, d0u8);
    564     q11u16 = vmull_u8(d8u8, d0u8);
    565     q12u16 = vmull_u8(d9u8, d0u8);
    566     q13u16 = vmull_u8(d11u8, d0u8);
    567     q14u16 = vmull_u8(d12u8, d0u8);
    568 
    569     d2u8 = vext_u8(d2u8, d3u8, 1);
    570     d5u8 = vext_u8(d5u8, d6u8, 1);
    571     d8u8 = vext_u8(d8u8, d9u8, 1);
    572     d11u8 = vext_u8(d11u8, d12u8, 1);
    573 
    574     q7u16 = vmlal_u8(q7u16, d2u8, d1u8);
    575     q9u16 = vmlal_u8(q9u16, d5u8, d1u8);
    576     q11u16 = vmlal_u8(q11u16, d8u8, d1u8);
    577     q13u16 = vmlal_u8(q13u16, d11u8, d1u8);
    578 
    579     d3u8 = vext_u8(d3u8, d4u8, 1);
    580     d6u8 = vext_u8(d6u8, d7u8, 1);
    581     d9u8 = vext_u8(d9u8, d10u8, 1);
    582     d12u8 = vext_u8(d12u8, d13u8, 1);
    583 
    584     q8u16 = vmlal_u8(q8u16, d3u8, d1u8);
    585     q10u16 = vmlal_u8(q10u16, d6u8, d1u8);
    586     q12u16 = vmlal_u8(q12u16, d9u8, d1u8);
    587     q14u16 = vmlal_u8(q14u16, d12u8, d1u8);
    588 
    589     d14u8 = vqrshrn_n_u16(q7u16, 7);
    590     d15u8 = vqrshrn_n_u16(q8u16, 7);
    591     d16u8 = vqrshrn_n_u16(q9u16, 7);
    592     d17u8 = vqrshrn_n_u16(q10u16, 7);
    593     d18u8 = vqrshrn_n_u16(q11u16, 7);
    594     d19u8 = vqrshrn_n_u16(q12u16, 7);
    595     d20u8 = vqrshrn_n_u16(q13u16, 7);
    596     d21u8 = vqrshrn_n_u16(q14u16, 7);
    597 
    598     d2u8 = vld1_u8(src_ptr);
    599     d3u8 = vld1_u8(src_ptr + 8);
    600     d4u8 = vld1_u8(src_ptr + 16);
    601     src_ptr += src_pixels_per_line;
    602     d5u8 = vld1_u8(src_ptr);
    603     d6u8 = vld1_u8(src_ptr + 8);
    604     d7u8 = vld1_u8(src_ptr + 16);
    605     src_ptr += src_pixels_per_line;
    606     d8u8 = vld1_u8(src_ptr);
    607     d9u8 = vld1_u8(src_ptr + 8);
    608     d10u8 = vld1_u8(src_ptr + 16);
    609     src_ptr += src_pixels_per_line;
    610     d11u8 = vld1_u8(src_ptr);
    611     d12u8 = vld1_u8(src_ptr + 8);
    612     d13u8 = vld1_u8(src_ptr + 16);
    613     src_ptr += src_pixels_per_line;
    614 
    615     q7u8 = vcombine_u8(d14u8, d15u8);
    616     q8u8 = vcombine_u8(d16u8, d17u8);
    617     q9u8 = vcombine_u8(d18u8, d19u8);
    618     q10u8 = vcombine_u8(d20u8, d21u8);
    619 
    620     vst1q_u8((uint8_t *)tmpp, q7u8);
    621     tmpp += 16;
    622     vst1q_u8((uint8_t *)tmpp, q8u8);
    623     tmpp += 16;
    624     vst1q_u8((uint8_t *)tmpp, q9u8);
    625     tmpp += 16;
    626     vst1q_u8((uint8_t *)tmpp, q10u8);
    627     tmpp += 16;
    628   }
    629 
    630   // First-pass filtering for rest 5 lines
    631   d14u8 = vld1_u8(src_ptr);
    632   d15u8 = vld1_u8(src_ptr + 8);
    633   d16u8 = vld1_u8(src_ptr + 16);
    634   src_ptr += src_pixels_per_line;
    635 
    636   q9u16 = vmull_u8(d2u8, d0u8);
    637   q10u16 = vmull_u8(d3u8, d0u8);
    638   q11u16 = vmull_u8(d5u8, d0u8);
    639   q12u16 = vmull_u8(d6u8, d0u8);
    640   q13u16 = vmull_u8(d8u8, d0u8);
    641   q14u16 = vmull_u8(d9u8, d0u8);
    642 
    643   d2u8 = vext_u8(d2u8, d3u8, 1);
    644   d5u8 = vext_u8(d5u8, d6u8, 1);
    645   d8u8 = vext_u8(d8u8, d9u8, 1);
    646 
    647   q9u16 = vmlal_u8(q9u16, d2u8, d1u8);
    648   q11u16 = vmlal_u8(q11u16, d5u8, d1u8);
    649   q13u16 = vmlal_u8(q13u16, d8u8, d1u8);
    650 
    651   d3u8 = vext_u8(d3u8, d4u8, 1);
    652   d6u8 = vext_u8(d6u8, d7u8, 1);
    653   d9u8 = vext_u8(d9u8, d10u8, 1);
    654 
    655   q10u16 = vmlal_u8(q10u16, d3u8, d1u8);
    656   q12u16 = vmlal_u8(q12u16, d6u8, d1u8);
    657   q14u16 = vmlal_u8(q14u16, d9u8, d1u8);
    658 
    659   q1u16 = vmull_u8(d11u8, d0u8);
    660   q2u16 = vmull_u8(d12u8, d0u8);
    661   q3u16 = vmull_u8(d14u8, d0u8);
    662   q4u16 = vmull_u8(d15u8, d0u8);
    663 
    664   d11u8 = vext_u8(d11u8, d12u8, 1);
    665   d14u8 = vext_u8(d14u8, d15u8, 1);
    666 
    667   q1u16 = vmlal_u8(q1u16, d11u8, d1u8);
    668   q3u16 = vmlal_u8(q3u16, d14u8, d1u8);
    669 
    670   d12u8 = vext_u8(d12u8, d13u8, 1);
    671   d15u8 = vext_u8(d15u8, d16u8, 1);
    672 
    673   q2u16 = vmlal_u8(q2u16, d12u8, d1u8);
    674   q4u16 = vmlal_u8(q4u16, d15u8, d1u8);
    675 
    676   d10u8 = vqrshrn_n_u16(q9u16, 7);
    677   d11u8 = vqrshrn_n_u16(q10u16, 7);
    678   d12u8 = vqrshrn_n_u16(q11u16, 7);
    679   d13u8 = vqrshrn_n_u16(q12u16, 7);
    680   d14u8 = vqrshrn_n_u16(q13u16, 7);
    681   d15u8 = vqrshrn_n_u16(q14u16, 7);
    682   d16u8 = vqrshrn_n_u16(q1u16, 7);
    683   d17u8 = vqrshrn_n_u16(q2u16, 7);
    684   d18u8 = vqrshrn_n_u16(q3u16, 7);
    685   d19u8 = vqrshrn_n_u16(q4u16, 7);
    686 
    687   q5u8 = vcombine_u8(d10u8, d11u8);
    688   q6u8 = vcombine_u8(d12u8, d13u8);
    689   q7u8 = vcombine_u8(d14u8, d15u8);
    690   q8u8 = vcombine_u8(d16u8, d17u8);
    691   q9u8 = vcombine_u8(d18u8, d19u8);
    692 
    693   vst1q_u8((uint8_t *)tmpp, q5u8);
    694   tmpp += 16;
    695   vst1q_u8((uint8_t *)tmpp, q6u8);
    696   tmpp += 16;
    697   vst1q_u8((uint8_t *)tmpp, q7u8);
    698   tmpp += 16;
    699   vst1q_u8((uint8_t *)tmpp, q8u8);
    700   tmpp += 16;
    701   vst1q_u8((uint8_t *)tmpp, q9u8);
    702 
    703   // secondpass_filter
    704   d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
    705   d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
    706 
    707   tmpp = tmp;
    708   q11u8 = vld1q_u8(tmpp);
    709   tmpp += 16;
    710   for (i = 4; i > 0; i--) {
    711     q12u8 = vld1q_u8(tmpp);
    712     tmpp += 16;
    713     q13u8 = vld1q_u8(tmpp);
    714     tmpp += 16;
    715     q14u8 = vld1q_u8(tmpp);
    716     tmpp += 16;
    717     q15u8 = vld1q_u8(tmpp);
    718     tmpp += 16;
    719 
    720     q1u16 = vmull_u8(vget_low_u8(q11u8), d0u8);
    721     q2u16 = vmull_u8(vget_high_u8(q11u8), d0u8);
    722     q3u16 = vmull_u8(vget_low_u8(q12u8), d0u8);
    723     q4u16 = vmull_u8(vget_high_u8(q12u8), d0u8);
    724     q5u16 = vmull_u8(vget_low_u8(q13u8), d0u8);
    725     q6u16 = vmull_u8(vget_high_u8(q13u8), d0u8);
    726     q7u16 = vmull_u8(vget_low_u8(q14u8), d0u8);
    727     q8u16 = vmull_u8(vget_high_u8(q14u8), d0u8);
    728 
    729     q1u16 = vmlal_u8(q1u16, vget_low_u8(q12u8), d1u8);
    730     q2u16 = vmlal_u8(q2u16, vget_high_u8(q12u8), d1u8);
    731     q3u16 = vmlal_u8(q3u16, vget_low_u8(q13u8), d1u8);
    732     q4u16 = vmlal_u8(q4u16, vget_high_u8(q13u8), d1u8);
    733     q5u16 = vmlal_u8(q5u16, vget_low_u8(q14u8), d1u8);
    734     q6u16 = vmlal_u8(q6u16, vget_high_u8(q14u8), d1u8);
    735     q7u16 = vmlal_u8(q7u16, vget_low_u8(q15u8), d1u8);
    736     q8u16 = vmlal_u8(q8u16, vget_high_u8(q15u8), d1u8);
    737 
    738     d2u8 = vqrshrn_n_u16(q1u16, 7);
    739     d3u8 = vqrshrn_n_u16(q2u16, 7);
    740     d4u8 = vqrshrn_n_u16(q3u16, 7);
    741     d5u8 = vqrshrn_n_u16(q4u16, 7);
    742     d6u8 = vqrshrn_n_u16(q5u16, 7);
    743     d7u8 = vqrshrn_n_u16(q6u16, 7);
    744     d8u8 = vqrshrn_n_u16(q7u16, 7);
    745     d9u8 = vqrshrn_n_u16(q8u16, 7);
    746 
    747     q1u8 = vcombine_u8(d2u8, d3u8);
    748     q2u8 = vcombine_u8(d4u8, d5u8);
    749     q3u8 = vcombine_u8(d6u8, d7u8);
    750     q4u8 = vcombine_u8(d8u8, d9u8);
    751 
    752     q11u8 = q15u8;
    753 
    754     vst1q_u8((uint8_t *)dst_ptr, q1u8);
    755     dst_ptr += dst_pitch;
    756     vst1q_u8((uint8_t *)dst_ptr, q2u8);
    757     dst_ptr += dst_pitch;
    758     vst1q_u8((uint8_t *)dst_ptr, q3u8);
    759     dst_ptr += dst_pitch;
    760     vst1q_u8((uint8_t *)dst_ptr, q4u8);
    761     dst_ptr += dst_pitch;
    762   }
    763   return;
    764 }
    765