diff options
author | jstebbins <[email protected]> | 2012-03-27 20:11:26 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2012-03-27 20:11:26 +0000 |
commit | 45b8f81a2e184e2b7deaf47afc49483766191a27 (patch) | |
tree | 30ed0892995cb4ad3255909f69269c453000800a /libhb/decomb.c | |
parent | 7eb7737023be00fa0dc9be75a4984b80c0e5ce57 (diff) |
Rework filter pipeline
This patch enhances the filter objects. The 2 key improvements are:
1. A filter can change the image dimensions as frames pass through it.
2. A filter can output more than one frame.
In addition, I have:
Moved cropping & scalling into a filter object
Added 90 degree rotation to the rotate filter
Moved subtitle burn-in rendering to a filter object.
Moved VFR/CFR handling into a framerate shaping filter object.
Removed render.c since all it's responsibilities got moved to filters.
Improves VOBSUB and SSA subtitle handling. Allows subtitle animations.
SSA karaoke support.
My apologies in advance if anything breaks ;)
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4546 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/decomb.c')
-rw-r--r-- | libhb/decomb.c | 158 |
1 files changed, 73 insertions, 85 deletions
diff --git a/libhb/decomb.c b/libhb/decomb.c index b9baa963a..7d911ff28 100644 --- a/libhb/decomb.c +++ b/libhb/decomb.c @@ -139,7 +139,6 @@ typedef struct yadif_thread_arg_s { struct hb_filter_private_s { - int pix_fmt; int width[3]; int height[3]; @@ -221,28 +220,24 @@ struct hb_filter_private_s // int alternator; // for bobbing parity when framedoubling }; -hb_filter_private_t * hb_decomb_init( int pix_fmt, - int width, - int height, - char * settings ); +static int hb_decomb_init( hb_filter_object_t * filter, + hb_filter_init_t * init ); -int hb_decomb_work( const hb_buffer_t * buf_in, - hb_buffer_t ** buf_out, - int pix_fmt, - int width, - int height, - hb_filter_private_t * pv ); +static int hb_decomb_work( hb_filter_object_t * filter, + hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out ); -void hb_decomb_close( hb_filter_private_t * pv ); +static void hb_decomb_close( hb_filter_object_t * filter ); hb_filter_object_t hb_filter_decomb = { - FILTER_DECOMB, - "Decomb", - NULL, - hb_decomb_init, - hb_decomb_work, - hb_decomb_close, + .id = HB_FILTER_DECOMB, + .enforce_order = 1, + .name = "Decomb", + .settings = NULL, + .init = hb_decomb_init, + .work = hb_decomb_work, + .close = hb_decomb_close, }; int cubic_interpolate_pixel( int y0, int y1, int y2, int y3 ) @@ -790,7 +785,7 @@ int check_filtered_combing_mask( hb_filter_private_t * pv ) pv->mask_box_x = x; pv->mask_box_y = y; - if ( block_score <= threshold && !( pv->buf_settings->flags & 16) ) + if ( block_score <= threshold && !( pv->buf_settings->s.flags & 16) ) { /* Blend video content that scores between ( threshold / 2 ) and threshold. */ @@ -799,7 +794,7 @@ int check_filtered_combing_mask( hb_filter_private_t * pv ) } else if( block_score > threshold ) { - if( pv->buf_settings->flags & 16 ) + if( pv->buf_settings->s.flags & 16 ) { /* Blend progressive content above the threshold.*/ pv->mask_box_color = 2; @@ -919,7 +914,7 @@ int check_combing_mask( hb_filter_private_t * pv ) pv->mask_box_x = x; pv->mask_box_y = y; - if ( block_score <= threshold && !( pv->buf_settings->flags & 16) ) + if ( block_score <= threshold && !( pv->buf_settings->s.flags & 16) ) { /* Blend video content that scores between ( threshold / 2 ) and threshold. */ @@ -928,7 +923,7 @@ int check_combing_mask( hb_filter_private_t * pv ) } else if( block_score > threshold ) { - if( pv->buf_settings->flags & 16 ) + if( pv->buf_settings->s.flags & 16 ) { /* Blend progressive content above the threshold.*/ pv->mask_box_color = 2; @@ -1994,29 +1989,22 @@ static void yadif_filter( uint8_t ** dst, } } -hb_filter_private_t * hb_decomb_init( int pix_fmt, - int width, - int height, - char * settings ) +static int hb_decomb_init( hb_filter_object_t * filter, + hb_filter_init_t * init ) { - if( pix_fmt != PIX_FMT_YUV420P ) - { - return 0; - } - - hb_filter_private_t * pv = calloc( 1, sizeof(struct hb_filter_private_s) ); - - pv->pix_fmt = pix_fmt; + filter->private_data = calloc( 1, sizeof(struct hb_filter_private_s) ); + hb_filter_private_t * pv = filter->private_data; - pv->width[0] = width; - pv->height[0] = height; - pv->width[1] = pv->width[2] = width >> 1; - pv->height[1] = pv->height[2] = height >> 1; + pv->width[0] = hb_image_stride( init->pix_fmt, init->width, 0 ); + pv->height[0] = hb_image_height( init->pix_fmt, init->height, 0 ); + pv->width[1] = pv->width[2] = hb_image_stride( init->pix_fmt, init->width, 1 ); + pv->height[1] = pv->height[2] = hb_image_height( init->pix_fmt, init->height, 1 ); build_gamma_lut( pv ); - pv->buf_out[0] = hb_video_buffer_init( width, height ); - pv->buf_out[1] = hb_video_buffer_init( width, height ); + pv->buf_out[0] = hb_video_buffer_init( init->width, init->height ); + pv->buf_out[1] = hb_video_buffer_init( init->width, init->height ); + pv->buf_settings = hb_buffer_init( 0 ); pv->deinterlaced_frames = 0; @@ -2049,9 +2037,9 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt, pv->mcdeint_mode = MCDEINT_MODE_DEFAULT; int mcdeint_qp = MCDEINT_QP_DEFAULT; - if( settings ) + if( filter->settings ) { - sscanf( settings, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", + sscanf( filter->settings, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", &pv->mode, &pv->spatial_metric, &pv->motion_threshold, @@ -2084,8 +2072,8 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt, 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 w = ((init->width + 31) & (~31))>>is_chroma; + int h = ((init->height+6+ 31) & (~31))>>is_chroma; pv->ref_stride[i] = w; @@ -2110,11 +2098,11 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt, if( pv->mode & MODE_EEDI2 ) { /* Allocate half-height eedi2 buffers */ - height = pv->height[0] / 2; + int height = pv->height[0] / 2; for( i = 0; i < 3; i++ ) { int is_chroma = !!i; - int w = ((width + 31) & (~31))>>is_chroma; + int w = ((init->width + 31) & (~31))>>is_chroma; int h = ((height+6+ 31) & (~31))>>is_chroma; for( j = 0; j < 4; j++ ) @@ -2128,7 +2116,7 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt, for( i = 0; i < 3; i++ ) { int is_chroma = !!i; - int w = ((width + 31) & (~31))>>is_chroma; + int w = ((init->width + 31) & (~31))>>is_chroma; int h = ((height+6+ 31) & (~31))>>is_chroma; for( j = 0; j < 5; j++ ) @@ -2276,14 +2264,17 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt, } } } + + mcdeint_init( &pv->mcdeint, pv->mcdeint_mode, mcdeint_qp, + init->pix_fmt, init->width, init->height ); - mcdeint_init( &pv->mcdeint, pv->mcdeint_mode, mcdeint_qp, width, height ); - - return pv; + return 0; } -void hb_decomb_close( hb_filter_private_t * pv ) +static void hb_decomb_close( hb_filter_object_t * filter ) { + hb_filter_private_t * pv = filter->private_data; + if( !pv ) { return; @@ -2451,33 +2442,30 @@ void hb_decomb_close( hb_filter_private_t * pv ) mcdeint_close( &pv->mcdeint ); free( pv ); + filter->private_data = NULL; } -int hb_decomb_work( const hb_buffer_t * cbuf_in, - hb_buffer_t ** buf_out, - int pix_fmt, - int width, - int height, - hb_filter_private_t * pv ) +static int hb_decomb_work( hb_filter_object_t * filter, + hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out ) { - hb_buffer_t * buf_in = (hb_buffer_t *)cbuf_in; + hb_filter_private_t * pv = filter->private_data; + hb_buffer_t * in = *buf_in; - if( !pv || - pix_fmt != pv->pix_fmt || - width != pv->width[0] || - height != pv->height[0] ) + if ( in->size <= 0 ) { - return FILTER_FAILED; + *buf_out = in; + *buf_in = NULL; + return HB_FILTER_DONE; } - avpicture_fill( &pv->pic_in, buf_in->data, - pix_fmt, width, height ); + hb_avpicture_fill( &pv->pic_in, in ); /* Determine if top-field first layout */ int tff; if( pv->parity < 0 ) { - tff = !!(buf_in->flags & PIC_FLAG_TOP_FIELD_FIRST); + tff = !!(in->s.flags & PIC_FLAG_TOP_FIELD_FIRST); } else { @@ -2492,18 +2480,16 @@ int hb_decomb_work( const hb_buffer_t * cbuf_in, { 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; + pv->buf_settings->s = in->s; + hb_buffer_move_subs( pv->buf_settings, in ); pv->yadif_ready = 1; - return FILTER_DELAY; + return HB_FILTER_DELAY; } - /* Perform yadif filtering */ - int frame; + /* Perform yadif filtering */ + int frame, out_frame; for( frame = 0; frame <= ( ( pv->mode & MODE_MCDEINT ) ? 1 : 0 ) ; frame++ ) // This would be what to use for bobbing: for( frame = 0; frame <= 0 ; frame++ ) { @@ -2531,8 +2517,8 @@ int hb_decomb_work( const hb_buffer_t * cbuf_in, #endif pv->tff = !parity; - avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data, - pix_fmt, width, height ); + hb_buffer_t *b = pv->buf_out[!(frame^1)]; + hb_avpicture_fill( &pv->pic_out, b ); /* XXX Should check here and only bother filtering field 2 when @@ -2548,27 +2534,29 @@ int hb_decomb_work( const hb_buffer_t * cbuf_in, if( pv->mcdeint_mode >= 0 /* && pv->yadif_arguments[0].is_combed */) { /* Perform mcdeint filtering */ - avpicture_fill( &pv->pic_in, pv->buf_out[(frame^1)]->data, - pix_fmt, width, height ); + b = pv->buf_out[(frame^1)]; + hb_avpicture_fill( &pv->pic_in, b ); mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv->width, pv->height, &pv->mcdeint ); - *buf_out = pv->buf_out[(frame^1)]; + out_frame = frame ^ 1; } else { - *buf_out = pv->buf_out[!(frame^1)]; + out_frame = !(frame ^ 1); } } + *buf_out = pv->buf_out[out_frame]; + // Allocate a replacement for the buffer we just consumed + pv->buf_out[out_frame] = hb_video_buffer_init( pv->width[0], pv->height[0] ); /* Copy buffered settings to output buffer settings */ - hb_buffer_copy_settings( *buf_out, pv->buf_settings ); + (*buf_out)->s = pv->buf_settings->s; + hb_buffer_move_subs( *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; + pv->buf_settings->s = in->s; + hb_buffer_move_subs( pv->buf_settings, in ); - return FILTER_OK; + return HB_FILTER_OK; } |