mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-29 19:50:40 +00:00
rtpbin: Allow synchronizing against RTP-Info without having received any RTCP
Previously the information was provided from rtpjitterbuffer to rtpbin only once the first RTCP SR was received, which is not necessary at all as all required information is available from the caps already. Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1162 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6543>
This commit is contained in:
parent
8bfba72ea4
commit
95a0649945
2 changed files with 103 additions and 0 deletions
|
@ -1652,6 +1652,9 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream,
|
||||||
|
|
||||||
rtp_info_sync = TRUE;
|
rtp_info_sync = TRUE;
|
||||||
GST_DEBUG_OBJECT (bin, "Doing RTP-Info sync");
|
GST_DEBUG_OBJECT (bin, "Doing RTP-Info sync");
|
||||||
|
} else if (!client->cname) {
|
||||||
|
GST_DEBUG_OBJECT (bin, "Have no CNAME yet");
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (bin, "Doing RTCP sync");
|
GST_DEBUG_OBJECT (bin, "Doing RTCP sync");
|
||||||
}
|
}
|
||||||
|
@ -1661,6 +1664,9 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream,
|
||||||
if (!GST_CLOCK_TIME_IS_VALID (npt_start)) {
|
if (!GST_CLOCK_TIME_IS_VALID (npt_start)) {
|
||||||
GST_DEBUG_OBJECT (bin, "invalidated sync data, bailing out");
|
GST_DEBUG_OBJECT (bin, "invalidated sync data, bailing out");
|
||||||
return;
|
return;
|
||||||
|
} else if (!client->cname) {
|
||||||
|
GST_DEBUG_OBJECT (bin, "Have no CNAME yet");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtp_info_sync = TRUE;
|
rtp_info_sync = TRUE;
|
||||||
|
@ -1987,6 +1993,22 @@ gst_rtp_bin_handle_sync (GstElement * jitterbuffer, GstStructure * s,
|
||||||
|
|
||||||
if (!gst_structure_get_uint64 (s, "sr-ext-rtptime", &extrtptime)
|
if (!gst_structure_get_uint64 (s, "sr-ext-rtptime", &extrtptime)
|
||||||
|| !gst_structure_has_field_typed (s, "sr-buffer", GST_TYPE_BUFFER)) {
|
|| !gst_structure_has_field_typed (s, "sr-buffer", GST_TYPE_BUFFER)) {
|
||||||
|
/* Do initial RTSP sync if allowed */
|
||||||
|
if (npt_start != GST_CLOCK_TIME_NONE
|
||||||
|
&& gst_structure_get_uint (s, "ssrc", &ssrc)) {
|
||||||
|
GST_DEBUG_OBJECT (bin, "handle sync from RTSP information for SSRC %08x",
|
||||||
|
ssrc);
|
||||||
|
|
||||||
|
if (ssrc != stream->ssrc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GST_RTP_BIN_LOCK (bin);
|
||||||
|
gst_rtp_bin_associate (bin, stream, cname ? strlen (cname) : 0,
|
||||||
|
(const guint8 *) cname, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE,
|
||||||
|
base_rtptime, base_time, clock_rate, clock_base, npt_start);
|
||||||
|
GST_RTP_BIN_UNLOCK (bin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
/* invalid structure */
|
/* invalid structure */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -396,6 +396,7 @@ struct _GstRtpJitterBufferPrivate
|
||||||
gint32 clock_rate;
|
gint32 clock_rate;
|
||||||
gint64 clock_base;
|
gint64 clock_base;
|
||||||
gint64 ts_offset_remainder;
|
gint64 ts_offset_remainder;
|
||||||
|
gboolean rtsp_sync_done;
|
||||||
|
|
||||||
/* when we are shutting down */
|
/* when we are shutting down */
|
||||||
GstFlowReturn srcresult;
|
GstFlowReturn srcresult;
|
||||||
|
@ -582,6 +583,7 @@ gst_rtp_jitter_buffer_set_active (GstRtpJitterBuffer * jitterbuffer,
|
||||||
static void do_handle_sync (GstRtpJitterBuffer * jitterbuffer);
|
static void do_handle_sync (GstRtpJitterBuffer * jitterbuffer);
|
||||||
static void do_handle_sync_inband (GstRtpJitterBuffer * jitterbuffer,
|
static void do_handle_sync_inband (GstRtpJitterBuffer * jitterbuffer,
|
||||||
guint64 ntpnstime);
|
guint64 ntpnstime);
|
||||||
|
static void do_handle_sync_rtsp (GstRtpJitterBuffer * jitterbuffer);
|
||||||
|
|
||||||
static void unschedule_current_timer (GstRtpJitterBuffer * jitterbuffer);
|
static void unschedule_current_timer (GstRtpJitterBuffer * jitterbuffer);
|
||||||
|
|
||||||
|
@ -1219,6 +1221,7 @@ gst_rtp_jitter_buffer_init (GstRtpJitterBuffer * jitterbuffer)
|
||||||
rtp_jitter_buffer_set_delay (priv->jbuf, priv->latency_ns);
|
rtp_jitter_buffer_set_delay (priv->jbuf, priv->latency_ns);
|
||||||
rtp_jitter_buffer_set_buffering (priv->jbuf, FALSE);
|
rtp_jitter_buffer_set_buffering (priv->jbuf, FALSE);
|
||||||
priv->active = TRUE;
|
priv->active = TRUE;
|
||||||
|
priv->rtsp_sync_done = FALSE;
|
||||||
|
|
||||||
priv->srcpad =
|
priv->srcpad =
|
||||||
gst_pad_new_from_static_template (&gst_rtp_jitter_buffer_src_template,
|
gst_pad_new_from_static_template (&gst_rtp_jitter_buffer_src_template,
|
||||||
|
@ -1461,6 +1464,7 @@ gst_rtp_jitter_buffer_clear_pt_map (GstRtpJitterBuffer * jitterbuffer)
|
||||||
/* do not clear current content, but refresh state for new arrival */
|
/* do not clear current content, but refresh state for new arrival */
|
||||||
GST_DEBUG_OBJECT (jitterbuffer, "reset jitterbuffer");
|
GST_DEBUG_OBJECT (jitterbuffer, "reset jitterbuffer");
|
||||||
rtp_jitter_buffer_reset_skew (priv->jbuf);
|
rtp_jitter_buffer_reset_skew (priv->jbuf);
|
||||||
|
priv->rtsp_sync_done = FALSE;
|
||||||
JBUF_UNLOCK (priv);
|
JBUF_UNLOCK (priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1652,6 +1656,8 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer,
|
||||||
else
|
else
|
||||||
priv->npt_stop = -1;
|
priv->npt_stop = -1;
|
||||||
|
|
||||||
|
priv->rtsp_sync_done = FALSE;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (jitterbuffer,
|
GST_DEBUG_OBJECT (jitterbuffer,
|
||||||
"npt start/stop: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
|
"npt start/stop: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (priv->npt_start), GST_TIME_ARGS (priv->npt_stop));
|
GST_TIME_ARGS (priv->npt_start), GST_TIME_ARGS (priv->npt_stop));
|
||||||
|
@ -1855,6 +1861,7 @@ gst_rtp_jitter_buffer_flush_stop (GstRtpJitterBuffer * jitterbuffer)
|
||||||
rtp_jitter_buffer_flush (priv->jbuf, NULL, NULL);
|
rtp_jitter_buffer_flush (priv->jbuf, NULL, NULL);
|
||||||
rtp_jitter_buffer_disable_buffering (priv->jbuf, FALSE);
|
rtp_jitter_buffer_disable_buffering (priv->jbuf, FALSE);
|
||||||
rtp_jitter_buffer_reset_skew (priv->jbuf);
|
rtp_jitter_buffer_reset_skew (priv->jbuf);
|
||||||
|
priv->rtsp_sync_done = FALSE;
|
||||||
rtp_timer_queue_remove_all (priv->timers);
|
rtp_timer_queue_remove_all (priv->timers);
|
||||||
g_queue_foreach (&priv->gap_packets, (GFunc) gst_buffer_unref, NULL);
|
g_queue_foreach (&priv->gap_packets, (GFunc) gst_buffer_unref, NULL);
|
||||||
g_queue_clear (&priv->gap_packets);
|
g_queue_clear (&priv->gap_packets);
|
||||||
|
@ -3074,6 +3081,7 @@ gst_rtp_jitter_buffer_reset (GstRtpJitterBuffer * jitterbuffer,
|
||||||
rtp_timer_queue_remove_all (priv->timers);
|
rtp_timer_queue_remove_all (priv->timers);
|
||||||
priv->discont = TRUE;
|
priv->discont = TRUE;
|
||||||
priv->last_popped_seqnum = -1;
|
priv->last_popped_seqnum = -1;
|
||||||
|
priv->rtsp_sync_done = FALSE;
|
||||||
|
|
||||||
if (priv->gap_packets.head) {
|
if (priv->gap_packets.head) {
|
||||||
GstBuffer *gap_buffer = priv->gap_packets.head->data;
|
GstBuffer *gap_buffer = priv->gap_packets.head->data;
|
||||||
|
@ -3643,6 +3651,9 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent,
|
||||||
update_rtx_timers (jitterbuffer, seqnum, dts, pts, do_next_seqnum, is_rtx,
|
update_rtx_timers (jitterbuffer, seqnum, dts, pts, do_next_seqnum, is_rtx,
|
||||||
g_steal_pointer (&timer));
|
g_steal_pointer (&timer));
|
||||||
|
|
||||||
|
if (priv->seqnum_base != -1)
|
||||||
|
do_handle_sync_rtsp (jitterbuffer);
|
||||||
|
|
||||||
/* we had an unhandled SR, handle it now */
|
/* we had an unhandled SR, handle it now */
|
||||||
if (priv->last_sr)
|
if (priv->last_sr)
|
||||||
do_handle_sync (jitterbuffer);
|
do_handle_sync (jitterbuffer);
|
||||||
|
@ -4635,6 +4646,76 @@ pause:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_handle_sync_rtsp (GstRtpJitterBuffer * jitterbuffer)
|
||||||
|
{
|
||||||
|
GstRtpJitterBufferPrivate *priv;
|
||||||
|
guint64 base_rtptime, base_time;
|
||||||
|
guint32 clock_rate;
|
||||||
|
guint64 clock_base;
|
||||||
|
guint64 npt_start;
|
||||||
|
|
||||||
|
priv = jitterbuffer->priv;
|
||||||
|
|
||||||
|
if (priv->rtsp_sync_done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* no RTSP information in the caps */
|
||||||
|
if (priv->clock_base == -1 || priv->npt_start == -1) {
|
||||||
|
priv->rtsp_sync_done = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the last values from the jitterbuffer */
|
||||||
|
rtp_jitter_buffer_get_sync (priv->jbuf, &base_rtptime, &base_time,
|
||||||
|
&clock_rate, NULL);
|
||||||
|
|
||||||
|
/* clock-base is the RTP timestamp at npt-start */
|
||||||
|
npt_start = priv->npt_start;
|
||||||
|
clock_base = priv->clock_base;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (jitterbuffer,
|
||||||
|
"NPT start %" GST_TIME_FORMAT ", clock-base %" G_GUINT64_FORMAT ", base %"
|
||||||
|
GST_TIME_FORMAT ", base RTP time %" G_GUINT64_FORMAT ", clock-rate %"
|
||||||
|
G_GUINT32_FORMAT, GST_TIME_ARGS (npt_start), clock_base,
|
||||||
|
GST_TIME_ARGS (base_time), base_rtptime, clock_rate);
|
||||||
|
|
||||||
|
if (base_rtptime == -1 || clock_rate == -1 || base_time == -1) {
|
||||||
|
GST_ERROR_OBJECT (jitterbuffer,
|
||||||
|
"No base RTP time, clock rate or base time");
|
||||||
|
priv->rtsp_sync_done = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstStructure *s;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
s = gst_structure_new ("application/x-rtp-sync",
|
||||||
|
"base-rtptime", G_TYPE_UINT64, base_rtptime,
|
||||||
|
"base-time", G_TYPE_UINT64, base_time,
|
||||||
|
"clock-rate", G_TYPE_UINT, clock_rate,
|
||||||
|
"clock-base", G_TYPE_UINT64, clock_base & G_MAXUINT32,
|
||||||
|
"npt-start", G_TYPE_UINT64, npt_start,
|
||||||
|
"ssrc", G_TYPE_UINT, priv->last_ssrc, NULL);
|
||||||
|
|
||||||
|
for (l = priv->cname_ssrc_mappings; l; l = l->next) {
|
||||||
|
const CNameSSRCMapping *map = l->data;
|
||||||
|
|
||||||
|
if (map->ssrc == priv->last_ssrc) {
|
||||||
|
gst_structure_set (s, "cname", G_TYPE_STRING, map->cname, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (jitterbuffer, "signaling sync");
|
||||||
|
JBUF_UNLOCK (priv);
|
||||||
|
g_signal_emit (jitterbuffer,
|
||||||
|
gst_rtp_jitter_buffer_signals[SIGNAL_HANDLE_SYNC], 0, s);
|
||||||
|
JBUF_LOCK (priv);
|
||||||
|
gst_structure_free (s);
|
||||||
|
priv->rtsp_sync_done = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_handle_sync_inband (GstRtpJitterBuffer * jitterbuffer, guint64 ntpnstime)
|
do_handle_sync_inband (GstRtpJitterBuffer * jitterbuffer, guint64 ntpnstime)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue