diff options
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | gst/rtpmanager/gstrtpjitterbuffer.c | 26 | ||||
-rw-r--r-- | gst/rtpmanager/rtpjitterbuffer.c | 73 | ||||
-rw-r--r-- | gst/rtpmanager/rtpjitterbuffer.h | 3 |
4 files changed, 92 insertions, 29 deletions
@@ -1,5 +1,24 @@ 2007-10-02 Wim Taymans <wim.taymans@gmail.com> + * gst/rtpmanager/gstrtpjitterbuffer.c: + (gst_rtp_jitter_buffer_flush_start), + (gst_rtp_jitter_buffer_flush_stop), + (gst_rtp_jitter_buffer_change_state), (apply_offset), + (gst_rtp_jitter_buffer_loop): + Remove some old unused variables. + Don't add the latency to the skew corrected timestamp, latency is only + used to sync against the clock. + Improve debugging. + + * gst/rtpmanager/rtpjitterbuffer.c: (rtp_jitter_buffer_init), + (rtp_jitter_buffer_reset_skew), (calculate_skew): + * gst/rtpmanager/rtpjitterbuffer.h: + Handle case where server timestamp goes backwards or wildly jumps by + temporarily pausing the skew correction. + Improve debugging. + +2007-10-02 Wim Taymans <wim.taymans@gmail.com> + * gst/sdp/Makefile.am: Forgot to commit makefile. diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index 2155df89..e087a7fe 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -152,7 +152,6 @@ struct _GstRtpJitterBufferPrivate /* clock rate and rtp timestamp offset */ gint32 clock_rate; gint64 clock_base; - guint64 exttimestamp; gint64 prev_ts_offset; /* when we are shutting down */ @@ -525,7 +524,6 @@ 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); - rtp_jitter_buffer_flush (priv->jbuf); /* unlock clock, we just unschedule, the entry will be released by the * locking streaming thread. */ if (priv->clock_id) @@ -549,7 +547,8 @@ gst_rtp_jitter_buffer_flush_stop (GstRtpJitterBuffer * jitterbuffer) priv->next_seqnum = -1; priv->clock_rate = -1; priv->eos = FALSE; - priv->exttimestamp = -1; + rtp_jitter_buffer_flush (priv->jbuf); + rtp_jitter_buffer_reset_skew (priv->jbuf); JBUF_UNLOCK (priv); } @@ -606,7 +605,8 @@ gst_rtp_jitter_buffer_change_state (GstElement * element, priv->peer_latency = 0; /* block until we go to PLAYING */ priv->blocked = TRUE; - priv->exttimestamp = -1; + /* reset skew detection initialy */ + rtp_jitter_buffer_reset_skew (priv->jbuf); JBUF_UNLOCK (priv); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: @@ -943,7 +943,7 @@ duplicate: } static GstClockTime -apply_latency (GstRtpJitterBuffer * jitterbuffer, GstClockTime timestamp) +apply_offset (GstRtpJitterBuffer * jitterbuffer, GstClockTime timestamp) { GstRtpJitterBufferPrivate *priv; @@ -955,10 +955,6 @@ apply_latency (GstRtpJitterBuffer * jitterbuffer, GstClockTime timestamp) /* apply the timestamp offset */ timestamp += priv->ts_offset; - /* add latency, this includes our own latency and the peer latency. */ - timestamp += (priv->latency_ms * GST_MSECOND); - timestamp += priv->peer_latency; - return timestamp; } @@ -1011,8 +1007,9 @@ again: seqnum, GST_TIME_ARGS (timestamp), rtp_jitter_buffer_num_packets (priv->jbuf)); - /* apply our latency to the incomming buffer before syncing. */ - out_time = apply_latency (jitterbuffer, timestamp); + /* apply our timestamp offset to the incomming buffer, this will be our output + * timestamp. */ + out_time = apply_offset (jitterbuffer, timestamp); /* If we don't know what the next seqnum should be (== -1) we have to wait * because it might be possible that we are not receiving this buffer in-order, @@ -1054,6 +1051,9 @@ again: /* prepare for sync against clock */ sync_time = out_time + GST_ELEMENT_CAST (jitterbuffer)->base_time; + /* add latency, this includes our own latency and the peer latency. */ + sync_time += (priv->latency_ms * GST_MSECOND); + sync_time += priv->peer_latency; /* create an entry for the clock */ id = priv->clock_id = gst_clock_new_single_shot_id (clock, sync_time); @@ -1093,7 +1093,7 @@ again: goto again; } /* Get new timestamp, latency might have changed */ - out_time = apply_latency (jitterbuffer, timestamp); + out_time = apply_offset (jitterbuffer, timestamp); } push_buffer: /* check if we are pushing something unexpected */ @@ -1115,7 +1115,7 @@ push_buffer: GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); } - /* apply timestamp to buffer now */ + /* apply timestamp with offset to buffer now */ GST_BUFFER_TIMESTAMP (outbuf) = out_time; /* now we are ready to push the buffer. Save the seqnum and release the lock diff --git a/gst/rtpmanager/rtpjitterbuffer.c b/gst/rtpmanager/rtpjitterbuffer.c index d0304198..a002cc38 100644 --- a/gst/rtpmanager/rtpjitterbuffer.c +++ b/gst/rtpmanager/rtpjitterbuffer.c @@ -65,13 +65,8 @@ static void rtp_jitter_buffer_init (RTPJitterBuffer * jbuf) { jbuf->packets = g_queue_new (); - jbuf->base_time = -1; - jbuf->base_rtptime = -1; - jbuf->ext_rtptime = -1; - jbuf->window_pos = 0; - jbuf->window_filling = TRUE; - jbuf->window_min = 0; - jbuf->skew = 0; + + rtp_jitter_buffer_reset_skew (jbuf); } static void @@ -130,6 +125,18 @@ rtp_jitter_buffer_get_clock_rate (RTPJitterBuffer * jbuf) return jbuf->clock_rate; } +void +rtp_jitter_buffer_reset_skew (RTPJitterBuffer * jbuf) +{ + jbuf->base_time = -1; + jbuf->base_rtptime = -1; + jbuf->ext_rtptime = -1; + jbuf->window_pos = 0; + jbuf->window_filling = TRUE; + jbuf->window_min = 0; + jbuf->skew = 0; + jbuf->prev_send_diff = -1; +} /* For the clock skew we use a windowed low point averaging algorithm as can be * found in http://www.grame.fr/pub/TR-050601.pdf. The idea is that the jitter is @@ -204,14 +211,47 @@ calculate_skew (RTPJitterBuffer * jbuf, guint32 rtptime, GstClockTime time) gstrtptime = gst_util_uint64_scale_int (ext_rtptime, GST_SECOND, jbuf->clock_rate); +again: /* first time, lock on to time and gstrtptime */ if (jbuf->base_time == -1) jbuf->base_time = time; if (jbuf->base_rtptime == -1) jbuf->base_rtptime = gstrtptime; - /* elapsed time at sender */ - send_diff = gstrtptime - jbuf->base_rtptime; + if (gstrtptime >= jbuf->base_rtptime) + send_diff = gstrtptime - jbuf->base_rtptime; + else { + /* elapsed time at sender, timestamps can go backwards and thus be smaller + * than our base time, take a new base time in that case. */ + GST_DEBUG ("backward timestamps at server, taking new base time"); + jbuf->base_rtptime = gstrtptime; + jbuf->base_time = time; + send_diff = 0; + } + + GST_DEBUG ("extrtp %" G_GUINT64_FORMAT ", gstrtp %" GST_TIME_FORMAT ", base %" + GST_TIME_FORMAT ", send_diff %" GST_TIME_FORMAT, ext_rtptime, + GST_TIME_ARGS (gstrtptime), GST_TIME_ARGS (jbuf->base_rtptime), + GST_TIME_ARGS (send_diff)); + + if (jbuf->prev_send_diff != -1) { + gint64 delta_diff; + + if (send_diff > jbuf->prev_send_diff) + delta_diff = send_diff - jbuf->prev_send_diff; + else + delta_diff = jbuf->prev_send_diff - send_diff; + + /* server changed rtp timestamps too quickly, reset skew detection and start + * again. */ + if (delta_diff > GST_SECOND / 4) { + GST_DEBUG ("delta changed too quickly %" GST_TIME_FORMAT " reset skew", + GST_TIME_ARGS (delta_diff)); + rtp_jitter_buffer_reset_skew (jbuf); + goto again; + } + } + jbuf->prev_send_diff = send_diff; /* we don't have an arrival timestamp so we can't do skew detection. we * should still apply a timestamp based on RTP timestamp and base_time */ @@ -221,6 +261,10 @@ calculate_skew (RTPJitterBuffer * jbuf, guint32 rtptime, GstClockTime time) /* elapsed time at receiver, includes the jitter */ recv_diff = time - jbuf->base_time; + GST_DEBUG ("time %" GST_TIME_FORMAT ", base %" GST_TIME_FORMAT ", recv_diff %" + GST_TIME_FORMAT, GST_TIME_ARGS (time), GST_TIME_ARGS (jbuf->base_time), + GST_TIME_ARGS (recv_diff)); + /* measure the diff */ delta = ((gint64) recv_diff) - ((gint64) send_diff); @@ -228,8 +272,7 @@ calculate_skew (RTPJitterBuffer * jbuf, guint32 rtptime, GstClockTime time) if (jbuf->window_filling) { /* we are filling the window */ - GST_DEBUG ("filling %d %" G_GINT64_FORMAT ", send_diff %" G_GUINT64_FORMAT, - pos, delta, send_diff); + GST_DEBUG ("filling %d, delta %" G_GINT64_FORMAT, pos, delta); jbuf->window[pos++] = delta; /* calc the min delta we observed */ if (pos == 1 || delta < jbuf->window_min) @@ -290,8 +333,8 @@ calculate_skew (RTPJitterBuffer * jbuf, guint32 rtptime, GstClockTime time) } /* average the min values */ jbuf->skew = (jbuf->window_min + (124 * jbuf->skew)) / 125; - GST_DEBUG ("new min: %" G_GINT64_FORMAT ", skew %" G_GINT64_FORMAT, - jbuf->window_min, jbuf->skew); + GST_DEBUG ("delta %" G_GINT64_FORMAT ", new min: %" G_GINT64_FORMAT, + delta, jbuf->window_min); } /* wrap around in the window */ if (pos >= jbuf->window_size) @@ -303,9 +346,7 @@ no_skew: * adjusted for the clock skew .*/ out_time = jbuf->base_time + send_diff + jbuf->skew; - GST_DEBUG ("base %" GST_TIME_FORMAT ", diff %" GST_TIME_FORMAT ", skew %" - G_GINT64_FORMAT ", out %" GST_TIME_FORMAT, - GST_TIME_ARGS (jbuf->base_time), GST_TIME_ARGS (send_diff), + GST_DEBUG ("skew %" G_GINT64_FORMAT ", out %" GST_TIME_FORMAT, jbuf->skew, GST_TIME_ARGS (out_time)); return out_time; diff --git a/gst/rtpmanager/rtpjitterbuffer.h b/gst/rtpmanager/rtpjitterbuffer.h index fdc8d488..d9903a1d 100644 --- a/gst/rtpmanager/rtpjitterbuffer.h +++ b/gst/rtpmanager/rtpjitterbuffer.h @@ -66,6 +66,7 @@ struct _RTPJitterBuffer { gboolean window_filling; gint64 window_min; gint64 skew; + gint64 prev_send_diff; RTPTailChanged tail_changed; gpointer user_data; @@ -86,6 +87,8 @@ void rtp_jitter_buffer_set_tail_changed (RTPJitterBuffer *jbuf, void rtp_jitter_buffer_set_clock_rate (RTPJitterBuffer *jbuf, gint clock_rate); gint rtp_jitter_buffer_get_clock_rate (RTPJitterBuffer *jbuf); +void rtp_jitter_buffer_reset_skew (RTPJitterBuffer *jbuf); + gboolean rtp_jitter_buffer_insert (RTPJitterBuffer *jbuf, GstBuffer *buf, GstClockTime time); GstBuffer * rtp_jitter_buffer_pop (RTPJitterBuffer *jbuf); |