OSDN Git Service

LinGui: fix me_method/me_range dependency
[handbrake-jp/handbrake-jp-git.git] / libhb / decomb.c
index df1838a..2194f56 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
                 {
@@ -1058,9 +1113,8 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt,
     pv->width[1]  = pv->width[2]  = width >> 1;
     pv->height[1] = pv->height[2] = height >> 1;
 
-    int buf_size = 3 * width * height / 2;
-    pv->buf_out[0] = hb_buffer_init( buf_size );
-    pv->buf_out[1] = hb_buffer_init( buf_size );
+    pv->buf_out[0] = hb_video_buffer_init( width, height );
+    pv->buf_out[1] = hb_video_buffer_init( width, height );
     pv->buf_settings = hb_buffer_init( 0 );
 
     pv->yadif_deinterlaced_frames = 0;