diff options
author | jstebbins <[email protected]> | 2012-05-01 17:17:55 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2012-05-01 17:17:55 +0000 |
commit | 3c2c830d58e7777d19b793fc7a6e08a921f0d12b (patch) | |
tree | d0db9229bd6d8c63a823aaafd366761022701b7a /libhb/deinterlace.c | |
parent | 31f5717ce0ab0e792342f193f5485bfe29790ffd (diff) |
libhb: bob deinterlacing
This is jbrjake's patch for bob deinterlacing applied to decomb and deinterlace
filters. Thanks to yeasah's for refinements and testing of this patch.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4625 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/deinterlace.c')
-rw-r--r-- | libhb/deinterlace.c | 190 |
1 files changed, 122 insertions, 68 deletions
diff --git a/libhb/deinterlace.c b/libhb/deinterlace.c index 029207805..4911f4bbc 100644 --- a/libhb/deinterlace.c +++ b/libhb/deinterlace.c @@ -21,7 +21,14 @@ #include "mpeg2dec/mpeg2.h" #include "mcdeint.h" -#define YADIF_MODE_DEFAULT -1 +// yadif_mode is a bit vector with the following flags +// Note that 2PASS should be enabled when using MCDEINT +#define MODE_YADIF_ENABLE 1 +#define MODE_YADIF_SPATIAL 2 +#define MODE_YADIF_2PASS 4 +#define MODE_YADIF_BOB 8 + +#define YADIF_MODE_DEFAULT 0 #define YADIF_PARITY_DEFAULT -1 #define MCDEINT_MODE_DEFAULT -1 @@ -155,7 +162,7 @@ static void yadif_filter_line( uint8_t *dst, YADIF_CHECK(-1) YADIF_CHECK(-2) }} }} YADIF_CHECK( 1) YADIF_CHECK( 2) }} }} - if( pv->yadif_mode < 2 ) + if( pv->yadif_mode & MODE_YADIF_SPATIAL ) { int b = (prev2[-2*refs] + next2[-2*refs])>>1; int f = (prev2[+2*refs] + next2[+2*refs])>>1; @@ -420,7 +427,7 @@ static int hb_deinterlace_init( hb_filter_object_t * filter, pv->cpu_count = hb_get_cpu_count(); /* Allocate yadif specific buffers */ - if( pv->yadif_mode >= 0 ) + if( pv->yadif_mode & MODE_YADIF_ENABLE ) { int i, j; for( i = 0; i < 3; i++ ) @@ -507,7 +514,7 @@ static void hb_deinterlace_close( hb_filter_object_t * filter ) } /* Cleanup yadif specific buffers */ - if( pv->yadif_mode >= 0 ) + if( pv->yadif_mode & MODE_YADIF_ENABLE ) { int i; for( i = 0; i<3*3; i++ ) @@ -556,6 +563,8 @@ static int hb_deinterlace_work( hb_filter_object_t * filter, AVPicture pic_out; hb_filter_private_t * pv = filter->private_data; hb_buffer_t * in = *buf_in; + hb_buffer_t * last = NULL, * out = NULL; + uint8_t duplicate = 0; if ( in->size <= 0 ) { @@ -564,99 +573,144 @@ static int hb_deinterlace_work( hb_filter_object_t * filter, return HB_FILTER_DONE; } - hb_avpicture_fill( &pic_in, in ); - - /* Use libavcodec deinterlace if yadif_mode < 0 */ - if( pv->yadif_mode < 0 ) + do { - hb_avpicture_fill( &pic_out, pv->buf_out[0] ); + hb_avpicture_fill( &pic_in, in ); - avpicture_deinterlace( &pic_out, &pic_in, pv->buf_out[0]->f.fmt, - pv->buf_out[0]->f.width, pv->buf_out[0]->f.height ); + /* Use libavcodec deinterlace if yadif_mode < 0 */ + if( !( pv->yadif_mode & MODE_YADIF_ENABLE ) ) + { + hb_avpicture_fill( &pic_out, pv->buf_out[0] ); - pv->buf_out[0]->s = in->s; - hb_buffer_move_subs( pv->buf_out[0], in ); + avpicture_deinterlace( &pic_out, &pic_in, pv->buf_out[0]->f.fmt, + pv->buf_out[0]->f.width, pv->buf_out[0]->f.height ); - *buf_out = pv->buf_out[0]; + pv->buf_out[0]->s = in->s; + hb_buffer_move_subs( pv->buf_out[0], in ); - // Allocate a replacement for the buffer we just consumed - hb_buffer_t * b = pv->buf_out[0]; - pv->buf_out[0] = hb_video_buffer_init( b->f.width, b->f.height ); + *buf_out = pv->buf_out[0]; - return HB_FILTER_OK; - } + // Allocate a replacement for the buffer we just consumed + hb_buffer_t * b = pv->buf_out[0]; + pv->buf_out[0] = hb_video_buffer_init( b->f.width, b->f.height ); - /* Determine if top-field first layout */ - int tff; - if( pv->yadif_parity < 0 ) - { - tff = !!(in->s.flags & PIC_FLAG_TOP_FIELD_FIRST); - } - else - { - tff = (pv->yadif_parity & 1) ^ 1; - } - - /* Store current frame in yadif cache */ - yadif_store_ref( (const uint8_t**)pic_in.data, pv ); + return HB_FILTER_OK; + } - /* If yadif is not ready, store another ref and return HB_FILTER_DELAY */ - if( pv->yadif_ready == 0 ) - { - yadif_store_ref( (const uint8_t**)pic_in.data, pv ); + /* Determine if top-field first layout */ + int tff; + if( pv->yadif_parity < 0 ) + { + tff = !!(in->s.flags & PIC_FLAG_TOP_FIELD_FIRST); + } + else + { + tff = (pv->yadif_parity & 1) ^ 1; + } - pv->buf_settings->s = in->s; - hb_buffer_move_subs( pv->buf_settings, in ); + /* Store current frame in yadif cache */ + if (!duplicate) + { + yadif_store_ref( (const uint8_t**)pic_in.data, pv ); + } - pv->yadif_ready = 1; + /* If yadif is not ready, store another ref and return HB_FILTER_DELAY */ + if( pv->yadif_ready == 0 ) + { + yadif_store_ref( (const uint8_t**)pic_in.data, pv ); - return HB_FILTER_DELAY; - } + pv->buf_settings->s = in->s; + hb_buffer_move_subs( pv->buf_settings, in ); - /* Perform yadif and mcdeint filtering */ - int frame; - int out_frame; - hb_buffer_t * b; - for( frame = 0; frame <= (pv->yadif_mode & 1); frame++ ) - { - AVPicture pic_yadif_out; - int parity = frame ^ tff ^ 1; + pv->yadif_ready = 1; - b = pv->buf_out[!(frame^1)]; - hb_avpicture_fill( &pic_yadif_out, b ); + return HB_FILTER_DELAY; + } - yadif_filter( pic_yadif_out.data, parity, tff, pv ); + /* deinterlace both fields if mcdeint is enabled without bob */ + int frame, num_frames = 1; + if( ( pv->yadif_mode & MODE_YADIF_2PASS ) && + !( pv->yadif_mode & MODE_YADIF_BOB ) ) + { + num_frames = 2; + } - if( pv->mcdeint_mode >= 0 ) + /* Perform yadif and mcdeint filtering */ + int out_frame; + hb_buffer_t * b; + for( frame = 0; frame < num_frames; frame++ ) { - b = pv->buf_out[(frame^1)]; - hb_avpicture_fill( &pic_out, b ); + AVPicture pic_yadif_out; + int parity = frame ^ tff ^ 1 ^ duplicate; - mcdeint_filter( pic_out.data, pic_yadif_out.data, parity, - pv->width, pv->height, &pv->mcdeint ); + b = pv->buf_out[!(frame^1)]; + hb_avpicture_fill( &pic_yadif_out, b ); - out_frame = (frame^1); + yadif_filter( pic_yadif_out.data, parity, tff, pv ); + + if( pv->mcdeint_mode >= 0 ) + { + b = pv->buf_out[(frame^1)]; + hb_avpicture_fill( &pic_out, b ); + + mcdeint_filter( pic_out.data, pic_yadif_out.data, parity, + pv->width, pv->height, &pv->mcdeint ); + + out_frame = (frame^1); + } + else + { + out_frame = !(frame^1); + } + } + + // Add to list of output buffers (should be at most 2) + if ( out == NULL ) + { + last = out = pv->buf_out[out_frame]; } else { - out_frame = !(frame^1); + last->next = pv->buf_out[out_frame]; + last = last->next; } - } - *buf_out = pv->buf_out[out_frame]; - // Allocate a replacement for the buffer we just consumed - b = pv->buf_out[out_frame]; - pv->buf_out[out_frame] = hb_video_buffer_init( b->f.width, b->f.height ); + // Allocate a replacement for the buffer we just consumed + b = pv->buf_out[out_frame]; + pv->buf_out[out_frame] = hb_video_buffer_init( b->f.width, b->f.height ); + + /* Copy buffered settings to output buffer settings */ + last->s = pv->buf_settings->s; + + if ( !duplicate ) + { + hb_buffer_move_subs( last, pv->buf_settings ); + } - /* Copy buffered settings to output buffer settings */ - (*buf_out)->s = pv->buf_settings->s; - hb_buffer_move_subs( *buf_out, pv->buf_settings ); + /* if bob mode is engaged, halve the duration of the + * timestamp, and request a duplicate. */ + if( pv->yadif_mode & MODE_YADIF_BOB ) + { + if ( !duplicate ) + { + last->s.stop -= (last->s.stop - last->s.start) / 2LL; + duplicate = 1; + } + else + { + last->s.start = out->s.stop; + last->s.new_chap = 0; + duplicate = 0; + } + } + } while ( duplicate ); /* Replace buffered settings with input buffer settings */ pv->buf_settings->s = in->s; hb_buffer_move_subs( pv->buf_settings, in ); + *buf_out = out; + return HB_FILTER_OK; } - |