|
MythTV
0.26-pre
|
00001 /* 00002 * Yadif 00003 * 00004 * Original taken from mplayer (vf_yadif.c) 00005 Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at> 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 * 00021 * converted for myth by Markus Schulz <msc@antzsystem.de> 00022 * */ 00023 #include <stdlib.h> 00024 #include <stdio.h> 00025 #include <unistd.h> 00026 #include "config.h" 00027 #if HAVE_STDINT_H 00028 #include <stdint.h> 00029 #endif 00030 #include <inttypes.h> 00031 00032 #include <string.h> 00033 #include <math.h> 00034 #include <pthread.h> 00035 00036 #include "filter.h" 00037 #include "frame.h" 00038 00039 #define MIN(a,b) ((a) > (b) ? (b) : (a)) 00040 #define MAX(a,b) ((a) < (b) ? (b) : (a)) 00041 #define ABS(a) ((a) > 0 ? (a) : (-(a))) 00042 00043 #define MIN3(a,b,c) MIN(MIN(a,b),c) 00044 #define MAX3(a,b,c) MAX(MAX(a,b),c) 00045 00046 #include "../mm_arch.h" 00047 #if HAVE_MMX 00048 #include "ffmpeg-mmx.h" 00049 #endif 00050 00051 #include "aclib.h" 00052 00053 static void* (*fast_memcpy)(void * to, const void * from, size_t len); 00054 00055 struct DeintThread 00056 { 00057 int ready; 00058 pthread_t id; 00059 int exists; 00060 }; 00061 00062 typedef struct ThisFilter 00063 { 00064 VideoFilter vf; 00065 00066 struct DeintThread *threads; 00067 VideoFrame *frame; 00068 int field; 00069 int ready; 00070 int kill_threads; 00071 int actual_threads; 00072 int requested_threads; 00073 pthread_mutex_t mutex; 00074 00075 long long last_framenr; 00076 00077 uint8_t *ref[4][3]; 00078 int stride[3]; 00079 int8_t got_frames[4]; 00080 00081 void (*filter_line)(struct ThisFilter *p, uint8_t *dst, 00082 uint8_t *prev, uint8_t *cur, uint8_t *next, 00083 int w, int refs, int parity); 00084 int mode; 00085 int width; 00086 int height; 00087 00088 int mm_flags; 00089 TF_STRUCT; 00090 } ThisFilter; 00091 00092 static void AllocFilter(ThisFilter* filter, int width, int height) 00093 { 00094 int i,j; 00095 if ((width != filter->width) || height != filter->height) 00096 { 00097 printf("YadifDeint: size changed from %d x %d -> %d x %d\n", 00098 filter->width, filter->height, width, height); 00099 for (i=0; i<3*3; i++) 00100 { 00101 uint8_t **p= &filter->ref[i%3][i/3]; 00102 if (*p) free(*p - 3*filter->stride[i/3]); 00103 *p= NULL; 00104 } 00105 for (i=0; i<3; i++) 00106 { 00107 int is_chroma= !!i; 00108 int w= ((width + 31) & (~31))>>is_chroma; 00109 int h= ((height+6+ 31) & (~31))>>is_chroma; 00110 00111 filter->stride[i]= w; 00112 for (j=0; j<3; j++) 00113 filter->ref[j][i]= (uint8_t*)calloc(w*h*sizeof(uint8_t),1)+3*w; 00114 } 00115 filter->width = width; 00116 filter->height = height; 00117 memset(filter->got_frames, 0, sizeof(filter->got_frames)); 00118 } 00119 } 00120 00121 static inline void * memcpy_pic2(void * dst, const void * src, 00122 int bytesPerLine, int height, 00123 int dstStride, int srcStride, int limit2width) 00124 { 00125 int i; 00126 void *retval=dst; 00127 00128 if (!limit2width && dstStride == srcStride) 00129 { 00130 if (srcStride < 0) 00131 { 00132 src = (const uint8_t*)src + (height-1)*srcStride; 00133 dst = (uint8_t*)dst + (height-1)*dstStride; 00134 srcStride = -srcStride; 00135 } 00136 fast_memcpy(dst, src, srcStride*height); 00137 } 00138 else 00139 { 00140 for (i=0; i<height; i++) 00141 { 00142 fast_memcpy(dst, src, bytesPerLine); 00143 src = (const uint8_t*)src + srcStride; 00144 dst = (uint8_t*)dst + dstStride; 00145 } 00146 } 00147 00148 return retval; 00149 } 00150 #define memcpy_pic(d, s, b, h, ds, ss) memcpy_pic2(d, s, b, h, ds, ss, 0) 00151 00152 static void store_ref(struct ThisFilter *p, uint8_t *src, int src_offsets[3], 00153 int src_stride[3], int width, int height) 00154 { 00155 int i; 00156 00157 memcpy (p->ref[3], p->ref[0], sizeof(uint8_t *)*3); 00158 memmove(p->ref[0], p->ref[1], sizeof(uint8_t *)*3*3); 00159 00160 memcpy (&p->got_frames[3], &p->got_frames[0], sizeof(uint8_t)); 00161 memmove(&p->got_frames[0], &p->got_frames[1], sizeof(uint8_t) * 3); 00162 00163 for (i=0; i<3; i++) 00164 { 00165 int is_chroma= !!i; 00166 memcpy_pic(p->ref[2][i], src + src_offsets[i], width>>is_chroma, 00167 height>>is_chroma, p->stride[i], src_stride[i]); 00168 } 00169 p->got_frames[2] = 1; 00170 } 00171 00172 00173 #if HAVE_MMX 00174 00175 #define LOAD4(mem,dst) \ 00176 "movd "mem", "#dst" \n\t"\ 00177 "punpcklbw %%mm7, "#dst" \n\t" 00178 00179 #define PABS(tmp,dst) \ 00180 "pxor "#tmp", "#tmp" \n\t"\ 00181 "psubw "#dst", "#tmp" \n\t"\ 00182 "pmaxsw "#tmp", "#dst" \n\t" 00183 00184 #define CHECK(pj,mj) \ 00185 "movq "#pj"(%[cur],%[mrefs]), %%mm2 \n\t" /* cur[x-refs-1+j] */\ 00186 "movq "#mj"(%[cur],%[prefs]), %%mm3 \n\t" /* cur[x+refs-1-j] */\ 00187 "movq %%mm2, %%mm4 \n\t"\ 00188 "movq %%mm2, %%mm5 \n\t"\ 00189 "pxor %%mm3, %%mm4 \n\t"\ 00190 "pavgb %%mm3, %%mm5 \n\t"\ 00191 "pand %[pb1], %%mm4 \n\t"\ 00192 "psubusb %%mm4, %%mm5 \n\t"\ 00193 "psrlq $8, %%mm5 \n\t"\ 00194 "punpcklbw %%mm7, %%mm5 \n\t" /* (cur[x-refs+j] + cur[x+refs-j])>>1 */\ 00195 "movq %%mm2, %%mm4 \n\t"\ 00196 "psubusb %%mm3, %%mm2 \n\t"\ 00197 "psubusb %%mm4, %%mm3 \n\t"\ 00198 "pmaxub %%mm3, %%mm2 \n\t"\ 00199 "movq %%mm2, %%mm3 \n\t"\ 00200 "movq %%mm2, %%mm4 \n\t" /* ABS(cur[x-refs-1+j] - cur[x+refs-1-j]) */\ 00201 "psrlq $8, %%mm3 \n\t" /* ABS(cur[x-refs +j] - cur[x+refs -j]) */\ 00202 "psrlq $16, %%mm4 \n\t" /* ABS(cur[x-refs+1+j] - cur[x+refs+1-j]) */\ 00203 "punpcklbw %%mm7, %%mm2 \n\t"\ 00204 "punpcklbw %%mm7, %%mm3 \n\t"\ 00205 "punpcklbw %%mm7, %%mm4 \n\t"\ 00206 "paddw %%mm3, %%mm2 \n\t"\ 00207 "paddw %%mm4, %%mm2 \n\t" /* score */ 00208 00209 #define CHECK1 \ 00210 "movq %%mm0, %%mm3 \n\t"\ 00211 "pcmpgtw %%mm2, %%mm3 \n\t" /* if (score < spatial_score) */\ 00212 "pminsw %%mm2, %%mm0 \n\t" /* spatial_score= score; */\ 00213 "movq %%mm3, %%mm6 \n\t"\ 00214 "pand %%mm3, %%mm5 \n\t"\ 00215 "pandn %%mm1, %%mm3 \n\t"\ 00216 "por %%mm5, %%mm3 \n\t"\ 00217 "movq %%mm3, %%mm1 \n\t" /* spatial_pred= (cur[x-refs+j] + cur[x+refs-j])>>1; */ 00218 00219 #define CHECK2 /* pretend not to have checked dir=2 if dir=1 was bad.\ 00220 hurts both quality and speed, but matches the C version. */\ 00221 "paddw %[pw1], %%mm6 \n\t"\ 00222 "psllw $14, %%mm6 \n\t"\ 00223 "paddsw %%mm6, %%mm2 \n\t"\ 00224 "movq %%mm0, %%mm3 \n\t"\ 00225 "pcmpgtw %%mm2, %%mm3 \n\t"\ 00226 "pminsw %%mm2, %%mm0 \n\t"\ 00227 "pand %%mm3, %%mm5 \n\t"\ 00228 "pandn %%mm1, %%mm3 \n\t"\ 00229 "por %%mm5, %%mm3 \n\t"\ 00230 "movq %%mm3, %%mm1 \n\t" 00231 00232 static void filter_line_mmx2(struct ThisFilter *p, uint8_t *dst, 00233 uint8_t *prev, uint8_t *cur, uint8_t *next, 00234 int w, int refs, int parity) 00235 { 00236 static const uint64_t pw_1 = 0x0001000100010001ULL; 00237 static const uint64_t pb_1 = 0x0101010101010101ULL; 00238 const int mode = p->mode; 00239 uint64_t tmp0, tmp1, tmp2, tmp3; 00240 int x; 00241 00242 #define FILTER\ 00243 for (x=0; x<w; x+=4){\ 00244 __asm__ volatile(\ 00245 "pxor %%mm7, %%mm7 \n\t"\ 00246 LOAD4("(%[cur],%[mrefs])", %%mm0) /* c = cur[x-refs] */\ 00247 LOAD4("(%[cur],%[prefs])", %%mm1) /* e = cur[x+refs] */\ 00248 LOAD4("(%["prev2"])", %%mm2) /* prev2[x] */\ 00249 LOAD4("(%["next2"])", %%mm3) /* next2[x] */\ 00250 "movq %%mm3, %%mm4 \n\t"\ 00251 "paddw %%mm2, %%mm3 \n\t"\ 00252 "psraw $1, %%mm3 \n\t" /* d = (prev2[x] + next2[x])>>1 */\ 00253 "movq %%mm0, %[tmp0] \n\t" /* c */\ 00254 "movq %%mm3, %[tmp1] \n\t" /* d */\ 00255 "movq %%mm1, %[tmp2] \n\t" /* e */\ 00256 "psubw %%mm4, %%mm2 \n\t"\ 00257 PABS( %%mm4, %%mm2) /* temporal_diff0 */\ 00258 LOAD4("(%[prev],%[mrefs])", %%mm3) /* prev[x-refs] */\ 00259 LOAD4("(%[prev],%[prefs])", %%mm4) /* prev[x+refs] */\ 00260 "psubw %%mm0, %%mm3 \n\t"\ 00261 "psubw %%mm1, %%mm4 \n\t"\ 00262 PABS( %%mm5, %%mm3)\ 00263 PABS( %%mm5, %%mm4)\ 00264 "paddw %%mm4, %%mm3 \n\t" /* temporal_diff1 */\ 00265 "psrlw $1, %%mm2 \n\t"\ 00266 "psrlw $1, %%mm3 \n\t"\ 00267 "pmaxsw %%mm3, %%mm2 \n\t"\ 00268 LOAD4("(%[next],%[mrefs])", %%mm3) /* next[x-refs] */\ 00269 LOAD4("(%[next],%[prefs])", %%mm4) /* next[x+refs] */\ 00270 "psubw %%mm0, %%mm3 \n\t"\ 00271 "psubw %%mm1, %%mm4 \n\t"\ 00272 PABS( %%mm5, %%mm3)\ 00273 PABS( %%mm5, %%mm4)\ 00274 "paddw %%mm4, %%mm3 \n\t" /* temporal_diff2 */\ 00275 "psrlw $1, %%mm3 \n\t"\ 00276 "pmaxsw %%mm3, %%mm2 \n\t"\ 00277 "movq %%mm2, %[tmp3] \n\t" /* diff */\ 00278 \ 00279 "paddw %%mm0, %%mm1 \n\t"\ 00280 "paddw %%mm0, %%mm0 \n\t"\ 00281 "psubw %%mm1, %%mm0 \n\t"\ 00282 "psrlw $1, %%mm1 \n\t" /* spatial_pred */\ 00283 PABS( %%mm2, %%mm0) /* ABS(c-e) */\ 00284 \ 00285 "movq -1(%[cur],%[mrefs]), %%mm2 \n\t" /* cur[x-refs-1] */\ 00286 "movq -1(%[cur],%[prefs]), %%mm3 \n\t" /* cur[x+refs-1] */\ 00287 "movq %%mm2, %%mm4 \n\t"\ 00288 "psubusb %%mm3, %%mm2 \n\t"\ 00289 "psubusb %%mm4, %%mm3 \n\t"\ 00290 "pmaxub %%mm3, %%mm2 \n\t"\ 00291 "pshufw $9,%%mm2, %%mm3 \n\t"\ 00292 "punpcklbw %%mm7, %%mm2 \n\t" /* ABS(cur[x-refs-1] - cur[x+refs-1]) */\ 00293 "punpcklbw %%mm7, %%mm3 \n\t" /* ABS(cur[x-refs+1] - cur[x+refs+1]) */\ 00294 "paddw %%mm2, %%mm0 \n\t"\ 00295 "paddw %%mm3, %%mm0 \n\t"\ 00296 "psubw %[pw1], %%mm0 \n\t" /* spatial_score */\ 00297 \ 00298 CHECK(-2,0)\ 00299 CHECK1\ 00300 CHECK(-3,1)\ 00301 CHECK2\ 00302 CHECK(0,-2)\ 00303 CHECK1\ 00304 CHECK(1,-3)\ 00305 CHECK2\ 00306 \ 00307 /* if (p->mode<2) ... */\ 00308 "movq %[tmp3], %%mm6 \n\t" /* diff */\ 00309 "cmpl $2, %[mode] \n\t"\ 00310 "jge 1f \n\t"\ 00311 LOAD4("(%["prev2"],%[mrefs],2)", %%mm2) /* prev2[x-2*refs] */\ 00312 LOAD4("(%["next2"],%[mrefs],2)", %%mm4) /* next2[x-2*refs] */\ 00313 LOAD4("(%["prev2"],%[prefs],2)", %%mm3) /* prev2[x+2*refs] */\ 00314 LOAD4("(%["next2"],%[prefs],2)", %%mm5) /* next2[x+2*refs] */\ 00315 "paddw %%mm4, %%mm2 \n\t"\ 00316 "paddw %%mm5, %%mm3 \n\t"\ 00317 "psrlw $1, %%mm2 \n\t" /* b */\ 00318 "psrlw $1, %%mm3 \n\t" /* f */\ 00319 "movq %[tmp0], %%mm4 \n\t" /* c */\ 00320 "movq %[tmp1], %%mm5 \n\t" /* d */\ 00321 "movq %[tmp2], %%mm7 \n\t" /* e */\ 00322 "psubw %%mm4, %%mm2 \n\t" /* b-c */\ 00323 "psubw %%mm7, %%mm3 \n\t" /* f-e */\ 00324 "movq %%mm5, %%mm0 \n\t"\ 00325 "psubw %%mm4, %%mm5 \n\t" /* d-c */\ 00326 "psubw %%mm7, %%mm0 \n\t" /* d-e */\ 00327 "movq %%mm2, %%mm4 \n\t"\ 00328 "pminsw %%mm3, %%mm2 \n\t"\ 00329 "pmaxsw %%mm4, %%mm3 \n\t"\ 00330 "pmaxsw %%mm5, %%mm2 \n\t"\ 00331 "pminsw %%mm5, %%mm3 \n\t"\ 00332 "pmaxsw %%mm0, %%mm2 \n\t" /* max */\ 00333 "pminsw %%mm0, %%mm3 \n\t" /* min */\ 00334 "pxor %%mm4, %%mm4 \n\t"\ 00335 "pmaxsw %%mm3, %%mm6 \n\t"\ 00336 "psubw %%mm2, %%mm4 \n\t" /* -max */\ 00337 "pmaxsw %%mm4, %%mm6 \n\t" /* diff= MAX3(diff, min, -max); */\ 00338 "1: \n\t"\ 00339 \ 00340 "movq %[tmp1], %%mm2 \n\t" /* d */\ 00341 "movq %%mm2, %%mm3 \n\t"\ 00342 "psubw %%mm6, %%mm2 \n\t" /* d-diff */\ 00343 "paddw %%mm6, %%mm3 \n\t" /* d+diff */\ 00344 "pmaxsw %%mm2, %%mm1 \n\t"\ 00345 "pminsw %%mm3, %%mm1 \n\t" /* d = clip(spatial_pred, d-diff, d+diff); */\ 00346 "packuswb %%mm1, %%mm1 \n\t"\ 00347 \ 00348 :[tmp0]"=m"(tmp0),\ 00349 [tmp1]"=m"(tmp1),\ 00350 [tmp2]"=m"(tmp2),\ 00351 [tmp3]"=m"(tmp3)\ 00352 :[prev] "r"(prev),\ 00353 [cur] "r"(cur),\ 00354 [next] "r"(next),\ 00355 [prefs]"r"((long)refs),\ 00356 [mrefs]"r"((long)-refs),\ 00357 [pw1] "m"(pw_1),\ 00358 [pb1] "m"(pb_1),\ 00359 [mode] "g"(mode)\ 00360 );\ 00361 __asm__ volatile("movd %%mm1, %0" :"=m"(*dst));\ 00362 dst += 4;\ 00363 prev+= 4;\ 00364 cur += 4;\ 00365 next+= 4;\ 00366 } 00367 00368 if (parity) 00369 { 00370 #define prev2 "prev" 00371 #define next2 "cur" 00372 FILTER 00373 #undef prev2 00374 #undef next2 00375 } 00376 else 00377 { 00378 #define prev2 "cur" 00379 #define next2 "next" 00380 FILTER 00381 #undef prev2 00382 #undef next2 00383 } 00384 } 00385 #undef LOAD4 00386 #undef PABS 00387 #undef CHECK 00388 #undef CHECK1 00389 #undef CHECK2 00390 #undef FILTER 00391 00392 #endif /* HAVE_MMX && defined(NAMED_ASM_ARGS) */ 00393 00394 static void filter_line_c(struct ThisFilter *p, uint8_t *dst, 00395 uint8_t *prev, uint8_t *cur, uint8_t *next, 00396 int w, int refs, int parity) 00397 { 00398 int x; 00399 uint8_t *prev2= parity ? prev : cur ; 00400 uint8_t *next2= parity ? cur : next; 00401 for (x=0; x<w; x++) 00402 { 00403 int c= cur[-refs]; 00404 int d= (prev2[0] + next2[0])>>1; 00405 int e= cur[+refs]; 00406 int temporal_diff0= ABS(prev2[0] - next2[0]); 00407 int temporal_diff1=( ABS(prev[-refs] - c) + ABS(prev[+refs] - e) )>>1; 00408 int temporal_diff2=( ABS(next[-refs] - c) + ABS(next[+refs] - e) )>>1; 00409 int diff= MAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2); 00410 int spatial_pred= (c+e)>>1; 00411 int spatial_score= ABS(cur[-refs-1] - cur[+refs-1]) + ABS(c-e) 00412 + ABS(cur[-refs+1] - cur[+refs+1]) - 1; 00413 00414 #define CHECK(j)\ 00415 { int score= ABS(cur[-refs-1+j] - cur[+refs-1-j])\ 00416 + ABS(cur[-refs +j] - cur[+refs -j])\ 00417 + ABS(cur[-refs+1+j] - cur[+refs+1-j]);\ 00418 if (score < spatial_score){\ 00419 spatial_score= score;\ 00420 spatial_pred= (cur[-refs +j] + cur[+refs -j])>>1;\ 00421 00422 CHECK(-1) CHECK(-2) }} }} 00423 CHECK( 1) CHECK( 2) }} }} 00424 00425 int b= (prev2[-2*refs] + next2[-2*refs])>>1; 00426 int f= (prev2[+2*refs] + next2[+2*refs])>>1; 00427 int max= MAX3(d-e, d-c, MIN(b-c, f-e)); 00428 int min= MIN3(d-e, d-c, MAX(b-c, f-e)); 00429 diff= MAX3(diff, min, -max); 00430 00431 if (spatial_pred > d + diff) 00432 spatial_pred = d + diff; 00433 else if (spatial_pred < d - diff) 00434 spatial_pred = d - diff; 00435 00436 dst[0] = spatial_pred; 00437 00438 dst++; 00439 cur++; 00440 prev++; 00441 next++; 00442 prev2++; 00443 next2++; 00444 } 00445 } 00446 00447 static void filter_func(struct ThisFilter *p, uint8_t *dst, int dst_offsets[3], 00448 int dst_stride[3], int width, int height, int parity, 00449 int tff, int this_slice, int total_slices) 00450 { 00451 if (total_slices < 1) 00452 return; 00453 00454 int y, i; 00455 uint8_t nr_p, nr_c; 00456 nr_c = p->got_frames[1] ? 1: 2; 00457 nr_p = p->got_frames[0] ? 0: nr_c; 00458 int slice_height = height / total_slices; 00459 slice_height = (slice_height >> 1) << 1; 00460 int starth = slice_height * this_slice; 00461 int endh = starth + slice_height; 00462 if ((this_slice + 1) >= total_slices) 00463 endh = height; 00464 00465 for (i = 0; i < 3; i++) 00466 { 00467 int is_chroma= !!i; 00468 int w = width >> is_chroma; 00469 int start = starth >> is_chroma; 00470 int end = endh >> is_chroma; 00471 int refs = p->stride[i]; 00472 00473 for (y = start; y < end; y++) 00474 { 00475 uint8_t *dst2= dst + dst_offsets[i] + y*dst_stride[i]; 00476 int field = parity ^ tff; 00477 if ((y ^ (1 - field)) & 1) 00478 { 00479 uint8_t *prev= &p->ref[nr_p][i][y*refs]; 00480 uint8_t *cur = &p->ref[nr_c][i][y*refs]; 00481 uint8_t *next= &p->ref[2][i][y*refs]; 00482 uint8_t *dst2= dst + dst_offsets[i] + y*dst_stride[i]; 00483 p->filter_line(p, dst2, prev, cur, next, w, refs, field); 00484 } 00485 else 00486 { 00487 fast_memcpy(dst2, &p->ref[nr_c][i][y*refs], w); 00488 } 00489 } 00490 } 00491 #if HAVE_MMX 00492 emms(); 00493 #endif 00494 } 00495 00496 static int YadifDeint (VideoFilter * f, VideoFrame * frame, int field) 00497 { 00498 ThisFilter *filter = (ThisFilter *) f; 00499 TF_VARS; 00500 00501 AllocFilter(filter, frame->width, frame->height); 00502 00503 if (filter->last_framenr != frame->frameNumber) 00504 { 00505 if (filter->last_framenr != (frame->frameNumber - 1)) 00506 memset(filter->got_frames, 0, sizeof(filter->got_frames)); 00507 store_ref(filter, frame->buf, frame->offsets, 00508 frame->pitches, frame->width, frame->height); 00509 } 00510 00511 if (filter->actual_threads < 1) 00512 { 00513 filter_func( 00514 filter, frame->buf, frame->offsets, frame->pitches, 00515 frame->width, frame->height, field, frame->top_field_first, 00516 0, 1); 00517 } 00518 else 00519 { 00520 int i; 00521 for (i = 0; i < filter->actual_threads; i++) 00522 filter->threads[i].ready = 1; 00523 filter->field = field; 00524 filter->frame = frame; 00525 filter->ready = filter->actual_threads; 00526 i = 0; 00527 while (filter->ready > 0 && i < 1000) 00528 { 00529 usleep(1000); 00530 i++; 00531 } 00532 } 00533 00534 filter->last_framenr = frame->frameNumber; 00535 00536 return 0; 00537 } 00538 00539 00540 static void CleanupYadifDeintFilter (VideoFilter * filter) 00541 { 00542 int i; 00543 ThisFilter* f = (ThisFilter*)filter; 00544 00545 if (f->threads != NULL) 00546 { 00547 f->kill_threads = 1; 00548 for (i = 0; i < f->requested_threads; i++) 00549 if (f->threads[i].exists) 00550 pthread_join(f->threads[i].id, NULL); 00551 free(f->threads); 00552 } 00553 00554 for (i = 0; i < 3*3; i++) 00555 { 00556 uint8_t **p= &f->ref[i%3][i/3]; 00557 if (*p) free(*p - 3*f->stride[i/3]); 00558 *p= NULL; 00559 } 00560 } 00561 00562 static void *YadifThread(void *args) 00563 { 00564 ThisFilter *filter = (ThisFilter*)args; 00565 00566 pthread_mutex_lock(&(filter->mutex)); 00567 int num = filter->actual_threads; 00568 filter->actual_threads = num + 1; 00569 pthread_mutex_unlock(&(filter->mutex)); 00570 00571 while (!filter->kill_threads) 00572 { 00573 usleep(1000); 00574 if (filter->ready && 00575 filter->frame != NULL && 00576 filter->threads[num].ready) 00577 { 00578 filter_func( 00579 filter, filter->frame->buf, filter->frame->offsets, 00580 filter->frame->pitches, filter->frame->width, 00581 filter->frame->height, filter->field, 00582 filter->frame->top_field_first, num, filter->actual_threads); 00583 00584 pthread_mutex_lock(&(filter->mutex)); 00585 filter->ready = filter->ready - 1; 00586 filter->threads[num].ready = 0; 00587 pthread_mutex_unlock(&(filter->mutex)); 00588 } 00589 } 00590 pthread_exit(NULL); 00591 return NULL; 00592 } 00593 00594 static VideoFilter * YadifDeintFilter(VideoFrameType inpixfmt, 00595 VideoFrameType outpixfmt, 00596 int *width, int *height, char *options, 00597 int threads) 00598 { 00599 ThisFilter *filter; 00600 (void) height; 00601 (void) options; 00602 00603 fprintf(stderr, "YadifDeint: In-Pixformat = %d Out-Pixformat=%d\n", 00604 inpixfmt, outpixfmt); 00605 filter = (ThisFilter *) malloc (sizeof(ThisFilter)); 00606 if (filter == NULL) 00607 { 00608 fprintf (stderr, "YadifDeint: failed to allocate memory.\n"); 00609 return NULL; 00610 } 00611 00612 filter->width = 0; 00613 filter->height = 0; 00614 filter->mode = 1; 00615 memset(filter->ref, 0, sizeof(filter->ref)); 00616 00617 AllocFilter(filter, *width, *height); 00618 00619 #if HAVE_MMX 00620 filter->mm_flags = av_get_cpu_flags(); 00621 TF_INIT(filter); 00622 #else 00623 filter->mm_flags = 0; 00624 #endif 00625 00626 filter->filter_line = filter_line_c; 00627 #if HAVE_MMX 00628 if (filter->mm_flags & AV_CPU_FLAG_MMX) 00629 { 00630 filter->filter_line = filter_line_mmx2; 00631 } 00632 00633 if (filter->mm_flags & AV_CPU_FLAG_SSE2) 00634 fast_memcpy=fast_memcpy_SSE; 00635 else if (filter->mm_flags & AV_CPU_FLAG_MMX2) 00636 fast_memcpy=fast_memcpy_MMX2; 00637 else if (filter->mm_flags & AV_CPU_FLAG_3DNOW) 00638 fast_memcpy=fast_memcpy_3DNow; 00639 else if (filter->mm_flags & AV_CPU_FLAG_MMX) 00640 fast_memcpy=fast_memcpy_MMX; 00641 else 00642 #endif 00643 fast_memcpy=memcpy; 00644 00645 filter->vf.filter = &YadifDeint; 00646 filter->vf.cleanup = &CleanupYadifDeintFilter; 00647 00648 filter->frame = NULL; 00649 filter->field = 0; 00650 filter->ready = 0; 00651 filter->kill_threads = 0; 00652 filter->actual_threads = 0; 00653 filter->requested_threads = threads; 00654 filter->threads = NULL; 00655 00656 if (filter->requested_threads > 1) 00657 { 00658 filter->threads = (struct DeintThread *) calloc(threads, 00659 sizeof(struct DeintThread)); 00660 if (filter->threads == NULL) 00661 { 00662 printf("YadifDeint: failed to allocate memory for threads - " 00663 "falling back to existing, single thread.\n"); 00664 filter->requested_threads = 1; 00665 } 00666 } 00667 00668 if (filter->requested_threads > 1) 00669 { 00670 pthread_mutex_init(&(filter->mutex), NULL); 00671 int success = 0; 00672 for (int i = 0; i < filter->requested_threads; i++) 00673 { 00674 if (pthread_create(&(filter->threads[i].id), NULL, 00675 YadifThread, (void*)filter) != 0) 00676 filter->threads[i].exists = 0; 00677 else 00678 { 00679 success++; 00680 filter->threads[i].exists = 1; 00681 } 00682 } 00683 00684 if (success < filter->requested_threads) 00685 { 00686 printf("YadifDeint: only created %d of %d threads - " 00687 "falling back to existing, single thread.\n" 00688 , success, filter->requested_threads); 00689 } 00690 else 00691 { 00692 int timeout = 0; 00693 while (filter->actual_threads != filter->requested_threads) 00694 { 00695 timeout++; 00696 if (timeout > 5000) 00697 { 00698 printf("YadifDeint: waited too long for threads to start." 00699 "- continuing.\n"); 00700 break; 00701 } 00702 usleep(1000); 00703 } 00704 printf("yadifdeint: Created %d threads (%d requested)\n", 00705 filter->actual_threads, filter->requested_threads); 00706 } 00707 } 00708 00709 if (filter->actual_threads < 1 ) 00710 { 00711 printf("YadifDeint: Using existing thread.\n"); 00712 } 00713 00714 return (VideoFilter *) filter; 00715 } 00716 00717 static FmtConv FmtList[] = 00718 { 00719 { FMT_YV12, FMT_YV12 } , 00720 FMT_NULL 00721 }; 00722 00723 ConstFilterInfo filter_table[] = 00724 { 00725 { 00726 filter_init: &YadifDeintFilter, 00727 name: "yadifdeint", 00728 descript: "combines data from several fields to deinterlace with less motion blur", 00729 formats: FmtList, 00730 libname: NULL 00731 }, 00732 { 00733 filter_init: &YadifDeintFilter, 00734 name: "yadifdoubleprocessdeint", 00735 descript: "combines data from several fields to deinterlace with less motion blur", 00736 formats: FmtList, 00737 libname: NULL 00738 },FILT_NULL 00739 }; 00740 00741 /* vim: set expandtab tabstop=4 shiftwidth=4: */
1.7.6.1