rendered paste bodyIndex: test/test.c===================================================================--- test/test.c (revision 1336)+++ test/test.c (working copy)@@ -300,6 +300,13 @@ 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 )@@ -725,6 +732,13 @@ { job->pixel_ratio = pixelratio; }+ + if (vfr)+ {+ detelecine = 1;+ job->vfr = 1;+ }+ /* Add selected filters */ job->filters = hb_list_init(); if( detelecine )@@ -926,9 +940,6 @@ if (maxHeight) job->maxHeight = maxHeight; - if (vfr)- job->vfr = 1;- if( subtitle_force ) { job->subtitle_force = subtitle_force;@@ -1626,6 +1637,7 @@ { int i; char * tmp = optarg;+// fprintf(stderr, "cropping string is: %s", tmp); for( i = 0; i < 4; i++ ) { if( !*tmp )@@ -1634,7 +1646,14 @@ tmp++; } break;- }+ +/* sscanf( optarg, "%d:%d:%d:%d",+ &crop[0],+ &crop[1],+ &crop[2],+ &crop[3]);+ break;+*/ } case 'r': { int i;Index: libhb/detelecine.c===================================================================--- libhb/detelecine.c (revision 1336)+++ libhb/detelecine.c (working copy)@@ -1027,7 +1027,9 @@ pv->width[1] * pv->height[1] * sizeof(uint8_t) ); memcpy( pv->pic_out.data[2], frame->buffer->planes[2], pv->width[2] * pv->height[2] * sizeof(uint8_t) );-+ + pv->buf_out->length = frame->length;+ pullup_release_frame( frame ); output_frame:Index: libhb/hb.c===================================================================--- libhb/hb.c (revision 1336)+++ libhb/hb.c (working copy)@@ -426,6 +426,115 @@ avpicture_free( &pic_in ); } + /**+ * 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 color_equal, int color_diff, int threshold)+{+ int j, k, n, off, block, cc_1, cc_2, cc[3], flag[3];+ uint16_t s1, s2, s3, s4;+ 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;+ if( buf->telecined )+ {+ return 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[k] = (int)((cc_1 + cc_2)*1000.0/(width*height));+ + /* If the plane's cc score meets the threshold, flag it as combed. */+ flag[k] = 0;+ if(cc[k] > thres)+ {+ flag[k] = 1;+ }+ }+ +#if 0+/* Debugging info */+// if(flag)+ 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] )+ {+ return 1;+ }++ return 0;+}++ /** * Calculates job width and height for anamorphic content, *Index: libhb/hb.h===================================================================--- libhb/hb.h (revision 1336)+++ 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, int color_equal, int color_diff, int threshold);+#define COLOR_EQUAL 10 // Sensitivity for detecting similar colors.+#define COLOR_DIFF 30 // Sensitivity for detecting different colors+#define THRESHOLD 9 // 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/render.c===================================================================--- libhb/render.c (revision 1336)+++ libhb/render.c (working copy)@@ -29,6 +29,7 @@ uint64_t total_gained_time; int64_t chapter_time; int chapter_val;+ int last_frame_length; }; int renderInit( hb_work_object_t *, hb_job_t * );@@ -282,6 +283,14 @@ if( result == FILTER_OK ) { buf_tmp_in = buf_tmp_out;+ if (buf_tmp_in->length == 3 || pv->last_frame_length == 3)+ {+ buf_tmp_in->telecined = 1;+ }+ else+ {+ buf_tmp_in->telecined = 0;+ } } else if( result == FILTER_DELAY ) {@@ -420,7 +429,10 @@ /* The current frame exists. That means it hasn't been dropped by a filter. Make it accessible as ivtc_buffer so we can edit its duration if needed. */ ivtc_buffer = *buf_out;+ + pv->last_frame_length = ivtc_buffer->length; + //hb_log("frame length: %i", ivtc_buffer->length); if( pv->lost_time[3] > 0 ) { /*@@ -562,6 +574,8 @@ pv->lost_time[0] = 0; pv->lost_time[1] = 0; pv->lost_time[2] = 0; pv->lost_time[3] = 0; pv->chapter_time = 0; pv->chapter_val = 0;+ + pv->last_frame_length = 0; /* Setup filters */ /* TODO: Move to work.c? */Index: libhb/deinterlace.c===================================================================--- libhb/deinterlace.c (revision 1336)+++ 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,12 +562,29 @@ 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++; - *buf_out = pv->buf_out[0];+ 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;+ + } return FILTER_OK; }@@ -545,6 +603,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 +621,48 @@ 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/internal.h===================================================================--- libhb/internal.h (revision 1336)+++ libhb/internal.h (working copy)@@ -54,7 +54,9 @@ #define HB_FRAME_REF 0xF0 uint8_t frametype; uint16_t flags;-+ int length;+ int telecined;+ /* Holds the output PTS from x264, for use by b-frame offsets in muxmp4.c */ int64_t renderOffset; Index: libhb/fifo.c===================================================================--- libhb/fifo.c (revision 1336)+++ libhb/fifo.c (working copy)@@ -321,6 +321,8 @@ dst->new_chap = src->new_chap; dst->frametype = src->frametype; dst->flags = src->flags;+ dst->length = src->length;+ dst->telecined = src->telecined; } hb_fifo_t * hb_fifo_init( int capacity )Index: libhb/scan.c===================================================================--- libhb/scan.c (revision 1336)+++ libhb/scan.c (working copy)@@ -286,6 +286,8 @@ hb_list_t * list_es, * list_raw; hb_libmpeg2_t * mpeg2; int progressive_count = 0;+ int interlacing[10];+ int ar16_count = 0, ar4_count = 0; buf_ps = hb_buffer_init( HB_DVD_READ_BUFFER_SIZE );@@ -419,7 +421,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; }@@ -449,7 +451,19 @@ } buf_raw = hb_list_item( list_raw, 0 );-+ + /* Check preview for interlacing artifacts */+ if( hb_detect_comb(buf_raw, title->width, title->height, 10, 30, 9) )+ {+ 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 ); @@ -522,7 +536,28 @@ (float) title->rate_base, title->crop[0], title->crop[1], title->crop[2], title->crop[3], title->aspect == HB_ASPECT_BASE * 16 / 9 ? "16:9" :- title->aspect == HB_ASPECT_BASE * 4 / 3 ? "4:3" : "none" );+ title->aspect == HB_ASPECT_BASE * 4 / 3 ? "4:3" : "none" );++ /* 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;+ }+ goto cleanup; error:Index: libhb/common.h===================================================================--- libhb/common.h (revision 1336)+++ libhb/common.h (working copy)@@ -426,6 +426,7 @@ int rate; int rate_base; int crop[4];+ int detected_interlacing; uint32_t palette[16];