OSDN Git Service

fix silence insertion problem in audio sync and pipeline stall problem
authorjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 3 Apr 2010 21:14:43 +0000 (21:14 +0000)
committerjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 3 Apr 2010 21:14:43 +0000 (21:14 +0000)
the current audio buffer was being dropped when silence was inserted, causing
the time to fall even further behind and provoke more silence insertion
in some cases.

with pont-to-point, it is possible for one stream to complete before the
other(s).  when the work_loop exits for that stream, the fifo is no longer
serviced and may fill.  This can back up and cause a stall in reader
causing the streams that are not yet complete to stall. The Solution is
to continue servicing the fifo after work for a stream is complete.  This was
complicated by the fact that the video sync work object was being used as the
indicator that all work was finished.  When it exited everything was told
to stop.  So now, the muxer work object (last in the chain) is the
indicator when work is done.

git-svn-id: svn://localhost/HandBrake/trunk@3197 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/internal.h
libhb/muxcommon.c
libhb/sync.c
libhb/work.c

index 7672c73..8223ebf 100644 (file)
@@ -152,7 +152,7 @@ hb_work_object_t * hb_codec_encoder( int );
 /***********************************************************************
  * sync.c
  **********************************************************************/
-int hb_sync_init( hb_job_t * job );
+hb_work_object_t * hb_sync_init( hb_job_t * job );
 
 /***********************************************************************
  * mpegdemux.c
index 1d27df6..702285b 100644 (file)
@@ -385,6 +385,10 @@ static void mux_loop( void * _w )
         }
 
         w->status = w->work( w, &buf_in, NULL );
+        if( buf_in )
+        {
+            hb_buffer_close( &buf_in );
+        }
     }
 }
 
@@ -445,8 +449,7 @@ hb_work_object_t * hb_muxer_init( hb_job_t * job )
     muxer->private_data->track = mux->ntracks;
     muxer->fifo_in = job->fifo_mpeg4;
     add_mux_track( mux, job->mux_data, 1 );
-    muxer->done = &job->done;
-    muxer->thread = hb_thread_init( muxer->name, mux_loop, muxer, HB_NORMAL_PRIORITY );
+    muxer->done = &muxer->private_data->mux->done;
 
     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
index 31c9583..e4d7a30 100644 (file)
@@ -100,7 +100,7 @@ static hb_buffer_t * OutputAudioFrame( hb_audio_t *audio, hb_buffer_t *buf,
  ***********************************************************************
  * Initialize the work object
  **********************************************************************/
-int hb_sync_init( hb_job_t * job )
+hb_work_object_t * hb_sync_init( hb_job_t * job )
 {
     hb_title_t        * title = job->title;
     hb_chapter_t      * chapter;
@@ -109,6 +109,7 @@ int hb_sync_init( hb_job_t * job )
     hb_work_private_t * pv;
     hb_sync_video_t   * sync;
     hb_work_object_t  * w;
+    hb_work_object_t  * ret = NULL;
 
     pv = calloc( 1, sizeof( hb_work_private_t ) );
     sync = &pv->type.video;
@@ -127,7 +128,7 @@ int hb_sync_init( hb_job_t * job )
         pv->common->start_found = 1;
     }
 
-    w = hb_get_work( WORK_SYNC_VIDEO );
+    ret = w = hb_get_work( WORK_SYNC_VIDEO );
     w->private_data = pv;
     w->fifo_in = job->fifo_raw;
     w->fifo_out = job->fifo_sync;
@@ -167,7 +168,6 @@ int hb_sync_init( hb_job_t * job )
         }
         sync->count_frames_max = duration * title->rate / title->rate_base / 90000;
     }
-    hb_list_add( job->list_work, w );
 
     hb_log( "sync: expecting %d video frames", sync->count_frames_max );
 
@@ -183,7 +183,7 @@ int hb_sync_init( hb_job_t * job )
     for ( i = 0; i < pv->common->pts_count; i++ )
         pv->common->first_pts[i] = INT64_MAX;
 
-    return 0;
+    return ret;
 }
 
 /***********************************************************************
@@ -800,7 +800,7 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
 
     /* Update UI */
     UpdateState( w );
-        
+
     return HB_WORK_OK;
 }
 
@@ -872,7 +872,6 @@ static int syncAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
     hb_job_t        * job = pv->job;
     hb_sync_audio_t * sync = &pv->type.audio;
     hb_buffer_t     * buf;
-    //hb_fifo_t       * fifo;
     int64_t start;
 
     *buf_out = NULL;
@@ -1017,8 +1016,6 @@ static int syncAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
                 (int)((start - sync->next_pts) / 90),
                 w->audio->id, start, sync->next_pts );
         InsertSilence( w, start - sync->next_pts );
-        *buf_out = buf;
-        return HB_WORK_OK;
     }
 
     /*
index af4665b..4448278 100644 (file)
@@ -381,6 +381,7 @@ 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 * sync;
     hb_work_object_t * muxer;
     hb_interjob_t * interjob;
 
@@ -641,12 +642,7 @@ static void do_job( hb_job_t * job, int cpu_count )
 
     }
     /* Synchronization */
-    if( hb_sync_init( job ) )
-    {
-        hb_error( "Failure to initialise sync" );
-        *job->die = 1;
-        goto cleanup;
-    }
+    sync = hb_sync_init( job );
 
     /* Video decoder */
     int vcodec = title->video_codec? title->video_codec : WORK_DECMPEG2;
@@ -658,7 +654,10 @@ static void do_job( hb_job_t * job, int cpu_count )
     /* Video renderer */
     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 )
+        w->fifo_out = job->fifo_render;
+    else
+        w->fifo_out = NULL;
 
     if( !job->indepth_scan )
     {
@@ -860,7 +859,7 @@ static void do_job( hb_job_t * job, int cpu_count )
     job->done = 0;
 
     /* Launch processing threads */
-    for( i = 1; i < hb_list_count( job->list_work ); i++ )
+    for( i = 0; i < hb_list_count( job->list_work ); i++ )
     {
         w = hb_list_item( job->list_work, i );
         w->done = &job->done;
@@ -875,12 +874,32 @@ static void do_job( hb_job_t * job, int cpu_count )
                                     HB_LOW_PRIORITY );
     }
 
-    // The muxer requires track information that's set up by the encoder
-    // init routines so we have to init the muxer last.
-    muxer = job->indepth_scan? NULL : hb_muxer_init( job );
+    if ( job->indepth_scan )
+    {
+        muxer = NULL;
+        w = sync;
+        sync->done = &job->done;
+    }
+    else
+    {
+        sync->done = &job->done;
+        sync->thread_sleep_interval = 10;
+        if( sync->init( w, job ) )
+        {
+            hb_error( "Failure to initialise thread '%s'", w->name );
+            *job->die = 1;
+            goto cleanup;
+        }
+        sync->thread = hb_thread_init( sync->name, work_loop, sync,
+                                    HB_LOW_PRIORITY );
 
-    w = hb_list_item( job->list_work, 0 );
-    while( !*job->die && w->status != HB_WORK_DONE )
+        // The muxer requires track information that's set up by the encoder
+        // init routines so we have to init the muxer last.
+        muxer = hb_muxer_init( job );
+        w = muxer;
+    }
+
+    while ( !*job->die && !*w->done && w->status != HB_WORK_DONE )
     {
         hb_buffer_t      * buf_in, * buf_out;
 
@@ -896,12 +915,17 @@ static void do_job( hb_job_t * job, int cpu_count )
             break;
         }
 
+        buf_out = NULL;
         w->status = w->work( w, &buf_in, &buf_out );
 
         if( buf_in )
         {
             hb_buffer_close( &buf_in );
         }
+        if ( buf_out && w->fifo_out == NULL )
+        {
+            hb_buffer_close( &buf_out );
+        }
         if( buf_out )
         {
             while ( !*job->die )
@@ -914,9 +938,20 @@ 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;
+    if( muxer != NULL )
+    {
+        muxer->close( muxer );
+        free( muxer );
+
+        if( sync->thread != NULL )
+        {
+            hb_thread_close( &sync->thread );
+            sync->close( sync );
+        }
+        free( sync );
+    }
 
     hb_handle_t * h = job->h;
     hb_state_t state;
@@ -926,12 +961,6 @@ static void do_job( hb_job_t * job, int cpu_count )
 
 cleanup:
     /* Stop the write thread (thread_close will block until the muxer finishes) */
-    if( muxer != NULL )
-    {
-        hb_thread_close( &muxer->thread );
-        muxer->close( muxer );
-    }
-
     job->done = 1;
 
     /* Close work objects */
@@ -1125,6 +1154,10 @@ static void work_loop( void * _w )
         {
             hb_buffer_close( &buf_in );
         }
+        if ( buf_out && w->fifo_out == NULL )
+        {
+            hb_buffer_close( &buf_out );
+        }
         if( buf_out )
         {
             while ( !*w->done )
@@ -1137,4 +1170,12 @@ static void work_loop( void * _w )
             }
         }
     }
+    // Consume data in incoming fifo till job complete so that
+    // residual data does not stall the pipeline
+    while( !*w->done )
+    {
+        buf_in = hb_fifo_get_wait( w->fifo_in );
+        if ( buf_in != NULL )
+            hb_buffer_close( &buf_in );
+    }
 }