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