mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-09 16:02:59 +00:00
gst/rtpmanager/gstrtpbin.c: Reset rtp timestamp interpollation when we detect a gap when the clock_base changed.
Original commit message from CVS: * gst/rtpmanager/gstrtpbin.c: (gst_rtp_bin_associate), (gst_rtp_bin_sync_chain), (new_ssrc_pad_found): Reset rtp timestamp interpollation when we detect a gap when the clock_base changed. Don't try to adjust the ts-offset when it's too big (> 3seconds) * gst/rtpmanager/gstrtpsession.c: (gst_rtp_session_set_ssrc): * gst/rtpmanager/gstrtpsession.h: Add method to set session SSRC. * gst/rtpmanager/rtpsession.c: (check_collision), (rtp_session_set_internal_ssrc), (rtp_session_get_internal_ssrc), (rtp_session_on_timeout): * gst/rtpmanager/rtpsession.h: Added debugging for the collision checks. Add method to change the internal SSRC of the session. * gst/rtpmanager/rtpsource.c: (rtp_source_process_rtp): Reset the clock base when we detect large jumps in the seqnums.
This commit is contained in:
parent
cc74738d83
commit
62ecaee748
6 changed files with 88 additions and 8 deletions
|
@ -119,6 +119,7 @@
|
||||||
|
|
||||||
#include "gstrtpbin-marshal.h"
|
#include "gstrtpbin-marshal.h"
|
||||||
#include "gstrtpbin.h"
|
#include "gstrtpbin.h"
|
||||||
|
#include "gstrtpsession.h"
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
|
GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
|
||||||
#define GST_CAT_DEFAULT gst_rtp_bin_debug
|
#define GST_CAT_DEFAULT gst_rtp_bin_debug
|
||||||
|
@ -317,6 +318,7 @@ struct _GstRtpBinStream
|
||||||
gint64 unix_delta;
|
gint64 unix_delta;
|
||||||
|
|
||||||
/* for lip-sync */
|
/* for lip-sync */
|
||||||
|
guint64 last_clock_base;
|
||||||
guint64 clock_base;
|
guint64 clock_base;
|
||||||
guint64 clock_base_time;
|
guint64 clock_base_time;
|
||||||
gint clock_rate;
|
gint clock_rate;
|
||||||
|
@ -876,13 +878,18 @@ gst_rtp_bin_associate (GstRtpBin * bin, GstRtpBinStream * stream, guint8 len,
|
||||||
else
|
else
|
||||||
diff = ostream->ts_offset - ostream->prev_ts_offset;
|
diff = ostream->ts_offset - ostream->prev_ts_offset;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (bin,
|
||||||
|
"ts-offset %" G_GUINT64_FORMAT ", prev %" G_GUINT64_FORMAT
|
||||||
|
", diff: %" G_GINT64_FORMAT, ostream->ts_offset,
|
||||||
|
ostream->prev_ts_offset, diff);
|
||||||
|
|
||||||
/* only change diff when it changed more than 1 millisecond. This
|
/* only change diff when it changed more than 1 millisecond. This
|
||||||
* compensates for rounding errors in NTP to RTP timestamp
|
* compensates for rounding errors in NTP to RTP timestamp
|
||||||
* conversions */
|
* conversions */
|
||||||
if (diff > GST_MSECOND)
|
if (diff > GST_MSECOND && diff < (3 * GST_SECOND)) {
|
||||||
g_object_set (ostream->buffer, "ts-offset", ostream->ts_offset, NULL);
|
g_object_set (ostream->buffer, "ts-offset", ostream->ts_offset, NULL);
|
||||||
|
ostream->prev_ts_offset = ostream->ts_offset;
|
||||||
ostream->prev_ts_offset = ostream->ts_offset;
|
}
|
||||||
}
|
}
|
||||||
GST_DEBUG_OBJECT (bin, "stream SSRC %08x, delta %" G_GINT64_FORMAT,
|
GST_DEBUG_OBJECT (bin, "stream SSRC %08x, delta %" G_GINT64_FORMAT,
|
||||||
ostream->ssrc, ostream->ts_offset);
|
ostream->ssrc, ostream->ts_offset);
|
||||||
|
@ -929,6 +936,9 @@ gst_rtp_bin_sync_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
guint32 rtptime;
|
guint32 rtptime;
|
||||||
gboolean have_sr, have_sdes;
|
gboolean have_sr, have_sdes;
|
||||||
gboolean more;
|
gboolean more;
|
||||||
|
guint64 clock_base;
|
||||||
|
|
||||||
|
clock_base = GST_BUFFER_OFFSET (buffer);
|
||||||
|
|
||||||
stream = gst_pad_get_element_private (pad);
|
stream = gst_pad_get_element_private (pad);
|
||||||
bin = stream->bin;
|
bin = stream->bin;
|
||||||
|
@ -938,6 +948,14 @@ gst_rtp_bin_sync_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
if (!gst_rtcp_buffer_validate (buffer))
|
if (!gst_rtcp_buffer_validate (buffer))
|
||||||
goto invalid_rtcp;
|
goto invalid_rtcp;
|
||||||
|
|
||||||
|
/* clock base changes when there is a huge gap in the timestamps or seqnum.
|
||||||
|
* When this happens we don't want to calculate the extended timestamp based
|
||||||
|
* on the previous one but reset the calculation. */
|
||||||
|
if (stream->last_clock_base != clock_base) {
|
||||||
|
stream->last_extrtptime = -1;
|
||||||
|
stream->last_clock_base = clock_base;
|
||||||
|
}
|
||||||
|
|
||||||
have_sr = FALSE;
|
have_sr = FALSE;
|
||||||
have_sdes = FALSE;
|
have_sdes = FALSE;
|
||||||
GST_RTCP_BUFFER_FOR_PACKETS (more, buffer, &packet) {
|
GST_RTCP_BUFFER_FOR_PACKETS (more, buffer, &packet) {
|
||||||
|
@ -989,7 +1007,7 @@ gst_rtp_bin_sync_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
gst_rtcp_packet_sdes_get_entry (&packet, &type, &len, &data);
|
gst_rtcp_packet_sdes_get_entry (&packet, &type, &len, &data);
|
||||||
|
|
||||||
if (type == GST_RTCP_SDES_CNAME) {
|
if (type == GST_RTCP_SDES_CNAME) {
|
||||||
stream->clock_base = GST_BUFFER_OFFSET (buffer);
|
stream->clock_base = clock_base;
|
||||||
stream->clock_base_time = GST_BUFFER_OFFSET_END (buffer);
|
stream->clock_base_time = GST_BUFFER_OFFSET_END (buffer);
|
||||||
/* associate the stream to CNAME */
|
/* associate the stream to CNAME */
|
||||||
gst_rtp_bin_associate (bin, stream, len, data);
|
gst_rtp_bin_associate (bin, stream, len, data);
|
||||||
|
@ -1876,6 +1894,7 @@ new_ssrc_pad_found (GstElement * element, guint ssrc, GstPad * pad,
|
||||||
gst_caps_to_string (caps), GST_DEBUG_PAD_NAME (pad));
|
gst_caps_to_string (caps), GST_DEBUG_PAD_NAME (pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream->last_clock_base = -1;
|
||||||
if (gst_structure_get_uint (s, "clock-base", &val))
|
if (gst_structure_get_uint (s, "clock-base", &val))
|
||||||
stream->clock_base = val;
|
stream->clock_base = val;
|
||||||
else
|
else
|
||||||
|
|
|
@ -237,6 +237,7 @@ struct _GstRtpSessionPrivate
|
||||||
{
|
{
|
||||||
GMutex *lock;
|
GMutex *lock;
|
||||||
GstClock *sysclock;
|
GstClock *sysclock;
|
||||||
|
|
||||||
RTPSession *session;
|
RTPSession *session;
|
||||||
|
|
||||||
/* thread for sending out RTCP */
|
/* thread for sending out RTCP */
|
||||||
|
@ -1846,3 +1847,9 @@ static void
|
||||||
gst_rtp_session_release_pad (GstElement * element, GstPad * pad)
|
gst_rtp_session_release_pad (GstElement * element, GstPad * pad)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_rtp_session_set_ssrc (GstRtpSession * sess, guint32 ssrc)
|
||||||
|
{
|
||||||
|
rtp_session_set_internal_ssrc (sess->priv->session, ssrc);
|
||||||
|
}
|
||||||
|
|
|
@ -75,4 +75,6 @@ struct _GstRtpSessionClass {
|
||||||
|
|
||||||
GType gst_rtp_session_get_type (void);
|
GType gst_rtp_session_get_type (void);
|
||||||
|
|
||||||
|
void gst_rtp_session_set_ssrc (GstRtpSession *sess, guint32 ssrc);
|
||||||
|
|
||||||
#endif /* __GST_RTP_SESSION_H__ */
|
#endif /* __GST_RTP_SESSION_H__ */
|
||||||
|
|
|
@ -916,7 +916,6 @@ check_collision (RTPSession * sess, RTPSource * source,
|
||||||
/* This is not our local source, but lets check if two remote
|
/* This is not our local source, but lets check if two remote
|
||||||
* source collide
|
* source collide
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (rtp) {
|
if (rtp) {
|
||||||
if (source->have_rtp_from) {
|
if (source->have_rtp_from) {
|
||||||
if (gst_netaddress_equal (&source->rtp_from, &arrival->address))
|
if (gst_netaddress_equal (&source->rtp_from, &arrival->address))
|
||||||
|
@ -938,8 +937,9 @@ check_collision (RTPSession * sess, RTPSource * source,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* We received RTP or RTCP from this source before but the network address
|
||||||
/* In this case, we have third-party collision or loop */
|
* changed. In this case, we have third-party collision or loop */
|
||||||
|
GST_DEBUG ("we have a third-party collision or loop");
|
||||||
|
|
||||||
/* FIXME: Log 3rd party collision somehow
|
/* FIXME: Log 3rd party collision somehow
|
||||||
* Maybe should be done in upper layer, only the SDES can tell us
|
* Maybe should be done in upper layer, only the SDES can tell us
|
||||||
|
@ -1026,7 +1026,7 @@ obtain_source (RTPSession * sess, guint32 ssrc, gboolean * created,
|
||||||
* rtp_session_get_internal_source:
|
* rtp_session_get_internal_source:
|
||||||
* @sess: a #RTPSession
|
* @sess: a #RTPSession
|
||||||
*
|
*
|
||||||
* Get the internal #RTPSource of @session.
|
* Get the internal #RTPSource of @sess.
|
||||||
*
|
*
|
||||||
* Returns: The internal #RTPSource. g_object_unref() after usage.
|
* Returns: The internal #RTPSource. g_object_unref() after usage.
|
||||||
*/
|
*/
|
||||||
|
@ -1042,6 +1042,48 @@ rtp_session_get_internal_source (RTPSession * sess)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rtp_session_set_internal_ssrc:
|
||||||
|
* @sess: a #RTPSession
|
||||||
|
* @ssrc: an SSRC
|
||||||
|
*
|
||||||
|
* Set the SSRC of @sess to @ssrc.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rtp_session_set_internal_ssrc (RTPSession * sess, guint32 ssrc)
|
||||||
|
{
|
||||||
|
RTP_SESSION_LOCK (sess);
|
||||||
|
g_hash_table_steal (sess->ssrcs[sess->mask_idx],
|
||||||
|
GINT_TO_POINTER (sess->source->ssrc));
|
||||||
|
|
||||||
|
sess->source->ssrc = ssrc;
|
||||||
|
rtp_source_reset (sess->source);
|
||||||
|
|
||||||
|
g_hash_table_insert (sess->ssrcs[sess->mask_idx],
|
||||||
|
GINT_TO_POINTER (sess->source->ssrc), sess->source);
|
||||||
|
RTP_SESSION_UNLOCK (sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rtp_session_get_internal_ssrc:
|
||||||
|
* @sess: a #RTPSession
|
||||||
|
*
|
||||||
|
* Get the internal SSRC of @sess.
|
||||||
|
*
|
||||||
|
* Returns: The SSRC of the session.
|
||||||
|
*/
|
||||||
|
guint32
|
||||||
|
rtp_session_get_internal_ssrc (RTPSession * sess)
|
||||||
|
{
|
||||||
|
guint32 ssrc;
|
||||||
|
|
||||||
|
RTP_SESSION_LOCK (sess);
|
||||||
|
ssrc = sess->source->ssrc;
|
||||||
|
RTP_SESSION_UNLOCK (sess);
|
||||||
|
|
||||||
|
return ssrc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rtp_session_add_source:
|
* rtp_session_add_source:
|
||||||
* @sess: a #RTPSession
|
* @sess: a #RTPSession
|
||||||
|
@ -2285,6 +2327,7 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for outdated collisions */
|
/* check for outdated collisions */
|
||||||
|
GST_DEBUG ("checking collision list");
|
||||||
item = g_list_first (sess->conflicting_addresses);
|
item = g_list_first (sess->conflicting_addresses);
|
||||||
while (item) {
|
while (item) {
|
||||||
RTPConflictingAddress *known_conflict = item->data;
|
RTPConflictingAddress *known_conflict = item->data;
|
||||||
|
@ -2294,12 +2337,14 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time,
|
||||||
RTCP_INTERVAL_COLLISION_TIMEOUT)) {
|
RTCP_INTERVAL_COLLISION_TIMEOUT)) {
|
||||||
sess->conflicting_addresses =
|
sess->conflicting_addresses =
|
||||||
g_list_delete_link (sess->conflicting_addresses, item);
|
g_list_delete_link (sess->conflicting_addresses, item);
|
||||||
|
GST_DEBUG ("collision %p timed out", known_conflict);
|
||||||
g_free (known_conflict);
|
g_free (known_conflict);
|
||||||
}
|
}
|
||||||
item = next_item;
|
item = next_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sess->change_ssrc) {
|
if (sess->change_ssrc) {
|
||||||
|
GST_DEBUG ("need to change our SSRC (%08x)", sess->source->ssrc);
|
||||||
g_hash_table_steal (sess->ssrcs[sess->mask_idx],
|
g_hash_table_steal (sess->ssrcs[sess->mask_idx],
|
||||||
GINT_TO_POINTER (sess->source->ssrc));
|
GINT_TO_POINTER (sess->source->ssrc));
|
||||||
|
|
||||||
|
@ -2313,6 +2358,7 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time,
|
||||||
sess->bye_reason = NULL;
|
sess->bye_reason = NULL;
|
||||||
sess->sent_bye = FALSE;
|
sess->sent_bye = FALSE;
|
||||||
sess->change_ssrc = FALSE;
|
sess->change_ssrc = FALSE;
|
||||||
|
GST_DEBUG ("changed our SSRC to %08x", sess->source->ssrc);
|
||||||
}
|
}
|
||||||
RTP_SESSION_UNLOCK (sess);
|
RTP_SESSION_UNLOCK (sess);
|
||||||
|
|
||||||
|
|
|
@ -264,6 +264,10 @@ gchar* rtp_session_get_sdes_string (RTPSession *sess, GstRTCPSDE
|
||||||
|
|
||||||
/* handling sources */
|
/* handling sources */
|
||||||
RTPSource* rtp_session_get_internal_source (RTPSession *sess);
|
RTPSource* rtp_session_get_internal_source (RTPSession *sess);
|
||||||
|
|
||||||
|
void rtp_session_set_internal_ssrc (RTPSession *sess, guint32 ssrc);
|
||||||
|
guint32 rtp_session_get_internal_ssrc (RTPSession *sess);
|
||||||
|
|
||||||
gboolean rtp_session_add_source (RTPSession *sess, RTPSource *src);
|
gboolean rtp_session_add_source (RTPSession *sess, RTPSource *src);
|
||||||
guint rtp_session_get_num_sources (RTPSession *sess);
|
guint rtp_session_get_num_sources (RTPSession *sess);
|
||||||
guint rtp_session_get_num_active_sources (RTPSession *sess);
|
guint rtp_session_get_num_active_sources (RTPSession *sess);
|
||||||
|
|
|
@ -923,11 +923,13 @@ rtp_source_process_rtp (RTPSource * src, GstBuffer * buffer,
|
||||||
} else {
|
} else {
|
||||||
/* unacceptable jump */
|
/* unacceptable jump */
|
||||||
stats->bad_seq = (seqnr + 1) & (RTP_SEQ_MOD - 1);
|
stats->bad_seq = (seqnr + 1) & (RTP_SEQ_MOD - 1);
|
||||||
|
src->clock_base = -1;
|
||||||
goto bad_sequence;
|
goto bad_sequence;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* duplicate or reordered packet, will be filtered by jitterbuffer. */
|
/* duplicate or reordered packet, will be filtered by jitterbuffer. */
|
||||||
GST_WARNING ("duplicate or reordered packet");
|
GST_WARNING ("duplicate or reordered packet");
|
||||||
|
src->clock_base = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
src->stats.octets_received += arrival->payload_len;
|
src->stats.octets_received += arrival->payload_len;
|
||||||
|
|
Loading…
Reference in a new issue