All pastes #1050235 Raw Edit

tritical comb detection

public diff v1 · immutable
#1050235 ·published 2008-06-18 15:46 UTC
rendered paste body
Index: libhb/decomb.c===================================================================--- libhb/decomb.c	(revision 1516)+++ libhb/decomb.c	(working copy)@@ -11,7 +11,7 @@  #define SUPPRESS_AV_LOG -#define MODE_DEFAULT     4+#define MODE_DEFAULT     1 #define PARITY_DEFAULT   -1  #define MCDEINT_MODE_DEFAULT   -1@@ -28,6 +28,13 @@     int              height[3];      int              mode;+    int              spatial_metric;+    int              motion_threshold;+    int              spatial_threshold;+    int              block_threshold;+    int              block_width;+    int              block_height;+     int              parity;          int              yadif_ready;@@ -41,27 +48,20 @@     AVFrame        * mcdeint_frame;     AVFrame        * mcdeint_frame_dec; -    int              comb;-    int              color_equal;-    int              color_diff;-    int              threshold;-    int              prog_equal;-    int              prog_diff;-    int              prog_threshold;-    int              deinterlaced_frames;-    int              passed_frames;+    int              yadif_deinterlaced_frames;+    int              blend_deinterlaced_frames;+    int              unfiltered_frames;      uint8_t        * ref[4][3];     int              ref_stride[3]; +    /* Make a buffer to store a comb mask. */+    uint8_t        * mask[3];+     AVPicture        pic_in;     AVPicture        pic_out;     hb_buffer_t *    buf_out[2];     hb_buffer_t *    buf_settings;-    -    int              cc_array[3][480][270];-    int              combed_macroblocks;-    int              uncombed_macroblocks; };  hb_filter_private_t * hb_decomb_init( int pix_fmt,@@ -81,7 +81,7 @@ hb_filter_object_t hb_filter_decomb = {     FILTER_DECOMB,-    "Decombs selectively with (ffmpeg or yadif/mcdeint or blending)",+    "Deinterlaces selectively with yadif/mcdeint or blending",     NULL,     hb_decomb_init,     hb_decomb_work,@@ -230,6 +230,244 @@     } } +int tritical_detect_comb( hb_filter_private_t * pv )+{+    /* A mish-mash of various comb detection tricks+       picked up fro neuron2's Decomb plugin for+       AviSynth and tritical's IsCombedT and+       IsCombedTIVTC plugins.                       */+       +    int x, y, k, width, height;+    +    /* Comb scoring algorithm */+    int spatial_metric  = pv->spatial_metric;+    /* Motion threshold */+    int mthresh         = pv->motion_threshold;+    /* Spatial threshold */+    int athresh         = pv->spatial_threshold;+    int athresh_squared = athresh * athresh;+    int athresh6        = 6 *athresh;+    /* Block mask threshold -- The number of pixels+       in a block_width * block_height window of+       he mask that need to show combing for the+       whole frame to be seen as such.            */+    int threshold       = pv->block_threshold;+    int block_width     = pv->block_width;+    int block_height    = pv->block_height;+    +    /* One pas for Y, one pass for Cb, one pass for Cr */    +    for( k = 0; k < 1; k++ )+    {+        int ref_stride  = pv->ref_stride[k];+        width           = pv->width[k];+        height          = pv->height[k];++        for( y = 2; y < ( height - 2 ); y++ )+        {+            /* These are just to make the buffer locations easier to read. */+            int back_2    = ( y - 2 )*ref_stride ;+            int back_1    = ( y - 1 )*ref_stride;+            int current   =         y*ref_stride;+            int forward_1 = ( y + 1 )*ref_stride;+            int forward_2 = ( y + 2 )*ref_stride;+            +            /* We need to examine a column of 5 pixels+               in the prev, cur, and next frames.      */+            uint8_t previous_frame[5];+            uint8_t current_frame[5];+            uint8_t next_frame[5];+            +            for( x = 0; x < width; x++ )+            {+                /* Fill up the current frame array with the current pixel values.*/+                current_frame[0] = pv->ref[1][k][back_2    + x];+                current_frame[1] = pv->ref[1][k][back_1    + x];+                current_frame[2] = pv->ref[1][k][current   + x];+                current_frame[3] = pv->ref[1][k][forward_1 + x];+                current_frame[4] = pv->ref[1][k][forward_2 + x];++                int up_diff   = current_frame[2] - current_frame[1];+                int down_diff = current_frame[2] - current_frame[3];++                if( ( up_diff >  athresh && down_diff >  athresh ) ||+                    ( up_diff < -athresh && down_diff < -athresh ) )+                {+                    /* The pixel above and below are different,+                       and they change in the same "direction" too.*/+                    int motion = 0;+                    if( mthresh > 0 )+                    {+                        /* Make sure there's sufficient motion between frame t-1 to frame t+1. */+                        previous_frame[0] = pv->ref[0][k][back_2    + x];+                        previous_frame[1] = pv->ref[0][k][back_1    + x];+                        previous_frame[2] = pv->ref[0][k][current   + x];+                        previous_frame[3] = pv->ref[0][k][forward_1 + x];+                        previous_frame[4] = pv->ref[0][k][forward_2 + x];+                        next_frame[0]     = pv->ref[2][k][back_2    + x];+                        next_frame[1]     = pv->ref[2][k][back_1    + x];+                        next_frame[2]     = pv->ref[2][k][current   + x];+                        next_frame[3]     = pv->ref[2][k][forward_1 + x];+                        next_frame[4]     = pv->ref[2][k][forward_2 + x];+                        +                        if( abs( previous_frame[2] - current_frame[2] ) > mthresh &&+                            abs(  current_frame[1] - next_frame[1]    ) > mthresh &&+                            abs(  current_frame[3] - next_frame[3]    ) > mthresh )+                                motion++;+                        if( abs(     next_frame[2] - current_frame[2] ) > mthresh &&+                            abs( previous_frame[1] - current_frame[1] ) > mthresh &&+                            abs( previous_frame[3] - current_frame[3] ) > mthresh )+                                motion++;+                    }+                    else+                    {+                        /* User doesn't want to check for motion,+                           so move on to the spatial check.       */+                        motion = 1;+                    }+                           +                    if( motion )+                    {+                           /*That means it's time for the spatial check.+                           We've got several options here.             */+                        if( spatial_metric == 0 )+                        {+                            /* Simple 32detect style comb detection */+                            if( ( abs( current_frame[2] - current_frame[4] ) < 10  ) &&+                                ( abs( current_frame[2] - current_frame[3] ) > 15 ) )+                            {+                                pv->mask[k][y*ref_stride + x] = 255;+                            }+                            else+                            {+                                pv->mask[k][y*ref_stride + x] = 0;+                            }+                        }+                        else if( spatial_metric == 1 )+                        {+                            /* This, for comparison, is what IsCombed uses.+                               It's better, but still noise senstive.      */+                               int combing = ( current_frame[1] - current_frame[2] ) *+                                             ( current_frame[3] - current_frame[2] );+                               +                               if( combing > athresh_squared )+                                   pv->mask[k][y*ref_stride + x] = 255; +                               else+                                   pv->mask[k][y*ref_stride + x] = 0;+                        }+                        else if( spatial_metric == 2 )+                        {+                            /* Tritical's noise-resistant combing scorer.+                               The check is done on a bob+blur convolution. */+                            int combing = abs( current_frame[0]+                                             + ( 4 * current_frame[2] )+                                             + current_frame[4]+                                             - ( 3 * ( current_frame[1]+                                                     + current_frame[3] ) ) );++                            /* If the frame is sufficiently combed,+                               then mark it down on the mask as 255. */+                            if( combing > athresh6 )+                                pv->mask[k][y*ref_stride + x] = 255; +                            else+                                pv->mask[k][y*ref_stride + x] = 0;+                        }+                    }+                    else+                    {+                        pv->mask[k][y*ref_stride + x] = 0;+                    }+                }+                else+                {+                    pv->mask[k][y*ref_stride + x] = 0;+                }+            }+        }+    }+    +    /* Go through the mask in X*Y blocks. If any of these windows+       have threshold or more combed pixels, consider the whole+       frame to be combed and send it on to be deinterlaced.     */+    int block_score = 0; int send_to_blend = 0;+    for( k = 0; k < 1; k++ )+    {+        int ref_stride = pv->ref_stride[k];        +        for( y = 0; y < ( pv->height[k] - block_height ); y = y + block_height )+        {+            for( x = 0; x < ( pv->width[k] - block_width ); x = x + block_width )+            {+                int block_x;+                int block_y;+                block_score = 0;+                for( block_y = 0; block_y < block_height; block_y++ )+                {+                    for( block_x = 0; block_x < block_width; block_x++ )+                    {+                        int mask_y = y + block_y;+                        int mask_x = x + block_x;+                        +                        /* We only want to mark a pixel in a block as combed+                           if the pixels above and below are as well. Got to+                           handle the top and bottom lines separately.       */+                        if( y + block_y == 0 )+                        {+                            if( pv->mask[k][mask_y*ref_stride+mask_x    ] == 255 &&+                                pv->mask[k][mask_y*ref_stride+mask_x + 1] == 255 )+                                    block_score++;+                        }+                        else if( y + block_y == pv->height[k] - 1 )+                        {+                            if( pv->mask[k][mask_y*ref_stride+mask_x - 1] == 255 &&+                                pv->mask[k][mask_y*ref_stride+mask_x    ] == 255 )+                                    block_score++;+                        }+                        else+                        {+                            if( pv->mask[k][mask_y*ref_stride+mask_x - 1] == 255 &&+                                pv->mask[k][mask_y*ref_stride+mask_x    ] == 255 &&+                                pv->mask[k][mask_y*ref_stride+mask_x + 1] == 255 )+                                    block_score++;+                        } +                    }+                }++                if( block_score >= ( threshold / 2 ) )+                {+#if 0+                    hb_log("decomb: frame %i | score %i | type %s", pv->yadif_deinterlaced_frames + pv->blend_deinterlaced_frames +  pv->unfiltered_frames + 1, block_score, pv->buf_settings->flags & 16 ? "Film" : "Video");+#endif+                    if ( block_score <= threshold && !( pv->buf_settings->flags & 16) )+                    {+                        /* Blend video content that scores between+                           ( threshold / 2 ) and threshold.        */+                        send_to_blend = 1;+                    }+                    else if( block_score > threshold && pv->buf_settings->flags & 16 )+                    {+                        /* Blend progressive content above the threshold.*/+                        return 2;+                    }+                    else if( block_score > threshold )+                    {+                        /* Yadif deinterlace video content above the threshold. */+                        return 1;+                    }+                }+            }+        } +    }+    +    if( send_to_blend )+    {+        return 2;+    }+    else+    {+        /* Consider this frame to be uncombed. */+        return 0;+    }+}+ static void yadif_filter_line( uint8_t *dst,                                uint8_t *prev,                                uint8_t *cur,@@ -245,32 +483,9 @@     int w = pv->width[plane];     int refs = pv->ref_stride[plane];     int x;-    int macroblock_x;-    int macroblock_y = y / 8 ;     -         for( x = 0; x < w; x++)     {--#if 0       -     /* Buggy experimental code for macroblock-by-macrobock comb detection.*/-        if(plane == 0 && pv->mode == 7)-        {-            if( !(x % 8))-                macroblock_x = x / 8;        -            -            if(pv->cc_array[plane][macroblock_x][macroblock_y] < 0 || pv->cc_array[plane][macroblock_x][macroblock_y] > 64)-            hb_log("[%i][%i] ( %i * %i )macroblock %i x %i is combed: %i", pv->deinterlaced_frames, plane, x, y, macroblock_x, macroblock_y, pv->cc_array[plane][macroblock_x][macroblock_y] );-            -            if(pv->cc_array[plane][macroblock_x][macroblock_y] == 0 && pv->cc_array[plane][macroblock_x+1][macroblock_y] == 0 && pv->cc_array[plane][macroblock_x-1][macroblock_y] == 0 && pv->cc_array[plane][macroblock_x][macroblock_y+1] == 0 && pv->cc_array[plane][macroblock_x][macroblock_y-1] == 0 )-            {-                dst[0] = cur[0];-                pv->uncombed_macroblocks++;-                goto end_of_yadif_filter_pixel;-            }-        }-        pv->combed_macroblocks++;-#endif         /* Pixel above*/         int c              = cur[-refs];         /* Temporal average -- the current pixel location in the previous and next fields */@@ -293,7 +508,7 @@         int spatial_pred;                   /* Spatial pred is either a bilinear or cubic vertical interpolation. */-        if( pv->mode >= 4  )+        if( pv->mode > 0 )         {             spatial_pred = cubic_interpolate( cur[-3*refs], cur[-refs], cur[+refs], cur[3*refs] );         }@@ -314,7 +529,7 @@                       + ABS(cur[-refs+1+j] - cur[+refs+1-j]);\             if( score < spatial_score ){\                 spatial_score = score;\-                if( pv->mode >= 4)\+                if( pv->mode > 0 )\                 {\                     switch(j)\                     {\@@ -340,8 +555,8 @@                 YADIF_CHECK(-1) YADIF_CHECK(-2) }} }}                 YADIF_CHECK( 1) YADIF_CHECK( 2) }} }}                                 -        /* Temporally adjust the spatial prediction by comparing against the-           alternate (associated) fields in the previous and next frames. */+        /* Temporally adjust the spatial prediction by comparing+           against fields in the previous and next frames.       */         int b = (prev2[-2*refs] + next2[-2*refs])>>1;         int f = (prev2[+2*refs] + next2[+2*refs])>>1;         @@ -361,7 +576,6 @@                  dst[0] = spatial_pred;                         -end_of_yadif_filter_pixel:         dst++;         cur++;         prev++;@@ -376,109 +590,21 @@                           int tff,                           hb_filter_private_t * pv ) {--#if 0-    /* Buggy, experimental code for macroblock-by-macroblock decombing.*/-    if( pv->mode == 7 )+    +    int is_combed = tritical_detect_comb( pv );+    +    if( is_combed == 1 )     {-        int x, y, block_x, block_y, plane, plane_width, plane_height, offset, cc;-        -        int stride = 0;-        int block = 8;-        int s[16];-        int color_diff = pv->color_diff;-        int color_equal = pv->color_equal;-        -        if ( pv->buf_settings->flags & 16 )-        {-            /* Frame is progressive, be more discerning. */-            color_diff = pv->prog_diff;-            color_equal = pv->prog_equal;-        }-        -        /* Iterate through planes */-        for( plane = 0; plane < 1; plane++ )-        {   -            plane_width =  pv->width[plane];-            plane_height = pv->height[plane];-        -            if( plane == 1 )-            {-                /* Y has already been checked, now offset by Y's dimensions-                   and divide all the other values by 2, since Cr and Cb-                   are half-size compared to Y.                               */-                stride = plane_width * plane_height;-            }-            else if ( plane == 2 )-            {-                /* Y and Cb are done, so the offset needs to be bumped-                   so it's width*height + (width / 2) * (height / 2)  */-                stride *= 5/4;-            }-            /* Grab a horizontal line */-            for(y = 0; y < plane_height; y += block )-            {-                uint8_t *line = &pv->ref[1][plane][ y*plane_width ];--                /* Iterate through it horizontally in blocks */-                for(x = 0; x < plane_width; x += block)-                {-                    /* Clear out the current macroblock mapping from the last frame. */-                    pv->cc_array[plane][x/block][y/block] = 0;-                    int sadA = 0;-                    int sadB = 0;-                    -                    /* Go through the block horizontally */-                    for(block_x = 0; block_x < block; block_x++)-                    {-                        /* Go through the block vertically, collecting pixels */-                        for(block_y = 0; block_y < block*2; block_y++)-                        {-                            s[block_y] = line[x+block_x+(block_y*plane_width)];-                        }--                        /* Now go through the results to check combing. */-                        for(block_y = 0; block_y < block; block_y++)-                        {-                            sadA += abs(s[block_y] - s[block_y+2]);-                            sadB += abs(s[block_y] - s[block_y+1]);-                            -//                            if( abs(s[block_y] - s[block_y+2]) < color_equal && abs(s[block_y] - s[block_y+1]) > color_diff)-//                            {-//                                pv->cc_array[plane][x/block][y/block]++;-//                            }-                        }-                    }-                    -                    if(sadA < sadB)-                    {-                        pv->cc_array[plane][x/block][y/block] = 1;-                    }-                    -                }-            }        -        }+        pv->yadif_deinterlaced_frames++;     }--#if 0-/* Visualize macroblocks */    -    int x, y;-    fprintf(stderr, "FRAME %i VISUALIZATION\n", pv->deinterlaced_frames);-    for( y = 0; y < 60; y++ )+    else if( is_combed == 2 )     {-        for( x = 0; x < 90; x++ )-        {-            if(pv->cc_array[0][x][y])-                fprintf(stderr, "X");-            else-                fprintf(stderr, "O");-                -        }-        fprintf(stderr, "\n");+        pv->blend_deinterlaced_frames++;     }-    fprintf(stderr, "\n\n");-#endif-#endif+    else+    {+        pv->unfiltered_frames++;+    }      int i;     for( i = 0; i < 3; i++ )@@ -490,7 +616,7 @@         int y;         for( y = 0; y < h; y++ )         {-            if( pv->mode == 3)+            if( ( pv->mode == 4 && is_combed ) || is_combed == 2 )             {                 uint8_t *prev = &pv->ref[0][i][y*ref_stride];                 uint8_t *cur  = &pv->ref[1][i][y*ref_stride];@@ -499,7 +625,7 @@                  blend_filter_line( dst2, cur, i, y, pv );             }-            else if( (y ^ parity) &  1 )+            else if( (y ^ parity) & 1 && is_combed == 1 )             {                 uint8_t *prev = &pv->ref[0][i][y*ref_stride];                 uint8_t *cur  = &pv->ref[1][i][y*ref_stride];@@ -655,20 +781,20 @@     pv->buf_out[1] = hb_buffer_init( buf_size );     pv->buf_settings = hb_buffer_init( 0 ); -    pv->deinterlaced_frames = 0;-    pv->passed_frames = 0;-    pv->color_equal = 10;-    pv->color_diff = 15;-    pv->threshold = 9;-    pv->prog_equal = 10;-    pv->prog_diff = 35;-    pv->prog_threshold = 9;-    -    pv->combed_macroblocks = 0;-    pv->uncombed_macroblocks = 0;-    +    pv->yadif_deinterlaced_frames = 0;+    pv->blend_deinterlaced_frames = 0;+    pv->unfiltered_frames = 0;+     pv->yadif_ready    = 0;+     pv->mode     = MODE_DEFAULT;+    pv->spatial_metric = 2;+    pv->motion_threshold = 6;+    pv->spatial_threshold = 9;+    pv->block_threshold = 80;+    pv->block_width = 16;+    pv->block_height = 16;+         pv->parity   = PARITY_DEFAULT;      pv->mcdeint_mode   = MCDEINT_MODE_DEFAULT;@@ -678,38 +804,45 @@     {         sscanf( settings, "%d:%d:%d:%d:%d:%d:%d",                 &pv->mode,-                &pv->color_equal,-                &pv->color_diff,-                &pv->threshold,-                &pv->prog_equal,-                &pv->prog_diff,-                &pv->prog_threshold );+                &pv->spatial_metric,+                &pv->motion_threshold,+                &pv->spatial_threshold,+                &pv->block_threshold,+                &pv->block_width,+                &pv->block_height );     }-    -    if( pv->mode == 2 || pv->mode == 5 )++    if( pv->mode == 2 || pv->mode == 3 )     {         pv->mcdeint_mode = 0;     }          /* Allocate yadif specific buffers */-    if( pv->mode > 0 )+    int i, j;+    for( i = 0; i < 3; i++ )     {-        int i, j;-        for( i = 0; i < 3; i++ )-        {-            int is_chroma = !!i;-            int w = ((width   + 31) & (~31))>>is_chroma;-            int h = ((height+6+ 31) & (~31))>>is_chroma;+        int is_chroma = !!i;+        int w = ((width   + 31) & (~31))>>is_chroma;+        int h = ((height+6+ 31) & (~31))>>is_chroma; -            pv->ref_stride[i] = w;+        pv->ref_stride[i] = w; -            for( j = 0; j < 3; j++ )-            {-                pv->ref[j][i] = malloc( w*h*sizeof(uint8_t) ) + 3*w;-            }+        for( j = 0; j < 3; j++ )+        {+            pv->ref[j][i] = malloc( w*h*sizeof(uint8_t) ) + 3*w;         }     } +    /* Allocate a buffer to store a comb mask. */+    for( i = 0; i < 3; i++ )+    {+        int is_chroma = !!i;+        int w = ((pv->width[0]   + 31) & (~31))>>is_chroma;+        int h = ((pv->height[0]+6+ 31) & (~31))>>is_chroma;++        pv->mask[i] = malloc( w*h*sizeof(uint8_t) ) + 3*w;+    }+     /* Allocate mcdeint specific buffers */     if( pv->mcdeint_mode >= 0 )     {@@ -770,14 +903,7 @@         return;     }     -    if( pv->mode < 7 )-    {-        hb_log("decomb: deinterlaced %i | unfiltered %i | total %i", pv->deinterlaced_frames, pv->passed_frames, pv->deinterlaced_frames + pv->passed_frames);-    }-    else-    {-        hb_log("decomb macroblock: deinterlaced: %i | unfiltered %i | total %i", pv->combed_macroblocks, pv->uncombed_macroblocks, pv->combed_macroblocks + pv->uncombed_macroblocks);-    }+    hb_log("decomb: yadif deinterlaced %i | blend deinterlaced %i | unfiltered %i | total %i", pv->yadif_deinterlaced_frames, pv->blend_deinterlaced_frames, pv->unfiltered_frames, pv->yadif_deinterlaced_frames + pv->blend_deinterlaced_frames + pv->unfiltered_frames);      /* Cleanup frame buffers */     if( pv->buf_out[0] )@@ -794,20 +920,28 @@     }      /* Cleanup yadif specific buffers */-    if( pv->mode > 0 )+    int i;+    for( i = 0; i<3*3; i++ )     {-        int i;-        for( i = 0; i<3*3; i++ )+        uint8_t **p = &pv->ref[i%3][i/3];+        if (*p)         {-            uint8_t **p = &pv->ref[i%3][i/3];-            if (*p)-            {-                free( *p - 3*pv->ref_stride[i/3] );-                *p = NULL;-            }+            free( *p - 3*pv->ref_stride[i/3] );+            *p = NULL;         }     }-+    +    /* Cleanup combing mask. */+    for( i = 0; i<3*3; i++ )+    {+        uint8_t **p = &pv->mask[i/3];+        if (*p)+        {+            free( *p - 3*pv->ref_stride[i/3] );+            *p = NULL;+        }+    }+         /* Cleanup mcdeint specific buffers */     if( pv->mcdeint_mode >= 0 )     {@@ -845,40 +979,6 @@     avpicture_fill( &pv->pic_in, buf_in->data,                     pix_fmt, width, height ); -    /* Use libavcodec deinterlace if mode == 0 */-    if( pv->mode == 0 )-    {-        avpicture_fill( &pv->pic_out, pv->buf_out[0]->data,-                        pix_fmt, width, height );--        /* Check for combing on the input frame */-        int interlaced =  hb_detect_comb(buf_in, width, height, pv->color_equal, pv->color_diff, pv->threshold, pv->prog_equal, pv->prog_diff, pv->prog_threshold);-        -        if(interlaced)-        {-            avpicture_deinterlace( &pv->pic_out, &pv->pic_in,-                                   pix_fmt, width, height );--            pv->deinterlaced_frames++;-            //hb_log("Frame %i is combed (Progressive: %s )", pv->deinterlaced_frames + pv->passed_frames, (buf_in->flags & 16) ? "Y" : "N");-            -            hb_buffer_copy_settings( pv->buf_out[0], buf_in );-            *buf_out = pv->buf_out[0];            -        }-        else-        {-            /* No combing detected, pass input frame through unmolested.*/-            -            pv->passed_frames++;-            -            hb_buffer_copy_settings( pv->buf_out[0], buf_in );-            *buf_out = buf_in;-            -        }--        return FILTER_OK;-    }-         /* Determine if top-field first layout */     int tff;     if( pv->parity < 0 )@@ -892,12 +992,6 @@      /* Store current frame in yadif cache */     store_ref( (const uint8_t**)pv->pic_in.data, pv );-    -    if( pv->mode < 7 )-    {-        /* Note down if the input frame is combed */-        pv->comb = (pv->comb << 1) | hb_detect_comb(buf_in, width, height, pv->color_equal, pv->color_diff, pv->threshold, pv->prog_equal, pv->prog_diff, pv->prog_threshold);-    }      /* If yadif is not ready, store another ref and return FILTER_DELAY */     if( pv->yadif_ready == 0 )@@ -914,71 +1008,27 @@         return FILTER_DELAY;     } -    /* yadif works one frame behind so if the previous frame-     * had combing, deinterlace it otherwise just output it. */-    if( pv->mode == 7 ) // Experimental for macroblock decombing+    /* Perform yadif filtering */        +    int frame;+    for( frame = 0; frame <= ( ( pv->mode == 2 || pv->mode == 3 )? 1 : 0 ) ; frame++ )     {-        /* Perform yadif filtering */-        -        pv->deinterlaced_frames++;-        int frame;-        for( frame = 0; frame <= ( ( pv->mode == 2 || pv->mode == 5 )? 1 : 0 ) ; frame++ )-        {-            int parity = frame ^ tff ^ 1;+        int parity = frame ^ tff ^ 1; -            avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data,-                            pix_fmt, width, height );+        avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data,+                        pix_fmt, width, height ); -            yadif_filter( pv->pic_out.data, parity, tff, pv );+        yadif_filter( pv->pic_out.data, parity, tff, pv ); -            if( pv->mcdeint_mode >= 0 )-            {-                /* Perform mcdeint filtering */-                avpicture_fill( &pv->pic_in,  pv->buf_out[(frame^1)]->data,-                                pix_fmt, width, height );--                mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv );-            }--            *buf_out = pv->buf_out[!(frame^1)];-        }-    }-    else if(  (pv->comb & 2 ) == 0 )-    {-        /* previous frame not interlaced - copy cached input frame to buf_out */-        -        pv->passed_frames++;-        -        avpicture_fill( &pv->pic_out,  pv->buf_out[0]->data, pix_fmt, width, height );-        get_ref( (uint8_t**)pv->pic_out.data, pv, 1 );-        *buf_out = pv->buf_out[0];-    }-    else-    {-        /* Perform yadif filtering */-        -        pv->deinterlaced_frames++;-        int frame;-        for( frame = 0; frame <= ( ( pv->mode == 2 || pv->mode == 5 )? 1 : 0 ) ; frame++ )+        if( pv->mcdeint_mode >= 0 )         {-            int parity = frame ^ tff ^ 1;--            avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data,+            /* Perform mcdeint filtering */+            avpicture_fill( &pv->pic_in,  pv->buf_out[(frame^1)]->data,                             pix_fmt, width, height ); -            yadif_filter( pv->pic_out.data, parity, tff, pv );+            mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv );+        } -            if( pv->mcdeint_mode >= 0 )-            {-                /* Perform mcdeint filtering */-                avpicture_fill( &pv->pic_in,  pv->buf_out[(frame^1)]->data,-                                pix_fmt, width, height );--                mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv );-            }--            *buf_out = pv->buf_out[!(frame^1)];-        }+        *buf_out = pv->buf_out[!(frame^1)];     }      /* Copy buffered settings to output buffer settings */