]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/dsputilenc_mmx.c
avformat/hlsenc: correctly compute target duration
[ffmpeg] / libavcodec / x86 / dsputilenc_mmx.c
1 /*
2  * MMX optimized DSP utils
3  * Copyright (c) 2000, 2001 Fabrice Bellard
4  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
5  *
6  * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24
25 #include "libavutil/attributes.h"
26 #include "libavutil/cpu.h"
27 #include "libavutil/x86/asm.h"
28 #include "libavutil/x86/cpu.h"
29 #include "libavcodec/dsputil.h"
30 #include "libavcodec/mpegvideo.h"
31 #include "dsputil_x86.h"
32
33 void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size);
34 void ff_get_pixels_sse2(int16_t *block, const uint8_t *pixels, int line_size);
35 void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2,
36                         int stride);
37 void ff_diff_pixels_sse2(int16_t *block, const uint8_t *s1, const uint8_t *s2,
38                          int stride);
39 int ff_sum_abs_dctelem_mmx(int16_t *block);
40 int ff_sum_abs_dctelem_mmxext(int16_t *block);
41 int ff_sum_abs_dctelem_sse2(int16_t *block);
42 int ff_sum_abs_dctelem_ssse3(int16_t *block);
43 int ff_sse8_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
44                 int line_size, int h);
45 int ff_sse16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
46                  int line_size, int h);
47 int ff_sse16_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
48                   int line_size, int h);
49 int ff_hf_noise8_mmx(uint8_t *pix1, int lsize, int h);
50 int ff_hf_noise16_mmx(uint8_t *pix1, int lsize, int h);
51
52 #define hadamard_func(cpu)                                              \
53     int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1,     \
54                                   uint8_t *src2, int stride, int h);    \
55     int ff_hadamard8_diff16_ ## cpu(MpegEncContext *s, uint8_t *src1,   \
56                                     uint8_t *src2, int stride, int h);
57
58 hadamard_func(mmx)
59 hadamard_func(mmxext)
60 hadamard_func(sse2)
61 hadamard_func(ssse3)
62
63 #if HAVE_YASM
64
65 static int nsse16_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2,
66                       int line_size, int h)
67 {
68     int score1, score2;
69
70     if (c)
71         score1 = c->dsp.sse[0](c, pix1, pix2, line_size, h);
72     else
73         score1 = ff_sse16_mmx(c, pix1, pix2, line_size, h);
74     score2 = ff_hf_noise16_mmx(pix1, line_size, h) + ff_hf_noise8_mmx(pix1+8, line_size, h)
75            - ff_hf_noise16_mmx(pix2, line_size, h) - ff_hf_noise8_mmx(pix2+8, line_size, h);
76
77     if (c)
78         return score1 + FFABS(score2) * c->avctx->nsse_weight;
79     else
80         return score1 + FFABS(score2) * 8;
81 }
82
83 static int nsse8_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2,
84                      int line_size, int h)
85 {
86     int score1 = ff_sse8_mmx(c, pix1, pix2, line_size, h);
87     int score2 = ff_hf_noise8_mmx(pix1, line_size, h) -
88                  ff_hf_noise8_mmx(pix2, line_size, h);
89
90     if (c)
91         return score1 + FFABS(score2) * c->avctx->nsse_weight;
92     else
93         return score1 + FFABS(score2) * 8;
94 }
95
96 #endif /* HAVE_YASM */
97
98 #if HAVE_INLINE_ASM
99
100 static int vsad_intra16_mmx(MpegEncContext *v, uint8_t *pix, uint8_t *dummy,
101                             int line_size, int h)
102 {
103     int tmp;
104
105     av_assert2((((int) pix) & 7) == 0);
106     av_assert2((line_size & 7) == 0);
107
108 #define SUM(in0, in1, out0, out1)               \
109     "movq (%0), %%mm2\n"                        \
110     "movq 8(%0), %%mm3\n"                       \
111     "add %2,%0\n"                               \
112     "movq %%mm2, " #out0 "\n"                   \
113     "movq %%mm3, " #out1 "\n"                   \
114     "psubusb " #in0 ", %%mm2\n"                 \
115     "psubusb " #in1 ", %%mm3\n"                 \
116     "psubusb " #out0 ", " #in0 "\n"             \
117     "psubusb " #out1 ", " #in1 "\n"             \
118     "por %%mm2, " #in0 "\n"                     \
119     "por %%mm3, " #in1 "\n"                     \
120     "movq " #in0 ", %%mm2\n"                    \
121     "movq " #in1 ", %%mm3\n"                    \
122     "punpcklbw %%mm7, " #in0 "\n"               \
123     "punpcklbw %%mm7, " #in1 "\n"               \
124     "punpckhbw %%mm7, %%mm2\n"                  \
125     "punpckhbw %%mm7, %%mm3\n"                  \
126     "paddw " #in1 ", " #in0 "\n"                \
127     "paddw %%mm3, %%mm2\n"                      \
128     "paddw %%mm2, " #in0 "\n"                   \
129     "paddw " #in0 ", %%mm6\n"
130
131
132     __asm__ volatile (
133         "movl    %3, %%ecx\n"
134         "pxor %%mm6, %%mm6\n"
135         "pxor %%mm7, %%mm7\n"
136         "movq  (%0), %%mm0\n"
137         "movq 8(%0), %%mm1\n"
138         "add %2, %0\n"
139         "jmp 2f\n"
140         "1:\n"
141
142         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
143         "2:\n"
144         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
145
146         "subl $2, %%ecx\n"
147         "jnz 1b\n"
148
149         "movq  %%mm6, %%mm0\n"
150         "psrlq $32,   %%mm6\n"
151         "paddw %%mm6, %%mm0\n"
152         "movq  %%mm0, %%mm6\n"
153         "psrlq $16,   %%mm0\n"
154         "paddw %%mm6, %%mm0\n"
155         "movd  %%mm0, %1\n"
156         : "+r" (pix), "=r" (tmp)
157         : "r" ((x86_reg) line_size), "m" (h)
158         : "%ecx");
159
160     return tmp & 0xFFFF;
161 }
162 #undef SUM
163
164 static int vsad_intra16_mmxext(MpegEncContext *v, uint8_t *pix, uint8_t *dummy,
165                                int line_size, int h)
166 {
167     int tmp;
168
169     av_assert2((((int) pix) & 7) == 0);
170     av_assert2((line_size & 7) == 0);
171
172 #define SUM(in0, in1, out0, out1)               \
173     "movq (%0), " #out0 "\n"                    \
174     "movq 8(%0), " #out1 "\n"                   \
175     "add %2, %0\n"                              \
176     "psadbw " #out0 ", " #in0 "\n"              \
177     "psadbw " #out1 ", " #in1 "\n"              \
178     "paddw " #in1 ", " #in0 "\n"                \
179     "paddw " #in0 ", %%mm6\n"
180
181     __asm__ volatile (
182         "movl %3, %%ecx\n"
183         "pxor %%mm6, %%mm6\n"
184         "pxor %%mm7, %%mm7\n"
185         "movq (%0), %%mm0\n"
186         "movq 8(%0), %%mm1\n"
187         "add %2, %0\n"
188         "jmp 2f\n"
189         "1:\n"
190
191         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
192         "2:\n"
193         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
194
195         "subl $2, %%ecx\n"
196         "jnz 1b\n"
197
198         "movd %%mm6, %1\n"
199         : "+r" (pix), "=r" (tmp)
200         : "r" ((x86_reg) line_size), "m" (h)
201         : "%ecx");
202
203     return tmp;
204 }
205 #undef SUM
206
207 static int vsad16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
208                       int line_size, int h)
209 {
210     int tmp;
211
212     av_assert2((((int) pix1) & 7) == 0);
213     av_assert2((((int) pix2) & 7) == 0);
214     av_assert2((line_size & 7) == 0);
215
216 #define SUM(in0, in1, out0, out1)       \
217     "movq (%0), %%mm2\n"                \
218     "movq (%1), " #out0 "\n"            \
219     "movq 8(%0), %%mm3\n"               \
220     "movq 8(%1), " #out1 "\n"           \
221     "add %3, %0\n"                      \
222     "add %3, %1\n"                      \
223     "psubb " #out0 ", %%mm2\n"          \
224     "psubb " #out1 ", %%mm3\n"          \
225     "pxor %%mm7, %%mm2\n"               \
226     "pxor %%mm7, %%mm3\n"               \
227     "movq %%mm2, " #out0 "\n"           \
228     "movq %%mm3, " #out1 "\n"           \
229     "psubusb " #in0 ", %%mm2\n"         \
230     "psubusb " #in1 ", %%mm3\n"         \
231     "psubusb " #out0 ", " #in0 "\n"     \
232     "psubusb " #out1 ", " #in1 "\n"     \
233     "por %%mm2, " #in0 "\n"             \
234     "por %%mm3, " #in1 "\n"             \
235     "movq " #in0 ", %%mm2\n"            \
236     "movq " #in1 ", %%mm3\n"            \
237     "punpcklbw %%mm7, " #in0 "\n"       \
238     "punpcklbw %%mm7, " #in1 "\n"       \
239     "punpckhbw %%mm7, %%mm2\n"          \
240     "punpckhbw %%mm7, %%mm3\n"          \
241     "paddw " #in1 ", " #in0 "\n"        \
242     "paddw %%mm3, %%mm2\n"              \
243     "paddw %%mm2, " #in0 "\n"           \
244     "paddw " #in0 ", %%mm6\n"
245
246
247     __asm__ volatile (
248         "movl %4, %%ecx\n"
249         "pxor %%mm6, %%mm6\n"
250         "pcmpeqw %%mm7, %%mm7\n"
251         "psllw $15, %%mm7\n"
252         "packsswb %%mm7, %%mm7\n"
253         "movq (%0), %%mm0\n"
254         "movq (%1), %%mm2\n"
255         "movq 8(%0), %%mm1\n"
256         "movq 8(%1), %%mm3\n"
257         "add %3, %0\n"
258         "add %3, %1\n"
259         "psubb %%mm2, %%mm0\n"
260         "psubb %%mm3, %%mm1\n"
261         "pxor %%mm7, %%mm0\n"
262         "pxor %%mm7, %%mm1\n"
263         "jmp 2f\n"
264         "1:\n"
265
266         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
267         "2:\n"
268         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
269
270         "subl $2, %%ecx\n"
271         "jnz 1b\n"
272
273         "movq %%mm6, %%mm0\n"
274         "psrlq $32, %%mm6\n"
275         "paddw %%mm6, %%mm0\n"
276         "movq %%mm0, %%mm6\n"
277         "psrlq $16, %%mm0\n"
278         "paddw %%mm6, %%mm0\n"
279         "movd %%mm0, %2\n"
280         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
281         : "r" ((x86_reg) line_size), "m" (h)
282         : "%ecx");
283
284     return tmp & 0x7FFF;
285 }
286 #undef SUM
287
288 static int vsad16_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
289                          int line_size, int h)
290 {
291     int tmp;
292
293     av_assert2((((int) pix1) & 7) == 0);
294     av_assert2((((int) pix2) & 7) == 0);
295     av_assert2((line_size & 7) == 0);
296
297 #define SUM(in0, in1, out0, out1)               \
298     "movq (%0), " #out0 "\n"                    \
299     "movq (%1), %%mm2\n"                        \
300     "movq 8(%0), " #out1 "\n"                   \
301     "movq 8(%1), %%mm3\n"                       \
302     "add %3, %0\n"                              \
303     "add %3, %1\n"                              \
304     "psubb %%mm2, " #out0 "\n"                  \
305     "psubb %%mm3, " #out1 "\n"                  \
306     "pxor %%mm7, " #out0 "\n"                   \
307     "pxor %%mm7, " #out1 "\n"                   \
308     "psadbw " #out0 ", " #in0 "\n"              \
309     "psadbw " #out1 ", " #in1 "\n"              \
310     "paddw " #in1 ", " #in0 "\n"                \
311     "paddw " #in0 ", %%mm6\n    "
312
313     __asm__ volatile (
314         "movl %4, %%ecx\n"
315         "pxor %%mm6, %%mm6\n"
316         "pcmpeqw %%mm7, %%mm7\n"
317         "psllw $15, %%mm7\n"
318         "packsswb %%mm7, %%mm7\n"
319         "movq (%0), %%mm0\n"
320         "movq (%1), %%mm2\n"
321         "movq 8(%0), %%mm1\n"
322         "movq 8(%1), %%mm3\n"
323         "add %3, %0\n"
324         "add %3, %1\n"
325         "psubb %%mm2, %%mm0\n"
326         "psubb %%mm3, %%mm1\n"
327         "pxor %%mm7, %%mm0\n"
328         "pxor %%mm7, %%mm1\n"
329         "jmp 2f\n"
330         "1:\n"
331
332         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
333         "2:\n"
334         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
335
336         "subl $2, %%ecx\n"
337         "jnz 1b\n"
338
339         "movd %%mm6, %2\n"
340         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
341         : "r" ((x86_reg) line_size), "m" (h)
342         : "%ecx");
343
344     return tmp;
345 }
346 #undef SUM
347
348
349 #endif /* HAVE_INLINE_ASM */
350
351 av_cold void ff_dsputilenc_init_mmx(DSPContext *c, AVCodecContext *avctx,
352                                     unsigned high_bit_depth)
353 {
354     int cpu_flags = av_get_cpu_flags();
355
356     if (EXTERNAL_MMX(cpu_flags)) {
357         if (!high_bit_depth)
358             c->get_pixels = ff_get_pixels_mmx;
359         c->diff_pixels = ff_diff_pixels_mmx;
360     }
361
362     if (EXTERNAL_SSE2(cpu_flags))
363         if (!high_bit_depth)
364             c->get_pixels = ff_get_pixels_sse2;
365
366 #if HAVE_INLINE_ASM
367     if (INLINE_MMX(cpu_flags)) {
368         c->vsad[4] = vsad_intra16_mmx;
369
370         if (!(avctx->flags & CODEC_FLAG_BITEXACT)) {
371             c->vsad[0]      = vsad16_mmx;
372         }
373     }
374
375     if (INLINE_MMXEXT(cpu_flags)) {
376         c->vsad[4]         = vsad_intra16_mmxext;
377
378         if (!(avctx->flags & CODEC_FLAG_BITEXACT)) {
379             c->vsad[0] = vsad16_mmxext;
380         }
381     }
382
383     if (INLINE_SSE2(cpu_flags)) {
384     }
385
386 #if HAVE_SSSE3_INLINE
387     if (INLINE_SSSE3(cpu_flags)) {
388     }
389 #endif
390 #endif /* HAVE_INLINE_ASM */
391
392     if (EXTERNAL_MMX(cpu_flags)) {
393         c->hadamard8_diff[0] = ff_hadamard8_diff16_mmx;
394         c->hadamard8_diff[1] = ff_hadamard8_diff_mmx;
395         c->sum_abs_dctelem   = ff_sum_abs_dctelem_mmx;
396         c->sse[0]            = ff_sse16_mmx;
397         c->sse[1]            = ff_sse8_mmx;
398 #if HAVE_YASM
399         c->nsse[0]           = nsse16_mmx;
400         c->nsse[1]           = nsse8_mmx;
401 #endif
402     }
403
404     if (EXTERNAL_MMXEXT(cpu_flags)) {
405         c->hadamard8_diff[0] = ff_hadamard8_diff16_mmxext;
406         c->hadamard8_diff[1] = ff_hadamard8_diff_mmxext;
407         c->sum_abs_dctelem   = ff_sum_abs_dctelem_mmxext;
408     }
409
410     if (EXTERNAL_SSE2(cpu_flags)) {
411         c->sse[0] = ff_sse16_sse2;
412         c->sum_abs_dctelem   = ff_sum_abs_dctelem_sse2;
413         c->diff_pixels = ff_diff_pixels_sse2;
414
415 #if HAVE_ALIGNED_STACK
416         c->hadamard8_diff[0] = ff_hadamard8_diff16_sse2;
417         c->hadamard8_diff[1] = ff_hadamard8_diff_sse2;
418 #endif
419     }
420
421     if (EXTERNAL_SSSE3(cpu_flags)) {
422         c->sum_abs_dctelem   = ff_sum_abs_dctelem_ssse3;
423 #if HAVE_ALIGNED_STACK
424         c->hadamard8_diff[0] = ff_hadamard8_diff16_ssse3;
425         c->hadamard8_diff[1] = ff_hadamard8_diff_ssse3;
426 #endif
427     }
428
429     ff_dsputil_init_pix_mmx(c, avctx);
430 }