From 5c05c88ac4db77caaff3ec8eee68b6d2df856ee7 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 30 Jan 2018 11:56:01 -0500 Subject: [PATCH] TT#31198 handle RTP seq and TS resets Change-Id: I853059769e5277391c3ff5c0f13e164d4dc53d4c --- lib/codeclib.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/codeclib.c b/lib/codeclib.c index 361fac6cd..ab054b2c5 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -10,6 +10,10 @@ +#define PACKET_SEQ_DUPE_THRES 100 +#define PACKET_TS_RESET_THRES 5000 // milliseconds + + #ifndef dbg #ifdef __DEBUG @@ -182,8 +186,18 @@ int decoder_input_data(decoder_t *dec, const str *data, unsigned long ts, } else { // shift pts according to rtp ts shift - dec->pts += (ts - dec->rtp_ts); - // XXX handle lost packets here if timestamps don't line up? + u_int64_t shift_ts = ts - dec->rtp_ts; + if ((shift_ts * dec->avcctx->time_base.num * 1000) / dec->avcctx->time_base.den + > PACKET_TS_RESET_THRES) + { + ilog(LOG_DEBUG, "Timestamp disconinuity detected, resetting timestamp from " + "%lu to %lu", + dec->rtp_ts, ts); + // XXX handle lost packets here if timestamps don't line up? + dec->pts += dec->avcctx->time_base.den; + } + else + dec->pts += shift_ts; } dec->rtp_ts = ts; @@ -423,6 +437,7 @@ out: ps->seq = (packet->seq + 1) & 0xffff; return packet; } + int packet_sequencer_insert(packet_sequencer_t *ps, seq_packet_t *p) { // check seq for dupes if (G_UNLIKELY(ps->seq == -1)) { @@ -432,11 +447,22 @@ int packet_sequencer_insert(packet_sequencer_t *ps, seq_packet_t *p) { } int diff = p->seq - ps->seq; - if (diff >= 0x8000) + // early packet: p->seq = 200, ps->seq = 150, diff = 50 + if (G_LIKELY(diff >= 0 && diff < PACKET_SEQ_DUPE_THRES)) + goto seq_ok; + // early packet with wrap-around: p->seq = 20, ps->seq = 65530, diff = -65510 + if (diff < (-0xffff + PACKET_SEQ_DUPE_THRES)) + goto seq_ok; + // recent duplicate: p->seq = 1000, ps->seq = 1080, diff = -80 + if (diff < 0 && diff > -PACKET_SEQ_DUPE_THRES) return -1; - if (diff < 0 && diff > -0x8000) + // recent duplicate after wrap-around: p->seq = 65530, ps->seq = 30, diff = 65500 + if (diff > (0xffff - PACKET_SEQ_DUPE_THRES)) return -1; + // everything else we consider a seq reset + ilog(LOG_DEBUG, "Seq reset detected: expected seq %i, received seq %i", ps->seq, p->seq); + ps->seq = p->seq; // seq ok - fall thru seq_ok: if (g_tree_lookup(ps->packets, GINT_TO_POINTER(p->seq)))