]> granicus.if.org Git - handbrake/commitdiff
This should fix the flickering line bugs with deinterlace and decomb. Yadif needs...
authorjbrjake <jb.rubin@gmail.com>
Thu, 23 Oct 2008 18:12:02 +0000 (18:12 +0000)
committerjbrjake <jb.rubin@gmail.com>
Thu, 23 Oct 2008 18:12:02 +0000 (18:12 +0000)
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1862 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/decomb.c
libhb/deinterlace.c

index df1838a7d1dd63d1730ccfb4a403e8084706334e..e83f0d5a6923c6b6b00b8eb1ad90004615e003d9 100644 (file)
@@ -630,6 +630,13 @@ static void yadif_filter_line( uint8_t *dst,
     int refs = pv->ref_stride[plane];
     int x;
     
+    /* Decomb's cubic interpolation can only function when there are
+       three samples above and below, so regress to yadif's traditional
+       two-tap interpolation when filtering at the top and bottom edges. */
+    int edge = 0;
+    if( ( y < 3 ) || ( y > ( pv->height[plane] - 4 ) )  )
+        edge = 1;
+
     for( x = 0; x < w; x++)
     {
         /* Pixel above*/
@@ -654,7 +661,7 @@ static void yadif_filter_line( uint8_t *dst,
         int spatial_pred;
          
         /* Spatial pred is either a bilinear or cubic vertical interpolation. */
-        if( pv->mode > 0 )
+        if( pv->mode > 0 && !edge)
         {
             spatial_pred = cubic_interpolate( cur[-3*refs], cur[-refs], cur[+refs], cur[3*refs] );
         }
@@ -675,7 +682,7 @@ static void yadif_filter_line( uint8_t *dst,
                       + ABS(cur[-refs+1+j] - cur[+refs+1-j]);\
             if( score < spatial_score ){\
                 spatial_score = score;\
-                if( pv->mode > 0 )\
+                if( pv->mode > 0 && !edge )\
                 {\
                     switch(j)\
                     {\
@@ -748,7 +755,7 @@ void yadif_decomb_filter_thread( void *thread_args_v )
     int segment, segment_start, segment_stop;
     yadif_thread_arg_t *thread_args = thread_args_v;
     uint8_t **dst;
-    int parity, tff, y, w, h, ref_stride, is_combed;
+    int parity, tff, y, w, h, penultimate, ultimate, ref_stride, is_combed;
 
     pv = thread_args->pv;
     segment = thread_args->segment;
@@ -794,6 +801,8 @@ void yadif_decomb_filter_thread( void *thread_args_v )
             tff = yadif_work->tff;
             w = pv->width[plane];
             h = pv->height[plane];
+            penultimate = h - 2;
+            ultimate = h - 1;
             ref_stride = pv->ref_stride[plane];
             segment_start = ( h / pv->cpu_count ) * segment;
             if( segment == pv->cpu_count - 1 )
@@ -810,6 +819,7 @@ void yadif_decomb_filter_thread( void *thread_args_v )
             {
                 if( ( pv->mode == 4 && is_combed ) || is_combed == 2 )
                 {
+                    /* This line gets blend filtered, not yadif filtered. */
                     uint8_t *prev = &pv->ref[0][plane][y*ref_stride];
                     uint8_t *cur  = &pv->ref[1][plane][y*ref_stride];
                     uint8_t *next = &pv->ref[2][plane][y*ref_stride];
@@ -817,14 +827,59 @@ void yadif_decomb_filter_thread( void *thread_args_v )
 
                     blend_filter_line( dst2, cur, plane, y, pv );
                 }
-                else if( (y ^ parity) & 1 && is_combed == 1 )
+                else if( ( ( y ^ parity ) &  1 )  && ( is_combed == 1 ) )
                 {
-                    uint8_t *prev = &pv->ref[0][plane][y*ref_stride];
-                    uint8_t *cur  = &pv->ref[1][plane][y*ref_stride];
-                    uint8_t *next = &pv->ref[2][plane][y*ref_stride];
-                    uint8_t *dst2 = &dst[plane][y*w];
-
-                    yadif_filter_line( dst2, prev, cur, next, plane, parity ^ tff, y, pv );
+                    /* This line gets yadif filtered. It is the bottom field
+                       when TFF and vice-versa. It's the field that gets
+                       filtered. Because yadif needs 2 lines above and below
+                       the one being filtered, we need to mirror the edges.
+                       When TFF, this means replacing the 2nd line with a
+                       copy of the 1st, and the last with the second-to-last. */
+                    if( y > 1 && y < ( h -2 ) )
+                    {
+                        /* This isn't the top or bottom, proceed as normal to yadif. */
+                        uint8_t *prev = &pv->ref[0][plane][y*ref_stride];
+                        uint8_t *cur  = &pv->ref[1][plane][y*ref_stride];
+                        uint8_t *next = &pv->ref[2][plane][y*ref_stride];
+                        uint8_t *dst2 = &dst[plane][y*w];
+
+                        yadif_filter_line( dst2, 
+                                           prev, 
+                                           cur, 
+                                           next, 
+                                           plane, 
+                                           parity ^ tff,
+                                           y, 
+                                           pv );
+                    }
+                    else if( y == 0 )
+                    {
+                        /* BFF, so y0 = y1 */
+                        memcpy( &dst[plane][y*w],
+                                &pv->ref[1][plane][1*ref_stride],
+                                w * sizeof(uint8_t) );
+                    }
+                    else if( y == 1 )
+                    {
+                        /* TFF, so y1 = y0 */
+                        memcpy( &dst[plane][y*w],
+                                &pv->ref[1][plane][0],
+                                w * sizeof(uint8_t) );
+                    }
+                    else if( y == penultimate )
+                    {
+                        /* BFF, so penultimate y = ultimate y */
+                        memcpy( &dst[plane][y*w],
+                                &pv->ref[1][plane][ultimate*ref_stride],
+                                w * sizeof(uint8_t) );
+                    }
+                    else if( y == ultimate )
+                    {
+                        /* TFF, so ultimate y = penultimate y */
+                        memcpy( &dst[plane][y*w],
+                                &pv->ref[1][plane][penultimate*ref_stride],
+                                w * sizeof(uint8_t) );
+                    }
                 }
                 else
                 {
index 7283634285630b4f1a259fd45cf346dc4bd8de8c..9e4c33eb4551531cc4448f60fdb1e02070ea43a5 100644 (file)
@@ -216,7 +216,7 @@ void yadif_filter_thread( void *thread_args_v )
     int segment, segment_start, segment_stop;
     yadif_thread_arg_t *thread_args = thread_args_v;
     uint8_t **dst;
-    int parity, tff, y, w, h, ref_stride;
+    int parity, tff, y, w, h, ref_stride, penultimate, ultimate;
 
 
     pv = thread_args->pv;
@@ -261,6 +261,8 @@ void yadif_filter_thread( void *thread_args_v )
             tff = yadif_work->tff;
             w = pv->width[plane];
             h = pv->height[plane];
+            penultimate = h -2;
+            ultimate = h - 1;
             ref_stride = pv->yadif_ref_stride[plane];
             segment_start = ( h / pv->cpu_count ) * segment;
             if( segment == pv->cpu_count - 1 )
@@ -275,24 +277,62 @@ void yadif_filter_thread( void *thread_args_v )
 
             for( y = segment_start; y < segment_stop; y++ )
             {
-                if( (y ^ parity) &  1 )
+                if( ( ( y ^ parity ) &  1 ) )
                 {
-                    uint8_t *prev = &pv->yadif_ref[0][plane][y*ref_stride];
-                    uint8_t *cur  = &pv->yadif_ref[1][plane][y*ref_stride];
-                    uint8_t *next = &pv->yadif_ref[2][plane][y*ref_stride];
-                    uint8_t *dst2 = &dst[plane][y*w];
-                    
-                    yadif_filter_line( dst2, 
-                                       prev, 
-                                       cur, 
-                                       next, 
-                                       plane, 
-                                       parity ^ tff, 
-                                       pv );
-                    
+                    /* This is the bottom field when TFF and vice-versa.
+                       It's the field that gets filtered. Because yadif
+                       needs 2 lines above and below the one being filtered,
+                       we need to mirror the edges. When TFF, this means
+                       replacing the 2nd line with a copy of the 1st,
+                       and the last with the second-to-last.                  */
+                    if( y > 1 && y < ( h -2 ) )
+                    {
+                        /* This isn't the top or bottom, proceed as normal to yadif. */
+                        uint8_t *prev = &pv->yadif_ref[0][plane][y*ref_stride];
+                        uint8_t *cur  = &pv->yadif_ref[1][plane][y*ref_stride];
+                        uint8_t *next = &pv->yadif_ref[2][plane][y*ref_stride];
+                        uint8_t *dst2 = &dst[plane][y*w];
+
+                        yadif_filter_line( dst2, 
+                                           prev, 
+                                           cur, 
+                                           next, 
+                                           plane, 
+                                           parity ^ tff, 
+                                           pv );
+                    }
+                    else if( y == 0 )
+                    {
+                        /* BFF, so y0 = y1 */
+                        memcpy( &dst[plane][y*w],
+                                &pv->yadif_ref[1][plane][1*ref_stride],
+                                w * sizeof(uint8_t) );
+                    }
+                    else if( y == 1 )
+                    {
+                        /* TFF, so y1 = y0 */
+                        memcpy( &dst[plane][y*w],
+                                &pv->yadif_ref[1][plane][0],
+                                w * sizeof(uint8_t) );
+                    }
+                    else if( y == penultimate )
+                    {
+                        /* BFF, so penultimate y = ultimate y */
+                        memcpy( &dst[plane][y*w],
+                                &pv->yadif_ref[1][plane][ultimate*ref_stride],
+                                w * sizeof(uint8_t) );
+                    }
+                    else if( y == ultimate )
+                    {
+                        /* TFF, so ultimate y = penultimate y */
+                        memcpy( &dst[plane][y*w],
+                                &pv->yadif_ref[1][plane][penultimate*ref_stride],
+                                w * sizeof(uint8_t) );
+                    }
                 }
                 else
                 {
+                    /* Preserve this field unfiltered */
                     memcpy( &dst[plane][y*w],
                             &pv->yadif_ref[1][plane][y*ref_stride],
                             w * sizeof(uint8_t) );