OSDN Git Service

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