mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
rtpjitterbuffer: add "add-reference-timestamp-meta" property
When syncing to an RFC7273 clock this will add the original reconstructed reference clock timestamp to buffers in form of a GstReferenceTimestampMeta. This is useful when we want to process or analyse data based on the original timestamps untainted by any local adjustments, for example reconstruct AES67 audio streams with sample accuracy. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1964>
This commit is contained in:
parent
3e3ba1772c
commit
c88bfc0b3e
4 changed files with 73 additions and 4 deletions
|
@ -17523,6 +17523,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"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": {
|
"do-lost": {
|
||||||
"blurb": "Send an event downstream when a packet is lost",
|
"blurb": "Send an event downstream when a packet is lost",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
|
|
@ -153,6 +153,7 @@ enum
|
||||||
#define DEFAULT_MAX_DROPOUT_TIME 60000
|
#define DEFAULT_MAX_DROPOUT_TIME 60000
|
||||||
#define DEFAULT_MAX_MISORDER_TIME 2000
|
#define DEFAULT_MAX_MISORDER_TIME 2000
|
||||||
#define DEFAULT_RFC7273_SYNC FALSE
|
#define DEFAULT_RFC7273_SYNC FALSE
|
||||||
|
#define DEFAULT_ADD_REFERENCE_TIMESTAMP_META FALSE
|
||||||
#define DEFAULT_FASTSTART_MIN_PACKETS 0
|
#define DEFAULT_FASTSTART_MIN_PACKETS 0
|
||||||
|
|
||||||
#define DEFAULT_AUTO_RTX_DELAY (20 * GST_MSECOND)
|
#define DEFAULT_AUTO_RTX_DELAY (20 * GST_MSECOND)
|
||||||
|
@ -186,6 +187,7 @@ enum
|
||||||
PROP_MAX_DROPOUT_TIME,
|
PROP_MAX_DROPOUT_TIME,
|
||||||
PROP_MAX_MISORDER_TIME,
|
PROP_MAX_MISORDER_TIME,
|
||||||
PROP_RFC7273_SYNC,
|
PROP_RFC7273_SYNC,
|
||||||
|
PROP_ADD_REFERENCE_TIMESTAMP_META,
|
||||||
PROP_FASTSTART_MIN_PACKETS
|
PROP_FASTSTART_MIN_PACKETS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -334,6 +336,10 @@ struct _GstRtpJitterBufferPrivate
|
||||||
guint32 max_dropout_time;
|
guint32 max_dropout_time;
|
||||||
guint32 max_misorder_time;
|
guint32 max_misorder_time;
|
||||||
guint faststart_min_packets;
|
guint faststart_min_packets;
|
||||||
|
gboolean add_reference_timestamp_meta;
|
||||||
|
|
||||||
|
/* Reference for GstReferenceTimestampMeta */
|
||||||
|
GstCaps *rfc7273_ref;
|
||||||
|
|
||||||
/* the last seqnum we pushed out */
|
/* the last seqnum we pushed out */
|
||||||
guint32 last_popped_seqnum;
|
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,
|
"(requires clock and offset to be provided)", DEFAULT_RFC7273_SYNC,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
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
|
* GstRtpJitterBuffer:faststart-min-packets
|
||||||
*
|
*
|
||||||
|
@ -1388,6 +1411,7 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer,
|
||||||
gint payload = -1;
|
gint payload = -1;
|
||||||
GstClockTime tval;
|
GstClockTime tval;
|
||||||
const gchar *ts_refclk, *mediaclk;
|
const gchar *ts_refclk, *mediaclk;
|
||||||
|
GstCaps *ts_meta_ref = NULL;
|
||||||
|
|
||||||
priv = jitterbuffer->priv;
|
priv = jitterbuffer->priv;
|
||||||
|
|
||||||
|
@ -1503,6 +1527,10 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer,
|
||||||
hostname = g_strdup (host);
|
hostname = g_strdup (host);
|
||||||
|
|
||||||
clock = gst_ntp_clock_new (NULL, hostname, port, 0);
|
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);
|
g_free (hostname);
|
||||||
}
|
}
|
||||||
} else if (g_str_has_prefix (ts_refclk, "ptp=IEEE1588-2008:")) {
|
} 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;
|
domain = 0;
|
||||||
|
|
||||||
clock = gst_ptp_clock_new (NULL, domain);
|
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 {
|
} else {
|
||||||
GST_FIXME_OBJECT (jitterbuffer, "Unsupported timestamp reference clock");
|
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);
|
rtp_jitter_buffer_set_media_clock (priv->jbuf, NULL, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_caps_take (&priv->rfc7273_ref, ts_meta_ref);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
@ -1721,6 +1754,7 @@ gst_rtp_jitter_buffer_change_state (GstElement * element,
|
||||||
JBUF_UNLOCK (priv);
|
JBUF_UNLOCK (priv);
|
||||||
g_thread_join (priv->timer_thread);
|
g_thread_join (priv->timer_thread);
|
||||||
priv->timer_thread = NULL;
|
priv->timer_thread = NULL;
|
||||||
|
gst_clear_caps (&priv->rfc7273_ref);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
break;
|
break;
|
||||||
|
@ -2914,6 +2948,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent,
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstClockTime now;
|
GstClockTime now;
|
||||||
GstClockTime dts, pts;
|
GstClockTime dts, pts;
|
||||||
|
GstClockTime ntp_time;
|
||||||
guint64 latency_ts;
|
guint64 latency_ts;
|
||||||
gboolean head;
|
gboolean head;
|
||||||
gboolean duplicate;
|
gboolean duplicate;
|
||||||
|
@ -3073,7 +3108,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent,
|
||||||
pts =
|
pts =
|
||||||
rtp_jitter_buffer_calculate_pts (priv->jbuf, dts, estimated_dts,
|
rtp_jitter_buffer_calculate_pts (priv->jbuf, dts, estimated_dts,
|
||||||
rtptime, gst_element_get_base_time (GST_ELEMENT_CAST (jitterbuffer)),
|
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))) {
|
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts))) {
|
||||||
/* A valid timestamp cannot be calculated, discard packet */
|
/* A valid timestamp cannot be calculated, discard packet */
|
||||||
|
@ -3136,7 +3171,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent,
|
||||||
pts =
|
pts =
|
||||||
rtp_jitter_buffer_calculate_pts (priv->jbuf, dts, estimated_dts,
|
rtp_jitter_buffer_calculate_pts (priv->jbuf, dts, estimated_dts,
|
||||||
rtptime, gst_element_get_base_time (GST_ELEMENT_CAST (jitterbuffer)),
|
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))) {
|
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts))) {
|
||||||
/* A valid timestamp cannot be calculated, discard packet */
|
/* 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);
|
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
|
/* 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
|
* 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);
|
priv->faststart_min_packets = g_value_get_uint (value);
|
||||||
JBUF_UNLOCK (priv);
|
JBUF_UNLOCK (priv);
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -4897,6 +4945,11 @@ gst_rtp_jitter_buffer_get_property (GObject * object,
|
||||||
g_value_set_uint (value, priv->faststart_min_packets);
|
g_value_set_uint (value, priv->faststart_min_packets);
|
||||||
JBUF_UNLOCK (priv);
|
JBUF_UNLOCK (priv);
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -703,7 +703,7 @@ queue_do_insert (RTPJitterBuffer * jbuf, GList * list, GList * item)
|
||||||
GstClockTime
|
GstClockTime
|
||||||
rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts,
|
rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts,
|
||||||
gboolean estimated_dts, guint32 rtptime, GstClockTime base_time,
|
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;
|
guint64 ext_rtptime;
|
||||||
GstClockTime gstrtptime, pts;
|
GstClockTime gstrtptime, pts;
|
||||||
|
@ -711,6 +711,8 @@ rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts,
|
||||||
guint64 media_clock_offset;
|
guint64 media_clock_offset;
|
||||||
gboolean rfc7273_mode;
|
gboolean rfc7273_mode;
|
||||||
|
|
||||||
|
*p_ntp_time = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
/* rtp time jumps are checked for during skew calculation, but bypassed
|
/* rtp time jumps are checked for during skew calculation, but bypassed
|
||||||
* in other mode, so mind those here and reset jb if needed.
|
* in other mode, so mind those here and reset jb if needed.
|
||||||
* Only reset if valid input time, which is likely for UDP input
|
* 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: %"
|
GST_DEBUG ("RFC7273 packet NTP time %" GST_TIME_FORMAT " (RTP: %"
|
||||||
G_GUINT64_FORMAT ")", GST_TIME_ARGS (ntptime), ntprtptime);
|
G_GUINT64_FORMAT ")", GST_TIME_ARGS (ntptime), ntprtptime);
|
||||||
|
|
||||||
|
*p_ntp_time = ntptime;
|
||||||
|
|
||||||
/* Packet timestamp converted to the pipeline clock.
|
/* Packet timestamp converted to the pipeline clock.
|
||||||
* Note that this includes again inaccuracy caused by the estimation of
|
* Note that this includes again inaccuracy caused by the estimation of
|
||||||
* the NTP vs. pipeline clock. */
|
* the NTP vs. pipeline clock. */
|
||||||
|
|
|
@ -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,
|
GstClockTime rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts, gboolean estimated_dts,
|
||||||
guint32 rtptime, GstClockTime base_time, gint gap,
|
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);
|
gboolean rtp_jitter_buffer_can_fast_start (RTPJitterBuffer * jbuf, gint num_packet);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue