From 8d924611e74ba8b6c36fe24db5b3648850751bf7 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 1 Sep 2009 12:41:36 +0200 Subject: jitterbuffer: make sure time does not go backwards When we construct a timestamp that would result in a timestamp that is earlier than when the packet was received, reset the skew calculation as this is probably a sign that the sender restarted or paused. Fixes #593354 --- gst/rtpmanager/gstrtpjitterbuffer.c | 24 ++++++++++++------------ gst/rtpmanager/rtpjitterbuffer.c | 24 +++++++++++++++++++----- gst/rtpmanager/rtpjitterbuffer.h | 10 +++++----- 3 files changed, 36 insertions(+), 22 deletions(-) (limited to 'gst/rtpmanager') diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index e3d6ed09..cb343d96 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -1,7 +1,7 @@ /* * Farsight Voice+Video library * - * Copyright 2007 Collabora Ltd, + * Copyright 2007 Collabora Ltd, * Copyright 2007 Nokia Corporation * @author: Philippe Kalaf . * Copyright 2007 Wim Taymans @@ -30,17 +30,17 @@ * from a network source. It will also wait for missing packets up to a * configurable time limit using the #GstRtpJitterBuffer:latency property. * Packets arriving too late are considered to be lost packets. - * + * * This element acts as a live element and so adds #GstRtpJitterBuffer:latency * to the pipeline. - * + * * The element needs the clock-rate of the RTP payload in order to estimate the * delay. This information is obtained either from the caps on the sink pad or, * when no caps are present, from the #GstRtpJitterBuffer::request-pt-map signal. * To clear the previous pt-map use the #GstRtpJitterBuffer::clear-pt-map signal. - * + * * This element will automatically be used inside gstrtpbin. - * + * * * Example pipelines * |[ @@ -300,7 +300,7 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass) /** * GstRtpJitterBuffer::latency: - * + * * The maximum latency of the jitterbuffer. Packets will be kept in the buffer * for at most this time. */ @@ -310,8 +310,8 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass) G_PARAM_READWRITE)); /** * GstRtpJitterBuffer::drop-on-latency: - * - * Drop oldest buffers when the queue is completely filled. + * + * Drop oldest buffers when the queue is completely filled. */ g_object_class_install_property (gobject_class, PROP_DROP_ON_LATENCY, g_param_spec_boolean ("drop-on-latency", @@ -320,7 +320,7 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass) DEFAULT_DROP_ON_LATENCY, G_PARAM_READWRITE)); /** * GstRtpJitterBuffer::ts-offset: - * + * * Adjust GStreamer output buffer timestamps in the jitterbuffer with offset. * This is mainly used to ensure interstream synchronisation. */ @@ -332,7 +332,7 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass) /** * GstRtpJitterBuffer::do-lost: - * + * * Send out a GstRTPPacketLost event downstream when a packet is considered * lost. */ @@ -761,7 +761,7 @@ gst_rtp_jitter_buffer_flush_start (GstRtpJitterBuffer * jitterbuffer) GST_DEBUG_OBJECT (jitterbuffer, "Disabling pop on queue"); /* this unblocks any waiting pops on the src pad task */ JBUF_SIGNAL (priv); - /* unlock clock, we just unschedule, the entry will be released by the + /* unlock clock, we just unschedule, the entry will be released by the * locking streaming thread. */ if (priv->clock_id) { gst_clock_id_unschedule (priv->clock_id); @@ -1211,7 +1211,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstBuffer * buffer) * FALSE if a packet with the same seqnum was already in the queue, meaning we * have a duplicate. */ if (G_UNLIKELY (!rtp_jitter_buffer_insert (priv->jbuf, buffer, timestamp, - priv->clock_rate, &tail))) + priv->clock_rate, (priv->latency_ms * GST_MSECOND), &tail))) goto duplicate; /* signal addition of new buffer when the _loop is waiting. */ diff --git a/gst/rtpmanager/rtpjitterbuffer.c b/gst/rtpmanager/rtpjitterbuffer.c index a38c2141..86629e87 100644 --- a/gst/rtpmanager/rtpjitterbuffer.c +++ b/gst/rtpmanager/rtpjitterbuffer.c @@ -183,7 +183,7 @@ rtp_jitter_buffer_resync (RTPJitterBuffer * jbuf, GstClockTime time, * * Both the window and the weighting used for averaging influence the accuracy * of the drift estimation. Finding the correct parameters turns out to be a - * compromise between accuracy and inertia. + * compromise between accuracy and inertia. * * We use a 2 second window or up to 512 data points, which is statistically big * enough to catch spikes (FIXME, detect spikes). @@ -195,7 +195,7 @@ rtp_jitter_buffer_resync (RTPJitterBuffer * jbuf, GstClockTime time, */ static GstClockTime calculate_skew (RTPJitterBuffer * jbuf, guint32 rtptime, GstClockTime time, - guint32 clock_rate) + guint32 clock_rate, GstClockTime max_delay) { guint64 ext_rtptime; guint64 send_diff, recv_diff; @@ -278,7 +278,7 @@ calculate_skew (RTPJitterBuffer * jbuf, guint32 rtptime, GstClockTime time, * changed too quickly we have to resync because the server likely restarted * its timestamps. */ if (ABS (delta - jbuf->skew) > GST_SECOND) { - GST_WARNING ("delta %" GST_TIME_FORMAT " too big, reset skew", + GST_WARNING ("delta - skew: %" GST_TIME_FORMAT " too big, reset skew", GST_TIME_ARGS (delta - jbuf->skew)); rtp_jitter_buffer_resync (jbuf, time, gstrtptime, ext_rtptime, TRUE); send_diff = 0; @@ -386,6 +386,18 @@ no_skew: out_time = jbuf->prev_out_time; } } + + if (out_time + max_delay < time) { + /* if we are going to produce a timestamp that is later than the input + * timestamp, we need to reset the jitterbuffer. Likely the server paused + * temporarily */ + GST_DEBUG ("out %" GST_TIME_FORMAT " + %" G_GUINT64_FORMAT " < time %" + GST_TIME_FORMAT ", reset jitterbuffer", GST_TIME_ARGS (out_time), + max_delay, GST_TIME_ARGS (time)); + rtp_jitter_buffer_resync (jbuf, time, gstrtptime, ext_rtptime, TRUE); + out_time = time; + send_diff = 0; + } } else out_time = -1; @@ -404,6 +416,7 @@ no_skew: * @buf: a buffer * @time: a running_time when this buffer was received in nanoseconds * @clock_rate: the clock-rate of the payload of @buf + * @max_delay: the maximum lateness of @buf * @tail: TRUE when the tail element changed. * * Inserts @buf into the packet queue of @jbuf. The sequence number of the @@ -415,7 +428,8 @@ no_skew: */ gboolean rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, GstBuffer * buf, - GstClockTime time, guint32 clock_rate, gboolean * tail) + GstClockTime time, guint32 clock_rate, GstClockTime max_delay, + gboolean * tail) { GList *list; guint32 rtptime; @@ -449,7 +463,7 @@ rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, GstBuffer * buf, * receive time, this function will retimestamp @buf with the skew corrected * running time. */ rtptime = gst_rtp_buffer_get_timestamp (buf); - time = calculate_skew (jbuf, rtptime, time, clock_rate); + time = calculate_skew (jbuf, rtptime, time, clock_rate, max_delay); GST_BUFFER_TIMESTAMP (buf) = time; /* It's more likely that the packet was inserted in the front of the buffer */ diff --git a/gst/rtpmanager/rtpjitterbuffer.h b/gst/rtpmanager/rtpjitterbuffer.h index ff1a16b0..9a7232c0 100644 --- a/gst/rtpmanager/rtpjitterbuffer.h +++ b/gst/rtpmanager/rtpjitterbuffer.h @@ -82,9 +82,10 @@ RTPJitterBuffer* rtp_jitter_buffer_new (void); void rtp_jitter_buffer_reset_skew (RTPJitterBuffer *jbuf); gboolean rtp_jitter_buffer_insert (RTPJitterBuffer *jbuf, GstBuffer *buf, - GstClockTime time, - guint32 clock_rate, - gboolean *tail); + GstClockTime time, + guint32 clock_rate, + GstClockTime max_delay, + gboolean *tail); GstBuffer * rtp_jitter_buffer_peek (RTPJitterBuffer *jbuf); GstBuffer * rtp_jitter_buffer_pop (RTPJitterBuffer *jbuf); @@ -95,7 +96,6 @@ guint32 rtp_jitter_buffer_get_ts_diff (RTPJitterBuffer *jbuf) void rtp_jitter_buffer_get_sync (RTPJitterBuffer *jbuf, guint64 *rtptime, guint64 *timestamp, guint32 *clock_rate, - guint64 *last_rtptime); - + guint64 *last_rtptime); #endif /* __RTP_JITTER_BUFFER_H__ */ -- cgit