X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fdecomb.c;h=4c0f42c179b18fb41307b7f24033a7b0ca6c4398;hb=f9341345b37e0738a140423297c222a7e40eddab;hp=604945819c9109cbf9e9012317b8ff5e2000bf42;hpb=7ae03186d14ac6b7c365f3f767c1052963625f50;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/decomb.c b/libhb/decomb.c index 60494581..4c0f42c1 100644 --- a/libhb/decomb.c +++ b/libhb/decomb.c @@ -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 )