rtp: include downstream latency in SR calculations
authorWim Taymans <wim.taymans@collabora.co.uk>
Mon, 7 Jan 2013 14:45:10 +0000 (15:45 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Mon, 7 Jan 2013 14:45:10 +0000 (15:45 +0100)
When we make a mapping between an RTP timestamp and an NTP timestamp, include
the downstream latency applied to the sinks. This makes it possible to have
both sinks run with different latencies and still have correct sync on the
client. It also is more correct because the RTP timestamp in the SR report will
actually correspond more closely to the NTP time it was sent on the server.
For pipelines with high latency on the sender side, this actually allows a
GStreamer receiver to perform synchronisation instead of dropping the RTCP
packets.

gst/rtpmanager/gstrtpsession.c

index acd2fdd..1e0e0ee 100644 (file)
@@ -242,6 +242,8 @@ struct _GstRtpSessionPrivate
   /* caps mapping */
   GHashTable *ptmap;
 
+  GstClockTime send_latency;
+
   gboolean use_pipeline_clock;
 };
 
@@ -1712,6 +1714,33 @@ gst_rtp_session_event_send_rtp_sink (GstPad * pad, GstObject * parent,
   return ret;
 }
 
+static gboolean
+gst_rtp_session_event_send_rtp_src (GstPad * pad, GstObject * parent,
+    GstEvent * event)
+{
+  GstRtpSession *rtpsession;
+  gboolean ret = FALSE;
+
+  rtpsession = GST_RTP_SESSION (parent);
+
+  GST_DEBUG_OBJECT (rtpsession, "received EVENT %s",
+      GST_EVENT_TYPE_NAME (event));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_LATENCY:
+      /* save the latency, we need this to know when an RTP packet will be
+       * rendered by the sink */
+      gst_event_parse_latency (event, &rtpsession->priv->send_latency);
+
+      ret = gst_pad_event_default (pad, parent, event);
+      break;
+    default:
+      ret = gst_pad_event_default (pad, parent, event);
+      break;
+  }
+  return ret;
+}
+
 static GstCaps *
 gst_rtp_session_getcaps_send_rtp (GstPad * pad, GstRtpSession * rtpsession,
     GstCaps * filter)
@@ -1829,6 +1858,7 @@ gst_rtp_session_chain_send_rtp_common (GstRtpSession * rtpsession,
     running_time =
         gst_segment_to_running_time (&rtpsession->send_rtp_seg, GST_FORMAT_TIME,
         timestamp);
+    running_time += priv->send_latency;
   } else {
     /* no timestamp. */
     running_time = -1;
@@ -2011,6 +2041,8 @@ create_send_rtp_sink (GstRtpSession * rtpsession)
       "send_rtp_src");
   gst_pad_set_iterate_internal_links_function (rtpsession->send_rtp_src,
       gst_rtp_session_iterate_internal_links);
+  gst_pad_set_event_function (rtpsession->send_rtp_src,
+      gst_rtp_session_event_send_rtp_src);
   gst_pad_set_active (rtpsession->send_rtp_src, TRUE);
   gst_element_add_pad (GST_ELEMENT_CAST (rtpsession), rtpsession->send_rtp_src);