1/*
2 * Copyright (c) 2008 Mans Rullgard <mans@mansr.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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
109function 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
133endfunc
134
135function 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
185endfunc
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
218function 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
234endfunc
235
236function ff_h264_h_loop_filter_chroma_neon, export=1
237        h264_loop_filter_start
238
239        sub             r0,  r0,  #2
240        vld1.32         {d18[0]}, [r0], r1
241        vld1.32         {d16[0]}, [r0], r1
242        vld1.32         {d0[0]},  [r0], r1
243        vld1.32         {d2[0]},  [r0], r1
244        vld1.32         {d18[1]}, [r0], r1
245        vld1.32         {d16[1]}, [r0], r1
246        vld1.32         {d0[1]},  [r0], r1
247        vld1.32         {d2[1]},  [r0], r1
248
249        vtrn.16         d18, d0
250        vtrn.16         d16, d2
251        vtrn.8          d18, d16
252        vtrn.8          d0,  d2
253
254        h264_loop_filter_chroma
255
256        vtrn.16         d18, d0
257        vtrn.16         d16, d2
258        vtrn.8          d18, d16
259        vtrn.8          d0,  d2
260
261        sub             r0,  r0,  r1, lsl #3
262        vst1.32         {d18[0]}, [r0], r1
263        vst1.32         {d16[0]}, [r0], r1
264        vst1.32         {d0[0]},  [r0], r1
265        vst1.32         {d2[0]},  [r0], r1
266        vst1.32         {d18[1]}, [r0], r1
267        vst1.32         {d16[1]}, [r0], r1
268        vst1.32         {d0[1]},  [r0], r1
269        vst1.32         {d2[1]},  [r0], r1
270
271        bx              lr
272endfunc
273
274@ Biweighted prediction
275
276.macro  biweight_16     macs, macd
277        vdup.8          d0,  r4
278        vdup.8          d1,  r5
279        vmov            q2,  q8
280        vmov            q3,  q8
2811:      subs            r3,  r3,  #2
282        vld1.8          {d20-d21},[r0,:128], r2
283        \macd           q2,  d0,  d20
284        pld             [r0]
285        \macd           q3,  d0,  d21
286        vld1.8          {d22-d23},[r1,:128], r2
287        \macs           q2,  d1,  d22
288        pld             [r1]
289        \macs           q3,  d1,  d23
290        vmov            q12, q8
291        vld1.8          {d28-d29},[r0,:128], r2
292        vmov            q13, q8
293        \macd           q12, d0,  d28
294        pld             [r0]
295        \macd           q13, d0,  d29
296        vld1.8          {d30-d31},[r1,:128], r2
297        \macs           q12, d1,  d30
298        pld             [r1]
299        \macs           q13, d1,  d31
300        vshl.s16        q2,  q2,  q9
301        vshl.s16        q3,  q3,  q9
302        vqmovun.s16     d4,  q2
303        vqmovun.s16     d5,  q3
304        vshl.s16        q12, q12, q9
305        vshl.s16        q13, q13, q9
306        vqmovun.s16     d24, q12
307        vqmovun.s16     d25, q13
308        vmov            q3,  q8
309        vst1.8          {d4- d5}, [r6,:128], r2
310        vmov            q2,  q8
311        vst1.8          {d24-d25},[r6,:128], r2
312        bne             1b
313        pop             {r4-r6, pc}
314.endm
315
316.macro  biweight_8      macs, macd
317        vdup.8          d0,  r4
318        vdup.8          d1,  r5
319        vmov            q1,  q8
320        vmov            q10, q8
3211:      subs            r3,  r3,  #2
322        vld1.8          {d4},[r0,:64], r2
323        \macd           q1,  d0,  d4
324        pld             [r0]
325        vld1.8          {d5},[r1,:64], r2
326        \macs           q1,  d1,  d5
327        pld             [r1]
328        vld1.8          {d6},[r0,:64], r2
329        \macd           q10, d0,  d6
330        pld             [r0]
331        vld1.8          {d7},[r1,:64], r2
332        \macs           q10, d1,  d7
333        pld             [r1]
334        vshl.s16        q1,  q1,  q9
335        vqmovun.s16     d2,  q1
336        vshl.s16        q10, q10, q9
337        vqmovun.s16     d4,  q10
338        vmov            q10, q8
339        vst1.8          {d2},[r6,:64], r2
340        vmov            q1,  q8
341        vst1.8          {d4},[r6,:64], r2
342        bne             1b
343        pop             {r4-r6, pc}
344.endm
345
346.macro  biweight_4      macs, macd
347        vdup.8          d0,  r4
348        vdup.8          d1,  r5
349        vmov            q1,  q8
350        vmov            q10, q8
3511:      subs            r3,  r3,  #4
352        vld1.32         {d4[0]},[r0,:32], r2
353        vld1.32         {d4[1]},[r0,:32], r2
354        \macd           q1,  d0,  d4
355        pld             [r0]
356        vld1.32         {d5[0]},[r1,:32], r2
357        vld1.32         {d5[1]},[r1,:32], r2
358        \macs           q1,  d1,  d5
359        pld             [r1]
360        blt             2f
361        vld1.32         {d6[0]},[r0,:32], r2
362        vld1.32         {d6[1]},[r0,:32], r2
363        \macd           q10, d0,  d6
364        pld             [r0]
365        vld1.32         {d7[0]},[r1,:32], r2
366        vld1.32         {d7[1]},[r1,:32], r2
367        \macs           q10, d1,  d7
368        pld             [r1]
369        vshl.s16        q1,  q1,  q9
370        vqmovun.s16     d2,  q1
371        vshl.s16        q10, q10, q9
372        vqmovun.s16     d4,  q10
373        vmov            q10, q8
374        vst1.32         {d2[0]},[r6,:32], r2
375        vst1.32         {d2[1]},[r6,:32], r2
376        vmov            q1,  q8
377        vst1.32         {d4[0]},[r6,:32], r2
378        vst1.32         {d4[1]},[r6,:32], r2
379        bne             1b
380        pop             {r4-r6, pc}
3812:      vshl.s16        q1,  q1,  q9
382        vqmovun.s16     d2,  q1
383        vst1.32         {d2[0]},[r6,:32], r2
384        vst1.32         {d2[1]},[r6,:32], r2
385        pop             {r4-r6, pc}
386.endm
387
388.macro  biweight_func   w
389function ff_biweight_h264_pixels_\w\()_neon, export=1
390        push            {r4-r6, lr}
391        ldr             r12, [sp, #16]
392        add             r4,  sp,  #20
393        ldm             r4,  {r4-r6}
394        lsr             lr,  r4,  #31
395        add             r6,  r6,  #1
396        eors            lr,  lr,  r5,  lsr #30
397        orr             r6,  r6,  #1
398        vdup.16         q9,  r12
399        lsl             r6,  r6,  r12
400        vmvn            q9,  q9
401        vdup.16         q8,  r6
402        mov             r6,  r0
403        beq             10f
404        subs            lr,  lr,  #1
405        beq             20f
406        subs            lr,  lr,  #1
407        beq             30f
408        b               40f
40910:     biweight_\w     vmlal.u8, vmlal.u8
41020:     rsb             r4,  r4,  #0
411        biweight_\w     vmlal.u8, vmlsl.u8
41230:     rsb             r4,  r4,  #0
413        rsb             r5,  r5,  #0
414        biweight_\w     vmlsl.u8, vmlsl.u8
41540:     rsb             r5,  r5,  #0
416        biweight_\w     vmlsl.u8, vmlal.u8
417endfunc
418.endm
419
420        biweight_func   16
421        biweight_func   8
422        biweight_func   4
423
424@ Weighted prediction
425
426.macro  weight_16       add
427        vdup.8          d0,  r12
4281:      subs            r2,  r2,  #2
429        vld1.8          {d20-d21},[r0,:128], r1
430        vmull.u8        q2,  d0,  d20
431        pld             [r0]
432        vmull.u8        q3,  d0,  d21
433        vld1.8          {d28-d29},[r0,:128], r1
434        vmull.u8        q12, d0,  d28
435        pld             [r0]
436        vmull.u8        q13, d0,  d29
437        \add            q2,  q8,  q2
438        vrshl.s16       q2,  q2,  q9
439        \add            q3,  q8,  q3
440        vrshl.s16       q3,  q3,  q9
441        vqmovun.s16     d4,  q2
442        vqmovun.s16     d5,  q3
443        \add            q12, q8,  q12
444        vrshl.s16       q12, q12, q9
445        \add            q13, q8,  q13
446        vrshl.s16       q13, q13, q9
447        vqmovun.s16     d24, q12
448        vqmovun.s16     d25, q13
449        vst1.8          {d4- d5}, [r4,:128], r1
450        vst1.8          {d24-d25},[r4,:128], r1
451        bne             1b
452        pop             {r4, pc}
453.endm
454
455.macro  weight_8        add
456        vdup.8          d0,  r12
4571:      subs            r2,  r2,  #2
458        vld1.8          {d4},[r0,:64], r1
459        vmull.u8        q1,  d0,  d4
460        pld             [r0]
461        vld1.8          {d6},[r0,:64], r1
462        vmull.u8        q10, d0,  d6
463        \add            q1,  q8,  q1
464        pld             [r0]
465        vrshl.s16       q1,  q1,  q9
466        vqmovun.s16     d2,  q1
467        \add            q10, q8,  q10
468        vrshl.s16       q10, q10, q9
469        vqmovun.s16     d4,  q10
470        vst1.8          {d2},[r4,:64], r1
471        vst1.8          {d4},[r4,:64], r1
472        bne             1b
473        pop             {r4, pc}
474.endm
475
476.macro  weight_4        add
477        vdup.8          d0,  r12
478        vmov            q1,  q8
479        vmov            q10, q8
4801:      subs            r2,  r2,  #4
481        vld1.32         {d4[0]},[r0,:32], r1
482        vld1.32         {d4[1]},[r0,:32], r1
483        vmull.u8        q1,  d0,  d4
484        pld             [r0]
485        blt             2f
486        vld1.32         {d6[0]},[r0,:32], r1
487        vld1.32         {d6[1]},[r0,:32], r1
488        vmull.u8        q10, d0,  d6
489        pld             [r0]
490        \add            q1,  q8,  q1
491        vrshl.s16       q1,  q1,  q9
492        vqmovun.s16     d2,  q1
493        \add            q10, q8,  q10
494        vrshl.s16       q10, q10, q9
495        vqmovun.s16     d4,  q10
496        vmov            q10, q8
497        vst1.32         {d2[0]},[r4,:32], r1
498        vst1.32         {d2[1]},[r4,:32], r1
499        vmov            q1,  q8
500        vst1.32         {d4[0]},[r4,:32], r1
501        vst1.32         {d4[1]},[r4,:32], r1
502        bne             1b
503        pop             {r4, pc}
5042:      \add            q1,  q8,  q1
505        vrshl.s16       q1,  q1,  q9
506        vqmovun.s16     d2,  q1
507        vst1.32         {d2[0]},[r4,:32], r1
508        vst1.32         {d2[1]},[r4,:32], r1
509        pop             {r4, pc}
510.endm
511
512.macro  weight_func     w
513function ff_weight_h264_pixels_\w\()_neon, export=1
514        push            {r4, lr}
515        ldr             r12, [sp, #8]
516        ldr             r4,  [sp, #12]
517        cmp             r3,  #1
518        lsl             r4,  r4,  r3
519        vdup.16         q8,  r4
520        mov             r4,  r0
521        ble             20f
522        rsb             lr,  r3,  #1
523        vdup.16         q9,  lr
524        cmp             r12, #0
525        blt             10f
526        weight_\w       vhadd.s16
52710:     rsb             r12, r12, #0
528        weight_\w       vhsub.s16
52920:     rsb             lr,  r3,  #0
530        vdup.16         q9,  lr
531        cmp             r12, #0
532        blt             10f
533        weight_\w       vadd.s16
53410:     rsb             r12, r12, #0
535        weight_\w       vsub.s16
536endfunc
537.endm
538
539        weight_func     16
540        weight_func     8
541        weight_func     4
542