4 //#include "mpeg2dec/mpeg2.h"
7 // Mode 1: Flip vertically (y0 becomes yN and yN becomes y0)
8 // Mode 2: Flip horizontally (x0 becomes xN and xN becomes x0)
9 // Mode 3: Flip both horizontally and vertically (modes 1 and 2 combined)
11 typedef struct rotate_arguments_s {
16 struct hb_filter_private_s
28 hb_thread_t ** rotate_threads; // Threads for Rotate - one per CPU
29 hb_lock_t ** rotate_begin_lock; // Thread has work
30 hb_lock_t ** rotate_complete_lock; // Thread has completed work
31 rotate_arguments_t *rotate_arguments; // Arguments to thread for work
35 hb_buffer_t * buf_out;
36 hb_buffer_t * buf_settings;
39 hb_filter_private_t * hb_rotate_init( int pix_fmt,
44 int hb_rotate_work( hb_buffer_t * buf_in,
45 hb_buffer_t ** buf_out,
49 hb_filter_private_t * pv );
51 void hb_rotate_close( hb_filter_private_t * pv );
53 hb_filter_object_t hb_filter_rotate =
56 "Rotate (flips image axes)",
64 static void rotate_filter_line( uint8_t *dst,
67 hb_filter_private_t * pv )
70 int w = pv->width[plane];
73 for( x = 0; x < w; x++)
86 typedef struct rotate_thread_arg_s {
87 hb_filter_private_t *pv;
89 } rotate_thread_arg_t;
92 * rotate this segment of all three planes in a single thread.
94 void rotate_filter_thread( void *thread_args_v )
96 rotate_arguments_t *rotate_work = NULL;
97 hb_filter_private_t * pv;
100 int segment, segment_start, segment_stop;
101 rotate_thread_arg_t *thread_args = thread_args_v;
103 int y, w, h, ref_stride;
106 pv = thread_args->pv;
107 segment = thread_args->segment;
109 hb_log("Rotate thread started for segment %d", segment);
114 * Wait here until there is work to do. hb_lock() blocks until
115 * render releases it to say that there is more work to do.
117 hb_lock( pv->rotate_begin_lock[segment] );
119 rotate_work = &pv->rotate_arguments[segment];
121 if( rotate_work->stop )
124 * No more work to do, exit this thread.
130 if( rotate_work->dst == NULL )
132 hb_error( "Thread started when no work available" );
138 * Process all three planes, but only this segment of it.
140 for( plane = 0; plane < 3; plane++)
143 dst = rotate_work->dst;
144 w = pv->width[plane];
145 h = pv->height[plane];
146 ref_stride = pv->ref_stride[plane];
147 segment_start = ( h / pv->cpu_count ) * segment;
148 if( segment == pv->cpu_count - 1 )
155 segment_stop = ( h / pv->cpu_count ) * ( segment + 1 );
158 for( y = segment_start; y < segment_stop; y++ )
164 cur = &pv->pic_in.data[plane][(h-y-1)*pv->pic_in.linesize[plane]];
168 cur = &pv->pic_in.data[plane][(y)*pv->pic_in.linesize[plane]];
170 uint8_t *dst2 = &dst[plane][y*w];
172 rotate_filter_line( dst2,
179 * Finished this segment, let everyone know.
181 hb_unlock( pv->rotate_complete_lock[segment] );
183 free( thread_args_v );
188 * threaded rotate - each thread rptates a single segment of all
189 * three planes. Where a segment is defined as the frame divided by
190 * the number of CPUs.
192 * This function blocks until the frame is rotated.
194 static void rotate_filter( uint8_t ** dst,
195 hb_filter_private_t * pv )
200 for( segment = 0; segment < pv->cpu_count; segment++ )
203 * Setup the work for this plane.
205 pv->rotate_arguments[segment].dst = dst;
208 * Let the thread for this plane know that we've setup work
209 * for it by releasing the begin lock (ensuring that the
210 * complete lock is already locked so that we block when
211 * we try to lock it again below).
213 hb_lock( pv->rotate_complete_lock[segment] );
214 hb_unlock( pv->rotate_begin_lock[segment] );
218 * Wait until all three threads have completed by trying to get
219 * the complete lock that we locked earlier for each thread, which
220 * will block until that thread has completed the work on that
223 for( segment = 0; segment < pv->cpu_count; segment++ )
225 hb_lock( pv->rotate_complete_lock[segment] );
226 hb_unlock( pv->rotate_complete_lock[segment] );
230 * Entire frame is now rotated.
235 hb_filter_private_t * hb_rotate_init( int pix_fmt,
240 if( pix_fmt != PIX_FMT_YUV420P )
245 hb_filter_private_t * pv = calloc( 1, sizeof(struct hb_filter_private_s) );
247 pv->pix_fmt = pix_fmt;
249 pv->width[0] = width;
250 pv->height[0] = height;
251 pv->width[1] = pv->width[2] = width >> 1;
252 pv->height[1] = pv->height[2] = height >> 1;
254 pv->buf_out = hb_video_buffer_init( width, height );
255 pv->buf_settings = hb_buffer_init( 0 );
257 pv->mode = MODE_DEFAULT;
259 pv->ref_stride[0] = pv->width[0];
260 pv->ref_stride[1] = pv->width[1];
261 pv->ref_stride[2] = pv->width[2];
265 sscanf( settings, "%d",
269 pv->cpu_count = hb_get_cpu_count();
273 * Create threads and locks.
275 pv->rotate_threads = malloc( sizeof( hb_thread_t* ) * pv->cpu_count );
276 pv->rotate_begin_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
277 pv->rotate_complete_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
278 pv->rotate_arguments = malloc( sizeof( rotate_arguments_t ) * pv->cpu_count );
281 for( i = 0; i < pv->cpu_count; i++ )
283 rotate_thread_arg_t *thread_args;
285 thread_args = malloc( sizeof( rotate_thread_arg_t ) );
288 thread_args->pv = pv;
289 thread_args->segment = i;
291 pv->rotate_begin_lock[i] = hb_lock_init();
292 pv->rotate_complete_lock[i] = hb_lock_init();
295 * Important to start off with the threads locked waiting
298 hb_lock( pv->rotate_begin_lock[i] );
300 pv->rotate_arguments[i].stop = 0;
301 pv->rotate_arguments[i].dst = NULL;
303 pv->rotate_threads[i] = hb_thread_init( "rotate_filter_segment",
304 rotate_filter_thread,
306 HB_NORMAL_PRIORITY );
308 hb_error( "rotate could not create threads" );
315 void hb_rotate_close( hb_filter_private_t * pv )
322 /* Cleanup frame buffers */
325 hb_buffer_close( &pv->buf_out );
327 if (pv->buf_settings )
329 hb_buffer_close( &pv->buf_settings );
333 for( i = 0; i < pv->cpu_count; i++)
336 * Tell each rotate thread to stop, and then cleanup.
338 pv->rotate_arguments[i].stop = 1;
339 hb_unlock( pv->rotate_begin_lock[i] );
341 hb_thread_close( &pv->rotate_threads[i] );
342 hb_lock_close( &pv->rotate_begin_lock[i] );
343 hb_lock_close( &pv->rotate_complete_lock[i] );
347 * free memory for rotate structs
349 free( pv->rotate_threads );
350 free( pv->rotate_begin_lock );
351 free( pv->rotate_complete_lock );
352 free( pv->rotate_arguments );
357 int hb_rotate_work( hb_buffer_t * buf_in,
358 hb_buffer_t ** buf_out,
362 hb_filter_private_t * pv )
365 pix_fmt != pv->pix_fmt ||
366 width != pv->width[0] ||
367 height != pv->height[0] )
369 return FILTER_FAILED;
372 avpicture_fill( &pv->pic_in, buf_in->data,
373 pix_fmt, width, height );
375 avpicture_fill( &pv->pic_out, pv->buf_out->data,
376 pix_fmt, width, height );
379 rotate_filter( pv->pic_out.data, pv );
380 hb_buffer_copy_settings( pv->buf_out, buf_in );
382 *buf_out = pv->buf_out;