All pastes #1179225 Raw Edit

threaded decomb

public diff v1 · immutable
#1179225 ·published 2008-08-20 00:44 UTC
rendered paste body
Index: 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 )     {