00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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" \
00186 "movq "#mj"(%[cur],%[prefs]), %%mm3 \n\t" \
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" \
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" \
00201 "psrlq $8, %%mm3 \n\t" \
00202 "psrlq $16, %%mm4 \n\t" \
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"
00208
00209 #define CHECK1 \
00210 "movq %%mm0, %%mm3 \n\t"\
00211 "pcmpgtw %%mm2, %%mm3 \n\t" \
00212 "pminsw %%mm2, %%mm0 \n\t" \
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"
00218
00219 #define CHECK2
00220 \
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) \
00247 LOAD4("(%[cur],%[prefs])", %%mm1) \
00248 LOAD4("(%["prev2"])", %%mm2) \
00249 LOAD4("(%["next2"])", %%mm3) \
00250 "movq %%mm3, %%mm4 \n\t"\
00251 "paddw %%mm2, %%mm3 \n\t"\
00252 "psraw $1, %%mm3 \n\t" \
00253 "movq %%mm0, %[tmp0] \n\t" \
00254 "movq %%mm3, %[tmp1] \n\t" \
00255 "movq %%mm1, %[tmp2] \n\t" \
00256 "psubw %%mm4, %%mm2 \n\t"\
00257 PABS( %%mm4, %%mm2) \
00258 LOAD4("(%[prev],%[mrefs])", %%mm3) \
00259 LOAD4("(%[prev],%[prefs])", %%mm4) \
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" \
00265 "psrlw $1, %%mm2 \n\t"\
00266 "psrlw $1, %%mm3 \n\t"\
00267 "pmaxsw %%mm3, %%mm2 \n\t"\
00268 LOAD4("(%[next],%[mrefs])", %%mm3) \
00269 LOAD4("(%[next],%[prefs])", %%mm4) \
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" \
00275 "psrlw $1, %%mm3 \n\t"\
00276 "pmaxsw %%mm3, %%mm2 \n\t"\
00277 "movq %%mm2, %[tmp3] \n\t" \
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" \
00283 PABS( %%mm2, %%mm0) \
00284 \
00285 "movq -1(%[cur],%[mrefs]), %%mm2 \n\t" \
00286 "movq -1(%[cur],%[prefs]), %%mm3 \n\t" \
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" \
00293 "punpcklbw %%mm7, %%mm3 \n\t" \
00294 "paddw %%mm2, %%mm0 \n\t"\
00295 "paddw %%mm3, %%mm0 \n\t"\
00296 "psubw %[pw1], %%mm0 \n\t" \
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 \
00308 "movq %[tmp3], %%mm6 \n\t" \
00309 "cmpl $2, %[mode] \n\t"\
00310 "jge 1f \n\t"\
00311 LOAD4("(%["prev2"],%[mrefs],2)", %%mm2) \
00312 LOAD4("(%["next2"],%[mrefs],2)", %%mm4) \
00313 LOAD4("(%["prev2"],%[prefs],2)", %%mm3) \
00314 LOAD4("(%["next2"],%[prefs],2)", %%mm5) \
00315 "paddw %%mm4, %%mm2 \n\t"\
00316 "paddw %%mm5, %%mm3 \n\t"\
00317 "psrlw $1, %%mm2 \n\t" \
00318 "psrlw $1, %%mm3 \n\t" \
00319 "movq %[tmp0], %%mm4 \n\t" \
00320 "movq %[tmp1], %%mm5 \n\t" \
00321 "movq %[tmp2], %%mm7 \n\t" \
00322 "psubw %%mm4, %%mm2 \n\t" \
00323 "psubw %%mm7, %%mm3 \n\t" \
00324 "movq %%mm5, %%mm0 \n\t"\
00325 "psubw %%mm4, %%mm5 \n\t" \
00326 "psubw %%mm7, %%mm0 \n\t" \
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" \
00333 "pminsw %%mm0, %%mm3 \n\t" \
00334 "pxor %%mm4, %%mm4 \n\t"\
00335 "pmaxsw %%mm3, %%mm6 \n\t"\
00336 "psubw %%mm2, %%mm4 \n\t" \
00337 "pmaxsw %%mm4, %%mm6 \n\t" \
00338 "1: \n\t"\
00339 \
00340 "movq %[tmp1], %%mm2 \n\t" \
00341 "movq %%mm2, %%mm3 \n\t"\
00342 "psubw %%mm6, %%mm2 \n\t" \
00343 "paddw %%mm6, %%mm3 \n\t" \
00344 "pmaxsw %%mm2, %%mm1 \n\t"\
00345 "pminsw %%mm3, %%mm1 \n\t" \
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
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