summaryrefslogtreecommitdiffstats
path: root/libhb/deinterlace.c
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2012-03-27 20:11:26 +0000
committerjstebbins <[email protected]>2012-03-27 20:11:26 +0000
commit45b8f81a2e184e2b7deaf47afc49483766191a27 (patch)
tree30ed0892995cb4ad3255909f69269c453000800a /libhb/deinterlace.c
parent7eb7737023be00fa0dc9be75a4984b80c0e5ce57 (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/deinterlace.c')
-rw-r--r--libhb/deinterlace.c173
1 files changed, 86 insertions, 87 deletions
diff --git a/libhb/deinterlace.c b/libhb/deinterlace.c
index bd51e9a77..2ed6ef3e5 100644
--- a/libhb/deinterlace.c
+++ b/libhb/deinterlace.c
@@ -40,7 +40,6 @@ typedef struct yadif_arguments_s {
struct hb_filter_private_s
{
- int pix_fmt;
int width[3];
int height[3];
@@ -61,34 +60,28 @@ struct hb_filter_private_s
int mcdeint_mode;
mcdeint_private_t mcdeint;
- AVPicture pic_in;
- AVPicture pic_out;
hb_buffer_t * buf_out[2];
hb_buffer_t * buf_settings;
};
-hb_filter_private_t * hb_deinterlace_init( int pix_fmt,
- int width,
- int height,
- char * settings );
+static int hb_deinterlace_init( hb_filter_object_t * filter,
+ hb_filter_init_t * init );
-int hb_deinterlace_work( 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_deinterlace_work( hb_filter_object_t * filter,
+ hb_buffer_t ** buf_in,
+ hb_buffer_t ** buf_out );
-void hb_deinterlace_close( hb_filter_private_t * pv );
+static void hb_deinterlace_close( hb_filter_object_t * filter );
hb_filter_object_t hb_filter_deinterlace =
{
- FILTER_DEINTERLACE,
- "Deinterlace (ffmpeg or yadif/mcdeint)",
- NULL,
- hb_deinterlace_init,
- hb_deinterlace_work,
- hb_deinterlace_close,
+ .id = HB_FILTER_DEINTERLACE,
+ .enforce_order = 1,
+ .name = "Deinterlace (ffmpeg or yadif/mcdeint)",
+ .settings = NULL,
+ .init = hb_deinterlace_init,
+ .work = hb_deinterlace_work,
+ .close = hb_deinterlace_close,
};
@@ -392,27 +385,19 @@ static void yadif_filter( uint8_t ** dst,
*/
}
-hb_filter_private_t * hb_deinterlace_init( int pix_fmt,
- int width,
- int height,
- char * settings )
+static int hb_deinterlace_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) );
+ filter->private_data = calloc( 1, sizeof(struct hb_filter_private_s) );
+ hb_filter_private_t * pv = filter->private_data;
- pv->pix_fmt = pix_fmt;
+ 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 );
- 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->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->yadif_ready = 0;
@@ -422,9 +407,9 @@ hb_filter_private_t * hb_deinterlace_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",
+ sscanf( filter->settings, "%d:%d:%d:%d",
&pv->yadif_mode,
&pv->yadif_parity,
&pv->mcdeint_mode,
@@ -440,8 +425,8 @@ hb_filter_private_t * hb_deinterlace_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->yadif_ref_stride[i] = w;
@@ -491,13 +476,16 @@ hb_filter_private_t * hb_deinterlace_init( int pix_fmt,
}
}
- mcdeint_init( &pv->mcdeint, pv->mcdeint_mode, mcdeint_qp, width, height );
+ mcdeint_init( &pv->mcdeint, pv->mcdeint_mode, mcdeint_qp,
+ init->pix_fmt, init->width, init->height );
- return pv;
+ return 0;
}
-void hb_deinterlace_close( hb_filter_private_t * pv )
+static void hb_deinterlace_close( hb_filter_object_t * filter )
{
+ hb_filter_private_t * pv = filter->private_data;
+
if( !pv )
{
return;
@@ -556,47 +544,52 @@ void hb_deinterlace_close( hb_filter_private_t * pv )
mcdeint_close( &pv->mcdeint );
free( pv );
+ filter->private_data = NULL;
}
-int hb_deinterlace_work( 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_deinterlace_work( hb_filter_object_t * filter,
+ hb_buffer_t ** buf_in,
+ hb_buffer_t ** buf_out )
{
- if( !pv ||
- pix_fmt != pv->pix_fmt ||
- width != pv->width[0] ||
- height != pv->height[0] )
+ AVPicture pic_in;
+ AVPicture pic_out;
+ hb_filter_private_t * pv = filter->private_data;
+ hb_buffer_t * in = *buf_in;
+
+ 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( &pic_in, in );
/* Use libavcodec deinterlace if yadif_mode < 0 */
if( pv->yadif_mode < 0 )
{
- avpicture_fill( &pv->pic_out, pv->buf_out[0]->data,
- pix_fmt, width, height );
+ hb_avpicture_fill( &pic_out, pv->buf_out[0] );
- avpicture_deinterlace( &pv->pic_out, &pv->pic_in,
- pix_fmt, width, height );
+ avpicture_deinterlace( &pic_out, &pic_in, pv->buf_out[0]->f.fmt,
+ pv->buf_out[0]->f.width, pv->buf_out[0]->f.height );
- hb_buffer_copy_settings( pv->buf_out[0], buf_in );
+ pv->buf_out[0]->s = in->s;
+ hb_buffer_move_subs( pv->buf_out[0], in );
*buf_out = pv->buf_out[0];
- return 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 );
+
+ return HB_FILTER_OK;
}
/* Determine if top-field first layout */
int tff;
if( pv->yadif_parity < 0 )
{
- tff = !!(buf_in->flags & PIC_FLAG_TOP_FIELD_FIRST);
+ tff = !!(in->s.flags & PIC_FLAG_TOP_FIELD_FIRST);
}
else
{
@@ -604,59 +597,65 @@ int hb_deinterlace_work( hb_buffer_t * buf_in,
}
/* Store current frame in yadif cache */
- yadif_store_ref( (const uint8_t**)pv->pic_in.data, pv );
+ yadif_store_ref( (const uint8_t**)pic_in.data, pv );
- /* If yadif is not ready, store another ref and return FILTER_DELAY */
+ /* If yadif is not ready, store another ref and return HB_FILTER_DELAY */
if( pv->yadif_ready == 0 )
{
- yadif_store_ref( (const uint8_t**)pv->pic_in.data, pv );
-
- hb_buffer_copy_settings( pv->buf_settings, buf_in );
+ yadif_store_ref( (const uint8_t**)pic_in.data, pv );
- /* 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 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;
- avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data,
- pix_fmt, width, height );
+ b = pv->buf_out[!(frame^1)];
+ hb_avpicture_fill( &pic_yadif_out, b );
- yadif_filter( pv->pic_out.data, parity, tff, pv );
+ yadif_filter( pic_yadif_out.data, parity, tff, pv );
if( pv->mcdeint_mode >= 0 )
{
- avpicture_fill( &pv->pic_in, pv->buf_out[(frame^1)]->data,
- pix_fmt, width, height );
+ b = pv->buf_out[(frame^1)];
+ hb_avpicture_fill( &pic_out, b );
- mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv->width, pv->height, &pv->mcdeint );
+ mcdeint_filter( pic_out.data, pic_yadif_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
+ 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 */
- 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;
}