summaryrefslogtreecommitdiffstats
path: root/libhb/deinterlace.c
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2012-05-17 19:51:35 +0000
committerjstebbins <[email protected]>2012-05-17 19:51:35 +0000
commit5a0673d1572fdfcd00063cfa9dffba907c808056 (patch)
treeb55af15b31edc30a69bf2c17818f6ea3565f9a9a /libhb/deinterlace.c
parentd005ce0b526630bd428c1e5a466b0a96f0b8ecba (diff)
libhb: tasksets API provided by scsiguy
This is an easier to use API for launching multithreaded tasks. And it is more portable since it does not rely on undefined/implementation specific behavior of POSIX mutexes. That is, the ability for one thread to unlock a mutex owned by another thread. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4685 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/deinterlace.c')
-rw-r--r--libhb/deinterlace.c111
1 files changed, 33 insertions, 78 deletions
diff --git a/libhb/deinterlace.c b/libhb/deinterlace.c
index 49681512c..e654817c3 100644
--- a/libhb/deinterlace.c
+++ b/libhb/deinterlace.c
@@ -20,6 +20,7 @@
#include "hbffmpeg.h"
#include "mpeg2dec/mpeg2.h"
#include "mcdeint.h"
+#include "taskset.h"
// yadif_mode is a bit vector with the following flags
// Note that 2PASS should be enabled when using MCDEINT
@@ -42,7 +43,6 @@ typedef struct yadif_arguments_s {
uint8_t **dst;
int parity;
int tff;
- int stop;
} yadif_arguments_t;
struct hb_filter_private_s
@@ -59,9 +59,8 @@ struct hb_filter_private_s
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
+ taskset_t yadif_taskset; // Threads for Yadif - one per CPU
+
yadif_arguments_t *yadif_arguments; // Arguments to thread for work
int mcdeint_mode;
@@ -220,27 +219,27 @@ void yadif_filter_thread( void *thread_args_v )
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.
+ * Wait here until there is work to do.
*/
- hb_lock( pv->yadif_begin_lock[segment] );
+ taskset_thread_wait4start( &pv->yadif_taskset, segment );
- yadif_work = &pv->yadif_arguments[segment];
- if( yadif_work->stop )
+ if( taskset_thread_stop( &pv->yadif_taskset, segment ) )
{
/*
* No more work to do, exit this thread.
*/
run = 0;
- continue;
+ goto report_completion;
}
+ yadif_work = &pv->yadif_arguments[segment];
+
if( yadif_work->dst == NULL )
{
hb_error( "Thread started when no work available" );
hb_snooze(500);
- continue;
+ goto report_completion;
}
/*
@@ -332,12 +331,13 @@ void yadif_filter_thread( void *thread_args_v )
}
}
}
+
+report_completion:
/*
* Finished this segment, let everyone know.
*/
- hb_unlock( pv->yadif_complete_lock[segment] );
+ taskset_thread_complete( &pv->yadif_taskset, segment );
}
- free( thread_args_v );
}
@@ -364,28 +364,10 @@ static void yadif_filter( uint8_t ** dst,
pv->yadif_arguments[segment].parity = parity;
pv->yadif_arguments[segment].tff = tff;
pv->yadif_arguments[segment].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[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] );
- }
+ /* Allow the taskset threads to make one pass over the data. */
+ taskset_cycle( &pv->yadif_taskset );
/*
* Entire frame is now deinterlaced.
@@ -444,41 +426,32 @@ static int hb_deinterlace_init( hb_filter_object_t * filter,
}
/*
- * Create yadif threads and locks.
+ * Setup yadif taskset.
*/
- 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 );
+ if( pv->yadif_arguments == NULL ||
+ taskset_init( &pv->yadif_taskset, /*thread_count*/pv->cpu_count,
+ sizeof( yadif_arguments_t ) ) == 0 )
+ {
+ hb_error( "yadif could not initialize taskset" );
+ }
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;
+ thread_args = taskset_thread_args( &pv->yadif_taskset, i );
- pv->yadif_begin_lock[i] = hb_lock_init();
- pv->yadif_complete_lock[i] = hb_lock_init();
+ thread_args->pv = pv;
+ thread_args->segment = i;
+ pv->yadif_arguments[i].dst = NULL;
- /*
- * 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_filter_thread,
- thread_args,
- HB_NORMAL_PRIORITY );
- } else {
- hb_error( "Yadif could not create threads" );
+ if( taskset_thread_spawn( &pv->yadif_taskset, i,
+ "yadif_filter_segment",
+ yadif_filter_thread,
+ HB_NORMAL_PRIORITY ) == 0 )
+ {
+ hb_error( "yadif could not spawn thread" );
}
}
}
@@ -526,25 +499,7 @@ static void hb_deinterlace_close( hb_filter_object_t * filter )
}
}
- 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 );
+ taskset_fini( &pv->yadif_taskset );
free( pv->yadif_arguments );
}