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