comparison libmpcodecs/vf_ivtc.c @ 32702:7af3e6f901fd

Convert some tabs to whitespace to allow using MPlayer filter sourcecode in FFmpeg.
author cehoyos
date Fri, 14 Jan 2011 22:10:21 +0000
parents a972c1a4a012
children 064be070d8c8
comparison
equal deleted inserted replaced
32701:02bc7c860503 32702:7af3e6f901fd
30 30
31 #include "libvo/fastmemcpy.h" 31 #include "libvo/fastmemcpy.h"
32 32
33 33
34 struct metrics { 34 struct metrics {
35 /* difference: total, even lines, odd lines */ 35 /* difference: total, even lines, odd lines */
36 int d, e, o; 36 int d, e, o;
37 /* noise: temporal, spacial (current), spacial (past) */ 37 /* noise: temporal, spacial (current), spacial (past) */
38 int t, s, p; 38 int t, s, p;
39 }; 39 };
40 40
41 struct frameinfo { 41 struct frameinfo {
42 /* peak, relative, mean */ 42 /* peak, relative, mean */
43 struct metrics p, r, m; 43 struct metrics p, r, m;
44 }; 44 };
45 45
46 struct vf_priv_s { 46 struct vf_priv_s {
47 struct frameinfo fi[2]; 47 struct frameinfo fi[2];
48 mp_image_t *dmpi; 48 mp_image_t *dmpi;
49 int first; 49 int first;
50 int drop, lastdrop, dropnext; 50 int drop, lastdrop, dropnext;
51 int inframes, outframes; 51 int inframes, outframes;
52 }; 52 };
53 53
54 enum { 54 enum {
55 F_DROP, 55 F_DROP,
56 F_MERGE, 56 F_MERGE,
57 F_NEXT, 57 F_NEXT,
58 F_SHOW 58 F_SHOW
59 }; 59 };
60 60
61 #if HAVE_MMX && HAVE_EBX_AVAILABLE 61 #if HAVE_MMX && HAVE_EBX_AVAILABLE
62 static void block_diffs_MMX(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns) 62 static void block_diffs_MMX(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns)
63 { 63 {
64 int i; 64 int i;
65 short out[24]; // output buffer for the partial metrics from the mmx code 65 short out[24]; // output buffer for the partial metrics from the mmx code
66 66
67 __asm__ ( 67 __asm__ (
68 "movl $4, %%ecx \n\t" 68 "movl $4, %%ecx \n\t"
69 "pxor %%mm4, %%mm4 \n\t" // 4 even difference sums 69 "pxor %%mm4, %%mm4 \n\t" // 4 even difference sums
70 "pxor %%mm5, %%mm5 \n\t" // 4 odd difference sums 70 "pxor %%mm5, %%mm5 \n\t" // 4 odd difference sums
71 "pxor %%mm7, %%mm7 \n\t" // all zeros 71 "pxor %%mm7, %%mm7 \n\t" // all zeros
72 72
73 ASMALIGN(4) 73 ASMALIGN(4)
74 "1: \n\t" 74 "1: \n\t"
75 75
76 // Even difference 76 // Even difference
77 "movq (%%"REG_S"), %%mm0 \n\t" 77 "movq (%%"REG_S"), %%mm0 \n\t"
78 "movq (%%"REG_S"), %%mm2 \n\t" 78 "movq (%%"REG_S"), %%mm2 \n\t"
79 "add %%"REG_a", %%"REG_S" \n\t" 79 "add %%"REG_a", %%"REG_S" \n\t"
80 "movq (%%"REG_D"), %%mm1 \n\t" 80 "movq (%%"REG_D"), %%mm1 \n\t"
81 "add %%"REG_b", %%"REG_D" \n\t" 81 "add %%"REG_b", %%"REG_D" \n\t"
82 "psubusb %%mm1, %%mm2 \n\t" 82 "psubusb %%mm1, %%mm2 \n\t"
83 "psubusb %%mm0, %%mm1 \n\t" 83 "psubusb %%mm0, %%mm1 \n\t"
84 "movq %%mm2, %%mm0 \n\t" 84 "movq %%mm2, %%mm0 \n\t"
85 "movq %%mm1, %%mm3 \n\t" 85 "movq %%mm1, %%mm3 \n\t"
86 "punpcklbw %%mm7, %%mm0 \n\t" 86 "punpcklbw %%mm7, %%mm0 \n\t"
87 "punpcklbw %%mm7, %%mm1 \n\t" 87 "punpcklbw %%mm7, %%mm1 \n\t"
88 "punpckhbw %%mm7, %%mm2 \n\t" 88 "punpckhbw %%mm7, %%mm2 \n\t"
89 "punpckhbw %%mm7, %%mm3 \n\t" 89 "punpckhbw %%mm7, %%mm3 \n\t"
90 "paddw %%mm0, %%mm4 \n\t" 90 "paddw %%mm0, %%mm4 \n\t"
91 "paddw %%mm1, %%mm4 \n\t" 91 "paddw %%mm1, %%mm4 \n\t"
92 "paddw %%mm2, %%mm4 \n\t" 92 "paddw %%mm2, %%mm4 \n\t"
93 "paddw %%mm3, %%mm4 \n\t" 93 "paddw %%mm3, %%mm4 \n\t"
94 94
95 // Odd difference 95 // Odd difference
96 "movq (%%"REG_S"), %%mm0 \n\t" 96 "movq (%%"REG_S"), %%mm0 \n\t"
97 "movq (%%"REG_S"), %%mm2 \n\t" 97 "movq (%%"REG_S"), %%mm2 \n\t"
98 "add %%"REG_a", %%"REG_S" \n\t" 98 "add %%"REG_a", %%"REG_S" \n\t"
99 "movq (%%"REG_D"), %%mm1 \n\t" 99 "movq (%%"REG_D"), %%mm1 \n\t"
100 "add %%"REG_b", %%"REG_D" \n\t" 100 "add %%"REG_b", %%"REG_D" \n\t"
101 "psubusb %%mm1, %%mm2 \n\t" 101 "psubusb %%mm1, %%mm2 \n\t"
102 "psubusb %%mm0, %%mm1 \n\t" 102 "psubusb %%mm0, %%mm1 \n\t"
103 "movq %%mm2, %%mm0 \n\t" 103 "movq %%mm2, %%mm0 \n\t"
104 "movq %%mm1, %%mm3 \n\t" 104 "movq %%mm1, %%mm3 \n\t"
105 "punpcklbw %%mm7, %%mm0 \n\t" 105 "punpcklbw %%mm7, %%mm0 \n\t"
106 "punpcklbw %%mm7, %%mm1 \n\t" 106 "punpcklbw %%mm7, %%mm1 \n\t"
107 "punpckhbw %%mm7, %%mm2 \n\t" 107 "punpckhbw %%mm7, %%mm2 \n\t"
108 "punpckhbw %%mm7, %%mm3 \n\t" 108 "punpckhbw %%mm7, %%mm3 \n\t"
109 "paddw %%mm0, %%mm5 \n\t" 109 "paddw %%mm0, %%mm5 \n\t"
110 "paddw %%mm1, %%mm5 \n\t" 110 "paddw %%mm1, %%mm5 \n\t"
111 "paddw %%mm2, %%mm5 \n\t" 111 "paddw %%mm2, %%mm5 \n\t"
112 "paddw %%mm3, %%mm5 \n\t" 112 "paddw %%mm3, %%mm5 \n\t"
113 113
114 "decl %%ecx \n\t" 114 "decl %%ecx \n\t"
115 "jnz 1b \n\t" 115 "jnz 1b \n\t"
116 "movq %%mm4, (%%"REG_d") \n\t" 116 "movq %%mm4, (%%"REG_d") \n\t"
117 "movq %%mm5, 8(%%"REG_d") \n\t" 117 "movq %%mm5, 8(%%"REG_d") \n\t"
118 : 118 :
119 : "S" (old), "D" (new), "a" (os), "b" (ns), "d" (out) 119 : "S" (old), "D" (new), "a" (os), "b" (ns), "d" (out)
120 : "memory" 120 : "memory"
121 ); 121 );
122 m->e = out[0]+out[1]+out[2]+out[3]; 122 m->e = out[0]+out[1]+out[2]+out[3];
123 m->o = out[4]+out[5]+out[6]+out[7]; 123 m->o = out[4]+out[5]+out[6]+out[7];
124 m->d = m->e + m->o; 124 m->d = m->e + m->o;
125 125
126 __asm__ ( 126 __asm__ (
127 // First loop to measure first four columns 127 // First loop to measure first four columns
128 "movl $4, %%ecx \n\t" 128 "movl $4, %%ecx \n\t"
129 "pxor %%mm4, %%mm4 \n\t" // Past spacial noise 129 "pxor %%mm4, %%mm4 \n\t" // Past spacial noise
130 "pxor %%mm5, %%mm5 \n\t" // Temporal noise 130 "pxor %%mm5, %%mm5 \n\t" // Temporal noise
131 "pxor %%mm6, %%mm6 \n\t" // Current spacial noise 131 "pxor %%mm6, %%mm6 \n\t" // Current spacial noise
132 132
133 ASMALIGN(4) 133 ASMALIGN(4)
134 "2: \n\t" 134 "2: \n\t"
135 135
136 "movq (%%"REG_S"), %%mm0 \n\t" 136 "movq (%%"REG_S"), %%mm0 \n\t"
137 "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t" 137 "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t"
138 "add %%"REG_a", %%"REG_S" \n\t" 138 "add %%"REG_a", %%"REG_S" \n\t"
139 "add %%"REG_a", %%"REG_S" \n\t" 139 "add %%"REG_a", %%"REG_S" \n\t"
140 "movq (%%"REG_D"), %%mm2 \n\t" 140 "movq (%%"REG_D"), %%mm2 \n\t"
141 "movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t" 141 "movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t"
142 "add %%"REG_b", %%"REG_D" \n\t" 142 "add %%"REG_b", %%"REG_D" \n\t"
143 "add %%"REG_b", %%"REG_D" \n\t" 143 "add %%"REG_b", %%"REG_D" \n\t"
144 "punpcklbw %%mm7, %%mm0 \n\t" 144 "punpcklbw %%mm7, %%mm0 \n\t"
145 "punpcklbw %%mm7, %%mm1 \n\t" 145 "punpcklbw %%mm7, %%mm1 \n\t"
146 "punpcklbw %%mm7, %%mm2 \n\t" 146 "punpcklbw %%mm7, %%mm2 \n\t"
147 "punpcklbw %%mm7, %%mm3 \n\t" 147 "punpcklbw %%mm7, %%mm3 \n\t"
148 "paddw %%mm1, %%mm4 \n\t" 148 "paddw %%mm1, %%mm4 \n\t"
149 "paddw %%mm1, %%mm5 \n\t" 149 "paddw %%mm1, %%mm5 \n\t"
150 "paddw %%mm3, %%mm6 \n\t" 150 "paddw %%mm3, %%mm6 \n\t"
151 "psubw %%mm0, %%mm4 \n\t" 151 "psubw %%mm0, %%mm4 \n\t"
152 "psubw %%mm2, %%mm5 \n\t" 152 "psubw %%mm2, %%mm5 \n\t"
153 "psubw %%mm2, %%mm6 \n\t" 153 "psubw %%mm2, %%mm6 \n\t"
154 154
155 "decl %%ecx \n\t" 155 "decl %%ecx \n\t"
156 "jnz 2b \n\t" 156 "jnz 2b \n\t"
157 157
158 "movq %%mm0, %%mm1 \n\t" 158 "movq %%mm0, %%mm1 \n\t"
159 "movq %%mm0, %%mm2 \n\t" 159 "movq %%mm0, %%mm2 \n\t"
160 "movq %%mm0, %%mm3 \n\t" 160 "movq %%mm0, %%mm3 \n\t"
161 "pcmpgtw %%mm4, %%mm1 \n\t" 161 "pcmpgtw %%mm4, %%mm1 \n\t"
162 "pcmpgtw %%mm5, %%mm2 \n\t" 162 "pcmpgtw %%mm5, %%mm2 \n\t"
163 "pcmpgtw %%mm6, %%mm3 \n\t" 163 "pcmpgtw %%mm6, %%mm3 \n\t"
164 "pxor %%mm1, %%mm4 \n\t" 164 "pxor %%mm1, %%mm4 \n\t"
165 "pxor %%mm2, %%mm5 \n\t" 165 "pxor %%mm2, %%mm5 \n\t"
166 "pxor %%mm3, %%mm6 \n\t" 166 "pxor %%mm3, %%mm6 \n\t"
167 "psubw %%mm1, %%mm4 \n\t" 167 "psubw %%mm1, %%mm4 \n\t"
168 "psubw %%mm2, %%mm5 \n\t" 168 "psubw %%mm2, %%mm5 \n\t"
169 "psubw %%mm3, %%mm6 \n\t" 169 "psubw %%mm3, %%mm6 \n\t"
170 "movq %%mm4, (%%"REG_d") \n\t" 170 "movq %%mm4, (%%"REG_d") \n\t"
171 "movq %%mm5, 16(%%"REG_d") \n\t" 171 "movq %%mm5, 16(%%"REG_d") \n\t"
172 "movq %%mm6, 32(%%"REG_d") \n\t" 172 "movq %%mm6, 32(%%"REG_d") \n\t"
173 173
174 "mov %%"REG_a", %%"REG_c" \n\t" 174 "mov %%"REG_a", %%"REG_c" \n\t"
175 "shl $3, %%"REG_c" \n\t" 175 "shl $3, %%"REG_c" \n\t"
176 "sub %%"REG_c", %%"REG_S" \n\t" 176 "sub %%"REG_c", %%"REG_S" \n\t"
177 "mov %%"REG_b", %%"REG_c" \n\t" 177 "mov %%"REG_b", %%"REG_c" \n\t"
178 "shl $3, %%"REG_c" \n\t" 178 "shl $3, %%"REG_c" \n\t"
179 "sub %%"REG_c", %%"REG_D" \n\t" 179 "sub %%"REG_c", %%"REG_D" \n\t"
180 180
181 // Second loop for the last four columns 181 // Second loop for the last four columns
182 "movl $4, %%ecx \n\t" 182 "movl $4, %%ecx \n\t"
183 "pxor %%mm4, %%mm4 \n\t" 183 "pxor %%mm4, %%mm4 \n\t"
184 "pxor %%mm5, %%mm5 \n\t" 184 "pxor %%mm5, %%mm5 \n\t"
185 "pxor %%mm6, %%mm6 \n\t" 185 "pxor %%mm6, %%mm6 \n\t"
186 186
187 ASMALIGN(4) 187 ASMALIGN(4)
188 "3: \n\t" 188 "3: \n\t"
189 189
190 "movq (%%"REG_S"), %%mm0 \n\t" 190 "movq (%%"REG_S"), %%mm0 \n\t"
191 "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t" 191 "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t"
192 "add %%"REG_a", %%"REG_S" \n\t" 192 "add %%"REG_a", %%"REG_S" \n\t"
193 "add %%"REG_a", %%"REG_S" \n\t" 193 "add %%"REG_a", %%"REG_S" \n\t"
194 "movq (%%"REG_D"), %%mm2 \n\t" 194 "movq (%%"REG_D"), %%mm2 \n\t"
195 "movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t" 195 "movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t"
196 "add %%"REG_b", %%"REG_D" \n\t" 196 "add %%"REG_b", %%"REG_D" \n\t"
197 "add %%"REG_b", %%"REG_D" \n\t" 197 "add %%"REG_b", %%"REG_D" \n\t"
198 "punpckhbw %%mm7, %%mm0 \n\t" 198 "punpckhbw %%mm7, %%mm0 \n\t"
199 "punpckhbw %%mm7, %%mm1 \n\t" 199 "punpckhbw %%mm7, %%mm1 \n\t"
200 "punpckhbw %%mm7, %%mm2 \n\t" 200 "punpckhbw %%mm7, %%mm2 \n\t"
201 "punpckhbw %%mm7, %%mm3 \n\t" 201 "punpckhbw %%mm7, %%mm3 \n\t"
202 "paddw %%mm1, %%mm4 \n\t" 202 "paddw %%mm1, %%mm4 \n\t"
203 "paddw %%mm1, %%mm5 \n\t" 203 "paddw %%mm1, %%mm5 \n\t"
204 "paddw %%mm3, %%mm6 \n\t" 204 "paddw %%mm3, %%mm6 \n\t"
205 "psubw %%mm0, %%mm4 \n\t" 205 "psubw %%mm0, %%mm4 \n\t"
206 "psubw %%mm2, %%mm5 \n\t" 206 "psubw %%mm2, %%mm5 \n\t"
207 "psubw %%mm2, %%mm6 \n\t" 207 "psubw %%mm2, %%mm6 \n\t"
208 208
209 "decl %%ecx \n\t" 209 "decl %%ecx \n\t"
210 "jnz 3b \n\t" 210 "jnz 3b \n\t"
211 211
212 "movq %%mm0, %%mm1 \n\t" 212 "movq %%mm0, %%mm1 \n\t"
213 "movq %%mm0, %%mm2 \n\t" 213 "movq %%mm0, %%mm2 \n\t"
214 "movq %%mm0, %%mm3 \n\t" 214 "movq %%mm0, %%mm3 \n\t"
215 "pcmpgtw %%mm4, %%mm1 \n\t" 215 "pcmpgtw %%mm4, %%mm1 \n\t"
216 "pcmpgtw %%mm5, %%mm2 \n\t" 216 "pcmpgtw %%mm5, %%mm2 \n\t"
217 "pcmpgtw %%mm6, %%mm3 \n\t" 217 "pcmpgtw %%mm6, %%mm3 \n\t"
218 "pxor %%mm1, %%mm4 \n\t" 218 "pxor %%mm1, %%mm4 \n\t"
219 "pxor %%mm2, %%mm5 \n\t" 219 "pxor %%mm2, %%mm5 \n\t"
220 "pxor %%mm3, %%mm6 \n\t" 220 "pxor %%mm3, %%mm6 \n\t"
221 "psubw %%mm1, %%mm4 \n\t" 221 "psubw %%mm1, %%mm4 \n\t"
222 "psubw %%mm2, %%mm5 \n\t" 222 "psubw %%mm2, %%mm5 \n\t"
223 "psubw %%mm3, %%mm6 \n\t" 223 "psubw %%mm3, %%mm6 \n\t"
224 "movq %%mm4, 8(%%"REG_d") \n\t" 224 "movq %%mm4, 8(%%"REG_d") \n\t"
225 "movq %%mm5, 24(%%"REG_d") \n\t" 225 "movq %%mm5, 24(%%"REG_d") \n\t"
226 "movq %%mm6, 40(%%"REG_d") \n\t" 226 "movq %%mm6, 40(%%"REG_d") \n\t"
227 227
228 "emms \n\t" 228 "emms \n\t"
229 : 229 :
230 : "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out) 230 : "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out)
231 : "memory" 231 : "memory"
232 ); 232 );
233 m->p = m->t = m->s = 0; 233 m->p = m->t = m->s = 0;
234 for (i=0; i<8; i++) { 234 for (i=0; i<8; i++) {
235 m->p += out[i]; 235 m->p += out[i];
236 m->t += out[8+i]; 236 m->t += out[8+i];
237 m->s += out[16+i]; 237 m->s += out[16+i];
238 } 238 }
239 //printf("e=%d o=%d d=%d p=%d t=%d s=%d\n", m->e, m->o, m->d, m->p, m->t, m->s); 239 //printf("e=%d o=%d d=%d p=%d t=%d s=%d\n", m->e, m->o, m->d, m->p, m->t, m->s);
240 } 240 }
241 #endif 241 #endif
242 242
243 //#define MAG(a) ((a)*(a)) 243 //#define MAG(a) ((a)*(a))
244 //#define MAG(a) (abs(a)) 244 //#define MAG(a) (abs(a))
249 #define LOWPASS(s) ((s)[0]) 249 #define LOWPASS(s) ((s)[0])
250 250
251 251
252 static void block_diffs_C(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns) 252 static void block_diffs_C(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns)
253 { 253 {
254 int x, y, e=0, o=0, s=0, p=0, t=0; 254 int x, y, e=0, o=0, s=0, p=0, t=0;
255 unsigned char *oldp, *newp; 255 unsigned char *oldp, *newp;
256 m->s = m->p = m->t = 0; 256 m->s = m->p = m->t = 0;
257 for (x = 8; x; x--) { 257 for (x = 8; x; x--) {
258 oldp = old++; 258 oldp = old++;
259 newp = new++; 259 newp = new++;
260 s = p = t = 0; 260 s = p = t = 0;
261 for (y = 4; y; y--) { 261 for (y = 4; y; y--) {
262 e += MAG(newp[0]-oldp[0]); 262 e += MAG(newp[0]-oldp[0]);
263 o += MAG(newp[ns]-oldp[os]); 263 o += MAG(newp[ns]-oldp[os]);
264 s += newp[ns]-newp[0]; 264 s += newp[ns]-newp[0];
265 p += oldp[os]-oldp[0]; 265 p += oldp[os]-oldp[0];
266 t += oldp[os]-newp[0]; 266 t += oldp[os]-newp[0];
267 oldp += os<<1; 267 oldp += os<<1;
268 newp += ns<<1; 268 newp += ns<<1;
269 } 269 }
270 m->s += MAG(s); 270 m->s += MAG(s);
271 m->p += MAG(p); 271 m->p += MAG(p);
272 m->t += MAG(t); 272 m->t += MAG(t);
273 } 273 }
274 m->e = e; 274 m->e = e;
275 m->o = o; 275 m->o = o;
276 m->d = e+o; 276 m->d = e+o;
277 } 277 }
278 278
279 static void (*block_diffs)(struct metrics *, unsigned char *, unsigned char *, int, int); 279 static void (*block_diffs)(struct metrics *, unsigned char *, unsigned char *, int, int);
280 280
281 #define MAXUP(a,b) ((a) = ((a)>(b)) ? (a) : (b)) 281 #define MAXUP(a,b) ((a) = ((a)>(b)) ? (a) : (b))
282 282
283 static void diff_planes(struct frameinfo *fi, 283 static void diff_planes(struct frameinfo *fi,
284 unsigned char *old, unsigned char *new, int w, int h, int os, int ns) 284 unsigned char *old, unsigned char *new, int w, int h, int os, int ns)
285 { 285 {
286 int x, y; 286 int x, y;
287 struct metrics l; 287 struct metrics l;
288 struct metrics *peak=&fi->p, *rel=&fi->r, *mean=&fi->m; 288 struct metrics *peak=&fi->p, *rel=&fi->r, *mean=&fi->m;
289 memset(peak, 0, sizeof(struct metrics)); 289 memset(peak, 0, sizeof(struct metrics));
290 memset(rel, 0, sizeof(struct metrics)); 290 memset(rel, 0, sizeof(struct metrics));
291 memset(mean, 0, sizeof(struct metrics)); 291 memset(mean, 0, sizeof(struct metrics));
292 for (y = 0; y < h-7; y += 8) { 292 for (y = 0; y < h-7; y += 8) {
293 for (x = 8; x < w-8-7; x += 8) { 293 for (x = 8; x < w-8-7; x += 8) {
294 block_diffs(&l, old+x+y*os, new+x+y*ns, os, ns); 294 block_diffs(&l, old+x+y*os, new+x+y*ns, os, ns);
295 mean->d += l.d; 295 mean->d += l.d;
296 mean->e += l.e; 296 mean->e += l.e;
297 mean->o += l.o; 297 mean->o += l.o;
298 mean->s += l.s; 298 mean->s += l.s;
299 mean->p += l.p; 299 mean->p += l.p;
300 mean->t += l.t; 300 mean->t += l.t;
301 MAXUP(peak->d, l.d); 301 MAXUP(peak->d, l.d);
302 MAXUP(peak->e, l.e); 302 MAXUP(peak->e, l.e);
303 MAXUP(peak->o, l.o); 303 MAXUP(peak->o, l.o);
304 MAXUP(peak->s, l.s); 304 MAXUP(peak->s, l.s);
305 MAXUP(peak->p, l.p); 305 MAXUP(peak->p, l.p);
306 MAXUP(peak->t, l.t); 306 MAXUP(peak->t, l.t);
307 MAXUP(rel->e, l.e-l.o); 307 MAXUP(rel->e, l.e-l.o);
308 MAXUP(rel->o, l.o-l.e); 308 MAXUP(rel->o, l.o-l.e);
309 MAXUP(rel->s, l.s-l.t); 309 MAXUP(rel->s, l.s-l.t);
310 MAXUP(rel->p, l.p-l.t); 310 MAXUP(rel->p, l.p-l.t);
311 MAXUP(rel->t, l.t-l.p); 311 MAXUP(rel->t, l.t-l.p);
312 MAXUP(rel->d, l.t-l.s); /* hack */ 312 MAXUP(rel->d, l.t-l.s); /* hack */
313 } 313 }
314 } 314 }
315 x = (w/8-2)*(h/8); 315 x = (w/8-2)*(h/8);
316 mean->d /= x; 316 mean->d /= x;
317 mean->e /= x; 317 mean->e /= x;
318 mean->o /= x; 318 mean->o /= x;
319 mean->s /= x; 319 mean->s /= x;
320 mean->p /= x; 320 mean->p /= x;
321 mean->t /= x; 321 mean->t /= x;
322 } 322 }
323 323
324 static void diff_fields(struct frameinfo *fi, mp_image_t *old, mp_image_t *new) 324 static void diff_fields(struct frameinfo *fi, mp_image_t *old, mp_image_t *new)
325 { 325 {
326 diff_planes(fi, old->planes[0], new->planes[0], 326 diff_planes(fi, old->planes[0], new->planes[0],
327 new->w, new->h, old->stride[0], new->stride[0]); 327 new->w, new->h, old->stride[0], new->stride[0]);
328 } 328 }
329 329
330 static void stats(struct frameinfo *f) 330 static void stats(struct frameinfo *f)
331 { 331 {
332 mp_msg(MSGT_VFILTER, MSGL_V, " pd=%d re=%d ro=%d rp=%d rt=%d rs=%d rd=%d pp=%d pt=%d ps=%d\r", 332 mp_msg(MSGT_VFILTER, MSGL_V, " pd=%d re=%d ro=%d rp=%d rt=%d rs=%d rd=%d pp=%d pt=%d ps=%d\r",
333 f->p.d, f->r.e, f->r.o, f->r.p, f->r.t, f->r.s, f->r.d, f->p.p, f->p.t, f->p.s); 333 f->p.d, f->r.e, f->r.o, f->r.p, f->r.t, f->r.s, f->r.d, f->p.p, f->p.t, f->p.s);
334 } 334 }
335 335
336 static int foo(struct vf_priv_s *p, mp_image_t *new, mp_image_t *cur) 336 static int foo(struct vf_priv_s *p, mp_image_t *new, mp_image_t *cur)
337 { 337 {
338 struct frameinfo *f = p->fi; 338 struct frameinfo *f = p->fi;
339 339
340 f[0] = f[1]; 340 f[0] = f[1];
341 diff_fields(&f[1], cur, new); 341 diff_fields(&f[1], cur, new);
342 stats(&f[1]); 342 stats(&f[1]);
343 343
344 // Immediately drop this frame if it's already been used. 344 // Immediately drop this frame if it's already been used.
345 if (p->dropnext) { 345 if (p->dropnext) {
346 p->dropnext = 0; 346 p->dropnext = 0;
347 return F_DROP; 347 return F_DROP;
348 } 348 }
349 349
350 // Sometimes a pulldown frame comes all by itself, so both 350 // Sometimes a pulldown frame comes all by itself, so both
351 // its top and bottom field are duplicates from the adjacent 351 // its top and bottom field are duplicates from the adjacent
352 // two frames. We can just drop such a frame, but we 352 // two frames. We can just drop such a frame, but we
353 // immediately show the next frame instead to keep the frame 353 // immediately show the next frame instead to keep the frame
354 // drops evenly spaced during normal 3:2 pulldown sequences. 354 // drops evenly spaced during normal 3:2 pulldown sequences.
355 if ((3*f[1].r.o < f[1].r.e) && (f[1].r.s < f[1].r.d)) { 355 if ((3*f[1].r.o < f[1].r.e) && (f[1].r.s < f[1].r.d)) {
356 p->dropnext = 1; 356 p->dropnext = 1;
357 return F_NEXT; 357 return F_NEXT;
358 } 358 }
359 359
360 // If none of these conditions hold, we will consider the frame 360 // If none of these conditions hold, we will consider the frame
361 // progressive and just show it as-is. 361 // progressive and just show it as-is.
362 if (!( (3*f[0].r.e < f[0].r.o) || 362 if (!( (3*f[0].r.e < f[0].r.o) ||
363 ((2*f[0].r.d < f[0].r.s) && (f[0].r.s > 1200)) || 363 ((2*f[0].r.d < f[0].r.s) && (f[0].r.s > 1200)) ||
364 ((2*f[1].r.t < f[1].r.p) && (f[1].r.p > 1200)) )) 364 ((2*f[1].r.t < f[1].r.p) && (f[1].r.p > 1200)) ))
365 return F_SHOW; 365 return F_SHOW;
366 366
367 // Otherwise, we have to decide whether to merge or drop. 367 // Otherwise, we have to decide whether to merge or drop.
368 // If the noise metric only increases minimally, we're off 368 // If the noise metric only increases minimally, we're off
369 // to a good start... 369 // to a good start...
370 if (((2*f[1].r.t < 3*f[1].r.p) && (f[1].r.t < 3600)) || 370 if (((2*f[1].r.t < 3*f[1].r.p) && (f[1].r.t < 3600)) ||
371 (f[1].r.t < 900) || (f[1].r.d < 900)) { 371 (f[1].r.t < 900) || (f[1].r.d < 900)) {
372 // ...and if noise decreases or the duplicate even field 372 // ...and if noise decreases or the duplicate even field
373 // is detected, we go ahead with the merge. 373 // is detected, we go ahead with the merge.
374 if ((3*f[0].r.e < f[0].r.o) || (2*f[1].r.t < f[1].r.p)) { 374 if ((3*f[0].r.e < f[0].r.o) || (2*f[1].r.t < f[1].r.p)) {
375 p->dropnext = 1; 375 p->dropnext = 1;
376 return F_MERGE; 376 return F_MERGE;
377 } 377 }
378 } 378 }
379 return F_DROP; 379 return F_DROP;
380 } 380 }
381 381
382 382
383 383
384 static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field) 384 static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field)
385 { 385 {
386 switch (field) { 386 switch (field) {
387 case 0: 387 case 0:
388 my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2, 388 my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
389 dmpi->stride[0]*2, mpi->stride[0]*2); 389 dmpi->stride[0]*2, mpi->stride[0]*2);
390 if (mpi->flags & MP_IMGFLAG_PLANAR) { 390 if (mpi->flags & MP_IMGFLAG_PLANAR) {
391 my_memcpy_pic(dmpi->planes[1], mpi->planes[1], 391 my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
392 mpi->chroma_width, mpi->chroma_height/2, 392 mpi->chroma_width, mpi->chroma_height/2,
393 dmpi->stride[1]*2, mpi->stride[1]*2); 393 dmpi->stride[1]*2, mpi->stride[1]*2);
394 my_memcpy_pic(dmpi->planes[2], mpi->planes[2], 394 my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
395 mpi->chroma_width, mpi->chroma_height/2, 395 mpi->chroma_width, mpi->chroma_height/2,
396 dmpi->stride[2]*2, mpi->stride[2]*2); 396 dmpi->stride[2]*2, mpi->stride[2]*2);
397 } 397 }
398 break; 398 break;
399 case 1: 399 case 1:
400 my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0], 400 my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
401 mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2, 401 mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
402 dmpi->stride[0]*2, mpi->stride[0]*2); 402 dmpi->stride[0]*2, mpi->stride[0]*2);
403 if (mpi->flags & MP_IMGFLAG_PLANAR) { 403 if (mpi->flags & MP_IMGFLAG_PLANAR) {
404 my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1], 404 my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
405 mpi->planes[1]+mpi->stride[1], 405 mpi->planes[1]+mpi->stride[1],
406 mpi->chroma_width, mpi->chroma_height/2, 406 mpi->chroma_width, mpi->chroma_height/2,
407 dmpi->stride[1]*2, mpi->stride[1]*2); 407 dmpi->stride[1]*2, mpi->stride[1]*2);
408 my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2], 408 my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
409 mpi->planes[2]+mpi->stride[2], 409 mpi->planes[2]+mpi->stride[2],
410 mpi->chroma_width, mpi->chroma_height/2, 410 mpi->chroma_width, mpi->chroma_height/2,
411 dmpi->stride[2]*2, mpi->stride[2]*2); 411 dmpi->stride[2]*2, mpi->stride[2]*2);
412 } 412 }
413 break; 413 break;
414 case 2: 414 case 2:
415 memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, 415 memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
416 dmpi->stride[0], mpi->stride[0]); 416 dmpi->stride[0], mpi->stride[0]);
417 if (mpi->flags & MP_IMGFLAG_PLANAR) { 417 if (mpi->flags & MP_IMGFLAG_PLANAR) {
418 memcpy_pic(dmpi->planes[1], mpi->planes[1], 418 memcpy_pic(dmpi->planes[1], mpi->planes[1],
419 mpi->chroma_width, mpi->chroma_height, 419 mpi->chroma_width, mpi->chroma_height,
420 dmpi->stride[1], mpi->stride[1]); 420 dmpi->stride[1], mpi->stride[1]);
421 memcpy_pic(dmpi->planes[2], mpi->planes[2], 421 memcpy_pic(dmpi->planes[2], mpi->planes[2],
422 mpi->chroma_width, mpi->chroma_height, 422 mpi->chroma_width, mpi->chroma_height,
423 dmpi->stride[2], mpi->stride[2]); 423 dmpi->stride[2], mpi->stride[2]);
424 } 424 }
425 break; 425 break;
426 } 426 }
427 } 427 }
428 428
429 static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi) 429 static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi)
430 { 430 {
431 struct vf_priv_s *p = vf->priv; 431 struct vf_priv_s *p = vf->priv;
432 int dropflag=0; 432 int dropflag=0;
433 433
434 if (!p->dropnext) switch (p->drop) { 434 if (!p->dropnext) switch (p->drop) {
435 case 0: 435 case 0:
436 dropflag = 0; 436 dropflag = 0;
437 break; 437 break;
438 case 1: 438 case 1:
439 dropflag = (++p->lastdrop >= 5); 439 dropflag = (++p->lastdrop >= 5);
440 break; 440 break;
441 case 2: 441 case 2:
442 dropflag = (++p->lastdrop >= 5) && (4*p->inframes <= 5*p->outframes); 442 dropflag = (++p->lastdrop >= 5) && (4*p->inframes <= 5*p->outframes);
443 break; 443 break;
444 } 444 }
445 445
446 if (dropflag) { 446 if (dropflag) {
447 //mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n", 447 //mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n",
448 // p->outframes, p->inframes, (float)p->outframes/p->inframes); 448 // p->outframes, p->inframes, (float)p->outframes/p->inframes);
449 mp_msg(MSGT_VFILTER, MSGL_V, "!"); 449 mp_msg(MSGT_VFILTER, MSGL_V, "!");
450 p->lastdrop = 0; 450 p->lastdrop = 0;
451 return 0; 451 return 0;
452 } 452 }
453 453
454 p->outframes++; 454 p->outframes++;
455 return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); 455 return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
456 } 456 }
457 457
458 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) 458 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
459 { 459 {
460 int ret=0; 460 int ret=0;
461 struct vf_priv_s *p = vf->priv; 461 struct vf_priv_s *p = vf->priv;
462 462
463 p->inframes++; 463 p->inframes++;
464 464
465 if (p->first) { /* hack */ 465 if (p->first) { /* hack */
466 p->first = 0; 466 p->first = 0;
467 return 1; 467 return 1;
468 } 468 }
469 469
470 if (!p->dmpi) p->dmpi = vf_get_image(vf->next, mpi->imgfmt, 470 if (!p->dmpi) p->dmpi = vf_get_image(vf->next, mpi->imgfmt,
471 MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | 471 MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
472 MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE, 472 MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
473 mpi->width, mpi->height); 473 mpi->width, mpi->height);
474 /* FIXME -- not correct, off by one frame! */ 474 /* FIXME -- not correct, off by one frame! */
475 p->dmpi->qscale = mpi->qscale; 475 p->dmpi->qscale = mpi->qscale;
476 p->dmpi->qstride = mpi->qstride; 476 p->dmpi->qstride = mpi->qstride;
477 p->dmpi->qscale_type = mpi->qscale_type; 477 p->dmpi->qscale_type = mpi->qscale_type;
478 478
479 switch (foo(p, mpi, p->dmpi)) { 479 switch (foo(p, mpi, p->dmpi)) {
480 case F_DROP: 480 case F_DROP:
481 copy_image(p->dmpi, mpi, 2); 481 copy_image(p->dmpi, mpi, 2);
482 ret = 0; 482 ret = 0;
483 p->lastdrop = 0; 483 p->lastdrop = 0;
484 mp_msg(MSGT_VFILTER, MSGL_V, "DROP\n"); 484 mp_msg(MSGT_VFILTER, MSGL_V, "DROP\n");
485 break; 485 break;
486 case F_MERGE: 486 case F_MERGE:
487 copy_image(p->dmpi, mpi, 0); 487 copy_image(p->dmpi, mpi, 0);
488 ret = do_put_image(vf, p->dmpi); 488 ret = do_put_image(vf, p->dmpi);
489 copy_image(p->dmpi, mpi, 1); 489 copy_image(p->dmpi, mpi, 1);
490 mp_msg(MSGT_VFILTER, MSGL_V, "MERGE\n"); 490 mp_msg(MSGT_VFILTER, MSGL_V, "MERGE\n");
491 p->dmpi = NULL; 491 p->dmpi = NULL;
492 break; 492 break;
493 case F_NEXT: 493 case F_NEXT:
494 copy_image(p->dmpi, mpi, 2); 494 copy_image(p->dmpi, mpi, 2);
495 ret = do_put_image(vf, p->dmpi); 495 ret = do_put_image(vf, p->dmpi);
496 mp_msg(MSGT_VFILTER, MSGL_V, "NEXT\n"); 496 mp_msg(MSGT_VFILTER, MSGL_V, "NEXT\n");
497 p->dmpi = NULL; 497 p->dmpi = NULL;
498 break; 498 break;
499 case F_SHOW: 499 case F_SHOW:
500 ret = do_put_image(vf, p->dmpi); 500 ret = do_put_image(vf, p->dmpi);
501 copy_image(p->dmpi, mpi, 2); 501 copy_image(p->dmpi, mpi, 2);
502 mp_msg(MSGT_VFILTER, MSGL_V, "OK\n"); 502 mp_msg(MSGT_VFILTER, MSGL_V, "OK\n");
503 p->dmpi = NULL; 503 p->dmpi = NULL;
504 break; 504 break;
505 } 505 }
506 return ret; 506 return ret;
507 } 507 }
508 508
509 static int query_format(struct vf_instance *vf, unsigned int fmt) 509 static int query_format(struct vf_instance *vf, unsigned int fmt)
510 { 510 {
511 switch (fmt) { 511 switch (fmt) {
512 case IMGFMT_YV12: 512 case IMGFMT_YV12:
513 case IMGFMT_IYUV: 513 case IMGFMT_IYUV:
514 case IMGFMT_I420: 514 case IMGFMT_I420:
515 return vf_next_query_format(vf, fmt); 515 return vf_next_query_format(vf, fmt);
516 } 516 }
517 return 0; 517 return 0;
518 } 518 }
519 519
520 static void uninit(struct vf_instance *vf) 520 static void uninit(struct vf_instance *vf)
521 { 521 {
522 free(vf->priv); 522 free(vf->priv);
523 } 523 }
524 524
525 static int vf_open(vf_instance_t *vf, char *args) 525 static int vf_open(vf_instance_t *vf, char *args)
526 { 526 {
527 struct vf_priv_s *p; 527 struct vf_priv_s *p;
528 vf->put_image = put_image; 528 vf->put_image = put_image;
529 vf->query_format = query_format; 529 vf->query_format = query_format;
530 vf->uninit = uninit; 530 vf->uninit = uninit;
531 vf->default_reqs = VFCAP_ACCEPT_STRIDE; 531 vf->default_reqs = VFCAP_ACCEPT_STRIDE;
532 vf->priv = p = calloc(1, sizeof(struct vf_priv_s)); 532 vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
533 p->drop = 0; 533 p->drop = 0;
534 p->first = 1; 534 p->first = 1;
535 if (args) sscanf(args, "%d", &p->drop); 535 if (args) sscanf(args, "%d", &p->drop);
536 block_diffs = block_diffs_C; 536 block_diffs = block_diffs_C;
537 #if HAVE_MMX && HAVE_EBX_AVAILABLE 537 #if HAVE_MMX && HAVE_EBX_AVAILABLE
538 if(gCpuCaps.hasMMX) block_diffs = block_diffs_MMX; 538 if(gCpuCaps.hasMMX) block_diffs = block_diffs_MMX;
539 #endif 539 #endif
540 return 1; 540 return 1;
541 } 541 }
542 542
543 const vf_info_t vf_info_ivtc = { 543 const vf_info_t vf_info_ivtc = {
544 "inverse telecine, take 2", 544 "inverse telecine, take 2",
545 "ivtc", 545 "ivtc",