rtpjitterbuffer: Avoid generation of invalid timestamps

When updating timestamps and timer timeouts with a new offset, make sure that
the resulting value is valid (and not a negative (signed) value which ends up in
a massive (unsigned) value).

Fixes #571

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/960>
This commit is contained in:
Edward Hervey 2021-04-22 08:57:23 +02:00 committed by Edward Hervey
parent a2c16ec632
commit 4d3b8d1129

View file

@ -2072,6 +2072,27 @@ get_pts_timeout (const RtpTimer * timer)
return timer->timeout - timer->offset; 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 static void
update_timer_offsets (GstRtpJitterBuffer * jitterbuffer) update_timer_offsets (GstRtpJitterBuffer * jitterbuffer)
{ {
@ -2081,8 +2102,15 @@ update_timer_offsets (GstRtpJitterBuffer * jitterbuffer)
while (test) { while (test) {
if (test->type != RTP_TIMER_EXPECTED) { if (test->type != RTP_TIMER_EXPECTED) {
test->timeout = get_pts_timeout (test) + new_offset; GstClockTime pts = get_pts_timeout (test);
test->offset = new_offset; 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 /* as we apply the offset on all timers, the order of timers won't
* change and we can skip updating the timer queue */ * change and we can skip updating the timer queue */
} }
@ -2130,7 +2158,8 @@ apply_offset (GstRtpJitterBuffer * jitterbuffer, GstClockTime timestamp)
return -1; return -1;
/* apply the timestamp offset, this is used for inter stream sync */ /* apply the timestamp offset, this is used for inter stream sync */
timestamp += priv->ts_offset; if (!safe_add (&timestamp, timestamp, priv->ts_offset))
timestamp = 0;
/* add the offset, this is used when buffering */ /* add the offset, this is used when buffering */
timestamp += priv->out_offset; timestamp += priv->out_offset;