diff options
author | jstebbins <[email protected]> | 2011-09-26 20:48:11 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2011-09-26 20:48:11 +0000 |
commit | 18591273b5278c8b9f2a0ab60e71dcf789bffd1f (patch) | |
tree | 222b3ad74c1247409cd5413fd47e20912fd79709 /libhb | |
parent | 070be6a0fd2bdcf4c60a207c79e10d0451e9be6a (diff) |
handle TS streams that have no PCRs better
For TS streams that don't have PCRs, we substitute the DTS timestamp
from the video track (or PTS if we don't see DTS). But these can bounce
around or be wider spaced in the stream that PCRs are meant to be. So I
have added a test to see if the timestamp looks like a discontinuity.
Then I only pass the timestamp as a PCR if there appears to be a
discontinuity. This prevents a lot of scr_offset thrashing.
I have also fixed an error in our scr_offset processing. It is rarely
triggered and it's effects are so minor with well behaved streams that
it would be completely unnoticed. But with the test stream I was using,
it caused a factor of 10 times more "audio went backwards" errors.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4254 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/reader.c | 40 | ||||
-rw-r--r-- | libhb/stream.c | 33 |
2 files changed, 58 insertions, 15 deletions
diff --git a/libhb/reader.c b/libhb/reader.c index c8a97ed39..0741fb179 100644 --- a/libhb/reader.c +++ b/libhb/reader.c @@ -22,6 +22,7 @@ hb_work_object_t hb_reader = typedef struct { + int startup; double average; // average time between packets int64_t last; // last timestamp seen on this stream int id; // stream id @@ -109,6 +110,7 @@ static int hb_reader_init( hb_work_object_t * w, hb_job_t * job ) (double)job->vrate; r->stream_timing[0].last = -r->stream_timing[0].average; r->stream_timing[0].valid = 1; + r->stream_timing[0].startup = 10; r->stream_timing[1].id = -1; r->demux.last_scr = -1; @@ -228,6 +230,7 @@ static stream_timing_t *id_to_st( hb_work_private_t *r, const hb_buffer_t *buf, } st->id = buf->id; st->average = 30.*90.; + st->startup = 10; st->last = -st->average; if ( ( st->is_audio = is_audio( r, buf->id ) ) != 0 ) { @@ -245,11 +248,26 @@ static stream_timing_t *id_to_st( hb_work_private_t *r, const hb_buffer_t *buf, static void update_ipt( hb_work_private_t *r, const hb_buffer_t *buf ) { stream_timing_t *st = id_to_st( r, buf, 1 ); + + if( buf->renderOffset < 0 ) + { + st->last += st->average; + return; + } + double dt = buf->renderOffset - st->last; // Protect against spurious bad timestamps if ( dt > -5 * 90000LL && dt < 5 * 90000LL ) { - st->average += ( dt - st->average ) * (1./32.); + if( st->startup ) + { + st->average += ( dt - st->average ) * (1./2.); + st->startup--; + } + else + { + st->average += ( dt - st->average ) * (1./32.); + } st->last = buf->renderOffset; } st->valid = 1; @@ -281,7 +299,6 @@ static void new_scr_offset( hb_work_private_t *r, hb_buffer_t *buf ) //hb_log("id %x last %ld avg %g nxt %ld renderOffset %ld scr_offset %ld", // buf->id, last, st->average, nxt, buf->renderOffset, r->scr_offset); r->scr_changes = r->demux.scr_changes; - st->last = nxt; } /*********************************************************************** @@ -587,15 +604,16 @@ void ReadLoop( void * _w ) } if ( buf->renderOffset != -1 ) { - if ( r->scr_changes == r->demux.scr_changes ) - { - // This packet is referenced to the same SCR as the last. - // Adjust timestamp to remove the System Clock Reference - // offset then update the average inter-packet time - // for this stream. - buf->renderOffset -= r->scr_offset; - update_ipt( r, buf ); - } + // This packet is referenced to the same SCR as the last. + // Adjust timestamp to remove the System Clock Reference + // offset then update the average inter-packet time + // for this stream. + buf->renderOffset -= r->scr_offset; + update_ipt( r, buf ); + } + else + { + update_ipt( r, buf ); } if ( !r->start_found ) { diff --git a/libhb/stream.c b/libhb/stream.c index f77e03c9a..2ca1fd643 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -161,6 +161,8 @@ struct hb_stream_s int pcr_in; // sequence number of most recent input pcr int64_t pcr; // most recent input pcr int64_t pcr_current; // circular buffer of output pcrs + int64_t last_timestamp; // used for discontinuity detection when + // there are no PCRs uint8_t *packet; // buffer for one TS packet hb_ts_stream_t *list; @@ -4412,8 +4414,21 @@ static hb_buffer_t * generate_output_data(hb_stream_t *stream, int curstream) // checked at once. int64_t bufpcr = b->pcr; int64_t curpcr = stream->ts.pcr_current; - if ( b->cur < stream->ts.pcr_out && - bufpcr != -1 && curpcr != -1 && curpcr - bufpcr > 200*90LL ) + if ( stream->ts.found_pcr && b->cur < stream->ts.pcr_out && + bufpcr != -1 && curpcr != -1 && + (uint64_t)( curpcr - bufpcr ) > 200*90LL ) + { + // we've sent up a new pcr but have a packet referenced to an + // old pcr and the difference was enough to trigger a discontinuity + // correction. smash the timestamps or we'll mess up the correction. + buf->start = -1; + buf->renderOffset = -1; + buf->stop = -1; + buf->pcr = -1; + } + else if ( b->cur < stream->ts.pcr_out && + bufpcr != -1 && curpcr != -1 && + ( curpcr - bufpcr > 200*90LL || bufpcr - curpcr > 200*90LL ) ) { // we've sent up a new pcr but have a packet referenced to an // old pcr and the difference was enough to trigger a discontinuity @@ -4641,6 +4656,7 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt ) ++stream->frames; // if we don't have a pcr yet use the dts from this frame + // to attempt to detect discontinuities if ( !stream->ts.found_pcr ) { // PES must begin with an mpeg start code & contain @@ -4652,8 +4668,16 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt ) return NULL; } // if we have a dts use it otherwise use the pts - stream->ts.pcr = pes_timestamp( pes + ( pes[7] & 0x40?14:9 ) ); - ++stream->ts.pcr_in; + int64_t timestamp; + timestamp = pes_timestamp( pes + ( pes[7] & 0x40?14:9 ) ); + if( stream->ts.last_timestamp < 0 || + timestamp - stream->ts.last_timestamp > 90 * 600 || + stream->ts.last_timestamp - timestamp > 90 * 600 ) + { + stream->ts.pcr = timestamp; + ++stream->ts.pcr_in; + } + stream->ts.last_timestamp = timestamp; } } @@ -4749,6 +4773,7 @@ void hb_ts_stream_reset(hb_stream_t *stream) stream->ts.pcr_in = 0; stream->ts.pcr = -1; stream->ts.pcr_current = -1; + stream->ts.last_timestamp = -1; stream->frames = 0; stream->errors = 0; |