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 
vp8_bilinear_predict4x4_neon(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)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 
vp8_bilinear_predict8x4_neon(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)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 
vp8_bilinear_predict8x8_neon(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)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 
vp8_bilinear_predict16x16_neon(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)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