rtpsession: Support disabling late adjustment of ntp-64 header ext

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>
This commit is contained in:
Matt Crane 2022-11-22 11:32:57 -05:00 committed by GStreamer Marge Bot
parent 18972fc942
commit ca7f66f9b5
6 changed files with 128 additions and 2 deletions

View file

@ -17401,6 +17401,18 @@
"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,
@ -19318,6 +19330,18 @@
"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,
@ -20083,6 +20107,18 @@
"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": {

View 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;

View 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;
};

View 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;

View 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);

View 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;