gst/rtpmanager/gstrtpbin.c: Reset rtp timestamp interpollation when we detect a gap...
authorWim Taymans <wim.taymans@gmail.com>
Wed, 13 Aug 2008 14:31:02 +0000 (14:31 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Tue, 11 Aug 2009 01:30:37 +0000 (02:30 +0100)
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
gst/rtpmanager/gstrtpsession.c
gst/rtpmanager/gstrtpsession.h
gst/rtpmanager/rtpsession.c
gst/rtpmanager/rtpsession.h
gst/rtpmanager/rtpsource.c

index de1f549..46ef4bb 100644 (file)
 
 #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
index b96a1df..7543797 100644 (file)
@@ -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);
+}
index 211fffb..5bbf377 100644 (file)
@@ -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__ */
index 1998247..bac851a 100644 (file)
@@ -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.
  */
@@ -1043,6 +1043,48 @@ rtp_session_get_internal_source (RTPSession * sess)
 }
 
 /**
+ * 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
  * @src: #RTPSource to add
@@ -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);
 
index 7c8db6d..d45a410 100644 (file)
@@ -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);
index 4c01a7a..ddbf733 100644 (file)
@@ -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;