]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/hevcdsp_init.c
vp9lpf/x86: make filter_16_h work on 32-bit.
[ffmpeg] / libavcodec / x86 / hevcdsp_init.c
1 /*
2  * Copyright (c) 2013 Seppo Tomperi
3  * Copyright (c) 2013 - 2014 Pierre-Edouard Lepere
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 "config.h"
23
24 #include "libavutil/cpu.h"
25 #include "libavutil/x86/cpu.h"
26
27 #include "libavcodec/hevcdsp.h"
28
29 #define LFC_FUNC(DIR, DEPTH, OPT) \
30 void ff_hevc_ ## DIR ## _loop_filter_chroma_ ## DEPTH ## _ ## OPT(uint8_t *pix, ptrdiff_t stride, int *tc, uint8_t *no_p, uint8_t *no_q);
31
32 #define LFL_FUNC(DIR, DEPTH, OPT) \
33 void ff_hevc_ ## DIR ## _loop_filter_luma_ ## DEPTH ## _ ## OPT(uint8_t *pix, ptrdiff_t stride, int beta, int *tc, uint8_t *no_p, uint8_t *no_q);
34
35 #define LFC_FUNCS(type, depth) \
36     LFC_FUNC(h, depth, sse2)   \
37     LFC_FUNC(v, depth, sse2)
38
39 #define LFL_FUNCS(type, depth) \
40     LFL_FUNC(h, depth, ssse3)  \
41     LFL_FUNC(v, depth, ssse3)
42
43 LFC_FUNCS(uint8_t, 8)
44 LFC_FUNCS(uint8_t, 10)
45 LFL_FUNCS(uint8_t, 8)
46 LFL_FUNCS(uint8_t, 10)
47
48 #define idct_dc_proto(size, bitd, opt) \
49                 void ff_hevc_idct_ ## size ## _dc_add_ ## bitd ## _ ## opt(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
50
51 idct_dc_proto(4, 8,mmxext);
52 idct_dc_proto(8, 8,mmxext);
53 idct_dc_proto(16,8,  sse2);
54 idct_dc_proto(32,8,  sse2);
55
56 idct_dc_proto(32,8,  avx2);
57
58 idct_dc_proto(4, 10,mmxext);
59 idct_dc_proto(8, 10,  sse2);
60 idct_dc_proto(16,10,  sse2);
61 idct_dc_proto(32,10,  sse2);
62 idct_dc_proto(8, 10,   avx);
63 idct_dc_proto(16,10,   avx);
64 idct_dc_proto(32,10,   avx);
65
66 idct_dc_proto(16,10,  avx2);
67 idct_dc_proto(32,10,  avx2);
68
69 #define IDCT_FUNCS(W, opt) \
70 void ff_hevc_idct_ ## W ## _dc_8_ ## opt(int16_t *coeffs); \
71 void ff_hevc_idct_ ## W ## _dc_10_ ## opt(int16_t *coeffs)
72
73 IDCT_FUNCS(4x4,   mmxext);
74 IDCT_FUNCS(8x8,   mmxext);
75 IDCT_FUNCS(8x8,   sse2);
76 IDCT_FUNCS(16x16, sse2);
77 IDCT_FUNCS(32x32, sse2);
78 IDCT_FUNCS(16x16, avx2);
79 IDCT_FUNCS(32x32, avx2);
80
81 #define GET_PIXELS(width, depth, cf)                                                                      \
82 void ff_hevc_get_pixels_ ## width ## _ ## depth ## _ ## cf(int16_t *dst, ptrdiff_t dststride,             \
83                                                            uint8_t *src, ptrdiff_t srcstride,             \
84                                                            int height, int mx, int my, int16_t *mcbuffer);
85
86 GET_PIXELS(4,  8, sse2)
87 GET_PIXELS(8,  8, sse2)
88 GET_PIXELS(12, 8, sse2)
89 GET_PIXELS(16, 8, sse2)
90 GET_PIXELS(24, 8, sse2)
91 GET_PIXELS(32, 8, sse2)
92 GET_PIXELS(48, 8, sse2)
93 GET_PIXELS(64, 8, sse2)
94
95 GET_PIXELS(4,  10, sse2)
96 GET_PIXELS(8,  10, sse2)
97 GET_PIXELS(12, 10, sse2)
98 GET_PIXELS(16, 10, sse2)
99 GET_PIXELS(24, 10, sse2)
100 GET_PIXELS(32, 10, sse2)
101 GET_PIXELS(48, 10, sse2)
102 GET_PIXELS(64, 10, sse2)
103
104 /* those are independent of the bit depth, so declared separately */
105 #define INTERP_HV_FUNC(width, cf)                                                         \
106 void ff_hevc_qpel_hv_ ## width ## _ ## cf(int16_t *dst, ptrdiff_t dststride,              \
107                                           int16_t *src, ptrdiff_t srcstride,              \
108                                           int height, int mx, int my, int16_t *mcbuffer); \
109 void ff_hevc_epel_hv_ ## width ## _ ## cf(int16_t *dst, ptrdiff_t dststride,              \
110                                           int16_t *src, ptrdiff_t srcstride,              \
111                                           int height, int mx, int my, int16_t *mcbuffer);
112
113 INTERP_HV_FUNC(4,  avx)
114 INTERP_HV_FUNC(8,  avx)
115 INTERP_HV_FUNC(12, avx)
116 INTERP_HV_FUNC(16, avx)
117 INTERP_HV_FUNC(24, avx)
118 INTERP_HV_FUNC(32, avx)
119 INTERP_HV_FUNC(48, avx)
120 INTERP_HV_FUNC(64, avx)
121
122 #if ARCH_X86_64 && HAVE_AVX_EXTERNAL
123 #define QPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv)                                                         \
124 static void hevc_qpel_hv_ ## width ## _ ## depth ## _ ## cf_hv(int16_t *dst, ptrdiff_t dststride,             \
125                                                                uint8_t *src, ptrdiff_t srcstride,             \
126                                                                int height, int mx, int my, int16_t *mcbuffer) \
127 {                                                                                                             \
128     const ptrdiff_t stride = FFALIGN(width + 7, 8);                                                           \
129     ff_hevc_qpel_h_ ## width ## _ ## depth ## _ ## cf_h(mcbuffer, 2 * stride, src - 3 * srcstride, srcstride, \
130                                                         height + 7, mx, my, mcbuffer);                        \
131     ff_hevc_qpel_hv_ ## width ## _ ## cf_hv(dst, dststride, mcbuffer + 3 * stride, 2 * stride,                \
132                                             height, mx, my, mcbuffer);                                        \
133 }
134 #else
135 #define QPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv)
136 #endif /* ARCH_X86_64 && HAVE_AVX_EXTERNAL */
137
138 #define QPEL_FUNCS(width, depth, cf_h, cf_v, cf_hv)                                                           \
139 void ff_hevc_qpel_h_ ## width ## _ ## depth ## _ ## cf_h(int16_t *dst, ptrdiff_t dststride,                   \
140                                                          uint8_t *src, ptrdiff_t srcstride,                   \
141                                                          int height, int mx, int my, int16_t *mcbuffer);      \
142 void ff_hevc_qpel_v_ ## width ## _ ## depth ## _ ## cf_v(int16_t *dst, ptrdiff_t dststride,                   \
143                                                          uint8_t *src, ptrdiff_t srcstride,                   \
144                                                          int height, int mx, int my, int16_t *mcbuffer);      \
145 QPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv)
146
147 QPEL_FUNCS(4,  8, ssse3, ssse3, avx)
148 QPEL_FUNCS(8,  8, ssse3, ssse3, avx)
149 QPEL_FUNCS(12, 8, ssse3, ssse3, avx)
150 QPEL_FUNCS(16, 8, ssse3, ssse3, avx)
151 QPEL_FUNCS(24, 8, ssse3, ssse3, avx)
152 QPEL_FUNCS(32, 8, ssse3, ssse3, avx)
153 QPEL_FUNCS(48, 8, ssse3, ssse3, avx)
154 QPEL_FUNCS(64, 8, ssse3, ssse3, avx)
155
156 QPEL_FUNCS(4,  10, avx, avx, avx)
157 QPEL_FUNCS(8,  10, avx, avx, avx)
158 QPEL_FUNCS(12, 10, avx, avx, avx)
159 QPEL_FUNCS(16, 10, avx, avx, avx)
160 QPEL_FUNCS(24, 10, avx, avx, avx)
161 QPEL_FUNCS(32, 10, avx, avx, avx)
162 QPEL_FUNCS(48, 10, avx, avx, avx)
163 QPEL_FUNCS(64, 10, avx, avx, avx)
164
165 #if ARCH_X86_64 && HAVE_AVX_EXTERNAL
166 #define EPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv)                                                         \
167 static void hevc_epel_hv_ ## width ## _ ## depth ## _ ## cf_hv(int16_t *dst, ptrdiff_t dststride,             \
168                                                                uint8_t *src, ptrdiff_t srcstride,             \
169                                                                int height, int mx, int my, int16_t *mcbuffer) \
170 {                                                                                                             \
171     const ptrdiff_t stride = FFALIGN(width + 3, 8);                                                           \
172     ff_hevc_epel_h_ ## width ## _ ## depth ## _ ## cf_h(mcbuffer, 2 * stride, src - srcstride, srcstride,     \
173                                                         height + 3, mx, my, mcbuffer);                        \
174     ff_hevc_epel_hv_ ## width ## _ ## cf_hv(dst, dststride, mcbuffer + stride, 2 * stride,                    \
175                                             height, mx, my, mcbuffer);                                        \
176 }
177 #else
178 #define EPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv)
179 #endif /* ARCH_X86_64 && HAVE_AVX_EXTERNAL */
180
181 #define EPEL_FUNCS(width, depth, cf_h, cf_v, cf_hv)                                                           \
182 void ff_hevc_epel_h_ ## width ## _ ## depth ## _ ## cf_h(int16_t *dst, ptrdiff_t dststride,                   \
183                                                          uint8_t *src, ptrdiff_t srcstride,                   \
184                                                          int height, int mx, int my, int16_t *mcbuffer);      \
185 void ff_hevc_epel_v_ ## width ## _ ## depth ## _ ## cf_v(int16_t *dst, ptrdiff_t dststride,                   \
186                                                          uint8_t *src, ptrdiff_t srcstride,                   \
187                                                          int height, int mx, int my, int16_t *mcbuffer);      \
188 EPEL_FUNC_HV(width, depth, cf_h, cf_v, cf_hv)
189
190 EPEL_FUNCS(4,  8, ssse3, ssse3, avx)
191 EPEL_FUNCS(8,  8, ssse3, ssse3, avx)
192 EPEL_FUNCS(12, 8, ssse3, ssse3, avx)
193 EPEL_FUNCS(16, 8, ssse3, ssse3, avx)
194 EPEL_FUNCS(24, 8, ssse3, ssse3, avx)
195 EPEL_FUNCS(32, 8, ssse3, ssse3, avx)
196
197 EPEL_FUNCS(4,  10, avx, avx, avx)
198 EPEL_FUNCS(8,  10, avx, avx, avx)
199 EPEL_FUNCS(12, 10, avx, avx, avx)
200 EPEL_FUNCS(16, 10, avx, avx, avx)
201 EPEL_FUNCS(24, 10, avx, avx, avx)
202 EPEL_FUNCS(32, 10, avx, avx, avx)
203
204 #define PUT_PRED(width, depth, cf_uw, cf_w) \
205 void ff_hevc_put_unweighted_pred_ ## width ## _ ## depth ## _ ## cf_uw(uint8_t *dst, ptrdiff_t dststride,                   \
206                                                                        int16_t *src, ptrdiff_t srcstride,                   \
207                                                                        int height);                                         \
208 void ff_hevc_put_unweighted_pred_avg_ ## width ## _ ## depth ## _ ## cf_uw(uint8_t *dst, ptrdiff_t dststride,               \
209                                                                            int16_t *src1, int16_t *src2,                    \
210                                                                            ptrdiff_t srcstride, int height);                \
211 void ff_hevc_put_weighted_pred_ ## width ## _ ## depth ## _ ## cf_w(uint8_t denom, int16_t weight, int16_t offset,          \
212                                                                     uint8_t *dst, ptrdiff_t dststride,                      \
213                                                                     int16_t *src, ptrdiff_t srcstride,                      \
214                                                                     int height);                                            \
215 void ff_hevc_put_weighted_pred_avg_ ## width ## _ ## depth ## _ ## cf_w(uint8_t denom, int16_t weight0, int16_t weight1,    \
216                                                                         int16_t offset0, int16_t offset1,                   \
217                                                                         uint8_t *dst, ptrdiff_t dststride,                  \
218                                                                         int16_t *src0, int16_t *src1, ptrdiff_t srcstride,  \
219                                                                         int height);
220
221 PUT_PRED(4,  8, sse2, sse4)
222 PUT_PRED(8,  8, sse2, sse4)
223 PUT_PRED(12, 8, sse2, sse4)
224 PUT_PRED(16, 8, sse2, sse4)
225 PUT_PRED(24, 8, sse2, sse4)
226 PUT_PRED(32, 8, sse2, sse4)
227 PUT_PRED(48, 8, sse2, sse4)
228 PUT_PRED(64, 8, sse2, sse4)
229
230 PUT_PRED(4,  10, sse2, sse4)
231 PUT_PRED(8,  10, sse2, sse4)
232 PUT_PRED(12, 10, sse2, sse4)
233 PUT_PRED(16, 10, sse2, sse4)
234 PUT_PRED(24, 10, sse2, sse4)
235 PUT_PRED(32, 10, sse2, sse4)
236 PUT_PRED(48, 10, sse2, sse4)
237 PUT_PRED(64, 10, sse2, sse4)
238
239 void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth)
240 {
241     int cpu_flags = av_get_cpu_flags();
242
243 #define SET_LUMA_FUNCS(tabname, funcname, depth, cf)      \
244     c->tabname[0] = funcname ## _4_  ## depth ## _ ## cf; \
245     c->tabname[1] = funcname ## _8_  ## depth ## _ ## cf; \
246     c->tabname[2] = funcname ## _12_ ## depth ## _ ## cf; \
247     c->tabname[3] = funcname ## _16_ ## depth ## _ ## cf; \
248     c->tabname[4] = funcname ## _24_ ## depth ## _ ## cf; \
249     c->tabname[5] = funcname ## _32_ ## depth ## _ ## cf; \
250     c->tabname[6] = funcname ## _48_ ## depth ## _ ## cf; \
251     c->tabname[7] = funcname ## _64_ ## depth ## _ ## cf;
252
253 #define SET_CHROMA_FUNCS(tabname, funcname, depth, cf)    \
254     c->tabname[1] = funcname ## _4_  ## depth ## _ ## cf; \
255     c->tabname[3] = funcname ## _8_  ## depth ## _ ## cf; \
256     c->tabname[4] = funcname ## _12_ ## depth ## _ ## cf; \
257     c->tabname[5] = funcname ## _16_ ## depth ## _ ## cf; \
258     c->tabname[6] = funcname ## _24_ ## depth ## _ ## cf; \
259     c->tabname[7] = funcname ## _32_ ## depth ## _ ## cf;
260
261 #define SET_QPEL_FUNCS(v, h, depth, cf, name) SET_LUMA_FUNCS  (put_hevc_qpel[v][h], name, depth, cf)
262 #define SET_EPEL_FUNCS(v, h, depth, cf, name) SET_CHROMA_FUNCS(put_hevc_epel[v][h], name, depth, cf)
263
264     if (bit_depth == 8) {
265         if (EXTERNAL_MMXEXT(cpu_flags)) {
266             c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_mmxext;
267             c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_mmxext;
268         }
269         if (EXTERNAL_SSE2(cpu_flags)) {
270             c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_8_sse2;
271             c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_8_sse2;
272
273             c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_sse2;
274             c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_sse2;
275             c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_sse2;
276             SET_QPEL_FUNCS(0, 0, 8, sse2, ff_hevc_get_pixels);
277             SET_EPEL_FUNCS(0, 0, 8, sse2, ff_hevc_get_pixels);
278
279             SET_LUMA_FUNCS(put_unweighted_pred,              ff_hevc_put_unweighted_pred,     8, sse2);
280             SET_LUMA_FUNCS(put_unweighted_pred_avg,          ff_hevc_put_unweighted_pred_avg, 8, sse2);
281             SET_CHROMA_FUNCS(put_unweighted_pred_chroma,     ff_hevc_put_unweighted_pred,     8, sse2);
282             SET_CHROMA_FUNCS(put_unweighted_pred_avg_chroma, ff_hevc_put_unweighted_pred_avg, 8, sse2);
283         }
284         if (EXTERNAL_SSSE3(cpu_flags)) {
285             SET_QPEL_FUNCS(0, 1, 8, ssse3, ff_hevc_qpel_h);
286             SET_QPEL_FUNCS(1, 0, 8, ssse3, ff_hevc_qpel_v);
287             SET_EPEL_FUNCS(0, 1, 8, ssse3, ff_hevc_epel_h);
288             SET_EPEL_FUNCS(1, 0, 8, ssse3, ff_hevc_epel_v);
289
290         }
291     } else if (bit_depth == 10) {
292         if (EXTERNAL_MMXEXT(cpu_flags)) {
293             c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_mmxext;
294             c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_mmxext;
295         }
296         if (EXTERNAL_SSE2(cpu_flags)) {
297             c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_10_sse2;
298             c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_10_sse2;
299
300             c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_sse2;
301             c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_sse2;
302             c->idct_dc[3] = ff_hevc_idct_32x32_dc_10_sse2;
303
304             SET_QPEL_FUNCS(0, 0, 10, sse2, ff_hevc_get_pixels);
305             SET_EPEL_FUNCS(0, 0, 10, sse2, ff_hevc_get_pixels);
306
307             SET_LUMA_FUNCS(put_unweighted_pred,              ff_hevc_put_unweighted_pred,     10, sse2);
308             SET_LUMA_FUNCS(put_unweighted_pred_avg,          ff_hevc_put_unweighted_pred_avg, 10, sse2);
309             SET_CHROMA_FUNCS(put_unweighted_pred_chroma,     ff_hevc_put_unweighted_pred,     10, sse2);
310             SET_CHROMA_FUNCS(put_unweighted_pred_avg_chroma, ff_hevc_put_unweighted_pred_avg, 10, sse2);
311         }
312     }
313
314 #if ARCH_X86_64
315     if (bit_depth == 8) {
316         if (EXTERNAL_SSSE3(cpu_flags)) {
317             c->hevc_v_loop_filter_luma = ff_hevc_v_loop_filter_luma_8_ssse3;
318             c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_8_ssse3;
319         }
320
321         if (EXTERNAL_SSE4(cpu_flags)) {
322             SET_LUMA_FUNCS(weighted_pred,              ff_hevc_put_weighted_pred,     8, sse4);
323             SET_CHROMA_FUNCS(weighted_pred_chroma,     ff_hevc_put_weighted_pred,     8, sse4);
324             SET_LUMA_FUNCS(weighted_pred_avg,          ff_hevc_put_weighted_pred_avg, 8, sse4);
325             SET_CHROMA_FUNCS(weighted_pred_avg_chroma, ff_hevc_put_weighted_pred_avg, 8, sse4);
326         }
327
328         if (EXTERNAL_AVX(cpu_flags)) {
329 #if HAVE_AVX_EXTERNAL
330             SET_QPEL_FUNCS(1, 1, 8, avx, hevc_qpel_hv);
331             SET_EPEL_FUNCS(1, 1, 8, avx, hevc_epel_hv);
332 #endif /* HAVE_AVX_EXTERNAL */
333         }
334         if (EXTERNAL_AVX2(cpu_flags)) {
335             c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_avx2;
336             c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_avx2;
337         }
338     } else if (bit_depth == 10) {
339         if (EXTERNAL_SSSE3(cpu_flags)) {
340             c->hevc_v_loop_filter_luma = ff_hevc_v_loop_filter_luma_10_ssse3;
341             c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_10_ssse3;
342         }
343         if (EXTERNAL_SSE4(cpu_flags)) {
344             SET_LUMA_FUNCS(weighted_pred,              ff_hevc_put_weighted_pred,     10, sse4);
345             SET_CHROMA_FUNCS(weighted_pred_chroma,     ff_hevc_put_weighted_pred,     10, sse4);
346             SET_LUMA_FUNCS(weighted_pred_avg,          ff_hevc_put_weighted_pred_avg, 10, sse4);
347             SET_CHROMA_FUNCS(weighted_pred_avg_chroma, ff_hevc_put_weighted_pred_avg, 10, sse4);
348         }
349         if (EXTERNAL_AVX(cpu_flags)) {
350 #if HAVE_AVX_EXTERNAL
351             SET_QPEL_FUNCS(0, 1, 10, avx, ff_hevc_qpel_h);
352             SET_QPEL_FUNCS(1, 0, 10, avx, ff_hevc_qpel_v);
353             SET_QPEL_FUNCS(1, 1, 10, avx, hevc_qpel_hv);
354             SET_EPEL_FUNCS(0, 1, 10, avx, ff_hevc_epel_h);
355             SET_EPEL_FUNCS(1, 0, 10, avx, ff_hevc_epel_v);
356             SET_EPEL_FUNCS(1, 1, 10, avx, hevc_epel_hv);
357 #endif /* HAVE_AVX_EXTERNAL */
358         }
359         if (EXTERNAL_AVX2(cpu_flags)) {
360             c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_avx2;
361             c->idct_dc[3] = ff_hevc_idct_32x32_dc_10_avx2;
362         }
363     }
364 #endif /* ARCH_X86_64 */
365 }