diff --git a/subprojects/gst-plugins-good/docs/gst_plugins_cache.json b/subprojects/gst-plugins-good/docs/gst_plugins_cache.json index 8001ddd6e7..8fa6e7bc6d 100644 --- a/subprojects/gst-plugins-good/docs/gst_plugins_cache.json +++ b/subprojects/gst-plugins-good/docs/gst_plugins_cache.json @@ -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, diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c index a030e9ae5f..4e86f6a238 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c @@ -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; diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.c b/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.c index 423b0d4d80..53285bda1c 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.c +++ b/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.c @@ -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 */ diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.h b/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.h index 3d052df47d..bf60703884 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.h +++ b/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.h @@ -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);