diff options
author | van <[email protected]> | 2008-07-30 22:27:33 +0000 |
---|---|---|
committer | van <[email protected]> | 2008-07-30 22:27:33 +0000 |
commit | bec5dee00e2b3f3c1cd0c9797e281eabeb19a4d7 (patch) | |
tree | 48c9d6273dce15f3af53737c4461e831834fff03 /libhb | |
parent | dff2e8c7a540f22a5a1157199c7aef26c4a4ffa2 (diff) |
Fix two problems that would cause HB to hang in the muxer whenever the input content's video finished before audio:
- 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
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/encfaac.c | 5 | ||||
-rw-r--r-- | libhb/sync.c | 46 | ||||
-rw-r--r-- | libhb/work.c | 40 |
3 files changed, 37 insertions, 54 deletions
diff --git a/libhb/encfaac.c b/libhb/encfaac.c index 645628a8e..ae2e54b36 100644 --- a/libhb/encfaac.c +++ b/libhb/encfaac.c @@ -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; } diff --git a/libhb/sync.c b/libhb/sync.c index 7f0ac86c4..09ef0d9a2 100644 --- a/libhb/sync.c +++ b/libhb/sync.c @@ -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 ) diff --git a/libhb/work.c b/libhb/work.c index f7d050b6a..5dddf26cb 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -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 ); |