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