rendered paste bodyIndex: test/test.c===================================================================--- test/test.c (revision 1306)+++ test/test.c (working copy)@@ -300,6 +300,12 @@ fprintf( stderr, " + %d, %s (iso639-2: %s)\n", i + 1, subtitle->lang, subtitle->iso639_2); }+ + if(title->detected_interlacing)+ {+ /* Interlacing was found in 6 or more preview frames */+ fprintf( stderr, " + interlacing artifacts detected\n");+ } } static int HandleEvents( hb_handle_t * h )Index: libhb/hb.c===================================================================--- libhb/hb.c (revision 1306)+++ libhb/hb.c (working copy)@@ -427,6 +427,109 @@ } /**+ * 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)+{+ 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;+ + /* These values are defined in hb.h */+ int thres = THRESHOLD;+ int eq = COLOR_EQUAL;+ int diff = COLOR_DIFF;+ + int offset = 0;+ + flag = 0;++ for(k=0; k < 3; k++)+ {+ /* One pas for Y, one pass for Cb, one pass for Cr */+ if( k == 1 )+ {+ /* Y has already been checked, now offset by Y's dimensions+ and divide all the other values by 2, since Cr and Cb+ are half-size compared to Y. */+ offset = width * height;+ width >>= 1;+ height >>= 1;+ thres >>= 1;+ eq >>= 1;+ diff >>= 1;+ }+ else if (k == 2 )+ {+ /* Y and Cb are done, so the offset needs to be bumped+ so it's width*height + (width / 2) * (height / 2) */+ offset *= 5/4;+ }+ + /* Look at one horizontal line at a time */+ block = width;+ + for(j=0; j<block; ++j)+ {+ off=0;+ + for(n=0; n<(height-4); n=n+2)+ {+ /* Look at groups of 4 sequential horizontal lines */+ s1 = ((buf->data+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);+ + /* Note if the 1st and 2nd lines are more different in+ color than the 1st and 3rd lines are similar in color.*/+ if((abs(s1 - s3) < eq) &&+ (abs(s1 - s2) > diff)) ++cc_1;+ + /* Note if the 2nd and 3rd lines are more different in+ color than the 2nd and 4th lines are similar in color.*/+ if((abs(s2 - s4) < eq) &&+ (abs(s2 - s3) > diff)) ++cc_2;+ + /* Now move down 2 horizontal lines before starting over.*/+ off +=2*block;+ }+ }+ + // compare results+ /* The final metric seems to be doing some kind of bits per pixel style calculation+ to decide whether or not enough lines showed alternating colors for the frame size. */+ cc = (int)((cc_1 + cc_2)*1000.0/(width*height));+ + /* But only really flag the plane as showing interlacing when it exceeds a threshold parameter.*/+ flag += (cc > thres) ? 1:0;+ }++#if 0+/* Debugging info */+ 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);+#endif+ + /* When more than one plane shows combing, tell the caller. */+ if (flag > 1)+ {+ return 1;+ }++ return 0;+}+++/** * Calculates job width and height for anamorphic content, * * @param job Handle to hb_job_tIndex: libhb/hb.h===================================================================--- libhb/hb.h (revision 1306)+++ 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 // Sensitivity for detecting similar colors.+#define COLOR_DIFF 30 // Sensitivity for detecting different colors+#define THRESHOLD 2 // Sensitivity for flagging planes as combed+ void hb_get_preview( hb_handle_t *, hb_title_t *, int, uint8_t * ); void hb_set_size( hb_job_t *, int ratio, int pixels );Index: libhb/deinterlace.c===================================================================--- libhb/deinterlace.c (revision 1306)+++ 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, @@ -521,12 +542,30 @@ avpicture_fill( &pv->pic_out, pv->buf_out[0]->data, pix_fmt, width, height ); - avpicture_deinterlace( &pv->pic_out, &pv->pic_in, + /* Check for coming on the input frame */+ int interlaced = ( hb_detect_comb(buf_in, width, height) );++ if( interlaced )+ {+ /* Combing detected, deinterlace this frame. */+#if 0+ hb_log("found combing! %i", interlaced);+#endif + 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+ {+ /* No combing detected, pass input frame through unmolested.*/+ hb_buffer_copy_settings( pv->buf_out[0], buf_in );++ *buf_out = buf_in;+ } return FILTER_OK; }@@ -545,56 +584,73 @@ /* 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) | hb_detect_comb(buf_in, width, height);+ /* If yadif is not ready, store another ref and return FILTER_DELAY */ if( pv->yadif_ready == 0 ) { 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;- - 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 )+ /* 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 */+#if 0+ hb_log("combing detected, passing to yadif");+#endif + 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/scan.c===================================================================--- libhb/scan.c (revision 1306)+++ libhb/scan.c (working copy)@@ -286,6 +286,7 @@ hb_list_t * list_es, * list_raw; hb_libmpeg2_t * mpeg2; int progressive_count = 0;+ int interlacing[10]; buf_ps = hb_buffer_init( HB_DVD_READ_BUFFER_SIZE ); list_es = hb_list_init();@@ -407,7 +408,7 @@ */ if( progressive_count == 6 ) {- hb_log("Title's mostly progressive NTSC, setting fps to 23.976");+ hb_log("Title's mostly NTSC Film, setting fps to 23.976"); } title->rate_base = 1126125; }@@ -440,7 +441,18 @@ } buf_raw = hb_list_item( list_raw, 0 );-+ + /* Check preview for interlacing artifacts */+ if( hb_detect_comb(buf_raw, title->width, title->height))+ {+ hb_log("Interlacing detected in preview frame %i", i);+ interlacing[i] = 1;+ }+ else+ {+ interlacing[i] = 0;+ }+ hb_get_tempory_filename( data->h, filename, "%x%d", (intptr_t)title, i ); @@ -493,7 +505,7 @@ break; } }-+ skip_preview: while( ( buf_raw = hb_list_item( list_raw, 0 ) ) ) {@@ -506,12 +518,32 @@ title->crop[1] = EVEN( title->crop[1] ); title->crop[2] = EVEN( title->crop[2] ); title->crop[3] = EVEN( title->crop[3] );-+ hb_log( "scan: %dx%d, %.3f fps, autocrop = %d/%d/%d/%d", title->width, title->height, (float) title->rate / (float) title->rate_base, title->crop[0], title->crop[1], title->crop[2], title->crop[3] );+ + /* Add up how many previews were interlaced.*/+ int interlacing_sum, t;+ for(t = 0; t < 10; t++ )+ {+ if( interlacing[t] == 1 )+ {+ interlacing_sum++;+ }+ } + if( interlacing_sum >= 6)+ {+ hb_log("Title is mostly interlaced or telecined (%i out of 10 previews). You should do something about that.", interlacing_sum);+ title->detected_interlacing = 1;+ }+ else+ {+ title->detected_interlacing = 0;+ }+ ret = 1; goto cleanup; Index: libhb/common.h===================================================================--- libhb/common.h (revision 1306)+++ libhb/common.h (working copy)@@ -435,6 +435,8 @@ /* Job template for this title */ hb_job_t * job;+ + int detected_interlacing; };