OSDN Git Service

fix: cannot preview with QT
[handbrake-jp/handbrake-jp.git] / libhb / detelecine.c
1 #include "hb.h"
2 #include "hbffmpeg.h"
3 #include "mpeg2dec/mpeg2.h"
4
5 /*
6  *
7  * PULLUP DEFINITIONS
8  *
9  */
10
11 #define PULLUP_FMT_Y         1
12 #define PULLUP_HAVE_BREAKS   1
13 #define PULLUP_HAVE_AFFINITY 2
14 #define PULLUP_BREAK_LEFT    1
15 #define PULLUP_BREAK_RIGHT   2
16
17 #define PULLUP_ABS( a ) (((a)^((a)>>31))-((a)>>31))
18
19 #ifndef PIC_FLAG_REPEAT_FIRST_FIELD
20 #define PIC_FLAG_REPEAT_FIRST_FIELD 256
21 #endif
22
23 struct pullup_buffer
24 {
25     int lock[2];
26     unsigned char **planes;
27 };
28
29 struct pullup_field
30 {
31     int parity;
32     struct pullup_buffer *buffer;
33     unsigned int flags;
34     int breaks;
35     int affinity;
36     int *diffs;
37     int *comb;
38     int *var;
39     struct pullup_field *prev, *next;
40 };
41
42 struct pullup_frame
43 {
44     int lock;
45     int length;
46     int parity;
47     struct pullup_buffer **ifields, *ofields[2];
48     struct pullup_buffer *buffer;
49 };
50
51 struct pullup_context
52 {
53     /* Public interface */
54     int format;
55     int nplanes;
56     int *bpp, *w, *h, *stride, *background;
57     unsigned int cpu;
58     int junk_left, junk_right, junk_top, junk_bottom;
59     int verbose;
60     int metric_plane;
61     int strict_breaks;
62     int strict_pairs;
63     int parity;
64     /* Internal data */
65     struct pullup_field *first, *last, *head;
66     struct pullup_buffer *buffers;
67     int nbuffers;
68     int (*diff)(unsigned char *, unsigned char *, int);
69     int (*comb)(unsigned char *, unsigned char *, int);
70     int (*var)(unsigned char *, unsigned char *, int);
71     int metric_w, metric_h, metric_len, metric_offset;
72     struct pullup_frame *frame;
73 };
74
75 /*
76  *
77  * DETELECINE FILTER DEFINITIONS
78  *
79  */
80
81 struct hb_filter_private_s
82 {
83     int              pix_fmt;
84     int              width[3];
85     int              height[3];
86
87     struct pullup_context * pullup_ctx;
88     int                     pullup_fakecount;
89     int                     pullup_skipflag;
90
91     AVPicture        pic_in;
92     AVPicture        pic_out;
93     hb_buffer_t    * buf_out;
94 };
95
96 hb_filter_private_t * hb_detelecine_init( int pix_fmt,
97                                           int width,
98                                           int height,
99                                           char * settings );
100
101 int hb_detelecine_work( const hb_buffer_t * buf_in,
102                         hb_buffer_t ** buf_out,
103                         int pix_fmt,
104                         int width,
105                         int height,
106                         hb_filter_private_t * pv );
107
108 void hb_detelecine_close( hb_filter_private_t * pv );
109
110 hb_filter_object_t hb_filter_detelecine =
111 {
112     FILTER_DETELECINE,
113     "Detelecine (pullup)",
114     NULL,
115     hb_detelecine_init,
116     hb_detelecine_work,
117     hb_detelecine_close,
118 };
119
120 /*
121  *
122  * PULLUP STATIC FUNCTIONS
123  *
124  */
125
126 static int pullup_diff_y( unsigned char  *a, unsigned char * b, int s )
127 {
128     int i, j, diff = 0;
129     for( i = 4; i; i-- )
130     {
131         for( j = 0; j < 8; j++ )
132         {
133             diff += PULLUP_ABS( a[j]-b[j] );
134         }
135         a+=s; b+=s;
136     }
137     return diff;
138 }
139
140 static int pullup_licomb_y( unsigned char * a, unsigned char * b, int s )
141 {
142     int i, j, diff = 0;
143     for( i = 4; i; i-- )
144     {
145         for( j = 0; j < 8; j++ )
146         {
147             diff += PULLUP_ABS( (a[j]<<1) - b[j-s] - b[j] )
148                   + PULLUP_ABS( (b[j]<<1) - a[j] - a[j+s] );
149         }
150         a+=s; b+=s;
151     }
152     return diff;
153 }
154
155 static int pullup_var_y( unsigned char * a, unsigned char * b, int s )
156 {
157     int i, j, var = 0;
158     for( i = 3; i; i-- )
159     {
160         for( j = 0; j < 8; j++ )
161         {
162             var += PULLUP_ABS( a[j]-a[j+s] );
163         }
164         a+=s; b+=s;
165     }
166     return 4*var;
167 }
168
169 static void pullup_alloc_metrics( struct pullup_context * c,
170                                   struct pullup_field * f )
171 {
172     f->diffs = calloc( c->metric_len, sizeof(int) );
173     f->comb  = calloc( c->metric_len, sizeof(int) );
174     f->var   = calloc( c->metric_len, sizeof(int) );
175 }
176
177 static void pullup_compute_metric( struct pullup_context * c,
178                                    struct pullup_field * fa, int pa,
179                                    struct pullup_field * fb, int pb,
180                                    int (* func)( unsigned char *,
181                                                  unsigned char *, int),
182                                    int * dest )
183 {
184     unsigned char *a, *b;
185     int x, y;
186     int mp    = c->metric_plane;
187     int xstep = c->bpp[mp];
188     int ystep = c->stride[mp]<<3;
189     int s     = c->stride[mp]<<1; /* field stride */
190     int w     = c->metric_w*xstep;
191
192     if( !fa->buffer || !fb->buffer ) return;
193
194     /* Shortcut for duplicate fields (e.g. from RFF flag) */
195     if( fa->buffer == fb->buffer && pa == pb )
196     {
197         memset( dest, 0, c->metric_len * sizeof(int) );
198         return;
199     }
200
201     a = fa->buffer->planes[mp] + pa * c->stride[mp] + c->metric_offset;
202     b = fb->buffer->planes[mp] + pb * c->stride[mp] + c->metric_offset;
203
204     for( y = c->metric_h; y; y-- )
205     {
206         for( x = 0; x < w; x += xstep )
207         {
208             *dest++ = func( a + x, b + x, s );
209         }
210         a += ystep; b += ystep;
211     }
212 }
213
214 static struct pullup_field * pullup_make_field_queue( struct pullup_context * c,
215                                                       int len )
216 {
217     struct pullup_field * head, * f;
218     f = head = calloc( 1, sizeof(struct pullup_field) );
219     pullup_alloc_metrics( c, f );
220     for ( ; len > 0; len-- )
221     {
222         f->next = calloc( 1, sizeof(struct pullup_field) );
223         f->next->prev = f;
224         f = f->next;
225         pullup_alloc_metrics( c, f );
226     }
227     f->next = head;
228     head->prev = f;
229     return head;
230 }
231
232 static void pullup_check_field_queue( struct pullup_context * c )
233 {
234     if( c->head->next == c->first )
235     {
236         struct pullup_field *f = calloc( 1, sizeof(struct pullup_field) );
237         pullup_alloc_metrics( c, f );
238         f->prev = c->head;
239         f->next = c->first;
240         c->head->next = f;
241         c->first->prev = f;
242     }
243 }
244
245 static void pullup_copy_field( struct pullup_context * c,
246                                struct pullup_buffer * dest,
247                                struct pullup_buffer * src,
248                                int parity )
249 {
250     int i, j;
251     unsigned char *d, *s;
252     for( i = 0; i < c->nplanes; i++ )
253     {
254         s = src->planes[i] + parity*c->stride[i];
255         d = dest->planes[i] + parity*c->stride[i];
256         for( j = c->h[i]>>1; j; j-- )
257         {
258             memcpy( d, s, c->stride[i] );
259             s += c->stride[i]<<1;
260             d += c->stride[i]<<1;
261         }
262     }
263 }
264
265
266 static int pullup_queue_length( struct pullup_field * begin,
267                                 struct pullup_field * end )
268 {
269     int count = 1;
270     struct pullup_field * f;
271
272     if( !begin || !end ) return 0;
273     for( f = begin; f != end; f = f->next ) count++;
274     return count;
275 }
276
277 static int pullup_find_first_break( struct pullup_field * f, int max )
278 {
279     int i;
280     for( i = 0; i < max; i++ )
281     {
282         if( f->breaks & PULLUP_BREAK_RIGHT ||
283             f->next->breaks & PULLUP_BREAK_LEFT )
284         {
285             return i+1;
286         }
287         f = f->next;
288     }
289     return 0;
290 }
291
292 static void pullup_compute_breaks( struct pullup_context * c,
293                                    struct pullup_field * f0 )
294 {
295     int i;
296     struct pullup_field *f1 = f0->next;
297     struct pullup_field *f2 = f1->next;
298     struct pullup_field *f3 = f2->next;
299     int l, max_l=0, max_r=0;
300
301     if( f0->flags & PULLUP_HAVE_BREAKS ) return;
302     f0->flags |= PULLUP_HAVE_BREAKS;
303
304     /* Special case when fields are 100% identical */
305     if( f0->buffer == f2->buffer && f1->buffer != f3->buffer )
306     {
307         f2->breaks |= PULLUP_BREAK_RIGHT;
308         return;
309     }
310     if( f0->buffer != f2->buffer && f1->buffer == f3->buffer )
311     {
312         f1->breaks |= PULLUP_BREAK_LEFT;
313         return;
314     }
315
316     for( i = 0; i < c->metric_len; i++ )
317     {
318         l = f2->diffs[i] - f3->diffs[i];
319         if(  l > max_l) max_l = l;
320         if( -l > max_r) max_r = -l;
321     }
322
323     /* Don't get tripped up when differences are mostly quant error */
324     if( max_l + max_r < 128 ) return;
325     if( max_l > 4*max_r ) f1->breaks |= PULLUP_BREAK_LEFT;
326     if( max_r > 4*max_l ) f2->breaks |= PULLUP_BREAK_RIGHT;
327 }
328
329 static void pullup_compute_affinity( struct pullup_context * c,
330                                      struct pullup_field * f )
331 {
332     int i;
333     int max_l = 0, max_r = 0, l;
334
335     if( f->flags & PULLUP_HAVE_AFFINITY )
336     {
337         return;
338     }
339     f->flags |= PULLUP_HAVE_AFFINITY;
340
341     if( f->buffer == f->next->next->buffer )
342     {
343         f->affinity             =  1;
344         f->next->affinity       =  0;
345         f->next->next->affinity = -1;
346
347         f->next->flags       |= PULLUP_HAVE_AFFINITY;
348         f->next->next->flags |= PULLUP_HAVE_AFFINITY;
349
350         return;
351     }
352
353     for( i = 0; i < c->metric_len; i++ )
354     {
355         int lv = f->prev->var[i];
356         int rv = f->next->var[i];
357         int v  = f->var[i];
358         int lc = f->comb[i] - (v+lv) + PULLUP_ABS( v-lv );
359         int rc = f->next->comb[i] - (v+rv) + PULLUP_ABS( v-rv );
360
361         lc = (lc > 0) ? lc : 0;
362         rc = (rc > 0) ? rc : 0;
363         l = lc - rc;
364         if(  l > max_l ) max_l = l;
365         if( -l > max_r ) max_r = -l;
366     }
367
368     if( max_l + max_r < 64 )
369     {
370         return;
371     }
372
373     if( max_r > 6*max_l )
374     {
375         f->affinity = -1;
376     }
377     else if( max_l > 6*max_r )
378     {
379         f->affinity = 1;
380     }
381 }
382
383 static void pullup_foo( struct pullup_context * c )
384 {
385     struct pullup_field * f = c->first;
386     int i, n = pullup_queue_length (f, c->last );
387     for( i = 0; i < n-1; i++ )
388     {
389         if( i < n-3 ) pullup_compute_breaks( c, f );
390         pullup_compute_affinity( c, f );
391         f = f->next;
392     }
393 }
394
395 static int pullup_decide_frame_length( struct pullup_context * c )
396 {
397     struct pullup_field *f0 = c->first;
398     struct pullup_field *f1 = f0->next;
399     struct pullup_field *f2 = f1->next;
400     int l;
401
402     if( pullup_queue_length( c->first, c->last ) < 4 )
403     {
404         return 0;
405     }
406     pullup_foo( c );
407
408     if( f0->affinity == -1 ) return 1;
409
410     l = pullup_find_first_break( f0, 3 );
411     if( l == 1 && c->strict_breaks < 0 ) l = 0;
412
413     switch (l)
414     {
415         case 1:
416             if ( c->strict_breaks < 1 &&
417                  f0->affinity == 1 &&
418                  f1->affinity == -1 )
419             {
420                 return 2;
421             }
422             else
423             {
424                 return 1;
425             }
426
427         case 2:
428             /* FIXME: strictly speaking, f0->prev is no longer valid... :) */
429             if( c->strict_pairs &&
430                 (f0->prev->breaks & PULLUP_BREAK_RIGHT) &&
431                 (f2->breaks & PULLUP_BREAK_LEFT) &&
432                 (f0->affinity != 1 || f1->affinity != -1) )
433             {
434                 return 1;
435             }
436             if( f1->affinity == 1 )
437             {
438                 return 1;
439             }
440             else
441             {
442                 return 2;
443             }
444
445         case 3:
446             if( f2->affinity == 1 )
447             {
448                 return 2;
449             }
450             else
451             {
452                 return 3;
453             }
454
455         default:
456             /* 9 possibilities covered before switch */
457             if( f1->affinity == 1 )
458             {
459                 return 1; /* covers 6 */
460             }
461             else if( f1->affinity == -1 )
462             {
463                 return 2; /* covers 6 */
464             }
465             else if( f2->affinity == -1 )
466             {
467                 /* covers 2 */
468                 if( f0->affinity == 1 )
469                 {
470                     return 3;
471                 }
472                 else
473                 {
474                     return 1;
475                 }
476             }
477             else
478             {
479                 return 2; /* the remaining 6 */
480             }
481     }
482 }
483
484 static void pullup_print_aff_and_breaks(struct pullup_context * c,
485                                         struct pullup_field * f )
486 {
487     int i;
488     struct pullup_field * f0 = f;
489     const char aff_l[] = "+..", aff_r[] = "..+";
490     printf( "\naffinity: " );
491     for( i = 0; i < 4; i++ )
492     {
493         printf( "%c%d%c",
494                 aff_l[1+f->affinity],
495                 i,
496                 aff_r[1+f->affinity] );
497
498         f = f->next;
499     }
500     f = f0;
501     printf("\nbreaks:   ");
502     for( i = 0; i < 4; i++ )
503     {
504         printf( "%c%d%c",
505                 f->breaks & PULLUP_BREAK_LEFT  ? '|' : '.',
506                 i,
507                 f->breaks & PULLUP_BREAK_RIGHT ? '|' : '.' );
508
509         f = f->next;
510     }
511     printf("\n");
512 }
513
514 /*
515  *
516  * PULLUP CONTEXT FUNCTIONS
517  *
518  */
519
520 struct pullup_context * pullup_alloc_context( void )
521 {
522     struct pullup_context * c;
523
524     c = calloc( 1, sizeof(struct pullup_context)) ;
525
526     return c;
527 }
528
529 void pullup_preinit_context( struct pullup_context * c )
530 {
531     c->bpp        = calloc( c->nplanes, sizeof(int) );
532     c->w          = calloc( c->nplanes, sizeof(int) );
533     c->h          = calloc( c->nplanes, sizeof(int) );
534     c->stride     = calloc( c->nplanes, sizeof(int) );
535     c->background = calloc( c->nplanes, sizeof(int) );
536 }
537
538 void pullup_init_context( struct pullup_context * c )
539 {
540     int mp = c->metric_plane;
541     if ( c->nbuffers < 10 )
542     {
543         c->nbuffers = 10;
544     }
545     c->buffers = calloc( c->nbuffers, sizeof (struct pullup_buffer) );
546
547     c->metric_w      = (c->w[mp] - ((c->junk_left + c->junk_right) << 3)) >> 3;
548     c->metric_h      = (c->h[mp] - ((c->junk_top + c->junk_bottom) << 1)) >> 3;
549     c->metric_offset = c->junk_left*c->bpp[mp] + (c->junk_top<<1)*c->stride[mp];
550     c->metric_len    = c->metric_w * c->metric_h;
551
552     c->head = pullup_make_field_queue( c, 8 );
553
554     c->frame = calloc( 1, sizeof (struct pullup_frame) );
555     c->frame->ifields = calloc( 3, sizeof (struct pullup_buffer *) );
556
557     if( c->format == PULLUP_FMT_Y )
558     {
559         c->diff = pullup_diff_y;
560         c->comb = pullup_licomb_y;
561         c->var  = pullup_var_y;
562     }
563 }
564
565 void pullup_free_context( struct pullup_context * c )
566 {
567     struct pullup_field * f;
568
569     free( c->buffers );
570
571     f = c->head->next;
572     while( f != c->head )
573     {
574         free( f->diffs );
575         free( f->comb );
576         f = f->next;
577         free( f->prev );
578     }
579     free( f->diffs );
580     free( f->comb );
581     free(f);
582
583     free( c->frame );
584     free( c );
585 }
586
587 /*
588  *
589  * PULLUP BUFFER FUNCTIONS
590  *
591  */
592
593 static void pullup_alloc_buffer( struct pullup_context * c,
594                                  struct pullup_buffer * b )
595 {
596     int i;
597     if( b->planes ) return;
598     b->planes = calloc( c->nplanes, sizeof(unsigned char *) );
599     for ( i = 0; i < c->nplanes; i++ )
600     {
601         b->planes[i] = malloc(c->h[i]*c->stride[i]);
602         /* Deal with idiotic 128=0 for chroma: */
603         memset( b->planes[i], c->background[i], c->h[i]*c->stride[i] );
604     }
605 }
606
607 struct pullup_buffer * pullup_lock_buffer( struct pullup_buffer * b,
608                                            int parity )
609 {
610     if( !b ) return 0;
611     if( (parity+1) & 1 ) b->lock[0]++;
612     if( (parity+1) & 2 ) b->lock[1]++;
613
614     return b;
615 }
616
617 void pullup_release_buffer( struct pullup_buffer * b,
618                             int parity )
619 {
620     if( !b ) return;
621     if( (parity+1) & 1 ) b->lock[0]--;
622     if( (parity+1) & 2 ) b->lock[1]--;
623 }
624
625 struct pullup_buffer * pullup_get_buffer( struct pullup_context * c,
626                                           int parity )
627 {
628     int i;
629
630     /* Try first to get the sister buffer for the previous field */
631     if( parity < 2 &&
632         c->last &&
633         parity != c->last->parity &&
634         !c->last->buffer->lock[parity])
635     {
636         pullup_alloc_buffer( c, c->last->buffer );
637         return pullup_lock_buffer( c->last->buffer, parity );
638     }
639
640     /* Prefer a buffer with both fields open */
641     for( i = 0; i < c->nbuffers; i++ )
642     {
643         if( c->buffers[i].lock[0] ) continue;
644         if( c->buffers[i].lock[1] ) continue;
645         pullup_alloc_buffer( c, &c->buffers[i] );
646         return pullup_lock_buffer( &c->buffers[i], parity );
647     }
648
649     if( parity == 2 ) return 0;
650
651     /* Search for any half-free buffer */
652     for( i = 0; i < c->nbuffers; i++ )
653     {
654         if( ((parity+1) & 1) && c->buffers[i].lock[0] ) continue;
655         if( ((parity+1) & 2) && c->buffers[i].lock[1] ) continue;
656         pullup_alloc_buffer( c, &c->buffers[i] );
657         return pullup_lock_buffer( &c->buffers[i], parity );
658     }
659
660     return 0;
661 }
662
663 /*
664  *
665  * PULLUP FRAME FUNCTIONS
666  *
667  */
668
669 struct pullup_frame * pullup_get_frame( struct pullup_context * c )
670 {
671     int i;
672     struct pullup_frame * fr = c->frame;
673     int n = pullup_decide_frame_length( c );
674     int aff = c->first->next->affinity;
675
676     if ( !n ) return 0;
677     if ( fr->lock ) return 0;
678
679     if ( c->verbose )
680     {
681         pullup_print_aff_and_breaks(c, c->first);
682         printf("duration: %d    \n", n);
683     }
684
685     fr->lock++;
686     fr->length = n;
687     fr->parity = c->first->parity;
688     fr->buffer = 0;
689     for( i = 0; i < n; i++ )
690     {
691         /* We cheat and steal the buffer without release+relock */
692         fr->ifields[i] = c->first->buffer;
693         c->first->buffer = 0;
694         c->first = c->first->next;
695     }
696
697     if( n == 1 )
698     {
699         fr->ofields[fr->parity] = fr->ifields[0];
700         fr->ofields[fr->parity^1] = 0;
701     }
702     else if( n == 2 )
703     {
704         fr->ofields[fr->parity] = fr->ifields[0];
705         fr->ofields[fr->parity^1] = fr->ifields[1];
706     }
707     else if( n == 3 )
708     {
709         if( aff == 0 )
710         {
711             aff = (fr->ifields[0] == fr->ifields[1]) ? -1 : 1;
712         }
713         fr->ofields[fr->parity]   = fr->ifields[1+aff];
714         fr->ofields[fr->parity^1] = fr->ifields[1];
715     }
716     pullup_lock_buffer( fr->ofields[0], 0 );
717     pullup_lock_buffer( fr->ofields[1], 1 );
718
719     if( fr->ofields[0] == fr->ofields[1] )
720     {
721         fr->buffer = fr->ofields[0];
722         pullup_lock_buffer(fr->buffer, 2);
723         return fr;
724     }
725     return fr;
726 }
727
728 void pullup_pack_frame( struct pullup_context * c, struct pullup_frame * fr)
729 {
730     int i;
731     if (fr->buffer) return;
732     if (fr->length < 2) return; /* FIXME: deal with this */
733     for( i = 0; i < 2; i++ )
734     {
735         if( fr->ofields[i]->lock[i^1] ) continue;
736         fr->buffer = fr->ofields[i];
737         pullup_lock_buffer(fr->buffer, 2);
738         pullup_copy_field( c, fr->buffer, fr->ofields[i^1], i^1 );
739         return;
740     }
741     fr->buffer = pullup_get_buffer( c, 2 );
742     pullup_copy_field( c, fr->buffer, fr->ofields[0], 0 );
743     pullup_copy_field( c, fr->buffer, fr->ofields[1], 1 );
744 }
745
746 void pullup_release_frame( struct pullup_frame * fr )
747 {
748     int i;
749     for( i = 0; i < fr->length; i++ )
750     {
751         pullup_release_buffer( fr->ifields[i], fr->parity ^ (i&1) );
752     }
753     pullup_release_buffer( fr->ofields[0], 0 );
754     pullup_release_buffer( fr->ofields[1], 1 );
755     if (fr->buffer) pullup_release_buffer( fr->buffer, 2 );
756     fr->lock--;
757 }
758
759 /*
760  *
761  * PULLUP FIELD FUNCTIONS
762  *
763  */
764
765 void pullup_submit_field( struct pullup_context * c,
766                           struct pullup_buffer * b,
767                           int parity )
768 {
769     struct pullup_field * f;
770
771     /* Grow the circular list if needed */
772     pullup_check_field_queue( c );
773
774     /* Cannot have two fields of same parity in a row; drop the new one */
775     if( c->last && c->last->parity == parity ) return;
776
777     f = c->head;
778     f->parity = parity;
779     f->buffer = pullup_lock_buffer( b, parity );
780     f->flags = 0;
781     f->breaks = 0;
782     f->affinity = 0;
783
784     pullup_compute_metric( c, f, parity, f->prev->prev,
785                            parity, c->diff, f->diffs );
786     pullup_compute_metric( c, parity?f->prev:f, 0,
787                            parity?f:f->prev, 1, c->comb, f->comb );
788     pullup_compute_metric( c, f, parity, f,
789                            -1, c->var, f->var );
790
791     /* Advance the circular list */
792     if( !c->first ) c->first = c->head;
793     c->last = c->head;
794     c->head = c->head->next;
795 }
796
797 void pullup_flush_fields( struct pullup_context * c )
798 {
799     struct pullup_field * f;
800
801     for( f = c->first; f && f != c->head; f = f->next )
802     {
803         pullup_release_buffer( f->buffer, f->parity );
804         f->buffer = 0;
805     }
806     c->first = c->last = 0;
807 }
808
809 /*
810  *
811  * DETELECINE FILTER FUNCTIONS
812  *
813  */
814
815 hb_filter_private_t * hb_detelecine_init( int pix_fmt,
816                                           int width,
817                                           int height,
818                                           char * settings )
819 {
820     if( pix_fmt != PIX_FMT_YUV420P )
821     {
822         return 0;
823     }
824
825     hb_filter_private_t * pv = malloc( sizeof(struct hb_filter_private_s) );
826
827     pv->pix_fmt  = pix_fmt;
828     pv->width[0]  = width;
829     pv->height[0] = height;
830     pv->width[1]  = pv->width[2] = width >> 1;
831     pv->height[1] = pv->height[2] = height >> 1;
832
833     pv->buf_out = hb_video_buffer_init( width, height );
834
835     struct pullup_context * ctx;
836     pv->pullup_ctx = ctx = pullup_alloc_context();
837
838     ctx->junk_left = ctx->junk_right  = 1;
839     ctx->junk_top  = ctx->junk_bottom = 4;
840     ctx->strict_breaks = -1;
841     ctx->metric_plane  = 0;
842     ctx->parity = -1;
843     
844     if( settings )
845     {
846         sscanf( settings, "%d:%d:%d:%d:%d:%d:%d",
847                 &ctx->junk_left,
848                 &ctx->junk_right,
849                 &ctx->junk_top,
850                 &ctx->junk_bottom,
851                 &ctx->strict_breaks,
852                 &ctx->metric_plane,
853                 &ctx->parity );
854     }
855
856     ctx->format = PULLUP_FMT_Y;
857     ctx->nplanes = 4;
858
859     pullup_preinit_context( ctx );
860
861     ctx->bpp[0] = ctx->bpp[1] = ctx->bpp[2] = 8;
862     ctx->background[1] = ctx->background[2] = 128;
863
864     ctx->w[0]      = pv->width[0];
865     ctx->h[0]      = pv->height[0];
866     ctx->stride[0] = pv->width[0];
867
868     ctx->w[1]      = pv->width[1];
869     ctx->h[1]      = pv->height[1];
870     ctx->stride[1] = pv->width[1];
871
872     ctx->w[2]      = pv->width[2];
873     ctx->h[2]      = pv->height[2];
874     ctx->stride[2] = pv->width[2];
875
876     ctx->w[3]      = ((width+15)/16) * ((height+15)/16);
877     ctx->h[3]      = 2;
878     ctx->stride[3] = ctx->w[3];
879
880 #if 0
881     ctx->verbose = 1;
882 #endif
883
884     pullup_init_context( ctx );
885
886     pv->pullup_fakecount = 1;
887     pv->pullup_skipflag = 0;
888
889     return pv;
890 }
891
892 void hb_detelecine_close( hb_filter_private_t * pv )
893 {
894     if( !pv )
895     {
896         return;
897     }
898
899     if( pv->buf_out )
900     {
901         hb_buffer_close( &pv->buf_out );
902     }
903
904     if( pv->pullup_ctx )
905     {
906         pullup_free_context( pv->pullup_ctx );
907     }
908
909     free( pv );
910 }
911
912 int hb_detelecine_work( const hb_buffer_t * buf_in,
913                         hb_buffer_t ** buf_out,
914                         int pix_fmt,
915                         int width,
916                         int height,
917                         hb_filter_private_t * pv )
918 {
919     if( !pv ||
920         pix_fmt != pv->pix_fmt ||
921         width != pv->width[0] ||
922         height != pv->height[0] )
923     {
924         return FILTER_FAILED;
925     }
926
927     struct pullup_context * ctx = pv->pullup_ctx;
928     struct pullup_buffer  * buf;
929     struct pullup_frame   * frame;
930
931     buf = pullup_get_buffer( ctx, 2 );
932     if( !buf )
933     {
934         frame = pullup_get_frame( ctx );
935         pullup_release_frame( frame );
936         hb_log( "Could not get buffer from pullup!" );
937         return FILTER_FAILED;
938     }
939
940     /* Copy input buffer into pullup buffer */
941     avpicture_fill( &pv->pic_in, buf_in->data,
942                     pix_fmt, width, height );
943
944     hb_buffer_copy_settings( pv->buf_out, buf_in );
945
946     memcpy( buf->planes[0], pv->pic_in.data[0],
947             pv->width[0] * pv->height[0] * sizeof(uint8_t) );
948     memcpy( buf->planes[1], pv->pic_in.data[1],
949             pv->width[1] * pv->height[1] * sizeof(uint8_t) );
950     memcpy( buf->planes[2], pv->pic_in.data[2],
951             pv->width[2] * pv->height[2] * sizeof(uint8_t) );
952
953     /* Submit buffer fields based on buffer flags.
954        Detelecine assumes BFF when the TFF flag isn't present. */
955     int parity = 1;
956     if( buf_in->flags & PIC_FLAG_TOP_FIELD_FIRST )
957     {
958         /* Source signals TFF */
959         parity = 0;
960     }
961     else if( ctx->parity == 0 )
962     {
963         /* Many non-MPEG-2 sources lack parity flags even though
964            they are TFF, so this allow users to override. */
965         parity = 0;
966     }
967     if( ctx->parity == 1 )
968     {
969         /* Override autodetected parity with BFF */
970         parity = 1;
971     }
972     pullup_submit_field( ctx, buf, parity );
973     pullup_submit_field( ctx, buf, parity^1 );
974     if( buf_in->flags & PIC_FLAG_REPEAT_FIRST_FIELD )
975     {
976         pullup_submit_field( ctx, buf, parity );
977     }
978     pullup_release_buffer( buf, 2 );
979
980     /* Get frame and check if pullup is ready */
981     frame = pullup_get_frame( ctx );
982     if( !frame )
983     {
984         if( pv->pullup_fakecount )
985         {
986             pv->pullup_fakecount--;
987
988             memcpy( pv->buf_out->data, buf_in->data, buf_in->size );
989
990             goto output_frame;
991         }
992         else
993         {
994             goto discard_frame;
995         }
996     }
997
998     /* Check to see if frame should be dropped */
999     if( frame->length < 2 )
1000     {
1001         pullup_release_frame( frame );
1002         frame = pullup_get_frame( ctx );
1003
1004         if (!frame)
1005         {
1006             goto discard_frame;
1007         }
1008         if( frame->length < 2 )
1009         {
1010             pullup_release_frame( frame );
1011
1012             if( !(buf_in->flags & PIC_FLAG_REPEAT_FIRST_FIELD) )
1013             {
1014                 goto discard_frame;
1015             }
1016
1017             frame = pullup_get_frame( ctx );
1018
1019             if( !frame )
1020             {
1021                 goto discard_frame;
1022             }
1023             if( frame->length < 2 )
1024             {
1025                 pullup_release_frame( frame );
1026                 goto discard_frame;
1027             }
1028         }
1029     }
1030
1031     /* Check to see if frame buffer is ready for export */
1032     if( !frame->buffer )
1033     {
1034         pullup_pack_frame( ctx, frame );
1035     }
1036
1037     /* Copy pullup frame buffer into output buffer */
1038     avpicture_fill( &pv->pic_out, pv->buf_out->data,
1039                     pix_fmt, width, height );
1040
1041     memcpy( pv->pic_out.data[0], frame->buffer->planes[0],
1042             pv->width[0] * pv->height[0] * sizeof(uint8_t) );
1043     memcpy( pv->pic_out.data[1], frame->buffer->planes[1],
1044             pv->width[1] * pv->height[1] * sizeof(uint8_t) );
1045     memcpy( pv->pic_out.data[2], frame->buffer->planes[2],
1046             pv->width[2] * pv->height[2] * sizeof(uint8_t) );
1047
1048     pullup_release_frame( frame );
1049
1050 output_frame:
1051     *buf_out = pv->buf_out;
1052     return FILTER_OK;
1053
1054 /* This and all discard_frame calls shown above are
1055    the result of me restoring the functionality in
1056    pullup that huevos_rancheros disabled because
1057    HB couldn't handle it.                           */
1058 discard_frame:
1059     *buf_out = pv->buf_out;
1060     return FILTER_DROP;
1061
1062 }
1063
1064