OSDN Git Service

x264 bump to r1101
[handbrake-jp/handbrake-jp-git.git] / libhb / decomb.c
index 6049458..4c0f42c 100644 (file)
@@ -6,7 +6,7 @@
    
    The yadif algorithm was created by Michael Niedermayer. */
 #include "hb.h"
-#include "libavcodec/avcodec.h"
+#include "hbffmpeg.h"
 #include "mpeg2dec/mpeg2.h"
 
 #define SUPPRESS_AV_LOG
@@ -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;
@@ -1125,7 +1179,7 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt,
         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;
+        pv->mask[i] = calloc( 1, w*h*sizeof(uint8_t) ) + 3*w;
     }
 
      /*
@@ -1255,7 +1309,7 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt,
                     avctx_enc->flags |= CODEC_FLAG_QPEL;
             }
 
-            avcodec_open(avctx_enc, enc);
+            hb_avcodec_open(avctx_enc, enc);
         }
 
         pv->mcdeint_frame       = avcodec_alloc_frame();
@@ -1359,7 +1413,7 @@ void hb_decomb_close( hb_filter_private_t * pv )
     {
         if( pv->mcdeint_avctx_enc )
         {
-            avcodec_close( pv->mcdeint_avctx_enc );
+            hb_avcodec_close( pv->mcdeint_avctx_enc );
             av_freep( &pv->mcdeint_avctx_enc );
         }
         if( pv->mcdeint_outbuf )