mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-21 05:26:23 +00:00
rtpbin: Pass NPT start from rtpjitterbuffer to rtpbin
And use it to detect synchronization changes (e.g. seeks) more reliably when doing RTP-Info based synchronization. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6543>
This commit is contained in:
parent
3eb22af88b
commit
b30671a8ee
2 changed files with 64 additions and 22 deletions
|
@ -493,8 +493,9 @@ struct _GstRtpBinStream
|
|||
gint64 base_rtptime;
|
||||
guint64 base_time;
|
||||
|
||||
/* clock-base for RTP-Info */
|
||||
/* clock-base and npt-start for RTP-Info */
|
||||
guint64 clock_base;
|
||||
guint64 npt_start;
|
||||
|
||||
/* Smoothing of ts-offset adjustments */
|
||||
gint64 avg_ts_offset;
|
||||
|
@ -1069,6 +1070,7 @@ gst_rtp_bin_reset_sync (GstRtpBin * rtpbin)
|
|||
stream->base_rtptime = -1;
|
||||
stream->base_time = GST_CLOCK_TIME_NONE;
|
||||
stream->clock_base = -1;
|
||||
stream->npt_start = GST_CLOCK_TIME_NONE;
|
||||
|
||||
stream->avg_ts_offset = 0;
|
||||
stream->is_initialized = FALSE;
|
||||
|
@ -1275,12 +1277,28 @@ get_client (GstRtpBin * bin, guint8 len, const guint8 * data)
|
|||
for (walk = bin->clients; walk; walk = g_slist_next (walk)) {
|
||||
GstRtpBinClient *client = (GstRtpBinClient *) walk->data;
|
||||
|
||||
/* In case of RTSP this can be called without a CNAME first, in which case
|
||||
* we assume that all streams belong to the same client.
|
||||
*
|
||||
* If RTCP is happening later we will get CNAMEs. Remove the client in
|
||||
* that case and create new ones with the actual CNAME once we have one.
|
||||
*
|
||||
* All streams are directly moved over to the new client.
|
||||
*/
|
||||
if (client->cname_len == 0 && len != 0) {
|
||||
result = client;
|
||||
g_free (result->cname);
|
||||
result->cname = g_strndup ((gchar *) data, len);
|
||||
result->cname_len = len;
|
||||
break;
|
||||
}
|
||||
|
||||
if (len != client->cname_len)
|
||||
continue;
|
||||
|
||||
if (!strncmp ((gchar *) data, client->cname, client->cname_len)) {
|
||||
if (len == 0 || !strncmp ((gchar *) data, client->cname, client->cname_len)) {
|
||||
GST_DEBUG_OBJECT (bin, "found existing client %p with CNAME %s", client,
|
||||
client->cname);
|
||||
GST_STR_NULL (client->cname));
|
||||
result = client;
|
||||
break;
|
||||
}
|
||||
|
@ -1293,7 +1311,7 @@ get_client (GstRtpBin * bin, guint8 len, const guint8 * data)
|
|||
result->cname_len = len;
|
||||
bin->clients = g_slist_prepend (bin->clients, result);
|
||||
GST_DEBUG_OBJECT (bin, "created new client %p with CNAME %s", result,
|
||||
result->cname);
|
||||
GST_STR_NULL (result->cname));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1472,9 +1490,17 @@ gst_rtp_bin_send_sync_event (GstRtpBinStream * stream)
|
|||
}
|
||||
}
|
||||
|
||||
/* associate a stream to the given CNAME. This will make sure all streams for
|
||||
/* Associate a stream to the given CNAME. This will make sure all streams for
|
||||
* that CNAME are synchronized together.
|
||||
*
|
||||
* For RTSP streams (or similar) this can also be called with a NULL CNAME and
|
||||
* no ntpnstime / last_extrtptime for doing synchronization based on the
|
||||
* RTP-Info (rtptime maps to rtp_clock_base, and npt_start is provided).
|
||||
*
|
||||
* Synchronization based on RTCP / NTP header extension is generally preferred
|
||||
* over RTP-Info if possible, and this can be configured via the rtcp-sync
|
||||
* property.
|
||||
*
|
||||
* @len: length of CNAME in @data
|
||||
* @data: CNAME
|
||||
* @ntpnstime: NTP time in nanoseconds that corresponds to RTP time @extrtptime.
|
||||
|
@ -1491,7 +1517,7 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream,
|
|||
const guint8 len, const guint8 * data, const guint64 ntpnstime,
|
||||
const guint64 extrtptime, const guint64 base_rtptime,
|
||||
const guint64 base_time, const guint clock_rate,
|
||||
const guint64 rtp_clock_base)
|
||||
const guint64 rtp_clock_base, const guint64 npt_start)
|
||||
{
|
||||
/* Don't do any stream offsetting in RFC7273 sync mode. Everything is
|
||||
* handled inside rtpjitterbuffer for this case. */
|
||||
|
@ -1598,13 +1624,13 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream,
|
|||
if (walk == NULL) {
|
||||
GST_DEBUG_OBJECT (bin,
|
||||
"new association of SSRC %08x with client %p with CNAME %s",
|
||||
stream->ssrc, client, client->cname);
|
||||
stream->ssrc, client, GST_STR_NULL (client->cname));
|
||||
client->streams = g_slist_prepend (client->streams, stream);
|
||||
client->nstreams++;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (bin,
|
||||
"found association of SSRC %08x with client %p with CNAME %s",
|
||||
stream->ssrc, client, client->cname);
|
||||
stream->ssrc, client, GST_STR_NULL (client->cname));
|
||||
}
|
||||
|
||||
/* First decide whether to do RTP-Info or RTCP / NTP header extension sync */
|
||||
|
@ -1625,6 +1651,11 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream,
|
|||
break;
|
||||
}
|
||||
case GST_RTP_BIN_RTCP_SYNC_RTP_INFO:{
|
||||
if (!GST_CLOCK_TIME_IS_VALID (npt_start)) {
|
||||
GST_DEBUG_OBJECT (bin, "invalidated sync data, bailing out");
|
||||
return;
|
||||
}
|
||||
|
||||
rtp_info_sync = TRUE;
|
||||
GST_DEBUG_OBJECT (bin, "Doing RTP-Info sync");
|
||||
|
||||
|
@ -1643,7 +1674,8 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream,
|
|||
|
||||
GST_DEBUG_OBJECT (bin,
|
||||
"base RTP time %" G_GUINT64_FORMAT ", clock-rate %d, " "clock-base %"
|
||||
G_GUINT64_FORMAT, base_rtptime, clock_rate, rtp_clock_base);
|
||||
G_GUINT64_FORMAT ", NPT start %" GST_TIME_FORMAT, base_rtptime,
|
||||
clock_rate, rtp_clock_base, GST_TIME_ARGS (npt_start));
|
||||
|
||||
/* convert to extended RTP time */
|
||||
rtp_clock_base_ext =
|
||||
|
@ -1662,8 +1694,8 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream,
|
|||
GST_DEBUG_OBJECT (bin, "RTP time difference %" GST_STIME_FORMAT,
|
||||
GST_STIME_ARGS (diff_rtp));
|
||||
|
||||
/* Calculate the difference between NPT start (0) and the local time */
|
||||
stream->rtp_delta = 0 - (base_time + diff_rtp);
|
||||
/* Calculate the difference between NPT start and the local time */
|
||||
stream->rtp_delta = npt_start - (base_time + diff_rtp);
|
||||
|
||||
for (walk = client->streams; walk; walk = g_slist_next (walk)) {
|
||||
GstRtpBinStream *ostream = (GstRtpBinStream *) walk->data;
|
||||
|
@ -1676,10 +1708,12 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream,
|
|||
|
||||
/* change in current stream's base from previously init'ed value leads
|
||||
* to reset of all stream's base, e.g. after a seek */
|
||||
if (stream != ostream && stream->clock_base >= 0 &&
|
||||
(stream->clock_base != rtp_clock_base)) {
|
||||
GST_DEBUG_OBJECT (bin, "reset upon clock base change");
|
||||
if (stream != ostream && stream->clock_base != -1 &&
|
||||
(stream->clock_base != rtp_clock_base
|
||||
|| stream->npt_start != npt_start)) {
|
||||
GST_DEBUG_OBJECT (bin, "reset upon clock base or NPT start change");
|
||||
ostream->clock_base = -1;
|
||||
ostream->npt_start = GST_CLOCK_TIME_NONE;
|
||||
ostream->rtp_delta = G_MININT64;
|
||||
if (ostream->have_sync == GST_RTP_BIN_STREAM_SYNCED_RTP_INFO)
|
||||
ostream->have_sync = GST_RTP_BIN_STREAM_SYNCED_NONE;
|
||||
|
@ -1760,11 +1794,13 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream,
|
|||
/* arrange to re-sync for each stream upon significant change, e.g. post-seek
|
||||
* or when the RTP base time changes because of a jitterbuffer reset */
|
||||
all_sync = all_sync && stream->base_rtptime == base_rtptime &&
|
||||
((rtp_info_sync && stream->clock_base == rtp_clock_base)
|
||||
((rtp_info_sync && stream->clock_base == rtp_clock_base
|
||||
&& stream->npt_start == npt_start)
|
||||
|| (!rtp_info_sync && stream->base_time == base_time));
|
||||
stream->base_rtptime = base_rtptime;
|
||||
if (rtp_info_sync) {
|
||||
stream->clock_base = rtp_clock_base;
|
||||
stream->npt_start = npt_start;
|
||||
} else {
|
||||
stream->base_time = base_time;
|
||||
}
|
||||
|
@ -1854,6 +1890,7 @@ gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
|
|||
GstRTCPPacket packet;
|
||||
guint32 ssrc;
|
||||
guint64 ntpnstime, inband_ntpnstime;
|
||||
guint64 npt_start = GST_CLOCK_TIME_NONE;
|
||||
gboolean have_sr;
|
||||
gboolean more;
|
||||
guint64 base_rtptime;
|
||||
|
@ -1867,7 +1904,7 @@ gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
|
|||
|
||||
bin = stream->bin;
|
||||
|
||||
GST_DEBUG_OBJECT (bin, "sync handler called");
|
||||
GST_DEBUG_OBJECT (bin, "sync handler called %" GST_PTR_FORMAT, s);
|
||||
|
||||
/* get the last relation between the rtp timestamps and the gstreamer
|
||||
* timestamps. We get this info directly from the jitterbuffer which
|
||||
|
@ -1882,13 +1919,13 @@ gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
|
|||
}
|
||||
|
||||
cname = gst_structure_get_string (s, "cname");
|
||||
gst_structure_get_uint64 (s, "npt-start", &npt_start);
|
||||
|
||||
/* if the jitterbuffer directly got the NTP timestamp then don't work
|
||||
* through the RTCP SR, otherwise extract it from there */
|
||||
if (gst_structure_get_uint64 (s, "inband-ntpnstime", &inband_ntpnstime)
|
||||
&& gst_structure_get_uint64 (s, "inband-ext-rtptime", &inband_ext_rtptime)
|
||||
&& (cname = gst_structure_get_string (s, "cname"))
|
||||
&& gst_structure_get_uint (s, "ssrc", &ssrc)) {
|
||||
&& cname && gst_structure_get_uint (s, "ssrc", &ssrc)) {
|
||||
GST_DEBUG_OBJECT (bin,
|
||||
"handle sync from inband NTP-64 information for SSRC %08x", ssrc);
|
||||
|
||||
|
@ -1898,7 +1935,7 @@ gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
|
|||
GST_RTP_BIN_LOCK (bin);
|
||||
gst_rtp_bin_associate (bin, stream, strlen (cname), (const guint8 *) cname,
|
||||
inband_ntpnstime, inband_ext_rtptime, base_rtptime, base_time,
|
||||
clock_rate, clock_base);
|
||||
clock_rate, clock_base, npt_start);
|
||||
GST_RTP_BIN_UNLOCK (bin);
|
||||
return;
|
||||
}
|
||||
|
@ -1917,7 +1954,7 @@ gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
|
|||
/* associate the stream to CNAME */
|
||||
gst_rtp_bin_associate (bin, stream, strlen (cname),
|
||||
(const guint8 *) cname, ntpnstime, extrtptime, base_rtptime,
|
||||
base_time, clock_rate, clock_base);
|
||||
base_time, clock_rate, clock_base, npt_start);
|
||||
GST_RTP_BIN_UNLOCK (bin);
|
||||
return;
|
||||
}
|
||||
|
@ -1961,7 +1998,7 @@ gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
|
|||
/* associate the stream to CNAME */
|
||||
gst_rtp_bin_associate (bin, stream, strlen (cname),
|
||||
(const guint8 *) cname, ntpnstime, extrtptime, base_rtptime,
|
||||
base_time, clock_rate, clock_base);
|
||||
base_time, clock_rate, clock_base, npt_start);
|
||||
GST_RTP_BIN_UNLOCK (bin);
|
||||
|
||||
goto out;
|
||||
|
@ -1997,7 +2034,7 @@ gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
|
|||
/* associate the stream to CNAME */
|
||||
gst_rtp_bin_associate (bin, stream, len, data,
|
||||
ntpnstime, extrtptime, base_rtptime, base_time, clock_rate,
|
||||
clock_base);
|
||||
clock_base, npt_start);
|
||||
GST_RTP_BIN_UNLOCK (bin);
|
||||
|
||||
goto out;
|
||||
|
@ -2056,6 +2093,7 @@ create_stream (GstRtpBinSession * session, guint32 ssrc)
|
|||
stream->base_rtptime = -1;
|
||||
stream->base_time = GST_CLOCK_TIME_NONE;
|
||||
stream->clock_base = -1;
|
||||
stream->npt_start = GST_CLOCK_TIME_NONE;
|
||||
|
||||
stream->avg_ts_offset = 0;
|
||||
stream->is_initialized = FALSE;
|
||||
|
|
|
@ -4688,6 +4688,7 @@ do_handle_sync_inband (GstRtpJitterBuffer * jitterbuffer, guint64 ntpnstime)
|
|||
"base-time", G_TYPE_UINT64, base_time,
|
||||
"clock-rate", G_TYPE_UINT, clock_rate,
|
||||
"clock-base", G_TYPE_UINT64, priv->clock_base & G_MAXUINT32,
|
||||
"npt-start", G_TYPE_UINT64, priv->npt_start,
|
||||
"cname", G_TYPE_STRING, cname,
|
||||
"ssrc", G_TYPE_UINT, priv->last_ssrc,
|
||||
"inband-ext-rtptime", G_TYPE_UINT64, last_rtptime,
|
||||
|
@ -4712,6 +4713,7 @@ do_handle_sync (GstRtpJitterBuffer * jitterbuffer)
|
|||
guint32 clock_rate;
|
||||
guint64 last_rtptime;
|
||||
guint64 clock_base;
|
||||
GstClockTime npt_start;
|
||||
guint64 ext_rtptime, diff;
|
||||
gboolean valid = TRUE, keep = FALSE;
|
||||
|
||||
|
@ -4722,6 +4724,7 @@ do_handle_sync (GstRtpJitterBuffer * jitterbuffer)
|
|||
&clock_rate, &last_rtptime);
|
||||
|
||||
clock_base = priv->clock_base;
|
||||
npt_start = priv->npt_start;
|
||||
ext_rtptime = priv->last_sr_ext_rtptime;
|
||||
|
||||
GST_DEBUG_OBJECT (jitterbuffer,
|
||||
|
@ -4776,6 +4779,7 @@ do_handle_sync (GstRtpJitterBuffer * jitterbuffer)
|
|||
"base-time", G_TYPE_UINT64, base_time,
|
||||
"clock-rate", G_TYPE_UINT, clock_rate,
|
||||
"clock-base", G_TYPE_UINT64, priv->clock_base & G_MAXUINT32,
|
||||
"npt-start", G_TYPE_UINT64, npt_start,
|
||||
"ssrc", G_TYPE_UINT, priv->last_sr_ssrc,
|
||||
"sr-ext-rtptime", G_TYPE_UINT64, ext_rtptime,
|
||||
"sr-ntpnstime", G_TYPE_UINT64, priv->last_sr_ntpnstime,
|
||||
|
|
Loading…
Reference in a new issue