summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2011-04-10 17:39:24 +0000
committerjstebbins <[email protected]>2011-04-10 17:39:24 +0000
commit48e2cd87978fc0e26044b0d686f1a9857dcf619d (patch)
tree810159e659320b125bf8a00b1ad1da8b53bb5b9a
parent9cc5c63d8d1d72240a50dd12f9c5f367b6321983 (diff)
Fix a deadlock that can happen with p-to-p encoding
With p-to-p, the audio sync thread waits for the video sync thread to reach the designated start point. There is a possibility that the video decoder will drop so many frames that the audio sync fifo fills before any frames reach the video sync thread. When this happens, drop some audio to unplug the pipeline. Also, to make this less likely to happen, start sending data to the video decoder 2 seconds before the actual desired start point. This will allow the decoder to find an initial i-frame before the audio stalls since the audio sync thread drops any audio that is before the designated start point. A side effect of this is our start time now more accurate since the decoder is only dropping frames before the start point instead of after. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3917 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r--libhb/reader.c16
-rw-r--r--libhb/sync.c25
2 files changed, 39 insertions, 2 deletions
diff --git a/libhb/reader.c b/libhb/reader.c
index d506719d4..ec05a4798 100644
--- a/libhb/reader.c
+++ b/libhb/reader.c
@@ -35,6 +35,7 @@ typedef struct
uint8_t saw_audio; // != 0 if we've seen audio
int start_found; // found pts_to_start point
+ int64_t pts_to_start;
uint64_t st_first;
} hb_reader_t;
@@ -72,6 +73,13 @@ hb_thread_t * hb_reader_init( hb_job_t * job )
if ( !job->pts_to_start )
r->start_found = 1;
+ else
+ {
+ // The frame at the actual start time may not be an i-frame
+ // so can't be decoded without starting a little early.
+ // sync.c will drop early frames.
+ r->pts_to_start = MAX(0, job->pts_to_start - 180000);
+ }
return hb_thread_init( "reader", ReaderFunc, r,
HB_NORMAL_PRIORITY );
@@ -265,6 +273,8 @@ static void ReaderFunc( void * _r )
}
else if ( r->job->pts_to_start )
{
+ // Note, bd seeks always put us to an i-frame. no need
+ // to start decoding early using r->pts_to_start
hb_bd_seek_pts( r->bd, r->job->pts_to_start );
r->job->pts_to_start = 0;
r->start_found = 1;
@@ -334,7 +344,11 @@ static void ReaderFunc( void * _r )
if ( hb_stream_read( r->stream, ps ) )
{
if ( ps->start > 0 )
+ {
pts_to_start += ps->start;
+ r->pts_to_start += ps->start;
+ r->job->pts_to_start += ps->start;
+ }
}
if ( hb_stream_seek_ts( r->stream, pts_to_start ) >= 0 )
@@ -519,7 +533,7 @@ static void ReaderFunc( void * _r )
UpdateState( r, start );
if ( !r->start_found &&
- start >= r->job->pts_to_start )
+ start >= r->pts_to_start )
{
// pts_to_start point found
r->start_found = 1;
diff --git a/libhb/sync.c b/libhb/sync.c
index bceeb10b5..6d7a778a5 100644
--- a/libhb/sync.c
+++ b/libhb/sync.c
@@ -914,7 +914,30 @@ static int syncAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
while ( !pv->common->start_found &&
buf->start >= pv->common->audio_pts_thresh )
{
- hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
+ hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 10 );
+ // There is an unfortunate unavoidable deadlock that can occur.
+ // Since we need to wait for a specific frame in syncVideoWork,
+ // syncAudioWork can be stalled indefinitely. The video decoder
+ // often drops multiple of the initial frames after starting
+ // because they require references that have not been decoded yet.
+ // This allows a lot of audio to be queued in the fifo and the
+ // audio fifo fills before we get a single video frame. So we
+ // must drop some audio to unplug the pipeline and allow the first
+ // video frame to be decoded.
+ if ( hb_fifo_is_full(w->fifo_in) )
+ {
+ hb_buffer_t *tmp;
+ tmp = buf = hb_fifo_get( w->fifo_in );
+ while ( tmp )
+ {
+ tmp = hb_fifo_get( w->fifo_in );
+ if ( tmp )
+ {
+ hb_buffer_close( &buf );
+ buf = tmp;
+ }
+ }
+ }
}
start = buf->start - pv->common->audio_pts_slip;
}