rtpjitterbuffer: Add new "rfc7273-reference-timestamp-meta-only" property

If this property is enabled then the jitterbuffer will do the normal PTS
calculations according to the configured mode instead of making use of
the RFC7273 media clock.

The timestamp calculated from the RFC7273 media clock will only be
stored in the reference timestamp meta, if addition of that meta is enabled.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5512>
This commit is contained in:
Sebastian Dröge 2023-11-13 15:51:44 +02:00 committed by GStreamer Marge Bot
parent eae3ef7461
commit db77deef00
4 changed files with 90 additions and 22 deletions

View file

@ -18761,6 +18761,18 @@
"type": "gboolean",
"writable": true
},
"rfc7273-reference-timestamp-meta-only": {
"blurb": "When enabled the PTS on the buffers are calculated normally and the RFC7273 clock is only used for the reference timestamp meta",
"conditionally-available": false,
"construct": false,
"construct-only": false,
"controllable": false,
"default": "false",
"mutable": "null",
"readable": true,
"type": "gboolean",
"writable": true
},
"rfc7273-sync": {
"blurb": "Synchronize received streams to the RFC7273 clock (requires clock and offset to be provided)",
"conditionally-available": false,

View file

@ -159,6 +159,7 @@ enum
#define DEFAULT_FASTSTART_MIN_PACKETS 0
#define DEFAULT_SYNC_INTERVAL 0
#define DEFAULT_RFC7273_USE_SYSTEM_CLOCK FALSE
#define DEFAULT_RFC7273_REFERENCE_TIMESTAMP_META_ONLY FALSE
#define DEFAULT_AUTO_RTX_DELAY (20 * GST_MSECOND)
#define DEFAULT_AUTO_RTX_TIMEOUT (40 * GST_MSECOND)
@ -195,6 +196,7 @@ enum
PROP_FASTSTART_MIN_PACKETS,
PROP_SYNC_INTERVAL,
PROP_RFC7273_USE_SYSTEM_CLOCK,
PROP_RFC7273_REFERENCE_TIMESTAMP_META_ONLY,
};
#define JBUF_LOCK(priv) G_STMT_START { \
@ -340,6 +342,7 @@ struct _GstRtpJitterBufferPrivate
gboolean add_reference_timestamp_meta;
guint sync_interval;
gboolean rfc7273_use_system_clock;
gboolean rfc7273_reference_timestamp_meta_only;
/* Reference for GstReferenceTimestampMeta */
GstCaps *reference_timestamp_caps;
@ -1027,6 +1030,32 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass)
"to be synced externally)", DEFAULT_RFC7273_USE_SYSTEM_CLOCK,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstRtpJitterBuffer:rfc7273-reference-timestamp-meta-only:
*
* When enabled, the jitterbuffer calculates the PTS of the outgoing buffers
* according to the configured mode as if not RFC7273 mode is enabled.
*
* The timestamps calculated from the RFC7273 clock are only put into the
* reference timestamp meta, if enabled via the corresponding property.
*
* This is useful in combination with the `rfc7273-use-system-clock`, or
* generally if synchronization should not be affected by the original
* sender timestamps but the original sender timestamps should nonetheless
* be available as metadata.
*
* Since: 1.24
*/
g_object_class_install_property (gobject_class,
PROP_RFC7273_REFERENCE_TIMESTAMP_META_ONLY,
g_param_spec_boolean ("rfc7273-reference-timestamp-meta-only",
"Use RFC7273 clock only for reference timestamp meta",
"When enabled the PTS on the buffers are calculated normally and the "
"RFC7273 clock is only used for the reference timestamp meta",
DEFAULT_RFC7273_REFERENCE_TIMESTAMP_META_ONLY,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstRtpJitterBuffer::request-pt-map:
* @buffer: the object which received the signal
@ -1159,6 +1188,8 @@ gst_rtp_jitter_buffer_init (GstRtpJitterBuffer * jitterbuffer)
priv->add_reference_timestamp_meta = DEFAULT_ADD_REFERENCE_TIMESTAMP_META;
priv->sync_interval = DEFAULT_SYNC_INTERVAL;
priv->rfc7273_use_system_clock = DEFAULT_RFC7273_USE_SYSTEM_CLOCK;
priv->rfc7273_reference_timestamp_meta_only =
DEFAULT_RFC7273_REFERENCE_TIMESTAMP_META_ONLY;
priv->ts_offset_remainder = 0;
priv->last_dts = -1;
@ -1626,6 +1657,7 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer,
if ((ts_refclk = gst_structure_get_string (caps_struct, "a-ts-refclk"))) {
gboolean use_system_clock;
gboolean reference_timestamp_meta_only;
GstClock *clock = NULL;
guint64 clock_offset = -1;
gint64 clock_correction = 0;
@ -1634,6 +1666,7 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer,
ts_refclk);
use_system_clock = priv->rfc7273_use_system_clock;
reference_timestamp_meta_only = priv->rfc7273_reference_timestamp_meta_only;
if (g_str_has_prefix (ts_refclk, "ntp=")) {
if (g_str_has_prefix (ts_refclk, "ntp=/traceable/")) {
@ -1727,9 +1760,9 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer,
}
rtp_jitter_buffer_set_media_clock (priv->jbuf, clock, clock_offset,
clock_correction);
clock_correction, reference_timestamp_meta_only);
} else {
rtp_jitter_buffer_set_media_clock (priv->jbuf, NULL, -1, 0);
rtp_jitter_buffer_set_media_clock (priv->jbuf, NULL, -1, 0, FALSE);
ts_meta_ref = gst_caps_new_empty_simple ("timestamp/x-ntp");
}
@ -5275,6 +5308,11 @@ gst_rtp_jitter_buffer_set_property (GObject * object,
priv->rfc7273_use_system_clock = g_value_get_boolean (value);
JBUF_UNLOCK (priv);
break;
case PROP_RFC7273_REFERENCE_TIMESTAMP_META_ONLY:
JBUF_LOCK (priv);
priv->rfc7273_reference_timestamp_meta_only = g_value_get_boolean (value);
JBUF_UNLOCK (priv);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -5447,6 +5485,11 @@ gst_rtp_jitter_buffer_get_property (GObject * object,
g_value_set_boolean (value, priv->rfc7273_use_system_clock);
JBUF_UNLOCK (priv);
break;
case PROP_RFC7273_REFERENCE_TIMESTAMP_META_ONLY:
JBUF_LOCK (priv);
g_value_set_boolean (value, priv->rfc7273_reference_timestamp_meta_only);
JBUF_UNLOCK (priv);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;

View file

@ -288,7 +288,8 @@ media_clock_synced_cb (GstClock * clock, gboolean synced,
*/
void
rtp_jitter_buffer_set_media_clock (RTPJitterBuffer * jbuf, GstClock * clock,
guint64 clock_offset, gint64 clock_correction)
guint64 clock_offset, gint64 clock_correction,
gboolean reference_timestamp_meta_only)
{
g_mutex_lock (&jbuf->clock_lock);
if (jbuf->media_clock) {
@ -301,6 +302,8 @@ rtp_jitter_buffer_set_media_clock (RTPJitterBuffer * jbuf, GstClock * clock,
jbuf->media_clock = clock;
jbuf->media_clock_offset = clock_offset;
jbuf->media_clock_correction = clock_correction;
jbuf->media_clock_reference_timestamp_meta_only =
reference_timestamp_meta_only;
if (jbuf->pipeline_clock && jbuf->media_clock) {
if (same_clock (jbuf->pipeline_clock, jbuf->media_clock)) {
@ -765,6 +768,7 @@ rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts,
GstClock *media_clock, *pipeline_clock;
guint64 media_clock_offset;
gint64 media_clock_correction;
gboolean media_clock_reference_timestamp_meta_only;
gboolean rfc7273_mode;
*p_ntp_time = GST_CLOCK_TIME_NONE;
@ -812,6 +816,8 @@ rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts,
jbuf->pipeline_clock ? gst_object_ref (jbuf->pipeline_clock) : NULL;
media_clock_offset = jbuf->media_clock_offset;
media_clock_correction = jbuf->media_clock_correction;
media_clock_reference_timestamp_meta_only =
jbuf->media_clock_reference_timestamp_meta_only;
g_mutex_unlock (&jbuf->clock_lock);
gstrtptime =
@ -1042,27 +1048,33 @@ rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts,
*p_ntp_time = ntptime;
if (media_clock_correction < 0 || ntptime >= media_clock_correction)
ntptime -= media_clock_correction;
else
ntptime = 0;
if (media_clock_reference_timestamp_meta_only) {
/* do skew calculation by measuring the difference between rtptime and the
* receive dts, this function will return the skew corrected rtptime. */
pts = calculate_skew (jbuf, ext_rtptime, gstrtptime, dts, gap, is_rtx);
} else {
if (media_clock_correction < 0 || ntptime >= media_clock_correction)
ntptime -= media_clock_correction;
else
ntptime = 0;
/* Packet timestamp converted to the pipeline clock.
* Note that this includes again inaccuracy caused by the estimation of
* the NTP vs. pipeline clock. */
rtpsystime =
gst_clock_adjust_with_calibration (media_clock, ntptime, internal,
external, rate_num, rate_denom);
/* Packet timestamp converted to the pipeline clock.
* Note that this includes again inaccuracy caused by the estimation of
* the NTP vs. pipeline clock. */
rtpsystime =
gst_clock_adjust_with_calibration (media_clock, ntptime, internal,
external, rate_num, rate_denom);
/* All this assumes that the pipeline has enough additional
* latency to cover for the network delay */
if (rtpsystime > base_time)
pts = rtpsystime - base_time;
else
pts = 0;
/* All this assumes that the pipeline has enough additional
* latency to cover for the network delay */
if (rtpsystime > base_time)
pts = rtpsystime - base_time;
else
pts = 0;
GST_DEBUG ("Packet pipeline clock time %" GST_TIME_FORMAT ", PTS %"
GST_TIME_FORMAT, GST_TIME_ARGS (rtpsystime), GST_TIME_ARGS (pts));
GST_DEBUG ("Packet pipeline clock time %" GST_TIME_FORMAT ", PTS %"
GST_TIME_FORMAT, GST_TIME_ARGS (rtpsystime), GST_TIME_ARGS (pts));
}
} else {
/* If we used the RFC7273 clock before and not anymore,
* we need to resync it later again */

View file

@ -109,6 +109,7 @@ struct _RTPJitterBuffer {
gulong media_clock_synced_id;
guint64 media_clock_offset;
gint64 media_clock_correction;
gboolean media_clock_reference_timestamp_meta_only;
gboolean rfc7273_sync;
};
@ -173,7 +174,7 @@ void rtp_jitter_buffer_set_delay (RTPJitterBuffer *jbuf,
void rtp_jitter_buffer_set_clock_rate (RTPJitterBuffer *jbuf, guint32 clock_rate);
guint32 rtp_jitter_buffer_get_clock_rate (RTPJitterBuffer *jbuf);
void rtp_jitter_buffer_set_media_clock (RTPJitterBuffer *jbuf, GstClock * clock, guint64 clock_offset, gint64 clock_correction);
void rtp_jitter_buffer_set_media_clock (RTPJitterBuffer *jbuf, GstClock * clock, guint64 clock_offset, gint64 clock_correction, gboolean reference_timestamp_meta_only);
void rtp_jitter_buffer_set_pipeline_clock (RTPJitterBuffer *jbuf, GstClock * clock);
gboolean rtp_jitter_buffer_get_rfc7273_sync (RTPJitterBuffer *jbuf);