rtpsession: Support disabling late adjustment of ntp-64 header ext
authorMatt Crane <matt@standard.ai>
Tue, 22 Nov 2022 16:32:57 +0000 (11:32 -0500)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 24 Nov 2022 08:23:03 +0000 (08:23 +0000)
Currently in rtp_session_send_rtp(), the existing ntp-64 RTP header
extension timestamp is updated with the actual NTP time before sending
the packet. However, there are some circumstances where we would like
to preserve the original timestamp obtained from reference timestamp
buffer metadata.

This commit provides the ability to configure whether or not to update
the ntp-64 header extension timestamp with the actual NTP time via the
update-ntp64-header-ext boolean property. The property is also exposed
via rtpbin. Default property value of TRUE will preserve existing
behavior (update ntp-64 header ext with actual NTP time).

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1580

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3451>

subprojects/gst-plugins-good/docs/gst_plugins_cache.json
subprojects/gst-plugins-good/gst/rtpmanager/gstrtpbin.c
subprojects/gst-plugins-good/gst/rtpmanager/gstrtpbin.h
subprojects/gst-plugins-good/gst/rtpmanager/gstrtpsession.c
subprojects/gst-plugins-good/gst/rtpmanager/rtpsession.c
subprojects/gst-plugins-good/gst/rtpmanager/rtpsession.h

index 0b03c5b..86e530d 100644 (file)
                         "type": "guint",
                         "writable": true
                     },
+                    "update-ntp64-header-ext": {
+                        "blurb": "Whether RTP NTP header extension should be updated with actual NTP time",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
                     "use-pipeline-clock": {
                         "blurb": "Use the pipeline running-time to set the NTP time in the RTCP SR messages (DEPRECATED: Use ntp-time-source property)",
                         "conditionally-available": false,
                         "type": "GstStructure",
                         "writable": false
                     },
+                    "update-ntp64-header-ext": {
+                        "blurb": "Whether RTP NTP header extension should be updated with actual NTP time",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
                     "use-pipeline-clock": {
                         "blurb": "Use the pipeline running-time to set the NTP time in the RTCP SR messages (DEPRECATED: Use ntp-time-source property)",
                         "conditionally-available": false,
                         "readable": true,
                         "type": "guint64",
                         "writable": true
+                    },
+                    "update-ntp64-header-ext": {
+                        "blurb": "Whether RTP NTP header extension should be updated with actual NTP time",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
                     }
                 },
                 "signals": {
index bee500e..0fbf082 100644 (file)
@@ -357,6 +357,7 @@ enum
 #define DEFAULT_MAX_TS_OFFSET        G_GINT64_CONSTANT(3000000000)
 #define DEFAULT_MIN_TS_OFFSET        MIN_TS_OFFSET_ROUND_OFF_COMP
 #define DEFAULT_TS_OFFSET_SMOOTHING_FACTOR  0
+#define DEFAULT_UPDATE_NTP64_HEADER_EXT TRUE
 
 enum
 {
@@ -389,6 +390,7 @@ enum
   PROP_TS_OFFSET_SMOOTHING_FACTOR,
   PROP_FEC_DECODERS,
   PROP_FEC_ENCODERS,
+  PROP_UPDATE_NTP64_HEADER_EXT,
 };
 
 #define GST_RTP_BIN_RTCP_SYNC_TYPE (gst_rtp_bin_rtcp_sync_get_type())
@@ -777,6 +779,10 @@ create_session (GstRtpBin * rtpbin, gint id)
 
   g_object_set (session, "max-dropout-time", rtpbin->max_dropout_time,
       "max-misorder-time", rtpbin->max_misorder_time, NULL);
+
+  g_object_set (session, "update-ntp64-header-ext",
+      rtpbin->update_ntp64_header_ext, NULL);
+
   GST_OBJECT_UNLOCK (rtpbin);
 
   /* provide clock_rate to the session manager when needed */
@@ -2980,6 +2986,22 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
           "fec-encoders='fec,0=\"rtpst2022-1-fecenc\\ rows\\=5\\ columns\\=5\";'",
           GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstRtpBin:update-ntp64-header-ext:
+   *
+   * Whether RTP NTP header extension should be updated with actual
+   * NTP time. If not, use the NTP time from buffer timestamp metadata
+   *
+   * Since: 1.22
+   */
+  g_object_class_install_property (gobject_class,
+      PROP_UPDATE_NTP64_HEADER_EXT,
+      g_param_spec_boolean ("update-ntp64-header-ext",
+          "Update NTP-64 RTP Header Extension",
+          "Whether RTP NTP header extension should be updated with actual NTP time",
+          DEFAULT_UPDATE_NTP64_HEADER_EXT,
+          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);
@@ -3070,6 +3092,7 @@ gst_rtp_bin_init (GstRtpBin * rtpbin)
   rtpbin->min_ts_offset = DEFAULT_MIN_TS_OFFSET;
   rtpbin->min_ts_offset_is_set = FALSE;
   rtpbin->ts_offset_smoothing_factor = DEFAULT_TS_OFFSET_SMOOTHING_FACTOR;
+  rtpbin->update_ntp64_header_ext = DEFAULT_UPDATE_NTP64_HEADER_EXT;
 
   /* some default SDES entries */
   cname = g_strdup_printf ("user%u@host-%x", g_random_int (), g_random_int ());
@@ -3409,6 +3432,13 @@ gst_rtp_bin_set_property (GObject * object, guint prop_id,
     case PROP_FEC_ENCODERS:
       gst_rtp_bin_set_fec_encoders_struct (rtpbin, g_value_get_boxed (value));
       break;
+    case PROP_UPDATE_NTP64_HEADER_EXT:
+      GST_RTP_BIN_LOCK (rtpbin);
+      rtpbin->update_ntp64_header_ext = g_value_get_boolean (value);
+      GST_RTP_BIN_UNLOCK (rtpbin);
+      gst_rtp_bin_propagate_property_to_session (rtpbin,
+          "update-ntp64-header-ext", value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -3518,6 +3548,9 @@ gst_rtp_bin_get_property (GObject * object, guint prop_id,
     case PROP_FEC_ENCODERS:
       g_value_take_boxed (value, gst_rtp_bin_get_fec_encoders_struct (rtpbin));
       break;
+    case PROP_UPDATE_NTP64_HEADER_EXT:
+      g_value_set_boolean (value, rtpbin->update_ntp64_header_ext);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index afb322a..eb98eb2 100644 (file)
@@ -98,6 +98,8 @@ struct _GstRtpBin {
   /* the default FEC encoder factories for sessions */
   GstStructure   *fec_encoders;
 
+  gboolean       update_ntp64_header_ext;
+
   /*< private >*/
   GstRtpBinPrivate *priv;
 };
index 3d38e14..b131e77 100644 (file)
@@ -223,6 +223,7 @@ enum
 #define DEFAULT_RTP_PROFILE          GST_RTP_PROFILE_AVP
 #define DEFAULT_NTP_TIME_SOURCE      GST_RTP_NTP_TIME_SOURCE_NTP
 #define DEFAULT_RTCP_SYNC_SEND_TIME  TRUE
+#define DEFAULT_UPDATE_NTP64_HEADER_EXT  TRUE
 
 enum
 {
@@ -244,7 +245,8 @@ enum
   PROP_TWCC_STATS,
   PROP_RTP_PROFILE,
   PROP_NTP_TIME_SOURCE,
-  PROP_RTCP_SYNC_SEND_TIME
+  PROP_RTCP_SYNC_SEND_TIME,
+  PROP_UPDATE_NTP64_HEADER_EXT
 };
 
 #define GST_RTP_SESSION_LOCK(sess)   g_mutex_lock (&(sess)->priv->lock)
@@ -810,6 +812,22 @@ gst_rtp_session_class_init (GstRtpSessionClass * klass)
           DEFAULT_RTCP_SYNC_SEND_TIME,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstRtpSession:update-ntp64-header-ext:
+   *
+   * Whether RTP NTP header extension should be updated with actual
+   * NTP time. If not, use the NTP time from buffer timestamp metadata
+   *
+   * Since: 1.22
+   */
+  g_object_class_install_property (gobject_class,
+      PROP_UPDATE_NTP64_HEADER_EXT,
+      g_param_spec_boolean ("update-ntp64-header-ext",
+          "Update NTP-64 RTP Header Extension",
+          "Whether RTP NTP header extension should be updated with actual NTP time",
+          DEFAULT_UPDATE_NTP64_HEADER_EXT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_rtp_session_change_state);
   gstelement_class->request_new_pad =
@@ -982,6 +1000,10 @@ gst_rtp_session_set_property (GObject * object, guint prop_id,
     case PROP_RTCP_SYNC_SEND_TIME:
       priv->rtcp_sync_send_time = g_value_get_boolean (value);
       break;
+    case PROP_UPDATE_NTP64_HEADER_EXT:
+      g_object_set_property (G_OBJECT (priv->session),
+          "update-ntp64-header-ext", value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1061,6 +1083,10 @@ gst_rtp_session_get_property (GObject * object, guint prop_id,
     case PROP_RTCP_SYNC_SEND_TIME:
       g_value_set_boolean (value, priv->rtcp_sync_send_time);
       break;
+    case PROP_UPDATE_NTP64_HEADER_EXT:
+      g_object_get_property (G_OBJECT (priv->session),
+          "update-ntp64-header-ext", value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 838c24c..294bcf0 100644 (file)
@@ -81,6 +81,7 @@ enum
 #define DEFAULT_RTCP_DISABLE_SR_TIMESTAMP FALSE
 #define DEFAULT_FAVOR_NEW            FALSE
 #define DEFAULT_TWCC_FEEDBACK_INTERVAL GST_CLOCK_TIME_NONE
+#define DEFAULT_UPDATE_NTP64_HEADER_EXT TRUE
 
 enum
 {
@@ -108,6 +109,7 @@ enum
   PROP_RTCP_REDUCED_SIZE,
   PROP_RTCP_DISABLE_SR_TIMESTAMP,
   PROP_TWCC_FEEDBACK_INTERVAL,
+  PROP_UPDATE_NTP64_HEADER_EXT,
   PROP_LAST,
 };
 
@@ -643,6 +645,21 @@ rtp_session_class_init (RTPSessionClass * klass)
       0, G_MAXUINT64, DEFAULT_TWCC_FEEDBACK_INTERVAL,
       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
+  /**
+   * RTPSession:update-ntp64-header-ext:
+   *
+   * Whether RTP NTP header extension should be updated with actual
+   * NTP time. If not, use the NTP time from buffer timestamp metadata
+   *
+   * Since: 1.22
+   */
+  properties[PROP_UPDATE_NTP64_HEADER_EXT] =
+      g_param_spec_boolean ("update-ntp64-header-ext",
+      "Update NTP-64 RTP Header Extension",
+      "Whether RTP NTP header extension should be updated with actual NTP time",
+      DEFAULT_UPDATE_NTP64_HEADER_EXT,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
   g_object_class_install_properties (gobject_class, PROP_LAST, properties);
 
   klass->get_source_by_ssrc =
@@ -688,6 +705,8 @@ rtp_session_init (RTPSession * sess)
   sess->header_len = UDP_IP_HEADER_OVERHEAD;
   sess->mtu = DEFAULT_RTCP_MTU;
 
+  sess->update_ntp64_header_ext = DEFAULT_UPDATE_NTP64_HEADER_EXT;
+
   sess->probation = DEFAULT_PROBATION;
   sess->max_dropout_time = DEFAULT_MAX_DROPOUT_TIME;
   sess->max_misorder_time = DEFAULT_MAX_MISORDER_TIME;
@@ -928,6 +947,9 @@ rtp_session_set_property (GObject * object, guint prop_id,
       rtp_twcc_manager_set_feedback_interval (sess->twcc,
           g_value_get_uint64 (value));
       break;
+    case PROP_UPDATE_NTP64_HEADER_EXT:
+      sess->update_ntp64_header_ext = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1014,6 +1036,9 @@ rtp_session_get_property (GObject * object, guint prop_id,
       g_value_set_uint64 (value,
           rtp_twcc_manager_get_feedback_interval (sess->twcc));
       break;
+    case PROP_UPDATE_NTP64_HEADER_EXT:
+      g_value_set_boolean (value, sess->update_ntp64_header_ext);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -3422,7 +3447,9 @@ rtp_session_send_rtp (RTPSession * sess, gpointer data, gboolean is_list,
     goto invalid_packet;
 
   /* Update any 64-bit NTP header extensions with the actual NTP time here */
-  update_ntp64_header_ext (&pinfo);
+  if (sess->update_ntp64_header_ext)
+    update_ntp64_header_ext (&pinfo);
+
   rtp_twcc_manager_send_packet (sess->twcc, &pinfo);
 
   source = obtain_internal_source (sess, pinfo.ssrc, &created, current_time);
index eb512c7..84b2948 100644 (file)
@@ -313,6 +313,8 @@ struct _RTPSession {
   /* RFC6051 64-bit NTP header extension */
   guint8 send_ntp64_ext_id;
 
+  gboolean update_ntp64_header_ext;
+
   /* Transport-wide cc-extension */
   RTPTWCCManager *twcc;
   RTPTWCCStats *twcc_stats;