typedef struct
{
+ int startup;
double average; // average time between packets
int64_t last; // last timestamp seen on this stream
int id; // stream id
(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;
}
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 )
{
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;
//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;
}
/***********************************************************************
}
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 )
{
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;
// 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
++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
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;
}
}
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;