Index: libhb/deinterlace.c =================================================================== --- libhb/deinterlace.c (revision 1397) +++ libhb/deinterlace.c (working copy) @@ -42,6 +42,14 @@ int yadif_parity; int yadif_ready; + int comb; + int comb_detect; + int color_equal; + int color_diff; + int threshold; + int deinterlaced_frames; + int passed_frames; + uint8_t * yadif_ref[4][3]; int yadif_ref_stride[3]; @@ -115,6 +123,26 @@ } } +static void yadif_get_ref( uint8_t ** pic, hb_filter_private_t * pv, int frm ) +{ + int i; + for( i = 0; i < 3; i++ ) + { + uint8_t * dst = pic[i]; + const uint8_t * ref = pv->yadif_ref[frm][i]; + int w = pv->width[i]; + int ref_stride = pv->yadif_ref_stride[i]; + + int y; + for( y = 0; y < pv->height[i]; y++ ) + { + memcpy(dst, ref, w); + dst += w; + ref += ref_stride; + } + } +} + static void yadif_filter_line( uint8_t *dst, uint8_t *prev, uint8_t *cur, @@ -356,6 +384,13 @@ 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->comb_detect = 0; + pv->color_equal = 10; + pv->color_diff = 30; + pv->threshold = 9; + pv->yadif_ready = 0; pv->yadif_mode = YADIF_MODE_DEFAULT; pv->yadif_parity = YADIF_PARITY_DEFAULT; @@ -365,11 +400,15 @@ if( settings ) { - sscanf( settings, "%d:%d:%d:%d", + sscanf( settings, "%d:%d:%d:%d:%d:%d:%d:%d", &pv->yadif_mode, &pv->yadif_parity, &pv->mcdeint_mode, - &pv->mcdeint_qp ); + &pv->mcdeint_qp, + &pv->comb_detect, + &pv->color_equal, + &pv->color_diff, + &pv->threshold ); } /* Allocate yadif specific buffers */ @@ -451,6 +490,8 @@ return; } + hb_log("deinterlacer: filtered %i | unfiltered %i | total %i", pv->deinterlaced_frames, pv->passed_frames, pv->deinterlaced_frames + pv->passed_frames); + /* Cleanup frame buffers */ if( pv->buf_out[0] ) { @@ -521,13 +562,31 @@ avpicture_fill( &pv->pic_out, pv->buf_out[0]->data, pix_fmt, width, height ); - avpicture_deinterlace( &pv->pic_out, &pv->pic_in, - pix_fmt, width, height ); + /* Check for combing on the input frame */ + int interlaced = pv->comb_detect ? ( hb_detect_comb(buf_in, width, height, pv->color_equal, pv->color_diff, pv->threshold)) : 1; + + if(interlaced) + { + avpicture_deinterlace( &pv->pic_out, &pv->pic_in, + pix_fmt, width, height ); - hb_buffer_copy_settings( pv->buf_out[0], buf_in ); + 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; + + } - *buf_out = pv->buf_out[0]; - return FILTER_OK; } @@ -545,6 +604,9 @@ /* Store current frame in yadif cache */ yadif_store_ref( (const uint8_t**)pv->pic_in.data, pv ); + /* Note down if the input frame is combed */ + pv->comb = (pv->comb << 1) | ( pv->comb_detect? hb_detect_comb(buf_in, width, height, pv->color_equal, pv->color_diff, pv->threshold) : 1); + /* If yadif is not ready, store another ref and return FILTER_DELAY */ if( pv->yadif_ready == 0 ) { @@ -560,30 +622,47 @@ return FILTER_DELAY; } - /* Perform yadif and mcdeint filtering */ - int frame; - for( frame = 0; frame <= (pv->yadif_mode & 1); frame++ ) + /* yadif & mcdeint work one frame behind so if the previous frame + * had combing, deinterlace it otherwise just output it. */ + if( (pv->comb & 2 ) == 0 ) { - int parity = frame ^ tff ^ 1; + /* 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 ); + yadif_get_ref( (uint8_t**)pv->pic_out.data, pv, 1 ); + *buf_out = pv->buf_out[0]; + } + else + { + /* Perform yadif and mcdeint filtering */ + + pv->deinterlaced_frames++; + int frame; + for( frame = 0; frame <= (pv->yadif_mode & 1); frame++ ) + { + int parity = frame ^ tff ^ 1; - avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data, - pix_fmt, width, height ); - - yadif_filter( pv->pic_out.data, parity, tff, pv ); - - if( pv->mcdeint_mode >= 0 ) - { - avpicture_fill( &pv->pic_in, pv->buf_out[(frame^1)]->data, + avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data, pix_fmt, width, height ); - mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv ); + yadif_filter( pv->pic_out.data, parity, tff, pv ); - *buf_out = pv->buf_out[ (frame^1)]; + if( pv->mcdeint_mode >= 0 ) + { + 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 + { + *buf_out = pv->buf_out[!(frame^1)]; + } } - else - { - *buf_out = pv->buf_out[!(frame^1)]; - } } /* Copy buffered settings to output buffer settings */ Index: libhb/hb.c =================================================================== --- libhb/hb.c (revision 1397) +++ libhb/hb.c (working copy) @@ -518,22 +518,29 @@ flag[k] = 0; if ( cc[k] > threshold ) { +// hb_log("Threhold %i: %i/%i | PTS: %lld (%fs)", k, cc[k], threshold, buf->start, (float)buf->start / 90000 ); flag[k] = 1; } } #if 0 /* Debugging info */ -// if(flag) + if(flag[0] || flag[1] || flag[2]) hb_log("flags: %i/%i/%i | cc0: %i | cc1: %i | cc2: %i", flag[0], flag[1], flag[2], cc[0], cc[1], cc[2]); #endif - /* When more than one plane shows combing, tell the caller. */ - if (flag[0] || flag[1] || flag[2] ) + /* For progressive frames, require the luma and one chroma plane to show combing. */ + if( (buf->flags & 16) && flag[0] && ( flag[1] || flag[2] ) ) { return 1; } + /* For video frames, when more than one plane shows combing, tell the caller. */ + if ( !(buf->flags & 16) && (flag[0] || flag[1] || flag[2]) ) + { + return 1; + } + return 0; }