summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2011-09-26 20:48:11 +0000
committerjstebbins <[email protected]>2011-09-26 20:48:11 +0000
commit18591273b5278c8b9f2a0ab60e71dcf789bffd1f (patch)
tree222b3ad74c1247409cd5413fd47e20912fd79709 /libhb
parent070be6a0fd2bdcf4c60a207c79e10d0451e9be6a (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.c40
-rw-r--r--libhb/stream.c33
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;