summaryrefslogtreecommitdiffstats
path: root/libhb/detelecine.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/detelecine.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/detelecine.c')
-rw-r--r--libhb/detelecine.c169
1 files changed, 67 insertions, 102 deletions
diff --git a/libhb/detelecine.c b/libhb/detelecine.c
index 202103828..0437730f2 100644
--- a/libhb/detelecine.c
+++ b/libhb/detelecine.c
@@ -80,41 +80,29 @@ struct pullup_context
struct hb_filter_private_s
{
- int pix_fmt;
- int width[3];
- int height[3];
-
struct pullup_context * pullup_ctx;
int pullup_fakecount;
int pullup_skipflag;
-
- AVPicture pic_in;
- AVPicture pic_out;
- hb_buffer_t * buf_out;
};
-hb_filter_private_t * hb_detelecine_init( int pix_fmt,
- int width,
- int height,
- char * settings );
+static int hb_detelecine_init( hb_filter_object_t * filter,
+ hb_filter_init_t * init );
-int hb_detelecine_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_detelecine_work( hb_filter_object_t * filter,
+ hb_buffer_t ** buf_in,
+ hb_buffer_t ** buf_out );
-void hb_detelecine_close( hb_filter_private_t * pv );
+static void hb_detelecine_close( hb_filter_object_t * filter );
hb_filter_object_t hb_filter_detelecine =
{
- FILTER_DETELECINE,
- "Detelecine (pullup)",
- NULL,
- hb_detelecine_init,
- hb_detelecine_work,
- hb_detelecine_close,
+ .id = HB_FILTER_DETELECINE,
+ .enforce_order = 1,
+ .name = "Detelecine (pullup)",
+ .settings = NULL,
+ .init = hb_detelecine_init,
+ .work = hb_detelecine_work,
+ .close = hb_detelecine_close,
};
/*
@@ -812,25 +800,11 @@ void pullup_flush_fields( struct pullup_context * c )
*
*/
-hb_filter_private_t * hb_detelecine_init( int pix_fmt,
- int width,
- int height,
- char * settings )
+static int hb_detelecine_init( hb_filter_object_t * filter,
+ hb_filter_init_t * init )
{
- if( pix_fmt != PIX_FMT_YUV420P )
- {
- return 0;
- }
-
- hb_filter_private_t * pv = malloc( sizeof(struct hb_filter_private_s) );
-
- pv->pix_fmt = pix_fmt;
- 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 = hb_video_buffer_init( width, height );
+ filter->private_data = calloc( sizeof(struct hb_filter_private_s), 1 );
+ hb_filter_private_t * pv = filter->private_data;
struct pullup_context * ctx;
pv->pullup_ctx = ctx = pullup_alloc_context();
@@ -841,9 +815,9 @@ hb_filter_private_t * hb_detelecine_init( int pix_fmt,
ctx->metric_plane = 0;
ctx->parity = -1;
- if( settings )
+ if( filter->settings )
{
- sscanf( settings, "%d:%d:%d:%d:%d:%d:%d",
+ sscanf( filter->settings, "%d:%d:%d:%d:%d:%d:%d",
&ctx->junk_left,
&ctx->junk_right,
&ctx->junk_top,
@@ -861,19 +835,19 @@ hb_filter_private_t * hb_detelecine_init( int pix_fmt,
ctx->bpp[0] = ctx->bpp[1] = ctx->bpp[2] = 8;
ctx->background[1] = ctx->background[2] = 128;
- ctx->w[0] = pv->width[0];
- ctx->h[0] = pv->height[0];
- ctx->stride[0] = pv->width[0];
+ ctx->w[0] = init->width;
+ ctx->h[0] = hb_image_height( init->pix_fmt, init->height, 0 );
+ ctx->stride[0] = hb_image_stride( init->pix_fmt, init->width, 0 );
- ctx->w[1] = pv->width[1];
- ctx->h[1] = pv->height[1];
- ctx->stride[1] = pv->width[1];
+ ctx->w[1] = init->width >> 1;
+ ctx->h[1] = hb_image_height( init->pix_fmt, init->height, 1 );
+ ctx->stride[1] = hb_image_stride( init->pix_fmt, init->width, 1 );
- ctx->w[2] = pv->width[2];
- ctx->h[2] = pv->height[2];
- ctx->stride[2] = pv->width[2];
+ ctx->w[1] = init->width >> 1;
+ ctx->h[2] = hb_image_height( init->pix_fmt, init->height, 2 );
+ ctx->stride[2] = hb_image_stride( init->pix_fmt, init->width, 2 );
- ctx->w[3] = ((width+15)/16) * ((height+15)/16);
+ ctx->w[3] = ((init->width+15)/16) * ((init->height+15)/16);
ctx->h[3] = 2;
ctx->stride[3] = ctx->w[3];
@@ -886,42 +860,40 @@ hb_filter_private_t * hb_detelecine_init( int pix_fmt,
pv->pullup_fakecount = 1;
pv->pullup_skipflag = 0;
- return pv;
+ return 0;
}
-void hb_detelecine_close( hb_filter_private_t * pv )
+static void hb_detelecine_close( hb_filter_object_t * filter )
{
+ hb_filter_private_t * pv = filter->private_data;
+
if( !pv )
{
return;
}
- if( pv->buf_out )
- {
- hb_buffer_close( &pv->buf_out );
- }
-
if( pv->pullup_ctx )
{
pullup_free_context( pv->pullup_ctx );
}
free( pv );
+ filter->private_data = NULL;
}
-int hb_detelecine_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_detelecine_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] )
+ hb_filter_private_t * pv = filter->private_data;
+ hb_buffer_t * in = *buf_in, * out;
+
+ if ( in->size <= 0 )
{
- return FILTER_FAILED;
+ *buf_out = in;
+ *buf_in = NULL;
+ return HB_FILTER_DONE;
}
struct pullup_context * ctx = pv->pullup_ctx;
@@ -934,26 +906,18 @@ int hb_detelecine_work( const hb_buffer_t * buf_in,
frame = pullup_get_frame( ctx );
pullup_release_frame( frame );
hb_log( "Could not get buffer from pullup!" );
- return FILTER_FAILED;
+ return HB_FILTER_FAILED;
}
/* Copy input buffer into pullup buffer */
- avpicture_fill( &pv->pic_in, buf_in->data,
- pix_fmt, width, height );
-
- hb_buffer_copy_settings( pv->buf_out, buf_in );
-
- memcpy( buf->planes[0], pv->pic_in.data[0],
- pv->width[0] * pv->height[0] * sizeof(uint8_t) );
- memcpy( buf->planes[1], pv->pic_in.data[1],
- pv->width[1] * pv->height[1] * sizeof(uint8_t) );
- memcpy( buf->planes[2], pv->pic_in.data[2],
- pv->width[2] * pv->height[2] * sizeof(uint8_t) );
+ memcpy( buf->planes[0], in->plane[0].data, in->plane[0].size );
+ memcpy( buf->planes[1], in->plane[1].data, in->plane[1].size );
+ memcpy( buf->planes[2], in->plane[2].data, in->plane[2].size );
/* Submit buffer fields based on buffer flags.
Detelecine assumes BFF when the TFF flag isn't present. */
int parity = 1;
- if( buf_in->flags & PIC_FLAG_TOP_FIELD_FIRST )
+ if( in->s.flags & PIC_FLAG_TOP_FIELD_FIRST )
{
/* Source signals TFF */
parity = 0;
@@ -971,7 +935,7 @@ int hb_detelecine_work( const hb_buffer_t * buf_in,
}
pullup_submit_field( ctx, buf, parity );
pullup_submit_field( ctx, buf, parity^1 );
- if( buf_in->flags & PIC_FLAG_REPEAT_FIRST_FIELD )
+ if( in->s.flags & PIC_FLAG_REPEAT_FIRST_FIELD )
{
pullup_submit_field( ctx, buf, parity );
}
@@ -985,7 +949,8 @@ int hb_detelecine_work( const hb_buffer_t * buf_in,
{
pv->pullup_fakecount--;
- memcpy( pv->buf_out->data, buf_in->data, buf_in->size );
+ *buf_in = NULL;
+ *buf_out = in;
goto output_frame;
}
@@ -1009,7 +974,7 @@ int hb_detelecine_work( const hb_buffer_t * buf_in,
{
pullup_release_frame( frame );
- if( !(buf_in->flags & PIC_FLAG_REPEAT_FIRST_FIELD) )
+ if( !(in->s.flags & PIC_FLAG_REPEAT_FIRST_FIELD) )
{
goto discard_frame;
}
@@ -1034,30 +999,30 @@ int hb_detelecine_work( const hb_buffer_t * buf_in,
pullup_pack_frame( ctx, frame );
}
- /* Copy pullup frame buffer into output buffer */
- avpicture_fill( &pv->pic_out, pv->buf_out->data,
- pix_fmt, width, height );
+ out = hb_video_buffer_init( in->f.width, in->f.height );
- memcpy( pv->pic_out.data[0], frame->buffer->planes[0],
- pv->width[0] * pv->height[0] * sizeof(uint8_t) );
- memcpy( pv->pic_out.data[1], frame->buffer->planes[1],
- pv->width[1] * pv->height[1] * sizeof(uint8_t) );
- memcpy( pv->pic_out.data[2], frame->buffer->planes[2],
- pv->width[2] * pv->height[2] * sizeof(uint8_t) );
+ /* Copy pullup frame buffer into output buffer */
+ memcpy( out->plane[0].data, frame->buffer->planes[0], in->plane[0].size );
+ memcpy( out->plane[1].data, frame->buffer->planes[1], in->plane[1].size );
+ memcpy( out->plane[2].data, frame->buffer->planes[2], in->plane[2].size );
pullup_release_frame( frame );
+ out->s = in->s;
+ hb_buffer_move_subs( out, in );
+
+ *buf_out = out;
+
output_frame:
- *buf_out = pv->buf_out;
- return FILTER_OK;
+
+ return HB_FILTER_OK;
/* This and all discard_frame calls shown above are
the result of me restoring the functionality in
pullup that huevos_rancheros disabled because
HB couldn't handle it. */
discard_frame:
- *buf_out = pv->buf_out;
- return FILTER_DROP;
+ return HB_FILTER_OK;
}