OSDN Git Service

Adds a parity parameter to detelecine and rewires it in decomb, so that TFF can be...
[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    Tritical's work inspired much of the comb detection code:
9    http://web.missouri.edu/~kes25c/
10 */
11
12 /*****
13 Parameters:
14     Mode : Spatial metric : Motion thresh : Spatial thresh : Block thresh :
15     Block width : Block height
16
17 Appended for EEDI2:
18     Magnitude thresh : Variance thresh : Laplacian thresh : Dilation thresh :
19     Erosion thresh : Noise thresh : Max search distance : Post-processing
20
21 Defaults:
22     7:2:6:9:80:16:16:10:20:20:4:2:50:24:1
23 *****/
24
25 #define MODE_YADIF       1 // Use yadif
26 #define MODE_BLEND       2 // Use blending interpolation
27 #define MODE_CUBIC       4 // Use cubic interpolation
28 #define MODE_EEDI2       8 // Use EEDI2 interpolation
29 #define MODE_MCDEINT    16 // Post-process with mcdeint
30 #define MODE_MASK       32 // Output combing masks instead of pictures
31
32 /***** 
33 These modes can be layered. For example, Yadif (1) + EEDI2 (8) = 9,
34 which will feed EEDI2 interpolations to yadif.
35
36 ** Working combos:
37  1: Just yadif
38  2: Just blend
39  3: Switch between yadif and blend
40  4: Just cubic interpolate
41  5: Cubic->yadif
42  6: Switch between cubic and blend
43  7: Switch between cubic->yadif and blend
44  8: Just EEDI2 interpolate
45  9: EEDI2->yadif
46 10: Switch between EEDI2 and blend
47 11: Switch between EEDI2->yadif and blend
48 17: Yadif->mcdeint
49 18: Blend->mcdeint
50 19: Switch between blending and yadif -> mcdeint
51 20: Cubic->mdeint
52 21: Cubic->yadif->mcdeint
53 22: Cubic or blend -> mcdeint
54 23: Cubic->yadif or blend -> mcdeint
55 24: EEDI2->mcdeint
56 25: EEDI2->yadif->mcdeint
57 ...okay I'm getting bored now listing all these different modes
58 32: Passes through the combing mask for every combed frame (white for combed pixels, otherwise black)
59 33+: Overlay the combing mask for every combed frame on top of the filtered output (white for combed pixels)
60
61 12-15: EEDI2 will override cubic interpolation
62 16: DOES NOT WORK BY ITSELF-- mcdeint needs to be fed by another deinterlacer
63 *****/
64
65 #include "hb.h"
66 #include "hbffmpeg.h"
67 #include "mpeg2dec/mpeg2.h"
68 #include "eedi2.h"
69
70 #define SUPPRESS_AV_LOG
71
72 #define PARITY_DEFAULT   -1
73
74 #define MCDEINT_MODE_DEFAULT   -1
75 #define MCDEINT_QP_DEFAULT      1
76
77 #define ABS(a) ((a) > 0 ? (a) : (-(a)))
78 #define MIN3(a,b,c) MIN(MIN(a,b),c)
79 #define MAX3(a,b,c) MAX(MAX(a,b),c)
80
81 // Some names to correspond to the pv->eedi_half array's contents
82 #define SRCPF 0
83 #define MSKPF 1
84 #define TMPPF 2
85 #define DSTPF 3
86 // Some names to correspond to the pv->eedi_full array's contents
87 #define DST2PF 0
88 #define TMP2PF2 1
89 #define MSK2PF 2
90 #define TMP2PF 3
91 #define DST2MPF 4
92
93 struct yadif_arguments_s {
94     uint8_t **dst;
95     int parity;
96     int tff;
97     int stop;
98     int is_combed;
99 };
100
101 struct decomb_arguments_s {
102     int stop;
103 };
104
105 struct eedi2_arguments_s {
106     int stop;
107 };
108
109 typedef struct yadif_arguments_s yadif_arguments_t;
110 typedef struct decomb_arguments_s decomb_arguments_t;
111 typedef struct eedi2_arguments_s eedi2_arguments_t;
112
113 typedef struct eedi2_thread_arg_s {
114     hb_filter_private_t *pv;
115     int plane;
116 } eedi2_thread_arg_t;
117
118 typedef struct decomb_thread_arg_s {
119     hb_filter_private_t *pv;
120     int segment;
121 } decomb_thread_arg_t;
122
123 typedef struct yadif_thread_arg_s {
124     hb_filter_private_t *pv;
125     int segment;
126 } yadif_thread_arg_t;
127
128 struct hb_filter_private_s
129 {
130     int              pix_fmt;
131     int              width[3];
132     int              height[3];
133
134     // Decomb parameters
135     int              mode;
136     int              spatial_metric;
137     int              motion_threshold;
138     int              spatial_threshold;
139     int              block_threshold;
140     int              block_width;
141     int              block_height;
142     
143     // EEDI2 parameters
144     int              magnitude_threshold;
145     int              variance_threshold;
146     int              laplacian_threshold;
147     int              dilation_threshold;
148     int              erosion_threshold;
149     int              noise_threshold;
150     int              maximum_search_distance;
151     int              post_processing;
152
153     int              parity;
154     int              tff;
155     
156     int              yadif_ready;
157
158     int              mcdeint_mode;
159     int              mcdeint_qp;
160
161     int              mcdeint_outbuf_size;
162     uint8_t        * mcdeint_outbuf;
163     AVCodecContext * mcdeint_avctx_enc;
164     AVFrame        * mcdeint_frame;
165     AVFrame        * mcdeint_frame_dec;
166
167     int              deinterlaced_frames;
168     int              blended_frames;
169     int              unfiltered_frames;
170
171     uint8_t        * ref[4][3];
172     int              ref_stride[3];
173
174     /* Make a buffer to store a comb mask. */
175     uint8_t        * mask[3];
176
177     uint8_t        * eedi_half[4][3];
178     uint8_t        * eedi_full[5][3];
179     int            * cx2;
180     int            * cy2;
181     int            * cxy;
182     int            * tmpc;
183     
184     AVPicture        pic_in;
185     AVPicture        pic_out;
186     hb_buffer_t *    buf_out[2];
187     hb_buffer_t *    buf_settings;
188     
189     int              cpu_count;
190
191     hb_thread_t    ** yadif_threads;         // Threads for Yadif - one per CPU
192     hb_lock_t      ** yadif_begin_lock;      // Thread has work
193     hb_lock_t      ** yadif_complete_lock;   // Thread has completed work
194     yadif_arguments_t *yadif_arguments;      // Arguments to thread for work
195     
196     hb_thread_t    ** decomb_threads;        // Threads for comb detection - one per CPU
197     hb_lock_t      ** decomb_begin_lock;     // Thread has work
198     hb_lock_t      ** decomb_complete_lock;  // Thread has completed work
199     decomb_arguments_t *decomb_arguments;    // Arguments to thread for work
200
201     hb_thread_t    ** eedi2_threads;        // Threads for eedi2 - one per plane
202     hb_lock_t      ** eedi2_begin_lock;     // Thread has work
203     hb_lock_t      ** eedi2_complete_lock;  // Thread has completed work
204     eedi2_arguments_t *eedi2_arguments;    // Arguments to thread for work
205
206 //    int              alternator;           // for bobbing parity when framedoubling
207 };
208
209 hb_filter_private_t * hb_decomb_init( int pix_fmt,
210                                            int width,
211                                            int height,
212                                            char * settings );
213
214 int hb_decomb_work(      const hb_buffer_t * buf_in,
215                          hb_buffer_t ** buf_out,
216                          int pix_fmt,
217                          int width,
218                          int height,
219                          hb_filter_private_t * pv );
220
221 void hb_decomb_close( hb_filter_private_t * pv );
222
223 hb_filter_object_t hb_filter_decomb =
224 {
225     FILTER_DECOMB,
226     "Decomb",
227     NULL,
228     hb_decomb_init,
229     hb_decomb_work,
230     hb_decomb_close,
231 };
232
233 int cubic_interpolate_pixel( int y0, int y1, int y2, int y3 )
234 {
235     /* From http://www.neuron2.net/library/cubicinterp.html */
236     int result = ( y0 * -3 ) + ( y1 * 23 ) + ( y2 * 23 ) + ( y3 * -3 );
237     result /= 40;
238     
239     if( result > 255 )
240     {
241         result = 255;
242     }
243     else if( result < 0 )
244     {
245         result = 0;
246     }
247     
248     return result;
249 }
250
251 static void cubic_interpolate_line( uint8_t *dst,
252                                uint8_t *cur,
253                                int plane,
254                                int y,
255                                hb_filter_private_t * pv )
256 {
257     int w = pv->width[plane];
258     int refs = pv->ref_stride[plane];
259     int x;
260
261     for( x = 0; x < w; x++)
262     {
263         int a, b, c, d;
264         a = b = c = d = 0;
265         
266         if( y >= 3 )
267         {
268             /* Normal top*/
269             a = cur[-3*refs];
270             b = cur[-refs];
271         }
272         else if( y == 2 || y == 1 )
273         {
274             /* There's only one sample above this pixel, use it twice. */
275             a = cur[-refs];
276             b = cur[-refs];
277         }
278         else if( y == 0 )
279         {
280             /* No samples above, triple up on the one below. */
281             a = cur[+refs];
282             b = cur[+refs];
283         }
284         
285         if( y <= ( pv->height[plane] - 4 ) )
286         {
287             /* Normal bottom*/
288             c = cur[+refs];
289             d = cur[3*refs];            
290         }
291         else if( y == ( pv->height[plane] - 3 ) || y == ( pv->height[plane] - 2 ) )
292         {
293             /* There's only one sample below, use it twice. */
294             c = cur[+refs];
295             d = cur[+refs];
296         }
297         else if( y == pv->height[plane] - 1)
298         {
299             /* No samples below, triple up on the one above. */
300             c = cur[-refs];
301             d = cur[-refs];
302         }
303         
304         dst[0] = cubic_interpolate_pixel( a, b, c, d );
305         
306         dst++;
307         cur++;
308     }
309 }
310
311 void apply_mask_line( uint8_t * srcp,
312                       uint8_t * mskp,
313                       int width )
314 {
315     int x;
316     
317     for( x = 0; x < width; x++ )
318     {
319         if( mskp[x] == 255 )
320         {
321             srcp[x] = 255;
322         }
323     }
324 }
325
326 void apply_mask( hb_filter_private_t * pv )
327 {
328     int plane, height;
329     
330     for( plane = 0; plane < 3; plane++ )
331     {
332         uint8_t * srcp = ( pv->mode & MODE_MCDEINT ) ? pv->pic_in.data[plane] : pv->pic_out.data[plane];
333         uint8_t * mskp = pv->mask[plane];
334         
335         for( height = 0; height < pv->height[plane]; height++ )
336         {
337             if( pv->mode == MODE_MASK && plane == 0 )
338             {
339                 memcpy( srcp, mskp, pv->width[plane] );
340             }
341             else if( pv->mode == MODE_MASK )
342             {
343                 memset( srcp, 128, pv->width[plane] );
344             }
345             else if( plane == 0 )
346             {
347                 apply_mask_line( srcp, mskp, pv->width[plane] );
348             }
349
350             srcp += pv->pic_out.linesize[plane];
351             mskp += pv->ref_stride[plane];
352         }
353     }
354 }
355
356 static void store_ref( const uint8_t ** pic,
357                              hb_filter_private_t * pv )
358 {
359     memcpy( pv->ref[3],
360             pv->ref[0],
361             sizeof(uint8_t *)*3 );
362
363     memmove( pv->ref[0],
364              pv->ref[1],
365              sizeof(uint8_t *)*3*3 );
366
367     int i;
368     for( i = 0; i < 3; i++ )
369     {
370         const uint8_t * src = pic[i];
371         uint8_t * ref = pv->ref[2][i];
372
373         int w = pv->width[i];
374         int h = pv->height[i];
375         int ref_stride = pv->ref_stride[i];
376
377         int y;
378         for( y = 0; y < h; y++ )
379         {
380             memcpy(ref, src, w);
381             src = (uint8_t*)src + w;
382             ref = (uint8_t*)ref + ref_stride;
383         }
384     }
385 }
386
387 /* This function may be useful in the future, if we want to output
388    a reference to an AVPicture, since they have different strides.
389 static void get_ref( uint8_t ** pic, hb_filter_private_t * pv, int frm )
390 {
391     int i;
392     for( i = 0; i < 3; i++ )
393     {
394         uint8_t * dst = pic[i];
395         const uint8_t * ref = pv->ref[frm][i];
396         int w = pv->width[i];
397         int ref_stride = pv->ref_stride[i];
398         
399         int y;
400         for( y = 0; y < pv->height[i]; y++ )
401         {
402             memcpy(dst, ref, w);
403             dst += w;
404             ref += ref_stride;
405         }
406     }
407 }
408 */
409
410 int blend_filter_pixel( int up2, int up1, int current, int down1, int down2 )
411 {
412     /* Low-pass 5-tap filter */
413     int result = 0;
414     result += -up2;
415     result += up1 * 2;
416     result += current * 6;
417     result += down1 *2;
418     result += -down2;
419     result /= 8;
420
421     if( result > 255 )
422     {
423         result = 255;
424     }
425     if( result < 0 )
426     {
427         result = 0;
428     }
429     
430     return result;
431 }
432
433 static void blend_filter_line( uint8_t *dst,
434                                uint8_t *cur,
435                                int plane,
436                                int y,
437                                hb_filter_private_t * pv )
438 {
439     int w = pv->width[plane];
440     int refs = pv->ref_stride[plane];
441     int x;
442
443     for( x = 0; x < w; x++)
444     {
445         int a, b, c, d, e;
446         
447         a = cur[-2*refs];
448         b = cur[-refs];
449         c = cur[0];
450         d = cur[+refs];
451         e = cur[2*refs];
452         
453         if( y == 0 )
454         {
455             /* First line, so A and B don't exist.*/
456             a = cur[0];
457             b = cur[0];
458         }
459         else if( y == 1 )
460         {
461             /* Second line, no A. */
462             a = cur[-refs];
463         }
464         else if( y == (pv->height[plane] - 2) )
465         {
466             /* Second to last line, no E. */
467             e = cur[+refs];
468         }
469         else if( y == (pv->height[plane] -1) )
470         {
471             /* Last line, no D or E. */
472             d = cur[0];
473             e = cur[0];
474         }
475                 
476         dst[0] = blend_filter_pixel( a, b, c, d, e );
477
478         dst++;
479         cur++;
480     }
481 }
482
483 int check_combing_mask( hb_filter_private_t * pv )
484 {
485     /* Go through the mask in X*Y blocks. If any of these windows
486        have threshold or more combed pixels, consider the whole
487        frame to be combed and send it on to be deinterlaced.     */
488
489     /* Block mask threshold -- The number of pixels
490        in a block_width * block_height window of
491        he mask that need to show combing for the
492        whole frame to be seen as such.            */
493     int threshold       = pv->block_threshold;
494     int block_width     = pv->block_width;
495     int block_height    = pv->block_height;
496     int block_x, block_y;
497     int block_score = 0; int send_to_blend = 0;
498     
499     int x, y, k;
500
501     for( k = 0; k < 1; k++ )
502     {
503         int ref_stride = pv->ref_stride[k];
504         for( y = 0; y < ( pv->height[k] - block_height ); y = y + block_height )
505         {
506             for( x = 0; x < ( pv->width[k] - block_width ); x = x + block_width )
507             {
508                 block_score = 0;
509                 for( block_y = 0; block_y < block_height; block_y++ )
510                 {
511                     for( block_x = 0; block_x < block_width; block_x++ )
512                     {
513                         int mask_y = y + block_y;
514                         int mask_x = x + block_x;
515                         
516                         /* We only want to mark a pixel in a block as combed
517                            if the pixels above and below are as well. Got to
518                            handle the top and bottom lines separately.       */
519                         if( y + block_y == 0 )
520                         {
521                             if( pv->mask[k][mask_y*ref_stride+mask_x    ] == 255 &&
522                                 pv->mask[k][mask_y*ref_stride+mask_x + 1] == 255 )
523                                     block_score++;
524                         }
525                         else if( y + block_y == pv->height[k] - 1 )
526                         {
527                             if( pv->mask[k][mask_y*ref_stride+mask_x - 1] == 255 &&
528                                 pv->mask[k][mask_y*ref_stride+mask_x    ] == 255 )
529                                     block_score++;
530                         }
531                         else
532                         {
533                             if( pv->mask[k][mask_y*ref_stride+mask_x - 1] == 255 &&
534                                 pv->mask[k][mask_y*ref_stride+mask_x    ] == 255 &&
535                                 pv->mask[k][mask_y*ref_stride+mask_x + 1] == 255 )
536                                     block_score++;
537                         } 
538                     }
539                 }
540
541                 if( block_score >= ( threshold / 2 ) )
542                 {
543 #if 0
544                     hb_log("decomb: frame %i | score %i | type %s", pv->deinterlaced_frames + pv->blended_frames +  pv->unfiltered_frames + 1, block_score, pv->buf_settings->flags & 16 ? "Film" : "Video");
545 #endif
546                     if ( block_score <= threshold && !( pv->buf_settings->flags & 16) )
547                     {
548                         /* Blend video content that scores between
549                            ( threshold / 2 ) and threshold.        */
550                         send_to_blend = 1;
551                     }
552                     else if( block_score > threshold )
553                     {
554                         if( pv->buf_settings->flags & 16 )
555                         {
556                             /* Blend progressive content above the threshold.*/
557                             return 2;
558                         }
559                         else
560                         {
561                             /* Yadif deinterlace video content above the threshold. */
562                             return 1;
563                         }
564                     }
565                 }
566             }
567         } 
568     }
569     
570     if( send_to_blend )
571     {
572         return 2;
573     }
574     else
575     {
576         /* Consider this frame to be uncombed. */
577         return 0;
578     }
579 }
580
581 void detect_combed_segment( hb_filter_private_t * pv, int segment_start, int segment_stop )
582 {
583     /* A mish-mash of various comb detection tricks
584        picked up from neuron2's Decomb plugin for
585        AviSynth and tritical's IsCombedT and
586        IsCombedTIVTC plugins.                       */
587        
588     int x, y, k, width, height;
589     
590     /* Comb scoring algorithm */
591     int spatial_metric  = pv->spatial_metric;
592     /* Motion threshold */
593     int mthresh         = pv->motion_threshold;
594     /* Spatial threshold */
595     int athresh         = pv->spatial_threshold;
596     int athresh_squared = athresh * athresh;
597     int athresh6        = 6 *athresh;
598
599     /* One pas for Y, one pass for U, one pass for V */    
600     for( k = 0; k < 1; k++ )
601     {
602         int ref_stride  = pv->ref_stride[k];
603         width           = pv->width[k];
604         height          = pv->height[k];
605         
606         /* Comb detection has to start at y = 2 and end at
607            y = height - 2, because it needs to examine
608            2 pixels above and 2 below the current pixel.      */
609         if( segment_start < 2 )
610             segment_start = 2;
611         if( segment_stop > height - 2 )
612             segment_stop = height - 2;
613             
614         for( y =  segment_start; y < segment_stop; y++ )
615         {
616             /* These are just to make the buffer locations easier to read. */
617             int back_2    = ( y - 2 )*ref_stride ;
618             int back_1    = ( y - 1 )*ref_stride;
619             int current   =         y*ref_stride;
620             int forward_1 = ( y + 1 )*ref_stride;
621             int forward_2 = ( y + 2 )*ref_stride;
622             
623             /* We need to examine a column of 5 pixels
624                in the prev, cur, and next frames.      */
625             uint8_t previous_frame[5];
626             uint8_t current_frame[5];
627             uint8_t next_frame[5];
628             
629             for( x = 0; x < width; x++ )
630             {
631                 /* Fill up the current frame array with the current pixel values.*/
632                 current_frame[0] = pv->ref[1][k][back_2    + x];
633                 current_frame[1] = pv->ref[1][k][back_1    + x];
634                 current_frame[2] = pv->ref[1][k][current   + x];
635                 current_frame[3] = pv->ref[1][k][forward_1 + x];
636                 current_frame[4] = pv->ref[1][k][forward_2 + x];
637
638                 int up_diff   = current_frame[2] - current_frame[1];
639                 int down_diff = current_frame[2] - current_frame[3];
640
641                 if( ( up_diff >  athresh && down_diff >  athresh ) ||
642                     ( up_diff < -athresh && down_diff < -athresh ) )
643                 {
644                     /* The pixel above and below are different,
645                        and they change in the same "direction" too.*/
646                     int motion = 0;
647                     if( mthresh > 0 )
648                     {
649                         /* Make sure there's sufficient motion between frame t-1 to frame t+1. */
650                         previous_frame[0] = pv->ref[0][k][back_2    + x];
651                         previous_frame[1] = pv->ref[0][k][back_1    + x];
652                         previous_frame[2] = pv->ref[0][k][current   + x];
653                         previous_frame[3] = pv->ref[0][k][forward_1 + x];
654                         previous_frame[4] = pv->ref[0][k][forward_2 + x];
655                         next_frame[0]     = pv->ref[2][k][back_2    + x];
656                         next_frame[1]     = pv->ref[2][k][back_1    + x];
657                         next_frame[2]     = pv->ref[2][k][current   + x];
658                         next_frame[3]     = pv->ref[2][k][forward_1 + x];
659                         next_frame[4]     = pv->ref[2][k][forward_2 + x];
660                         
661                         if( abs( previous_frame[2] - current_frame[2] ) > mthresh &&
662                             abs(  current_frame[1] - next_frame[1]    ) > mthresh &&
663                             abs(  current_frame[3] - next_frame[3]    ) > mthresh )
664                                 motion++;
665                         if( abs(     next_frame[2] - current_frame[2] ) > mthresh &&
666                             abs( previous_frame[1] - current_frame[1] ) > mthresh &&
667                             abs( previous_frame[3] - current_frame[3] ) > mthresh )
668                                 motion++;
669                     }
670                     else
671                     {
672                         /* User doesn't want to check for motion,
673                            so move on to the spatial check.       */
674                         motion = 1;
675                     }
676                            
677                     if( motion || ( pv->deinterlaced_frames==0 && pv->blended_frames==0 && pv->unfiltered_frames==0) )
678                     {
679                            /* That means it's time for the spatial check.
680                               We've got several options here.             */
681                         if( spatial_metric == 0 )
682                         {
683                             /* Simple 32detect style comb detection */
684                             if( ( abs( current_frame[2] - current_frame[4] ) < 10  ) &&
685                                 ( abs( current_frame[2] - current_frame[3] ) > 15 ) )
686                             {
687                                 pv->mask[k][y*ref_stride + x] = 255;
688                             }
689                             else
690                             {
691                                 pv->mask[k][y*ref_stride + x] = 0;
692                             }
693                         }
694                         else if( spatial_metric == 1 )
695                         {
696                             /* This, for comparison, is what IsCombed uses.
697                                It's better, but still noise senstive.      */
698                                int combing = ( current_frame[1] - current_frame[2] ) *
699                                              ( current_frame[3] - current_frame[2] );
700                                
701                                if( combing > athresh_squared )
702                                    pv->mask[k][y*ref_stride + x] = 255; 
703                                else
704                                    pv->mask[k][y*ref_stride + x] = 0;
705                         }
706                         else if( spatial_metric == 2 )
707                         {
708                             /* Tritical's noise-resistant combing scorer.
709                                The check is done on a bob+blur convolution. */
710                             int combing = abs( current_frame[0]
711                                              + ( 4 * current_frame[2] )
712                                              + current_frame[4]
713                                              - ( 3 * ( current_frame[1]
714                                                      + current_frame[3] ) ) );
715
716                             /* If the frame is sufficiently combed,
717                                then mark it down on the mask as 255. */
718                             if( combing > athresh6 )
719                                 pv->mask[k][y*ref_stride + x] = 255; 
720                             else
721                                 pv->mask[k][y*ref_stride + x] = 0;
722                         }
723                     }
724                     else
725                     {
726                         pv->mask[k][y*ref_stride + x] = 0;
727                     }
728                 }
729                 else
730                 {
731                     pv->mask[k][y*ref_stride + x] = 0;
732                 }
733             }
734         }
735     }
736 }
737
738 // This function calls all the eedi2 filters in sequence for a given plane.
739 // It outputs the final interpolated image to pv->eedi_full[DST2PF].
740 void eedi2_interpolate_plane( hb_filter_private_t * pv, int k )
741 {
742     /* We need all these pointers. No, seriously.
743        I swear. It's not a joke. They're used.
744        All nine of them.                         */
745     uint8_t * mskp = pv->eedi_half[MSKPF][k];
746     uint8_t * srcp = pv->eedi_half[SRCPF][k];
747     uint8_t * tmpp = pv->eedi_half[TMPPF][k];
748     uint8_t * dstp = pv->eedi_half[DSTPF][k];
749     uint8_t * dst2p = pv->eedi_full[DST2PF][k];
750     uint8_t * tmp2p2 = pv->eedi_full[TMP2PF2][k];
751     uint8_t * msk2p = pv->eedi_full[MSK2PF][k];
752     uint8_t * tmp2p = pv->eedi_full[TMP2PF][k];
753     uint8_t * dst2mp = pv->eedi_full[DST2MPF][k];
754     int * cx2 = pv->cx2;
755     int * cy2 = pv->cy2;
756     int * cxy = pv->cxy;
757     int * tmpc = pv->tmpc;
758
759     int pitch = pv->ref_stride[k];
760     int height = pv->height[k]; int width = pv->width[k];
761     int half_height = height / 2;
762
763     // edge mask
764     eedi2_build_edge_mask( mskp, pitch, srcp, pitch,
765                      pv->magnitude_threshold, pv->variance_threshold, pv->laplacian_threshold, 
766                      half_height, width );
767     eedi2_erode_edge_mask( mskp, pitch, tmpp, pitch, pv->erosion_threshold, half_height, width );
768     eedi2_dilate_edge_mask( tmpp, pitch, mskp, pitch, pv->dilation_threshold, half_height, width );
769     eedi2_erode_edge_mask( mskp, pitch, tmpp, pitch, pv->erosion_threshold, half_height, width );
770     eedi2_remove_small_gaps( tmpp, pitch, mskp, pitch, half_height, width );
771
772     // direction mask
773     eedi2_calc_directions( k, mskp, pitch, srcp, pitch, tmpp, pitch,
774                      pv->maximum_search_distance, pv->noise_threshold,
775                      half_height, width );
776     eedi2_filter_dir_map( mskp, pitch, tmpp, pitch, dstp, pitch, half_height, width );
777     eedi2_expand_dir_map( mskp, pitch, dstp, pitch, tmpp, pitch, half_height, width );
778     eedi2_filter_map( mskp, pitch, tmpp, pitch, dstp, pitch, half_height, width );
779
780     // upscale 2x vertically
781     eedi2_upscale_by_2( srcp, dst2p, half_height, pitch );
782     eedi2_upscale_by_2( dstp, tmp2p2, half_height, pitch );
783     eedi2_upscale_by_2( mskp, msk2p, half_height, pitch );
784
785     // upscale the direction mask
786     eedi2_mark_directions_2x( msk2p, pitch, tmp2p2, pitch, tmp2p, pitch, pv->tff, height, width );
787     eedi2_filter_dir_map_2x( msk2p, pitch, tmp2p, pitch,  dst2mp, pitch, pv->tff, height, width );
788     eedi2_expand_dir_map_2x( msk2p, pitch, dst2mp, pitch, tmp2p, pitch, pv->tff, height, width );
789     eedi2_fill_gaps_2x( msk2p, pitch, tmp2p, pitch, dst2mp, pitch, pv->tff, height, width );
790     eedi2_fill_gaps_2x( msk2p, pitch, dst2mp, pitch, tmp2p, pitch, pv->tff, height, width );
791
792     // interpolate a full-size plane
793     eedi2_interpolate_lattice( k, tmp2p, pitch, dst2p, pitch, tmp2p2, pitch, pv->tff,
794                          pv->noise_threshold, height, width );
795
796     if( pv->post_processing == 1 || pv->post_processing == 3 )
797     {
798         // make sure the edge directions are consistent
799         eedi2_bit_blit( tmp2p2, pitch, tmp2p, pitch, pv->width[k], pv->height[k] );
800         eedi2_filter_dir_map_2x( msk2p, pitch, tmp2p, pitch, dst2mp, pitch, pv->tff, height, width );
801         eedi2_expand_dir_map_2x( msk2p, pitch, dst2mp, pitch, tmp2p, pitch, pv->tff, height, width );
802         eedi2_post_process( tmp2p, pitch, tmp2p2, pitch, dst2p, pitch, pv->tff, height, width );
803     }
804     if( pv->post_processing == 2 || pv->post_processing == 3 )
805     {
806         // filter junctions and corners
807         eedi2_gaussian_blur1( srcp, pitch, tmpp, pitch, srcp, pitch, half_height, width );
808         eedi2_calc_derivatives( srcp, pitch, half_height, width, cx2, cy2, cxy );
809         eedi2_gaussian_blur_sqrt2( cx2, tmpc, cx2, pitch, half_height, width);
810         eedi2_gaussian_blur_sqrt2( cy2, tmpc, cy2, pitch, half_height, width);
811         eedi2_gaussian_blur_sqrt2( cxy, tmpc, cxy, pitch, half_height, width);
812         eedi2_post_process_corner( cx2, cy2, cxy, pitch, tmp2p2, pitch, dst2p, pitch, height, width, pv->tff );
813     }
814 }
815
816 /*
817  *  eedi2 interpolate this plane in a single thread.
818  */
819 void eedi2_filter_thread( void *thread_args_v )
820 {
821     eedi2_arguments_t *eedi2_work = NULL;
822     hb_filter_private_t * pv;
823     int run = 1;
824     int plane;
825     eedi2_thread_arg_t *thread_args = thread_args_v;
826
827     pv = thread_args->pv;
828     plane = thread_args->plane;
829
830     hb_log("eedi2 thread started for plane %d", plane);
831
832     while( run )
833     {
834         /*
835          * Wait here until there is work to do. hb_lock() blocks until
836          * render releases it to say that there is more work to do.
837          */
838         hb_lock( pv->eedi2_begin_lock[plane] );
839
840         eedi2_work = &pv->eedi2_arguments[plane];
841
842         if( eedi2_work->stop )
843         {
844             /*
845              * No more work to do, exit this thread.
846              */
847             run = 0;
848             continue;
849         } 
850
851         /*
852          * Process plane
853          */
854             eedi2_interpolate_plane( pv, plane );
855         
856         /*
857          * Finished this segment, let everyone know.
858          */
859         hb_unlock( pv->eedi2_complete_lock[plane] );
860     }
861     free( thread_args_v );
862 }
863
864 // Sets up the input field planes for EEDI2 in pv->eedi_half[SRCPF]
865 // and then runs eedi2_filter_thread for each plane.
866 void eedi2_planer( hb_filter_private_t * pv )
867 {
868     /* Copy the first field from the source to a half-height frame. */
869     int i;
870     for( i = 0;  i < 3; i++ )
871     {
872         int pitch = pv->ref_stride[i];
873         int start_line = !pv->tff;
874         eedi2_fill_half_height_buffer_plane( &pv->ref[1][i][pitch*start_line], pv->eedi_half[SRCPF][i], pitch, pv->height[i] );
875     }
876     
877     int plane;
878     for( plane = 0; plane < 3; plane++ )
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->eedi2_complete_lock[plane] );
887         hb_unlock( pv->eedi2_begin_lock[plane] );
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( plane = 0; plane < 3; plane++ )
897     {
898         hb_lock( pv->eedi2_complete_lock[plane] );
899         hb_unlock( pv->eedi2_complete_lock[plane] );
900     }
901 }
902
903
904 /*
905  * comb detect this segment of all three planes in a single thread.
906  */
907 void decomb_filter_thread( void *thread_args_v )
908 {
909     decomb_arguments_t *decomb_work = NULL;
910     hb_filter_private_t * pv;
911     int run = 1;
912     int segment, segment_start, segment_stop, plane;
913     decomb_thread_arg_t *thread_args = thread_args_v;
914
915     pv = thread_args->pv;
916     segment = thread_args->segment;
917
918     hb_log("decomb thread started for segment %d", segment);
919
920     while( run )
921     {
922         /*
923          * Wait here until there is work to do. hb_lock() blocks until
924          * render releases it to say that there is more work to do.
925          */
926         hb_lock( pv->decomb_begin_lock[segment] );
927
928         decomb_work = &pv->decomb_arguments[segment];
929
930         if( decomb_work->stop )
931         {
932             /*
933              * No more work to do, exit this thread.
934              */
935             run = 0;
936             continue;
937         } 
938
939         /*
940          * Process segment (for now just from luma)
941          */
942         for( plane = 0; plane < 1; plane++)
943         {
944
945             int h = pv->height[plane];
946             segment_start = ( h / pv->cpu_count ) * segment;
947             if( segment == pv->cpu_count - 1 )
948             {
949                 /*
950                  * Final segment
951                  */
952                 segment_stop = h;
953             } else {
954                 segment_stop = ( h / pv->cpu_count ) * ( segment + 1 );
955             }
956             
957             detect_combed_segment( pv, segment_start, segment_stop );
958         }
959         /*
960          * Finished this segment, let everyone know.
961          */
962         hb_unlock( pv->decomb_complete_lock[segment] );
963     }
964     free( thread_args_v );
965 }
966
967 int comb_segmenter( hb_filter_private_t * pv )
968 {
969     int segment;
970
971     for( segment = 0; segment < pv->cpu_count; segment++ )
972     {  
973         /*
974          * Let the thread for this plane know that we've setup work 
975          * for it by releasing the begin lock (ensuring that the
976          * complete lock is already locked so that we block when
977          * we try to lock it again below).
978          */
979         hb_lock( pv->decomb_complete_lock[segment] );
980         hb_unlock( pv->decomb_begin_lock[segment] );
981     }
982
983     /*
984      * Wait until all three threads have completed by trying to get
985      * the complete lock that we locked earlier for each thread, which
986      * will block until that thread has completed the work on that
987      * plane.
988      */
989     for( segment = 0; segment < pv->cpu_count; segment++ )
990     {
991         hb_lock( pv->decomb_complete_lock[segment] );
992         hb_unlock( pv->decomb_complete_lock[segment] );
993     }
994     
995     return check_combing_mask( pv );
996 }
997
998 static void yadif_filter_line( uint8_t *dst,
999                                uint8_t *prev,
1000                                uint8_t *cur,
1001                                uint8_t *next,
1002                                int plane,
1003                                int parity,
1004                                int y,
1005                                hb_filter_private_t * pv )
1006 {
1007     /* While prev and next point to the previous and next frames,
1008        prev2 and next2 will shift depending on the parity, usually 1.
1009        They are the previous and next fields, the fields temporally adjacent
1010        to the other field in the current frame--the one not being filtered.  */
1011     uint8_t *prev2 = parity ? prev : cur ;
1012     uint8_t *next2 = parity ? cur  : next;
1013     
1014     int w = pv->width[plane];
1015     int refs = pv->ref_stride[plane];
1016     int x;
1017     int eedi2_mode = ( pv->mode & MODE_EEDI2 );
1018     
1019     /* We can replace spatial_pred with this interpolation*/
1020     uint8_t * eedi2_guess = &pv->eedi_full[DST2PF][plane][y*refs];
1021
1022     /* Decomb's cubic interpolation can only function when there are
1023        three samples above and below, so regress to yadif's traditional
1024        two-tap interpolation when filtering at the top and bottom edges. */
1025     int vertical_edge = 0;
1026     if( ( y < 3 ) || ( y > ( pv->height[plane] - 4 ) )  )
1027         vertical_edge = 1;
1028
1029     for( x = 0; x < w; x++)
1030     {
1031         /* Pixel above*/
1032         int c              = cur[-refs];
1033         /* Temporal average: the current location in the adjacent fields */
1034         int d              = (prev2[0] + next2[0])>>1;
1035         /* Pixel below */
1036         int e              = cur[+refs];
1037         
1038         /* How the current pixel changes between the adjacent fields */
1039         int temporal_diff0 = ABS(prev2[0] - next2[0]);
1040         /* The average of how much the pixels above and below change from the frame before to now. */
1041         int temporal_diff1 = ( ABS(prev[-refs] - cur[-refs]) + ABS(prev[+refs] - cur[+refs]) ) >> 1;
1042         /* The average of how much the pixels above and below change from now to the next frame. */
1043         int temporal_diff2 = ( ABS(next[-refs] - cur[-refs]) + ABS(next[+refs] - cur[+refs]) ) >> 1;
1044         /* For the actual difference, use the largest of the previous average diffs. */
1045         int diff           = MAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2);
1046
1047         int spatial_pred;
1048         
1049         if( eedi2_mode )
1050         {
1051             /* Who needs yadif's spatial predictions when we can have EEDI2's? */
1052             spatial_pred = eedi2_guess[0];
1053             eedi2_guess++;
1054         }
1055         else // Yadif spatial interpolation
1056         {
1057             /* SAD of how the pixel-1, the pixel, and the pixel+1 change from the line above to below. */ 
1058             int spatial_score  = ABS(cur[-refs-1] - cur[+refs-1]) + ABS(cur[-refs]-cur[+refs]) +
1059                                          ABS(cur[-refs+1] - cur[+refs+1]) - 1;         
1060             
1061             /* Spatial pred is either a bilinear or cubic vertical interpolation. */
1062             if( ( pv->mode & MODE_CUBIC ) && !vertical_edge)
1063             {
1064                 spatial_pred = cubic_interpolate_pixel( cur[-3*refs], cur[-refs], cur[+refs], cur[3*refs] );
1065             }
1066             else
1067             {
1068                 spatial_pred = (c+e)>>1;
1069             }
1070
1071         /* EDDI: Edge Directed Deinterlacing Interpolation
1072            Checks 4 different slopes to see if there is more similarity along a diagonal
1073            than there was vertically. If a diagonal is more similar, then it indicates
1074            an edge, so interpolate along that instead of a vertical line, using either
1075            linear or cubic interpolation depending on mode. */
1076         #define YADIF_CHECK(j)\
1077                 {   int score = ABS(cur[-refs-1+j] - cur[+refs-1-j])\
1078                               + ABS(cur[-refs  +j] - cur[+refs  -j])\
1079                               + ABS(cur[-refs+1+j] - cur[+refs+1-j]);\
1080                     if( score < spatial_score ){\
1081                         spatial_score = score;\
1082                         if( ( pv->mode & MODE_CUBIC ) && !vertical_edge )\
1083                         {\
1084                             switch(j)\
1085                             {\
1086                                 case -1:\
1087                                     spatial_pred = cubic_interpolate_pixel(cur[-3 * refs - 3], cur[-refs -1], cur[+refs + 1], cur[3* refs + 3] );\
1088                                 break;\
1089                                 case -2:\
1090                                     spatial_pred = cubic_interpolate_pixel( ( ( cur[-3*refs - 4] + cur[-refs - 4] ) / 2 ) , cur[-refs -2], cur[+refs + 2], ( ( cur[3*refs + 4] + cur[refs + 4] ) / 2 ) );\
1091                                 break;\
1092                                 case 1:\
1093                                     spatial_pred = cubic_interpolate_pixel(cur[-3 * refs +3], cur[-refs +1], cur[+refs - 1], cur[3* refs -3] );\
1094                                 break;\
1095                                 case 2:\
1096                                     spatial_pred = cubic_interpolate_pixel(( ( cur[-3*refs + 4] + cur[-refs + 4] ) / 2 ), cur[-refs +2], cur[+refs - 2], ( ( cur[3*refs - 4] + cur[refs - 4] ) / 2 ) );\
1097                                 break;\
1098                             }\
1099                         }\
1100                         else\
1101                         {\
1102                             spatial_pred = ( cur[-refs +j] + cur[+refs -j] ) >>1;\
1103                         }\
1104
1105                         if( x >= 2 && x <= w - 3 )
1106                         {
1107                             YADIF_CHECK(-1)
1108                             if( x >= 3 && x <= w - 4 )
1109                             {
1110                                 YADIF_CHECK(-2) }} }}
1111                             }
1112                         }
1113                         if( x >= 2 && x <= w - 3 )
1114                         {
1115                             YADIF_CHECK(1)
1116                             if( x >= 3 && x <= w - 4 )
1117                             {
1118                                 YADIF_CHECK(2) }} }}
1119                             }
1120                         }
1121         }
1122
1123         /* Temporally adjust the spatial prediction by
1124            comparing against lines in the adjacent fields. */
1125         int b = (prev2[-2*refs] + next2[-2*refs])>>1;
1126         int f = (prev2[+2*refs] + next2[+2*refs])>>1;
1127         
1128         /* Find the median value */
1129         int max = MAX3(d-e, d-c, MIN(b-c, f-e));
1130         int min = MIN3(d-e, d-c, MAX(b-c, f-e));
1131         diff = MAX3( diff, min, -max );
1132         
1133         if( spatial_pred > d + diff )
1134         {
1135             spatial_pred = d + diff;
1136         }
1137         else if( spatial_pred < d - diff )
1138         {
1139             spatial_pred = d - diff;
1140         }
1141         
1142         dst[0] = spatial_pred;
1143                         
1144         dst++;
1145         cur++;
1146         prev++;
1147         next++;
1148         prev2++;
1149         next2++;
1150     }
1151 }
1152
1153 /*
1154  * deinterlace this segment of all three planes in a single thread.
1155  */
1156 void yadif_decomb_filter_thread( void *thread_args_v )
1157 {
1158     yadif_arguments_t *yadif_work = NULL;
1159     hb_filter_private_t * pv;
1160     int run = 1;
1161     int plane;
1162     int segment, segment_start, segment_stop;
1163     yadif_thread_arg_t *thread_args = thread_args_v;
1164     uint8_t **dst;
1165     int parity, tff, y, w, h, penultimate, ultimate, ref_stride, is_combed;
1166
1167     pv = thread_args->pv;
1168     segment = thread_args->segment;
1169
1170     hb_log("yadif thread started for segment %d", segment);
1171
1172     while( run )
1173     {
1174         /*
1175          * Wait here until there is work to do. hb_lock() blocks until
1176          * render releases it to say that there is more work to do.
1177          */
1178         hb_lock( pv->yadif_begin_lock[segment] );
1179
1180         yadif_work = &pv->yadif_arguments[segment];
1181
1182         if( yadif_work->stop )
1183         {
1184             /*
1185              * No more work to do, exit this thread.
1186              */
1187             run = 0;
1188             continue;
1189         } 
1190
1191         if( yadif_work->dst == NULL )
1192         {
1193             hb_error( "thread started when no work available" );
1194             hb_snooze(500);
1195             continue;
1196         }
1197         
1198         is_combed = pv->yadif_arguments[segment].is_combed;
1199
1200         /*
1201          * Process all three planes, but only this segment of it.
1202          */
1203         for( plane = 0; plane < 3; plane++)
1204         {
1205
1206             dst = yadif_work->dst;
1207             parity = yadif_work->parity;
1208             tff = yadif_work->tff;
1209             w = pv->width[plane];
1210             h = pv->height[plane];
1211             penultimate = h - 2;
1212             ultimate = h - 1;
1213             ref_stride = pv->ref_stride[plane];
1214             segment_start = ( h / pv->cpu_count ) * segment;
1215             if( segment == pv->cpu_count - 1 )
1216             {
1217                 /*
1218                  * Final segment
1219                  */
1220                 segment_stop = h;
1221             } else {
1222                 segment_stop = ( h / pv->cpu_count ) * ( segment + 1 );
1223             }
1224
1225             for( y = segment_start; y < segment_stop; y++ )
1226             {
1227                 if( is_combed == 2 )
1228                 {
1229                     /* This line gets blend filtered, not yadif filtered. */
1230                     uint8_t *cur  = &pv->ref[1][plane][y*ref_stride];
1231                     uint8_t *dst2 = &dst[plane][y*w];
1232                     /* These will be useful if we ever do temporal blending. */
1233                     // uint8_t *prev = &pv->ref[0][plane][y*ref_stride];
1234                     // uint8_t *next = &pv->ref[2][plane][y*ref_stride];
1235
1236                     blend_filter_line( dst2, cur, plane, y, pv );
1237                 }
1238                 else if( pv->mode == MODE_CUBIC && is_combed && ( ( y ^ parity ) & 1 ) )
1239                 {
1240                     /* Just apply vertical cubic interpolation */
1241                     uint8_t *cur  = &pv->ref[1][plane][y*ref_stride];
1242                     uint8_t *dst2 = &dst[plane][y*w];
1243                     
1244                     cubic_interpolate_line( dst2, cur, plane, y, pv );
1245                 }
1246                 else if( pv->mode & MODE_YADIF && ( ( y ^ parity ) &  1 )  && ( is_combed == 1 ) )
1247                 {
1248                     /* This line gets yadif filtered. It is the bottom field
1249                        when TFF and vice-versa. It's the field that gets
1250                        filtered. Because yadif needs 2 lines above and below
1251                        the one being filtered, we need to mirror the edges.
1252                        When TFF, this means replacing the 2nd line with a
1253                        copy of the 1st, and the last with the second-to-last. */
1254                     if( y > 1 && y < ( h -2 ) )
1255                     {
1256                         /* This isn't the top or bottom, proceed as normal to yadif. */
1257                         uint8_t *prev = &pv->ref[0][plane][y*ref_stride];
1258                         uint8_t *cur  = &pv->ref[1][plane][y*ref_stride];
1259                         uint8_t *next = &pv->ref[2][plane][y*ref_stride];
1260                         uint8_t *dst2 = &dst[plane][y*w];
1261
1262                         yadif_filter_line( dst2, 
1263                                            prev, 
1264                                            cur, 
1265                                            next, 
1266                                            plane, 
1267                                            parity ^ tff,
1268                                            y, 
1269                                            pv );
1270                     }
1271                     else if( y == 0 )
1272                     {
1273                         /* BFF, so y0 = y1 */
1274                         memcpy( &dst[plane][y*w],
1275                                 &pv->ref[1][plane][1*ref_stride],
1276                                 w * sizeof(uint8_t) );
1277                     }
1278                     else if( y == 1 )
1279                     {
1280                         /* TFF, so y1 = y0 */
1281                         memcpy( &dst[plane][y*w],
1282                                 &pv->ref[1][plane][0],
1283                                 w * sizeof(uint8_t) );
1284                     }
1285                     else if( y == penultimate )
1286                     {
1287                         /* BFF, so penultimate y = ultimate y */
1288                         memcpy( &dst[plane][y*w],
1289                                 &pv->ref[1][plane][ultimate*ref_stride],
1290                                 w * sizeof(uint8_t) );
1291                     }
1292                     else if( y == ultimate )
1293                     {
1294                         /* TFF, so ultimate y = penultimate y */
1295                         memcpy( &dst[plane][y*w],
1296                                 &pv->ref[1][plane][penultimate*ref_stride],
1297                                 w * sizeof(uint8_t) );
1298                     }
1299                 }
1300                 else
1301                 {
1302                     memcpy( &dst[plane][y*w],
1303                             &pv->ref[1][plane][y*ref_stride],
1304                             w * sizeof(uint8_t) );              
1305                 }
1306             }
1307         }
1308         /*
1309          * Finished this segment, let everyone know.
1310          */
1311         hb_unlock( pv->yadif_complete_lock[segment] );
1312     }
1313     free( thread_args_v );
1314 }
1315
1316 static void yadif_filter( uint8_t ** dst,
1317                           int parity,
1318                           int tff,
1319                           hb_filter_private_t * pv )
1320 {
1321     /* If we're running comb detection, do it now, otherwise default to true. */
1322     int is_combed = pv->spatial_metric >= 0 ? comb_segmenter( pv ) : 1;
1323     
1324     /* The comb detector suggests three different values:
1325        0: Don't comb this frame.
1326        1: Deinterlace this frame.
1327        2: Blend this frame.
1328        Since that might conflict with the filter's mode,
1329        it may be necesary to adjust this value.          */
1330     if( is_combed == 1 && (pv->mode == MODE_BLEND) )
1331     {
1332         /* All combed frames are getting blended */
1333         is_combed = 2;
1334     }
1335     else if( is_combed == 2 && !( pv->mode & MODE_BLEND ) )
1336     {
1337         /* Blending is disabled, so force interpolation of these frames. */
1338         is_combed = 1;
1339     }
1340     if( is_combed == 1 &&
1341         ( pv->mode & MODE_BLEND ) &&
1342         !( pv->mode & ( MODE_YADIF | MODE_EEDI2 | MODE_CUBIC ) ) )
1343     {
1344         /* Deinterlacers are disabled, blending isn't, so blend these frames. */
1345         is_combed = 2;
1346     }
1347     else if( is_combed &&
1348              !( pv->mode & ( MODE_BLEND | MODE_YADIF | MODE_EEDI2 | MODE_CUBIC | MODE_MASK ) ) )
1349     {
1350         /* No deinterlacer or mask chosen, pass the frame through. */
1351         is_combed = 0;
1352     }
1353     
1354     if( is_combed == 1 )
1355     {
1356         pv->deinterlaced_frames++;
1357     }
1358     else if( is_combed == 2 )
1359     {
1360         pv->blended_frames++;
1361     }
1362     else
1363     {
1364         pv->unfiltered_frames++;
1365     }
1366     
1367     if( is_combed == 1 && ( pv->mode & MODE_EEDI2 ) )
1368     {
1369         /* Generate an EEDI2 interpolation */
1370         eedi2_planer( pv );
1371     }
1372     
1373     if( is_combed )
1374     {
1375         if( ( pv->mode & MODE_EEDI2 ) && !( pv->mode & MODE_YADIF ) && is_combed == 1 )
1376         {
1377             // Just pass through the EEDI2 interpolation
1378             int i;
1379             for( i = 0; i < 3; i++ )
1380             {
1381                 uint8_t * ref = pv->eedi_full[DST2PF][i];
1382                 uint8_t * dest = dst[i];
1383
1384                 int w = pv->width[i];
1385                 int ref_stride = pv->ref_stride[i];
1386
1387                 int y;
1388                 for( y = 0; y < pv->height[i]; y++ )
1389                 {
1390                     memcpy(dest, ref, w);
1391                     dest += w;
1392                     ref += ref_stride;
1393                 }
1394             }
1395         }
1396         else
1397         {
1398             int segment;
1399
1400             for( segment = 0; segment < pv->cpu_count; segment++ )
1401             {  
1402                 /*
1403                  * Setup the work for this plane.
1404                  */
1405                 pv->yadif_arguments[segment].parity = parity;
1406                 pv->yadif_arguments[segment].tff = tff;
1407                 pv->yadif_arguments[segment].dst = dst;
1408                 pv->yadif_arguments[segment].is_combed = is_combed;
1409
1410                 /*
1411                  * Let the thread for this plane know that we've setup work 
1412                  * for it by releasing the begin lock (ensuring that the
1413                  * complete lock is already locked so that we block when
1414                  * we try to lock it again below).
1415                  */
1416                 hb_lock( pv->yadif_complete_lock[segment] );
1417                 hb_unlock( pv->yadif_begin_lock[segment] );
1418             }
1419
1420             /*
1421              * Wait until all three threads have completed by trying to get
1422              * the complete lock that we locked earlier for each thread, which
1423              * will block until that thread has completed the work on that
1424              * plane.
1425              */
1426             for( segment = 0; segment < pv->cpu_count; segment++ )
1427             {
1428                 hb_lock( pv->yadif_complete_lock[segment] );
1429                 hb_unlock( pv->yadif_complete_lock[segment] );
1430             }
1431
1432             /*
1433              * Entire frame is now deinterlaced.
1434              */
1435         }
1436     }
1437     else
1438     {
1439         /*  Just passing through... */
1440         
1441         /* For mcdeint's benefit... */
1442         pv->yadif_arguments[0].is_combed = is_combed; // 0
1443         
1444         int i;
1445         for( i = 0; i < 3; i++ )
1446         {
1447             uint8_t * ref = pv->ref[1][i];
1448             uint8_t * dest = dst[i];
1449             
1450             int w = pv->width[i];
1451             int ref_stride = pv->ref_stride[i];
1452             
1453             int y;
1454             for( y = 0; y < pv->height[i]; y++ )
1455             {
1456                 memcpy(dest, ref, w);
1457                 dest += w;
1458                 ref += ref_stride;
1459             }
1460         }
1461     }
1462     
1463     if( pv->mode & MODE_MASK && pv->spatial_metric >= 0 )
1464     {
1465         if( pv->mode == MODE_MASK || is_combed )
1466         apply_mask( pv );
1467     }
1468 }
1469
1470 static void mcdeint_filter( uint8_t ** dst,
1471                             uint8_t ** src,
1472                             int parity,
1473                             hb_filter_private_t * pv )
1474 {
1475     int x, y, i;
1476     int out_size;
1477
1478 #ifdef SUPPRESS_AV_LOG
1479     /* TODO: temporarily change log level to suppress obnoxious debug output */
1480     int loglevel = av_log_get_level();
1481     av_log_set_level( AV_LOG_QUIET );
1482 #endif
1483
1484     for( i=0; i<3; i++ )
1485     {
1486         pv->mcdeint_frame->data[i] = src[i];
1487         pv->mcdeint_frame->linesize[i] = pv->width[i];
1488     }
1489     pv->mcdeint_avctx_enc->me_cmp     = FF_CMP_SAD;
1490     pv->mcdeint_avctx_enc->me_sub_cmp = FF_CMP_SAD;
1491     pv->mcdeint_frame->quality        = pv->mcdeint_qp * FF_QP2LAMBDA;
1492
1493     out_size = avcodec_encode_video( pv->mcdeint_avctx_enc,
1494                                      pv->mcdeint_outbuf,
1495                                      pv->mcdeint_outbuf_size,
1496                                      pv->mcdeint_frame );
1497
1498     pv->mcdeint_frame_dec = pv->mcdeint_avctx_enc->coded_frame;
1499
1500     for( i = 0; i < 3; i++ )
1501     {
1502         int w    = pv->width[i];
1503         int h    = pv->height[i];
1504         int fils = pv->mcdeint_frame_dec->linesize[i];
1505         int srcs = pv->width[i];
1506
1507         for( y = 0; y < h; y++ )
1508         {
1509             if( (y ^ parity) & 1 )
1510             {
1511                 for( x = 0; x < w; x++ )
1512                 {
1513                     if( (x-1)+(y-1)*w >= 0 && (x+1)+(y+1)*w < w*h )
1514                     {
1515                         uint8_t * filp =
1516                             &pv->mcdeint_frame_dec->data[i][x + y*fils];
1517                         uint8_t * srcp = &src[i][x + y*srcs];
1518
1519                         int diff0 = filp[-fils] - srcp[-srcs];
1520                         int diff1 = filp[+fils] - srcp[+srcs];
1521                         int spatial_score;
1522                         
1523                         spatial_score =
1524                             ABS(srcp[-srcs-1] - srcp[+srcs-1]) +
1525                             ABS(srcp[-srcs  ] - srcp[+srcs  ]) +
1526                             ABS(srcp[-srcs+1] - srcp[+srcs+1]) - 1;
1527
1528                         int temp = filp[0];
1529
1530 #define MCDEINT_CHECK(j)\
1531                         {   int score = ABS(srcp[-srcs-1+j] - srcp[+srcs-1-j])\
1532                                       + ABS(srcp[-srcs  +j] - srcp[+srcs  -j])\
1533                                       + ABS(srcp[-srcs+1+j] - srcp[+srcs+1-j]);\
1534                             if( score < spatial_score ) {\
1535                                 spatial_score = score;\
1536                                 diff0 = filp[-fils+j] - srcp[-srcs+j];\
1537                                 diff1 = filp[+fils-j] - srcp[+srcs-j];
1538
1539                         if( x >= 2 && x <= w - 3 )
1540                         {
1541                             MCDEINT_CHECK(-1)
1542                             if( x >= 3 && x <= w - 4 )
1543                             {
1544                                 MCDEINT_CHECK(-2) }} }}
1545                             }
1546                         }
1547                         if( x >= 2 && x <= w - 3 )
1548                         {
1549                             MCDEINT_CHECK(1)
1550                             if( x >= 3 && x <= w - 4 )
1551                             {
1552                                 MCDEINT_CHECK(2) }} }}
1553                             }
1554                         }
1555
1556                         if(diff0 + diff1 > 0)
1557                         {
1558                             temp -= (diff0 + diff1 -
1559                                      ABS( ABS(diff0) - ABS(diff1) ) / 2) / 2;
1560                         }
1561                         else
1562                         {
1563                             temp -= (diff0 + diff1 +
1564                                      ABS( ABS(diff0) - ABS(diff1) ) / 2) / 2;
1565                         }
1566
1567                         filp[0] = dst[i][x + y*w] =
1568                             temp > 255U ? ~(temp>>31) : temp;
1569                     }
1570                     else
1571                     {
1572                         dst[i][x + y*w] =
1573                             pv->mcdeint_frame_dec->data[i][x + y*fils];
1574                     }
1575                 }
1576             }
1577             else
1578             {
1579                 for( x = 0; x < w; x++ )
1580                 {
1581                     pv->mcdeint_frame_dec->data[i][x + y*fils] =
1582                         dst[i][x + y*w]= src[i][x + y*srcs];
1583                 }
1584             }
1585         }
1586     }
1587
1588 #ifdef SUPPRESS_AV_LOG
1589     /* TODO: restore previous log level */
1590     av_log_set_level(loglevel);
1591 #endif
1592 }
1593
1594 hb_filter_private_t * hb_decomb_init( int pix_fmt,
1595                                            int width,
1596                                            int height,
1597                                            char * settings )
1598 {
1599     if( pix_fmt != PIX_FMT_YUV420P )
1600     {
1601         return 0;
1602     }
1603
1604     hb_filter_private_t * pv = calloc( 1, sizeof(struct hb_filter_private_s) );
1605
1606     pv->pix_fmt = pix_fmt;
1607
1608     pv->width[0]  = width;
1609     pv->height[0] = height;
1610     pv->width[1]  = pv->width[2]  = width >> 1;
1611     pv->height[1] = pv->height[2] = height >> 1;
1612
1613     pv->buf_out[0] = hb_video_buffer_init( width, height );
1614     pv->buf_out[1] = hb_video_buffer_init( width, height );
1615     pv->buf_settings = hb_buffer_init( 0 );
1616
1617     pv->deinterlaced_frames = 0;
1618     pv->blended_frames = 0;
1619     pv->unfiltered_frames = 0;
1620
1621     pv->yadif_ready    = 0;
1622
1623     pv->mode     = MODE_YADIF | MODE_BLEND | MODE_CUBIC;
1624     pv->spatial_metric = 2;
1625     pv->motion_threshold = 6;
1626     pv->spatial_threshold = 9;
1627     pv->block_threshold = 80;
1628     pv->block_width = 16;
1629     pv->block_height = 16;
1630     
1631     pv->magnitude_threshold = 10;
1632     pv->variance_threshold = 20;
1633     pv->laplacian_threshold = 20;
1634     pv->dilation_threshold = 4;
1635     pv->erosion_threshold = 2;
1636     pv->noise_threshold = 50;
1637     pv->maximum_search_distance = 24;
1638     pv->post_processing = 1;
1639
1640     pv->parity   = PARITY_DEFAULT;
1641
1642     pv->mcdeint_mode   = MCDEINT_MODE_DEFAULT;
1643     pv->mcdeint_qp     = MCDEINT_QP_DEFAULT;
1644
1645     if( settings )
1646     {
1647         sscanf( settings, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
1648                 &pv->mode,
1649                 &pv->spatial_metric,
1650                 &pv->motion_threshold,
1651                 &pv->spatial_threshold,
1652                 &pv->block_threshold,
1653                 &pv->block_width,
1654                 &pv->block_height,
1655                 &pv->magnitude_threshold,
1656                 &pv->variance_threshold,
1657                 &pv->laplacian_threshold,
1658                 &pv->dilation_threshold,
1659                 &pv->erosion_threshold,
1660                 &pv->noise_threshold,
1661                 &pv->maximum_search_distance,
1662                 &pv->post_processing,
1663                 &pv->parity );
1664     }
1665     
1666     pv->cpu_count = hb_get_cpu_count();
1667     
1668
1669     if( pv->mode & MODE_MCDEINT )
1670     {
1671         pv->mcdeint_mode = 2;
1672     }
1673     
1674     /* Allocate yadif specific buffers */
1675     int i, j;
1676     for( i = 0; i < 3; i++ )
1677     {
1678         int is_chroma = !!i;
1679         int w = ((width   + 31) & (~31))>>is_chroma;
1680         int h = ((height+6+ 31) & (~31))>>is_chroma;
1681
1682         pv->ref_stride[i] = w;
1683
1684         for( j = 0; j < 3; j++ )
1685         {
1686             pv->ref[j][i] = calloc( 1, w*h*sizeof(uint8_t) ) + 3*w;
1687         }
1688     }
1689
1690     /* Allocate a buffer to store a comb mask. */
1691     for( i = 0; i < 3; i++ )
1692     {
1693         int is_chroma = !!i;
1694         int w = ((pv->width[0]   + 31) & (~31))>>is_chroma;
1695         int h = ((pv->height[0]+6+ 31) & (~31))>>is_chroma;
1696
1697         pv->mask[i] = calloc( 1, w*h*sizeof(uint8_t) ) + 3*w;
1698     }
1699     
1700     if( pv->mode & MODE_EEDI2 )
1701     {
1702         /* Allocate half-height eedi2 buffers */
1703         height = pv->height[0] / 2;
1704         for( i = 0; i < 3; i++ )
1705         {
1706             int is_chroma = !!i;
1707             int w = ((width   + 31) & (~31))>>is_chroma;
1708             int h = ((height+6+ 31) & (~31))>>is_chroma;
1709
1710             for( j = 0; j < 4; j++ )
1711             {
1712                 pv->eedi_half[j][i] = calloc( 1, w*h*sizeof(uint8_t) ) + 3*w;
1713             }
1714         }
1715
1716         /* Allocate full-height eedi2 buffers */
1717         height = pv->height[0];
1718         for( i = 0; i < 3; i++ )
1719         {
1720             int is_chroma = !!i;
1721             int w = ((width   + 31) & (~31))>>is_chroma;
1722             int h = ((height+6+ 31) & (~31))>>is_chroma;
1723
1724             for( j = 0; j < 5; j++ )
1725             {
1726                 pv->eedi_full[j][i] = calloc( 1, w*h*sizeof(uint8_t) ) + 3*w;
1727             }
1728         }
1729     }
1730     
1731      /*
1732       * Create yadif threads and locks.
1733       */
1734      pv->yadif_threads = malloc( sizeof( hb_thread_t* ) * pv->cpu_count );
1735      pv->yadif_begin_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
1736      pv->yadif_complete_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
1737      pv->yadif_arguments = malloc( sizeof( yadif_arguments_t ) * pv->cpu_count );
1738
1739      for( i = 0; i < pv->cpu_count; i++ )
1740      {
1741          yadif_thread_arg_t *thread_args;
1742
1743          thread_args = malloc( sizeof( yadif_thread_arg_t ) );
1744
1745          if( thread_args )
1746          {
1747              thread_args->pv = pv;
1748              thread_args->segment = i;
1749
1750              pv->yadif_begin_lock[i] = hb_lock_init();
1751              pv->yadif_complete_lock[i] = hb_lock_init();
1752
1753              /*
1754               * Important to start off with the threads locked waiting
1755               * on input.
1756               */
1757              hb_lock( pv->yadif_begin_lock[i] );
1758
1759              pv->yadif_arguments[i].stop = 0;
1760              pv->yadif_arguments[i].dst = NULL;
1761              
1762              pv->yadif_threads[i] = hb_thread_init( "yadif_filter_segment",
1763                                                     yadif_decomb_filter_thread,
1764                                                     thread_args,
1765                                                     HB_NORMAL_PRIORITY );
1766          }
1767          else
1768          {
1769              hb_error( "yadif could not create threads" );
1770          }
1771     }
1772     
1773     /*
1774      * Create decomb threads and locks.
1775      */
1776     pv->decomb_threads = malloc( sizeof( hb_thread_t* ) * pv->cpu_count );
1777     pv->decomb_begin_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
1778     pv->decomb_complete_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
1779     pv->decomb_arguments = malloc( sizeof( decomb_arguments_t ) * pv->cpu_count );
1780     
1781     for( i = 0; i < pv->cpu_count; i++ )
1782     {
1783         decomb_thread_arg_t *decomb_thread_args;
1784     
1785         decomb_thread_args = malloc( sizeof( decomb_thread_arg_t ) );
1786     
1787         if( decomb_thread_args )
1788         {
1789             decomb_thread_args->pv = pv;
1790             decomb_thread_args->segment = i;
1791     
1792             pv->decomb_begin_lock[i] = hb_lock_init();
1793             pv->decomb_complete_lock[i] = hb_lock_init();
1794     
1795             /*
1796              * Important to start off with the threads locked waiting
1797              * on input.
1798              */
1799             hb_lock( pv->decomb_begin_lock[i] );
1800     
1801             pv->decomb_arguments[i].stop = 0;
1802     
1803             pv->decomb_threads[i] = hb_thread_init( "decomb_filter_segment",
1804                                                    decomb_filter_thread,
1805                                                    decomb_thread_args,
1806                                                    HB_NORMAL_PRIORITY );
1807         }
1808         else
1809         {
1810             hb_error( "decomb could not create threads" );
1811         }
1812     }
1813     
1814     if( pv->mode & MODE_EEDI2 )
1815     {
1816         /*
1817          * Create eedi2 threads and locks.
1818          */
1819         pv->eedi2_threads = malloc( sizeof( hb_thread_t* ) * 3 );
1820         pv->eedi2_begin_lock = malloc( sizeof( hb_lock_t * ) * 3 );
1821         pv->eedi2_complete_lock = malloc( sizeof( hb_lock_t * ) * 3 );
1822         pv->eedi2_arguments = malloc( sizeof( eedi2_arguments_t ) * 3 );
1823
1824         if( pv->post_processing > 1 )
1825         {
1826             pv->cx2 = (int*)eedi2_aligned_malloc(pv->height[0]*pv->ref_stride[0]*sizeof(int), 16);
1827             pv->cy2 = (int*)eedi2_aligned_malloc(pv->height[0]*pv->ref_stride[0]*sizeof(int), 16);
1828             pv->cxy = (int*)eedi2_aligned_malloc(pv->height[0]*pv->ref_stride[0]*sizeof(int), 16);
1829             pv->tmpc = (int*)eedi2_aligned_malloc(pv->height[0]*pv->ref_stride[0]*sizeof(int), 16);
1830             if( !pv->cx2 || !pv->cy2 || !pv->cxy || !pv->tmpc )
1831                 hb_log("EEDI2: failed to malloc derivative arrays");
1832             else
1833                 hb_log("EEDI2: successfully mallloced derivative arrays");
1834         }
1835
1836         for( i = 0; i < 3; i++ )
1837         {
1838             eedi2_thread_arg_t *eedi2_thread_args;
1839
1840             eedi2_thread_args = malloc( sizeof( eedi2_thread_arg_t ) );
1841
1842             if( eedi2_thread_args )
1843             {
1844                 eedi2_thread_args->pv = pv;
1845                 eedi2_thread_args->plane = i;
1846
1847                 pv->eedi2_begin_lock[i] = hb_lock_init();
1848                 pv->eedi2_complete_lock[i] = hb_lock_init();
1849
1850                 /*
1851                  * Important to start off with the threads locked waiting
1852                  * on input.
1853                  */
1854                 hb_lock( pv->eedi2_begin_lock[i] );
1855
1856                 pv->eedi2_arguments[i].stop = 0;
1857
1858                 pv->eedi2_threads[i] = hb_thread_init( "eedi2_filter_segment",
1859                                                        eedi2_filter_thread,
1860                                                        eedi2_thread_args,
1861                                                        HB_NORMAL_PRIORITY );
1862             }
1863             else
1864             {
1865                 hb_error( "eedi2 could not create threads" );
1866             }
1867         }
1868     }
1869     
1870     
1871     /* Allocate mcdeint specific buffers */
1872     if( pv->mcdeint_mode >= 0 )
1873     {
1874         avcodec_init();
1875         avcodec_register_all();
1876         AVCodec * enc = avcodec_find_encoder( CODEC_ID_SNOW );
1877         int i;
1878         for (i = 0; i < 3; i++ )
1879         {
1880             AVCodecContext * avctx_enc;
1881
1882             avctx_enc = pv->mcdeint_avctx_enc = avcodec_alloc_context();
1883
1884             avctx_enc->width                    = width;
1885             avctx_enc->height                   = height;
1886             avctx_enc->time_base                = (AVRational){1,25};  // meaningless
1887             avctx_enc->gop_size                 = 300;
1888             avctx_enc->max_b_frames             = 0;
1889             avctx_enc->pix_fmt                  = PIX_FMT_YUV420P;
1890             avctx_enc->flags                    = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
1891             avctx_enc->strict_std_compliance    = FF_COMPLIANCE_EXPERIMENTAL;
1892             avctx_enc->global_quality           = 1;
1893             avctx_enc->flags2                   = CODEC_FLAG2_MEMC_ONLY;
1894             avctx_enc->me_cmp                   = FF_CMP_SAD; //SSE;
1895             avctx_enc->me_sub_cmp               = FF_CMP_SAD; //SSE;
1896             avctx_enc->mb_cmp                   = FF_CMP_SSE;
1897
1898             switch( pv->mcdeint_mode )
1899             {
1900                 case 3:
1901                     avctx_enc->refs = 3;
1902                 case 2:
1903                     avctx_enc->me_method = ME_ITER;
1904                 case 1:
1905                     avctx_enc->flags |= CODEC_FLAG_4MV;
1906                     avctx_enc->dia_size =2;
1907                 case 0:
1908                     avctx_enc->flags |= CODEC_FLAG_QPEL;
1909             }
1910
1911             hb_avcodec_open(avctx_enc, enc);
1912         }
1913
1914         pv->mcdeint_frame       = avcodec_alloc_frame();
1915         pv->mcdeint_outbuf_size = width * height * 10;
1916         pv->mcdeint_outbuf      = malloc( pv->mcdeint_outbuf_size );
1917     }
1918
1919     return pv;
1920 }
1921
1922 void hb_decomb_close( hb_filter_private_t * pv )
1923 {
1924     if( !pv )
1925     {
1926         return;
1927     }
1928     
1929     hb_log("decomb: deinterlaced %i | blended %i | unfiltered %i | total %i", pv->deinterlaced_frames, pv->blended_frames, pv->unfiltered_frames, pv->deinterlaced_frames + pv->blended_frames + pv->unfiltered_frames);
1930
1931     /* Cleanup frame buffers */
1932     if( pv->buf_out[0] )
1933     {
1934         hb_buffer_close( &pv->buf_out[0] );
1935     }
1936     if( pv->buf_out[1] )
1937     {
1938         hb_buffer_close( &pv->buf_out[1] );
1939     }
1940     if (pv->buf_settings )
1941     {
1942         hb_buffer_close( &pv->buf_settings );
1943     }
1944
1945     /* Cleanup yadif specific buffers */
1946     int i;
1947     for( i = 0; i<3*3; i++ )
1948     {
1949         uint8_t **p = &pv->ref[i%3][i/3];
1950         if (*p)
1951         {
1952             free( *p - 3*pv->ref_stride[i/3] );
1953             *p = NULL;
1954         }
1955     }
1956     
1957     /* Cleanup combing mask. */
1958     for( i = 0; i<3*3; i++ )
1959     {
1960         uint8_t **p = &pv->mask[i/3];
1961         if (*p)
1962         {
1963             free( *p - 3*pv->ref_stride[i/3] );
1964             *p = NULL;
1965         }
1966     }
1967     
1968     if( pv->mode & MODE_EEDI2 )
1969     {
1970         /* Cleanup eedi-half  buffers */
1971         int j;
1972         for( i = 0; i<3; i++ )
1973         {
1974             for( j = 0; j < 4; j++ )
1975             {
1976                 uint8_t **p = &pv->eedi_half[j][i];
1977                 if (*p)
1978                 {
1979                     free( *p - 3*pv->ref_stride[i] );
1980                     *p = NULL;
1981                 }            
1982             }
1983         }
1984
1985         /* Cleanup eedi-full  buffers */
1986         for( i = 0; i<3; i++ )
1987         {
1988             for( j = 0; j < 5; j++ )
1989             {
1990                 uint8_t **p = &pv->eedi_full[j][i];
1991                 if (*p)
1992                 {
1993                     free( *p - 3*pv->ref_stride[i] );
1994                     *p = NULL;
1995                 }            
1996             }
1997         }
1998     }
1999     
2000     if( pv->post_processing > 1  && ( pv->mode & MODE_EEDI2 ) )
2001     {
2002         if (pv->cx2) eedi2_aligned_free(pv->cx2);
2003         if (pv->cy2) eedi2_aligned_free(pv->cy2);
2004         if (pv->cxy) eedi2_aligned_free(pv->cxy);
2005         if (pv->tmpc) eedi2_aligned_free(pv->tmpc);
2006     }
2007     
2008     for( i = 0; i < pv->cpu_count; i++)
2009     {
2010         /*
2011          * Tell each yadif thread to stop, and then cleanup.
2012          */
2013         pv->yadif_arguments[i].stop = 1;
2014         hb_unlock(  pv->yadif_begin_lock[i] );
2015
2016         hb_thread_close( &pv->yadif_threads[i] );
2017         hb_lock_close( &pv->yadif_begin_lock[i] );
2018         hb_lock_close( &pv->yadif_complete_lock[i] );
2019     }
2020     
2021     /*
2022      * free memory for yadif structs
2023      */
2024     free( pv->yadif_threads );
2025     free( pv->yadif_begin_lock );
2026     free( pv->yadif_complete_lock );
2027     free( pv->yadif_arguments );
2028     
2029     for( i = 0; i < pv->cpu_count; i++)
2030     {
2031         /*
2032          * Tell each decomb thread to stop, and then cleanup.
2033          */
2034         pv->decomb_arguments[i].stop = 1;
2035         hb_unlock(  pv->decomb_begin_lock[i] );
2036
2037         hb_thread_close( &pv->decomb_threads[i] );
2038         hb_lock_close( &pv->decomb_begin_lock[i] );
2039         hb_lock_close( &pv->decomb_complete_lock[i] );
2040     }
2041     
2042     /*
2043      * free memory for decomb structs
2044      */
2045     free( pv->decomb_threads );
2046     free( pv->decomb_begin_lock );
2047     free( pv->decomb_complete_lock );
2048     free( pv->decomb_arguments );
2049     
2050     if( pv->mode & MODE_EEDI2 )
2051     {
2052         for( i = 0; i < 3; i++)
2053         {
2054             /*
2055              * Tell each eedi2 thread to stop, and then cleanup.
2056              */
2057             pv->eedi2_arguments[i].stop = 1;
2058             hb_unlock(  pv->eedi2_begin_lock[i] );
2059
2060             hb_thread_close( &pv->eedi2_threads[i] );
2061             hb_lock_close( &pv->eedi2_begin_lock[i] );
2062             hb_lock_close( &pv->eedi2_complete_lock[i] );
2063         }
2064
2065         /*
2066          * free memory for eedi2 structs
2067          */
2068         free( pv->eedi2_threads );
2069         free( pv->eedi2_begin_lock );
2070         free( pv->eedi2_complete_lock );
2071         free( pv->eedi2_arguments );
2072     }
2073     
2074     /* Cleanup mcdeint specific buffers */
2075     if( pv->mcdeint_mode >= 0 )
2076     {
2077         if( pv->mcdeint_avctx_enc )
2078         {
2079             hb_avcodec_close( pv->mcdeint_avctx_enc );
2080             av_freep( &pv->mcdeint_avctx_enc );
2081         }
2082         if( pv->mcdeint_outbuf )
2083         {
2084             free( pv->mcdeint_outbuf );
2085         }
2086     }
2087
2088     free( pv );
2089 }
2090
2091 int hb_decomb_work( const hb_buffer_t * cbuf_in,
2092                     hb_buffer_t ** buf_out,
2093                     int pix_fmt,
2094                     int width,
2095                     int height,
2096                     hb_filter_private_t * pv )
2097 {
2098     hb_buffer_t * buf_in = (hb_buffer_t *)cbuf_in;
2099
2100     if( !pv ||
2101         pix_fmt != pv->pix_fmt ||
2102         width   != pv->width[0] ||
2103         height  != pv->height[0] )
2104     {
2105         return FILTER_FAILED;
2106     }
2107
2108     avpicture_fill( &pv->pic_in, buf_in->data,
2109                     pix_fmt, width, height );
2110
2111     /* Determine if top-field first layout */
2112     int tff;
2113     if( pv->parity < 0 )
2114     {
2115         tff = !!(buf_in->flags & PIC_FLAG_TOP_FIELD_FIRST);
2116     }
2117     else
2118     {
2119         tff = (pv->parity & 1) ^ 1;
2120     }
2121
2122     /* Store current frame in yadif cache */
2123     store_ref( (const uint8_t**)pv->pic_in.data, pv );
2124
2125     /* If yadif is not ready, store another ref and return FILTER_DELAY */
2126     if( pv->yadif_ready == 0 )
2127     {
2128         store_ref( (const uint8_t**)pv->pic_in.data, pv );
2129
2130         hb_buffer_copy_settings( pv->buf_settings, buf_in );
2131
2132         /* don't let 'work_loop' send a chapter mark upstream */
2133         buf_in->new_chap  = 0;
2134
2135         pv->yadif_ready = 1;
2136
2137         return FILTER_DELAY;
2138     }
2139
2140     /* Perform yadif filtering */        
2141     int frame;
2142     for( frame = 0; frame <= ( ( pv->mode & MODE_MCDEINT ) ? 1 : 0 ) ; frame++ )
2143 // This would be what to use for bobbing: for( frame = 0; frame <= 0 ; frame++ )
2144     {
2145
2146 #if 0        
2147         /* Perhaps skip the second run if the frame is uncombed? */
2148         if( frame && !pv->yadif_arguments[0].is_combed )
2149         {
2150             break;
2151         }
2152 #endif        
2153         int parity = frame ^ tff ^ 1;
2154
2155 // This will be for bobbing
2156 #if 0
2157         if( pv->alternator )
2158         {
2159             parity = !parity;
2160             pv->alternator = 0;
2161         }
2162         else
2163         {
2164             pv->alternator = 1;
2165         }
2166 #endif
2167         pv->tff = !parity;
2168
2169         avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data,
2170                         pix_fmt, width, height );
2171
2172         /* XXX
2173             Should check here and only bother filtering field 2 when
2174            field 1 was detected as combed.
2175            And when it's not, it's a progressive frame,
2176            so mcdeint should be skipped...
2177         */
2178         yadif_filter( pv->pic_out.data, parity, tff, pv );
2179
2180         /* Commented out code in the line below would skip mcdeint
2181            on uncombed frames. Possibly a bad idea, since mcdeint
2182            maintains the same snow context for the entire video... */
2183         if( pv->mcdeint_mode >= 0 /* && pv->yadif_arguments[0].is_combed */)
2184         {
2185             /* Perform mcdeint filtering */
2186             avpicture_fill( &pv->pic_in,  pv->buf_out[(frame^1)]->data,
2187                             pix_fmt, width, height );
2188
2189             mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv );
2190         }
2191
2192         *buf_out = pv->buf_out[!(frame^1)];
2193     }
2194
2195     /* Copy buffered settings to output buffer settings */
2196     hb_buffer_copy_settings( *buf_out, pv->buf_settings );
2197
2198     /* Replace buffered settings with input buffer settings */
2199     hb_buffer_copy_settings( pv->buf_settings, buf_in );
2200
2201     /* don't let 'work_loop' send a chapter mark upstream */
2202     buf_in->new_chap  = 0;
2203
2204     return FILTER_OK;
2205 }