summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2014-07-14 16:46:40 +0000
committerjstebbins <[email protected]>2014-07-14 16:46:40 +0000
commit3f4f145e07c87301bce71d13a140c36f01640a45 (patch)
treeb0b9334012a758f57a4a4e5b735e765d6c311808 /libhb
parent70f4a8751ea04c69095025394adecff6a2c8edea (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.h1
-rw-r--r--libhb/reader.c63
-rw-r--r--libhb/stream.c24
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;