rendered paste bodyIndex: libhb/deinterlace.c===================================================================--- libhb/deinterlace.c (revision 1627)+++ libhb/deinterlace.c (working copy)@@ -32,6 +32,13 @@ #define MIN3(a,b,c) MIN(MIN(a,b),c) #define MAX3(a,b,c) MAX(MAX(a,b),c) +typedef struct yadif_arguments_s {+ uint8_t **dst;+ int parity;+ int tff;+ int stop;+} yadif_arguments_t;+ struct hb_filter_private_s { int pix_fmt;@@ -45,6 +52,11 @@ uint8_t * yadif_ref[4][3]; int yadif_ref_stride[3]; + hb_thread_t * yadif_threads[3]; // Threads for Yadif - one per plane+ hb_lock_t * yadif_begin_lock[3]; // Thread has work+ hb_lock_t * yadif_complete_lock[3]; // Thread has completed work+ yadif_arguments_t yadif_arguments[3]; // Arguments to thread for work+ int mcdeint_mode; int mcdeint_qp; @@ -84,6 +96,7 @@ hb_deinterlace_close, }; + static void yadif_store_ref( const uint8_t ** pic, hb_filter_private_t * pv ) {@@ -102,7 +115,6 @@ uint8_t * ref = pv->yadif_ref[2][i]; int w = pv->width[i];- int h = pv->height[i]; int ref_stride = pv->yadif_ref_stride[i]; int y;@@ -185,40 +197,143 @@ } } -static void yadif_filter( uint8_t ** dst,- int parity,- int tff,- hb_filter_private_t * pv )+typedef struct yadif_thread_arg_s {+ hb_filter_private_t *pv;+ int plane;+} yadif_thread_arg_t;++void yadif_filter_thread( void *thread_args_v ) {- int i;- for( i = 0; i < 3; i++ )+ yadif_arguments_t *yadif_work = NULL;+ hb_filter_private_t * pv;+ int run = 1;+ int plane;+ yadif_thread_arg_t *thread_args = thread_args_v;+ uint8_t **dst;+ int parity, tff, y, w, h, ref_stride;+++ pv = thread_args->pv;+ plane = thread_args->plane;++ hb_log("Yadif Deinterlace thread started for plane %d", plane);++ while( run ) {- int w = pv->width[i];- int h = pv->height[i];- int ref_stride = pv->yadif_ref_stride[i];+ /*+ * Wait here until there is work to do. hb_lock() blocks until+ * render releases it to say that there is more work to do.+ */+ hb_lock( pv->yadif_begin_lock[plane] ); - int y;- for( y = 0; y < h; y++ )+ yadif_work = &pv->yadif_arguments[plane];++ if( yadif_work->stop ) {+ /*+ * No more work to do, exit this thread.+ */+ run = 0;+ continue;+ } ++ if( yadif_work->dst == NULL )+ {+ hb_error( "Thread started when no work available" );+ hb_snooze(500);+ continue;+ }++ dst = yadif_work->dst;+ parity = yadif_work->parity;+ tff = yadif_work->tff;+ w = pv->width[plane];+ h = pv->height[plane];+ ref_stride = pv->yadif_ref_stride[plane];++ for( y = 0 ; y < h; y++ )+ { if( (y ^ parity) & 1 ) {- uint8_t *prev = &pv->yadif_ref[0][i][y*ref_stride];- uint8_t *cur = &pv->yadif_ref[1][i][y*ref_stride];- uint8_t *next = &pv->yadif_ref[2][i][y*ref_stride];- uint8_t *dst2 = &dst[i][y*w];-- yadif_filter_line( dst2, prev, cur, next, i, parity ^ tff, pv );+ uint8_t *prev = &pv->yadif_ref[0][plane][y*ref_stride];+ uint8_t *cur = &pv->yadif_ref[1][plane][y*ref_stride];+ uint8_t *next = &pv->yadif_ref[2][plane][y*ref_stride];+ uint8_t *dst2 = &dst[plane][y*w];+ + yadif_filter_line( dst2, + prev, + cur, + next, + plane, + parity ^ tff, + pv );+ } else {- memcpy( &dst[i][y*w],- &pv->yadif_ref[1][i][y*ref_stride],+ memcpy( &dst[plane][y*w],+ &pv->yadif_ref[1][plane][y*ref_stride], w * sizeof(uint8_t) ); } }+ /*+ * Finished this plane, let everyone know.+ */+ hb_unlock( pv->yadif_complete_lock[plane] ); }++ free( thread_args_v ); } ++/*+ * threaded yadif - each thread deinterlaces a single plane. This+ * function blocks until the frame is deinterlaced.+ */+static void yadif_filter( uint8_t ** dst,+ int parity,+ int tff,+ hb_filter_private_t * pv )+{++ int plane;++ for( plane = 0; plane < 3; plane++ )+ { + /*+ * Setup the work for this plane.+ */+ pv->yadif_arguments[plane].parity = parity;+ pv->yadif_arguments[plane].tff = tff;+ pv->yadif_arguments[plane].dst = dst;++ /*+ * Let the thread for this plane know that we've setup work + * for it by releasing the begin lock (ensuring that the+ * complete lock is already locked so that we block when+ * we try to lock it again below).+ */+ hb_lock( pv->yadif_complete_lock[plane] );+ hb_unlock( pv->yadif_begin_lock[plane] );+ }++ /*+ * Wait until all three threads have completed by trying to get+ * the complete lock that we locked earlier for each thread, which+ * will block until that thread has completed the work on that+ * plane.+ */+ for( plane = 0; plane < 3; plane++ )+ {+ hb_lock( pv->yadif_complete_lock[plane] );+ hb_unlock( pv->yadif_complete_lock[plane] );+ }++ /*+ * Entire frame is now deinterlaced.+ */+}+ static void mcdeint_filter( uint8_t ** dst, uint8_t ** src, int parity,@@ -389,6 +504,40 @@ pv->yadif_ref[j][i] = malloc( w*h*sizeof(uint8_t) ) + 3*w; } }++ /*+ * Create yadif threads and locks.+ */+ for( i = 0; i < 3; i++ )+ {+ yadif_thread_arg_t *thread_args;++ thread_args = malloc( sizeof( yadif_thread_arg_t ) );++ if( thread_args ) {+ thread_args->pv = pv;+ thread_args->plane = i;++ pv->yadif_begin_lock[i] = hb_lock_init();+ pv->yadif_complete_lock[i] = hb_lock_init();++ /*+ * Important to start off with the threads locked waiting+ * on input.+ */+ hb_lock( pv->yadif_begin_lock[i] );++ pv->yadif_arguments[i].stop = 0;+ pv->yadif_arguments[i].dst = NULL;+ + pv->yadif_threads[i] = hb_thread_init( "yadif_filter_plane",+ yadif_filter_thread,+ thread_args,+ HB_NORMAL_PRIORITY );+ } else {+ hb_error( "Yadif could not create threads" );+ }+ } } /* Allocate mcdeint specific buffers */@@ -478,6 +627,19 @@ *p = NULL; } }++ for( i = 0; i < 3; i++)+ {+ /*+ * Tell each yadif thread to stop, and then cleanup.+ */+ pv->yadif_arguments[i].stop = 1;+ hb_unlock( pv->yadif_begin_lock[i] );++ hb_thread_close( &pv->yadif_threads[i] );+ hb_lock_close( &pv->yadif_begin_lock[i] );+ hb_lock_close( &pv->yadif_complete_lock[i] );+ } } /* Cleanup mcdeint specific buffers */