summaryrefslogtreecommitdiffstats
path: root/gst/rtpmanager/gstrtpjitterbuffer.c
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2008-09-05 13:52:34 +0000
committerWim Taymans <wim.taymans@gmail.com>2008-09-05 13:52:34 +0000
commita35d1dde421be0655eb36fed9f415a25f5fa00e0 (patch)
treec0bfaa3e8fccfad821f2175dc419987caf0c2636 /gst/rtpmanager/gstrtpjitterbuffer.c
parent64cd01e7e8a143e523466c911f7bb2e148508c3b (diff)
downloadgst-plugins-bad-a35d1dde421be0655eb36fed9f415a25f5fa00e0.tar.gz
gst-plugins-bad-a35d1dde421be0655eb36fed9f415a25f5fa00e0.tar.bz2
gst-plugins-bad-a35d1dde421be0655eb36fed9f415a25f5fa00e0.zip
gst/rtpmanager/gstrtpbin.*: Add signal to notify listeners when a sender becomes a receiver.
Original commit message from CVS: * gst/rtpmanager/gstrtpbin.c: (on_sender_timeout), (create_session), (gst_rtp_bin_associate), (gst_rtp_bin_sync_chain), (gst_rtp_bin_class_init), (gst_rtp_bin_request_new_pad): * gst/rtpmanager/gstrtpbin.h: Add signal to notify listeners when a sender becomes a receiver. Tweak lip-sync code, don't store our own copy of the ts-offset of the jitterbuffer, don't adjust sync if the change is less than 4msec. Get the RTP timestamp <-> GStreamer timestamp relation directly from the jitterbuffer instead of our inaccurate version from the source. * gst/rtpmanager/gstrtpjitterbuffer.c: (gst_rtp_jitter_buffer_chain), (gst_rtp_jitter_buffer_loop), (gst_rtp_jitter_buffer_get_sync): * gst/rtpmanager/gstrtpjitterbuffer.h: Add G_LIKELY macros, use global defines for max packet reorder and dropouts. Reset the jitterbuffer clock skew detection when packets seqnums are changed unexpectedly. * gst/rtpmanager/gstrtpsession.c: (on_sender_timeout), (gst_rtp_session_class_init), (gst_rtp_session_init): * gst/rtpmanager/gstrtpsession.h: Add sender timeout signal. * gst/rtpmanager/rtpjitterbuffer.c: (rtp_jitter_buffer_reset_skew), (calculate_skew), (rtp_jitter_buffer_insert), (rtp_jitter_buffer_get_sync): * gst/rtpmanager/rtpjitterbuffer.h: Add some G_LIKELY macros. Keep track of the extended RTP timestamp so that we can report the RTP timestamp <-> GStreamer timestamp relation for lip-sync. Remove server timestamp gap detection code, the server can sometimes make a huge gap in timestamps (talk spurts,...) see #549774. Detect timetamp weirdness instead by observing the sender/receiver timestamp relation and resync if it changes more than 1 second. Add method to report about the current rtp <-> gst timestamp relation which is needed for lip-sync. * gst/rtpmanager/rtpsession.c: (rtp_session_class_init), (on_sender_timeout), (check_collision), (rtp_session_process_sr), (session_cleanup): * gst/rtpmanager/rtpsession.h: Add sender timeout signal. Remove inaccurate rtp <-> gst timestamp relation code, the jitterbuffer can now do an accurate reporting about this. * gst/rtpmanager/rtpsource.c: (rtp_source_init), (rtp_source_update_caps), (calculate_jitter), (rtp_source_process_rtp): * gst/rtpmanager/rtpsource.h: Remove inaccurate rtp <-> gst timestamp relation code. * gst/rtpmanager/rtpstats.h: Define global max-reorder and max-dropout constants for use in various subsystems.
Diffstat (limited to 'gst/rtpmanager/gstrtpjitterbuffer.c')
-rw-r--r--gst/rtpmanager/gstrtpjitterbuffer.c80
1 files changed, 52 insertions, 28 deletions
diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c
index b9b15691..d48bc40f 100644
--- a/gst/rtpmanager/gstrtpjitterbuffer.c
+++ b/gst/rtpmanager/gstrtpjitterbuffer.c
@@ -65,6 +65,7 @@
#include "gstrtpjitterbuffer.h"
#include "rtpjitterbuffer.h"
+#include "rtpstats.h"
GST_DEBUG_CATEGORY (rtpjitterbuffer_debug);
#define GST_CAT_DEFAULT (rtpjitterbuffer_debug)
@@ -108,7 +109,7 @@ enum
#define JBUF_LOCK_CHECK(priv,label) G_STMT_START { \
JBUF_LOCK (priv); \
- if (priv->srcresult != GST_FLOW_OK) \
+ if (G_UNLIKELY (priv->srcresult != GST_FLOW_OK)) \
goto label; \
} G_STMT_END
@@ -117,7 +118,7 @@ enum
#define JBUF_WAIT_CHECK(priv,label) G_STMT_START { \
JBUF_WAIT(priv); \
- if (priv->srcresult != GST_FLOW_OK) \
+ if (G_UNLIKELY (priv->srcresult != GST_FLOW_OK)) \
goto label; \
} G_STMT_END
@@ -830,12 +831,12 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstBuffer * buffer)
jitterbuffer = GST_RTP_JITTER_BUFFER (gst_pad_get_parent (pad));
- if (!gst_rtp_buffer_validate (buffer))
+ if (G_UNLIKELY (!gst_rtp_buffer_validate (buffer)))
goto invalid_buffer;
priv = jitterbuffer->priv;
- if (priv->last_pt != gst_rtp_buffer_get_payload_type (buffer)) {
+ if (G_UNLIKELY (priv->last_pt != gst_rtp_buffer_get_payload_type (buffer))) {
GstCaps *caps;
priv->last_pt = gst_rtp_buffer_get_payload_type (buffer);
@@ -848,14 +849,14 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstBuffer * buffer)
}
}
- if (priv->clock_rate == -1) {
+ if (G_UNLIKELY (priv->clock_rate == -1)) {
guint8 pt;
/* no clock rate given on the caps, try to get one with the signal */
pt = gst_rtp_buffer_get_payload_type (buffer);
gst_rtp_jitter_buffer_get_clock_rate (jitterbuffer, pt);
- if (priv->clock_rate == -1)
+ if (G_UNLIKELY (priv->clock_rate == -1))
goto not_negotiated;
}
@@ -875,35 +876,42 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstBuffer * buffer)
JBUF_LOCK_CHECK (priv, out_flushing);
/* don't accept more data on EOS */
- if (priv->eos)
+ if (G_UNLIKELY (priv->eos))
goto have_eos;
/* let's check if this buffer is too late, we can only accept packets with
* bigger seqnum than the one we last pushed. */
- if (priv->last_popped_seqnum != -1) {
+ if (G_LIKELY (priv->last_popped_seqnum != -1)) {
gint gap;
+ gboolean reset = FALSE;
gap = gst_rtp_buffer_compare_seqnum (priv->last_popped_seqnum, seqnum);
- if (gap <= 0) {
+ if (G_UNLIKELY (gap <= 0)) {
/* priv->last_popped_seqnum >= seqnum, this packet is too late or the
* sender might have been restarted with different seqnum. */
- if (gap < -100) {
+ if (gap < -RTP_MAX_MISORDER) {
GST_DEBUG_OBJECT (jitterbuffer, "reset: buffer too old %d", gap);
- priv->last_popped_seqnum = -1;
- priv->next_seqnum = -1;
+ reset = TRUE;
} else {
goto too_late;
}
} else {
/* priv->last_popped_seqnum < seqnum, this is a new packet */
- if (gap > 3000) {
+ if (G_UNLIKELY (gap > RTP_MAX_DROPOUT)) {
GST_DEBUG_OBJECT (jitterbuffer, "reset: too many dropped packets %d",
gap);
- priv->last_popped_seqnum = -1;
- priv->next_seqnum = -1;
+ reset = TRUE;
+ } else {
+ GST_DEBUG_OBJECT (jitterbuffer, "dropped packets %d but <= %d", gap,
+ RTP_MAX_DROPOUT);
}
}
+ if (G_UNLIKELY (reset)) {
+ priv->last_popped_seqnum = -1;
+ priv->next_seqnum = -1;
+ rtp_jitter_buffer_reset_skew (priv->jbuf);
+ }
}
/* let's drop oldest packet if the queue is already full and drop-on-latency
@@ -915,7 +923,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstBuffer * buffer)
latency_ts =
gst_util_uint64_scale_int (priv->latency_ms, priv->clock_rate, 1000);
- if (rtp_jitter_buffer_get_ts_diff (priv->jbuf) >= latency_ts) {
+ if (G_UNLIKELY (rtp_jitter_buffer_get_ts_diff (priv->jbuf) >= latency_ts)) {
GstBuffer *old_buf;
old_buf = rtp_jitter_buffer_pop (priv->jbuf);
@@ -934,8 +942,8 @@ 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, timestamp,
- priv->clock_rate, &tail))
+ if (G_UNLIKELY (!rtp_jitter_buffer_insert (priv->jbuf, buffer, timestamp,
+ priv->clock_rate, &tail)))
goto duplicate;
/* signal addition of new buffer when the _loop is waiting. */
@@ -944,7 +952,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstBuffer * buffer)
/* let's unschedule and unblock any waiting buffers. We only want to do this
* when the tail buffer changed */
- if (priv->clock_id && tail) {
+ if (G_UNLIKELY (priv->clock_id && tail)) {
GST_DEBUG_OBJECT (jitterbuffer,
"Unscheduling waiting buffer, new tail buffer");
gst_clock_id_unschedule (priv->clock_id);
@@ -1051,12 +1059,12 @@ again:
GST_DEBUG_OBJECT (jitterbuffer, "Peeking item");
while (TRUE) {
/* always wait if we are blocked */
- if (!priv->blocked) {
+ if (G_LIKELY (!priv->blocked)) {
/* if we have a packet, we can exit the loop and grab it */
if (rtp_jitter_buffer_num_packets (priv->jbuf) > 0)
break;
/* no packets but we are EOS, do eos logic */
- if (priv->eos)
+ if (G_UNLIKELY (priv->eos))
goto do_eos;
}
/* underrun, wait for packets or flushing now */
@@ -1091,12 +1099,12 @@ again:
/* get the gap between this and the previous packet. If we don't know the
* previous packet seqnum assume no gap. */
- if (next_seqnum != -1) {
+ if (G_LIKELY (next_seqnum != -1)) {
gap = gst_rtp_buffer_compare_seqnum (next_seqnum, seqnum);
/* if we have a packet that we already pushed or considered dropped, pop it
* off and get the next packet */
- if (gap < 0) {
+ if (G_UNLIKELY (gap < 0)) {
GST_DEBUG_OBJECT (jitterbuffer, "Old packet #%d, next #%d dropping",
seqnum, next_seqnum);
outbuf = rtp_jitter_buffer_pop (priv->jbuf);
@@ -1116,7 +1124,7 @@ again:
* determine if we have missing a packet. If we have a missing packet (which
* must be before this packet) we can wait for it until the deadline for this
* packet expires. */
- if (gap != 0 && out_time != -1) {
+ if (G_UNLIKELY (gap != 0 && out_time != -1)) {
GstClockID id;
GstClockTime sync_time;
GstClockReturn ret;
@@ -1188,8 +1196,9 @@ again:
/* at this point, the clock could have been unlocked by a timeout, a new
* tail element was added to the queue or because we are shutting down. Check
* for shutdown first. */
- if (priv->srcresult != GST_FLOW_OK)
- goto flushing;
+ if G_UNLIKELY
+ ((priv->srcresult != GST_FLOW_OK))
+ goto flushing;
/* if we got unscheduled and we are not flushing, it's because a new tail
* element became available in the queue. Grab it and try to push or sync. */
@@ -1239,7 +1248,7 @@ push_buffer:
/* when we get here we are ready to pop and push the buffer */
outbuf = rtp_jitter_buffer_pop (priv->jbuf);
- if (discont || priv->discont) {
+ if (G_UNLIKELY (discont || priv->discont)) {
/* set DISCONT flag when we missed a packet. We pushed the buffer writable
* into the jitterbuffer so we can modify now. */
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
@@ -1261,7 +1270,7 @@ push_buffer:
"Pushing buffer %d, timestamp %" GST_TIME_FORMAT, seqnum,
GST_TIME_ARGS (out_time));
result = gst_pad_push (priv->srcpad, outbuf);
- if (result != GST_FLOW_OK)
+ if (G_UNLIKELY (result != GST_FLOW_OK))
goto pause;
return;
@@ -1451,3 +1460,18 @@ gst_rtp_jitter_buffer_get_property (GObject * object,
break;
}
}
+
+void
+gst_rtp_jitter_buffer_get_sync (GstRtpJitterBuffer * buffer, guint64 * rtptime,
+ guint64 * timestamp)
+{
+ GstRtpJitterBufferPrivate *priv;
+
+ g_return_if_fail (GST_IS_RTP_JITTER_BUFFER (buffer));
+
+ priv = buffer->priv;
+
+ JBUF_LOCK (priv);
+ rtp_jitter_buffer_get_sync (priv->jbuf, rtptime, timestamp);
+ JBUF_UNLOCK (priv);
+}