]> git.sesse.net Git - ffmpeg/blob - libavfilter/x86/yadif.c
Fix compile on Darwin (FATE). Compile error:
[ffmpeg] / libavfilter / x86 / yadif.c
1 /*
2  * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "libavutil/cpu.h"
22 #include "libavutil/x86_cpu.h"
23 #include "libavfilter/yadif.h"
24
25 #define LOAD4(mem,dst) \
26             "movd      "mem", "#dst" \n\t"\
27             "punpcklbw %%mm7, "#dst" \n\t"
28
29 #define PABS(tmp,dst) \
30             "pxor     "#tmp", "#tmp" \n\t"\
31             "psubw    "#dst", "#tmp" \n\t"\
32             "pmaxsw   "#tmp", "#dst" \n\t"
33
34 #define CHECK(pj,mj) \
35             "movq "#pj"(%[cur],%[mrefs]), %%mm2 \n\t" /* cur[x-refs-1+j] */\
36             "movq "#mj"(%[cur],%[prefs]), %%mm3 \n\t" /* cur[x+refs-1-j] */\
37             "movq      %%mm2, %%mm4 \n\t"\
38             "movq      %%mm2, %%mm5 \n\t"\
39             "pxor      %%mm3, %%mm4 \n\t"\
40             "pavgb     %%mm3, %%mm5 \n\t"\
41             "pand     "MANGLE(pb_1)", %%mm4 \n\t"\
42             "psubusb   %%mm4, %%mm5 \n\t"\
43             "psrlq     $8,    %%mm5 \n\t"\
44             "punpcklbw %%mm7, %%mm5 \n\t" /* (cur[x-refs+j] + cur[x+refs-j])>>1 */\
45             "movq      %%mm2, %%mm4 \n\t"\
46             "psubusb   %%mm3, %%mm2 \n\t"\
47             "psubusb   %%mm4, %%mm3 \n\t"\
48             "pmaxub    %%mm3, %%mm2 \n\t"\
49             "movq      %%mm2, %%mm3 \n\t"\
50             "movq      %%mm2, %%mm4 \n\t" /* ABS(cur[x-refs-1+j] - cur[x+refs-1-j]) */\
51             "psrlq      $8,   %%mm3 \n\t" /* ABS(cur[x-refs  +j] - cur[x+refs  -j]) */\
52             "psrlq     $16,   %%mm4 \n\t" /* ABS(cur[x-refs+1+j] - cur[x+refs+1-j]) */\
53             "punpcklbw %%mm7, %%mm2 \n\t"\
54             "punpcklbw %%mm7, %%mm3 \n\t"\
55             "punpcklbw %%mm7, %%mm4 \n\t"\
56             "paddw     %%mm3, %%mm2 \n\t"\
57             "paddw     %%mm4, %%mm2 \n\t" /* score */
58
59 #define CHECK1 \
60             "movq      %%mm0, %%mm3 \n\t"\
61             "pcmpgtw   %%mm2, %%mm3 \n\t" /* if(score < spatial_score) */\
62             "pminsw    %%mm2, %%mm0 \n\t" /* spatial_score= score; */\
63             "movq      %%mm3, %%mm6 \n\t"\
64             "pand      %%mm3, %%mm5 \n\t"\
65             "pandn     %%mm1, %%mm3 \n\t"\
66             "por       %%mm5, %%mm3 \n\t"\
67             "movq      %%mm3, %%mm1 \n\t" /* spatial_pred= (cur[x-refs+j] + cur[x+refs-j])>>1; */
68
69 #define CHECK2 /* pretend not to have checked dir=2 if dir=1 was bad.\
70                   hurts both quality and speed, but matches the C version. */\
71             "paddw    "MANGLE(pw_1)", %%mm6 \n\t"\
72             "psllw     $14,   %%mm6 \n\t"\
73             "paddsw    %%mm6, %%mm2 \n\t"\
74             "movq      %%mm0, %%mm3 \n\t"\
75             "pcmpgtw   %%mm2, %%mm3 \n\t"\
76             "pminsw    %%mm2, %%mm0 \n\t"\
77             "pand      %%mm3, %%mm5 \n\t"\
78             "pandn     %%mm1, %%mm3 \n\t"\
79             "por       %%mm5, %%mm3 \n\t"\
80             "movq      %%mm3, %%mm1 \n\t"
81
82 DECLARE_ASM_CONST(16, uint64_t, pw_1) = 0x0001000100010001ULL;
83 DECLARE_ASM_CONST(16, uint64_t, pb_1) = 0x0101010101010101ULL;
84
85 void ff_yadif_filter_line_mmx(uint8_t *dst,
86                               uint8_t *prev, uint8_t *cur, uint8_t *next,
87                               int w, int refs, int parity, int mode)
88 {
89     uint64_t tmp0, tmp1, tmp2, tmp3;
90     int x;
91
92 #define FILTER\
93     for(x=0; x<w; x+=4){\
94         __asm__ volatile(\
95             "pxor      %%mm7, %%mm7 \n\t"\
96             LOAD4("(%[cur],%[mrefs])", %%mm0) /* c = cur[x-refs] */\
97             LOAD4("(%[cur],%[prefs])", %%mm1) /* e = cur[x+refs] */\
98             LOAD4("(%["prev2"])", %%mm2) /* prev2[x] */\
99             LOAD4("(%["next2"])", %%mm3) /* next2[x] */\
100             "movq      %%mm3, %%mm4 \n\t"\
101             "paddw     %%mm2, %%mm3 \n\t"\
102             "psraw     $1,    %%mm3 \n\t" /* d = (prev2[x] + next2[x])>>1 */\
103             "movq      %%mm0, %[tmp0] \n\t" /* c */\
104             "movq      %%mm3, %[tmp1] \n\t" /* d */\
105             "movq      %%mm1, %[tmp2] \n\t" /* e */\
106             "psubw     %%mm4, %%mm2 \n\t"\
107             PABS(      %%mm4, %%mm2) /* temporal_diff0 */\
108             LOAD4("(%[prev],%[mrefs])", %%mm3) /* prev[x-refs] */\
109             LOAD4("(%[prev],%[prefs])", %%mm4) /* prev[x+refs] */\
110             "psubw     %%mm0, %%mm3 \n\t"\
111             "psubw     %%mm1, %%mm4 \n\t"\
112             PABS(      %%mm5, %%mm3)\
113             PABS(      %%mm5, %%mm4)\
114             "paddw     %%mm4, %%mm3 \n\t" /* temporal_diff1 */\
115             "psrlw     $1,    %%mm2 \n\t"\
116             "psrlw     $1,    %%mm3 \n\t"\
117             "pmaxsw    %%mm3, %%mm2 \n\t"\
118             LOAD4("(%[next],%[mrefs])", %%mm3) /* next[x-refs] */\
119             LOAD4("(%[next],%[prefs])", %%mm4) /* next[x+refs] */\
120             "psubw     %%mm0, %%mm3 \n\t"\
121             "psubw     %%mm1, %%mm4 \n\t"\
122             PABS(      %%mm5, %%mm3)\
123             PABS(      %%mm5, %%mm4)\
124             "paddw     %%mm4, %%mm3 \n\t" /* temporal_diff2 */\
125             "psrlw     $1,    %%mm3 \n\t"\
126             "pmaxsw    %%mm3, %%mm2 \n\t"\
127             "movq      %%mm2, %[tmp3] \n\t" /* diff */\
128 \
129             "paddw     %%mm0, %%mm1 \n\t"\
130             "paddw     %%mm0, %%mm0 \n\t"\
131             "psubw     %%mm1, %%mm0 \n\t"\
132             "psrlw     $1,    %%mm1 \n\t" /* spatial_pred */\
133             PABS(      %%mm2, %%mm0)      /* ABS(c-e) */\
134 \
135             "movq -1(%[cur],%[mrefs]), %%mm2 \n\t" /* cur[x-refs-1] */\
136             "movq -1(%[cur],%[prefs]), %%mm3 \n\t" /* cur[x+refs-1] */\
137             "movq      %%mm2, %%mm4 \n\t"\
138             "psubusb   %%mm3, %%mm2 \n\t"\
139             "psubusb   %%mm4, %%mm3 \n\t"\
140             "pmaxub    %%mm3, %%mm2 \n\t"\
141             "pshufw $9,%%mm2, %%mm3 \n\t"\
142             "punpcklbw %%mm7, %%mm2 \n\t" /* ABS(cur[x-refs-1] - cur[x+refs-1]) */\
143             "punpcklbw %%mm7, %%mm3 \n\t" /* ABS(cur[x-refs+1] - cur[x+refs+1]) */\
144             "paddw     %%mm2, %%mm0 \n\t"\
145             "paddw     %%mm3, %%mm0 \n\t"\
146             "psubw    "MANGLE(pw_1)", %%mm0 \n\t" /* spatial_score */\
147 \
148             CHECK(-2,0)\
149             CHECK1\
150             CHECK(-3,1)\
151             CHECK2\
152             CHECK(0,-2)\
153             CHECK1\
154             CHECK(1,-3)\
155             CHECK2\
156 \
157             /* if(p->mode<2) ... */\
158             "movq    %[tmp3], %%mm6 \n\t" /* diff */\
159             "cmp       $2, %[mode] \n\t"\
160             "jge       1f \n\t"\
161             LOAD4("(%["prev2"],%[mrefs],2)", %%mm2) /* prev2[x-2*refs] */\
162             LOAD4("(%["next2"],%[mrefs],2)", %%mm4) /* next2[x-2*refs] */\
163             LOAD4("(%["prev2"],%[prefs],2)", %%mm3) /* prev2[x+2*refs] */\
164             LOAD4("(%["next2"],%[prefs],2)", %%mm5) /* next2[x+2*refs] */\
165             "paddw     %%mm4, %%mm2 \n\t"\
166             "paddw     %%mm5, %%mm3 \n\t"\
167             "psrlw     $1,    %%mm2 \n\t" /* b */\
168             "psrlw     $1,    %%mm3 \n\t" /* f */\
169             "movq    %[tmp0], %%mm4 \n\t" /* c */\
170             "movq    %[tmp1], %%mm5 \n\t" /* d */\
171             "movq    %[tmp2], %%mm7 \n\t" /* e */\
172             "psubw     %%mm4, %%mm2 \n\t" /* b-c */\
173             "psubw     %%mm7, %%mm3 \n\t" /* f-e */\
174             "movq      %%mm5, %%mm0 \n\t"\
175             "psubw     %%mm4, %%mm5 \n\t" /* d-c */\
176             "psubw     %%mm7, %%mm0 \n\t" /* d-e */\
177             "movq      %%mm2, %%mm4 \n\t"\
178             "pminsw    %%mm3, %%mm2 \n\t"\
179             "pmaxsw    %%mm4, %%mm3 \n\t"\
180             "pmaxsw    %%mm5, %%mm2 \n\t"\
181             "pminsw    %%mm5, %%mm3 \n\t"\
182             "pmaxsw    %%mm0, %%mm2 \n\t" /* max */\
183             "pminsw    %%mm0, %%mm3 \n\t" /* min */\
184             "pxor      %%mm4, %%mm4 \n\t"\
185             "pmaxsw    %%mm3, %%mm6 \n\t"\
186             "psubw     %%mm2, %%mm4 \n\t" /* -max */\
187             "pmaxsw    %%mm4, %%mm6 \n\t" /* diff= MAX3(diff, min, -max); */\
188             "1: \n\t"\
189 \
190             "movq    %[tmp1], %%mm2 \n\t" /* d */\
191             "movq      %%mm2, %%mm3 \n\t"\
192             "psubw     %%mm6, %%mm2 \n\t" /* d-diff */\
193             "paddw     %%mm6, %%mm3 \n\t" /* d+diff */\
194             "pmaxsw    %%mm2, %%mm1 \n\t"\
195             "pminsw    %%mm3, %%mm1 \n\t" /* d = clip(spatial_pred, d-diff, d+diff); */\
196             "packuswb  %%mm1, %%mm1 \n\t"\
197 \
198             :[tmp0]"=m"(tmp0),\
199              [tmp1]"=m"(tmp1),\
200              [tmp2]"=m"(tmp2),\
201              [tmp3]"=m"(tmp3)\
202             :[prev] "r"(prev),\
203              [cur]  "r"(cur),\
204              [next] "r"(next),\
205              [prefs]"r"((x86_reg)refs),\
206              [mrefs]"r"((x86_reg)-refs),\
207              [mode] "g"(mode)\
208         );\
209         __asm__ volatile("movd %%mm1, %0" :"=m"(*dst));\
210         dst += 4;\
211         prev+= 4;\
212         cur += 4;\
213         next+= 4;\
214     }
215
216     if (parity) {
217 #define prev2 "prev"
218 #define next2 "cur"
219         FILTER
220 #undef prev2
221 #undef next2
222     } else {
223 #define prev2 "cur"
224 #define next2 "next"
225         FILTER
226 #undef prev2
227 #undef next2
228     }
229 }
230 #undef LOAD4
231 #undef PABS
232 #undef CHECK
233 #undef CHECK1
234 #undef CHECK2
235 #undef FILTER