Mercurial > mplayer.hg
comparison libmpcodecs/vf_divtc.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 | 02214457c955 |
comparison
equal
deleted
inserted
replaced
32701:02bc7c860503 | 32702:7af3e6f901fd |
---|---|
54 #if HAVE_MMX && HAVE_EBX_AVAILABLE | 54 #if HAVE_MMX && HAVE_EBX_AVAILABLE |
55 static int diff_MMX(unsigned char *old, unsigned char *new, int os, int ns) | 55 static int diff_MMX(unsigned char *old, unsigned char *new, int os, int ns) |
56 { | 56 { |
57 volatile short out[4]; | 57 volatile short out[4]; |
58 __asm__ ( | 58 __asm__ ( |
59 "movl $8, %%ecx \n\t" | 59 "movl $8, %%ecx \n\t" |
60 "pxor %%mm4, %%mm4 \n\t" | 60 "pxor %%mm4, %%mm4 \n\t" |
61 "pxor %%mm7, %%mm7 \n\t" | 61 "pxor %%mm7, %%mm7 \n\t" |
62 | 62 |
63 ASMALIGN(4) | 63 ASMALIGN(4) |
64 "1: \n\t" | 64 "1: \n\t" |
65 | 65 |
66 "movq (%%"REG_S"), %%mm0 \n\t" | 66 "movq (%%"REG_S"), %%mm0 \n\t" |
67 "movq (%%"REG_S"), %%mm2 \n\t" | 67 "movq (%%"REG_S"), %%mm2 \n\t" |
68 "add %%"REG_a", %%"REG_S" \n\t" | 68 "add %%"REG_a", %%"REG_S" \n\t" |
69 "movq (%%"REG_D"), %%mm1 \n\t" | 69 "movq (%%"REG_D"), %%mm1 \n\t" |
70 "add %%"REG_b", %%"REG_D" \n\t" | 70 "add %%"REG_b", %%"REG_D" \n\t" |
71 "psubusb %%mm1, %%mm2 \n\t" | 71 "psubusb %%mm1, %%mm2 \n\t" |
72 "psubusb %%mm0, %%mm1 \n\t" | 72 "psubusb %%mm0, %%mm1 \n\t" |
73 "movq %%mm2, %%mm0 \n\t" | 73 "movq %%mm2, %%mm0 \n\t" |
74 "movq %%mm1, %%mm3 \n\t" | 74 "movq %%mm1, %%mm3 \n\t" |
75 "punpcklbw %%mm7, %%mm0 \n\t" | 75 "punpcklbw %%mm7, %%mm0 \n\t" |
76 "punpcklbw %%mm7, %%mm1 \n\t" | 76 "punpcklbw %%mm7, %%mm1 \n\t" |
77 "punpckhbw %%mm7, %%mm2 \n\t" | 77 "punpckhbw %%mm7, %%mm2 \n\t" |
78 "punpckhbw %%mm7, %%mm3 \n\t" | 78 "punpckhbw %%mm7, %%mm3 \n\t" |
79 "paddw %%mm0, %%mm4 \n\t" | 79 "paddw %%mm0, %%mm4 \n\t" |
80 "paddw %%mm1, %%mm4 \n\t" | 80 "paddw %%mm1, %%mm4 \n\t" |
81 "paddw %%mm2, %%mm4 \n\t" | 81 "paddw %%mm2, %%mm4 \n\t" |
82 "paddw %%mm3, %%mm4 \n\t" | 82 "paddw %%mm3, %%mm4 \n\t" |
83 | 83 |
84 "decl %%ecx \n\t" | 84 "decl %%ecx \n\t" |
85 "jnz 1b \n\t" | 85 "jnz 1b \n\t" |
86 "movq %%mm4, (%%"REG_d") \n\t" | 86 "movq %%mm4, (%%"REG_d") \n\t" |
87 "emms \n\t" | 87 "emms \n\t" |
88 : | 88 : |
89 : "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out) | 89 : "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out) |
90 : "%ecx", "memory" | 90 : "%ecx", "memory" |
91 ); | 91 ); |
92 return out[0]+out[1]+out[2]+out[3]; | 92 return out[0]+out[1]+out[2]+out[3]; |
93 } | 93 } |
94 #endif | 94 #endif |
95 | 95 |
96 static int diff_C(unsigned char *old, unsigned char *new, int os, int ns) | 96 static int diff_C(unsigned char *old, unsigned char *new, int os, int ns) |
97 { | 97 { |
98 int x, y, d=0; | 98 int x, y, d=0; |
99 | 99 |
100 for(y=8; y; y--, new+=ns, old+=os) | 100 for(y=8; y; y--, new+=ns, old+=os) |
101 for(x=8; x; x--) | 101 for(x=8; x; x--) |
102 d+=abs(new[x]-old[x]); | 102 d+=abs(new[x]-old[x]); |
103 | 103 |
104 return d; | 104 return d; |
105 } | 105 } |
106 | 106 |
107 static int (*diff)(unsigned char *, unsigned char *, int, int); | 107 static int (*diff)(unsigned char *, unsigned char *, int, int); |
108 | 108 |
109 static int diff_plane(unsigned char *old, unsigned char *new, | 109 static int diff_plane(unsigned char *old, unsigned char *new, |
110 int w, int h, int os, int ns, int arg) | 110 int w, int h, int os, int ns, int arg) |
111 { | 111 { |
112 int x, y, d, max=0, sum=0, n=0; | 112 int x, y, d, max=0, sum=0, n=0; |
113 | 113 |
114 for(y=0; y<h-7; y+=8) | 114 for(y=0; y<h-7; y+=8) |
115 { | 115 { |
116 for(x=0; x<w-7; x+=8) | 116 for(x=0; x<w-7; x+=8) |
117 { | 117 { |
118 d=diff(old+x+y*os, new+x+y*ns, os, ns); | 118 d=diff(old+x+y*os, new+x+y*ns, os, ns); |
119 if(d>max) max=d; | 119 if(d>max) max=d; |
120 sum+=d; | 120 sum+=d; |
121 n++; | 121 n++; |
122 } | 122 } |
123 } | 123 } |
124 | 124 |
125 return (sum+n*max)/2; | 125 return (sum+n*max)/2; |
126 } | 126 } |
127 | 127 |
128 /* | 128 /* |
129 static unsigned int checksum_plane(unsigned char *p, unsigned char *z, | 129 static unsigned int checksum_plane(unsigned char *p, unsigned char *z, |
130 int w, int h, int s, int zs, int arg) | 130 int w, int h, int s, int zs, int arg) |
131 { | 131 { |
132 unsigned int shift, sum; | 132 unsigned int shift, sum; |
133 unsigned char *e; | 133 unsigned char *e; |
134 | 134 |
135 for(sum=0; h; h--, p+=s-w) | 135 for(sum=0; h; h--, p+=s-w) |
136 for(e=p+w, shift=32; p<e;) | 136 for(e=p+w, shift=32; p<e;) |
137 sum^=(*p++)<<(shift=(shift-8)&31); | 137 sum^=(*p++)<<(shift=(shift-8)&31); |
138 | 138 |
139 return sum; | 139 return sum; |
140 } | 140 } |
141 */ | 141 */ |
142 | 142 |
143 static unsigned int checksum_plane(unsigned char *p, unsigned char *z, | 143 static unsigned int checksum_plane(unsigned char *p, unsigned char *z, |
144 int w, int h, int s, int zs, int arg) | 144 int w, int h, int s, int zs, int arg) |
145 { | 145 { |
146 unsigned int shift; | 146 unsigned int shift; |
147 uint32_t sum, t; | 147 uint32_t sum, t; |
148 unsigned char *e, *e2; | 148 unsigned char *e, *e2; |
149 #if HAVE_FAST_64BIT | 149 #if HAVE_FAST_64BIT |
154 wsum_t wsum; | 154 wsum_t wsum; |
155 | 155 |
156 for(sum=0; h; h--, p+=s-w) | 156 for(sum=0; h; h--, p+=s-w) |
157 { | 157 { |
158 for(shift=0, e=p+w; (int)p&(sizeof(wsum_t)-1) && p<e;) | 158 for(shift=0, e=p+w; (int)p&(sizeof(wsum_t)-1) && p<e;) |
159 sum^=*p++<<(shift=(shift-8)&31); | 159 sum^=*p++<<(shift=(shift-8)&31); |
160 | 160 |
161 for(wsum=0, e2=e-sizeof(wsum_t)+1; p<e2; p+=sizeof(wsum_t)) | 161 for(wsum=0, e2=e-sizeof(wsum_t)+1; p<e2; p+=sizeof(wsum_t)) |
162 wsum^=*(wsum_t *)p; | 162 wsum^=*(wsum_t *)p; |
163 | 163 |
164 #if HAVE_FAST_64BIT | 164 #if HAVE_FAST_64BIT |
165 t=be2me_32((uint32_t)(wsum>>32^wsum)); | 165 t=be2me_32((uint32_t)(wsum>>32^wsum)); |
166 #else | 166 #else |
167 t=be2me_32(wsum); | 167 t=be2me_32(wsum); |
168 #endif | 168 #endif |
169 | 169 |
170 for(sum^=(t<<shift|t>>(32-shift)); p<e;) | 170 for(sum^=(t<<shift|t>>(32-shift)); p<e;) |
171 sum^=*p++<<(shift=(shift-8)&31); | 171 sum^=*p++<<(shift=(shift-8)&31); |
172 } | 172 } |
173 | 173 |
174 return sum; | 174 return sum; |
175 } | 175 } |
176 | 176 |
177 static int deghost_plane(unsigned char *d, unsigned char *s, | 177 static int deghost_plane(unsigned char *d, unsigned char *s, |
178 int w, int h, int ds, int ss, int threshold) | 178 int w, int h, int ds, int ss, int threshold) |
179 { | 179 { |
180 int t; | 180 int t; |
181 unsigned char *e; | 181 unsigned char *e; |
182 | 182 |
183 for(; h; h--, s+=ss-w, d+=ds-w) | 183 for(; h; h--, s+=ss-w, d+=ds-w) |
184 for(e=d+w; d<e; d++, s++) | 184 for(e=d+w; d<e; d++, s++) |
185 if(abs(*d-*s)>=threshold) | 185 if(abs(*d-*s)>=threshold) |
186 *d=(t=(*d<<1)-*s)<0?0:t>255?255:t; | 186 *d=(t=(*d<<1)-*s)<0?0:t>255?255:t; |
187 | 187 |
188 return 0; | 188 return 0; |
189 } | 189 } |
190 | 190 |
191 static int copyop(unsigned char *d, unsigned char *s, int bpl, int h, int dstride, int sstride, int dummy) { | 191 static int copyop(unsigned char *d, unsigned char *s, int bpl, int h, int dstride, int sstride, int dummy) { |
192 memcpy_pic(d, s, bpl, h, dstride, sstride); | 192 memcpy_pic(d, s, bpl, h, dstride, sstride); |
193 return 0; | 193 return 0; |
194 } | 194 } |
195 | 195 |
196 static int imgop(int(*planeop)(unsigned char *, unsigned char *, | 196 static int imgop(int(*planeop)(unsigned char *, unsigned char *, |
197 int, int, int, int, int), | 197 int, int, int, int, int), |
198 mp_image_t *dst, mp_image_t *src, int arg) | 198 mp_image_t *dst, mp_image_t *src, int arg) |
199 { | 199 { |
200 if(dst->flags&MP_IMGFLAG_PLANAR) | 200 if(dst->flags&MP_IMGFLAG_PLANAR) |
201 return planeop(dst->planes[0], src?src->planes[0]:0, | 201 return planeop(dst->planes[0], src?src->planes[0]:0, |
202 dst->w, dst->h, | 202 dst->w, dst->h, |
203 dst->stride[0], src?src->stride[0]:0, arg)+ | 203 dst->stride[0], src?src->stride[0]:0, arg)+ |
204 planeop(dst->planes[1], src?src->planes[1]:0, | 204 planeop(dst->planes[1], src?src->planes[1]:0, |
205 dst->chroma_width, dst->chroma_height, | 205 dst->chroma_width, dst->chroma_height, |
206 dst->stride[1], src?src->stride[1]:0, arg)+ | 206 dst->stride[1], src?src->stride[1]:0, arg)+ |
207 planeop(dst->planes[2], src?src->planes[2]:0, | 207 planeop(dst->planes[2], src?src->planes[2]:0, |
208 dst->chroma_width, dst->chroma_height, | 208 dst->chroma_width, dst->chroma_height, |
209 dst->stride[2], src?src->stride[2]:0, arg); | 209 dst->stride[2], src?src->stride[2]:0, arg); |
210 | 210 |
211 return planeop(dst->planes[0], src?src->planes[0]:0, | 211 return planeop(dst->planes[0], src?src->planes[0]:0, |
212 dst->w*(dst->bpp/8), dst->h, | 212 dst->w*(dst->bpp/8), dst->h, |
213 dst->stride[0], src?src->stride[0]:0, arg); | 213 dst->stride[0], src?src->stride[0]:0, arg); |
214 } | 214 } |
215 | 215 |
216 /* | 216 /* |
217 * Find the phase in which the telecine pattern fits best to the | 217 * Find the phase in which the telecine pattern fits best to the |
218 * given 5 frame slice of frame difference measurements. | 218 * given 5 frame slice of frame difference measurements. |
220 * If phase1 and phase2 are not negative, only the two specified | 220 * If phase1 and phase2 are not negative, only the two specified |
221 * phases are tested. | 221 * phases are tested. |
222 */ | 222 */ |
223 | 223 |
224 static int match(struct vf_priv_s *p, int *diffs, | 224 static int match(struct vf_priv_s *p, int *diffs, |
225 int phase1, int phase2, double *strength) | 225 int phase1, int phase2, double *strength) |
226 { | 226 { |
227 static const int pattern1[]={ -4, 1, 1, 1, 1 }, | 227 static const int pattern1[]={ -4, 1, 1, 1, 1 }, |
228 pattern2[]={ -2, -3, 4, 4, -3 }, *pattern; | 228 pattern2[]={ -2, -3, 4, 4, -3 }, *pattern; |
229 int f, m, n, t[5]; | 229 int f, m, n, t[5]; |
230 | 230 |
231 pattern=p->deghost>0?pattern2:pattern1; | 231 pattern=p->deghost>0?pattern2:pattern1; |
232 | 232 |
233 for(f=0; f<5; f++) | 233 for(f=0; f<5; f++) |
234 { | 234 { |
235 if(phase1<0 || phase2<0 || f==phase1 || f==phase2) | 235 if(phase1<0 || phase2<0 || f==phase1 || f==phase2) |
236 { | 236 { |
237 for(n=t[f]=0; n<5; n++) | 237 for(n=t[f]=0; n<5; n++) |
238 t[f]+=diffs[n]*pattern[(n-f+5)%5]; | 238 t[f]+=diffs[n]*pattern[(n-f+5)%5]; |
239 } | 239 } |
240 else | 240 else |
241 t[f]=INT_MIN; | 241 t[f]=INT_MIN; |
242 } | 242 } |
243 | 243 |
244 /* find the best match */ | 244 /* find the best match */ |
245 for(m=0, n=1; n<5; n++) | 245 for(m=0, n=1; n<5; n++) |
246 if(t[n]>t[m]) m=n; | 246 if(t[n]>t[m]) m=n; |
247 | 247 |
248 if(strength) | 248 if(strength) |
249 { | 249 { |
250 /* the second best match */ | 250 /* the second best match */ |
251 for(f=m?0:1, n=f+1; n<5; n++) | 251 for(f=m?0:1, n=f+1; n<5; n++) |
252 if(n!=m && t[n]>t[f]) f=n; | 252 if(n!=m && t[n]>t[f]) f=n; |
253 | 253 |
254 *strength=(t[m]>0?(double)(t[m]-t[f])/t[m]:0.0); | 254 *strength=(t[m]>0?(double)(t[m]-t[f])/t[m]:0.0); |
255 } | 255 } |
256 | 256 |
257 return m; | 257 return m; |
264 struct vf_priv_s *p=vf->priv; | 264 struct vf_priv_s *p=vf->priv; |
265 unsigned int checksum; | 265 unsigned int checksum; |
266 double d; | 266 double d; |
267 | 267 |
268 dmpi=vf_get_image(vf->next, mpi->imgfmt, | 268 dmpi=vf_get_image(vf->next, mpi->imgfmt, |
269 MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | | 269 MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | |
270 MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE, | 270 MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE, |
271 mpi->width, mpi->height); | 271 mpi->width, mpi->height); |
272 vf_clone_mpi_attributes(dmpi, mpi); | 272 vf_clone_mpi_attributes(dmpi, mpi); |
273 | 273 |
274 newphase=p->phase; | 274 newphase=p->phase; |
275 | 275 |
276 switch(p->pass) | 276 switch(p->pass) |
277 { | 277 { |
278 case 1: | 278 case 1: |
279 fprintf(p->file, "%08x %d\n", | 279 fprintf(p->file, "%08x %d\n", |
280 (unsigned int)imgop((void *)checksum_plane, mpi, 0, 0), | 280 (unsigned int)imgop((void *)checksum_plane, mpi, 0, 0), |
281 p->frameno?imgop(diff_plane, dmpi, mpi, 0):0); | 281 p->frameno?imgop(diff_plane, dmpi, mpi, 0):0); |
282 break; | 282 break; |
283 | 283 |
284 case 2: | 284 case 2: |
285 if(p->frameno/5>p->bcount) | 285 if(p->frameno/5>p->bcount) |
286 { | 286 { |
287 mp_msg(MSGT_VFILTER, MSGL_ERR, | 287 mp_msg(MSGT_VFILTER, MSGL_ERR, |
288 "\n%s: Log file ends prematurely! " | 288 "\n%s: Log file ends prematurely! " |
289 "Switching to one pass mode.\n", vf->info->name); | 289 "Switching to one pass mode.\n", vf->info->name); |
290 p->pass=0; | 290 p->pass=0; |
291 break; | 291 break; |
292 } | 292 } |
293 | 293 |
294 checksum=(unsigned int)imgop((void *)checksum_plane, mpi, 0, 0); | 294 checksum=(unsigned int)imgop((void *)checksum_plane, mpi, 0, 0); |
295 | 295 |
296 if(checksum!=p->csdata[p->frameno]) | 296 if(checksum!=p->csdata[p->frameno]) |
297 { | 297 { |
298 for(f=0; f<100; f++) | 298 for(f=0; f<100; f++) |
299 if(p->frameno+f<p->fcount && p->csdata[p->frameno+f]==checksum) | 299 if(p->frameno+f<p->fcount && p->csdata[p->frameno+f]==checksum) |
300 break; | 300 break; |
301 else if(p->frameno-f>=0 && p->csdata[p->frameno-f]==checksum) | 301 else if(p->frameno-f>=0 && p->csdata[p->frameno-f]==checksum) |
302 { | 302 { |
303 f=-f; | 303 f=-f; |
304 break; | 304 break; |
305 } | 305 } |
306 | 306 |
307 if(f<100) | 307 if(f<100) |
308 { | 308 { |
309 mp_msg(MSGT_VFILTER, MSGL_INFO, | 309 mp_msg(MSGT_VFILTER, MSGL_INFO, |
310 "\n%s: Mismatch with pass-1: %+d frame(s).\n", | 310 "\n%s: Mismatch with pass-1: %+d frame(s).\n", |
311 vf->info->name, f); | 311 vf->info->name, f); |
312 | 312 |
313 p->frameno+=f; | 313 p->frameno+=f; |
314 p->misscount=0; | 314 p->misscount=0; |
315 } | 315 } |
316 else if(p->misscount++>=30) | 316 else if(p->misscount++>=30) |
317 { | 317 { |
318 mp_msg(MSGT_VFILTER, MSGL_ERR, | 318 mp_msg(MSGT_VFILTER, MSGL_ERR, |
319 "\n%s: Sync with pass-1 lost! " | 319 "\n%s: Sync with pass-1 lost! " |
320 "Switching to one pass mode.\n", vf->info->name); | 320 "Switching to one pass mode.\n", vf->info->name); |
321 p->pass=0; | 321 p->pass=0; |
322 break; | 322 break; |
323 } | 323 } |
324 } | 324 } |
325 | 325 |
326 n=(p->frameno)/5; | 326 n=(p->frameno)/5; |
327 if(n>=p->bcount) n=p->bcount-1; | 327 if(n>=p->bcount) n=p->bcount-1; |
328 | 328 |
329 newphase=p->bdata[n]; | 329 newphase=p->bdata[n]; |
330 break; | 330 break; |
331 | 331 |
332 default: | 332 default: |
333 if(p->frameno) | 333 if(p->frameno) |
334 { | 334 { |
335 int *sump=p->sum+p->frameno%5, | 335 int *sump=p->sum+p->frameno%5, |
336 *histp=p->history+p->frameno%p->window; | 336 *histp=p->history+p->frameno%p->window; |
337 | 337 |
338 *sump-=*histp; | 338 *sump-=*histp; |
339 *sump+=(*histp=imgop(diff_plane, dmpi, mpi, 0)); | 339 *sump+=(*histp=imgop(diff_plane, dmpi, mpi, 0)); |
340 } | 340 } |
341 | 341 |
342 m=match(p, p->sum, -1, -1, &d); | 342 m=match(p, p->sum, -1, -1, &d); |
343 | 343 |
344 if(d>=p->threshold) | 344 if(d>=p->threshold) |
345 newphase=m; | 345 newphase=m; |
346 } | 346 } |
347 | 347 |
348 n=p->ocount++%5; | 348 n=p->ocount++%5; |
349 | 349 |
350 if(newphase!=p->phase && ((p->phase+4)%5<n)==((newphase+4)%5<n)) | 350 if(newphase!=p->phase && ((p->phase+4)%5<n)==((newphase+4)%5<n)) |
351 { | 351 { |
352 p->phase=newphase; | 352 p->phase=newphase; |
353 mp_msg(MSGT_VFILTER, MSGL_STATUS, | 353 mp_msg(MSGT_VFILTER, MSGL_STATUS, |
354 "\n%s: Telecine phase %d.\n", vf->info->name, p->phase); | 354 "\n%s: Telecine phase %d.\n", vf->info->name, p->phase); |
355 } | 355 } |
356 | 356 |
357 switch((p->frameno++-p->phase+10)%5) | 357 switch((p->frameno++-p->phase+10)%5) |
358 { | 358 { |
359 case 0: | 359 case 0: |
360 imgop(copyop, dmpi, mpi, 0); | 360 imgop(copyop, dmpi, mpi, 0); |
361 return 0; | 361 return 0; |
362 | 362 |
363 case 4: | 363 case 4: |
364 if(p->deghost>0) | 364 if(p->deghost>0) |
365 { | 365 { |
366 tmpi=vf_get_image(vf->next, mpi->imgfmt, | 366 tmpi=vf_get_image(vf->next, mpi->imgfmt, |
367 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | | 367 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | |
368 MP_IMGFLAG_READABLE, | 368 MP_IMGFLAG_READABLE, |
369 mpi->width, mpi->height); | 369 mpi->width, mpi->height); |
370 vf_clone_mpi_attributes(tmpi, mpi); | 370 vf_clone_mpi_attributes(tmpi, mpi); |
371 | 371 |
372 imgop(copyop, tmpi, mpi, 0); | 372 imgop(copyop, tmpi, mpi, 0); |
373 imgop(deghost_plane, tmpi, dmpi, p->deghost); | 373 imgop(deghost_plane, tmpi, dmpi, p->deghost); |
374 imgop(copyop, dmpi, mpi, 0); | 374 imgop(copyop, dmpi, mpi, 0); |
375 return vf_next_put_image(vf, tmpi, MP_NOPTS_VALUE); | 375 return vf_next_put_image(vf, tmpi, MP_NOPTS_VALUE); |
376 } | 376 } |
377 } | 377 } |
378 | 378 |
379 imgop(copyop, dmpi, mpi, 0); | 379 imgop(copyop, dmpi, mpi, 0); |
380 return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); | 380 return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); |
381 } | 381 } |
393 | 393 |
394 n=15; | 394 n=15; |
395 while(fgets(lbuf, 256, p->file)) | 395 while(fgets(lbuf, 256, p->file)) |
396 { | 396 { |
397 if(n>=bufsize-19) | 397 if(n>=bufsize-19) |
398 { | 398 { |
399 bufsize=bufsize?bufsize*2:30000; | 399 bufsize=bufsize?bufsize*2:30000; |
400 if((bp=realloc(buf, bufsize*sizeof *buf))) buf=bp; | 400 if((bp=realloc(buf, bufsize*sizeof *buf))) buf=bp; |
401 if((cp=realloc(cbuf, bufsize*sizeof *cbuf))) cbuf=cp; | 401 if((cp=realloc(cbuf, bufsize*sizeof *cbuf))) cbuf=cp; |
402 | 402 |
403 if(!bp || !cp) | 403 if(!bp || !cp) |
404 { | 404 { |
405 mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: Not enough memory.\n", | 405 mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: Not enough memory.\n", |
406 vf_info_divtc.name); | 406 vf_info_divtc.name); |
407 free(buf); | 407 free(buf); |
408 free(cbuf); | 408 free(cbuf); |
409 return 0; | 409 return 0; |
410 } | 410 } |
411 } | 411 } |
412 sscanf(lbuf, "%x %d", cbuf+n, buf+n); | 412 sscanf(lbuf, "%x %d", cbuf+n, buf+n); |
413 n++; | 413 n++; |
414 } | 414 } |
415 | 415 |
416 if(!n) | 416 if(!n) |
417 { | 417 { |
418 mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: Empty 2-pass log file.\n", | 418 mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: Empty 2-pass log file.\n", |
419 vf_info_divtc.name); | 419 vf_info_divtc.name); |
420 free(buf); | 420 free(buf); |
421 free(cbuf); | 421 free(cbuf); |
422 return 0; | 422 return 0; |
423 } | 423 } |
424 | 424 |
450 { | 450 { |
451 int deghost=-p->deghost; | 451 int deghost=-p->deghost; |
452 double s0=0.0, s1=0.0; | 452 double s0=0.0, s1=0.0; |
453 | 453 |
454 for(f=0; f<n; f+=5) | 454 for(f=0; f<n; f+=5) |
455 { | 455 { |
456 p->deghost=0; match(p, buf+f, -1, -1, &d); s0+=d; | 456 p->deghost=0; match(p, buf+f, -1, -1, &d); s0+=d; |
457 p->deghost=1; match(p, buf+f, -1, -1, &d); s1+=d; | 457 p->deghost=1; match(p, buf+f, -1, -1, &d); s1+=d; |
458 } | 458 } |
459 | 459 |
460 p->deghost=s1>s0?deghost:0; | 460 p->deghost=s1>s0?deghost:0; |
461 | 461 |
462 mp_msg(MSGT_VFILTER, MSGL_INFO, | 462 mp_msg(MSGT_VFILTER, MSGL_INFO, |
463 "%s: Deghosting %-3s (relative pattern strength %+.2fdB).\n", | 463 "%s: Deghosting %-3s (relative pattern strength %+.2fdB).\n", |
464 vf_info_divtc.name, | 464 vf_info_divtc.name, |
465 p->deghost?"ON":"OFF", | 465 p->deghost?"ON":"OFF", |
466 10.0*log10(s1/s0)); | 466 10.0*log10(s1/s0)); |
467 } | 467 } |
468 | 468 |
469 /* analyze the data */ | 469 /* analyze the data */ |
470 | 470 |
471 for(f=0; f<5; f++) | 471 for(f=0; f<5; f++) |
472 for(sum[f]=0, n=-15; n<20; n+=5) | 472 for(sum[f]=0, n=-15; n<20; n+=5) |
473 sum[f]+=buf[n+f]; | 473 sum[f]+=buf[n+f]; |
474 | 474 |
475 for(f=0; f<b; f++) | 475 for(f=0; f<b; f++) |
476 { | 476 { |
477 m=match(p, sum, -1, -1, &d); | 477 m=match(p, sum, -1, -1, &d); |
478 | 478 |
479 if(d>=p->threshold) | 479 if(d>=p->threshold) |
480 pbuf[f]=m; | 480 pbuf[f]=m; |
481 | 481 |
482 if(f<b-1) | 482 if(f<b-1) |
483 for(n=0; n<5; n++) | 483 for(n=0; n<5; n++) |
484 sum[n]=sum[n]-buf[5*(f-3)+n]+buf[5*(f+4)+n]; | 484 sum[n]=sum[n]-buf[5*(f-3)+n]+buf[5*(f+4)+n]; |
485 } | 485 } |
486 | 486 |
487 /* fill in the gaps */ | 487 /* fill in the gaps */ |
488 | 488 |
489 /* the beginning */ | 489 /* the beginning */ |
491 | 491 |
492 if(f==b) | 492 if(f==b) |
493 { | 493 { |
494 free(buf-15); | 494 free(buf-15); |
495 mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: No telecine pattern found!\n", | 495 mp_msg(MSGT_VFILTER, MSGL_FATAL, "%s: No telecine pattern found!\n", |
496 vf_info_divtc.name); | 496 vf_info_divtc.name); |
497 return 0; | 497 return 0; |
498 } | 498 } |
499 | 499 |
500 for(n=0; n<f; pbuf[n++]=pbuf[f]); | 500 for(n=0; n<f; pbuf[n++]=pbuf[f]); |
501 | 501 |
509 while(f<b && pbuf[f]!=-1) f++; | 509 while(f<b && pbuf[f]!=-1) f++; |
510 if(f==b) break; | 510 if(f==b) break; |
511 for(n=f; pbuf[n]==-1; n++); | 511 for(n=f; pbuf[n]==-1; n++); |
512 | 512 |
513 if(pbuf[f-1]==pbuf[n]) | 513 if(pbuf[f-1]==pbuf[n]) |
514 { | 514 { |
515 /* just a gap */ | 515 /* just a gap */ |
516 while(f<n) pbuf[f++]=pbuf[n]; | 516 while(f<n) pbuf[f++]=pbuf[n]; |
517 } | 517 } |
518 else | 518 else |
519 { | 519 { |
520 /* phase change, reanalyze the original data in the gap with zero | 520 /* phase change, reanalyze the original data in the gap with zero |
521 threshold for only the two phases that appear at the ends */ | 521 threshold for only the two phases that appear at the ends */ |
522 | 522 |
523 for(i=0; i<5; i++) | 523 for(i=0; i<5; i++) |
524 for(sum[i]=0, j=5*f-15; j<5*f; j+=5) | 524 for(sum[i]=0, j=5*f-15; j<5*f; j+=5) |
525 sum[i]+=buf[i+j]; | 525 sum[i]+=buf[i+j]; |
526 | 526 |
527 for(i=f; i<n; i++) | 527 for(i=f; i<n; i++) |
528 { | 528 { |
529 pbuf[i]=match(p, sum, pbuf[f-1], pbuf[n], 0); | 529 pbuf[i]=match(p, sum, pbuf[f-1], pbuf[n], 0); |
530 | 530 |
531 for(j=0; j<5; j++) | 531 for(j=0; j<5; j++) |
532 sum[j]=sum[j]-buf[5*(i-3)+j]+buf[5*(i+4)+j]; | 532 sum[j]=sum[j]-buf[5*(i-3)+j]+buf[5*(i+4)+j]; |
533 } | 533 } |
534 | 534 |
535 /* estimate the transition point by dividing the gap | 535 /* estimate the transition point by dividing the gap |
536 in the same proportion as the number of matches of each kind */ | 536 in the same proportion as the number of matches of each kind */ |
537 | 537 |
538 for(i=f, m=f; i<n; i++) | 538 for(i=f, m=f; i<n; i++) |
539 if(pbuf[i]==pbuf[f-1]) m++; | 539 if(pbuf[i]==pbuf[f-1]) m++; |
540 | 540 |
541 /* find the transition of the right direction nearest to the | 541 /* find the transition of the right direction nearest to the |
542 estimated point */ | 542 estimated point */ |
543 | 543 |
544 if(m>f && m<n) | 544 if(m>f && m<n) |
545 { | 545 { |
546 for(j=m; j>f; j--) | 546 for(j=m; j>f; j--) |
547 if(pbuf[j-1]==pbuf[f-1] && pbuf[j]==pbuf[n]) break; | 547 if(pbuf[j-1]==pbuf[f-1] && pbuf[j]==pbuf[n]) break; |
548 for(s=m; s<n; s++) | 548 for(s=m; s<n; s++) |
549 if(pbuf[s-1]==pbuf[f-1] && pbuf[s]==pbuf[n]) break; | 549 if(pbuf[s-1]==pbuf[f-1] && pbuf[s]==pbuf[n]) break; |
550 | 550 |
551 m=(s-m<m-j)?s:j; | 551 m=(s-m<m-j)?s:j; |
552 } | 552 } |
553 | 553 |
554 /* and rewrite the data to allow only this one transition */ | 554 /* and rewrite the data to allow only this one transition */ |
555 | 555 |
556 for(i=f; i<m; i++) | 556 for(i=f; i<m; i++) |
557 pbuf[i]=pbuf[f-1]; | 557 pbuf[i]=pbuf[f-1]; |
558 | 558 |
559 for(; i<n; i++) | 559 for(; i<n; i++) |
560 pbuf[i]=pbuf[n]; | 560 pbuf[i]=pbuf[n]; |
561 | 561 |
562 f=n; | 562 f=n; |
563 } | 563 } |
564 } | 564 } |
565 | 565 |
566 free(buf-15); | 566 free(buf-15); |
567 | 567 |
568 return 1; | 568 return 1; |
575 case IMGFMT_444P: case IMGFMT_IYUV: case IMGFMT_RGB24: | 575 case IMGFMT_444P: case IMGFMT_IYUV: case IMGFMT_RGB24: |
576 case IMGFMT_422P: case IMGFMT_UYVY: case IMGFMT_BGR24: | 576 case IMGFMT_422P: case IMGFMT_UYVY: case IMGFMT_BGR24: |
577 case IMGFMT_411P: case IMGFMT_YUY2: case IMGFMT_IF09: | 577 case IMGFMT_411P: case IMGFMT_YUY2: case IMGFMT_IF09: |
578 case IMGFMT_YV12: case IMGFMT_I420: case IMGFMT_YVU9: | 578 case IMGFMT_YV12: case IMGFMT_I420: case IMGFMT_YVU9: |
579 case IMGFMT_IUYV: case IMGFMT_Y800: case IMGFMT_Y8: | 579 case IMGFMT_IUYV: case IMGFMT_Y800: case IMGFMT_Y8: |
580 return vf_next_query_format(vf,fmt); | 580 return vf_next_query_format(vf,fmt); |
581 } | 581 } |
582 | 582 |
583 return 0; | 583 return 0; |
584 } | 584 } |
585 | 585 |
602 | 602 |
603 if(args && !(args=strdup(args))) | 603 if(args && !(args=strdup(args))) |
604 { | 604 { |
605 nomem: | 605 nomem: |
606 mp_msg(MSGT_VFILTER, MSGL_FATAL, | 606 mp_msg(MSGT_VFILTER, MSGL_FATAL, |
607 "%s: Not enough memory.\n", vf->info->name); | 607 "%s: Not enough memory.\n", vf->info->name); |
608 fail: | 608 fail: |
609 uninit(vf); | 609 uninit(vf); |
610 free(args); | 610 free(args); |
611 return 0; | 611 return 0; |
612 } | 612 } |
622 p->threshold=0.5; | 622 p->threshold=0.5; |
623 p->window=30; | 623 p->window=30; |
624 | 624 |
625 if((ap=args)) | 625 if((ap=args)) |
626 while(*ap) | 626 while(*ap) |
627 { | 627 { |
628 q=ap; | 628 q=ap; |
629 if((ap=strchr(q, ':'))) *ap++=0; else ap=q+strlen(q); | 629 if((ap=strchr(q, ':'))) *ap++=0; else ap=q+strlen(q); |
630 if((a=strchr(q, '='))) *a++=0; else a=q+strlen(q); | 630 if((a=strchr(q, '='))) *a++=0; else a=q+strlen(q); |
631 | 631 |
632 switch(*q) | 632 switch(*q) |
633 { | 633 { |
634 case 0: break; | 634 case 0: break; |
635 case 'f': filename=a; break; | 635 case 'f': filename=a; break; |
636 case 't': p->threshold=atof(a); break; | 636 case 't': p->threshold=atof(a); break; |
637 case 'w': p->window=5*(atoi(a)+4)/5; break; | 637 case 'w': p->window=5*(atoi(a)+4)/5; break; |
638 case 'd': p->deghost=atoi(a); break; | 638 case 'd': p->deghost=atoi(a); break; |
639 case 'p': | 639 case 'p': |
640 if(q[1]=='h') p->phase=atoi(a); | 640 if(q[1]=='h') p->phase=atoi(a); |
641 else p->pass=atoi(a); | 641 else p->pass=atoi(a); |
642 break; | 642 break; |
643 | 643 |
644 case 'h': | 644 case 'h': |
645 mp_msg(MSGT_VFILTER, MSGL_INFO, | 645 mp_msg(MSGT_VFILTER, MSGL_INFO, |
646 "\n%s options:\n\n" | 646 "\n%s options:\n\n" |
647 "pass=1|2 - Use 2-pass mode.\n" | 647 "pass=1|2 - Use 2-pass mode.\n" |
648 "file=filename - Set the 2-pass log file name " | 648 "file=filename - Set the 2-pass log file name " |
649 "(default %s).\n" | 649 "(default %s).\n" |
650 "threshold=value - Set the pattern recognition " | 650 "threshold=value - Set the pattern recognition " |
651 "sensitivity (default %g).\n" | 651 "sensitivity (default %g).\n" |
652 "deghost=value - Select deghosting threshold " | 652 "deghost=value - Select deghosting threshold " |
653 "(default %d).\n" | 653 "(default %d).\n" |
654 "window=numframes - Set the statistics window " | 654 "window=numframes - Set the statistics window " |
655 "for 1-pass mode (default %d).\n" | 655 "for 1-pass mode (default %d).\n" |
656 "phase=0|1|2|3|4 - Set the initial phase " | 656 "phase=0|1|2|3|4 - Set the initial phase " |
657 "for 1-pass mode (default %d).\n\n" | 657 "for 1-pass mode (default %d).\n\n" |
658 "The option names can be abbreviated to the shortest " | 658 "The option names can be abbreviated to the shortest " |
659 "unique prefix.\n\n", | 659 "unique prefix.\n\n", |
660 vf->info->name, filename, p->threshold, p->deghost, | 660 vf->info->name, filename, p->threshold, p->deghost, |
661 p->window, p->phase%5); | 661 p->window, p->phase%5); |
662 break; | 662 break; |
663 | 663 |
664 default: | 664 default: |
665 mp_msg(MSGT_VFILTER, MSGL_FATAL, | 665 mp_msg(MSGT_VFILTER, MSGL_FATAL, |
666 "%s: Unknown argument %s.\n", vf->info->name, q); | 666 "%s: Unknown argument %s.\n", vf->info->name, q); |
667 goto fail; | 667 goto fail; |
668 } | 668 } |
669 } | 669 } |
670 | 670 |
671 switch(p->pass) | 671 switch(p->pass) |
672 { | 672 { |
673 case 1: | 673 case 1: |
674 if(!(p->file=fopen(filename, "w"))) | 674 if(!(p->file=fopen(filename, "w"))) |
675 { | 675 { |
676 mp_msg(MSGT_VFILTER, MSGL_FATAL, | 676 mp_msg(MSGT_VFILTER, MSGL_FATAL, |
677 "%s: Can't create file %s.\n", vf->info->name, filename); | 677 "%s: Can't create file %s.\n", vf->info->name, filename); |
678 goto fail; | 678 goto fail; |
679 } | 679 } |
680 | 680 |
681 break; | 681 break; |
682 | 682 |
683 case 2: | 683 case 2: |
684 if(!(p->file=fopen(filename, "r"))) | 684 if(!(p->file=fopen(filename, "r"))) |
685 { | 685 { |
686 mp_msg(MSGT_VFILTER, MSGL_FATAL, | 686 mp_msg(MSGT_VFILTER, MSGL_FATAL, |
687 "%s: Can't open file %s.\n", vf->info->name, filename); | 687 "%s: Can't open file %s.\n", vf->info->name, filename); |
688 goto fail; | 688 goto fail; |
689 } | 689 } |
690 | 690 |
691 if(!analyze(p)) | 691 if(!analyze(p)) |
692 goto fail; | 692 goto fail; |
693 | 693 |
694 fclose(p->file); | 694 fclose(p->file); |
695 p->file=0; | 695 p->file=0; |
696 break; | 696 break; |
697 } | 697 } |
698 | 698 |
699 if(p->window<5) p->window=5; | 699 if(p->window<5) p->window=5; |
700 if(!(p->history=calloc(sizeof *p->history, p->window))) | 700 if(!(p->history=calloc(sizeof *p->history, p->window))) |
701 goto nomem; | 701 goto nomem; |