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