diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index 6f7185c2d9..b360831a5f 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -2072,6 +2072,27 @@ get_pts_timeout (const RtpTimer * timer) return timer->timeout - timer->offset; } +static inline gboolean +safe_add (guint64 * res, guint64 val, gint64 offset) +{ + if (val <= G_MAXINT64) { + gint64 tmp = (gint64) val + offset; + if (tmp >= 0) { + *res = tmp; + return TRUE; + } + return FALSE; + } + /* From here, val > G_MAXINT64 */ + + /* Negative value */ + if (offset < 0 && val < -offset) + return FALSE; + + *res = val + offset; + return TRUE; +} + static void update_timer_offsets (GstRtpJitterBuffer * jitterbuffer) { @@ -2081,8 +2102,15 @@ update_timer_offsets (GstRtpJitterBuffer * jitterbuffer) while (test) { if (test->type != RTP_TIMER_EXPECTED) { - test->timeout = get_pts_timeout (test) + new_offset; - test->offset = new_offset; + GstClockTime pts = get_pts_timeout (test); + if (safe_add (&test->timeout, pts, new_offset)) { + test->offset = new_offset; + } else { + GST_DEBUG_OBJECT (jitterbuffer, + "Invalidating timeout (pts lower than new offset)"); + test->timeout = GST_CLOCK_TIME_NONE; + test->offset = 0; + } /* as we apply the offset on all timers, the order of timers won't * change and we can skip updating the timer queue */ } @@ -2130,7 +2158,8 @@ apply_offset (GstRtpJitterBuffer * jitterbuffer, GstClockTime timestamp) return -1; /* apply the timestamp offset, this is used for inter stream sync */ - timestamp += priv->ts_offset; + if (!safe_add (×tamp, timestamp, priv->ts_offset)) + timestamp = 0; /* add the offset, this is used when buffering */ timestamp += priv->out_offset;