summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjbrjake <[email protected]>2008-07-11 21:59:15 +0000
committerjbrjake <[email protected]>2008-07-11 21:59:15 +0000
commit4ac57457da4b980f1e49a1cf8905be0917648d9f (patch)
treebb822276bd2e9a29767e4e68cb0b57abf2e8a154
parent88fa043fa37a190b8fb9258698e03e166318016c (diff)
Much improved decomb filter. Totally different algorithm, with a temporal element, a block window, and a simple weighting decision for which deinterlacer to use. See code comments.
The code isn't well optimized yet, and would probably benefit from -O3 (as opposed to the -Os optimization level currently used in macosx builds). git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1566 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r--libhb/decomb.c643
-rw-r--r--macosx/Controller.mm2
-rw-r--r--test/test.c2
3 files changed, 354 insertions, 293 deletions
diff --git a/libhb/decomb.c b/libhb/decomb.c
index e29f253e6..1b18328d4 100644
--- a/libhb/decomb.c
+++ b/libhb/decomb.c
@@ -11,7 +11,7 @@
#define SUPPRESS_AV_LOG
-#define MODE_DEFAULT 4
+#define MODE_DEFAULT 1
#define PARITY_DEFAULT -1
#define MCDEINT_MODE_DEFAULT -1
@@ -28,6 +28,13 @@ struct hb_filter_private_s
int height[3];
int mode;
+ int spatial_metric;
+ int motion_threshold;
+ int spatial_threshold;
+ int block_threshold;
+ int block_width;
+ int block_height;
+
int parity;
int yadif_ready;
@@ -41,27 +48,20 @@ struct hb_filter_private_s
AVFrame * mcdeint_frame;
AVFrame * mcdeint_frame_dec;
- int comb;
- int color_equal;
- int color_diff;
- int threshold;
- int prog_equal;
- int prog_diff;
- int prog_threshold;
- int deinterlaced_frames;
- int passed_frames;
+ int yadif_deinterlaced_frames;
+ int blend_deinterlaced_frames;
+ int unfiltered_frames;
uint8_t * ref[4][3];
int ref_stride[3];
+ /* Make a buffer to store a comb mask. */
+ uint8_t * mask[3];
+
AVPicture pic_in;
AVPicture pic_out;
hb_buffer_t * buf_out[2];
hb_buffer_t * buf_settings;
-
- int cc_array[3][480][270];
- int combed_macroblocks;
- int uncombed_macroblocks;
};
hb_filter_private_t * hb_decomb_init( int pix_fmt,
@@ -81,7 +81,7 @@ void hb_decomb_close( hb_filter_private_t * pv );
hb_filter_object_t hb_filter_decomb =
{
FILTER_DECOMB,
- "Decombs selectively with (ffmpeg or yadif/mcdeint or blending)",
+ "Deinterlaces selectively with yadif/mcdeint or lowpass5 blending",
NULL,
hb_decomb_init,
hb_decomb_work,
@@ -230,6 +230,255 @@ static void blend_filter_line( uint8_t *dst,
}
}
+int check_combing_mask( hb_filter_private_t * pv )
+{
+ /* Go through the mask in X*Y 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. */
+
+ /* Block mask threshold -- The number of pixels
+ in a block_width * block_height window of
+ he mask that need to show combing for the
+ whole frame to be seen as such. */
+ int threshold = pv->block_threshold;
+ int block_width = pv->block_width;
+ int block_height = pv->block_height;
+ int block_x, block_y;
+ int block_score = 0; int send_to_blend = 0;
+
+ int x, y, k;
+
+ for( k = 0; k < 1; k++ )
+ {
+ int ref_stride = pv->ref_stride[k];
+ for( y = 0; y < ( pv->height[k] - block_height ); y = y + block_height )
+ {
+ for( x = 0; x < ( pv->width[k] - block_width ); x = x + block_width )
+ {
+ block_score = 0;
+ for( block_y = 0; block_y < block_height; block_y++ )
+ {
+ for( block_x = 0; block_x < block_width; block_x++ )
+ {
+ int mask_y = y + block_y;
+ int mask_x = x + block_x;
+
+ /* We only want to mark a pixel in a block as combed
+ if the pixels above and below are as well. Got to
+ handle the top and bottom lines separately. */
+ if( y + block_y == 0 )
+ {
+ if( pv->mask[k][mask_y*ref_stride+mask_x ] == 255 &&
+ pv->mask[k][mask_y*ref_stride+mask_x + 1] == 255 )
+ block_score++;
+ }
+ else if( y + block_y == pv->height[k] - 1 )
+ {
+ if( pv->mask[k][mask_y*ref_stride+mask_x - 1] == 255 &&
+ pv->mask[k][mask_y*ref_stride+mask_x ] == 255 )
+ block_score++;
+ }
+ else
+ {
+ if( pv->mask[k][mask_y*ref_stride+mask_x - 1] == 255 &&
+ pv->mask[k][mask_y*ref_stride+mask_x ] == 255 &&
+ pv->mask[k][mask_y*ref_stride+mask_x + 1] == 255 )
+ block_score++;
+ }
+ }
+ }
+
+ if( block_score >= ( threshold / 2 ) )
+ {
+#if 0
+ hb_log("decomb: frame %i | score %i | type %s", pv->yadif_deinterlaced_frames + pv->blend_deinterlaced_frames + pv->unfiltered_frames + 1, block_score, pv->buf_settings->flags & 16 ? "Film" : "Video");
+#endif
+ if ( block_score <= threshold && !( pv->buf_settings->flags & 16) )
+ {
+ /* Blend video content that scores between
+ ( threshold / 2 ) and threshold. */
+ send_to_blend = 1;
+ }
+ else if( block_score > threshold )
+ {
+ if( pv->buf_settings->flags & 16 )
+ {
+ /* Blend progressive content above the threshold.*/
+ return 2;
+ }
+ else
+ {
+ /* Yadif deinterlace video content above the threshold. */
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if( send_to_blend )
+ {
+ return 2;
+ }
+ else
+ {
+ /* Consider this frame to be uncombed. */
+ return 0;
+ }
+}
+
+int tritical_detect_comb( hb_filter_private_t * pv )
+{
+ /* A mish-mash of various comb detection tricks
+ picked up from neuron2's Decomb plugin for
+ AviSynth and tritical's IsCombedT and
+ IsCombedTIVTC plugins. */
+
+ int x, y, k, width, height;
+
+ /* Comb scoring algorithm */
+ int spatial_metric = pv->spatial_metric;
+ /* Motion threshold */
+ int mthresh = pv->motion_threshold;
+ /* Spatial threshold */
+ int athresh = pv->spatial_threshold;
+ int athresh_squared = athresh * athresh;
+ int athresh6 = 6 *athresh;
+
+ /* 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];
+ width = pv->width[k];
+ 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 )*ref_stride ;
+ int back_1 = ( y - 1 )*ref_stride;
+ int current = y*ref_stride;
+ int forward_1 = ( y + 1 )*ref_stride;
+ int forward_2 = ( y + 2 )*ref_stride;
+
+ /* We need to examine a column of 5 pixels
+ in the prev, cur, and next frames. */
+ uint8_t previous_frame[5];
+ uint8_t current_frame[5];
+ uint8_t next_frame[5];
+
+ for( x = 0; x < width; x++ )
+ {
+ /* Fill up the current frame array with the current pixel values.*/
+ current_frame[0] = pv->ref[1][k][back_2 + x];
+ current_frame[1] = pv->ref[1][k][back_1 + x];
+ current_frame[2] = pv->ref[1][k][current + x];
+ current_frame[3] = pv->ref[1][k][forward_1 + x];
+ current_frame[4] = pv->ref[1][k][forward_2 + x];
+
+ int up_diff = current_frame[2] - current_frame[1];
+ int down_diff = current_frame[2] - current_frame[3];
+
+ if( ( up_diff > athresh && down_diff > athresh ) ||
+ ( up_diff < -athresh && down_diff < -athresh ) )
+ {
+ /* The pixel above and below are different,
+ and they change in the same "direction" too.*/
+ int motion = 0;
+ if( mthresh > 0 )
+ {
+ /* Make sure there's sufficient motion between frame t-1 to frame t+1. */
+ previous_frame[0] = pv->ref[0][k][back_2 + x];
+ previous_frame[1] = pv->ref[0][k][back_1 + x];
+ previous_frame[2] = pv->ref[0][k][current + x];
+ previous_frame[3] = pv->ref[0][k][forward_1 + x];
+ previous_frame[4] = pv->ref[0][k][forward_2 + x];
+ next_frame[0] = pv->ref[2][k][back_2 + x];
+ next_frame[1] = pv->ref[2][k][back_1 + x];
+ next_frame[2] = pv->ref[2][k][current + x];
+ next_frame[3] = pv->ref[2][k][forward_1 + x];
+ next_frame[4] = pv->ref[2][k][forward_2 + x];
+
+ if( abs( previous_frame[2] - current_frame[2] ) > mthresh &&
+ abs( current_frame[1] - next_frame[1] ) > mthresh &&
+ abs( current_frame[3] - next_frame[3] ) > mthresh )
+ motion++;
+ if( abs( next_frame[2] - current_frame[2] ) > mthresh &&
+ abs( previous_frame[1] - current_frame[1] ) > mthresh &&
+ abs( previous_frame[3] - current_frame[3] ) > mthresh )
+ motion++;
+ }
+ else
+ {
+ /* User doesn't want to check for motion,
+ so move on to the spatial check. */
+ motion = 1;
+ }
+
+ if( motion || ( pv->yadif_deinterlaced_frames==0 && pv->blend_deinterlaced_frames==0 && pv->unfiltered_frames==0) )
+ {
+ /*That means it's time for the spatial check.
+ We've got several options here. */
+ if( spatial_metric == 0 )
+ {
+ /* Simple 32detect style comb detection */
+ if( ( abs( current_frame[2] - current_frame[4] ) < 10 ) &&
+ ( abs( current_frame[2] - current_frame[3] ) > 15 ) )
+ {
+ pv->mask[k][y*ref_stride + x] = 255;
+ }
+ else
+ {
+ pv->mask[k][y*ref_stride + x] = 0;
+ }
+ }
+ else if( spatial_metric == 1 )
+ {
+ /* This, for comparison, is what IsCombed uses.
+ It's better, but still noise senstive. */
+ int combing = ( current_frame[1] - current_frame[2] ) *
+ ( current_frame[3] - current_frame[2] );
+
+ if( combing > athresh_squared )
+ pv->mask[k][y*ref_stride + x] = 255;
+ else
+ pv->mask[k][y*ref_stride + x] = 0;
+ }
+ else if( spatial_metric == 2 )
+ {
+ /* Tritical's noise-resistant combing scorer.
+ The check is done on a bob+blur convolution. */
+ int combing = abs( current_frame[0]
+ + ( 4 * current_frame[2] )
+ + current_frame[4]
+ - ( 3 * ( current_frame[1]
+ + current_frame[3] ) ) );
+
+ /* If the frame is sufficiently combed,
+ then mark it down on the mask as 255. */
+ if( combing > athresh6 )
+ pv->mask[k][y*ref_stride + x] = 255;
+ else
+ pv->mask[k][y*ref_stride + x] = 0;
+ }
+ }
+ else
+ {
+ pv->mask[k][y*ref_stride + x] = 0;
+ }
+ }
+ else
+ {
+ pv->mask[k][y*ref_stride + x] = 0;
+ }
+ }
+ }
+ }
+
+ return check_combing_mask( pv );
+}
+
static void yadif_filter_line( uint8_t *dst,
uint8_t *prev,
uint8_t *cur,
@@ -245,32 +494,9 @@ static void yadif_filter_line( uint8_t *dst,
int w = pv->width[plane];
int refs = pv->ref_stride[plane];
int x;
- int macroblock_x;
- int macroblock_y = y / 8 ;
-
for( x = 0; x < w; x++)
{
-
-#if 0
- /* Buggy experimental code for macroblock-by-macrobock comb detection.*/
- if(plane == 0 && pv->mode == 7)
- {
- if( !(x % 8))
- macroblock_x = x / 8;
-
- if(pv->cc_array[plane][macroblock_x][macroblock_y] < 0 || pv->cc_array[plane][macroblock_x][macroblock_y] > 64)
- hb_log("[%i][%i] ( %i * %i )macroblock %i x %i is combed: %i", pv->deinterlaced_frames, plane, x, y, macroblock_x, macroblock_y, pv->cc_array[plane][macroblock_x][macroblock_y] );
-
- if(pv->cc_array[plane][macroblock_x][macroblock_y] == 0 && pv->cc_array[plane][macroblock_x+1][macroblock_y] == 0 && pv->cc_array[plane][macroblock_x-1][macroblock_y] == 0 && pv->cc_array[plane][macroblock_x][macroblock_y+1] == 0 && pv->cc_array[plane][macroblock_x][macroblock_y-1] == 0 )
- {
- dst[0] = cur[0];
- pv->uncombed_macroblocks++;
- goto end_of_yadif_filter_pixel;
- }
- }
- pv->combed_macroblocks++;
-#endif
/* Pixel above*/
int c = cur[-refs];
/* Temporal average -- the current pixel location in the previous and next fields */
@@ -293,7 +519,7 @@ static void yadif_filter_line( uint8_t *dst,
int spatial_pred;
/* Spatial pred is either a bilinear or cubic vertical interpolation. */
- if( pv->mode >= 4 )
+ if( pv->mode > 0 )
{
spatial_pred = cubic_interpolate( cur[-3*refs], cur[-refs], cur[+refs], cur[3*refs] );
}
@@ -314,7 +540,7 @@ static void yadif_filter_line( uint8_t *dst,
+ ABS(cur[-refs+1+j] - cur[+refs+1-j]);\
if( score < spatial_score ){\
spatial_score = score;\
- if( pv->mode >= 4)\
+ if( pv->mode > 0 )\
{\
switch(j)\
{\
@@ -340,8 +566,8 @@ static void yadif_filter_line( uint8_t *dst,
YADIF_CHECK(-1) YADIF_CHECK(-2) }} }}
YADIF_CHECK( 1) YADIF_CHECK( 2) }} }}
- /* Temporally adjust the spatial prediction by comparing against the
- alternate (associated) fields in the previous and next frames. */
+ /* Temporally adjust the spatial prediction by comparing
+ against fields in the previous and next frames. */
int b = (prev2[-2*refs] + next2[-2*refs])>>1;
int f = (prev2[+2*refs] + next2[+2*refs])>>1;
@@ -361,7 +587,6 @@ static void yadif_filter_line( uint8_t *dst,
dst[0] = spatial_pred;
-end_of_yadif_filter_pixel:
dst++;
cur++;
prev++;
@@ -376,109 +601,21 @@ static void yadif_filter( uint8_t ** dst,
int tff,
hb_filter_private_t * pv )
{
-
-#if 0
- /* Buggy, experimental code for macroblock-by-macroblock decombing.*/
- if( pv->mode == 7 )
+
+ int is_combed = tritical_detect_comb( pv );
+
+ if( is_combed == 1 )
{
- int x, y, block_x, block_y, plane, plane_width, plane_height, offset, cc;
-
- int stride = 0;
- int block = 8;
- int s[16];
- int color_diff = pv->color_diff;
- int color_equal = pv->color_equal;
-
- if ( pv->buf_settings->flags & 16 )
- {
- /* Frame is progressive, be more discerning. */
- color_diff = pv->prog_diff;
- color_equal = pv->prog_equal;
- }
-
- /* Iterate through planes */
- for( plane = 0; plane < 1; plane++ )
- {
- plane_width = pv->width[plane];
- plane_height = pv->height[plane];
-
- if( plane == 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. */
- stride = plane_width * plane_height;
- }
- else if ( plane == 2 )
- {
- /* Y and Cb are done, so the offset needs to be bumped
- so it's width*height + (width / 2) * (height / 2) */
- stride *= 5/4;
- }
- /* Grab a horizontal line */
- for(y = 0; y < plane_height; y += block )
- {
- uint8_t *line = &pv->ref[1][plane][ y*plane_width ];
-
- /* Iterate through it horizontally in blocks */
- for(x = 0; x < plane_width; x += block)
- {
- /* Clear out the current macroblock mapping from the last frame. */
- pv->cc_array[plane][x/block][y/block] = 0;
- int sadA = 0;
- int sadB = 0;
-
- /* Go through the block horizontally */
- for(block_x = 0; block_x < block; block_x++)
- {
- /* Go through the block vertically, collecting pixels */
- for(block_y = 0; block_y < block*2; block_y++)
- {
- s[block_y] = line[x+block_x+(block_y*plane_width)];
- }
-
- /* Now go through the results to check combing. */
- for(block_y = 0; block_y < block; block_y++)
- {
- sadA += abs(s[block_y] - s[block_y+2]);
- sadB += abs(s[block_y] - s[block_y+1]);
-
-// if( abs(s[block_y] - s[block_y+2]) < color_equal && abs(s[block_y] - s[block_y+1]) > color_diff)
-// {
-// pv->cc_array[plane][x/block][y/block]++;
-// }
- }
- }
-
- if(sadA < sadB)
- {
- pv->cc_array[plane][x/block][y/block] = 1;
- }
-
- }
- }
- }
+ pv->yadif_deinterlaced_frames++;
}
-
-#if 0
-/* Visualize macroblocks */
- int x, y;
- fprintf(stderr, "FRAME %i VISUALIZATION\n", pv->deinterlaced_frames);
- for( y = 0; y < 60; y++ )
+ else if( is_combed == 2 )
{
- for( x = 0; x < 90; x++ )
- {
- if(pv->cc_array[0][x][y])
- fprintf(stderr, "X");
- else
- fprintf(stderr, "O");
-
- }
- fprintf(stderr, "\n");
+ pv->blend_deinterlaced_frames++;
+ }
+ else
+ {
+ pv->unfiltered_frames++;
}
- fprintf(stderr, "\n\n");
-#endif
-#endif
int i;
for( i = 0; i < 3; i++ )
@@ -490,7 +627,7 @@ static void yadif_filter( uint8_t ** dst,
int y;
for( y = 0; y < h; y++ )
{
- if( pv->mode == 3)
+ if( ( pv->mode == 4 && is_combed ) || is_combed == 2 )
{
uint8_t *prev = &pv->ref[0][i][y*ref_stride];
uint8_t *cur = &pv->ref[1][i][y*ref_stride];
@@ -499,7 +636,7 @@ static void yadif_filter( uint8_t ** dst,
blend_filter_line( dst2, cur, i, y, pv );
}
- else if( (y ^ parity) & 1 )
+ else if( (y ^ parity) & 1 && is_combed == 1 )
{
uint8_t *prev = &pv->ref[0][i][y*ref_stride];
uint8_t *cur = &pv->ref[1][i][y*ref_stride];
@@ -655,20 +792,20 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt,
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->color_equal = 10;
- pv->color_diff = 15;
- pv->threshold = 9;
- pv->prog_equal = 10;
- pv->prog_diff = 35;
- pv->prog_threshold = 9;
-
- pv->combed_macroblocks = 0;
- pv->uncombed_macroblocks = 0;
-
+ pv->yadif_deinterlaced_frames = 0;
+ pv->blend_deinterlaced_frames = 0;
+ pv->unfiltered_frames = 0;
+
pv->yadif_ready = 0;
+
pv->mode = MODE_DEFAULT;
+ pv->spatial_metric = 2;
+ pv->motion_threshold = 6;
+ pv->spatial_threshold = 9;
+ pv->block_threshold = 80;
+ pv->block_width = 16;
+ pv->block_height = 16;
+
pv->parity = PARITY_DEFAULT;
pv->mcdeint_mode = MCDEINT_MODE_DEFAULT;
@@ -678,38 +815,45 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt,
{
sscanf( settings, "%d:%d:%d:%d:%d:%d:%d",
&pv->mode,
- &pv->color_equal,
- &pv->color_diff,
- &pv->threshold,
- &pv->prog_equal,
- &pv->prog_diff,
- &pv->prog_threshold );
+ &pv->spatial_metric,
+ &pv->motion_threshold,
+ &pv->spatial_threshold,
+ &pv->block_threshold,
+ &pv->block_width,
+ &pv->block_height );
}
-
- if( pv->mode == 2 || pv->mode == 5 )
+
+ if( pv->mode == 2 || pv->mode == 3 )
{
pv->mcdeint_mode = 0;
}
/* Allocate yadif specific buffers */
- if( pv->mode > 0 )
+ int i, j;
+ for( i = 0; i < 3; i++ )
{
- int i, j;
- for( i = 0; i < 3; i++ )
- {
- int is_chroma = !!i;
- int w = ((width + 31) & (~31))>>is_chroma;
- int h = ((height+6+ 31) & (~31))>>is_chroma;
+ int is_chroma = !!i;
+ int w = ((width + 31) & (~31))>>is_chroma;
+ int h = ((height+6+ 31) & (~31))>>is_chroma;
- pv->ref_stride[i] = w;
+ pv->ref_stride[i] = w;
- for( j = 0; j < 3; j++ )
- {
- pv->ref[j][i] = malloc( w*h*sizeof(uint8_t) ) + 3*w;
- }
+ for( j = 0; j < 3; j++ )
+ {
+ pv->ref[j][i] = malloc( w*h*sizeof(uint8_t) ) + 3*w;
}
}
+ /* Allocate a buffer to store a comb mask. */
+ 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;
+
+ pv->mask[i] = malloc( w*h*sizeof(uint8_t) ) + 3*w;
+ }
+
/* Allocate mcdeint specific buffers */
if( pv->mcdeint_mode >= 0 )
{
@@ -770,14 +914,7 @@ void hb_decomb_close( hb_filter_private_t * pv )
return;
}
- if( pv->mode < 7 )
- {
- hb_log("decomb: deinterlaced %i | unfiltered %i | total %i", pv->deinterlaced_frames, pv->passed_frames, pv->deinterlaced_frames + pv->passed_frames);
- }
- else
- {
- hb_log("decomb macroblock: deinterlaced: %i | unfiltered %i | total %i", pv->combed_macroblocks, pv->uncombed_macroblocks, pv->combed_macroblocks + pv->uncombed_macroblocks);
- }
+ hb_log("decomb: yadif deinterlaced %i | blend deinterlaced %i | unfiltered %i | total %i", pv->yadif_deinterlaced_frames, pv->blend_deinterlaced_frames, pv->unfiltered_frames, pv->yadif_deinterlaced_frames + pv->blend_deinterlaced_frames + pv->unfiltered_frames);
/* Cleanup frame buffers */
if( pv->buf_out[0] )
@@ -794,20 +931,28 @@ void hb_decomb_close( hb_filter_private_t * pv )
}
/* Cleanup yadif specific buffers */
- if( pv->mode > 0 )
+ int i;
+ for( i = 0; i<3*3; i++ )
{
- int i;
- for( i = 0; i<3*3; i++ )
+ uint8_t **p = &pv->ref[i%3][i/3];
+ if (*p)
{
- uint8_t **p = &pv->ref[i%3][i/3];
- if (*p)
- {
- free( *p - 3*pv->ref_stride[i/3] );
- *p = NULL;
- }
+ free( *p - 3*pv->ref_stride[i/3] );
+ *p = NULL;
}
}
-
+
+ /* Cleanup combing mask. */
+ for( i = 0; i<3*3; i++ )
+ {
+ uint8_t **p = &pv->mask[i/3];
+ if (*p)
+ {
+ free( *p - 3*pv->ref_stride[i/3] );
+ *p = NULL;
+ }
+ }
+
/* Cleanup mcdeint specific buffers */
if( pv->mcdeint_mode >= 0 )
{
@@ -845,40 +990,6 @@ int hb_decomb_work( const hb_buffer_t * cbuf_in,
avpicture_fill( &pv->pic_in, buf_in->data,
pix_fmt, width, height );
- /* Use libavcodec deinterlace if mode == 0 */
- if( pv->mode == 0 )
- {
- avpicture_fill( &pv->pic_out, pv->buf_out[0]->data,
- 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);
-
- if(interlaced)
- {
- avpicture_deinterlace( &pv->pic_out, &pv->pic_in,
- pix_fmt, width, height );
-
- 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;
-
- }
-
- return FILTER_OK;
- }
-
/* Determine if top-field first layout */
int tff;
if( pv->parity < 0 )
@@ -892,12 +1003,6 @@ int hb_decomb_work( const hb_buffer_t * cbuf_in,
/* Store current frame in yadif cache */
store_ref( (const uint8_t**)pv->pic_in.data, pv );
-
- 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);
- }
/* If yadif is not ready, store another ref and return FILTER_DELAY */
if( pv->yadif_ready == 0 )
@@ -914,71 +1019,27 @@ int hb_decomb_work( const hb_buffer_t * cbuf_in,
return FILTER_DELAY;
}
- /* yadif works one frame behind so if the previous frame
- * had combing, deinterlace it otherwise just output it. */
- if( pv->mode == 7 ) // Experimental for macroblock decombing
+ /* Perform yadif filtering */
+ int frame;
+ for( frame = 0; frame <= ( ( pv->mode == 2 || pv->mode == 3 )? 1 : 0 ) ; frame++ )
{
- /* Perform yadif filtering */
-
- pv->deinterlaced_frames++;
- int frame;
- for( frame = 0; frame <= ( ( pv->mode == 2 || pv->mode == 5 )? 1 : 0 ) ; frame++ )
- {
- int parity = frame ^ tff ^ 1;
+ 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 )
- {
- /* Perform mcdeint filtering */
- avpicture_fill( &pv->pic_in, pv->buf_out[(frame^1)]->data,
- pix_fmt, width, height );
+ 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)];
- }
- }
- else if( (pv->comb & 2 ) == 0 )
- {
- /* 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 );
- get_ref( (uint8_t**)pv->pic_out.data, pv, 1 );
- *buf_out = pv->buf_out[0];
- }
- else
- {
- /* Perform yadif filtering */
-
- pv->deinterlaced_frames++;
- int frame;
- for( frame = 0; frame <= ( ( pv->mode == 2 || pv->mode == 5 )? 1 : 0 ) ; frame++ )
+ if( pv->mcdeint_mode >= 0 )
{
- int parity = frame ^ tff ^ 1;
-
- avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data,
+ /* Perform mcdeint filtering */
+ avpicture_fill( &pv->pic_in, pv->buf_out[(frame^1)]->data,
pix_fmt, width, height );
- yadif_filter( pv->pic_out.data, parity, tff, pv );
-
- if( pv->mcdeint_mode >= 0 )
- {
- /* Perform mcdeint filtering */
- 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)];
+ mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv );
}
+
+ *buf_out = pv->buf_out[!(frame^1)];
}
/* Copy buffered settings to output buffer settings */
diff --git a/macosx/Controller.mm b/macosx/Controller.mm
index 42bd48d8e..0143763e0 100644
--- a/macosx/Controller.mm
+++ b/macosx/Controller.mm
@@ -2703,7 +2703,7 @@ the user is using "Custom" settings by determining the sender*/
}
else if ([fPictureController decomb] == 1)
{
- [fPicSettingDecomb setStringValue: @"4:10:15:9:10:35:9"];
+ [fPicSettingDecomb setStringValue: @"1:2:6:9:80:16:16"];
}
else if ([fPictureController decomb] == 2)
{
diff --git a/test/test.c b/test/test.c
index 8f8d272eb..fec091a93 100644
--- a/test/test.c
+++ b/test/test.c
@@ -1504,7 +1504,7 @@ static void ShowHelp()
" -9, --detelecine Detelecine video with pullup filter\n"
" <L:R:T:B:SB:MP> (default 1:1:4:4:0:0)\n"
" -5, --decomb Selectively deinterlaces when it detects combing\n"
- " <M:EQ:DF:TR:EQ:DF:TR> (default: 4:10:15:9:10:35:9)\n"
+ " <MO:ME:MT:ST:BT:BX:BY> (default: 1:2:6:9:80:16:16)\n"
" -g, --grayscale Grayscale encoding\n"
" -p, --pixelratio Store pixel aspect ratio in video stream\n"
" -P, --loosePixelratio Store pixel aspect ratio with specified width\n"