diff --git a/subprojects/gst-plugins-good/docs/gst_plugins_cache.json b/subprojects/gst-plugins-good/docs/gst_plugins_cache.json index 7dd832070a..f17a2575df 100644 --- a/subprojects/gst-plugins-good/docs/gst_plugins_cache.json +++ b/subprojects/gst-plugins-good/docs/gst_plugins_cache.json @@ -17523,6 +17523,18 @@ } }, "properties": { + "add-reference-timestamp-meta": { + "blurb": "Add Reference Timestamp Meta to buffers with the original clock timestamp before any adjustments when syncing to an RFC7273 clock.", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, "do-lost": { "blurb": "Send an event downstream when a packet is lost", "conditionally-available": false, diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c index db43cc8de0..3702a47292 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpjitterbuffer.c @@ -153,6 +153,7 @@ enum #define DEFAULT_MAX_DROPOUT_TIME 60000 #define DEFAULT_MAX_MISORDER_TIME 2000 #define DEFAULT_RFC7273_SYNC FALSE +#define DEFAULT_ADD_REFERENCE_TIMESTAMP_META FALSE #define DEFAULT_FASTSTART_MIN_PACKETS 0 #define DEFAULT_AUTO_RTX_DELAY (20 * GST_MSECOND) @@ -186,6 +187,7 @@ enum PROP_MAX_DROPOUT_TIME, PROP_MAX_MISORDER_TIME, PROP_RFC7273_SYNC, + PROP_ADD_REFERENCE_TIMESTAMP_META, PROP_FASTSTART_MIN_PACKETS }; @@ -334,6 +336,10 @@ struct _GstRtpJitterBufferPrivate guint32 max_dropout_time; guint32 max_misorder_time; guint faststart_min_packets; + gboolean add_reference_timestamp_meta; + + /* Reference for GstReferenceTimestampMeta */ + GstCaps *rfc7273_ref; /* the last seqnum we pushed out */ guint32 last_popped_seqnum; @@ -885,6 +891,23 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass) "(requires clock and offset to be provided)", DEFAULT_RFC7273_SYNC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstRtpJitterBuffer:add-reference-timestamp-meta: + * + * When syncing to a RFC7273 clock, add #GstReferenceTimestampMeta + * to buffers with the original reconstructed reference clock timestamp. + * + * Since: 1.22 + */ + g_object_class_install_property (gobject_class, + PROP_ADD_REFERENCE_TIMESTAMP_META, + g_param_spec_boolean ("add-reference-timestamp-meta", + "Add Reference Timestamp Meta", + "Add Reference Timestamp Meta to buffers with the original clock timestamp " + "before any adjustments when syncing to an RFC7273 clock.", + DEFAULT_ADD_REFERENCE_TIMESTAMP_META, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * GstRtpJitterBuffer:faststart-min-packets * @@ -1388,6 +1411,7 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer, gint payload = -1; GstClockTime tval; const gchar *ts_refclk, *mediaclk; + GstCaps *ts_meta_ref = NULL; priv = jitterbuffer->priv; @@ -1503,6 +1527,10 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer, hostname = g_strdup (host); clock = gst_ntp_clock_new (NULL, hostname, port, 0); + + ts_meta_ref = gst_caps_new_simple ("timestamp/x-ntp", + "host", G_TYPE_STRING, hostname, "port", G_TYPE_INT, port, NULL); + g_free (hostname); } } else if (g_str_has_prefix (ts_refclk, "ptp=IEEE1588-2008:")) { @@ -1514,6 +1542,10 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer, domain = 0; clock = gst_ptp_clock_new (NULL, domain); + + ts_meta_ref = gst_caps_new_simple ("timestamp/x-ptp", + "version", G_TYPE_STRING, "IEEE1588-2008", + "domain", G_TYPE_INT, domain, NULL); } else { GST_FIXME_OBJECT (jitterbuffer, "Unsupported timestamp reference clock"); } @@ -1536,6 +1568,7 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer, rtp_jitter_buffer_set_media_clock (priv->jbuf, NULL, -1); } + gst_caps_take (&priv->rfc7273_ref, ts_meta_ref); return TRUE; /* ERRORS */ @@ -1721,6 +1754,7 @@ gst_rtp_jitter_buffer_change_state (GstElement * element, JBUF_UNLOCK (priv); g_thread_join (priv->timer_thread); priv->timer_thread = NULL; + gst_clear_caps (&priv->rfc7273_ref); break; case GST_STATE_CHANGE_READY_TO_NULL: break; @@ -2914,6 +2948,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent, GstFlowReturn ret = GST_FLOW_OK; GstClockTime now; GstClockTime dts, pts; + GstClockTime ntp_time; guint64 latency_ts; gboolean head; gboolean duplicate; @@ -3073,7 +3108,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent, pts = rtp_jitter_buffer_calculate_pts (priv->jbuf, dts, estimated_dts, rtptime, gst_element_get_base_time (GST_ELEMENT_CAST (jitterbuffer)), - 0, FALSE); + 0, FALSE, &ntp_time); if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts))) { /* A valid timestamp cannot be calculated, discard packet */ @@ -3136,7 +3171,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent, pts = rtp_jitter_buffer_calculate_pts (priv->jbuf, dts, estimated_dts, rtptime, gst_element_get_base_time (GST_ELEMENT_CAST (jitterbuffer)), - gap, is_rtx); + gap, is_rtx, &ntp_time); if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts))) { /* A valid timestamp cannot be calculated, discard packet */ @@ -3248,6 +3283,14 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent, JBUF_SIGNAL_EVENT (priv); } } + // ntp_time will only be set in case of RFC7273 sync + if (priv->add_reference_timestamp_meta && GST_CLOCK_TIME_IS_VALID (ntp_time) + && priv->rfc7273_ref != NULL) { + buffer = gst_buffer_make_writable (buffer); + + gst_buffer_add_reference_timestamp_meta (buffer, + priv->rfc7273_ref, ntp_time, GST_CLOCK_TIME_NONE); + } /* If we estimated the DTS, don't consider it in the clock skew calculations * later. The code above always sets dts to pts or the other way around if @@ -4741,6 +4784,11 @@ gst_rtp_jitter_buffer_set_property (GObject * object, priv->faststart_min_packets = g_value_get_uint (value); JBUF_UNLOCK (priv); break; + case PROP_ADD_REFERENCE_TIMESTAMP_META: + JBUF_LOCK (priv); + priv->add_reference_timestamp_meta = g_value_get_boolean (value); + JBUF_UNLOCK (priv); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -4897,6 +4945,11 @@ gst_rtp_jitter_buffer_get_property (GObject * object, g_value_set_uint (value, priv->faststart_min_packets); JBUF_UNLOCK (priv); break; + case PROP_ADD_REFERENCE_TIMESTAMP_META: + JBUF_LOCK (priv); + g_value_set_boolean (value, priv->add_reference_timestamp_meta); + 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 5893c66673..af8cf637d3 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.c +++ b/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.c @@ -703,7 +703,7 @@ queue_do_insert (RTPJitterBuffer * jbuf, GList * list, GList * item) GstClockTime rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts, gboolean estimated_dts, guint32 rtptime, GstClockTime base_time, - gint gap, gboolean is_rtx) + gint gap, gboolean is_rtx, GstClockTime * p_ntp_time) { guint64 ext_rtptime; GstClockTime gstrtptime, pts; @@ -711,6 +711,8 @@ rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts, guint64 media_clock_offset; gboolean rfc7273_mode; + *p_ntp_time = GST_CLOCK_TIME_NONE; + /* rtp time jumps are checked for during skew calculation, but bypassed * in other mode, so mind those here and reset jb if needed. * Only reset if valid input time, which is likely for UDP input @@ -951,6 +953,8 @@ rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts, GST_DEBUG ("RFC7273 packet NTP time %" GST_TIME_FORMAT " (RTP: %" G_GUINT64_FORMAT ")", GST_TIME_ARGS (ntptime), ntprtptime); + *p_ntp_time = ntptime; + /* Packet timestamp converted to the pipeline clock. * Note that this includes again inaccuracy caused by the estimation of * the NTP vs. pipeline clock. */ diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.h b/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.h index 8accee4b40..d0e60c275d 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.h +++ b/subprojects/gst-plugins-good/gst/rtpmanager/rtpjitterbuffer.h @@ -210,7 +210,7 @@ void rtp_jitter_buffer_get_sync (RTPJitterBuffer *jbuf, GstClockTime rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts, gboolean estimated_dts, guint32 rtptime, GstClockTime base_time, gint gap, - gboolean is_rtx); + gboolean is_rtx, GstClockTime * p_ntp_time); gboolean rtp_jitter_buffer_can_fast_start (RTPJitterBuffer * jbuf, gint num_packet);