]> git.sesse.net Git - vlc/blob - modules/video_filter/yadif.h
Use var_InheritString for --decklink-video-connection.
[vlc] / modules / video_filter / yadif.h
1 /*
2  * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * This file is part of MPlayer.
5  *
6  * MPlayer 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  * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 /* */
22 #if defined(CAN_COMPILE_SSE2) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 0))
23
24 #define HAVE_YADIF_SSE2
25
26 #define LOAD4(mem,dst) \
27             "movd      "mem", "#dst" \n\t"\
28             "punpcklbw %%mm7, "#dst" \n\t"
29
30 #define PABS(tmp,dst) \
31             "pxor     "#tmp", "#tmp" \n\t"\
32             "psubw    "#dst", "#tmp" \n\t"\
33             "pmaxsw   "#tmp", "#dst" \n\t"
34
35 #define CHECK(pj,mj) \
36             "movq "#pj"(%[cur],%[mrefs]), %%mm2 \n\t" /* cur[x-refs-1+j] */\
37             "movq "#mj"(%[cur],%[prefs]), %%mm3 \n\t" /* cur[x+refs-1-j] */\
38             "movq      %%mm2, %%mm4 \n\t"\
39             "movq      %%mm2, %%mm5 \n\t"\
40             "pxor      %%mm3, %%mm4 \n\t"\
41             "pavgb     %%mm3, %%mm5 \n\t"\
42             "pand     %[pb1], %%mm4 \n\t"\
43             "psubusb   %%mm4, %%mm5 \n\t"\
44             "psrlq     $8,    %%mm5 \n\t"\
45             "punpcklbw %%mm7, %%mm5 \n\t" /* (cur[x-refs+j] + cur[x+refs-j])>>1 */\
46             "movq      %%mm2, %%mm4 \n\t"\
47             "psubusb   %%mm3, %%mm2 \n\t"\
48             "psubusb   %%mm4, %%mm3 \n\t"\
49             "pmaxub    %%mm3, %%mm2 \n\t"\
50             "movq      %%mm2, %%mm3 \n\t"\
51             "movq      %%mm2, %%mm4 \n\t" /* ABS(cur[x-refs-1+j] - cur[x+refs-1-j]) */\
52             "psrlq      $8,   %%mm3 \n\t" /* ABS(cur[x-refs  +j] - cur[x+refs  -j]) */\
53             "psrlq     $16,   %%mm4 \n\t" /* ABS(cur[x-refs+1+j] - cur[x+refs+1-j]) */\
54             "punpcklbw %%mm7, %%mm2 \n\t"\
55             "punpcklbw %%mm7, %%mm3 \n\t"\
56             "punpcklbw %%mm7, %%mm4 \n\t"\
57             "paddw     %%mm3, %%mm2 \n\t"\
58             "paddw     %%mm4, %%mm2 \n\t" /* score */
59
60 #define CHECK1 \
61             "movq      %%mm0, %%mm3 \n\t"\
62             "pcmpgtw   %%mm2, %%mm3 \n\t" /* if(score < spatial_score) */\
63             "pminsw    %%mm2, %%mm0 \n\t" /* spatial_score= score; */\
64             "movq      %%mm3, %%mm6 \n\t"\
65             "pand      %%mm3, %%mm5 \n\t"\
66             "pandn     %%mm1, %%mm3 \n\t"\
67             "por       %%mm5, %%mm3 \n\t"\
68             "movq      %%mm3, %%mm1 \n\t" /* spatial_pred= (cur[x-refs+j] + cur[x+refs-j])>>1; */
69
70 #define CHECK2 /* pretend not to have checked dir=2 if dir=1 was bad.\
71                   hurts both quality and speed, but matches the C version. */\
72             "paddw    %[pw1], %%mm6 \n\t"\
73             "psllw     $14,   %%mm6 \n\t"\
74             "paddsw    %%mm6, %%mm2 \n\t"\
75             "movq      %%mm0, %%mm3 \n\t"\
76             "pcmpgtw   %%mm2, %%mm3 \n\t"\
77             "pminsw    %%mm2, %%mm0 \n\t"\
78             "pand      %%mm3, %%mm5 \n\t"\
79             "pandn     %%mm1, %%mm3 \n\t"\
80             "por       %%mm5, %%mm3 \n\t"\
81             "movq      %%mm3, %%mm1 \n\t"
82
83 static void yadif_filter_line_mmx2(struct vf_priv_s *p, uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int refs, int parity){
84     static const uint64_t pw_1 = 0x0001000100010001ULL;
85     static const uint64_t pb_1 = 0x0101010101010101ULL;
86     const int mode = p->mode;
87     uint64_t tmp0, tmp1, tmp2, tmp3;
88     int x;
89
90 #define FILTER\
91     for(x=0; x<w; x+=4){\
92         __asm__ volatile(\
93             "pxor      %%mm7, %%mm7 \n\t"\
94             LOAD4("(%[cur],%[mrefs])", %%mm0) /* c = cur[x-refs] */\
95             LOAD4("(%[cur],%[prefs])", %%mm1) /* e = cur[x+refs] */\
96             LOAD4("(%["prev2"])", %%mm2) /* prev2[x] */\
97             LOAD4("(%["next2"])", %%mm3) /* next2[x] */\
98             "movq      %%mm3, %%mm4 \n\t"\
99             "paddw     %%mm2, %%mm3 \n\t"\
100             "psraw     $1,    %%mm3 \n\t" /* d = (prev2[x] + next2[x])>>1 */\
101             "movq      %%mm0, %[tmp0] \n\t" /* c */\
102             "movq      %%mm3, %[tmp1] \n\t" /* d */\
103             "movq      %%mm1, %[tmp2] \n\t" /* e */\
104             "psubw     %%mm4, %%mm2 \n\t"\
105             PABS(      %%mm4, %%mm2) /* temporal_diff0 */\
106             LOAD4("(%[prev],%[mrefs])", %%mm3) /* prev[x-refs] */\
107             LOAD4("(%[prev],%[prefs])", %%mm4) /* prev[x+refs] */\
108             "psubw     %%mm0, %%mm3 \n\t"\
109             "psubw     %%mm1, %%mm4 \n\t"\
110             PABS(      %%mm5, %%mm3)\
111             PABS(      %%mm5, %%mm4)\
112             "paddw     %%mm4, %%mm3 \n\t" /* temporal_diff1 */\
113             "psrlw     $1,    %%mm2 \n\t"\
114             "psrlw     $1,    %%mm3 \n\t"\
115             "pmaxsw    %%mm3, %%mm2 \n\t"\
116             LOAD4("(%[next],%[mrefs])", %%mm3) /* next[x-refs] */\
117             LOAD4("(%[next],%[prefs])", %%mm4) /* next[x+refs] */\
118             "psubw     %%mm0, %%mm3 \n\t"\
119             "psubw     %%mm1, %%mm4 \n\t"\
120             PABS(      %%mm5, %%mm3)\
121             PABS(      %%mm5, %%mm4)\
122             "paddw     %%mm4, %%mm3 \n\t" /* temporal_diff2 */\
123             "psrlw     $1,    %%mm3 \n\t"\
124             "pmaxsw    %%mm3, %%mm2 \n\t"\
125             "movq      %%mm2, %[tmp3] \n\t" /* diff */\
126 \
127             "paddw     %%mm0, %%mm1 \n\t"\
128             "paddw     %%mm0, %%mm0 \n\t"\
129             "psubw     %%mm1, %%mm0 \n\t"\
130             "psrlw     $1,    %%mm1 \n\t" /* spatial_pred */\
131             PABS(      %%mm2, %%mm0)      /* ABS(c-e) */\
132 \
133             "movq -1(%[cur],%[mrefs]), %%mm2 \n\t" /* cur[x-refs-1] */\
134             "movq -1(%[cur],%[prefs]), %%mm3 \n\t" /* cur[x+refs-1] */\
135             "movq      %%mm2, %%mm4 \n\t"\
136             "psubusb   %%mm3, %%mm2 \n\t"\
137             "psubusb   %%mm4, %%mm3 \n\t"\
138             "pmaxub    %%mm3, %%mm2 \n\t"\
139             "pshufw $9,%%mm2, %%mm3 \n\t"\
140             "punpcklbw %%mm7, %%mm2 \n\t" /* ABS(cur[x-refs-1] - cur[x+refs-1]) */\
141             "punpcklbw %%mm7, %%mm3 \n\t" /* ABS(cur[x-refs+1] - cur[x+refs+1]) */\
142             "paddw     %%mm2, %%mm0 \n\t"\
143             "paddw     %%mm3, %%mm0 \n\t"\
144             "psubw    %[pw1], %%mm0 \n\t" /* spatial_score */\
145 \
146             CHECK(-2,0)\
147             CHECK1\
148             CHECK(-3,1)\
149             CHECK2\
150             CHECK(0,-2)\
151             CHECK1\
152             CHECK(1,-3)\
153             CHECK2\
154 \
155             /* if(p->mode<2) ... */\
156             "movq    %[tmp3], %%mm6 \n\t" /* diff */\
157             "cmp       $2, %[mode] \n\t"\
158             "jge       1f \n\t"\
159             LOAD4("(%["prev2"],%[mrefs],2)", %%mm2) /* prev2[x-2*refs] */\
160             LOAD4("(%["next2"],%[mrefs],2)", %%mm4) /* next2[x-2*refs] */\
161             LOAD4("(%["prev2"],%[prefs],2)", %%mm3) /* prev2[x+2*refs] */\
162             LOAD4("(%["next2"],%[prefs],2)", %%mm5) /* next2[x+2*refs] */\
163             "paddw     %%mm4, %%mm2 \n\t"\
164             "paddw     %%mm5, %%mm3 \n\t"\
165             "psrlw     $1,    %%mm2 \n\t" /* b */\
166             "psrlw     $1,    %%mm3 \n\t" /* f */\
167             "movq    %[tmp0], %%mm4 \n\t" /* c */\
168             "movq    %[tmp1], %%mm5 \n\t" /* d */\
169             "movq    %[tmp2], %%mm7 \n\t" /* e */\
170             "psubw     %%mm4, %%mm2 \n\t" /* b-c */\
171             "psubw     %%mm7, %%mm3 \n\t" /* f-e */\
172             "movq      %%mm5, %%mm0 \n\t"\
173             "psubw     %%mm4, %%mm5 \n\t" /* d-c */\
174             "psubw     %%mm7, %%mm0 \n\t" /* d-e */\
175             "movq      %%mm2, %%mm4 \n\t"\
176             "pminsw    %%mm3, %%mm2 \n\t"\
177             "pmaxsw    %%mm4, %%mm3 \n\t"\
178             "pmaxsw    %%mm5, %%mm2 \n\t"\
179             "pminsw    %%mm5, %%mm3 \n\t"\
180             "pmaxsw    %%mm0, %%mm2 \n\t" /* max */\
181             "pminsw    %%mm0, %%mm3 \n\t" /* min */\
182             "pxor      %%mm4, %%mm4 \n\t"\
183             "pmaxsw    %%mm3, %%mm6 \n\t"\
184             "psubw     %%mm2, %%mm4 \n\t" /* -max */\
185             "pmaxsw    %%mm4, %%mm6 \n\t" /* diff= MAX3(diff, min, -max); */\
186             "1: \n\t"\
187 \
188             "movq    %[tmp1], %%mm2 \n\t" /* d */\
189             "movq      %%mm2, %%mm3 \n\t"\
190             "psubw     %%mm6, %%mm2 \n\t" /* d-diff */\
191             "paddw     %%mm6, %%mm3 \n\t" /* d+diff */\
192             "pmaxsw    %%mm2, %%mm1 \n\t"\
193             "pminsw    %%mm3, %%mm1 \n\t" /* d = clip(spatial_pred, d-diff, d+diff); */\
194             "packuswb  %%mm1, %%mm1 \n\t"\
195 \
196             :[tmp0]"=m"(tmp0),\
197              [tmp1]"=m"(tmp1),\
198              [tmp2]"=m"(tmp2),\
199              [tmp3]"=m"(tmp3)\
200             :[prev] "r"(prev),\
201              [cur]  "r"(cur),\
202              [next] "r"(next),\
203              [prefs]"r"((x86_reg)refs),\
204              [mrefs]"r"((x86_reg)-refs),\
205              [pw1]  "m"(pw_1),\
206              [pb1]  "m"(pb_1),\
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
236
237 #endif
238
239 static void yadif_filter_line_c(struct vf_priv_s *p, uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int refs, int parity){
240     int x;
241     uint8_t *prev2= parity ? prev : cur ;
242     uint8_t *next2= parity ? cur  : next;
243     for(x=0; x<w; x++){
244         int c= cur[-refs];
245         int d= (prev2[0] + next2[0])>>1;
246         int e= cur[+refs];
247         int temporal_diff0= FFABS(prev2[0] - next2[0]);
248         int temporal_diff1=( FFABS(prev[-refs] - c) + FFABS(prev[+refs] - e) )>>1;
249         int temporal_diff2=( FFABS(next[-refs] - c) + FFABS(next[+refs] - e) )>>1;
250         int diff= FFMAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2);
251         int spatial_pred= (c+e)>>1;
252         int spatial_score= FFABS(cur[-refs-1] - cur[+refs-1]) + FFABS(c-e)
253                          + FFABS(cur[-refs+1] - cur[+refs+1]) - 1;
254
255 #define CHECK(j)\
256     {   int score= FFABS(cur[-refs-1+j] - cur[+refs-1-j])\
257                  + FFABS(cur[-refs  +j] - cur[+refs  -j])\
258                  + FFABS(cur[-refs+1+j] - cur[+refs+1-j]);\
259         if(score < spatial_score){\
260             spatial_score= score;\
261             spatial_pred= (cur[-refs  +j] + cur[+refs  -j])>>1;\
262
263         CHECK(-1) CHECK(-2) }} }}
264         CHECK( 1) CHECK( 2) }} }}
265
266         if(p->mode<2){
267             int b= (prev2[-2*refs] + next2[-2*refs])>>1;
268             int f= (prev2[+2*refs] + next2[+2*refs])>>1;
269 #if 0
270             int a= cur[-3*refs];
271             int g= cur[+3*refs];
272             int max= FFMAX3(d-e, d-c, FFMIN3(FFMAX(b-c,f-e),FFMAX(b-c,b-a),FFMAX(f-g,f-e)) );
273             int min= FFMIN3(d-e, d-c, FFMAX3(FFMIN(b-c,f-e),FFMIN(b-c,b-a),FFMIN(f-g,f-e)) );
274 #else
275             int max= FFMAX3(d-e, d-c, FFMIN(b-c, f-e));
276             int min= FFMIN3(d-e, d-c, FFMAX(b-c, f-e));
277 #endif
278
279             diff= FFMAX3(diff, min, -max);
280         }
281
282         if(spatial_pred > d + diff)
283            spatial_pred = d + diff;
284         else if(spatial_pred < d - diff)
285            spatial_pred = d - diff;
286
287         dst[0] = spatial_pred;
288
289         dst++;
290         cur++;
291         prev++;
292         next++;
293         prev2++;
294         next2++;
295     }
296 }
297