All pastes #1167434 Raw Edit

Threaded yadif patch

public diff v1 · immutable
#1167434 ·published 2008-08-12 04:25 UTC
rendered paste body
Index: 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 */