diff options
author | jstebbins <[email protected]> | 2014-07-14 16:46:40 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2014-07-14 16:46:40 +0000 |
commit | 3f4f145e07c87301bce71d13a140c36f01640a45 (patch) | |
tree | b0b9334012a758f57a4a4e5b735e765d6c311808 /libhb | |
parent | 70f4a8751ea04c69095025394adecff6a2c8edea (diff) |
libhb: work around libav decoder error durint p-to-p encoding
In some cases, initial data when in p-to-p mode causes libav decoder
initialization to fail. This only happens when multi-threaded encoding
is enabled.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6229 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/internal.h | 1 | ||||
-rw-r--r-- | libhb/reader.c | 63 | ||||
-rw-r--r-- | libhb/stream.c | 24 |
3 files changed, 65 insertions, 23 deletions
diff --git a/libhb/internal.h b/libhb/internal.h index 2f7cbacc1..ed7eab367 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -344,6 +344,7 @@ int hb_stream_seek_chapter( hb_stream_t *, int ); int hb_stream_chapter( hb_stream_t * ); hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt ); +void hb_stream_set_need_keyframe( hb_stream_t *stream, int need_keyframe ); #define STR4_TO_UINT32(p) \ diff --git a/libhb/reader.c b/libhb/reader.c index 472b4cfb0..5f753a7ed 100644 --- a/libhb/reader.c +++ b/libhb/reader.c @@ -349,7 +349,7 @@ void ReadLoop( void * _w ) hb_work_object_t * w = _w; hb_work_private_t * r = w->private_data; hb_fifo_t ** fifos; - hb_buffer_t * buf; + hb_buffer_t * buf = NULL; hb_list_t * list; int n; int chapter = -1; @@ -456,7 +456,11 @@ void ReadLoop( void * _w ) r->start_found = 2; r->duration -= r->job->pts_to_start; r->job->pts_to_start = pts_to_start; + hb_buffer_close(&buf); } + // hb_stream_seek_ts does nothing for TS streams and will return + // an error. In this case, the current buf remains valid and + // gets processed below. } else if( r->stream ) { @@ -503,28 +507,32 @@ void ReadLoop( void * _w ) break; } - if (r->bd) + if (buf == NULL) { - if( (buf = hb_bd_read( r->bd )) == NULL ) - { - break; - } - } - else if (r->dvd) - { - if( (buf = hb_dvd_read( r->dvd )) == NULL ) - { - break; - } + if (r->bd) + { + if( (buf = hb_bd_read( r->bd )) == NULL ) + { + break; + } + } + else if (r->dvd) + { + if( (buf = hb_dvd_read( r->dvd )) == NULL ) + { + break; + } + } + else if (r->stream) + { + if ( (buf = hb_stream_read( r->stream )) == NULL ) + { + break; + } + } } - else if (r->stream) + if (r->stream && r->start_found == 2 ) { - if ( (buf = hb_stream_read( r->stream )) == NULL ) - { - break; - } - if ( r->start_found == 2 ) - { // We will inspect the timestamps of each frame in sync // to skip from this seek point to the timestamp we // want to start at. @@ -537,7 +545,6 @@ void ReadLoop( void * _w ) r->job->pts_to_start = 0; } r->start_found = 1; - } } (hb_demux[r->title->demuxer])( buf, list, &r->demux ); @@ -623,11 +630,20 @@ void ReadLoop( void * _w ) break; } - if ( !r->start_found && - start >= r->pts_to_start ) + if (!r->start_found && start >= r->pts_to_start) { // pts_to_start point found r->start_found = 1; + if (r->stream) + { + // libav multi-threaded decoders can get into + // a bad state if the initial data is not + // decodable. So try to improve the chances of + // a good start by waiting for an initial iframe + hb_stream_set_need_keyframe(r->stream, 1); + hb_buffer_close( &buf ); + continue; + } } // This log is handy when you need to debug timing problems //hb_log("id %x scr_offset %"PRId64 @@ -677,6 +693,7 @@ void ReadLoop( void * _w ) push_buf( r, fifos[n], buf_copy ); } push_buf( r, fifos[0], buf ); + buf = NULL; } else { diff --git a/libhb/stream.c b/libhb/stream.c index 2b551e7ca..37f1fc3a2 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -4872,6 +4872,30 @@ static hb_buffer_t * hb_ts_stream_decode( hb_stream_t *stream ) return NULL; } +void hb_stream_set_need_keyframe(hb_stream_t *stream, int need_keyframe) +{ + if ( stream->hb_stream_type == transport ) + { + // Only wait for a keyframe if the stream is known to have IDRs + if ( stream->has_IDRs ) + { + stream->need_keyframe = need_keyframe; + } + } + else if ( stream->hb_stream_type == program ) + { + // Only wait for a keyframe if the stream is known to have IDRs + if ( stream->has_IDRs ) + { + stream->need_keyframe = need_keyframe; + } + } + else + { + stream->need_keyframe = need_keyframe; + } +} + void hb_ts_stream_reset(hb_stream_t *stream) { int i; |