rendered paste bodyIndex: libhb/decomb.c===================================================================--- libhb/decomb.c (revision 1645)+++ libhb/decomb.c (working copy)@@ -21,6 +21,14 @@ #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;+ int is_combed;+} yadif_arguments_t;+ struct hb_filter_private_s { int pix_fmt;@@ -62,6 +70,13 @@ AVPicture pic_out; hb_buffer_t * buf_out[2]; hb_buffer_t * buf_settings;+ + int cpu_count;++ hb_thread_t ** yadif_threads; // Threads for Yadif - one per CPU+ hb_lock_t ** yadif_begin_lock; // Thread has work+ hb_lock_t ** yadif_complete_lock; // Thread has completed work+ yadif_arguments_t *yadif_arguments; // Arguments to thread for work }; hb_filter_private_t * hb_decomb_init( int pix_fmt,@@ -599,6 +614,116 @@ } } +typedef struct yadif_thread_arg_s {+ hb_filter_private_t *pv;+ int segment;+} yadif_thread_arg_t;++/*+ * deinterlace this segment of all three planes in a single thread.+ */+void yadif_decomb_filter_thread( void *thread_args_v )+{+ yadif_arguments_t *yadif_work = NULL;+ hb_filter_private_t * pv;+ int run = 1;+ int plane;+ int segment, segment_start, segment_stop;+ yadif_thread_arg_t *thread_args = thread_args_v;+ uint8_t **dst;+ int parity, tff, y, w, h, ref_stride;++ pv = thread_args->pv;+ segment = thread_args->segment;+ int is_combed = pv->yadif_arguments[segment].is_combed;++ hb_log("Yadif Deinterlace thread started for segment %d", segment);++ while( run )+ {+ /*+ * 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[segment] );++ yadif_work = &pv->yadif_arguments[segment];++ 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;+ }+ + /*+ * Process all three planes, but only this segment of it.+ */+ for( plane = 0; plane < 3; plane++)+ {++ dst = yadif_work->dst;+ parity = yadif_work->parity;+ tff = yadif_work->tff;+ w = pv->width[plane];+ h = pv->height[plane];+ ref_stride = pv->ref_stride[plane];+ segment_start = ( h / pv->cpu_count ) * segment;+ if( segment == pv->cpu_count - 1 )+ {+ /*+ * Final segment+ */+ segment_stop = h;+ } else {+ segment_stop = ( h / pv->cpu_count ) * ( segment + 1 );+ }++ for( y = segment_start; y < segment_stop; y++ )+ {+ if( ( pv->mode == 4 && is_combed ) || is_combed == 2 )+ {+ uint8_t *prev = &pv->ref[0][plane][y*ref_stride];+ uint8_t *cur = &pv->ref[1][plane][y*ref_stride];+ uint8_t *next = &pv->ref[2][plane][y*ref_stride];+ uint8_t *dst2 = &dst[plane][y*w];++ blend_filter_line( dst2, cur, plane, y, pv );+ }+ else if( (y ^ parity) & 1 && is_combed == 1 )+ {+ uint8_t *prev = &pv->ref[0][plane][y*ref_stride];+ uint8_t *cur = &pv->ref[1][plane][y*ref_stride];+ uint8_t *next = &pv->ref[2][plane][y*ref_stride];+ uint8_t *dst2 = &dst[plane][y*w];++ yadif_filter_line( dst2, prev, cur, next, plane, parity ^ tff, y, pv );+ }+ else+ {+ memcpy( &dst[plane][y*w],+ &pv->ref[1][plane][y*ref_stride],+ w * sizeof(uint8_t) ); + }+ }+ }+ /*+ * Finished this segment, let everyone know.+ */+ hb_unlock( pv->yadif_complete_lock[segment] );+ }+ free( thread_args_v );+}+ static void yadif_filter( uint8_t ** dst, int parity, int tff,@@ -620,42 +745,43 @@ pv->unfiltered_frames++; } - int i;- for( i = 0; i < 3; i++ )- {- int w = pv->width[i];- int h = pv->height[i];- int ref_stride = pv->ref_stride[i]; - - int y;- for( y = 0; y < h; y++ )- {- if( ( pv->mode == 4 && is_combed ) || is_combed == 2 )- {- uint8_t *prev = &pv->ref[0][i][y*ref_stride];- uint8_t *cur = &pv->ref[1][i][y*ref_stride];- uint8_t *next = &pv->ref[2][i][y*ref_stride];- uint8_t *dst2 = &dst[i][y*w];+ int segment; - blend_filter_line( dst2, cur, i, y, pv );- }- else if( (y ^ parity) & 1 && is_combed == 1 )- {- uint8_t *prev = &pv->ref[0][i][y*ref_stride];- uint8_t *cur = &pv->ref[1][i][y*ref_stride];- uint8_t *next = &pv->ref[2][i][y*ref_stride];- uint8_t *dst2 = &dst[i][y*w];+ for( segment = 0; segment < pv->cpu_count; segment++ )+ { + /*+ * Setup the work for this plane.+ */+ pv->yadif_arguments[segment].parity = parity;+ pv->yadif_arguments[segment].tff = tff;+ pv->yadif_arguments[segment].dst = dst;+ pv->yadif_arguments[segment].is_combed = is_combed; - yadif_filter_line( dst2, prev, cur, next, i, parity ^ tff, y, pv );- }- else- {- memcpy( &dst[i][y*w],- &pv->ref[1][i][y*ref_stride],- w * sizeof(uint8_t) ); - }- }+ /*+ * 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[segment] );+ hb_unlock( pv->yadif_begin_lock[segment] ); }++ /*+ * 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( segment = 0; segment < pv->cpu_count; segment++ )+ {+ hb_lock( pv->yadif_complete_lock[segment] );+ hb_unlock( pv->yadif_complete_lock[segment] );+ }++ /*+ * Entire frame is now deinterlaced.+ */ } static void mcdeint_filter( uint8_t ** dst,@@ -825,6 +951,9 @@ &pv->block_width, &pv->block_height ); }+ + pv->cpu_count = hb_get_cpu_count();+ if( pv->mode == 2 || pv->mode == 3 ) {@@ -857,6 +986,48 @@ pv->mask[i] = malloc( w*h*sizeof(uint8_t) ) + 3*w; } + /*+ * Create yadif threads and locks.+ */+ pv->yadif_threads = malloc( sizeof( hb_thread_t* ) * pv->cpu_count );+ pv->yadif_begin_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );+ pv->yadif_complete_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );+ pv->yadif_arguments = malloc( sizeof( yadif_arguments_t ) * pv->cpu_count );++ for( i = 0; i < pv->cpu_count; i++ )+ {+ yadif_thread_arg_t *thread_args;++ thread_args = malloc( sizeof( yadif_thread_arg_t ) );++ if( thread_args )+ {+ thread_args->pv = pv;+ thread_args->segment = 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_segment",+ yadif_decomb_filter_thread,+ thread_args,+ HB_NORMAL_PRIORITY );+ }+ else+ {+ hb_error( "Yadif could not create threads" );+ }+ }+ /* Allocate mcdeint specific buffers */ if( pv->mcdeint_mode >= 0 ) {@@ -956,6 +1127,27 @@ } } + for( i = 0; i < pv->cpu_count; 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] );+ }+ + /*+ * free memory for yadif structs+ */+ free( pv->yadif_threads );+ free( pv->yadif_begin_lock );+ free( pv->yadif_complete_lock );+ free( pv->yadif_arguments );+ /* Cleanup mcdeint specific buffers */ if( pv->mcdeint_mode >= 0 ) {