Index: libhb/deinterlace.c =================================================================== --- libhb/deinterlace.c (revision 1487) +++ libhb/deinterlace.c (working copy) @@ -34,6 +34,7 @@ struct hb_filter_private_s { + int cpu_count; int pix_fmt; int width[3]; int height[3]; @@ -45,6 +46,10 @@ uint8_t * yadif_ref[4][3]; int yadif_ref_stride[3]; + hb_thread_t ** yadif_threads; + hb_fifo_t * yadif_fifo; + hb_lock_t ** yadif_locks; + int mcdeint_mode; int mcdeint_qp; @@ -84,6 +89,14 @@ hb_deinterlace_close, }; +typedef struct yadif_arguments_s { + uint8_t **dst; + int parity; + int tff; + int plane; + int y; +} yadif_arguments_t; + 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,115 @@ } } -static void yadif_filter( uint8_t ** dst, - int parity, - int tff, - hb_filter_private_t * pv ) +void yadif_filter_segment( void *pv_v ) { - int i; - for( i = 0; i < 3; i++ ) + hb_buffer_t *yadif_job; + yadif_arguments_t *segment_data = NULL; + hb_filter_private_t * pv = pv_v; + int run = 1; + + while( run ) { - int w = pv->width[i]; - int h = pv->height[i]; - int ref_stride = pv->yadif_ref_stride[i]; + yadif_job = hb_fifo_see( pv->yadif_fifo ); - int y; - for( y = 0; y < h; y++ ) + if( yadif_job == NULL ) { - if( (y ^ parity) & 1 ) + /* + * No work to do - try again in a moment + */ + hb_snooze( 5 ); + continue; + } else { + + if( yadif_job->size == 0 ) { - 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]; + run = 0; + continue; + } - yadif_filter_line( dst2, prev, cur, next, i, parity ^ tff, pv ); - } - else + yadif_job = hb_fifo_get( pv->yadif_fifo ); + segment_data = (yadif_arguments_t*)yadif_job->data; + uint8_t **dst = segment_data->dst; + int parity = segment_data->parity; + int tff = segment_data->tff; + int i = segment_data->plane; + hb_filter_private_t * pv = pv_v; + int y; + + int w = pv->width[i]; + int h = pv->height[i]; + int ref_stride = pv->yadif_ref_stride[i]; + + for( y = 0 ; y < h; y++ ) { - memcpy( &dst[i][y*w], - &pv->yadif_ref[1][i][y*ref_stride], - w * sizeof(uint8_t) ); + 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 ); + + } + else + { + memcpy( &dst[i][y*w], + &pv->yadif_ref[1][i][y*ref_stride], + w * sizeof(uint8_t) ); + } } + hb_buffer_close( &yadif_job ); + hb_unlock( pv->yadif_locks[i] ); } } } + +static void yadif_filter( uint8_t ** dst, + int parity, + int tff, + hb_filter_private_t * pv ) +{ + + int thread_count = 3; + hb_buffer_t * yadif_job; + yadif_arguments_t * arguments; + + int i; + for( i = 0; i < thread_count; i++) + { + yadif_job = hb_buffer_init( sizeof( yadif_arguments_t ) ); + arguments = (yadif_arguments_t*)yadif_job->data; + + arguments->parity = parity; + arguments->tff = tff; + arguments->dst = dst; + arguments->plane = i; + + hb_lock( pv->yadif_locks[i] ); + hb_fifo_push( pv->yadif_fifo, yadif_job ); + } + + /* + * wait until all threads have completed by trying to get the same + * lock as we locked earlier for each thread, which will block until + * that thread has completed the work on that segment. + */ + for( i = 0; i < thread_count; i++ ) + { + hb_lock( pv->yadif_locks[i] ); + hb_unlock( pv->yadif_locks[i] ); + } + +} + static void mcdeint_filter( uint8_t ** dst, uint8_t ** src, int parity, @@ -344,6 +431,8 @@ hb_filter_private_t * pv = calloc( 1, sizeof(struct hb_filter_private_s) ); + pv->cpu_count = hb_get_cpu_count(); + pv->pix_fmt = pix_fmt; pv->width[0] = width; @@ -389,6 +478,23 @@ pv->yadif_ref[j][i] = malloc( w*h*sizeof(uint8_t) ) + 3*w; } } + + pv->yadif_fifo = hb_fifo_init( 5 ); + + /* + * Create threads. + */ + pv->yadif_threads = malloc( sizeof( hb_thread_t* ) * 3 ); + pv->yadif_locks = malloc( sizeof(hb_lock_t* ) * 3 ); + + for( i = 0; i < 3; i++ ) + { + pv->yadif_threads[i] = hb_thread_init( "yadif_segment", + yadif_filter_segment, + pv, + HB_NORMAL_PRIORITY ); + pv->yadif_locks[i] = hb_lock_init(); + } } /* Allocate mcdeint specific buffers */ @@ -478,6 +584,24 @@ *p = NULL; } } + + for( i = 0; i < 3; i++) + { + /* + * Send an empty buffer into the fifo to release the threads + * from their loops. + */ + hb_buffer_t *kill_em; + kill_em = hb_buffer_init( 0 ); + hb_fifo_push( pv->yadif_fifo, kill_em ); + hb_thread_close( &pv->yadif_threads[i] ); + hb_lock_close( &pv->yadif_locks[i] ); + } + + /* + * TODO Need to free fifo as well. + */ + free(pv->yadif_threads); } /* Cleanup mcdeint specific buffers */