MythTV  master
filter_yadif.c
Go to the documentation of this file.
1 /*
2  * Yadif
3  *
4  * Original taken from mplayer (vf_yadif.c)
5  Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20  *
21  * converted for myth by Markus Schulz <msc@antzsystem.de>
22  * */
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include "config.h"
27 #if HAVE_STDINT_H
28 #include <stdint.h>
29 #endif
30 #include <inttypes.h>
31 
32 #include <string.h>
33 #include <math.h>
34 #include <pthread.h>
35 
36 #include "filter.h"
37 #include "mythframe.h"
38 
39 #define MIN(a,b) ((a) > (b) ? (b) : (a))
40 #define MAX(a,b) ((a) < (b) ? (b) : (a))
41 #define ABS(a) ((a) > 0 ? (a) : (-(a)))
42 
43 #define MIN3(a,b,c) MIN(MIN(a,b),c)
44 #define MAX3(a,b,c) MAX(MAX(a,b),c)
45 
46 #include "../mm_arch.h"
47 #if HAVE_MMX
48 #include "ffmpeg-mmx.h"
49 #endif
50 
51 #include "aclib.h"
52 
53 static void* (*fast_memcpy)(void * to, const void * from, size_t len);
54 
55 struct DeintThread
56 {
57  int ready;
58  pthread_t id;
59  int exists;
60 };
61 
62 typedef struct ThisFilter
63 {
65 
66  struct DeintThread *threads;
68  int field;
69  int ready;
70  int kill_threads;
71  int actual_threads;
73  pthread_mutex_t mutex;
74 
75  long long last_framenr;
76 
77  uint8_t *ref[4][3];
78  int stride[3];
79  int8_t got_frames[4];
80 
81  void (*filter_line)(struct ThisFilter *p, uint8_t *dst,
82  const uint8_t *prev, const uint8_t *cur, const uint8_t *next,
83  int w, int refs, int parity);
84  int mode;
85  int width;
86  int height;
87 
88  int mm_flags;
89  TF_STRUCT;
90 } ThisFilter;
91 
92 static void AllocFilter(ThisFilter* filter, int width, int height)
93 {
94  if ((width != filter->width) || height != filter->height)
95  {
96  printf("YadifDeint: size changed from %d x %d -> %d x %d\n",
97  filter->width, filter->height, width, height);
98  for (int i=0; i<3*3; i++)
99  {
100  uint8_t **p= &filter->ref[i%3][i/3];
101  if (*p) free(*p - 3*filter->stride[i/3]);
102  *p= NULL;
103  }
104  for (int i=0; i<3; i++)
105  {
106  int is_chroma= !!i;
107  int w= ((width + 31) & (~31))>>is_chroma;
108  int h= ((height+6+ 31) & (~31))>>is_chroma;
109 
110  filter->stride[i]= w;
111  for (int j=0; j<3; j++)
112  filter->ref[j][i]= (uint8_t*)calloc(w*h*sizeof(uint8_t),1)+3*w;
113  }
114  filter->width = width;
115  filter->height = height;
116  memset(filter->got_frames, 0, sizeof(filter->got_frames));
117  }
118 }
119 
120 static inline void * memcpy_pic2(void * dst, const void * src,
121  int bytesPerLine, int height,
122  int dstStride, int srcStride, int limit2width)
123 {
124  void *retval=dst;
125 
126  if (!limit2width && dstStride == srcStride)
127  {
128  if (srcStride < 0)
129  {
130  src = (const uint8_t*)src + (height-1)*srcStride;
131  dst = (uint8_t*)dst + (height-1)*dstStride;
132  srcStride = -srcStride;
133  }
135  }
136  else
137  {
138  for (int i=0; i<height; i++)
139  {
140  fast_memcpy(dst, src, bytesPerLine);
141  src = (const uint8_t*)src + srcStride;
142  dst = (uint8_t*)dst + dstStride;
143  }
144  }
145 
146  return retval;
147 }
148 #define memcpy_pic(d, s, b, h, ds, ss) memcpy_pic2(d, s, b, h, ds, ss, 0)
149 
150 static void store_ref(struct ThisFilter *p, uint8_t *src, int src_offsets[3],
151  int src_stride[3], int width, int height)
152 {
153  int i;
154 
155  memcpy (p->ref[3], p->ref[0], sizeof(uint8_t *)*3);
156  memmove(p->ref[0], p->ref[1], sizeof(uint8_t *)*3*3);
157 
158  memcpy (&p->got_frames[3], &p->got_frames[0], sizeof(uint8_t));
159  memmove(&p->got_frames[0], &p->got_frames[1], sizeof(uint8_t) * 3);
160 
161  for (i=0; i<3; i++)
162  {
163  int is_chroma= !!i;
164  memcpy_pic(p->ref[2][i], src + src_offsets[i], width>>is_chroma,
165  height>>is_chroma, p->stride[i], src_stride[i]);
166  }
167  p->got_frames[2] = 1;
168 }
169 
170 
171 #if HAVE_MMX
172 
173 #define LOAD4(mem,dst) \
174  "movd "mem", "#dst" \n\t"\
175  "punpcklbw %%mm7, "#dst" \n\t"
176 
177 #define PABS(tmp,dst) \
178  "pxor "#tmp", "#tmp" \n\t"\
179  "psubw "#dst", "#tmp" \n\t"\
180  "pmaxsw "#tmp", "#dst" \n\t"
181 
182 #define CHECK(pj,mj) \
183  "movq "#pj"(%[cur],%[mrefs]), %%mm2 \n\t" /* cur[x-refs-1+j] */\
184  "movq "#mj"(%[cur],%[prefs]), %%mm3 \n\t" /* cur[x+refs-1-j] */\
185  "movq %%mm2, %%mm4 \n\t"\
186  "movq %%mm2, %%mm5 \n\t"\
187  "pxor %%mm3, %%mm4 \n\t"\
188  "pavgb %%mm3, %%mm5 \n\t"\
189  "pand %[pb1], %%mm4 \n\t"\
190  "psubusb %%mm4, %%mm5 \n\t"\
191  "psrlq $8, %%mm5 \n\t"\
192  "punpcklbw %%mm7, %%mm5 \n\t" /* (cur[x-refs+j] + cur[x+refs-j])>>1 */\
193  "movq %%mm2, %%mm4 \n\t"\
194  "psubusb %%mm3, %%mm2 \n\t"\
195  "psubusb %%mm4, %%mm3 \n\t"\
196  "pmaxub %%mm3, %%mm2 \n\t"\
197  "movq %%mm2, %%mm3 \n\t"\
198  "movq %%mm2, %%mm4 \n\t" /* ABS(cur[x-refs-1+j] - cur[x+refs-1-j]) */\
199  "psrlq $8, %%mm3 \n\t" /* ABS(cur[x-refs +j] - cur[x+refs -j]) */\
200  "psrlq $16, %%mm4 \n\t" /* ABS(cur[x-refs+1+j] - cur[x+refs+1-j]) */\
201  "punpcklbw %%mm7, %%mm2 \n\t"\
202  "punpcklbw %%mm7, %%mm3 \n\t"\
203  "punpcklbw %%mm7, %%mm4 \n\t"\
204  "paddw %%mm3, %%mm2 \n\t"\
205  "paddw %%mm4, %%mm2 \n\t" /* score */
206 
207 #define CHECK1 \
208  "movq %%mm0, %%mm3 \n\t"\
209  "pcmpgtw %%mm2, %%mm3 \n\t" /* if (score < spatial_score) */\
210  "pminsw %%mm2, %%mm0 \n\t" /* spatial_score= score; */\
211  "movq %%mm3, %%mm6 \n\t"\
212  "pand %%mm3, %%mm5 \n\t"\
213  "pandn %%mm1, %%mm3 \n\t"\
214  "por %%mm5, %%mm3 \n\t"\
215  "movq %%mm3, %%mm1 \n\t" /* spatial_pred= (cur[x-refs+j] + cur[x+refs-j])>>1; */
216 
217 #define CHECK2 /* pretend not to have checked dir=2 if dir=1 was bad.\
218  hurts both quality and speed, but matches the C version. */\
219  "paddw %[pw1], %%mm6 \n\t"\
220  "psllw $14, %%mm6 \n\t"\
221  "paddsw %%mm6, %%mm2 \n\t"\
222  "movq %%mm0, %%mm3 \n\t"\
223  "pcmpgtw %%mm2, %%mm3 \n\t"\
224  "pminsw %%mm2, %%mm0 \n\t"\
225  "pand %%mm3, %%mm5 \n\t"\
226  "pandn %%mm1, %%mm3 \n\t"\
227  "por %%mm5, %%mm3 \n\t"\
228  "movq %%mm3, %%mm1 \n\t"
229 
230 static void filter_line_mmx2(struct ThisFilter *p, uint8_t *dst,
231  const uint8_t *prev, const uint8_t *cur, const uint8_t *next,
232  int w, int refs, int parity)
233 {
234  static const uint64_t pw_1 = 0x0001000100010001ULL;
235  static const uint64_t pb_1 = 0x0101010101010101ULL;
236  const int mode = p->mode;
237  uint64_t tmp0, tmp1, tmp2, tmp3;
238  int x;
239 
240 #define FILTER\
241  for (x=0; x<w; x+=4){\
242  __asm__ volatile(\
243  "pxor %%mm7, %%mm7 \n\t"\
244  LOAD4("(%[cur],%[mrefs])", %%mm0) /* c = cur[x-refs] */\
245  LOAD4("(%[cur],%[prefs])", %%mm1) /* e = cur[x+refs] */\
246  LOAD4("(%["prev2"])", %%mm2) /* prev2[x] */\
247  LOAD4("(%["next2"])", %%mm3) /* next2[x] */\
248  "movq %%mm3, %%mm4 \n\t"\
249  "paddw %%mm2, %%mm3 \n\t"\
250  "psraw $1, %%mm3 \n\t" /* d = (prev2[x] + next2[x])>>1 */\
251  "movq %%mm0, %[tmp0] \n\t" /* c */\
252  "movq %%mm3, %[tmp1] \n\t" /* d */\
253  "movq %%mm1, %[tmp2] \n\t" /* e */\
254  "psubw %%mm4, %%mm2 \n\t"\
255  PABS( %%mm4, %%mm2) /* temporal_diff0 */\
256  LOAD4("(%[prev],%[mrefs])", %%mm3) /* prev[x-refs] */\
257  LOAD4("(%[prev],%[prefs])", %%mm4) /* prev[x+refs] */\
258  "psubw %%mm0, %%mm3 \n\t"\
259  "psubw %%mm1, %%mm4 \n\t"\
260  PABS( %%mm5, %%mm3)\
261  PABS( %%mm5, %%mm4)\
262  "paddw %%mm4, %%mm3 \n\t" /* temporal_diff1 */\
263  "psrlw $1, %%mm2 \n\t"\
264  "psrlw $1, %%mm3 \n\t"\
265  "pmaxsw %%mm3, %%mm2 \n\t"\
266  LOAD4("(%[next],%[mrefs])", %%mm3) /* next[x-refs] */\
267  LOAD4("(%[next],%[prefs])", %%mm4) /* next[x+refs] */\
268  "psubw %%mm0, %%mm3 \n\t"\
269  "psubw %%mm1, %%mm4 \n\t"\
270  PABS( %%mm5, %%mm3)\
271  PABS( %%mm5, %%mm4)\
272  "paddw %%mm4, %%mm3 \n\t" /* temporal_diff2 */\
273  "psrlw $1, %%mm3 \n\t"\
274  "pmaxsw %%mm3, %%mm2 \n\t"\
275  "movq %%mm2, %[tmp3] \n\t" /* diff */\
276 \
277  "paddw %%mm0, %%mm1 \n\t"\
278  "paddw %%mm0, %%mm0 \n\t"\
279  "psubw %%mm1, %%mm0 \n\t"\
280  "psrlw $1, %%mm1 \n\t" /* spatial_pred */\
281  PABS( %%mm2, %%mm0) /* ABS(c-e) */\
282 \
283  "movq -1(%[cur],%[mrefs]), %%mm2 \n\t" /* cur[x-refs-1] */\
284  "movq -1(%[cur],%[prefs]), %%mm3 \n\t" /* cur[x+refs-1] */\
285  "movq %%mm2, %%mm4 \n\t"\
286  "psubusb %%mm3, %%mm2 \n\t"\
287  "psubusb %%mm4, %%mm3 \n\t"\
288  "pmaxub %%mm3, %%mm2 \n\t"\
289  "pshufw $9,%%mm2, %%mm3 \n\t"\
290  "punpcklbw %%mm7, %%mm2 \n\t" /* ABS(cur[x-refs-1] - cur[x+refs-1]) */\
291  "punpcklbw %%mm7, %%mm3 \n\t" /* ABS(cur[x-refs+1] - cur[x+refs+1]) */\
292  "paddw %%mm2, %%mm0 \n\t"\
293  "paddw %%mm3, %%mm0 \n\t"\
294  "psubw %[pw1], %%mm0 \n\t" /* spatial_score */\
295 \
296  CHECK(-2,0)\
297  CHECK1\
298  CHECK(-3,1)\
299  CHECK2\
300  CHECK(0,-2)\
301  CHECK1\
302  CHECK(1,-3)\
303  CHECK2\
304 \
305  /* if (p->mode<2) ... */\
306  "movq %[tmp3], %%mm6 \n\t" /* diff */\
307  "cmpl $2, %[mode] \n\t"\
308  "jge 1f \n\t"\
309  LOAD4("(%["prev2"],%[mrefs],2)", %%mm2) /* prev2[x-2*refs] */\
310  LOAD4("(%["next2"],%[mrefs],2)", %%mm4) /* next2[x-2*refs] */\
311  LOAD4("(%["prev2"],%[prefs],2)", %%mm3) /* prev2[x+2*refs] */\
312  LOAD4("(%["next2"],%[prefs],2)", %%mm5) /* next2[x+2*refs] */\
313  "paddw %%mm4, %%mm2 \n\t"\
314  "paddw %%mm5, %%mm3 \n\t"\
315  "psrlw $1, %%mm2 \n\t" /* b */\
316  "psrlw $1, %%mm3 \n\t" /* f */\
317  "movq %[tmp0], %%mm4 \n\t" /* c */\
318  "movq %[tmp1], %%mm5 \n\t" /* d */\
319  "movq %[tmp2], %%mm7 \n\t" /* e */\
320  "psubw %%mm4, %%mm2 \n\t" /* b-c */\
321  "psubw %%mm7, %%mm3 \n\t" /* f-e */\
322  "movq %%mm5, %%mm0 \n\t"\
323  "psubw %%mm4, %%mm5 \n\t" /* d-c */\
324  "psubw %%mm7, %%mm0 \n\t" /* d-e */\
325  "movq %%mm2, %%mm4 \n\t"\
326  "pminsw %%mm3, %%mm2 \n\t"\
327  "pmaxsw %%mm4, %%mm3 \n\t"\
328  "pmaxsw %%mm5, %%mm2 \n\t"\
329  "pminsw %%mm5, %%mm3 \n\t"\
330  "pmaxsw %%mm0, %%mm2 \n\t" /* max */\
331  "pminsw %%mm0, %%mm3 \n\t" /* min */\
332  "pxor %%mm4, %%mm4 \n\t"\
333  "pmaxsw %%mm3, %%mm6 \n\t"\
334  "psubw %%mm2, %%mm4 \n\t" /* -max */\
335  "pmaxsw %%mm4, %%mm6 \n\t" /* diff= MAX3(diff, min, -max); */\
336  "1: \n\t"\
337 \
338  "movq %[tmp1], %%mm2 \n\t" /* d */\
339  "movq %%mm2, %%mm3 \n\t"\
340  "psubw %%mm6, %%mm2 \n\t" /* d-diff */\
341  "paddw %%mm6, %%mm3 \n\t" /* d+diff */\
342  "pmaxsw %%mm2, %%mm1 \n\t"\
343  "pminsw %%mm3, %%mm1 \n\t" /* d = clip(spatial_pred, d-diff, d+diff); */\
344  "packuswb %%mm1, %%mm1 \n\t"\
345 \
346  :[tmp0]"=m"(tmp0),\
347  [tmp1]"=m"(tmp1),\
348  [tmp2]"=m"(tmp2),\
349  [tmp3]"=m"(tmp3)\
350  :[prev] "r"(prev),\
351  [cur] "r"(cur),\
352  [next] "r"(next),\
353  [prefs]"r"((long)refs),\
354  [mrefs]"r"((long)-refs),\
355  [pw1] "m"(pw_1),\
356  [pb1] "m"(pb_1),\
357  [mode] "g"(mode)\
358  );\
359  __asm__ volatile("movd %%mm1, %0" :"=m"(*dst));\
360  dst += 4;\
361  prev+= 4;\
362  cur += 4;\
363  next+= 4;\
364  }
365 
366  if (parity)
367  {
368 #define prev2 "prev"
369 #define next2 "cur"
370  FILTER
371 #undef prev2
372 #undef next2
373  }
374  else
375  {
376 #define prev2 "cur"
377 #define next2 "next"
378  FILTER
379 #undef prev2
380 #undef next2
381  }
382 }
383 #undef LOAD4
384 #undef PABS
385 #undef CHECK
386 #undef CHECK1
387 #undef CHECK2
388 #undef FILTER
389 
390 #endif /* HAVE_MMX && defined(NAMED_ASM_ARGS) */
391 
392 static void filter_line_c(struct ThisFilter *p, uint8_t *dst,
393  const uint8_t *prev, const uint8_t *cur, const uint8_t *next,
394  int w, int refs, int parity)
395 {
396  (void) p;
397  int x;
398  const uint8_t *prev2= parity ? prev : cur ;
399  const uint8_t *next2= parity ? cur : next;
400  for (x=0; x<w; x++)
401  {
402  int c= cur[-refs];
403  int d= (prev2[0] + next2[0])>>1;
404  int e= cur[+refs];
405  int temporal_diff0= ABS(prev2[0] - next2[0]);
406  int temporal_diff1=( ABS(prev[-refs] - c) + ABS(prev[+refs] - e) )>>1;
407  int temporal_diff2=( ABS(next[-refs] - c) + ABS(next[+refs] - e) )>>1;
408  int diff= MAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2);
409  int spatial_pred= (c+e)>>1;
410  int spatial_score= ABS(cur[-refs-1] - cur[+refs-1]) + ABS(c-e)
411  + ABS(cur[-refs+1] - cur[+refs+1]) - 1;
412  int score;
413 
414 #define CHECK(j)\
415  { score= ABS(cur[-refs-1+(j)] - cur[+refs-1-(j)])\
416  + ABS(cur[-refs +(j)] - cur[+refs -(j)])\
417  + ABS(cur[-refs+1+(j)] - cur[+refs+1-(j)]);\
418  if (score < spatial_score){\
419  spatial_score= score;\
420  spatial_pred= (cur[-refs +(j)] + cur[+refs -(j)])>>1;\
421 
422  CHECK(-1) CHECK(-2) }} }}
423  CHECK( 1) CHECK( 2) }} }}
424 
425  int b= (prev2[-2*refs] + next2[-2*refs])>>1;
426  int f= (prev2[+2*refs] + next2[+2*refs])>>1;
427  int max= MAX3(d-e, d-c, MIN(b-c, f-e));
428  int min= MIN3(d-e, d-c, MAX(b-c, f-e));
429  diff= MAX3(diff, min, -max);
430 
431  if (spatial_pred > d + diff)
432  spatial_pred = d + diff;
433  else if (spatial_pred < d - diff)
434  spatial_pred = d - diff;
435 
436  dst[0] = spatial_pred;
437 
438  dst++;
439  cur++;
440  prev++;
441  next++;
442  prev2++;
443  next2++;
444  }
445 }
446 
447 static void filter_func(struct ThisFilter *p, uint8_t *dst, int dst_offsets[3],
448  const int dst_stride[3], int width, int height, int parity,
449  int tff, int this_slice, int total_slices)
450 {
451  if (total_slices < 1)
452  return;
453 
454  int y, i;
455  uint8_t nr_p, nr_c;
456  nr_c = p->got_frames[1] ? 1: 2;
457  nr_p = p->got_frames[0] ? 0: nr_c;
458  int slice_height = height / total_slices;
459  slice_height = (slice_height >> 1) << 1;
460  int starth = slice_height * this_slice;
461  int endh = starth + slice_height;
462  if ((this_slice + 1) >= total_slices)
463  endh = height;
464 
465  for (i = 0; i < 3; i++)
466  {
467  int is_chroma= !!i;
468  int w = width >> is_chroma;
469  int start = starth >> is_chroma;
470  int end = endh >> is_chroma;
471  int refs = p->stride[i];
472 
473  for (y = start; y < end; y++)
474  {
475  uint8_t *dst2= dst + dst_offsets[i] + y*dst_stride[i];
476  int field = parity ^ tff;
477  if ((y ^ (1 - field)) & 1)
478  {
479  uint8_t *prev= &p->ref[nr_p][i][y*refs];
480  uint8_t *cur = &p->ref[nr_c][i][y*refs];
481  uint8_t *next= &p->ref[2][i][y*refs];
482  uint8_t *dst2a= dst + dst_offsets[i] + y*dst_stride[i];
483  p->filter_line(p, dst2a, prev, cur, next, w, refs, field);
484  }
485  else
486  {
487  fast_memcpy(dst2, &p->ref[nr_c][i][y*refs], w);
488  }
489  }
490  }
491 #if HAVE_MMX
492  emms();
493 #endif
494 }
495 
496 static int YadifDeint (VideoFilter * f, VideoFrame * frame, int field)
497 {
498  ThisFilter *filter = (ThisFilter *) f;
499 
500  AllocFilter(filter, frame->width, frame->height);
501 
502  if (filter->last_framenr != frame->frameNumber)
503  {
504  if (filter->last_framenr != (frame->frameNumber - 1))
505  memset(filter->got_frames, 0, sizeof(filter->got_frames));
506  store_ref(filter, frame->buf, frame->offsets,
508  }
509 
510  if (filter->actual_threads < 1)
511  {
512  filter_func(
513  filter, frame->buf, frame->offsets, frame->pitches,
515  0, 1);
516  }
517  else
518  {
519  int i;
520  for (i = 0; i < filter->actual_threads; i++)
521  filter->threads[i].ready = 1;
522  filter->field = field;
523  filter->frame = frame;
524  filter->ready = filter->actual_threads;
525  i = 0;
526  while (filter->ready > 0 && i < 1000)
527  {
528  usleep(1000);
529  i++;
530  }
531  }
532 
533  filter->last_framenr = frame->frameNumber;
534 
535  return 0;
536 }
537 
538 
539 static void CleanupYadifDeintFilter (VideoFilter * filter)
540 {
541  int i;
542  ThisFilter* f = (ThisFilter*)filter;
543 
544  if (f->threads != NULL)
545  {
546  f->kill_threads = 1;
547  for (i = 0; i < f->requested_threads; i++)
548  if (f->threads[i].exists)
549  pthread_join(f->threads[i].id, NULL);
550  free(f->threads);
551  }
552 
553  for (i = 0; i < 3*3; i++)
554  {
555  uint8_t **p= &f->ref[i%3][i/3];
556  if (*p) free(*p - 3*f->stride[i/3]);
557  *p= NULL;
558  }
559 }
560 
561 static void *YadifThread(void *args)
562 {
563  ThisFilter *filter = (ThisFilter*)args;
564 
565  pthread_mutex_lock(&(filter->mutex));
566  int num = filter->actual_threads;
567  filter->actual_threads = num + 1;
568  pthread_mutex_unlock(&(filter->mutex));
569 
570  while (!filter->kill_threads)
571  {
572  usleep(1000);
573  if (filter->ready &&
574  filter->frame != NULL &&
575  filter->threads[num].ready)
576  {
577  filter_func(
578  filter, filter->frame->buf, filter->frame->offsets,
579  filter->frame->pitches, filter->frame->width,
580  filter->frame->height, filter->field,
581  filter->frame->top_field_first, num, filter->actual_threads);
582 
583  pthread_mutex_lock(&(filter->mutex));
584  filter->ready = filter->ready - 1;
585  filter->threads[num].ready = 0;
586  pthread_mutex_unlock(&(filter->mutex));
587  }
588  }
589  pthread_exit(NULL);
590  return NULL;
591 }
592 
594  VideoFrameType outpixfmt,
595  const int *width, const int *height, const char *options,
596  int threads)
597 {
598  ThisFilter *filter;
599  (void) options;
600 
601  fprintf(stderr, "YadifDeint: In-Pixformat = %d Out-Pixformat=%d\n",
602  inpixfmt, outpixfmt);
603  filter = (ThisFilter *) malloc (sizeof(ThisFilter));
604  if (filter == NULL)
605  {
606  fprintf (stderr, "YadifDeint: failed to allocate memory.\n");
607  return NULL;
608  }
609 
610  filter->width = 0;
611  filter->height = 0;
612  filter->mode = 1;
613  memset(filter->ref, 0, sizeof(filter->ref));
614 
615  AllocFilter(filter, *width, *height);
616 
617 #if HAVE_MMX
618  filter->mm_flags = av_get_cpu_flags();
619  TF_INIT(filter);
620 #else
621  filter->mm_flags = 0;
622 #endif
623 
624  filter->filter_line = filter_line_c;
625 #if HAVE_MMX
626  if (filter->mm_flags & AV_CPU_FLAG_MMX)
627  {
628  filter->filter_line = filter_line_mmx2;
629  }
630 
631  if (filter->mm_flags & AV_CPU_FLAG_SSE2)
633  else if (filter->mm_flags & AV_CPU_FLAG_MMX2)
635  else if (filter->mm_flags & AV_CPU_FLAG_3DNOW)
637  else if (filter->mm_flags & AV_CPU_FLAG_MMX)
639  else
640 #endif
641  fast_memcpy=memcpy;
642 
643  filter->vf.filter = &YadifDeint;
645 
646  filter->frame = NULL;
647  filter->field = 0;
648  filter->ready = 0;
649  filter->kill_threads = 0;
650  filter->actual_threads = 0;
651  filter->requested_threads = threads;
652  filter->threads = NULL;
653 
654  if (filter->requested_threads > 1)
655  {
656  filter->threads = (struct DeintThread *) calloc(threads,
657  sizeof(struct DeintThread));
658  if (filter->threads == NULL)
659  {
660  printf("YadifDeint: failed to allocate memory for threads - "
661  "falling back to existing, single thread.\n");
662  filter->requested_threads = 1;
663  }
664  }
665 
666  if (filter->requested_threads > 1)
667  {
668  pthread_mutex_init(&(filter->mutex), NULL);
669  int success = 0;
670  for (int i = 0; i < filter->requested_threads; i++)
671  {
672  if (pthread_create(&(filter->threads[i].id), NULL,
673  YadifThread, (void*)filter) != 0)
674  filter->threads[i].exists = 0;
675  else
676  {
677  success++;
678  filter->threads[i].exists = 1;
679  }
680  }
681 
682  if (success < filter->requested_threads)
683  {
684  printf("YadifDeint: only created %d of %d threads - "
685  "falling back to existing, single thread.\n"
686  , success, filter->requested_threads);
687  }
688  else
689  {
690  int timeout = 0;
691  while (filter->actual_threads != filter->requested_threads)
692  {
693  timeout++;
694  if (timeout > 5000)
695  {
696  printf("YadifDeint: waited too long for threads to start."
697  "- continuing.\n");
698  break;
699  }
700  usleep(1000);
701  }
702  printf("yadifdeint: Created %d threads (%d requested)\n",
703  filter->actual_threads, filter->requested_threads);
704  }
705  }
706 
707  if (filter->actual_threads < 1 )
708  {
709  printf("YadifDeint: Using existing thread.\n");
710  }
711 
712  return (VideoFilter *) filter;
713 }
714 
715 static FmtConv FmtList[] =
716 {
717  { FMT_YV12, FMT_YV12 } ,
718  FMT_NULL
719 };
720 
722 {
723  {
725  .name= (char*)"yadifdeint",
726  .descript= (char*)
727  "combines data from several fields to "
728  "deinterlace with less motion blur",
729  .formats= FmtList,
730  .libname= NULL
731  },
732  {
733  .filter_init= &YadifDeintFilter,
734  .name= (char*)"yadifdoubleprocessdeint",
735  .descript= (char*)
736  "combines data from several fields to "
737  "deinterlace with less motion blur",
738  .formats= FmtList,
739  .libname= NULL
740  },
741  FILT_NULL
742 };
743 
744 /* vim: set expandtab tabstop=4 shiftwidth=4: */
int pitches[3]
Y, U, & V pitches.
Definition: mythframe.h:63
int(* filter)(struct VideoFilter_ *, VideoFrame *, int)
Definition: filter.h:37
init_filter filter_init
Definition: filter.h:28
const FilterInfo filter_table[]
Definition: filter_yadif.c:721
struct DeintThread * threads
static void filter_line_c(struct ThisFilter *p, uint8_t *dst, const uint8_t *prev, const uint8_t *cur, const uint8_t *next, int w, int refs, int parity)
Definition: filter_yadif.c:392
static void AllocFilter(ThisFilter *filter, int width, int height)
Definition: filter_yadif.c:92
stderr
Definition: ttvdb.py:1426
#define MAX(a, b)
Definition: filter_yadif.c:40
void * fast_memcpy_MMX(void *to, const void *from, size_t len)
unsigned char * dst[3]
static int YadifDeint(VideoFilter *f, VideoFrame *frame, int field)
Definition: filter_yadif.c:496
#define NULL
Definition: H264Parser.h:62
pthread_mutex_t mutex
pp_mode * mode
void(* cleanup)(struct VideoFilter_ *)
Definition: filter.h:38
enum FrameType_ VideoFrameType
static void store_ref(struct ThisFilter *p, uint8_t *src, int src_offsets[3], int src_stride[3], int width, int height)
Definition: filter_yadif.c:150
#define MIN(a, b)
Definition: filter_yadif.c:39
void(* filter_line)(struct ThisFilter *p, uint8_t *dst, const uint8_t *prev, const uint8_t *cur, const uint8_t *next, int w, int refs, int parity)
Definition: filter_yadif.c:81
unsigned char b
Definition: ParseText.cpp:329
uint8_t * prev
int offsets[3]
Y, U, & V offsets.
Definition: mythframe.h:64
VideoFilter vf
Definition: filter_adjust.c:36
struct ThisFilter ThisFilter
int height
Definition: mythframe.h:42
static const uint16_t * d
long long last_framenr
long long frameNumber
Definition: mythframe.h:48
static VideoFilter * YadifDeintFilter(VideoFrameType inpixfmt, VideoFrameType outpixfmt, const int *width, const int *height, const char *options, int threads)
Definition: filter_yadif.c:593
int top_field_first
1 if top field is first.
Definition: mythframe.h:58
int stride[NCHANS]
static void filter_func(struct ThisFilter *p, uint8_t *dst, int dst_offsets[3], const int dst_stride[3], int width, int height, int parity, int tff, int dirty)
#define FMT_NULL
Definition: filter.h:20
int8_t got_frames[NREFS+1]
PictureAttribute next(PictureAttributeSupported supported, PictureAttribute attribute)
#define emms()
Definition: mm_arch.h:15
#define CHECK(j)
static void CleanupYadifDeintFilter(VideoFilter *filter)
Definition: filter_yadif.c:539
uint8_t * ref[NREFS+1][NCHANS]
static FmtConv FmtList[]
Definition: filter_yadif.c:715
#define FILT_NULL
Definition: filter.h:47
#define MAX3(a, b, c)
Definition: filter_yadif.c:44
#define ABS(a)
Definition: filter_yadif.c:41
VideoFrame * frame
#define TF_INIT(filter)
Definition: filter.h:110
unsigned char * buf
Definition: mythframe.h:39
void * fast_memcpy_SSE(void *to, const void *from, size_t len)
static void *(* fast_memcpy)(void *to, const void *from, size_t len)
Definition: filter_yadif.c:53
static void * memcpy_pic2(void *dst, const void *src, int bytesPerLine, int height, int dstStride, int srcStride, int limit2width)
Definition: filter_yadif.c:120
void * fast_memcpy_3DNow(void *to, const void *from, size_t len)
#define MIN3(a, b, c)
Definition: filter_yadif.c:43
#define memcpy_pic(d, s, b, h, ds, ss)
Definition: filter_yadif.c:148
void * fast_memcpy_MMX2(void *to, const void *from, size_t len)
unsigned char * src[3]
static void * YadifThread(void *args)
Definition: filter_yadif.c:561