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