]> granicus.if.org Git - handbrake/commitdiff
Fix two problems that would cause HB to hang in the muxer whenever the input content...
authorvan <vanj.hb@gmail.com>
Wed, 30 Jul 2008 22:27:33 +0000 (22:27 +0000)
committervan <vanj.hb@gmail.com>
Wed, 30 Jul 2008 22:27:33 +0000 (22:27 +0000)
 - sync has to keep processing until all its input fifos report eof otherwise it won't send an eof on all its output fifos.
 - do_job has to wait for muxer to finish. Waiting for anything earlier in the pipeline (we were waiting for the video encoder) can cause other parts of the pipeline to get terminated early which will result in lost data & no eofs.

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1597 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/encfaac.c
libhb/sync.c
libhb/work.c

index 645628a8ee44aba9d5cfe2028098d6d3e86d7ada..ae2e54b360cc0d03698798e23644f7cbee843537 100644 (file)
@@ -206,7 +206,10 @@ static hb_buffer_t *Flush( hb_work_object_t *w, hb_buffer_t *bufin )
         }
     }
     // add the eof marker to the end of our buf chain
-    buf->next = bufin;
+    if ( buf )
+        buf->next = bufin;
+    else
+        bufout = bufin;
     return bufout;
 }
 
index 7f0ac86c4d941315bb4db0fa3c2209a7131d9d08..09ef0d9a27317cf4cca8dd2a4a210777481965ba 100644 (file)
@@ -39,8 +39,11 @@ typedef struct
 struct hb_work_private_s
 {
     hb_job_t * job;
-    int        done;
-
+    int        busy;            // bitmask with one bit for each active input
+                                // (bit 0 = video; 1 = audio 0, 2 = audio 1, ...
+                                // appropriate bit is cleared when input gets
+                                // an eof buf. syncWork returns done when all
+                                // bits are clear.
     /* Video */
     hb_subtitle_t * subtitle;
     int64_t pts_offset;
@@ -69,7 +72,7 @@ struct hb_work_private_s
  * Local prototypes
  **********************************************************************/
 static void InitAudio( hb_work_object_t * w, int i );
-static int  SyncVideo( hb_work_object_t * w );
+static void SyncVideo( hb_work_object_t * w );
 static void SyncAudio( hb_work_object_t * w, int i );
 static void InsertSilence( hb_work_object_t * w, int i, int64_t d );
 static void UpdateState( hb_work_object_t * w );
@@ -92,7 +95,6 @@ int syncInit( hb_work_object_t * w, hb_job_t * job )
 
     pv->job            = job;
     pv->pts_offset     = INT64_MIN;
-    pv->count_frames   = 0;
 
     /* Calculate how many video frames we are expecting */
     duration = 0;
@@ -106,18 +108,18 @@ int syncInit( hb_work_object_t * w, hb_job_t * job )
     pv->count_frames_max = duration * job->vrate / job->vrate_base / 90000;
 
     hb_log( "sync: expecting %d video frames", pv->count_frames_max );
+    pv->busy |= 1;
 
     /* Initialize libsamplerate for every audio track we have */
     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
+        pv->busy |= ( 1 << (i + 1) );
         InitAudio( w, i );
     }
 
     /* Get subtitle info, if any */
     pv->subtitle = hb_list_item( title->list_subtitle, 0 );
 
-    pv->video_sequence = 0;
-
     return 0;
 }
 
@@ -180,17 +182,20 @@ int syncWork( hb_work_object_t * w, hb_buffer_t ** unused1,
     hb_work_private_t * pv = w->private_data;
     int i;
 
+    if ( pv->busy & 1 )
+        SyncVideo( w );
+
     /* If we ever got a video frame, handle audio now */
     if( pv->pts_offset != INT64_MIN )
     {
         for( i = 0; i < hb_list_count( pv->job->title->list_audio ); i++ )
         {
-            SyncAudio( w, i );
+            if ( pv->busy & ( 1 << (i + 1) ) )
+                SyncAudio( w, i );
         }
     }
 
-    /* Handle video */
-    return SyncVideo( w );
+    return ( pv->busy? HB_WORK_OK : HB_WORK_DONE );
 }
 
 hb_work_object_t hb_sync =
@@ -263,29 +268,24 @@ static void InitAudio( hb_work_object_t * w, int i )
  ***********************************************************************
  *
  **********************************************************************/
-static int SyncVideo( hb_work_object_t * w )
+static void SyncVideo( hb_work_object_t * w )
 {
     hb_work_private_t * pv = w->private_data;
     hb_buffer_t * cur, * next, * sub = NULL;
     hb_job_t * job = pv->job;
 
-    if( pv->done )
-    {
-        return HB_WORK_DONE;
-    }
-
     if( !pv->cur && !( pv->cur = hb_fifo_get( job->fifo_raw ) ) )
     {
         /* We haven't even got a frame yet */
-        return HB_WORK_OK;
+        return;
     }
     cur = pv->cur;
     if( cur->size == 0 )
     {
         /* we got an end-of-stream. Feed it downstream & signal that we're done. */
         hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
-        pv->done = 1;
-        return HB_WORK_DONE;
+        pv->busy &=~ 1;
+        return;
     }
 
     /* At this point we have a frame to process. Let's check
@@ -304,8 +304,8 @@ static int SyncVideo( hb_work_object_t * w )
              * video (we don't know its duration). On DVDs the final frame
              * is often strange and dropping it seems to be a good idea. */
             hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
-            pv->done = 1;
-            return HB_WORK_DONE;
+            pv->busy &=~ 1;
+            return;
         }
         if( pv->pts_offset == INT64_MIN )
         {
@@ -618,15 +618,14 @@ static int SyncVideo( hb_work_object_t * w )
         {
             hb_log( "sync: got too many frames (%d), exiting early",
                     pv->count_frames );
-            pv->done = 1;
 
             // Drop an empty buffer into our output to ensure that things
             // get flushed all the way out.
             hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
-            return HB_WORK_DONE;
+            pv->busy &=~ 1;
+            return;
         }
     }
-    return HB_WORK_OK;
 }
 
 static void OutputAudioFrame( hb_job_t *job, hb_audio_t *audio, hb_buffer_t *buf,
@@ -723,6 +722,7 @@ static void SyncAudio( hb_work_object_t * w, int i )
         {
             buf = hb_fifo_get( audio->priv.fifo_raw );
             hb_fifo_push( fifo, buf );
+            pv->busy &=~ (1 << (i + 1) );
             return;
         }
         if ( (int64_t)( buf->start - sync->next_pts ) < 0 )
index f7d050b6a575cd0b12cb7d4bf3414906e5cc4245..5dddf26cb38f1b2253e58520659f028ee7e8796b 100644 (file)
@@ -125,11 +125,9 @@ static void do_job( hb_job_t * job, int cpu_count )
     hb_title_t    * title;
     int             i, j;
     hb_work_object_t * w;
-    hb_work_object_t * final_w = NULL;
 
     hb_audio_t   * audio;
     hb_subtitle_t * subtitle;
-    int done;
     unsigned int subtitle_highest = 0;
     unsigned int subtitle_highest_id = 0;
     unsigned int subtitle_lowest = -1;
@@ -265,7 +263,7 @@ static void do_job( hb_job_t * job, int cpu_count )
     }
 
        hb_log (" + PixelRatio: %d, width:%d, height: %d",job->pixel_ratio,job->width, job->height);
-    job->fifo_mpeg2  = hb_fifo_init( 128 );
+    job->fifo_mpeg2  = hb_fifo_init( 256 );
     job->fifo_raw    = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
     job->fifo_sync   = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
     job->fifo_render = hb_fifo_init( FIFO_CPU_MULT * cpu_count );
@@ -287,15 +285,6 @@ static void do_job( hb_job_t * job, int cpu_count )
     hb_list_add( job->list_work, ( w = hb_get_work( WORK_RENDER ) ) );
     w->fifo_in  = job->fifo_sync;
     w->fifo_out = job->fifo_render;
-    if ( job->indepth_scan )
-    {
-        /*
-         * if we're doing a subtitle scan the last thread in the
-         * processing pipeline is render - remember it so we can
-         * wait for its completion below.
-         */
-        final_w = w;
-    }
 
     if( !job->indepth_scan )
     {
@@ -327,13 +316,6 @@ static void do_job( hb_job_t * job, int cpu_count )
         w->config   = &job->config;
 
         hb_list_add( job->list_work, w );
-
-        /*
-         * if we're not doing a subtitle scan the last thread in the
-         * processing pipeline is the encoder - remember it so we can
-         * wait for its completion below.
-         */
-        final_w = w;
     }
 
     if( job->select_subtitle && !job->indepth_scan )
@@ -661,17 +643,12 @@ static void do_job( hb_job_t * job, int cpu_count )
     // init routines so we have to init the muxer last.
     job->muxer = job->indepth_scan? NULL : hb_muxer_init( job );
 
-    done = 0;
     w = hb_list_item( job->list_work, 0 );
-    w->thread_sleep_interval = 50;
+    w->thread_sleep_interval = 10;
     w->init( w, job );
     while( !*job->die )
     {
-        if ( !done && ( w->status = w->work( w, NULL, NULL ) ) == HB_WORK_DONE )
-        {
-            done = 1;
-        }
-        if( done && final_w->status == HB_WORK_DONE )
+        if ( ( w->status = w->work( w, NULL, NULL ) ) == HB_WORK_DONE )
         {
             break;
         }
@@ -680,9 +657,14 @@ static void do_job( hb_job_t * job, int cpu_count )
     hb_list_rem( job->list_work, w );
     w->close( w );
     free( w );
-    job->done = 1;
 
 cleanup:
+    /* Stop the write thread (thread_close will block until the muxer finishes) */
+    if( job->muxer != NULL )
+        hb_thread_close( &job->muxer );
+
+    job->done = 1;
+
     /* Close work objects */
     while( ( w = hb_list_item( job->list_work, 0 ) ) )
     {
@@ -697,11 +679,9 @@ cleanup:
 
     hb_list_close( &job->list_work );
 
-    /* Stop read & write threads */
+    /* Stop the read thread */
     if( job->reader != NULL )
         hb_thread_close( &job->reader );
-    if( job->muxer != NULL )
-        hb_thread_close( &job->muxer );
 
     /* Close fifos */
     hb_fifo_close( &job->fifo_mpeg2 );