From 85b99b9077b0c3f57cd6dac0c00123ac9d487791 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 13 Aug 2008 14:31:02 +0000 Subject: gst/rtpmanager/gstrtpbin.c: Reset rtp timestamp interpollation when we detect a gap when the clock_base changed. Original commit message from CVS: * gst/rtpmanager/gstrtpbin.c: (gst_rtp_bin_associate), (gst_rtp_bin_sync_chain), (new_ssrc_pad_found): Reset rtp timestamp interpollation when we detect a gap when the clock_base changed. Don't try to adjust the ts-offset when it's too big (> 3seconds) * gst/rtpmanager/gstrtpsession.c: (gst_rtp_session_set_ssrc): * gst/rtpmanager/gstrtpsession.h: Add method to set session SSRC. * gst/rtpmanager/rtpsession.c: (check_collision), (rtp_session_set_internal_ssrc), (rtp_session_get_internal_ssrc), (rtp_session_on_timeout): * gst/rtpmanager/rtpsession.h: Added debugging for the collision checks. Add method to change the internal SSRC of the session. * gst/rtpmanager/rtpsource.c: (rtp_source_process_rtp): Reset the clock base when we detect large jumps in the seqnums. --- gst/rtpmanager/gstrtpbin.c | 27 +++++++++++++++++---- gst/rtpmanager/gstrtpsession.c | 7 ++++++ gst/rtpmanager/gstrtpsession.h | 2 ++ gst/rtpmanager/rtpsession.c | 54 ++++++++++++++++++++++++++++++++++++++---- gst/rtpmanager/rtpsession.h | 4 ++++ gst/rtpmanager/rtpsource.c | 2 ++ 6 files changed, 88 insertions(+), 8 deletions(-) (limited to 'gst') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index de1f549d..46ef4bb9 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -119,6 +119,7 @@ #include "gstrtpbin-marshal.h" #include "gstrtpbin.h" +#include "gstrtpsession.h" GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug); #define GST_CAT_DEFAULT gst_rtp_bin_debug @@ -317,6 +318,7 @@ struct _GstRtpBinStream gint64 unix_delta; /* for lip-sync */ + guint64 last_clock_base; guint64 clock_base; guint64 clock_base_time; gint clock_rate; @@ -876,13 +878,18 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream, guint8 len, else diff = ostream->ts_offset - ostream->prev_ts_offset; + GST_DEBUG_OBJECT (bin, + "ts-offset %" G_GUINT64_FORMAT ", prev %" G_GUINT64_FORMAT + ", diff: %" G_GINT64_FORMAT, ostream->ts_offset, + ostream->prev_ts_offset, diff); + /* only change diff when it changed more than 1 millisecond. This * compensates for rounding errors in NTP to RTP timestamp * conversions */ - if (diff > GST_MSECOND) + if (diff > GST_MSECOND && diff < (3 * GST_SECOND)) { g_object_set (ostream->buffer, "ts-offset", ostream->ts_offset, NULL); - - ostream->prev_ts_offset = ostream->ts_offset; + ostream->prev_ts_offset = ostream->ts_offset; + } } GST_DEBUG_OBJECT (bin, "stream SSRC %08x, delta %" G_GINT64_FORMAT, ostream->ssrc, ostream->ts_offset); @@ -929,6 +936,9 @@ gst_rtp_bin_sync_chain (GstPad * pad, GstBuffer * buffer) guint32 rtptime; gboolean have_sr, have_sdes; gboolean more; + guint64 clock_base; + + clock_base = GST_BUFFER_OFFSET (buffer); stream = gst_pad_get_element_private (pad); bin = stream->bin; @@ -938,6 +948,14 @@ gst_rtp_bin_sync_chain (GstPad * pad, GstBuffer * buffer) if (!gst_rtcp_buffer_validate (buffer)) goto invalid_rtcp; + /* clock base changes when there is a huge gap in the timestamps or seqnum. + * When this happens we don't want to calculate the extended timestamp based + * on the previous one but reset the calculation. */ + if (stream->last_clock_base != clock_base) { + stream->last_extrtptime = -1; + stream->last_clock_base = clock_base; + } + have_sr = FALSE; have_sdes = FALSE; GST_RTCP_BUFFER_FOR_PACKETS (more, buffer, &packet) { @@ -989,7 +1007,7 @@ gst_rtp_bin_sync_chain (GstPad * pad, GstBuffer * buffer) gst_rtcp_packet_sdes_get_entry (&packet, &type, &len, &data); if (type == GST_RTCP_SDES_CNAME) { - stream->clock_base = GST_BUFFER_OFFSET (buffer); + stream->clock_base = clock_base; stream->clock_base_time = GST_BUFFER_OFFSET_END (buffer); /* associate the stream to CNAME */ gst_rtp_bin_associate (bin, stream, len, data); @@ -1876,6 +1894,7 @@ new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad, gst_caps_to_string (caps), GST_DEBUG_PAD_NAME (pad)); } + stream->last_clock_base = -1; if (gst_structure_get_uint (s, "clock-base", &val)) stream->clock_base = val; else diff --git a/gst/rtpmanager/gstrtpsession.c b/gst/rtpmanager/gstrtpsession.c index b96a1dfc..75437977 100644 --- a/gst/rtpmanager/gstrtpsession.c +++ b/gst/rtpmanager/gstrtpsession.c @@ -237,6 +237,7 @@ struct _GstRtpSessionPrivate { GMutex *lock; GstClock *sysclock; + RTPSession *session; /* thread for sending out RTCP */ @@ -1846,3 +1847,9 @@ static void gst_rtp_session_release_pad (GstElement * element, GstPad * pad) { } + +void +gst_rtp_session_set_ssrc (GstRtpSession * sess, guint32 ssrc) +{ + rtp_session_set_internal_ssrc (sess->priv->session, ssrc); +} diff --git a/gst/rtpmanager/gstrtpsession.h b/gst/rtpmanager/gstrtpsession.h index 211fffb3..5bbf377a 100644 --- a/gst/rtpmanager/gstrtpsession.h +++ b/gst/rtpmanager/gstrtpsession.h @@ -75,4 +75,6 @@ struct _GstRtpSessionClass { GType gst_rtp_session_get_type (void); +void gst_rtp_session_set_ssrc (GstRtpSession *sess, guint32 ssrc); + #endif /* __GST_RTP_SESSION_H__ */ diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c index 19982478..bac851aa 100644 --- a/gst/rtpmanager/rtpsession.c +++ b/gst/rtpmanager/rtpsession.c @@ -916,7 +916,6 @@ check_collision (RTPSession * sess, RTPSource * source, /* This is not our local source, but lets check if two remote * source collide */ - if (rtp) { if (source->have_rtp_from) { if (gst_netaddress_equal (&source->rtp_from, &arrival->address)) @@ -938,8 +937,9 @@ check_collision (RTPSession * sess, RTPSource * source, return FALSE; } } - - /* In this case, we have third-party collision or loop */ + /* We received RTP or RTCP from this source before but the network address + * changed. In this case, we have third-party collision or loop */ + GST_DEBUG ("we have a third-party collision or loop"); /* FIXME: Log 3rd party collision somehow * Maybe should be done in upper layer, only the SDES can tell us @@ -1026,7 +1026,7 @@ obtain_source (RTPSession * sess, guint32 ssrc, gboolean * created, * rtp_session_get_internal_source: * @sess: a #RTPSession * - * Get the internal #RTPSource of @session. + * Get the internal #RTPSource of @sess. * * Returns: The internal #RTPSource. g_object_unref() after usage. */ @@ -1042,6 +1042,48 @@ rtp_session_get_internal_source (RTPSession * sess) return result; } +/** + * rtp_session_set_internal_ssrc: + * @sess: a #RTPSession + * @ssrc: an SSRC + * + * Set the SSRC of @sess to @ssrc. + */ +void +rtp_session_set_internal_ssrc (RTPSession * sess, guint32 ssrc) +{ + RTP_SESSION_LOCK (sess); + g_hash_table_steal (sess->ssrcs[sess->mask_idx], + GINT_TO_POINTER (sess->source->ssrc)); + + sess->source->ssrc = ssrc; + rtp_source_reset (sess->source); + + g_hash_table_insert (sess->ssrcs[sess->mask_idx], + GINT_TO_POINTER (sess->source->ssrc), sess->source); + RTP_SESSION_UNLOCK (sess); +} + +/** + * rtp_session_get_internal_ssrc: + * @sess: a #RTPSession + * + * Get the internal SSRC of @sess. + * + * Returns: The SSRC of the session. + */ +guint32 +rtp_session_get_internal_ssrc (RTPSession * sess) +{ + guint32 ssrc; + + RTP_SESSION_LOCK (sess); + ssrc = sess->source->ssrc; + RTP_SESSION_UNLOCK (sess); + + return ssrc; +} + /** * rtp_session_add_source: * @sess: a #RTPSession @@ -2285,6 +2327,7 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time, } /* check for outdated collisions */ + GST_DEBUG ("checking collision list"); item = g_list_first (sess->conflicting_addresses); while (item) { RTPConflictingAddress *known_conflict = item->data; @@ -2294,12 +2337,14 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time, RTCP_INTERVAL_COLLISION_TIMEOUT)) { sess->conflicting_addresses = g_list_delete_link (sess->conflicting_addresses, item); + GST_DEBUG ("collision %p timed out", known_conflict); g_free (known_conflict); } item = next_item; } if (sess->change_ssrc) { + GST_DEBUG ("need to change our SSRC (%08x)", sess->source->ssrc); g_hash_table_steal (sess->ssrcs[sess->mask_idx], GINT_TO_POINTER (sess->source->ssrc)); @@ -2313,6 +2358,7 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time, sess->bye_reason = NULL; sess->sent_bye = FALSE; sess->change_ssrc = FALSE; + GST_DEBUG ("changed our SSRC to %08x", sess->source->ssrc); } RTP_SESSION_UNLOCK (sess); diff --git a/gst/rtpmanager/rtpsession.h b/gst/rtpmanager/rtpsession.h index 7c8db6dd..d45a4108 100644 --- a/gst/rtpmanager/rtpsession.h +++ b/gst/rtpmanager/rtpsession.h @@ -264,6 +264,10 @@ gchar* rtp_session_get_sdes_string (RTPSession *sess, GstRTCPSDE /* handling sources */ RTPSource* rtp_session_get_internal_source (RTPSession *sess); + +void rtp_session_set_internal_ssrc (RTPSession *sess, guint32 ssrc); +guint32 rtp_session_get_internal_ssrc (RTPSession *sess); + gboolean rtp_session_add_source (RTPSession *sess, RTPSource *src); guint rtp_session_get_num_sources (RTPSession *sess); guint rtp_session_get_num_active_sources (RTPSession *sess); diff --git a/gst/rtpmanager/rtpsource.c b/gst/rtpmanager/rtpsource.c index 4c01a7ad..ddbf733b 100644 --- a/gst/rtpmanager/rtpsource.c +++ b/gst/rtpmanager/rtpsource.c @@ -923,11 +923,13 @@ rtp_source_process_rtp (RTPSource * src, GstBuffer * buffer, } else { /* unacceptable jump */ stats->bad_seq = (seqnr + 1) & (RTP_SEQ_MOD - 1); + src->clock_base = -1; goto bad_sequence; } } else { /* duplicate or reordered packet, will be filtered by jitterbuffer. */ GST_WARNING ("duplicate or reordered packet"); + src->clock_base = -1; } src->stats.octets_received += arrival->payload_len; -- cgit v1.2.1