summaryrefslogtreecommitdiffstats
path: root/libhb/rotate.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/rotate.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/rotate.c')
-rw-r--r--libhb/rotate.c284
1 files changed, 153 insertions, 131 deletions
diff --git a/libhb/rotate.c b/libhb/rotate.c
index efa825a91..5f9558764 100644
--- a/libhb/rotate.c
+++ b/libhb/rotate.c
@@ -9,19 +9,18 @@
// Mode 3: Flip both horizontally and vertically (modes 1 and 2 combined)
typedef struct rotate_arguments_s {
- uint8_t **dst;
+ hb_buffer_t *dst;
+ hb_buffer_t *src;
int stop;
} rotate_arguments_t;
struct hb_filter_private_s
{
- int pix_fmt;
- int width[3];
- int height[3];
-
int mode;
-
- int ref_stride[3];
+ int width;
+ int height;
+ int par_width;
+ int par_height;
int cpu_count;
@@ -29,60 +28,33 @@ struct hb_filter_private_s
hb_lock_t ** rotate_begin_lock; // Thread has work
hb_lock_t ** rotate_complete_lock; // Thread has completed work
rotate_arguments_t *rotate_arguments; // Arguments to thread for work
-
- AVPicture pic_in;
- AVPicture pic_out;
- hb_buffer_t * buf_out;
- hb_buffer_t * buf_settings;
};
-hb_filter_private_t * hb_rotate_init( int pix_fmt,
- int width,
- int height,
- char * settings );
+static int hb_rotate_init( hb_filter_object_t * filter,
+ hb_filter_init_t * init );
-int hb_rotate_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_rotate_work( hb_filter_object_t * filter,
+ hb_buffer_t ** buf_in,
+ hb_buffer_t ** buf_out );
-void hb_rotate_close( hb_filter_private_t * pv );
+static void hb_rotate_close( hb_filter_object_t * filter );
+
+static int hb_rotate_info( hb_filter_object_t * filter,
+ hb_filter_info_t * info );
hb_filter_object_t hb_filter_rotate =
{
- FILTER_ROTATE,
- "Rotate (flips image axes)",
- NULL,
- hb_rotate_init,
- hb_rotate_work,
- hb_rotate_close,
+ .id = HB_FILTER_ROTATE,
+ .enforce_order = 0,
+ .name = "Rotate (rotate & flip image axes)",
+ .settings = NULL,
+ .init = hb_rotate_init,
+ .work = hb_rotate_work,
+ .close = hb_rotate_close,
+ .info = hb_rotate_info
};
-static void rotate_filter_line( uint8_t *dst,
- uint8_t *cur,
- int plane,
- hb_filter_private_t * pv )
-{
-
- int w = pv->width[plane];
-
- int x;
- for( x = 0; x < w; x++)
- {
- if( pv->mode & 2 )
- {
- dst[x] = cur[w-x-1];
- }
- else
- {
- dst[x] = cur[x];
- }
- }
-}
-
typedef struct rotate_thread_arg_s {
hb_filter_private_t *pv;
int segment;
@@ -99,8 +71,10 @@ void rotate_filter_thread( void *thread_args_v )
int plane;
int segment, segment_start, segment_stop;
rotate_thread_arg_t *thread_args = thread_args_v;
- uint8_t **dst;
- int y, w, h, ref_stride;
+ uint8_t *dst;
+ hb_buffer_t *dst_buf;
+ hb_buffer_t *src_buf;
+ int y;
pv = thread_args->pv;
@@ -137,13 +111,18 @@ void rotate_filter_thread( void *thread_args_v )
/*
* Process all three planes, but only this segment of it.
*/
+ dst_buf = rotate_work->dst;
+ src_buf = rotate_work->src;
for( plane = 0; plane < 3; plane++)
{
+ int dst_stride, src_stride;
+
+ dst = dst_buf->plane[plane].data;
+ dst_stride = dst_buf->plane[plane].stride;
+ src_stride = src_buf->plane[plane].stride;
- dst = rotate_work->dst;
- w = pv->width[plane];
- h = pv->height[plane];
- ref_stride = pv->ref_stride[plane];
+ int h = src_buf->plane[plane].height;
+ int w = src_buf->plane[plane].width;
segment_start = ( h / pv->cpu_count ) * segment;
if( segment == pv->cpu_count - 1 )
{
@@ -158,21 +137,35 @@ void rotate_filter_thread( void *thread_args_v )
for( y = segment_start; y < segment_stop; y++ )
{
uint8_t * cur;
-
- if( pv->mode & 1 )
- {
- cur = &pv->pic_in.data[plane][(h-y-1)*pv->pic_in.linesize[plane]];
- }
- else
+ int x, xo, yo;
+
+ cur = &src_buf->plane[plane].data[y * src_stride];
+ for( x = 0; x < w; x++)
{
- cur = &pv->pic_in.data[plane][(y)*pv->pic_in.linesize[plane]];
+ if( pv->mode & 1 )
+ {
+ yo = h - y - 1;
+ }
+ else
+ {
+ yo = y;
+ }
+ if( pv->mode & 2 )
+ {
+ xo = w - x - 1;
+ }
+ else
+ {
+ xo = x;
+ }
+ if( pv->mode & 4 ) // Rotate 90 clockwise
+ {
+ int tmp = xo;
+ xo = h - yo - 1;
+ yo = tmp;
+ }
+ dst[yo*dst_stride + xo] = cur[x];
}
- uint8_t *dst2 = &dst[plane][y*w];
-
- rotate_filter_line( dst2,
- cur,
- plane,
- pv );
}
}
/*
@@ -185,14 +178,16 @@ void rotate_filter_thread( void *thread_args_v )
/*
- * threaded rotate - each thread rptates a single segment of all
+ * threaded rotate - each thread rotates a single segment of all
* three planes. Where a segment is defined as the frame divided by
* the number of CPUs.
*
* This function blocks until the frame is rotated.
*/
-static void rotate_filter( uint8_t ** dst,
- hb_filter_private_t * pv )
+static void rotate_filter(
+ hb_filter_private_t * pv,
+ hb_buffer_t *out,
+ hb_buffer_t *in )
{
int segment;
@@ -202,7 +197,8 @@ static void rotate_filter( uint8_t ** dst,
/*
* Setup the work for this plane.
*/
- pv->rotate_arguments[segment].dst = dst;
+ pv->rotate_arguments[segment].dst = out;
+ pv->rotate_arguments[segment].src = in;
/*
* Let the thread for this plane know that we've setup work
@@ -232,37 +228,17 @@ static void rotate_filter( uint8_t ** dst,
}
-hb_filter_private_t * hb_rotate_init( int pix_fmt,
- int width,
- int height,
- char * settings )
+static int hb_rotate_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;
-
- 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 );
- pv->buf_settings = hb_buffer_init( 0 );
+ filter->private_data = calloc( 1, sizeof(struct hb_filter_private_s) );
+ hb_filter_private_t * pv = filter->private_data;
pv->mode = MODE_DEFAULT;
- pv->ref_stride[0] = pv->width[0];
- pv->ref_stride[1] = pv->width[1];
- pv->ref_stride[2] = pv->width[2];
-
- if( settings )
+ if( filter->settings )
{
- sscanf( settings, "%d",
+ sscanf( filter->settings, "%d",
&pv->mode );
}
@@ -308,25 +284,64 @@ hb_filter_private_t * hb_rotate_init( int pix_fmt,
hb_error( "rotate could not create threads" );
}
}
+ // Set init width/height so the next stage in the pipline
+ // knows what it will be getting
+ if( pv->mode & 4 )
+ {
+ // 90 degree rotation, exchange width and height
+ int tmp = init->width;
+ init->width = init->height;
+ init->height = tmp;
+
+ tmp = init->par_width;
+ init->par_width = init->par_height;
+ init->par_height = tmp;
+ }
+ pv->width = init->width;
+ pv->height = init->height;
+ pv->par_width = init->par_width;
+ pv->par_height = init->par_height;
- return pv;
+ return 0;
}
-void hb_rotate_close( hb_filter_private_t * pv )
+static int hb_rotate_info( hb_filter_object_t * filter,
+ hb_filter_info_t * info )
{
+ hb_filter_private_t * pv = filter->private_data;
if( !pv )
+ return 1;
+
+ memset( info, 0, sizeof( hb_filter_info_t ) );
+ info->out.width = pv->width;
+ info->out.height = pv->height;
+ info->out.par_width = pv->par_width;
+ info->out.par_height = pv->par_height;
+ int pos = 0;
+ if( pv->mode & 1 )
+ pos += sprintf( &info->human_readable_desc[pos], "flip vertical" );
+ if( pv->mode & 2 )
{
- return;
+ if( pos )
+ pos += sprintf( &info->human_readable_desc[pos], "/" );
+ pos += sprintf( &info->human_readable_desc[pos], "flip horizontal" );
}
-
- /* Cleanup frame buffers */
- if( pv->buf_out )
+ if( pv->mode & 4 )
{
- hb_buffer_close( &pv->buf_out );
+ if( pos )
+ pos += sprintf( &info->human_readable_desc[pos], "/" );
+ pos += sprintf( &info->human_readable_desc[pos], "rotate 90" );
}
- if (pv->buf_settings )
+ return 0;
+}
+
+static void hb_rotate_close( hb_filter_object_t * filter )
+{
+ hb_filter_private_t * pv = filter->private_data;
+
+ if( !pv )
{
- hb_buffer_close( &pv->buf_settings );
+ return;
}
int i;
@@ -352,36 +367,43 @@ void hb_rotate_close( hb_filter_private_t * pv )
free( pv->rotate_arguments );
free( pv );
+ filter->private_data = NULL;
}
-int hb_rotate_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_rotate_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;
}
- avpicture_fill( &pv->pic_in, buf_in->data,
- pix_fmt, width, height );
+ int width_out, height_out;
+ if ( pv->mode & 4 )
+ {
+ width_out = in->f.height;
+ height_out = in->f.width;
+ }
+ else
+ {
+ width_out = in->f.width;
+ height_out = in->f.height;
+ }
- avpicture_fill( &pv->pic_out, pv->buf_out->data,
- pix_fmt, width, height );
+ out = hb_video_buffer_init( width_out, height_out );
- //do stuff here
- rotate_filter( pv->pic_out.data, pv );
- hb_buffer_copy_settings( pv->buf_out, buf_in );
+ // Rotate!
+ rotate_filter( pv, out, in );
+ out->s = in->s;
+ hb_buffer_move_subs( out, in );
- *buf_out = pv->buf_out;
+ *buf_out = out;
- return FILTER_OK;
+ return HB_FILTER_OK;
}
-
-