rtpbin/session: Add new ntp-time-source property and deprecate use-pipeline-clock...
authorSebastian Dröge <sebastian@centricular.com>
Fri, 12 Jun 2015 21:29:19 +0000 (23:29 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Fri, 12 Jun 2015 21:35:42 +0000 (23:35 +0200)
The new property allows to select the time source that should be used for the
NTP time in RTCP packets. By default it will continue to calculate the NTP
timestamp (1900 epoch) based on the realtime clock. Alternatively it can use
the UNIX timestamp (1970 epoch), the pipeline's running time or the pipeline's
clock time. The latter is especially useful for synchronizing multiple
receivers if all of them share the same clock.

If use-pipeline-clock is set to TRUE, it will override the ntp-time-source
setting and continue to use the running time plus 70 years. This is only kept
for backwards compatibility.

gst/rtpmanager/gstrtpbin.c
gst/rtpmanager/gstrtpbin.h
gst/rtpmanager/gstrtpsession.c
gst/rtpmanager/gstrtpsession.h

index cf324e3239ed64b627778935d14a2170cfd6d1ef..6face869543682f987f18fd8c87227895984156a 100644 (file)
@@ -289,6 +289,7 @@ enum
 #define DEFAULT_DO_SYNC_EVENT        FALSE
 #define DEFAULT_DO_RETRANSMISSION    FALSE
 #define DEFAULT_RTP_PROFILE          GST_RTP_PROFILE_AVPF
+#define DEFAULT_NTP_TIME_SOURCE      GST_RTP_NTP_TIME_SOURCE_NTP
 
 enum
 {
@@ -306,7 +307,8 @@ enum
   PROP_USE_PIPELINE_CLOCK,
   PROP_DO_SYNC_EVENT,
   PROP_DO_RETRANSMISSION,
-  PROP_RTP_PROFILE
+  PROP_RTP_PROFILE,
+  PROP_NTP_TIME_SOURCE
 };
 
 #define GST_RTP_BIN_RTCP_SYNC_TYPE (gst_rtp_bin_rtcp_sync_get_type())
@@ -622,8 +624,13 @@ create_session (GstRtpBin * rtpbin, gint id)
 
   /* configure SDES items */
   GST_OBJECT_LOCK (rtpbin);
-  g_object_set (session, "sdes", rtpbin->sdes, "use-pipeline-clock",
-      rtpbin->use_pipeline_clock, "rtp-profile", rtpbin->rtp_profile, NULL);
+  g_object_set (session, "sdes", rtpbin->sdes, "rtp-profile",
+      rtpbin->rtp_profile, NULL);
+  if (rtpbin->use_pipeline_clock)
+    g_object_set (session, "use-pipeline-clock", rtpbin->use_pipeline_clock,
+        NULL);
+  else
+    g_object_set (session, "ntp-time-source", rtpbin->ntp_time_source, NULL);
   GST_OBJECT_UNLOCK (rtpbin);
 
   /* provide clock_rate to the session manager when needed */
@@ -1004,24 +1011,41 @@ get_current_times (GstRtpBin * bin, GstClockTime * running_time,
     gst_object_ref (clock);
     GST_OBJECT_UNLOCK (bin);
 
+    /* get current clock time and convert to running time */
     clock_time = gst_clock_get_time (clock);
+    rt = clock_time - base_time;
 
     if (bin->use_pipeline_clock) {
-      ntpns = clock_time - base_time;
+      ntpns = rt;
+      /* add constant to convert from 1970 based time to 1900 based time */
+      ntpns += (2208988800LL * GST_SECOND);
     } else {
-      GTimeVal current;
-
-      /* get current NTP time */
-      g_get_current_time (&current);
-      ntpns = GST_TIMEVAL_TO_TIME (current);
+      switch (bin->ntp_time_source) {
+        case GST_RTP_NTP_TIME_SOURCE_NTP:
+        case GST_RTP_NTP_TIME_SOURCE_UNIX:{
+          GTimeVal current;
+
+          /* get current NTP time */
+          g_get_current_time (&current);
+          ntpns = GST_TIMEVAL_TO_TIME (current);
+
+          /* add constant to convert from 1970 based time to 1900 based time */
+          if (bin->ntp_time_source == GST_RTP_NTP_TIME_SOURCE_NTP)
+            ntpns += (2208988800LL * GST_SECOND);
+          break;
+        }
+        case GST_RTP_NTP_TIME_SOURCE_RUNNING_TIME:
+          ntpns = rt;
+          break;
+        case GST_RTP_NTP_TIME_SOURCE_CLOCK_TIME:
+          ntpns = clock_time;
+          break;
+        default:
+          g_assert_not_reached ();
+          break;
+      }
     }
 
-    /* add constant to convert from 1970 based time to 1900 based time */
-    ntpns += (2208988800LL * GST_SECOND);
-
-    /* get current clock time and convert to running time */
-    rt = clock_time - base_time;
-
     gst_object_unref (clock);
   } else {
     GST_OBJECT_UNLOCK (bin);
@@ -2061,9 +2085,10 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
 
   g_object_class_install_property (gobject_class, PROP_USE_PIPELINE_CLOCK,
       g_param_spec_boolean ("use-pipeline-clock", "Use pipeline clock",
-          "Use the pipeline running-time to set the NTP time in the RTCP SR messages",
+          "Use the pipeline running-time to set the NTP time in the RTCP SR messages "
+          "(DEPRECATED: Use ntp-source property)",
           DEFAULT_USE_PIPELINE_CLOCK,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
   /**
    * GstRtpBin:buffer-mode:
    *
@@ -2140,6 +2165,12 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
           GST_TYPE_RTP_PROFILE, DEFAULT_RTP_PROFILE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_NTP_TIME_SOURCE,
+      g_param_spec_enum ("ntp-time-source", "NTP Time Source",
+          "NTP time source for RTCP packets",
+          gst_rtp_ntp_time_source_get_type (), DEFAULT_NTP_TIME_SOURCE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state);
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_rtp_bin_request_new_pad);
@@ -2203,6 +2234,7 @@ gst_rtp_bin_init (GstRtpBin * rtpbin)
   rtpbin->send_sync_event = DEFAULT_DO_SYNC_EVENT;
   rtpbin->do_retransmission = DEFAULT_DO_RETRANSMISSION;
   rtpbin->rtp_profile = DEFAULT_RTP_PROFILE;
+  rtpbin->ntp_time_source = DEFAULT_NTP_TIME_SOURCE;
 
   /* some default SDES entries */
   cname = g_strdup_printf ("user%u@host-%x", g_random_int (), g_random_int ());
@@ -2366,6 +2398,20 @@ gst_rtp_bin_set_property (GObject * object, guint prop_id,
     case PROP_RTP_PROFILE:
       rtpbin->rtp_profile = g_value_get_enum (value);
       break;
+    case PROP_NTP_TIME_SOURCE:{
+      GSList *sessions;
+      GST_RTP_BIN_LOCK (rtpbin);
+      rtpbin->ntp_time_source = g_value_get_enum (value);
+      for (sessions = rtpbin->sessions; sessions;
+          sessions = g_slist_next (sessions)) {
+        GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
+
+        g_object_set (G_OBJECT (session->session),
+            "ntp-time-source", rtpbin->ntp_time_source, NULL);
+      }
+      GST_RTP_BIN_UNLOCK (rtpbin);
+      break;
+    }
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2431,6 +2477,9 @@ gst_rtp_bin_get_property (GObject * object, guint prop_id,
     case PROP_RTP_PROFILE:
       g_value_set_enum (value, rtpbin->rtp_profile);
       break;
+    case PROP_NTP_TIME_SOURCE:
+      g_value_set_enum (value, rtpbin->ntp_time_source);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 61cf5dd3f73753f963151f52508fc16810008066..87c1fada4c70932b386fbbc64d8a089e2bcc4973 100644 (file)
@@ -23,6 +23,7 @@
 #include <gst/gst.h>
 
 #include "rtpsession.h"
+#include "gstrtpsession.h"
 #include "rtpjitterbuffer.h"
 
 #define GST_TYPE_RTP_BIN \
@@ -63,6 +64,7 @@ struct _GstRtpBin {
   RTPJitterBufferMode buffer_mode;
   gboolean        buffering;
   gboolean        use_pipeline_clock;
+  GstRtpNtpTimeSource ntp_time_source;
   gboolean        send_sync_event;
   GstClockTime    buffer_start;
   gboolean        do_retransmission;
index 5051d689b63d512c79777e501b97fff8a21752cb..b1ebceafc8dad86fcc16943be11e506e064be218 100644 (file)
 GST_DEBUG_CATEGORY_STATIC (gst_rtp_session_debug);
 #define GST_CAT_DEFAULT gst_rtp_session_debug
 
+GType
+gst_rtp_ntp_time_source_get_type (void)
+{
+  static GType type = 0;
+  static const GEnumValue values[] = {
+    {GST_RTP_NTP_TIME_SOURCE_NTP, "NTP time based on realtime clock", "ntp"},
+    {GST_RTP_NTP_TIME_SOURCE_UNIX, "UNIX time based on realtime clock", "unix"},
+    {GST_RTP_NTP_TIME_SOURCE_RUNNING_TIME,
+          "Running time based on pipeline clock",
+        "running-time"},
+    {GST_RTP_NTP_TIME_SOURCE_CLOCK_TIME, "Pipeline clock time", "clock-time"},
+    {0, NULL, NULL},
+  };
+
+  if (!type) {
+    type = g_enum_register_static ("GstRtpNtpTimeSource", values);
+  }
+  return type;
+}
+
 /* sink pads */
 static GstStaticPadTemplate rtpsession_recv_rtp_sink_template =
 GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink",
@@ -202,6 +222,7 @@ enum
 #define DEFAULT_RTCP_MIN_INTERVAL    (RTP_STATS_MIN_INTERVAL * GST_SECOND)
 #define DEFAULT_PROBATION            RTP_DEFAULT_PROBATION
 #define DEFAULT_RTP_PROFILE          GST_RTP_PROFILE_AVP
+#define DEFAULT_NTP_TIME_SOURCE      GST_RTP_NTP_TIME_SOURCE_NTP
 
 enum
 {
@@ -218,7 +239,8 @@ enum
   PROP_RTCP_MIN_INTERVAL,
   PROP_PROBATION,
   PROP_STATS,
-  PROP_RTP_PROFILE
+  PROP_RTP_PROFILE,
+  PROP_NTP_TIME_SOURCE
 };
 
 #define GST_RTP_SESSION_GET_PRIVATE(obj)  \
@@ -251,6 +273,7 @@ struct _GstRtpSessionPrivate
   GstClockTime send_latency;
 
   gboolean use_pipeline_clock;
+  GstRtpNtpTimeSource ntp_time_source;
 
   guint rtx_count;
 };
@@ -611,9 +634,10 @@ gst_rtp_session_class_init (GstRtpSessionClass * klass)
 
   g_object_class_install_property (gobject_class, PROP_USE_PIPELINE_CLOCK,
       g_param_spec_boolean ("use-pipeline-clock", "Use pipeline clock",
-          "Use the pipeline running-time to set the NTP time in the RTCP SR messages",
+          "Use the pipeline running-time to set the NTP time in the RTCP SR messages "
+          "(DEPRECATED: Use ntp-source property)",
           DEFAULT_USE_PIPELINE_CLOCK,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
 
   g_object_class_install_property (gobject_class, PROP_RTCP_MIN_INTERVAL,
       g_param_spec_uint64 ("rtcp-min-interval", "Minimum RTCP interval",
@@ -652,6 +676,12 @@ gst_rtp_session_class_init (GstRtpSessionClass * klass)
           "RTP profile to use", GST_TYPE_RTP_PROFILE, DEFAULT_RTP_PROFILE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_NTP_TIME_SOURCE,
+      g_param_spec_enum ("ntp-time-source", "NTP Time Source",
+          "NTP time source for RTCP packets",
+          gst_rtp_ntp_time_source_get_type (), DEFAULT_NTP_TIME_SOURCE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_rtp_session_change_state);
   gstelement_class->request_new_pad =
@@ -727,6 +757,8 @@ gst_rtp_session_init (GstRtpSession * rtpsession)
   rtpsession->priv->thread_stopped = TRUE;
 
   rtpsession->priv->rtx_count = 0;
+
+  rtpsession->priv->ntp_time_source = DEFAULT_NTP_TIME_SOURCE;
 }
 
 static void
@@ -786,6 +818,9 @@ gst_rtp_session_set_property (GObject * object, guint prop_id,
     case PROP_RTP_PROFILE:
       g_object_set_property (G_OBJECT (priv->session), "rtp-profile", value);
       break;
+    case PROP_NTP_TIME_SOURCE:
+      priv->ntp_time_source = g_value_get_enum (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -846,6 +881,9 @@ gst_rtp_session_get_property (GObject * object, guint prop_id,
     case PROP_RTP_PROFILE:
       g_object_get_property (G_OBJECT (priv->session), "rtp-profile", value);
       break;
+    case PROP_NTP_TIME_SOURCE:
+      g_value_set_enum (value, priv->ntp_time_source);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -884,17 +922,35 @@ get_current_times (GstRtpSession * rtpsession, GstClockTime * running_time,
 
     if (rtpsession->priv->use_pipeline_clock) {
       ntpns = rt;
+      /* add constant to convert from 1970 based time to 1900 based time */
+      ntpns += (2208988800LL * GST_SECOND);
     } else {
-      GTimeVal current;
-
-      /* get current NTP time */
-      g_get_current_time (&current);
-      ntpns = GST_TIMEVAL_TO_TIME (current);
+      switch (rtpsession->priv->ntp_time_source) {
+        case GST_RTP_NTP_TIME_SOURCE_NTP:
+        case GST_RTP_NTP_TIME_SOURCE_UNIX:{
+          GTimeVal current;
+
+          /* get current NTP time */
+          g_get_current_time (&current);
+          ntpns = GST_TIMEVAL_TO_TIME (current);
+
+          /* add constant to convert from 1970 based time to 1900 based time */
+          if (rtpsession->priv->ntp_time_source == GST_RTP_NTP_TIME_SOURCE_NTP)
+            ntpns += (2208988800LL * GST_SECOND);
+          break;
+        }
+        case GST_RTP_NTP_TIME_SOURCE_RUNNING_TIME:
+          ntpns = rt;
+          break;
+        case GST_RTP_NTP_TIME_SOURCE_CLOCK_TIME:
+          ntpns = clock_time;
+          break;
+        default:
+          g_assert_not_reached ();
+          break;
+      }
     }
 
-    /* add constant to convert from 1970 based time to 1900 based time */
-    ntpns += (2208988800LL * GST_SECOND);
-
     gst_object_unref (clock);
   } else {
     GST_OBJECT_UNLOCK (rtpsession);
index bbaafa6163a94feb05a0dcd08e9319ede2b57fb1..a144c28caa67be3f17a4cd2de370404f9f72fd9c 100644 (file)
@@ -76,4 +76,13 @@ struct _GstRtpSessionClass {
 
 GType gst_rtp_session_get_type (void);
 
+typedef enum {
+  GST_RTP_NTP_TIME_SOURCE_NTP,
+  GST_RTP_NTP_TIME_SOURCE_UNIX,
+  GST_RTP_NTP_TIME_SOURCE_RUNNING_TIME,
+  GST_RTP_NTP_TIME_SOURCE_CLOCK_TIME
+} GstRtpNtpTimeSource;
+
+GType gst_rtp_ntp_time_source_get_type (void);
+
 #endif /* __GST_RTP_SESSION_H__ */