gst/realmedia/rdtdepay.*: Check seqnum gaps and drop duplicate packets or mark outgoi...
authorWim Taymans <wim.taymans@gmail.com>
Wed, 27 Aug 2008 11:28:50 +0000 (11:28 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 27 Aug 2008 11:28:50 +0000 (11:28 +0000)
Original commit message from CVS:
* gst/realmedia/rdtdepay.c: (gst_rdt_depay_handle_data),
(gst_rdt_depay_change_state):
* gst/realmedia/rdtdepay.h:
Check seqnum gaps and drop duplicate packets or mark outgoing buffers
with a DISCONT flag when needed.
* gst/realmedia/rdtmanager.c: (gst_rdt_manager_query_src):
Report the configure latency instead of a hardcoded value.

ChangeLog
gst/realmedia/rdtdepay.c
gst/realmedia/rdtdepay.h
gst/realmedia/rdtmanager.c

index bd798bf..1e93d01 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2008-08-27  Wim Taymans  <wim.taymans@collabora.co.uk>
 
+       * gst/realmedia/rdtdepay.c: (gst_rdt_depay_handle_data),
+       (gst_rdt_depay_change_state):
+       * gst/realmedia/rdtdepay.h:
+       Check seqnum gaps and drop duplicate packets or mark outgoing buffers
+       with a DISCONT flag when needed.
+
+       * gst/realmedia/rdtmanager.c: (gst_rdt_manager_query_src):
+       Report the configure latency instead of a hardcoded value.
+
+2008-08-27  Wim Taymans  <wim.taymans@collabora.co.uk>
+
        * gst/realmedia/rdtmanager.c: (create_session), (activate_session),
        (free_session), (gst_rdt_manager_query_src),
        (gst_rdt_manager_src_activate_push),
index 3deacd7..3668da2 100644 (file)
@@ -222,6 +222,9 @@ gst_rdt_depay_handle_data (GstRDTDepay * rdtdepay, GstClockTime outtime,
   guint size;
   guint16 stream_id;
   guint32 timestamp;
+  gint gap;
+  guint16 seqnum;
+  gboolean discont;
 
   /* get pointers to the packet data */
   gst_rdt_packet_data_peek_data (packet, &data, &size);
@@ -236,6 +239,41 @@ gst_rdt_depay_handle_data (GstRDTDepay * rdtdepay, GstClockTime outtime,
   stream_id = gst_rdt_packet_data_get_stream_id (packet);
   timestamp = gst_rdt_packet_data_get_timestamp (packet);
 
+  seqnum = gst_rdt_packet_data_get_seq (packet);
+
+  GST_DEBUG_OBJECT (rdtdepay, "stream_id %u, timestamp %u, seqnum %d",
+      stream_id, timestamp, seqnum);
+
+  if (rdtdepay->next_seqnum != -1) {
+    gap = gst_rdt_buffer_compare_seqnum (seqnum, rdtdepay->next_seqnum);
+
+    /* if we have no gap, all is fine */
+    if (G_UNLIKELY (gap != 0)) {
+      GST_LOG_OBJECT (rdtdepay, "got packet %u, expected %u, gap %d", seqnum,
+          rdtdepay->next_seqnum, gap);
+      if (gap < 0) {
+        /* seqnum > next_seqnum, we are missing some packets, this is always a
+         * DISCONT. */
+        GST_LOG_OBJECT (rdtdepay, "%d missing packets", gap);
+        rdtdepay->discont = TRUE;
+      } else {
+        /* seqnum < next_seqnum, we have seen this packet before or the sender
+         * could be restarted. If the packet is not too old, we throw it away as
+         * a duplicate, otherwise we mark discont and continue. 100 misordered
+         * packets is a good threshold. See also RFC 4737. */
+        if (gap < 100)
+          goto dropping;
+
+        GST_LOG_OBJECT (rdtdepay,
+            "%d > 100, packet too old, sender likely restarted", gap);
+        rdtdepay->discont = TRUE;
+      }
+    }
+  }
+  rdtdepay->next_seqnum = (seqnum + 1);
+  if (rdtdepay->next_seqnum == 0xff00)
+    rdtdepay->next_seqnum = 0;
+
   GST_WRITE_UINT16_BE (outdata + 0, 0); /* version   */
   GST_WRITE_UINT16_BE (outdata + 2, size + 12); /* length    */
   GST_WRITE_UINT16_BE (outdata + 4, stream_id); /* stream    */
@@ -243,13 +281,19 @@ gst_rdt_depay_handle_data (GstRDTDepay * rdtdepay, GstClockTime outtime,
   GST_WRITE_UINT16_BE (outdata + 10, 0);        /* flags     */
   memcpy (outdata + 12, data, size);
 
-  GST_DEBUG_OBJECT (rdtdepay, "Passing on packet "
-      "stream_id=%u timestamp=%u, outtime %" GST_TIME_FORMAT, stream_id,
-      timestamp, GST_TIME_ARGS (outtime));
+  GST_DEBUG_OBJECT (rdtdepay, "Pushing packet, outtime %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (outtime));
 
   ret = gst_rdt_depay_push (rdtdepay, outbuf);
 
   return ret;
+
+  /* ERRORS */
+dropping:
+  {
+    GST_WARNING_OBJECT (rdtdepay, "%d <= 100, dropping old packet", gap);
+    return GST_FLOW_OK;
+  }
 }
 
 static GstFlowReturn
@@ -355,6 +399,7 @@ gst_rdt_depay_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_NULL_TO_READY:
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
+      rdtdepay->next_seqnum = -1;
       break;
     default:
       break;
index 2f6f3e9..9099a41 100644 (file)
@@ -47,6 +47,7 @@ struct _GstRDTDepay
   GstPad *srcpad;
 
   guint clock_rate;
+  guint32 next_seqnum;
 
   gboolean discont;
   GstBuffer *header;
index 144a0f4..1d4540e 100644 (file)
@@ -528,9 +528,15 @@ gst_rdt_manager_query_src (GstPad * pad, GstQuery * query)
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_LATENCY:
     {
+      GstClockTime latency;
+
+      latency = rdtmanager->latency * GST_MSECOND;
+
       /* we pretend to be live with a 3 second latency */
-      gst_query_set_latency (query, TRUE, 5 * GST_SECOND, -1);
-      GST_DEBUG_OBJECT (rdtmanager, "reporting 5 seconds of latency");
+      gst_query_set_latency (query, TRUE, latency, -1);
+
+      GST_DEBUG_OBJECT (rdtmanager, "reporting %" GST_TIME_FORMAT " of latency",
+          GST_TIME_ARGS (latency));
       res = TRUE;
       break;
     }