hevc: Add NEON 4x4 and 8x8 IDCT
[ffmpeg.git] / libavcodec / arm / hevc_idct.S
1 /*
2  * ARM NEON optimised IDCT functions for HEVC decoding
3  * Copyright (c) 2017 Alexandra Hájková
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavutil/arm/asm.S"
23
24 const trans, align=4
25         .short 64, 83, 64, 36
26         .short 89, 75, 50, 18
27         .short 90, 87, 80, 70
28         .short 57, 43, 25, 9
29 endconst
30
31 .macro sum_sub out, in, c, op
32   .ifc \op, +
33         vmlal.s16       \out, \in, \c
34   .else
35         vmlsl.s16       \out, \in, \c
36   .endif
37 .endm
38
39 .macro tr_4x4 in0, in1, in2, in3, out0, out1, out2, out3, shift, tmp0, tmp1, tmp2, tmp3, tmp4
40          vshll.s16      \tmp0, \in0, #6
41          vmull.s16      \tmp2, \in1, d4[1]
42          vmov           \tmp1, \tmp0
43          vmull.s16      \tmp3, \in1, d4[3]
44          vmlal.s16      \tmp0, \in2, d4[0] @e0
45          vmlsl.s16      \tmp1, \in2, d4[0] @e1
46          vmlal.s16      \tmp2, \in3, d4[3] @o0
47          vmlsl.s16      \tmp3, \in3, d4[1] @o1
48
49          vadd.s32       \tmp4, \tmp0, \tmp2
50          vsub.s32       \tmp0, \tmp0, \tmp2
51          vadd.s32       \tmp2, \tmp1, \tmp3
52          vsub.s32       \tmp1, \tmp1, \tmp3
53          vqrshrn.s32    \out0, \tmp4, #\shift
54          vqrshrn.s32    \out3, \tmp0, #\shift
55          vqrshrn.s32    \out1, \tmp2, #\shift
56          vqrshrn.s32    \out2, \tmp1, #\shift
57 .endm
58
59 .macro tr_4x4_8 in0, in1, in2, in3, out0, out1, out2, out3, tmp0, tmp1, tmp2, tmp3
60          vshll.s16      \tmp0, \in0, #6
61          vld1.s16       {\in0}, [r1, :64]!
62          vmov           \tmp1, \tmp0
63          vmull.s16      \tmp2, \in1, \in0[1]
64          vmull.s16      \tmp3, \in1, \in0[3]
65          vmlal.s16      \tmp0, \in2, \in0[0] @e0
66          vmlsl.s16      \tmp1, \in2, \in0[0] @e1
67          vmlal.s16      \tmp2, \in3, \in0[3] @o0
68          vmlsl.s16      \tmp3, \in3, \in0[1] @o1
69
70          vld1.s16       {\in0}, [r1, :64]
71
72          vadd.s32       \out0, \tmp0, \tmp2
73          vadd.s32       \out1, \tmp1, \tmp3
74          vsub.s32       \out2, \tmp1, \tmp3
75          vsub.s32       \out3, \tmp0, \tmp2
76
77          sub            r1,  r1,  #8
78 .endm
79
80 @ Do a 4x4 transpose, using q registers for the subtransposes that don't
81 @ need to address the indiviudal d registers.
82 @ r0,r1 == rq0, r2,r3 == rq1
83 .macro transpose_4x4 rq0, rq1, r0, r1, r2, r3
84         vtrn.32         \rq0, \rq1
85         vtrn.16         \r0,  \r1
86         vtrn.16         \r2,  \r3
87 .endm
88
89 .macro idct_4x4 bitdepth
90 function ff_hevc_idct_4x4_\bitdepth\()_neon, export=1
91 @r0 - coeffs
92         vld1.s16        {q0-q1}, [r0, :128]
93
94         movrel          r1, trans
95         vld1.s16        {d4}, [r1, :64]
96
97         tr_4x4          d0, d1, d2, d3, d16, d17, d18, d19, 7, q10, q11, q12, q13, q0
98         transpose_4x4   q8, q9, d16, d17, d18, d19
99
100         tr_4x4          d16, d17, d18, d19, d0, d1, d2, d3, 20 - \bitdepth, q10, q11, q12, q13, q0
101         transpose_4x4   q0, q1, d0, d1, d2, d3
102         vst1.s16        {d0-d3}, [r0, :128]
103         bx lr
104 endfunc
105 .endm
106
107 .macro transpose8_4x4 r0, r1, r2, r3
108         vtrn.16         \r0,  \r1
109         vtrn.16         \r2,  \r3
110         vtrn.32         \r0,  \r2
111         vtrn.32         \r1,  \r3
112 .endm
113
114 .macro transpose_8x8 r0, r1, r2, r3, r4, r5, r6, r7, l0, l1, l2, l3, l4, l5, l6, l7
115         transpose8_4x4  \r0, \r1, \r2, \r3
116         transpose8_4x4  \r4, \r5, \r6, \r7
117
118         transpose8_4x4  \l0, \l1, \l2, \l3
119         transpose8_4x4  \l4, \l5, \l6, \l7
120 .endm
121
122 .macro tr_8x4 shift, in0, in1, in2, in3, in4, in5, in6, in7
123         tr_4x4_8        \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15
124
125         vmull.s16       q14, \in1, \in0[2]
126         vmull.s16       q12, \in1, \in0[0]
127         vmull.s16       q13, \in1, \in0[1]
128         sum_sub         q14, \in3, \in0[0], -
129         sum_sub         q12, \in3, \in0[1], +
130         sum_sub         q13, \in3, \in0[3], -
131
132         sum_sub         q14, \in5, \in0[3], +
133         sum_sub         q12, \in5, \in0[2], +
134         sum_sub         q13, \in5, \in0[0], -
135
136         sum_sub         q14, \in7, \in0[1], +
137         sum_sub         q12, \in7, \in0[3], +
138         sum_sub         q13, \in7, \in0[2], -
139
140         vadd.s32        q15, q10, q14
141         vsub.s32        q10, q10, q14
142         vqrshrn.s32     \in2, q15, \shift
143
144         vmull.s16       q15, \in1, \in0[3]
145         sum_sub         q15, \in3, \in0[2], -
146         sum_sub         q15, \in5, \in0[1], +
147         sum_sub         q15, \in7, \in0[0], -
148
149         vqrshrn.s32     \in5, q10,  \shift
150
151         vadd.s32        q10, q8, q12
152         vsub.s32        q8,  q8, q12
153         vadd.s32        q12, q9, q13
154         vsub.s32        q9,  q9, q13
155         vadd.s32        q14, q11, q15
156         vsub.s32        q11, q11, q15
157
158         vqrshrn.s32     \in0, q10, \shift
159         vqrshrn.s32     \in7, q8,  \shift
160         vqrshrn.s32     \in1, q12, \shift
161         vqrshrn.s32     \in6, q9,  \shift
162         vqrshrn.s32     \in3, q14, \shift
163         vqrshrn.s32     \in4, q11, \shift
164 .endm
165
166 .macro idct_8x8 bitdepth
167 function ff_hevc_idct_8x8_\bitdepth\()_neon, export=1
168 @r0 - coeffs
169         vpush           {q4-q7}
170
171         mov             r1,  r0
172         mov             r2,  #64
173         add             r3,  r0,  #32
174         vld1.s16        {q0-q1}, [r1,:128], r2
175         vld1.s16        {q2-q3}, [r3,:128], r2
176         vld1.s16        {q4-q5}, [r1,:128], r2
177         vld1.s16        {q6-q7}, [r3,:128], r2
178
179         movrel          r1, trans
180
181         tr_8x4          7, d0, d2, d4, d6, d8, d10, d12, d14
182         tr_8x4          7, d1, d3, d5, d7, d9, d11, d13, d15
183
184         @ Transpose each 4x4 block, and swap how d4-d7 and d8-d11 are used.
185         @ Layout before:
186         @ d0  d1
187         @ d2  d3
188         @ d4  d5
189         @ d6  d7
190         @ d8  d9
191         @ d10 d11
192         @ d12 d13
193         @ d14 d15
194         transpose_8x8   d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
195         @ Now the layout is:
196         @ d0  d8
197         @ d2  d10
198         @ d4  d12
199         @ d6  d14
200         @ d1  d9
201         @ d3  d11
202         @ d5  d13
203         @ d7  d15
204
205         tr_8x4          20 - \bitdepth, d0, d2, d4, d6, d1, d3, d5, d7
206         vswp            d0, d8
207         tr_8x4          20 - \bitdepth, d0, d10, d12, d14, d9, d11, d13, d15
208         vswp            d0, d8
209
210         transpose_8x8   d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15
211
212         mov             r1,  r0
213         mov             r2,  #64
214         add             r3,  r0,  #32
215         vst1.s16        {q0-q1}, [r1,:128], r2
216         vst1.s16        {q2-q3}, [r3,:128], r2
217         vst1.s16        {q4-q5}, [r1,:128], r2
218         vst1.s16        {q6-q7}, [r3,:128], r2
219
220         vpop            {q4-q7}
221         bx              lr
222 endfunc
223 .endm
224
225 idct_4x4 8
226 idct_4x4 10
227 idct_8x8 8
228 idct_8x8 10