Index: libhb/decomb.c =================================================================== --- libhb/decomb.c (revision 1474) +++ libhb/decomb.c (working copy) @@ -230,6 +230,205 @@ } } +int tritical_detect_comb( hb_filter_private_t * pv ) +{ + int x, y, i, j, k; + + /* Motion threshold */ + int mthresh = 6; + /* Spatial threshold */ + int athresh = 15; + /* Block mask threshold -- The number of pixels + in a 4x8 block of the mask that need to show + combing for the whole frame to be seen as such. */ + int threshold = 15; + + int color_equal = 10; + int color_diff = 15; + + /* Make a buffer to store a comb mask. */ + uint8_t * mask[3]; + for( i = 0; i < 3; i++ ) + { + int is_chroma = !!i; + int w = ((pv->width[0] + 31) & (~31))>>is_chroma; + int h = ((pv->height[0]+6+ 31) & (~31))>>is_chroma; + + mask[i] = malloc( w*h*sizeof(uint8_t) ) + 3*w; + } + + /* One pas for Y, one pass for Cb, one pass for Cr */ + for( k = 0; k < 1; k++ ) + { + int ref_stride = pv->ref_stride[k]; + int width = pv->width[k]; + int height = pv->height[k]; + + for( y = 2; y < (height-2); y++ ) + { + /* These are just to make the buffer locations easier to read. */ + int back_2 = y - 2; + int back_1 = y - 1; + int forward_1 = y + 1; + int forward_2 = y + 2; + + /* We need to examine a column of 5 pixels + in the prev, cur, and next frames. */ + uint8_t frame_a[5]; + uint8_t frame_b[5]; + uint8_t frame_c[5]; + + for( x = 0; x < width; x++ ) + { + /* Fill up the frame arrays with the current pixel values.*/ + frame_a[0] = pv->ref[0][k][back_2*ref_stride + x]; + frame_a[1] = pv->ref[0][k][back_1*ref_stride + x]; + frame_a[2] = pv->ref[0][k][y*ref_stride + x]; + frame_a[3] = pv->ref[0][k][forward_1*ref_stride + x]; + frame_a[4] = pv->ref[0][k][forward_2*ref_stride + x]; + frame_b[0] = pv->ref[1][k][back_2*ref_stride + x]; + frame_b[1] = pv->ref[1][k][back_1*ref_stride + x]; + frame_b[2] = pv->ref[1][k][y*ref_stride + x]; + frame_b[3] = pv->ref[1][k][forward_1*ref_stride + x]; + frame_b[4] = pv->ref[1][k][forward_2*ref_stride + x]; + frame_c[0] = pv->ref[2][k][back_2*ref_stride + x]; + frame_c[1] = pv->ref[2][k][back_1*ref_stride + x]; + frame_c[2] = pv->ref[2][k][y*ref_stride + x]; + frame_c[3] = pv->ref[2][k][forward_1*ref_stride + x]; + frame_c[4] = pv->ref[2][k][forward_2*ref_stride + x]; + + /* Make sure there's sufficient motion between frame t-1 to frame t+1. */ + int motion = 0; + if( abs(frame_a[2] - frame_b[2] ) > mthresh && abs(frame_b[1] - frame_c[1] ) > mthresh && abs(frame_b[3] - frame_c[3] ) > mthresh ) + motion++; + if( abs(frame_c[2] - frame_b[2] ) > mthresh && abs(frame_a[1] - frame_b[1] ) > mthresh && abs(frame_a[3] - frame_b[3] ) > mthresh ) + motion++; + +#if 0 + /* Visualizes the pixel values being examined. */ + hb_log("\n PLANE: %i X: %i Y: %i \n %i %i %i \n %i %i %i \n %i %i %i \n %i %i %i \n %i %i %i", k, x, y, + frame_a[0], frame_b[0], frame_c[0], + frame_a[1], frame_b[1], frame_c[1], + frame_a[2], frame_b[2], frame_c[2], + frame_a[3], frame_b[3], frame_c[3], + frame_a[4], frame_b[4], frame_c[4] ); +#endif + if( motion ) + { + /* There is movement in this pixel location. */ + if( ( frame_b[1] - frame_b[2] ) * ( frame_b[3] - frame_b[2] ) > 0 ) + { + /* The pixel above and below are different, + and are so in the same "direction" too. + That means it's time for the spatial check. */ + + /* Simple 32detect style comb detection */ + if( ( abs( frame_b[2] - frame_b[4] ) < color_equal ) && + ( abs( frame_b[2] - frame_b[3] ) > color_diff ) ) + { + mask[k][y*ref_stride + x] = 255; + } + else + { + mask[k][y*ref_stride + x] = 0; + } + +#if 0 + /* The combing check is done on a bob+blur convolution. */ + int combing = abs( frame_b[0] + (4 * frame_b[2] ) + frame_b[4] - (3 * ( frame_b[1] + frame_b[3] ) ) ); + + /* If the frame is sufficiently combed, + then mark it down on the mask as 255. */ + if( combing > 6*athresh ) + mask[k][y*ref_stride + x] = 255; + else + mask[k][y*ref_stride + x] = 0; +#endif + +#if 0 + /* This, for comparison, is what IsCombed uses. + It's simpler, but more noise senstive. */ + int combing = (frame_b[1] - frame_b[2]) * (frame_b[3] - frame_b[2]); + if( combing > 20 ) + mask[k][y*ref_stride + x] = 255; + else + mask[k][y*ref_stride + x] = 0; +#endif + } + else + { + mask[k][y*ref_stride + x] = 0; + } + } + else + { + mask[k][y*ref_stride + x] = 0; + } + } + } + } + + /* Go through the mask in 4x8 blocks. If any of these windows + have threshold or more combed pixels, consider the whole + frame to be combed and send it on to be deinterlaced. */ + int block_score = 0; + for(k = 0; k < 1; k++ ) + { + int ref_stride = pv->ref_stride[k]; + for( y = 0; y < ( pv->height[k] - 8 ); y = y + 8 ) + { + for( x = 0; x < ( pv->width[k] - 4 ); x = x + 4 ) + { + int block_x; + int block_y; + block_score = 0; + for(block_y = 0; block_y < 8; block_y++ ) + { + for(block_x = 0; block_x < 4; block_x++ ) + { + int mask_y = y + block_y; + int mask_x = x + block_x; + + if( mask[k][mask_y*ref_stride+mask_x] == 255 ) + { + block_score++; + } + } + } + + if( block_score >= threshold ) + { + /* Consider this frame to be combed. + Clear the mask buffer and return 1. */ + for( i = 0; i<3*3; i++ ) + { + uint8_t **p = &mask[i/3]; + if (*p) + { + free( *p - 3*pv->ref_stride[i/3] ); + *p = NULL; + } + } + return 1; + } + } + } + } + + /* Consider this frame to be uncombed. + Clear the mask buffer and return 0. */ + for( i = 0; i<3*3; i++ ) + { + uint8_t **p = &mask[i/3]; + if (*p) + { + free( *p - 3*pv->ref_stride[i/3] ); + *p = NULL; + } + } + return 0; +} + static void yadif_filter_line( uint8_t *dst, uint8_t *prev, uint8_t *cur, @@ -376,7 +575,17 @@ int tff, hb_filter_private_t * pv ) { - + + int is_combed = tritical_detect_comb( pv ); + + if(is_combed) + { + pv->deinterlaced_frames++; + } + else + { + pv->passed_frames++; + } #if 0 /* Buggy, experimental code for macroblock-by-macroblock decombing.*/ if( pv->mode == 7 ) @@ -499,7 +708,7 @@ blend_filter_line( dst2, cur, i, y, pv ); } - else if( (y ^ parity) & 1 ) + else if( (y ^ parity) & 1 && is_combed ) { uint8_t *prev = &pv->ref[0][i][y*ref_stride]; uint8_t *cur = &pv->ref[1][i][y*ref_stride]; @@ -850,14 +1059,14 @@ pix_fmt, width, height ); /* Check for combing on the input frame */ - int interlaced = hb_detect_comb(buf_in, width, height, pv->color_equal, pv->color_diff, pv->threshold, pv->prog_equal, pv->prog_diff, pv->prog_threshold); + int interlaced = 1; // hb_detect_comb(buf_in, width, height, pv->color_equal, pv->color_diff, pv->threshold, pv->prog_equal, pv->prog_diff, pv->prog_threshold); if(interlaced) { avpicture_deinterlace( &pv->pic_out, &pv->pic_in, pix_fmt, width, height ); - pv->deinterlaced_frames++; +// 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 ); @@ -867,7 +1076,7 @@ { /* No combing detected, pass input frame through unmolested.*/ - pv->passed_frames++; + // pv->passed_frames++; hb_buffer_copy_settings( pv->buf_out[0], buf_in ); *buf_out = buf_in; @@ -894,7 +1103,7 @@ if( pv->mode < 7 ) { /* Note down if the input frame is combed */ - pv->comb = (pv->comb << 1) | hb_detect_comb(buf_in, width, height, pv->color_equal, pv->color_diff, pv->threshold, pv->prog_equal, pv->prog_diff, pv->prog_threshold); + pv->comb = (pv->comb << 1) | 1; //hb_detect_comb(buf_in, width, height, pv->color_equal, pv->color_diff, pv->threshold, pv->prog_equal, pv->prog_diff, pv->prog_threshold); } /* If yadif is not ready, store another ref and return FILTER_DELAY */ @@ -918,7 +1127,7 @@ { /* Perform yadif filtering */ - pv->deinterlaced_frames++; +// pv->deinterlaced_frames++; int frame; for( frame = 0; frame <= ( ( pv->mode == 2 || pv->mode == 5 )? 1 : 0 ) ; frame++ ) { @@ -955,7 +1164,7 @@ { /* Perform yadif filtering */ - pv->deinterlaced_frames++; +// pv->deinterlaced_frames++; int frame; for( frame = 0; frame <= ( ( pv->mode == 2 || pv->mode == 5 )? 1 : 0 ) ; frame++ ) {