arm: Implement a NEON version of 422 h264_h_loop_filter_chroma
[libav.git] / libavcodec / arm / h264dsp_neon.S
1 /*
2 * Copyright (c) 2008 Mans Rullgard <mans@mansr.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "libavutil/arm/asm.S"
22 #include "neon.S"
23
24 /* H.264 loop filter */
25
26 .macro h264_loop_filter_start
27 ldr r12, [sp]
28 tst r2, r2
29 ldr r12, [r12]
30 it ne
31 tstne r3, r3
32 vmov.32 d24[0], r12
33 and r12, r12, r12, lsl #16
34 it eq
35 bxeq lr
36 ands r12, r12, r12, lsl #8
37 it lt
38 bxlt lr
39 .endm
40
41 .macro h264_loop_filter_luma
42 vdup.8 q11, r2 @ alpha
43 vmovl.u8 q12, d24
44 vabd.u8 q6, q8, q0 @ abs(p0 - q0)
45 vmovl.u16 q12, d24
46 vabd.u8 q14, q9, q8 @ abs(p1 - p0)
47 vsli.16 q12, q12, #8
48 vabd.u8 q15, q1, q0 @ abs(q1 - q0)
49 vsli.32 q12, q12, #16
50 vclt.u8 q6, q6, q11 @ < alpha
51 vdup.8 q11, r3 @ beta
52 vclt.s8 q7, q12, #0
53 vclt.u8 q14, q14, q11 @ < beta
54 vclt.u8 q15, q15, q11 @ < beta
55 vbic q6, q6, q7
56 vabd.u8 q4, q10, q8 @ abs(p2 - p0)
57 vand q6, q6, q14
58 vabd.u8 q5, q2, q0 @ abs(q2 - q0)
59 vclt.u8 q4, q4, q11 @ < beta
60 vand q6, q6, q15
61 vclt.u8 q5, q5, q11 @ < beta
62 vand q4, q4, q6
63 vand q5, q5, q6
64 vand q12, q12, q6
65 vrhadd.u8 q14, q8, q0
66 vsub.i8 q6, q12, q4
67 vqadd.u8 q7, q9, q12
68 vhadd.u8 q10, q10, q14
69 vsub.i8 q6, q6, q5
70 vhadd.u8 q14, q2, q14
71 vmin.u8 q7, q7, q10
72 vqsub.u8 q11, q9, q12
73 vqadd.u8 q2, q1, q12
74 vmax.u8 q7, q7, q11
75 vqsub.u8 q11, q1, q12
76 vmin.u8 q14, q2, q14
77 vmovl.u8 q2, d0
78 vmax.u8 q14, q14, q11
79 vmovl.u8 q10, d1
80 vsubw.u8 q2, q2, d16
81 vsubw.u8 q10, q10, d17
82 vshl.i16 q2, q2, #2
83 vshl.i16 q10, q10, #2
84 vaddw.u8 q2, q2, d18
85 vaddw.u8 q10, q10, d19
86 vsubw.u8 q2, q2, d2
87 vsubw.u8 q10, q10, d3
88 vrshrn.i16 d4, q2, #3
89 vrshrn.i16 d5, q10, #3
90 vbsl q4, q7, q9
91 vbsl q5, q14, q1
92 vneg.s8 q7, q6
93 vmovl.u8 q14, d16
94 vmin.s8 q2, q2, q6
95 vmovl.u8 q6, d17
96 vmax.s8 q2, q2, q7
97 vmovl.u8 q11, d0
98 vmovl.u8 q12, d1
99 vaddw.s8 q14, q14, d4
100 vaddw.s8 q6, q6, d5
101 vsubw.s8 q11, q11, d4
102 vsubw.s8 q12, q12, d5
103 vqmovun.s16 d16, q14
104 vqmovun.s16 d17, q6
105 vqmovun.s16 d0, q11
106 vqmovun.s16 d1, q12
107 .endm
108
109 function ff_h264_v_loop_filter_luma_neon, export=1
110 h264_loop_filter_start
111
112 vld1.8 {d0, d1}, [r0,:128], r1
113 vld1.8 {d2, d3}, [r0,:128], r1
114 vld1.8 {d4, d5}, [r0,:128], r1
115 sub r0, r0, r1, lsl #2
116 sub r0, r0, r1, lsl #1
117 vld1.8 {d20,d21}, [r0,:128], r1
118 vld1.8 {d18,d19}, [r0,:128], r1
119 vld1.8 {d16,d17}, [r0,:128], r1
120
121 vpush {d8-d15}
122
123 h264_loop_filter_luma
124
125 sub r0, r0, r1, lsl #1
126 vst1.8 {d8, d9}, [r0,:128], r1
127 vst1.8 {d16,d17}, [r0,:128], r1
128 vst1.8 {d0, d1}, [r0,:128], r1
129 vst1.8 {d10,d11}, [r0,:128]
130
131 vpop {d8-d15}
132 bx lr
133 endfunc
134
135 function ff_h264_h_loop_filter_luma_neon, export=1
136 h264_loop_filter_start
137
138 sub r0, r0, #4
139 vld1.8 {d6}, [r0], r1
140 vld1.8 {d20}, [r0], r1
141 vld1.8 {d18}, [r0], r1
142 vld1.8 {d16}, [r0], r1
143 vld1.8 {d0}, [r0], r1
144 vld1.8 {d2}, [r0], r1
145 vld1.8 {d4}, [r0], r1
146 vld1.8 {d26}, [r0], r1
147 vld1.8 {d7}, [r0], r1
148 vld1.8 {d21}, [r0], r1
149 vld1.8 {d19}, [r0], r1
150 vld1.8 {d17}, [r0], r1
151 vld1.8 {d1}, [r0], r1
152 vld1.8 {d3}, [r0], r1
153 vld1.8 {d5}, [r0], r1
154 vld1.8 {d27}, [r0], r1
155
156 transpose_8x8 q3, q10, q9, q8, q0, q1, q2, q13
157
158 vpush {d8-d15}
159
160 h264_loop_filter_luma
161
162 transpose_4x4 q4, q8, q0, q5
163
164 sub r0, r0, r1, lsl #4
165 add r0, r0, #2
166 vst1.32 {d8[0]}, [r0], r1
167 vst1.32 {d16[0]}, [r0], r1
168 vst1.32 {d0[0]}, [r0], r1
169 vst1.32 {d10[0]}, [r0], r1
170 vst1.32 {d8[1]}, [r0], r1
171 vst1.32 {d16[1]}, [r0], r1
172 vst1.32 {d0[1]}, [r0], r1
173 vst1.32 {d10[1]}, [r0], r1
174 vst1.32 {d9[0]}, [r0], r1
175 vst1.32 {d17[0]}, [r0], r1
176 vst1.32 {d1[0]}, [r0], r1
177 vst1.32 {d11[0]}, [r0], r1
178 vst1.32 {d9[1]}, [r0], r1
179 vst1.32 {d17[1]}, [r0], r1
180 vst1.32 {d1[1]}, [r0], r1
181 vst1.32 {d11[1]}, [r0], r1
182
183 vpop {d8-d15}
184 bx lr
185 endfunc
186
187 .macro h264_loop_filter_chroma
188 vdup.8 d22, r2 @ alpha
189 vmovl.u8 q12, d24
190 vabd.u8 d26, d16, d0 @ abs(p0 - q0)
191 vmovl.u8 q2, d0
192 vabd.u8 d28, d18, d16 @ abs(p1 - p0)
193 vsubw.u8 q2, q2, d16
194 vsli.16 d24, d24, #8
195 vshl.i16 q2, q2, #2
196 vabd.u8 d30, d2, d0 @ abs(q1 - q0)
197 vaddw.u8 q2, q2, d18
198 vclt.u8 d26, d26, d22 @ < alpha
199 vsubw.u8 q2, q2, d2
200 vdup.8 d22, r3 @ beta
201 vrshrn.i16 d4, q2, #3
202 vclt.u8 d28, d28, d22 @ < beta
203 vclt.u8 d30, d30, d22 @ < beta
204 vmin.s8 d4, d4, d24
205 vneg.s8 d25, d24
206 vand d26, d26, d28
207 vmax.s8 d4, d4, d25
208 vand d26, d26, d30
209 vmovl.u8 q11, d0
210 vand d4, d4, d26
211 vmovl.u8 q14, d16
212 vaddw.s8 q14, q14, d4
213 vsubw.s8 q11, q11, d4
214 vqmovun.s16 d16, q14
215 vqmovun.s16 d0, q11
216 .endm
217
218 function ff_h264_v_loop_filter_chroma_neon, export=1
219 h264_loop_filter_start
220
221 sub r0, r0, r1, lsl #1
222 vld1.8 {d18}, [r0,:64], r1
223 vld1.8 {d16}, [r0,:64], r1
224 vld1.8 {d0}, [r0,:64], r1
225 vld1.8 {d2}, [r0,:64]
226
227 h264_loop_filter_chroma
228
229 sub r0, r0, r1, lsl #1
230 vst1.8 {d16}, [r0,:64], r1
231 vst1.8 {d0}, [r0,:64], r1
232
233 bx lr
234 endfunc
235
236 function ff_h264_h_loop_filter_chroma_neon, export=1
237 h264_loop_filter_start
238
239 sub r0, r0, #2
240 h_loop_filter_chroma420:
241 vld1.32 {d18[0]}, [r0], r1
242 vld1.32 {d16[0]}, [r0], r1
243 vld1.32 {d0[0]}, [r0], r1
244 vld1.32 {d2[0]}, [r0], r1
245 vld1.32 {d18[1]}, [r0], r1
246 vld1.32 {d16[1]}, [r0], r1
247 vld1.32 {d0[1]}, [r0], r1
248 vld1.32 {d2[1]}, [r0], r1
249
250 vtrn.16 d18, d0
251 vtrn.16 d16, d2
252 vtrn.8 d18, d16
253 vtrn.8 d0, d2
254
255 h264_loop_filter_chroma
256
257 vtrn.16 d18, d0
258 vtrn.16 d16, d2
259 vtrn.8 d18, d16
260 vtrn.8 d0, d2
261
262 sub r0, r0, r1, lsl #3
263 vst1.32 {d18[0]}, [r0], r1
264 vst1.32 {d16[0]}, [r0], r1
265 vst1.32 {d0[0]}, [r0], r1
266 vst1.32 {d2[0]}, [r0], r1
267 vst1.32 {d18[1]}, [r0], r1
268 vst1.32 {d16[1]}, [r0], r1
269 vst1.32 {d0[1]}, [r0], r1
270 vst1.32 {d2[1]}, [r0], r1
271
272 bx lr
273 endfunc
274
275 function ff_h264_h_loop_filter_chroma422_neon, export=1
276 h264_loop_filter_start
277 push {r4, lr}
278 add r4, r0, r1
279 add r1, r1, r1
280 sub r0, r0, #2
281
282 bl h_loop_filter_chroma420
283
284 ldr r12, [sp, #8]
285 ldr r12, [r12]
286 vmov.32 d24[0], r12
287 sub r0, r4, #2
288
289 bl h_loop_filter_chroma420
290 pop {r4, pc}
291 endfunc
292
293 @ Biweighted prediction
294
295 .macro biweight_16 macs, macd
296 vdup.8 d0, r4
297 vdup.8 d1, r5
298 vmov q2, q8
299 vmov q3, q8
300 1: subs r3, r3, #2
301 vld1.8 {d20-d21},[r0,:128], r2
302 \macd q2, d0, d20
303 pld [r0]
304 \macd q3, d0, d21
305 vld1.8 {d22-d23},[r1,:128], r2
306 \macs q2, d1, d22
307 pld [r1]
308 \macs q3, d1, d23
309 vmov q12, q8
310 vld1.8 {d28-d29},[r0,:128], r2
311 vmov q13, q8
312 \macd q12, d0, d28
313 pld [r0]
314 \macd q13, d0, d29
315 vld1.8 {d30-d31},[r1,:128], r2
316 \macs q12, d1, d30
317 pld [r1]
318 \macs q13, d1, d31
319 vshl.s16 q2, q2, q9
320 vshl.s16 q3, q3, q9
321 vqmovun.s16 d4, q2
322 vqmovun.s16 d5, q3
323 vshl.s16 q12, q12, q9
324 vshl.s16 q13, q13, q9
325 vqmovun.s16 d24, q12
326 vqmovun.s16 d25, q13
327 vmov q3, q8
328 vst1.8 {d4- d5}, [r6,:128], r2
329 vmov q2, q8
330 vst1.8 {d24-d25},[r6,:128], r2
331 bne 1b
332 pop {r4-r6, pc}
333 .endm
334
335 .macro biweight_8 macs, macd
336 vdup.8 d0, r4
337 vdup.8 d1, r5
338 vmov q1, q8
339 vmov q10, q8
340 1: subs r3, r3, #2
341 vld1.8 {d4},[r0,:64], r2
342 \macd q1, d0, d4
343 pld [r0]
344 vld1.8 {d5},[r1,:64], r2
345 \macs q1, d1, d5
346 pld [r1]
347 vld1.8 {d6},[r0,:64], r2
348 \macd q10, d0, d6
349 pld [r0]
350 vld1.8 {d7},[r1,:64], r2
351 \macs q10, d1, d7
352 pld [r1]
353 vshl.s16 q1, q1, q9
354 vqmovun.s16 d2, q1
355 vshl.s16 q10, q10, q9
356 vqmovun.s16 d4, q10
357 vmov q10, q8
358 vst1.8 {d2},[r6,:64], r2
359 vmov q1, q8
360 vst1.8 {d4},[r6,:64], r2
361 bne 1b
362 pop {r4-r6, pc}
363 .endm
364
365 .macro biweight_4 macs, macd
366 vdup.8 d0, r4
367 vdup.8 d1, r5
368 vmov q1, q8
369 vmov q10, q8
370 1: subs r3, r3, #4
371 vld1.32 {d4[0]},[r0,:32], r2
372 vld1.32 {d4[1]},[r0,:32], r2
373 \macd q1, d0, d4
374 pld [r0]
375 vld1.32 {d5[0]},[r1,:32], r2
376 vld1.32 {d5[1]},[r1,:32], r2
377 \macs q1, d1, d5
378 pld [r1]
379 blt 2f
380 vld1.32 {d6[0]},[r0,:32], r2
381 vld1.32 {d6[1]},[r0,:32], r2
382 \macd q10, d0, d6
383 pld [r0]
384 vld1.32 {d7[0]},[r1,:32], r2
385 vld1.32 {d7[1]},[r1,:32], r2
386 \macs q10, d1, d7
387 pld [r1]
388 vshl.s16 q1, q1, q9
389 vqmovun.s16 d2, q1
390 vshl.s16 q10, q10, q9
391 vqmovun.s16 d4, q10
392 vmov q10, q8
393 vst1.32 {d2[0]},[r6,:32], r2
394 vst1.32 {d2[1]},[r6,:32], r2
395 vmov q1, q8
396 vst1.32 {d4[0]},[r6,:32], r2
397 vst1.32 {d4[1]},[r6,:32], r2
398 bne 1b
399 pop {r4-r6, pc}
400 2: vshl.s16 q1, q1, q9
401 vqmovun.s16 d2, q1
402 vst1.32 {d2[0]},[r6,:32], r2
403 vst1.32 {d2[1]},[r6,:32], r2
404 pop {r4-r6, pc}
405 .endm
406
407 .macro biweight_func w
408 function ff_biweight_h264_pixels_\w\()_neon, export=1
409 push {r4-r6, lr}
410 ldr r12, [sp, #16]
411 add r4, sp, #20
412 ldm r4, {r4-r6}
413 lsr lr, r4, #31
414 add r6, r6, #1
415 eors lr, lr, r5, lsr #30
416 orr r6, r6, #1
417 vdup.16 q9, r12
418 lsl r6, r6, r12
419 vmvn q9, q9
420 vdup.16 q8, r6
421 mov r6, r0
422 beq 10f
423 subs lr, lr, #1
424 beq 20f
425 subs lr, lr, #1
426 beq 30f
427 b 40f
428 10: biweight_\w vmlal.u8, vmlal.u8
429 20: rsb r4, r4, #0
430 biweight_\w vmlal.u8, vmlsl.u8
431 30: rsb r4, r4, #0
432 rsb r5, r5, #0
433 biweight_\w vmlsl.u8, vmlsl.u8
434 40: rsb r5, r5, #0
435 biweight_\w vmlsl.u8, vmlal.u8
436 endfunc
437 .endm
438
439 biweight_func 16
440 biweight_func 8
441 biweight_func 4
442
443 @ Weighted prediction
444
445 .macro weight_16 add
446 vdup.8 d0, r12
447 1: subs r2, r2, #2
448 vld1.8 {d20-d21},[r0,:128], r1
449 vmull.u8 q2, d0, d20
450 pld [r0]
451 vmull.u8 q3, d0, d21
452 vld1.8 {d28-d29},[r0,:128], r1
453 vmull.u8 q12, d0, d28
454 pld [r0]
455 vmull.u8 q13, d0, d29
456 \add q2, q8, q2
457 vrshl.s16 q2, q2, q9
458 \add q3, q8, q3
459 vrshl.s16 q3, q3, q9
460 vqmovun.s16 d4, q2
461 vqmovun.s16 d5, q3
462 \add q12, q8, q12
463 vrshl.s16 q12, q12, q9
464 \add q13, q8, q13
465 vrshl.s16 q13, q13, q9
466 vqmovun.s16 d24, q12
467 vqmovun.s16 d25, q13
468 vst1.8 {d4- d5}, [r4,:128], r1
469 vst1.8 {d24-d25},[r4,:128], r1
470 bne 1b
471 pop {r4, pc}
472 .endm
473
474 .macro weight_8 add
475 vdup.8 d0, r12
476 1: subs r2, r2, #2
477 vld1.8 {d4},[r0,:64], r1
478 vmull.u8 q1, d0, d4
479 pld [r0]
480 vld1.8 {d6},[r0,:64], r1
481 vmull.u8 q10, d0, d6
482 \add q1, q8, q1
483 pld [r0]
484 vrshl.s16 q1, q1, q9
485 vqmovun.s16 d2, q1
486 \add q10, q8, q10
487 vrshl.s16 q10, q10, q9
488 vqmovun.s16 d4, q10
489 vst1.8 {d2},[r4,:64], r1
490 vst1.8 {d4},[r4,:64], r1
491 bne 1b
492 pop {r4, pc}
493 .endm
494
495 .macro weight_4 add
496 vdup.8 d0, r12
497 vmov q1, q8
498 vmov q10, q8
499 1: subs r2, r2, #4
500 vld1.32 {d4[0]},[r0,:32], r1
501 vld1.32 {d4[1]},[r0,:32], r1
502 vmull.u8 q1, d0, d4
503 pld [r0]
504 blt 2f
505 vld1.32 {d6[0]},[r0,:32], r1
506 vld1.32 {d6[1]},[r0,:32], r1
507 vmull.u8 q10, d0, d6
508 pld [r0]
509 \add q1, q8, q1
510 vrshl.s16 q1, q1, q9
511 vqmovun.s16 d2, q1
512 \add q10, q8, q10
513 vrshl.s16 q10, q10, q9
514 vqmovun.s16 d4, q10
515 vmov q10, q8
516 vst1.32 {d2[0]},[r4,:32], r1
517 vst1.32 {d2[1]},[r4,:32], r1
518 vmov q1, q8
519 vst1.32 {d4[0]},[r4,:32], r1
520 vst1.32 {d4[1]},[r4,:32], r1
521 bne 1b
522 pop {r4, pc}
523 2: \add q1, q8, q1
524 vrshl.s16 q1, q1, q9
525 vqmovun.s16 d2, q1
526 vst1.32 {d2[0]},[r4,:32], r1
527 vst1.32 {d2[1]},[r4,:32], r1
528 pop {r4, pc}
529 .endm
530
531 .macro weight_func w
532 function ff_weight_h264_pixels_\w\()_neon, export=1
533 push {r4, lr}
534 ldr r12, [sp, #8]
535 ldr r4, [sp, #12]
536 cmp r3, #1
537 lsl r4, r4, r3
538 vdup.16 q8, r4
539 mov r4, r0
540 ble 20f
541 rsb lr, r3, #1
542 vdup.16 q9, lr
543 cmp r12, #0
544 blt 10f
545 weight_\w vhadd.s16
546 10: rsb r12, r12, #0
547 weight_\w vhsub.s16
548 20: rsb lr, r3, #0
549 vdup.16 q9, lr
550 cmp r12, #0
551 blt 10f
552 weight_\w vadd.s16
553 10: rsb r12, r12, #0
554 weight_\w vsub.s16
555 endfunc
556 .endm
557
558 weight_func 16
559 weight_func 8
560 weight_func 4