diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2007-09-16 19:40:31 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2007-09-16 19:40:31 +0000 |
commit | 04d3b8290698e41034809e8baec11622ca128243 (patch) | |
tree | df6c408b0b15acbf31a1743d7ce7a882b47a9b7d /gst/rtpmanager/gstrtpjitterbuffer.c | |
parent | 51990d65dc103c9355bb83ef4bc75f7e1eae0ac4 (diff) | |
download | gst-plugins-bad-04d3b8290698e41034809e8baec11622ca128243.tar.gz gst-plugins-bad-04d3b8290698e41034809e8baec11622ca128243.tar.bz2 gst-plugins-bad-04d3b8290698e41034809e8baec11622ca128243.zip |
gst/rtpmanager/gstrtpbin.c: Use lock to protect variable.
Original commit message from CVS:
* gst/rtpmanager/gstrtpbin.c: (gst_rtp_bin_set_property),
(gst_rtp_bin_get_property):
Use lock to protect variable.
* gst/rtpmanager/gstrtpjitterbuffer.c:
(gst_rtp_jitter_buffer_class_init),
(gst_jitter_buffer_sink_parse_caps), (gst_rtp_jitter_buffer_chain),
(convert_rtptime_to_gsttime), (gst_rtp_jitter_buffer_loop):
Reconstruct GST timestamp from RTP timestamps based on measured clock
skew and sync offset.
* gst/rtpmanager/rtpjitterbuffer.c: (rtp_jitter_buffer_init),
(rtp_jitter_buffer_set_tail_changed),
(rtp_jitter_buffer_set_clock_rate),
(rtp_jitter_buffer_get_clock_rate), (calculate_skew),
(rtp_jitter_buffer_insert), (rtp_jitter_buffer_peek):
* gst/rtpmanager/rtpjitterbuffer.h:
Measure clock skew.
Add callback to be notfied when a new packet was inserted at the tail.
* gst/rtpmanager/rtpsource.c: (rtp_source_init),
(calculate_jitter), (rtp_source_send_rtp):
* gst/rtpmanager/rtpsource.h:
Remove clock skew detection, it's move to the jitterbuffer now.
Diffstat (limited to 'gst/rtpmanager/gstrtpjitterbuffer.c')
-rw-r--r-- | gst/rtpmanager/gstrtpjitterbuffer.c | 153 |
1 files changed, 78 insertions, 75 deletions
diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index 327ff0a3..57be42ec 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -320,7 +320,7 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass) klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_jitter_buffer_clear_pt_map); GST_DEBUG_CATEGORY_INIT - (rtpjitterbuffer_debug, "rtpjitterbuffer", 0, "RTP Jitter Buffer"); + (rtpjitterbuffer_debug, "gstrtpjitterbuffer", 0, "RTP Jitter Buffer"); } static void @@ -453,6 +453,8 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer, if (priv->clock_rate <= 0) goto wrong_rate; + rtp_jitter_buffer_set_clock_rate (priv->jbuf, priv->clock_rate); + GST_DEBUG_OBJECT (jitterbuffer, "got clock-rate %d", priv->clock_rate); /* gah, clock-base is uint. If we don't have a base, we will use the first @@ -794,6 +796,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstBuffer * buffer) GstRtpJitterBufferPrivate *priv; guint16 seqnum; GstFlowReturn ret = GST_FLOW_OK; + GstClockTime timestamp; jitterbuffer = GST_RTP_JITTER_BUFFER (gst_pad_get_parent (pad)); @@ -811,10 +814,23 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstBuffer * buffer) gst_rtp_jitter_buffer_get_clock_rate (jitterbuffer, pt); if (priv->clock_rate == -1) goto not_negotiated; + + rtp_jitter_buffer_set_clock_rate (priv->jbuf, priv->clock_rate); } + /* take the timestamp of the buffer. This is the time when the packet was + * received and is used to calculate jitter and clock skew. We will adjust + * this timestamp with the smoothed value after processing it in the + * jitterbuffer. */ + timestamp = GST_BUFFER_TIMESTAMP (buffer); + /* bring to running time */ + timestamp = gst_segment_to_running_time (&priv->segment, GST_FORMAT_TIME, + timestamp); + seqnum = gst_rtp_buffer_get_seq (buffer); - GST_DEBUG_OBJECT (jitterbuffer, "Received packet #%d", seqnum); + GST_DEBUG_OBJECT (jitterbuffer, + "Received packet #%d at time %" GST_TIME_FORMAT, seqnum, + GST_TIME_ARGS (timestamp)); JBUF_LOCK_CHECK (priv, out_flushing); /* don't accept more data on EOS */ @@ -852,7 +868,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstBuffer * buffer) /* now insert the packet into the queue in sorted order. This function returns * FALSE if a packet with the same seqnum was already in the queue, meaning we * have a duplicate. */ - if (!rtp_jitter_buffer_insert (priv->jbuf, buffer)) + if (!rtp_jitter_buffer_insert (priv->jbuf, buffer, timestamp)) goto duplicate; /* signal addition of new buffer */ @@ -926,6 +942,37 @@ duplicate: } } +static GstClockTime +convert_rtptime_to_gsttime (GstRtpJitterBuffer * jitterbuffer, + guint64 exttimestamp) +{ + GstClockTime timestamp; + GstRtpJitterBufferPrivate *priv; + + priv = jitterbuffer->priv; + + /* construct a timestamp from the RTP timestamp now. We don't apply this + * timestamp to the outgoing buffer yet as the popped buffer might not be the + * one we need to push out right now. */ + timestamp = + gst_util_uint64_scale_int (exttimestamp, GST_SECOND, priv->clock_rate); + + /* apply first observed timestamp */ + timestamp += priv->jbuf->base_time; + + /* apply the current clock skew */ + timestamp += priv->jbuf->skew; + + /* 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; +} + /** * This funcion will push out buffers on the source pad. * @@ -942,9 +989,7 @@ gst_rtp_jitter_buffer_loop (GstRtpJitterBuffer * jitterbuffer) guint16 seqnum; guint32 rtp_time; GstClockTime timestamp; - gint64 running_time; guint64 exttimestamp; - gint ts_offset_rtp; priv = jitterbuffer->priv; @@ -968,19 +1013,29 @@ again: /* pop a buffer, we must have a buffer now */ outbuf = rtp_jitter_buffer_pop (priv->jbuf); - seqnum = gst_rtp_buffer_get_seq (outbuf); - /* get the max deadline to wait for the missing packets, this is the time - * of the currently popped packet */ + /* construct extended RTP timestamp from packet */ rtp_time = gst_rtp_buffer_get_timestamp (outbuf); exttimestamp = gst_rtp_buffer_ext_timestamp (&priv->exttimestamp, rtp_time); + /* if no clock_base was given, take first ts as base */ + if (priv->clock_base == -1) { + GST_DEBUG_OBJECT (jitterbuffer, + "no clock base, using exttimestamp %" G_GUINT64_FORMAT, exttimestamp); + priv->clock_base = exttimestamp; + } + /* subtract the base clock time so that we start counting from 0 */ + exttimestamp -= priv->clock_base; + GST_DEBUG_OBJECT (jitterbuffer, "Popped buffer #%d, rtptime %u, exttime %" G_GUINT64_FORMAT ", now %d left", seqnum, rtp_time, exttimestamp, rtp_jitter_buffer_num_packets (priv->jbuf)); + /* convert the RTP timestamp to a gstreamer timestamp. */ + timestamp = convert_rtptime_to_gsttime (jitterbuffer, exttimestamp); + /* 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, * a buffer with a lower seqnum could arrive later and we want to push that @@ -991,7 +1046,7 @@ again: * packet expires. */ if (priv->next_seqnum == -1 || priv->next_seqnum != seqnum) { GstClockID id; - GstClockTimeDiff jitter; + GstClockTime sync_time; GstClockReturn ret; GstClock *clock; @@ -1007,34 +1062,6 @@ again: GST_DEBUG_OBJECT (jitterbuffer, "First buffer %d, do sync", seqnum); } - GST_DEBUG_OBJECT (jitterbuffer, - "exttimestamp %" G_GUINT64_FORMAT ", base %" G_GINT64_FORMAT, - exttimestamp, priv->clock_base); - - /* if no clock_base was given, take first ts as base */ - if (priv->clock_base == -1) { - GST_DEBUG_OBJECT (jitterbuffer, - "no clock base, using exttimestamp %" G_GUINT64_FORMAT, exttimestamp); - priv->clock_base = exttimestamp; - } - - /* take rtp timestamp offset into account, this should not wrap around since - * we are dealing with the extended timestamp here. */ - exttimestamp -= priv->clock_base; - - /* bring timestamp to gst time */ - timestamp = - gst_util_uint64_scale_int (exttimestamp, GST_SECOND, priv->clock_rate); - - GST_DEBUG_OBJECT (jitterbuffer, - "exttimestamp %" G_GUINT64_FORMAT ", clock-rate %u, timestamp %" - GST_TIME_FORMAT, exttimestamp, priv->clock_rate, - GST_TIME_ARGS (timestamp)); - - /* bring to running time */ - running_time = gst_segment_to_running_time (&priv->segment, GST_FORMAT_TIME, - timestamp); - GST_OBJECT_LOCK (jitterbuffer); clock = GST_ELEMENT_CLOCK (jitterbuffer); if (!clock) { @@ -1043,25 +1070,21 @@ again: goto push_buffer; } - /* add latency, this includes our own latency and the peer latency. */ - running_time += (priv->latency_ms * GST_MSECOND); - running_time += priv->peer_latency; - - GST_DEBUG_OBJECT (jitterbuffer, "sync to running_time %" GST_TIME_FORMAT, - GST_TIME_ARGS (running_time)); + GST_DEBUG_OBJECT (jitterbuffer, "sync to timestamp %" GST_TIME_FORMAT, + GST_TIME_ARGS (timestamp)); /* prepare for sync against clock */ - running_time += GST_ELEMENT_CAST (jitterbuffer)->base_time; + sync_time = timestamp + GST_ELEMENT_CAST (jitterbuffer)->base_time; /* create an entry for the clock */ - id = priv->clock_id = gst_clock_new_single_shot_id (clock, running_time); + id = priv->clock_id = gst_clock_new_single_shot_id (clock, sync_time); priv->waiting_seqnum = seqnum; GST_OBJECT_UNLOCK (jitterbuffer); /* release the lock so that the other end can push stuff or unlock */ JBUF_UNLOCK (priv); - ret = gst_clock_id_wait (id, &jitter); + ret = gst_clock_id_wait (id, NULL); JBUF_LOCK (priv); /* and free the entry */ @@ -1080,8 +1103,9 @@ again: if (ret == GST_CLOCK_UNSCHEDULED) { GST_DEBUG_OBJECT (jitterbuffer, "Wait got unscheduled, will retry to push with new buffer"); - /* reinsert popped buffer into queue */ - if (!rtp_jitter_buffer_insert (priv->jbuf, outbuf)) { + /* reinsert popped buffer into queue, no need to recalculate skew, we do + * that when inserting the buffer in the chain function */ + if (!rtp_jitter_buffer_insert (priv->jbuf, outbuf, -1)) { GST_DEBUG_OBJECT (jitterbuffer, "Duplicate packet #%d detected, dropping", seqnum); priv->num_duplicates++; @@ -1089,6 +1113,9 @@ again: } goto again; } + /* After waiting, we might have a better estimate of skew, generate a new + * timestamp before pushing out the buffer */ + timestamp = convert_rtptime_to_gsttime (jitterbuffer, exttimestamp); } push_buffer: /* check if we are pushing something unexpected */ @@ -1105,37 +1132,13 @@ push_buffer: /* update stats */ priv->num_late += dropped; - /* set DISCONT flag */ + /* set DISCONT flag when we missed a packet. */ outbuf = gst_buffer_make_metadata_writable (outbuf); GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); } - /* apply the timestamp offset */ - if (priv->ts_offset > 0) - ts_offset_rtp = - gst_util_uint64_scale_int (priv->ts_offset, priv->clock_rate, - GST_SECOND); - else if (priv->ts_offset < 0) - ts_offset_rtp = - -gst_util_uint64_scale_int (-priv->ts_offset, priv->clock_rate, - GST_SECOND); - else - ts_offset_rtp = 0; - - if (ts_offset_rtp != 0) { - guint32 timestamp; - - /* if the offset changed, mark with discont */ - if (priv->ts_offset != priv->prev_ts_offset) { - GST_DEBUG_OBJECT (jitterbuffer, "changing offset to %d", ts_offset_rtp); - GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); - priv->prev_ts_offset = priv->ts_offset; - } - - timestamp = gst_rtp_buffer_get_timestamp (outbuf); - timestamp += ts_offset_rtp; - gst_rtp_buffer_set_timestamp (outbuf, timestamp); - } + /* apply timestamp to buffer now */ + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; /* now we are ready to push the buffer. Save the seqnum and release the lock * so the other end can push stuff in the queue again. */ |