]> git.sesse.net Git - ffmpeg/blob - libavcodec/arm/hevcdsp_idct_neon.S
Merge commit 'b62ed6873821c8fce8f7e2c2927ae54f86afeb22'
[ffmpeg] / libavcodec / arm / hevcdsp_idct_neon.S
1 /*
2  * ARM NEON optimised IDCT functions for HEVC decoding
3  * Copyright (c) 2014 Seppo Tomperi <seppo.tomperi@vtt.fi>
4  * Copyright (c) 2017 Alexandra Hájková
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "libavutil/arm/asm.S"
24
25 const trans, align=4
26         .short 64, 83, 64, 36
27         .short 89, 75, 50, 18
28         .short 90, 87, 80, 70
29         .short 57, 43, 25, 9
30 endconst
31
32 function ff_hevc_idct_4x4_dc_neon_8, export=1
33         ldrsh       r1, [r0]
34         ldr         r2, =0x20
35         add         r1, #1
36         asr         r1, #1
37         add         r1, r2
38         asr         r1, #6
39         vdup.16     q0, r1
40         vdup.16     q1, r1
41         vst1.16     {q0, q1}, [r0]
42         bx lr
43 endfunc
44
45 function ff_hevc_idct_8x8_dc_neon_8, export=1
46         ldrsh       r1, [r0]
47         ldr         r2, =0x20
48         add         r1, #1
49         asr         r1, #1
50         add         r1, r2
51         asr         r1, #6
52         vdup.16     q8, r1
53         vdup.16     q9, r1
54         vmov.16     q10, q8
55         vmov.16     q11, q8
56         vmov.16     q12, q8
57         vmov.16     q13, q8
58         vmov.16     q14, q8
59         vmov.16     q15, q8
60         vstm        r0, {q8-q15}
61         bx lr
62 endfunc
63
64 function ff_hevc_idct_16x16_dc_neon_8, export=1
65         ldrsh       r1, [r0]
66         ldr         r2, =0x20
67         add         r1, #1
68         asr         r1, #1
69         add         r1, r2
70         asr         r1, #6
71         vdup.16     q8, r1
72         vdup.16     q9, r1
73         vmov.16     q10, q8
74         vmov.16     q11, q8
75         vmov.16     q12, q8
76         vmov.16     q13, q8
77         vmov.16     q14, q8
78         vmov.16     q15, q8
79         vstm        r0!, {q8-q15}
80         vstm        r0!, {q8-q15}
81         vstm        r0!, {q8-q15}
82         vstm        r0, {q8-q15}
83         bx lr
84 endfunc
85
86 function ff_hevc_idct_32x32_dc_neon_8, export=1
87         ldrsh       r1, [r0]
88         ldr         r2, =0x20
89         add         r1, #1
90         asr         r1, #1
91         add         r1, r2
92         asr         r1, #6
93         mov         r3, #16
94         vdup.16     q8, r1
95         vdup.16     q9, r1
96         vmov.16     q10, q8
97         vmov.16     q11, q8
98         vmov.16     q12, q8
99         vmov.16     q13, q8
100         vmov.16     q14, q8
101         vmov.16     q15, q8
102 1:      subs        r3, #1
103         vstm        r0!, {q8-q15}
104         bne         1b
105         bx lr
106 endfunc
107
108 function ff_hevc_add_residual_4x4_neon_8, export=1
109         vldm        r1, {q0-q1}
110         vld1.32     d4[0], [r0], r2
111         vld1.32     d4[1], [r0], r2
112         vld1.32     d5[0], [r0], r2
113         vld1.32     d5[1], [r0], r2
114         sub         r0, r0, r2, lsl #2
115         vmovl.u8    q8, d4
116         vmovl.u8    q9, d5
117         vqadd.s16   q0, q0, q8
118         vqadd.s16   q1, q1, q9
119         vqmovun.s16 d0, q0
120         vqmovun.s16 d1, q1
121         vst1.32     d0[0], [r0], r2
122         vst1.32     d0[1], [r0], r2
123         vst1.32     d1[0], [r0], r2
124         vst1.32     d1[1], [r0], r2
125         bx          lr
126 endfunc
127
128 function ff_hevc_add_residual_8x8_neon_8, export=1
129         mov         r3,   #8
130 1:      subs        r3,   #1
131         vld1.16     {q0}, [r1]!
132         vld1.8      d16,  [r0]
133         vmovl.u8    q8,   d16
134         vqadd.s16   q0,   q8
135         vqmovun.s16 d0,   q0
136         vst1.32     d0,   [r0], r2
137         bne         1b
138         bx          lr
139 endfunc
140
141 function ff_hevc_add_residual_16x16_neon_8, export=1
142         mov         r3,   #16
143 1:      subs        r3,   #1
144         vld1.16     {q0, q1}, [r1]!
145         vld1.8      {q8},  [r0]
146         vmovl.u8    q9,  d16
147         vmovl.u8    q10, d17
148         vqadd.s16   q0,  q9
149         vqadd.s16   q1,  q10
150         vqmovun.s16 d0,  q0
151         vqmovun.s16 d1,  q1
152         vst1.8      {q0},   [r0], r2
153         bne         1b
154         bx          lr
155 endfunc
156
157 function ff_hevc_add_residual_32x32_neon_8, export=1
158         mov         r3,   #32
159 1:      subs        r3,   #1
160         vldm        r1!, {q0-q3}
161         vld1.8      {q8, q9},  [r0]
162         vmovl.u8    q10, d16
163         vmovl.u8    q11, d17
164         vmovl.u8    q12, d18
165         vmovl.u8    q13, d19
166         vqadd.s16   q0,  q10
167         vqadd.s16   q1,  q11
168         vqadd.s16   q2,  q12
169         vqadd.s16   q3,  q13
170         vqmovun.s16 d0,  q0
171         vqmovun.s16 d1,  q1
172         vqmovun.s16 d2,  q2
173         vqmovun.s16 d3,  q3
174         vst1.8     {q0, q1},   [r0], r2
175         bne         1b
176         bx          lr
177 endfunc
178
179 /* uses registers q2 - q9 for temp values */
180 /* TODO: reorder */
181 .macro tr4_luma_shift r0, r1, r2, r3, shift
182         vaddl.s16   q5, \r0, \r2    // c0 = src0 + src2
183         vaddl.s16   q2, \r2, \r3    // c1 = src2 + src3
184         vsubl.s16   q4, \r0, \r3    // c2 = src0 - src3
185         vmull.s16   q6, \r1, d0[0]  // c3 = 74 * src1
186
187         vaddl.s16   q7, \r0, \r3    // src0 + src3
188         vsubw.s16   q7, q7, \r2     // src0 - src2 + src3
189         vmul.s32    q7, q7, d0[0]   // dst2 = 74 * (src0 - src2 + src3)
190
191         vmul.s32    q8, q5, d0[1]   // 29 * c0
192         vmul.s32    q9, q2, d1[0]   // 55 * c1
193         vadd.s32    q8, q9          // 29 * c0 + 55 * c1
194         vadd.s32    q8, q6          // dst0 = 29 * c0 + 55 * c1 + c3
195
196         vmul.s32    q2, q2, d0[1]   // 29 * c1
197         vmul.s32    q9, q4, d1[0]   // 55 * c2
198         vsub.s32    q9, q2          // 55 * c2 - 29 * c1
199         vadd.s32    q9, q6          // dst1 = 55 * c2 - 29 * c1 + c3
200
201         vmul.s32    q5, q5, d1[0]   // 55 * c0
202         vmul.s32    q4, q4, d0[1]   // 29 * c2
203         vadd.s32    q5, q4          // 55 * c0 + 29 * c2
204         vsub.s32    q5, q6          // dst3 = 55 * c0 + 29 * c2 - c3
205
206         vqrshrn.s32   \r0, q8, \shift
207         vqrshrn.s32   \r1, q9, \shift
208         vqrshrn.s32   \r2, q7, \shift
209         vqrshrn.s32   \r3, q5, \shift
210 .endm
211
212 function ff_hevc_transform_luma_4x4_neon_8, export=1
213         vpush       {d8-d15}
214         vld1.16     {q14, q15}, [r0]  // coeffs
215         ldr         r3, =0x4a  // 74
216         vmov.32     d0[0], r3
217         ldr         r3, =0x1d  // 29
218         vmov.32     d0[1], r3
219         ldr         r3, =0x37  // 55
220         vmov.32     d1[0], r3
221
222         tr4_luma_shift d28, d29, d30, d31, #7
223
224         vtrn.16     d28, d29
225         vtrn.16     d30, d31
226         vtrn.32     q14, q15
227
228         tr4_luma_shift d28, d29, d30, d31, #12
229
230         vtrn.16     d28, d29
231         vtrn.16     d30, d31
232         vtrn.32     q14, q15
233         vst1.16     {q14, q15}, [r0]
234         vpop        {d8-d15}
235         bx lr
236 endfunc
237
238 .macro sum_sub out, in, c, op
239   .ifc \op, +
240         vmlal.s16       \out, \in, \c
241   .else
242         vmlsl.s16       \out, \in, \c
243   .endif
244 .endm
245
246 .macro tr_4x4 in0, in1, in2, in3, out0, out1, out2, out3, shift, tmp0, tmp1, tmp2, tmp3, tmp4
247          vshll.s16      \tmp0, \in0, #6
248          vmull.s16      \tmp2, \in1, d4[1]
249          vmov           \tmp1, \tmp0
250          vmull.s16      \tmp3, \in1, d4[3]
251          vmlal.s16      \tmp0, \in2, d4[0] @e0
252          vmlsl.s16      \tmp1, \in2, d4[0] @e1
253          vmlal.s16      \tmp2, \in3, d4[3] @o0
254          vmlsl.s16      \tmp3, \in3, d4[1] @o1
255
256          vadd.s32       \tmp4, \tmp0, \tmp2
257          vsub.s32       \tmp0, \tmp0, \tmp2
258          vadd.s32       \tmp2, \tmp1, \tmp3
259          vsub.s32       \tmp1, \tmp1, \tmp3
260          vqrshrn.s32    \out0, \tmp4, #\shift
261          vqrshrn.s32    \out3, \tmp0, #\shift
262          vqrshrn.s32    \out1, \tmp2, #\shift
263          vqrshrn.s32    \out2, \tmp1, #\shift
264 .endm
265
266 .macro tr_4x4_8 in0, in1, in2, in3, out0, out1, out2, out3, tmp0, tmp1, tmp2, tmp3
267          vshll.s16      \tmp0, \in0, #6
268          vld1.s16       {\in0}, [r1, :64]!
269          vmov           \tmp1, \tmp0
270          vmull.s16      \tmp2, \in1, \in0[1]
271          vmull.s16      \tmp3, \in1, \in0[3]
272          vmlal.s16      \tmp0, \in2, \in0[0] @e0
273          vmlsl.s16      \tmp1, \in2, \in0[0] @e1
274          vmlal.s16      \tmp2, \in3, \in0[3] @o0
275          vmlsl.s16      \tmp3, \in3, \in0[1] @o1
276
277          vld1.s16       {\in0}, [r1, :64]
278
279          vadd.s32       \out0, \tmp0, \tmp2
280          vadd.s32       \out1, \tmp1, \tmp3
281          vsub.s32       \out2, \tmp1, \tmp3
282          vsub.s32       \out3, \tmp0, \tmp2
283
284          sub            r1,  r1,  #8
285 .endm
286
287 @ Do a 4x4 transpose, using q registers for the subtransposes that don't
288 @ need to address the indiviudal d registers.
289 @ r0,r1 == rq0, r2,r3 == rq1
290 .macro transpose_4x4 rq0, rq1, r0, r1, r2, r3
291         vtrn.32         \rq0, \rq1
292         vtrn.16         \r0,  \r1
293         vtrn.16         \r2,  \r3
294 .endm
295
296 .macro idct_4x4 bitdepth
297 function ff_hevc_idct_4x4_\bitdepth\()_neon, export=1
298 @r0 - coeffs
299         vld1.s16        {q0-q1}, [r0, :128]
300
301         movrel          r1, trans
302         vld1.s16        {d4}, [r1, :64]
303
304         tr_4x4          d0, d1, d2, d3, d16, d17, d18, d19, 7, q10, q11, q12, q13, q0
305         transpose_4x4   q8, q9, d16, d17, d18, d19
306
307         tr_4x4          d16, d17, d18, d19, d0, d1, d2, d3, 20 - \bitdepth, q10, q11, q12, q13, q0
308         transpose_4x4   q0, q1, d0, d1, d2, d3
309         vst1.s16        {d0-d3}, [r0, :128]
310         bx lr
311 endfunc
312 .endm
313
314 .macro transpose8_4x4 r0, r1, r2, r3
315         vtrn.16         \r0,  \r1
316         vtrn.16         \r2,  \r3
317         vtrn.32         \r0,  \r2
318         vtrn.32         \r1,  \r3
319 .endm
320
321 .macro transpose_8x8 r0, r1, r2, r3, r4, r5, r6, r7, l0, l1, l2, l3, l4, l5, l6, l7
322         transpose8_4x4  \r0, \r1, \r2, \r3
323         transpose8_4x4  \r4, \r5, \r6, \r7
324
325         transpose8_4x4  \l0, \l1, \l2, \l3
326         transpose8_4x4  \l4, \l5, \l6, \l7
327 .endm
328
329 .macro tr_8x4 shift, in0, in1, in2, in3, in4, in5, in6, in7
330         tr_4x4_8        \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15
331
332         vmull.s16       q14, \in1, \in0[2]
333         vmull.s16       q12, \in1, \in0[0]
334         vmull.s16       q13, \in1, \in0[1]
335         sum_sub         q14, \in3, \in0[0], -
336         sum_sub         q12, \in3, \in0[1], +
337         sum_sub         q13, \in3, \in0[3], -
338
339         sum_sub         q14, \in5, \in0[3], +
340         sum_sub         q12, \in5, \in0[2], +
341         sum_sub         q13, \in5, \in0[0], -
342
343         sum_sub         q14, \in7, \in0[1], +
344         sum_sub         q12, \in7, \in0[3], +
345         sum_sub         q13, \in7, \in0[2], -
346
347         vadd.s32        q15, q10, q14
348         vsub.s32        q10, q10, q14
349         vqrshrn.s32     \in2, q15, \shift
350
351         vmull.s16       q15, \in1, \in0[3]
352         sum_sub         q15, \in3, \in0[2], -
353         sum_sub         q15, \in5, \in0[1], +
354         sum_sub         q15, \in7, \in0[0], -
355
356         vqrshrn.s32     \in5, q10,  \shift
357
358         vadd.s32        q10, q8, q12
359         vsub.s32        q8,  q8, q12
360         vadd.s32        q12, q9, q13
361         vsub.s32        q9,  q9, q13
362         vadd.s32        q14, q11, q15
363         vsub.s32        q11, q11, q15
364
365         vqrshrn.s32     \in0, q10, \shift
366         vqrshrn.s32     \in7, q8,  \shift
367         vqrshrn.s32     \in1, q12, \shift
368         vqrshrn.s32     \in6, q9,  \shift
369         vqrshrn.s32     \in3, q14, \shift
370         vqrshrn.s32     \in4, q11, \shift
371 .endm
372
373 .macro idct_8x8 bitdepth
374 function ff_hevc_idct_8x8_\bitdepth\()_neon, export=1
375 @r0 - coeffs
376         vpush           {q4-q7}
377
378         mov             r1,  r0
379         mov             r2,  #64
380         add             r3,  r0,  #32
381         vld1.s16        {q0-q1}, [r1,:128], r2
382         vld1.s16        {q2-q3}, [r3,:128], r2
383         vld1.s16        {q4-q5}, [r1,:128], r2
384         vld1.s16        {q6-q7}, [r3,:128], r2
385
386         movrel          r1, trans
387
388         tr_8x4          7, d0, d2, d4, d6, d8, d10, d12, d14
389         tr_8x4          7, d1, d3, d5, d7, d9, d11, d13, d15
390
391         @ Transpose each 4x4 block, and swap how d4-d7 and d8-d11 are used.
392         @ Layout before:
393         @ d0  d1
394         @ d2  d3
395         @ d4  d5
396         @ d6  d7
397         @ d8  d9
398         @ d10 d11
399         @ d12 d13
400         @ d14 d15
401         transpose_8x8   d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
402         @ Now the layout is:
403         @ d0  d8
404         @ d2  d10
405         @ d4  d12
406         @ d6  d14
407         @ d1  d9
408         @ d3  d11
409         @ d5  d13
410         @ d7  d15
411
412         tr_8x4          20 - \bitdepth, d0, d2, d4, d6, d1, d3, d5, d7
413         vswp            d0, d8
414         tr_8x4          20 - \bitdepth, d0, d10, d12, d14, d9, d11, d13, d15
415         vswp            d0, d8
416
417         transpose_8x8   d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
418
419         mov             r1,  r0
420         mov             r2,  #64
421         add             r3,  r0,  #32
422         vst1.s16        {q0-q1}, [r1,:128], r2
423         vst1.s16        {q2-q3}, [r3,:128], r2
424         vst1.s16        {q4-q5}, [r1,:128], r2
425         vst1.s16        {q6-q7}, [r3,:128], r2
426
427         vpop            {q4-q7}
428         bx              lr
429 endfunc
430 .endm
431
432 idct_4x4 8
433 idct_4x4 10
434 idct_8x8 8
435 idct_8x8 10