Index: libhb/deinterlace.c =================================================================== --- libhb/deinterlace.c (revision 1252) +++ libhb/deinterlace.c (working copy) @@ -41,6 +41,7 @@ int yadif_mode; int yadif_parity; int yadif_ready; + int comb; uint8_t * yadif_ref[4][3]; int yadif_ref_stride[3]; @@ -115,6 +116,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, @@ -520,13 +541,28 @@ { avpicture_fill( &pv->pic_out, pv->buf_out[0]->data, pix_fmt, width, height ); - - avpicture_deinterlace( &pv->pic_out, &pv->pic_in, + + int interlaced = ( hb_detect_comb(buf_in, width, height) ); + + if( interlaced ) + { +// hb_log("found combing! %i", interlaced); + + avpicture_deinterlace( &pv->pic_out, &pv->pic_in, pix_fmt, width, height ); - - hb_buffer_copy_settings( pv->buf_out[0], buf_in ); + + hb_buffer_copy_settings( pv->buf_out[0], buf_in ); + + *buf_out = pv->buf_out[0]; - *buf_out = pv->buf_out[0]; + } + else + { + + hb_buffer_copy_settings( pv->buf_out[0], buf_in ); + + *buf_out = buf_in; + } return FILTER_OK; } @@ -544,6 +580,7 @@ /* Store current frame in yadif cache */ yadif_store_ref( (const uint8_t**)pv->pic_in.data, pv ); + pv->comb = (pv->comb << 1) | hb_detect_comb(buf_in, width, height); /* If yadif is not ready, store another ref and return FILTER_DELAY */ if( pv->yadif_ready == 0 ) @@ -551,50 +588,63 @@ yadif_store_ref( (const uint8_t**)pv->pic_in.data, pv ); hb_buffer_copy_settings( pv->buf_settings, buf_in ); - - /* don't let 'work_loop' send a chapter mark upstream */ - buf_in->new_chap = 0; + /* don't let 'work_loop' send a chapter mark upstream */ + buf_in->new_chap = 0; + pv->yadif_ready = 1; 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 */ + 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 */ +// hb_log("combing detected, passing to yadif"); - 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 ) + int frame; + for( frame = 0; frame <= (pv->yadif_mode & 1); frame++ ) { - avpicture_fill( &pv->pic_in, pv->buf_out[(frame^1)]->data, + int parity = frame ^ tff ^ 1; + + 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 ); - - *buf_out = pv->buf_out[ (frame^1)]; + + 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, + 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 */ hb_buffer_copy_settings( *buf_out, pv->buf_settings ); /* Replace buffered settings with input buffer settings */ hb_buffer_copy_settings( pv->buf_settings, buf_in ); - - /* don't let 'work_loop' send a chapter mark upstream */ - buf_in->new_chap = 0; + /* don't let 'work_loop' send a chapter mark upstream */ + buf_in->new_chap = 0; + return FILTER_OK; } Index: libhb/hb.c =================================================================== --- libhb/hb.c (revision 1252) +++ libhb/hb.c (working copy) @@ -427,6 +427,88 @@ } /** + * Analyzes a frame to detect interlacing artifacts + * and returns true if interlacing (combing) is found. + * + * Code taken from Thomas Oestreich's 32detect filter + * in the Transcode project, with minor formatting changes. + * + * @param buf An hb_buffer structure holding valid frame data. + * @param width The frame's width in pixels. + * @param height The frame's height in pixels. + */ +int hb_detect_comb( hb_buffer_t * buf, int width, int height) +{ + /* See if frame shows interlacing */ + int j, k, n, off, block, cc_1, cc_2, cc, flag; + uint16_t s1, s2, s3, s4; + cc = 0; cc_1 = 0; cc_2 = 0; + + int thres = THRESHOLD; + int eq = COLOR_EQUAL; + int diff = COLOR_DIFF; + + int offset = 0; + + flag = 0; + + for(k=0; k < 3; k++) + { + if( k == 1 ) + { + offset = width * height; + width >>= 1; + height >>= 1; + thres >>= 1; + eq >>= 1; + diff >>= 1; + } + else if (k == 2 ) + { + offset *= 5/4; + } + + block = width; + + for(j=0; jdata+offset)[off+j ] & 0xff); + s2 = ((buf->data+offset)[off+j+ block] & 0xff); + s3 = ((buf->data+offset)[off+j+2*block] & 0xff); + s4 = ((buf->data+offset)[off+j+3*block] & 0xff); + + if((abs(s1 - s3) < eq) && + (abs(s1 - s2) > diff)) ++cc_1; + + if((abs(s2 - s4) < eq) && + (abs(s2 - s3) > diff)) ++cc_2; + + off +=2*block; + } + } + + // compare results + + cc = (int)((cc_1 + cc_2)*1000.0/(width*height)); + + flag += (cc > thres) ? 1:0; + } + + if(flag) +// hb_log("flag: %i | cc: %f | cc1: %i | cc2: %i", flag, (float)((cc_1 + cc_2)*1000.0/(width*height)), cc_1, cc_2); + + if (flag > 1) + return 1; + else + return 0; +} + + +/** * Calculates job width and height for anamorphic content, * * @param job Handle to hb_job_t Index: libhb/hb.h =================================================================== --- libhb/hb.h (revision 1252) +++ libhb/hb.h (working copy) @@ -75,6 +75,14 @@ Returns the list of valid titles detected by the latest scan. */ hb_list_t * hb_get_titles( hb_handle_t * ); +/* hb_detect_comb() + Analyze a frame for interlacing artifacts, returns true if they're found. + Taken from Thomas Oestreich's 32detect filter in the Transcode project. */ +int hb_detect_comb( hb_buffer_t * buf, int width, int height); +#define COLOR_EQUAL 10 +#define COLOR_DIFF 30 +#define THRESHOLD 2 + void hb_get_preview( hb_handle_t *, hb_title_t *, int, uint8_t * ); void hb_set_size( hb_job_t *, int ratio, int pixels );