OSDN Git Service

Ooops, I wanted height not width there.
[handbrake-jp/handbrake-jp-git.git] / libhb / decomb.c
1 /* $Id: decomb.c,v 1.14 2008/04/25 5:00:00 jbrjake Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.fr/>.
5    It may be used under the terms of the GNU General Public License. 
6    
7    The yadif algorithm was created by Michael Niedermayer. */
8 #include "hb.h"
9 #include "libavcodec/avcodec.h"
10 #include "mpeg2dec/mpeg2.h"
11
12 #define SUPPRESS_AV_LOG
13
14 #define MODE_DEFAULT     1
15 #define PARITY_DEFAULT   -1
16
17 #define MCDEINT_MODE_DEFAULT   -1
18 #define MCDEINT_QP_DEFAULT      1
19
20 #define ABS(a) ((a) > 0 ? (a) : (-(a)))
21 #define MIN3(a,b,c) MIN(MIN(a,b),c)
22 #define MAX3(a,b,c) MAX(MAX(a,b),c)
23
24 typedef struct yadif_arguments_s {
25     uint8_t **dst;
26     int parity;
27     int tff;
28     int stop;
29     int is_combed;
30 } yadif_arguments_t;
31
32 typedef struct decomb_arguments_s {
33     int stop;
34 } decomb_arguments_t;
35
36 struct hb_filter_private_s
37 {
38     int              pix_fmt;
39     int              width[3];
40     int              height[3];
41
42     int              mode;
43     int              spatial_metric;
44     int              motion_threshold;
45     int              spatial_threshold;
46     int              block_threshold;
47     int              block_width;
48     int              block_height;
49
50     int              parity;
51     
52     int              yadif_ready;
53
54     int              mcdeint_mode;
55     int              mcdeint_qp;
56
57     int              mcdeint_outbuf_size;
58     uint8_t        * mcdeint_outbuf;
59     AVCodecContext * mcdeint_avctx_enc;
60     AVFrame        * mcdeint_frame;
61     AVFrame        * mcdeint_frame_dec;
62
63     int              yadif_deinterlaced_frames;
64     int              blend_deinterlaced_frames;
65     int              unfiltered_frames;
66
67     uint8_t        * ref[4][3];
68     int              ref_stride[3];
69
70     /* Make a buffer to store a comb mask. */
71     uint8_t        * mask[3];
72
73     AVPicture        pic_in;
74     AVPicture        pic_out;
75     hb_buffer_t *    buf_out[2];
76     hb_buffer_t *    buf_settings;
77     
78     int              cpu_count;
79
80     hb_thread_t    ** yadif_threads;         // Threads for Yadif - one per CPU
81     hb_lock_t      ** yadif_begin_lock;      // Thread has work
82     hb_lock_t      ** yadif_complete_lock;   // Thread has completed work
83     yadif_arguments_t *yadif_arguments;      // Arguments to thread for work
84     
85     hb_thread_t    ** decomb_threads;        // Threads for comb detection - one per CPU
86     hb_lock_t      ** decomb_begin_lock;     // Thread has work
87     hb_lock_t      ** decomb_complete_lock;  // Thread has completed work
88     decomb_arguments_t *decomb_arguments;    // Arguments to thread for work
89     
90 };
91
92 hb_filter_private_t * hb_decomb_init( int pix_fmt,
93                                            int width,
94                                            int height,
95                                            char * settings );
96
97 int hb_decomb_work(      const hb_buffer_t * buf_in,
98                          hb_buffer_t ** buf_out,
99                          int pix_fmt,
100                          int width,
101                          int height,
102                          hb_filter_private_t * pv );
103
104 void hb_decomb_close( hb_filter_private_t * pv );
105
106 hb_filter_object_t hb_filter_decomb =
107 {
108     FILTER_DECOMB,
109     "Deinterlaces selectively with yadif/mcdeint and lowpass5 blending",
110     NULL,
111     hb_decomb_init,
112     hb_decomb_work,
113     hb_decomb_close,
114 };
115
116 int cubic_interpolate( int y0, int y1, int y2, int y3 )
117 {
118     /* From http://www.neuron2.net/library/cubicinterp.html */
119     int result = ( y0 * -3 ) + ( y1 * 23 ) + ( y2 * 23 ) + ( y3 * -3 );
120     result /= 40;
121     
122     if( result > 255 )
123     {
124         result = 255;
125     }
126     else if( result < 0 )
127     {
128         result = 0;
129     }
130     
131     return result;
132 }
133
134 static void store_ref( const uint8_t ** pic,
135                              hb_filter_private_t * pv )
136 {
137     memcpy( pv->ref[3],
138             pv->ref[0],
139             sizeof(uint8_t *)*3 );
140
141     memmove( pv->ref[0],
142              pv->ref[1],
143              sizeof(uint8_t *)*3*3 );
144
145     int i;
146     for( i = 0; i < 3; i++ )
147     {
148         const uint8_t * src = pic[i];
149         uint8_t * ref = pv->ref[2][i];
150
151         int w = pv->width[i];
152         int h = pv->height[i];
153         int ref_stride = pv->ref_stride[i];
154
155         int y;
156         for( y = 0; y < pv->height[i]; y++ )
157         {
158             memcpy(ref, src, w);
159             src = (uint8_t*)src + w;
160             ref = (uint8_t*)ref + ref_stride;
161         }
162     }
163 }
164
165 static void get_ref( uint8_t ** pic, hb_filter_private_t * pv, int frm )
166 {
167     int i;
168     for( i = 0; i < 3; i++ )
169     {
170         uint8_t * dst = pic[i];
171         const uint8_t * ref = pv->ref[frm][i];
172         int w = pv->width[i];
173         int ref_stride = pv->ref_stride[i];
174         
175         int y;
176         for( y = 0; y < pv->height[i]; y++ )
177         {
178             memcpy(dst, ref, w);
179             dst += w;
180             ref += ref_stride;
181         }
182     }
183 }
184
185 int blend_filter_pixel( int up2, int up1, int current, int down1, int down2 )
186 {
187     /* Low-pass 5-tap filter */
188     int result = 0;
189     result += -up2;
190     result += up1 * 2;
191     result += current * 6;
192     result += down1 *2;
193     result += -down2;
194     result /= 8;
195
196     if( result > 255 )
197     {
198         result = 255;
199     }
200     if( result < 0 )
201     {
202         result = 0;
203     }
204     
205     return result;
206 }
207
208 static void blend_filter_line( uint8_t *dst,
209                                uint8_t *cur,
210                                int plane,
211                                int y,
212                                hb_filter_private_t * pv )
213 {
214     int w = pv->width[plane];
215     int refs = pv->ref_stride[plane];
216     int x;
217
218     for( x = 0; x < w; x++)
219     {
220         int a, b, c, d, e;
221         
222         a = cur[-2*refs];
223         b = cur[-refs];
224         c = cur[0];
225         d = cur[+refs];
226         e = cur[2*refs];
227         
228         if( y == 0 )
229         {
230             /* First line, so A and B don't exist.*/
231             a = cur[0];
232             b = cur[0];
233         }
234         else if( y == 1 )
235         {
236             /* Second line, no A. */
237             a = cur[-refs];
238         }
239         else if( y == (pv->height[plane] - 2) )
240         {
241             /* Second to last line, no E. */
242             e = cur[+refs];
243         }
244         else if( y == (pv->height[plane] -1) )
245         {
246             /* Last line, no D or E. */
247             d = cur[0];
248             e = cur[0];
249         }
250                 
251         dst[0] = blend_filter_pixel( a, b, c, d, e );
252
253         dst++;
254         cur++;
255     }
256 }
257
258 int check_combing_mask( hb_filter_private_t * pv )
259 {
260     /* Go through the mask in X*Y blocks. If any of these windows
261        have threshold or more combed pixels, consider the whole
262        frame to be combed and send it on to be deinterlaced.     */
263
264     /* Block mask threshold -- The number of pixels
265        in a block_width * block_height window of
266        he mask that need to show combing for the
267        whole frame to be seen as such.            */
268     int threshold       = pv->block_threshold;
269     int block_width     = pv->block_width;
270     int block_height    = pv->block_height;
271     int block_x, block_y;
272     int block_score = 0; int send_to_blend = 0;
273     
274     int x, y, k;
275
276     for( k = 0; k < 1; k++ )
277     {
278         int ref_stride = pv->ref_stride[k];
279         for( y = 0; y < ( pv->height[k] - block_height ); y = y + block_height )
280         {
281             for( x = 0; x < ( pv->width[k] - block_width ); x = x + block_width )
282             {
283                 block_score = 0;
284                 for( block_y = 0; block_y < block_height; block_y++ )
285                 {
286                     for( block_x = 0; block_x < block_width; block_x++ )
287                     {
288                         int mask_y = y + block_y;
289                         int mask_x = x + block_x;
290                         
291                         /* We only want to mark a pixel in a block as combed
292                            if the pixels above and below are as well. Got to
293                            handle the top and bottom lines separately.       */
294                         if( y + block_y == 0 )
295                         {
296                             if( pv->mask[k][mask_y*ref_stride+mask_x    ] == 255 &&
297                                 pv->mask[k][mask_y*ref_stride+mask_x + 1] == 255 )
298                                     block_score++;
299                         }
300                         else if( y + block_y == pv->height[k] - 1 )
301                         {
302                             if( pv->mask[k][mask_y*ref_stride+mask_x - 1] == 255 &&
303                                 pv->mask[k][mask_y*ref_stride+mask_x    ] == 255 )
304                                     block_score++;
305                         }
306                         else
307                         {
308                             if( pv->mask[k][mask_y*ref_stride+mask_x - 1] == 255 &&
309                                 pv->mask[k][mask_y*ref_stride+mask_x    ] == 255 &&
310                                 pv->mask[k][mask_y*ref_stride+mask_x + 1] == 255 )
311                                     block_score++;
312                         } 
313                     }
314                 }
315
316                 if( block_score >= ( threshold / 2 ) )
317                 {
318 #if 0
319                     hb_log("decomb: frame %i | score %i | type %s", pv->yadif_deinterlaced_frames + pv->blend_deinterlaced_frames +  pv->unfiltered_frames + 1, block_score, pv->buf_settings->flags & 16 ? "Film" : "Video");
320 #endif
321                     if ( block_score <= threshold && !( pv->buf_settings->flags & 16) )
322                     {
323                         /* Blend video content that scores between
324                            ( threshold / 2 ) and threshold.        */
325                         send_to_blend = 1;
326                     }
327                     else if( block_score > threshold )
328                     {
329                         if( pv->buf_settings->flags & 16 )
330                         {
331                             /* Blend progressive content above the threshold.*/
332                             return 2;
333                         }
334                         else
335                         {
336                             /* Yadif deinterlace video content above the threshold. */
337                             return 1;
338                         }
339                     }
340                 }
341             }
342         } 
343     }
344     
345     if( send_to_blend )
346     {
347         return 2;
348     }
349     else
350     {
351         /* Consider this frame to be uncombed. */
352         return 0;
353     }
354 }
355
356 int detect_combed_segment( hb_filter_private_t * pv, int segment_start, int segment_stop )
357 {
358     /* A mish-mash of various comb detection tricks
359        picked up from neuron2's Decomb plugin for
360        AviSynth and tritical's IsCombedT and
361        IsCombedTIVTC plugins.                       */
362        
363     int x, y, k, width, height;
364     
365     /* Comb scoring algorithm */
366     int spatial_metric  = pv->spatial_metric;
367     /* Motion threshold */
368     int mthresh         = pv->motion_threshold;
369     /* Spatial threshold */
370     int athresh         = pv->spatial_threshold;
371     int athresh_squared = athresh * athresh;
372     int athresh6        = 6 *athresh;
373
374     /* One pas for Y, one pass for U, one pass for V */    
375     for( k = 0; k < 1; k++ )
376     {
377         int ref_stride  = pv->ref_stride[k];
378         width           = pv->width[k];
379         height          = pv->height[k];
380         
381         /* Comb detection has to start at y = 2 and end at
382            y = height - 2, because it needs to examine
383            2 pixels above and 2 below the current pixel.      */
384         if( segment_start < 2 )
385             segment_start = 2;
386         if( segment_stop > height - 2 )
387             segment_stop = height - 2;
388             
389         for( y =  segment_start; y < segment_stop; y++ )
390         {
391             /* These are just to make the buffer locations easier to read. */
392             int back_2    = ( y - 2 )*ref_stride ;
393             int back_1    = ( y - 1 )*ref_stride;
394             int current   =         y*ref_stride;
395             int forward_1 = ( y + 1 )*ref_stride;
396             int forward_2 = ( y + 2 )*ref_stride;
397             
398             /* We need to examine a column of 5 pixels
399                in the prev, cur, and next frames.      */
400             uint8_t previous_frame[5];
401             uint8_t current_frame[5];
402             uint8_t next_frame[5];
403             
404             for( x = 0; x < width; x++ )
405             {
406                 /* Fill up the current frame array with the current pixel values.*/
407                 current_frame[0] = pv->ref[1][k][back_2    + x];
408                 current_frame[1] = pv->ref[1][k][back_1    + x];
409                 current_frame[2] = pv->ref[1][k][current   + x];
410                 current_frame[3] = pv->ref[1][k][forward_1 + x];
411                 current_frame[4] = pv->ref[1][k][forward_2 + x];
412
413                 int up_diff   = current_frame[2] - current_frame[1];
414                 int down_diff = current_frame[2] - current_frame[3];
415
416                 if( ( up_diff >  athresh && down_diff >  athresh ) ||
417                     ( up_diff < -athresh && down_diff < -athresh ) )
418                 {
419                     /* The pixel above and below are different,
420                        and they change in the same "direction" too.*/
421                     int motion = 0;
422                     if( mthresh > 0 )
423                     {
424                         /* Make sure there's sufficient motion between frame t-1 to frame t+1. */
425                         previous_frame[0] = pv->ref[0][k][back_2    + x];
426                         previous_frame[1] = pv->ref[0][k][back_1    + x];
427                         previous_frame[2] = pv->ref[0][k][current   + x];
428                         previous_frame[3] = pv->ref[0][k][forward_1 + x];
429                         previous_frame[4] = pv->ref[0][k][forward_2 + x];
430                         next_frame[0]     = pv->ref[2][k][back_2    + x];
431                         next_frame[1]     = pv->ref[2][k][back_1    + x];
432                         next_frame[2]     = pv->ref[2][k][current   + x];
433                         next_frame[3]     = pv->ref[2][k][forward_1 + x];
434                         next_frame[4]     = pv->ref[2][k][forward_2 + x];
435                         
436                         if( abs( previous_frame[2] - current_frame[2] ) > mthresh &&
437                             abs(  current_frame[1] - next_frame[1]    ) > mthresh &&
438                             abs(  current_frame[3] - next_frame[3]    ) > mthresh )
439                                 motion++;
440                         if( abs(     next_frame[2] - current_frame[2] ) > mthresh &&
441                             abs( previous_frame[1] - current_frame[1] ) > mthresh &&
442                             abs( previous_frame[3] - current_frame[3] ) > mthresh )
443                                 motion++;
444                     }
445                     else
446                     {
447                         /* User doesn't want to check for motion,
448                            so move on to the spatial check.       */
449                         motion = 1;
450                     }
451                            
452                     if( motion || ( pv->yadif_deinterlaced_frames==0 && pv->blend_deinterlaced_frames==0 && pv->unfiltered_frames==0) )
453                     {
454                            /* That means it's time for the spatial check.
455                               We've got several options here.             */
456                         if( spatial_metric == 0 )
457                         {
458                             /* Simple 32detect style comb detection */
459                             if( ( abs( current_frame[2] - current_frame[4] ) < 10  ) &&
460                                 ( abs( current_frame[2] - current_frame[3] ) > 15 ) )
461                             {
462                                 pv->mask[k][y*ref_stride + x] = 255;
463                             }
464                             else
465                             {
466                                 pv->mask[k][y*ref_stride + x] = 0;
467                             }
468                         }
469                         else if( spatial_metric == 1 )
470                         {
471                             /* This, for comparison, is what IsCombed uses.
472                                It's better, but still noise senstive.      */
473                                int combing = ( current_frame[1] - current_frame[2] ) *
474                                              ( current_frame[3] - current_frame[2] );
475                                
476                                if( combing > athresh_squared )
477                                    pv->mask[k][y*ref_stride + x] = 255; 
478                                else
479                                    pv->mask[k][y*ref_stride + x] = 0;
480                         }
481                         else if( spatial_metric == 2 )
482                         {
483                             /* Tritical's noise-resistant combing scorer.
484                                The check is done on a bob+blur convolution. */
485                             int combing = abs( current_frame[0]
486                                              + ( 4 * current_frame[2] )
487                                              + current_frame[4]
488                                              - ( 3 * ( current_frame[1]
489                                                      + current_frame[3] ) ) );
490
491                             /* If the frame is sufficiently combed,
492                                then mark it down on the mask as 255. */
493                             if( combing > athresh6 )
494                                 pv->mask[k][y*ref_stride + x] = 255; 
495                             else
496                                 pv->mask[k][y*ref_stride + x] = 0;
497                         }
498                     }
499                     else
500                     {
501                         pv->mask[k][y*ref_stride + x] = 0;
502                     }
503                 }
504                 else
505                 {
506                     pv->mask[k][y*ref_stride + x] = 0;
507                 }
508             }
509         }
510     }
511 }
512
513 typedef struct decomb_thread_arg_s {
514     hb_filter_private_t *pv;
515     int segment;
516 } decomb_thread_arg_t;
517
518 /*
519  * comb detect this segment of all three planes in a single thread.
520  */
521 void decomb_filter_thread( void *thread_args_v )
522 {
523     decomb_arguments_t *decomb_work = NULL;
524     hb_filter_private_t * pv;
525     int run = 1;
526     int segment, segment_start, segment_stop, plane;
527     decomb_thread_arg_t *thread_args = thread_args_v;
528
529     pv = thread_args->pv;
530     segment = thread_args->segment;
531
532     hb_log("decomb thread started for segment %d", segment);
533
534     while( run )
535     {
536         /*
537          * Wait here until there is work to do. hb_lock() blocks until
538          * render releases it to say that there is more work to do.
539          */
540         hb_lock( pv->decomb_begin_lock[segment] );
541
542         decomb_work = &pv->decomb_arguments[segment];
543
544         if( decomb_work->stop )
545         {
546             /*
547              * No more work to do, exit this thread.
548              */
549             run = 0;
550             continue;
551         } 
552
553         /*
554          * Process segment (for now just from luma)
555          */
556         for( plane = 0; plane < 1; plane++)
557         {
558
559             int w = pv->width[plane];
560             int h = pv->height[plane];
561             int ref_stride = pv->ref_stride[plane];
562             segment_start = ( h / pv->cpu_count ) * segment;
563             if( segment == pv->cpu_count - 1 )
564             {
565                 /*
566                  * Final segment
567                  */
568                 segment_stop = h;
569             } else {
570                 segment_stop = ( h / pv->cpu_count ) * ( segment + 1 );
571             }
572             
573             detect_combed_segment( pv, segment_start, segment_stop );
574         }
575         /*
576          * Finished this segment, let everyone know.
577          */
578         hb_unlock( pv->decomb_complete_lock[segment] );
579     }
580     free( thread_args_v );
581 }
582
583 int comb_segmenter( hb_filter_private_t * pv )
584 {
585     int segment;
586
587     for( segment = 0; segment < pv->cpu_count; segment++ )
588     {  
589         /*
590          * Let the thread for this plane know that we've setup work 
591          * for it by releasing the begin lock (ensuring that the
592          * complete lock is already locked so that we block when
593          * we try to lock it again below).
594          */
595         hb_lock( pv->decomb_complete_lock[segment] );
596         hb_unlock( pv->decomb_begin_lock[segment] );
597     }
598
599     /*
600      * Wait until all three threads have completed by trying to get
601      * the complete lock that we locked earlier for each thread, which
602      * will block until that thread has completed the work on that
603      * plane.
604      */
605     for( segment = 0; segment < pv->cpu_count; segment++ )
606     {
607         hb_lock( pv->decomb_complete_lock[segment] );
608         hb_unlock( pv->decomb_complete_lock[segment] );
609     }
610     
611     return check_combing_mask( pv );
612 }
613
614 static void yadif_filter_line( uint8_t *dst,
615                                uint8_t *prev,
616                                uint8_t *cur,
617                                uint8_t *next,
618                                int plane,
619                                int parity,
620                                int y,
621                                hb_filter_private_t * pv )
622 {
623     /* While prev and next point to the previous and next frames,
624        prev2 and next2 will shift depending on the parity, usually 1.
625        They are the previous and next fields, the fields temporally adjacent
626        to the other field in the current frame--the one not being filtered.  */
627     uint8_t *prev2 = parity ? prev : cur ;
628     uint8_t *next2 = parity ? cur  : next;
629     int w = pv->width[plane];
630     int refs = pv->ref_stride[plane];
631     int x;
632     
633     for( x = 0; x < w; x++)
634     {
635         /* Pixel above*/
636         int c              = cur[-refs];
637         /* Temporal average: the current location in the adjacent fields */
638         int d              = (prev2[0] + next2[0])>>1;
639         /* Pixel below */
640         int e              = cur[+refs];
641         
642         /* How the current pixel changes between the adjacent fields */
643         int temporal_diff0 = ABS(prev2[0] - next2[0]);
644         /* The average of how much the pixels above and below change from the frame before to now. */
645         int temporal_diff1 = ( ABS(prev[-refs] - cur[-refs]) + ABS(prev[+refs] - cur[+refs]) ) >> 1;
646         /* The average of how much the pixels above and below change from now to the next frame. */
647         int temporal_diff2 = ( ABS(next[-refs] - cur[-refs]) + ABS(next[+refs] - cur[+refs]) ) >> 1;
648         /* For the actual difference, use the largest of the previous average diffs. */
649         int diff           = MAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2);
650         
651         /* SAD of how the pixel-1, the pixel, and the pixel+1 change from the line above to below. */ 
652         int spatial_score  = ABS(cur[-refs-1] - cur[+refs-1]) + ABS(cur[-refs]-cur[+refs]) +
653                                      ABS(cur[-refs+1] - cur[+refs+1]) - 1;         
654         int spatial_pred;
655          
656         /* Spatial pred is either a bilinear or cubic vertical interpolation. */
657         if( pv->mode > 0 )
658         {
659             spatial_pred = cubic_interpolate( cur[-3*refs], cur[-refs], cur[+refs], cur[3*refs] );
660         }
661         else
662         {
663             spatial_pred = (c+e)>>1;
664         }
665
666 /* EDDI: Edge Directed Deinterlacing Interpolation
667    Uses the Martinez-Lim Line Shift Parametric Modeling algorithm...I think.
668    Checks 4 different slopes to see if there is more similarity along a diagonal
669    than there was vertically. If a diagonal is more similar, then it indicates
670    an edge, so interpolate along that instead of a vertical line, using either
671    linear or cubic interpolation depending on mode. */
672 #define YADIF_CHECK(j)\
673         {   int score = ABS(cur[-refs-1+j] - cur[+refs-1-j])\
674                       + ABS(cur[-refs  +j] - cur[+refs  -j])\
675                       + ABS(cur[-refs+1+j] - cur[+refs+1-j]);\
676             if( score < spatial_score ){\
677                 spatial_score = score;\
678                 if( pv->mode > 0 )\
679                 {\
680                     switch(j)\
681                     {\
682                         case -1:\
683                             spatial_pred = cubic_interpolate(cur[-3 * refs - 3], cur[-refs -1], cur[+refs + 1], cur[3* refs + 3] );\
684                         break;\
685                         case -2:\
686                             spatial_pred = cubic_interpolate( ( ( cur[-3*refs - 4] + cur[-refs - 4] ) / 2 ) , cur[-refs -2], cur[+refs + 2], ( ( cur[3*refs + 4] + cur[refs + 4] ) / 2 ) );\
687                         break;\
688                         case 1:\
689                             spatial_pred = cubic_interpolate(cur[-3 * refs +3], cur[-refs +1], cur[+refs - 1], cur[3* refs -3] );\
690                         break;\
691                         case 2:\
692                             spatial_pred = cubic_interpolate(( ( cur[-3*refs + 4] + cur[-refs + 4] ) / 2 ), cur[-refs +2], cur[+refs - 2], ( ( cur[3*refs - 4] + cur[refs - 4] ) / 2 ) );\
693                         break;\
694                     }\
695                 }\
696                 else\
697                 {\
698                     spatial_pred = ( cur[-refs +j] + cur[+refs -j] ) >>1;\
699                 }\
700                 
701                 YADIF_CHECK(-1) YADIF_CHECK(-2) }} }}
702                 YADIF_CHECK( 1) YADIF_CHECK( 2) }} }}
703                                 
704         /* Temporally adjust the spatial prediction by
705            comparing against lines in the adjacent fields. */
706         int b = (prev2[-2*refs] + next2[-2*refs])>>1;
707         int f = (prev2[+2*refs] + next2[+2*refs])>>1;
708         
709         /* Find the median value */
710         int max = MAX3(d-e, d-c, MIN(b-c, f-e));
711         int min = MIN3(d-e, d-c, MAX(b-c, f-e));
712         diff = MAX3( diff, min, -max );
713         
714         if( spatial_pred > d + diff )
715         {
716             spatial_pred = d + diff;
717         }
718         else if( spatial_pred < d - diff )
719         {
720             spatial_pred = d - diff;
721         }
722         
723         dst[0] = spatial_pred;
724                         
725         dst++;
726         cur++;
727         prev++;
728         next++;
729         prev2++;
730         next2++;
731     }
732 }
733
734 typedef struct yadif_thread_arg_s {
735     hb_filter_private_t *pv;
736     int segment;
737 } yadif_thread_arg_t;
738
739 /*
740  * deinterlace this segment of all three planes in a single thread.
741  */
742 void yadif_decomb_filter_thread( void *thread_args_v )
743 {
744     yadif_arguments_t *yadif_work = NULL;
745     hb_filter_private_t * pv;
746     int run = 1;
747     int plane;
748     int segment, segment_start, segment_stop;
749     yadif_thread_arg_t *thread_args = thread_args_v;
750     uint8_t **dst;
751     int parity, tff, y, w, h, ref_stride, is_combed;
752
753     pv = thread_args->pv;
754     segment = thread_args->segment;
755
756     hb_log("yadif thread started for segment %d", segment);
757
758     while( run )
759     {
760         /*
761          * Wait here until there is work to do. hb_lock() blocks until
762          * render releases it to say that there is more work to do.
763          */
764         hb_lock( pv->yadif_begin_lock[segment] );
765
766         yadif_work = &pv->yadif_arguments[segment];
767
768         if( yadif_work->stop )
769         {
770             /*
771              * No more work to do, exit this thread.
772              */
773             run = 0;
774             continue;
775         } 
776
777         if( yadif_work->dst == NULL )
778         {
779             hb_error( "thread started when no work available" );
780             hb_snooze(500);
781             continue;
782         }
783         
784         is_combed = pv->yadif_arguments[segment].is_combed;
785
786         /*
787          * Process all three planes, but only this segment of it.
788          */
789         for( plane = 0; plane < 3; plane++)
790         {
791
792             dst = yadif_work->dst;
793             parity = yadif_work->parity;
794             tff = yadif_work->tff;
795             w = pv->width[plane];
796             h = pv->height[plane];
797             ref_stride = pv->ref_stride[plane];
798             segment_start = ( h / pv->cpu_count ) * segment;
799             if( segment == pv->cpu_count - 1 )
800             {
801                 /*
802                  * Final segment
803                  */
804                 segment_stop = h;
805             } else {
806                 segment_stop = ( h / pv->cpu_count ) * ( segment + 1 );
807             }
808
809             for( y = segment_start; y < segment_stop; y++ )
810             {
811                 if( ( pv->mode == 4 && is_combed ) || is_combed == 2 )
812                 {
813                     uint8_t *prev = &pv->ref[0][plane][y*ref_stride];
814                     uint8_t *cur  = &pv->ref[1][plane][y*ref_stride];
815                     uint8_t *next = &pv->ref[2][plane][y*ref_stride];
816                     uint8_t *dst2 = &dst[plane][y*w];
817
818                     blend_filter_line( dst2, cur, plane, y, pv );
819                 }
820                 else if( (y ^ parity) & 1 && is_combed == 1 )
821                 {
822                     uint8_t *prev = &pv->ref[0][plane][y*ref_stride];
823                     uint8_t *cur  = &pv->ref[1][plane][y*ref_stride];
824                     uint8_t *next = &pv->ref[2][plane][y*ref_stride];
825                     uint8_t *dst2 = &dst[plane][y*w];
826
827                     yadif_filter_line( dst2, prev, cur, next, plane, parity ^ tff, y, pv );
828                 }
829                 else
830                 {
831                     memcpy( &dst[plane][y*w],
832                             &pv->ref[1][plane][y*ref_stride],
833                             w * sizeof(uint8_t) );              
834                 }
835             }
836         }
837         /*
838          * Finished this segment, let everyone know.
839          */
840         hb_unlock( pv->yadif_complete_lock[segment] );
841     }
842     free( thread_args_v );
843 }
844
845 static void yadif_filter( uint8_t ** dst,
846                           int parity,
847                           int tff,
848                           hb_filter_private_t * pv )
849 {
850     
851     int is_combed = comb_segmenter( pv );
852     
853     if( is_combed == 1 )
854     {
855         pv->yadif_deinterlaced_frames++;
856     }
857     else if( is_combed == 2 )
858     {
859         pv->blend_deinterlaced_frames++;
860     }
861     else
862     {
863         pv->unfiltered_frames++;
864     }
865     
866     if( is_combed )
867     {
868         int segment;
869
870         for( segment = 0; segment < pv->cpu_count; segment++ )
871         {  
872             /*
873              * Setup the work for this plane.
874              */
875             pv->yadif_arguments[segment].parity = parity;
876             pv->yadif_arguments[segment].tff = tff;
877             pv->yadif_arguments[segment].dst = dst;
878             pv->yadif_arguments[segment].is_combed = is_combed;
879
880             /*
881              * Let the thread for this plane know that we've setup work 
882              * for it by releasing the begin lock (ensuring that the
883              * complete lock is already locked so that we block when
884              * we try to lock it again below).
885              */
886             hb_lock( pv->yadif_complete_lock[segment] );
887             hb_unlock( pv->yadif_begin_lock[segment] );
888         }
889
890         /*
891          * Wait until all three threads have completed by trying to get
892          * the complete lock that we locked earlier for each thread, which
893          * will block until that thread has completed the work on that
894          * plane.
895          */
896         for( segment = 0; segment < pv->cpu_count; segment++ )
897         {
898             hb_lock( pv->yadif_complete_lock[segment] );
899             hb_unlock( pv->yadif_complete_lock[segment] );
900         }
901
902         /*
903          * Entire frame is now deinterlaced.
904          */
905     }
906     else
907     {
908         /*  Just passing through... */
909         int i;
910         for( i = 0; i < 3; i++ )
911         {
912             uint8_t * ref = pv->ref[1][i];
913             uint8_t * dest = dst[i];
914             
915             int w = pv->width[i];
916             int ref_stride = pv->ref_stride[i];
917             
918             int y;
919             for( y = 0; y < pv->height[i]; y++ )
920             {
921                 memcpy(dest, ref, w);
922                 dest += w;
923                 ref += ref_stride;
924             }
925         }
926     }
927 }
928
929 static void mcdeint_filter( uint8_t ** dst,
930                             uint8_t ** src,
931                             int parity,
932                             hb_filter_private_t * pv )
933 {
934     int x, y, i;
935     int out_size;
936
937 #ifdef SUPPRESS_AV_LOG
938     /* TODO: temporarily change log level to suppress obnoxious debug output */
939     int loglevel = av_log_get_level();
940     av_log_set_level( AV_LOG_QUIET );
941 #endif
942
943     for( i=0; i<3; i++ )
944     {
945         pv->mcdeint_frame->data[i] = src[i];
946         pv->mcdeint_frame->linesize[i] = pv->width[i];
947     }
948     pv->mcdeint_avctx_enc->me_cmp     = FF_CMP_SAD;
949     pv->mcdeint_avctx_enc->me_sub_cmp = FF_CMP_SAD;
950     pv->mcdeint_frame->quality        = pv->mcdeint_qp * FF_QP2LAMBDA;
951
952     out_size = avcodec_encode_video( pv->mcdeint_avctx_enc,
953                                      pv->mcdeint_outbuf,
954                                      pv->mcdeint_outbuf_size,
955                                      pv->mcdeint_frame );
956
957     pv->mcdeint_frame_dec = pv->mcdeint_avctx_enc->coded_frame;
958
959     for( i = 0; i < 3; i++ )
960     {
961         int w    = pv->width[i];
962         int h    = pv->height[i];
963         int fils = pv->mcdeint_frame_dec->linesize[i];
964         int srcs = pv->width[i];
965
966         for( y = 0; y < h; y++ )
967         {
968             if( (y ^ parity) & 1 )
969             {
970                 for( x = 0; x < w; x++ )
971                 {
972                     if( (x-2)+(y-1)*w >= 0 && (x+2)+(y+1)*w < w*h )
973                     {
974                         uint8_t * filp =
975                             &pv->mcdeint_frame_dec->data[i][x + y*fils];
976                         uint8_t * srcp = &src[i][x + y*srcs];
977
978                         int diff0 = filp[-fils] - srcp[-srcs];
979                         int diff1 = filp[+fils] - srcp[+srcs];
980
981                         int spatial_score =
982                               ABS(srcp[-srcs-1] - srcp[+srcs-1])
983                             + ABS(srcp[-srcs  ] - srcp[+srcs  ])
984                             + ABS(srcp[-srcs+1] - srcp[+srcs+1]) - 1;
985
986                         int temp = filp[0];
987
988 #define MCDEINT_CHECK(j)\
989                         {   int score = ABS(srcp[-srcs-1+j] - srcp[+srcs-1-j])\
990                                       + ABS(srcp[-srcs  +j] - srcp[+srcs  -j])\
991                                       + ABS(srcp[-srcs+1+j] - srcp[+srcs+1-j]);\
992                             if( score < spatial_score ) {\
993                                 spatial_score = score;\
994                                 diff0 = filp[-fils+j] - srcp[-srcs+j];\
995                                 diff1 = filp[+fils-j] - srcp[+srcs-j];
996
997                         MCDEINT_CHECK(-1) MCDEINT_CHECK(-2) }} }}
998                         MCDEINT_CHECK( 1) MCDEINT_CHECK( 2) }} }}
999
1000                         if(diff0 + diff1 > 0)
1001                         {
1002                             temp -= (diff0 + diff1 -
1003                                      ABS( ABS(diff0) - ABS(diff1) ) / 2) / 2;
1004                         }
1005                         else
1006                         {
1007                             temp -= (diff0 + diff1 +
1008                                      ABS( ABS(diff0) - ABS(diff1) ) / 2) / 2;
1009                         }
1010
1011                         filp[0] = dst[i][x + y*w] =
1012                             temp > 255U ? ~(temp>>31) : temp;
1013                     }
1014                     else
1015                     {
1016                         dst[i][x + y*w] =
1017                             pv->mcdeint_frame_dec->data[i][x + y*fils];
1018                     }
1019                 }
1020             }
1021         }
1022
1023         for( y = 0; y < h; y++ )
1024         {
1025             if( !((y ^ parity) & 1) )
1026             {
1027                 for( x = 0; x < w; x++ )
1028                 {
1029                     pv->mcdeint_frame_dec->data[i][x + y*fils] =
1030                         dst[i][x + y*w]= src[i][x + y*srcs];
1031                 }
1032             }
1033         }
1034     }
1035
1036 #ifdef SUPPRESS_AV_LOG
1037     /* TODO: restore previous log level */
1038     av_log_set_level(loglevel);
1039 #endif
1040 }
1041
1042 hb_filter_private_t * hb_decomb_init( int pix_fmt,
1043                                            int width,
1044                                            int height,
1045                                            char * settings )
1046 {
1047     if( pix_fmt != PIX_FMT_YUV420P )
1048     {
1049         return 0;
1050     }
1051
1052     hb_filter_private_t * pv = calloc( 1, sizeof(struct hb_filter_private_s) );
1053
1054     pv->pix_fmt = pix_fmt;
1055
1056     pv->width[0]  = width;
1057     pv->height[0] = height;
1058     pv->width[1]  = pv->width[2]  = width >> 1;
1059     pv->height[1] = pv->height[2] = height >> 1;
1060
1061     int buf_size = 3 * width * height / 2;
1062     pv->buf_out[0] = hb_buffer_init( buf_size );
1063     pv->buf_out[1] = hb_buffer_init( buf_size );
1064     pv->buf_settings = hb_buffer_init( 0 );
1065
1066     pv->yadif_deinterlaced_frames = 0;
1067     pv->blend_deinterlaced_frames = 0;
1068     pv->unfiltered_frames = 0;
1069
1070     pv->yadif_ready    = 0;
1071
1072     pv->mode     = MODE_DEFAULT;
1073     pv->spatial_metric = 2;
1074     pv->motion_threshold = 6;
1075     pv->spatial_threshold = 9;
1076     pv->block_threshold = 80;
1077     pv->block_width = 16;
1078     pv->block_height = 16;
1079     
1080     pv->parity   = PARITY_DEFAULT;
1081
1082     pv->mcdeint_mode   = MCDEINT_MODE_DEFAULT;
1083     pv->mcdeint_qp     = MCDEINT_QP_DEFAULT;
1084
1085     if( settings )
1086     {
1087         sscanf( settings, "%d:%d:%d:%d:%d:%d:%d",
1088                 &pv->mode,
1089                 &pv->spatial_metric,
1090                 &pv->motion_threshold,
1091                 &pv->spatial_threshold,
1092                 &pv->block_threshold,
1093                 &pv->block_width,
1094                 &pv->block_height );
1095     }
1096     
1097     pv->cpu_count = hb_get_cpu_count();
1098     
1099
1100     if( pv->mode == 2 || pv->mode == 3 )
1101     {
1102         pv->mcdeint_mode = 0;
1103     }
1104     
1105     /* Allocate yadif specific buffers */
1106     int i, j;
1107     for( i = 0; i < 3; i++ )
1108     {
1109         int is_chroma = !!i;
1110         int w = ((width   + 31) & (~31))>>is_chroma;
1111         int h = ((height+6+ 31) & (~31))>>is_chroma;
1112
1113         pv->ref_stride[i] = w;
1114
1115         for( j = 0; j < 3; j++ )
1116         {
1117             pv->ref[j][i] = malloc( w*h*sizeof(uint8_t) ) + 3*w;
1118         }
1119     }
1120
1121     /* Allocate a buffer to store a comb mask. */
1122     for( i = 0; i < 3; i++ )
1123     {
1124         int is_chroma = !!i;
1125         int w = ((pv->width[0]   + 31) & (~31))>>is_chroma;
1126         int h = ((pv->height[0]+6+ 31) & (~31))>>is_chroma;
1127
1128         pv->mask[i] = calloc( 1, w*h*sizeof(uint8_t) ) + 3*w;
1129     }
1130
1131      /*
1132       * Create yadif threads and locks.
1133       */
1134      pv->yadif_threads = malloc( sizeof( hb_thread_t* ) * pv->cpu_count );
1135      pv->yadif_begin_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
1136      pv->yadif_complete_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
1137      pv->yadif_arguments = malloc( sizeof( yadif_arguments_t ) * pv->cpu_count );
1138
1139      for( i = 0; i < pv->cpu_count; i++ )
1140      {
1141          yadif_thread_arg_t *thread_args;
1142
1143          thread_args = malloc( sizeof( yadif_thread_arg_t ) );
1144
1145          if( thread_args )
1146          {
1147              thread_args->pv = pv;
1148              thread_args->segment = i;
1149
1150              pv->yadif_begin_lock[i] = hb_lock_init();
1151              pv->yadif_complete_lock[i] = hb_lock_init();
1152
1153              /*
1154               * Important to start off with the threads locked waiting
1155               * on input.
1156               */
1157              hb_lock( pv->yadif_begin_lock[i] );
1158
1159              pv->yadif_arguments[i].stop = 0;
1160              pv->yadif_arguments[i].dst = NULL;
1161              
1162              pv->yadif_threads[i] = hb_thread_init( "yadif_filter_segment",
1163                                                     yadif_decomb_filter_thread,
1164                                                     thread_args,
1165                                                     HB_NORMAL_PRIORITY );
1166          }
1167          else
1168          {
1169              hb_error( "yadif could not create threads" );
1170          }
1171     }
1172     
1173     /*
1174      * Create decomb threads and locks.
1175      */
1176     pv->decomb_threads = malloc( sizeof( hb_thread_t* ) * pv->cpu_count );
1177     pv->decomb_begin_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
1178     pv->decomb_complete_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
1179     pv->decomb_arguments = malloc( sizeof( decomb_arguments_t ) * pv->cpu_count );
1180     
1181     for( i = 0; i < pv->cpu_count; i++ )
1182     {
1183         decomb_thread_arg_t *decomb_thread_args;
1184     
1185         decomb_thread_args = malloc( sizeof( decomb_thread_arg_t ) );
1186     
1187         if( decomb_thread_args )
1188         {
1189             decomb_thread_args->pv = pv;
1190             decomb_thread_args->segment = i;
1191     
1192             pv->decomb_begin_lock[i] = hb_lock_init();
1193             pv->decomb_complete_lock[i] = hb_lock_init();
1194     
1195             /*
1196              * Important to start off with the threads locked waiting
1197              * on input.
1198              */
1199             hb_lock( pv->decomb_begin_lock[i] );
1200     
1201             pv->decomb_arguments[i].stop = 0;
1202     
1203             pv->decomb_threads[i] = hb_thread_init( "decomb_filter_segment",
1204                                                    decomb_filter_thread,
1205                                                    decomb_thread_args,
1206                                                    HB_NORMAL_PRIORITY );
1207         }
1208         else
1209         {
1210             hb_error( "decomb could not create threads" );
1211         }
1212     }
1213
1214     
1215     
1216     /* Allocate mcdeint specific buffers */
1217     if( pv->mcdeint_mode >= 0 )
1218     {
1219         avcodec_init();
1220         avcodec_register_all();
1221
1222         AVCodec * enc = avcodec_find_encoder( CODEC_ID_SNOW );
1223
1224         int i;
1225         for (i = 0; i < 3; i++ )
1226         {
1227             AVCodecContext * avctx_enc;
1228
1229             avctx_enc = pv->mcdeint_avctx_enc = avcodec_alloc_context();
1230
1231             avctx_enc->width                    = width;
1232             avctx_enc->height                   = height;
1233             avctx_enc->time_base                = (AVRational){1,25};  // meaningless
1234             avctx_enc->gop_size                 = 300;
1235             avctx_enc->max_b_frames             = 0;
1236             avctx_enc->pix_fmt                  = PIX_FMT_YUV420P;
1237             avctx_enc->flags                    = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
1238             avctx_enc->strict_std_compliance    = FF_COMPLIANCE_EXPERIMENTAL;
1239             avctx_enc->global_quality           = 1;
1240             avctx_enc->flags2                   = CODEC_FLAG2_MEMC_ONLY;
1241             avctx_enc->me_cmp                   = FF_CMP_SAD; //SSE;
1242             avctx_enc->me_sub_cmp               = FF_CMP_SAD; //SSE;
1243             avctx_enc->mb_cmp                   = FF_CMP_SSE;
1244
1245             switch( pv->mcdeint_mode )
1246             {
1247                 case 3:
1248                     avctx_enc->refs = 3;
1249                 case 2:
1250                     avctx_enc->me_method = ME_UMH;
1251                 case 1:
1252                     avctx_enc->flags |= CODEC_FLAG_4MV;
1253                     avctx_enc->dia_size =2;
1254                 case 0:
1255                     avctx_enc->flags |= CODEC_FLAG_QPEL;
1256             }
1257
1258             avcodec_open(avctx_enc, enc);
1259         }
1260
1261         pv->mcdeint_frame       = avcodec_alloc_frame();
1262         pv->mcdeint_outbuf_size = width * height * 10;
1263         pv->mcdeint_outbuf      = malloc( pv->mcdeint_outbuf_size );
1264     }
1265
1266     return pv;
1267 }
1268
1269 void hb_decomb_close( hb_filter_private_t * pv )
1270 {
1271     if( !pv )
1272     {
1273         return;
1274     }
1275     
1276     hb_log("decomb: yadif deinterlaced %i | blend deinterlaced %i | unfiltered %i | total %i", pv->yadif_deinterlaced_frames, pv->blend_deinterlaced_frames, pv->unfiltered_frames, pv->yadif_deinterlaced_frames + pv->blend_deinterlaced_frames + pv->unfiltered_frames);
1277
1278     /* Cleanup frame buffers */
1279     if( pv->buf_out[0] )
1280     {
1281         hb_buffer_close( &pv->buf_out[0] );
1282     }
1283     if( pv->buf_out[1] )
1284     {
1285         hb_buffer_close( &pv->buf_out[1] );
1286     }
1287     if (pv->buf_settings )
1288     {
1289         hb_buffer_close( &pv->buf_settings );
1290     }
1291
1292     /* Cleanup yadif specific buffers */
1293     int i;
1294     for( i = 0; i<3*3; i++ )
1295     {
1296         uint8_t **p = &pv->ref[i%3][i/3];
1297         if (*p)
1298         {
1299             free( *p - 3*pv->ref_stride[i/3] );
1300             *p = NULL;
1301         }
1302     }
1303     
1304     /* Cleanup combing mask. */
1305     for( i = 0; i<3*3; i++ )
1306     {
1307         uint8_t **p = &pv->mask[i/3];
1308         if (*p)
1309         {
1310             free( *p - 3*pv->ref_stride[i/3] );
1311             *p = NULL;
1312         }
1313     }
1314     
1315     for( i = 0; i < pv->cpu_count; i++)
1316     {
1317         /*
1318          * Tell each yadif thread to stop, and then cleanup.
1319          */
1320         pv->yadif_arguments[i].stop = 1;
1321         hb_unlock(  pv->yadif_begin_lock[i] );
1322
1323         hb_thread_close( &pv->yadif_threads[i] );
1324         hb_lock_close( &pv->yadif_begin_lock[i] );
1325         hb_lock_close( &pv->yadif_complete_lock[i] );
1326     }
1327     
1328     /*
1329      * free memory for yadif structs
1330      */
1331     free( pv->yadif_threads );
1332     free( pv->yadif_begin_lock );
1333     free( pv->yadif_complete_lock );
1334     free( pv->yadif_arguments );
1335     
1336     for( i = 0; i < pv->cpu_count; i++)
1337     {
1338         /*
1339          * Tell each decomb thread to stop, and then cleanup.
1340          */
1341         pv->decomb_arguments[i].stop = 1;
1342         hb_unlock(  pv->decomb_begin_lock[i] );
1343
1344         hb_thread_close( &pv->decomb_threads[i] );
1345         hb_lock_close( &pv->decomb_begin_lock[i] );
1346         hb_lock_close( &pv->decomb_complete_lock[i] );
1347     }
1348     
1349     /*
1350      * free memory for decomb structs
1351      */
1352     free( pv->decomb_threads );
1353     free( pv->decomb_begin_lock );
1354     free( pv->decomb_complete_lock );
1355     free( pv->decomb_arguments );
1356     
1357     /* Cleanup mcdeint specific buffers */
1358     if( pv->mcdeint_mode >= 0 )
1359     {
1360         if( pv->mcdeint_avctx_enc )
1361         {
1362             avcodec_close( pv->mcdeint_avctx_enc );
1363             av_freep( &pv->mcdeint_avctx_enc );
1364         }
1365         if( pv->mcdeint_outbuf )
1366         {
1367             free( pv->mcdeint_outbuf );
1368         }
1369     }
1370
1371     free( pv );
1372 }
1373
1374 int hb_decomb_work( const hb_buffer_t * cbuf_in,
1375                     hb_buffer_t ** buf_out,
1376                     int pix_fmt,
1377                     int width,
1378                     int height,
1379                     hb_filter_private_t * pv )
1380 {
1381     hb_buffer_t * buf_in = (hb_buffer_t *)cbuf_in;
1382
1383     if( !pv ||
1384         pix_fmt != pv->pix_fmt ||
1385         width   != pv->width[0] ||
1386         height  != pv->height[0] )
1387     {
1388         return FILTER_FAILED;
1389     }
1390
1391     avpicture_fill( &pv->pic_in, buf_in->data,
1392                     pix_fmt, width, height );
1393
1394     /* Determine if top-field first layout */
1395     int tff;
1396     if( pv->parity < 0 )
1397     {
1398         tff = !!(buf_in->flags & PIC_FLAG_TOP_FIELD_FIRST);
1399     }
1400     else
1401     {
1402         tff = (pv->parity & 1) ^ 1;
1403     }
1404
1405     /* Store current frame in yadif cache */
1406     store_ref( (const uint8_t**)pv->pic_in.data, pv );
1407
1408     /* If yadif is not ready, store another ref and return FILTER_DELAY */
1409     if( pv->yadif_ready == 0 )
1410     {
1411         store_ref( (const uint8_t**)pv->pic_in.data, pv );
1412
1413         hb_buffer_copy_settings( pv->buf_settings, buf_in );
1414
1415         /* don't let 'work_loop' send a chapter mark upstream */
1416         buf_in->new_chap  = 0;
1417
1418         pv->yadif_ready = 1;
1419
1420         return FILTER_DELAY;
1421     }
1422
1423     /* Perform yadif filtering */        
1424     int frame;
1425     for( frame = 0; frame <= ( ( pv->mode == 2 || pv->mode == 3 )? 1 : 0 ) ; frame++ )
1426     {
1427         int parity = frame ^ tff ^ 1;
1428
1429         avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data,
1430                         pix_fmt, width, height );
1431
1432         yadif_filter( pv->pic_out.data, parity, tff, pv );
1433
1434         if( pv->mcdeint_mode >= 0 )
1435         {
1436             /* Perform mcdeint filtering */
1437             avpicture_fill( &pv->pic_in,  pv->buf_out[(frame^1)]->data,
1438                             pix_fmt, width, height );
1439
1440             mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv );
1441         }
1442
1443         *buf_out = pv->buf_out[!(frame^1)];
1444     }
1445
1446     /* Copy buffered settings to output buffer settings */
1447     hb_buffer_copy_settings( *buf_out, pv->buf_settings );
1448
1449     /* Replace buffered settings with input buffer settings */
1450     hb_buffer_copy_settings( pv->buf_settings, buf_in );
1451
1452     /* don't let 'work_loop' send a chapter mark upstream */
1453     buf_in->new_chap  = 0;
1454
1455     return FILTER_OK;
1456 }