* Copyright 2007 Nokia Corporation
* @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk>.
* Copyright 2007 Wim Taymans <wim.taymans@gmail.com>
+ * Copyright 2015 Kurento (http://kurento.org/)
+ * @author: Miguel París <mparisdiaz@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
guint64 num_rtx_failed;
gdouble avg_rtx_num;
guint64 avg_rtx_rtt;
+ RTPPacketRateCtx packet_rate_ctx;
/* for the jitter */
GstClockTime last_dts;
static gboolean
handle_big_gap_buffer (GstRtpJitterBuffer * jitterbuffer, gboolean future,
- GstBuffer * buffer, guint8 pt, guint16 seqnum, gint gap)
+ GstBuffer * buffer, guint8 pt, guint16 seqnum, gint gap, guint max_dropout,
+ guint max_misorder)
{
GstRtpJitterBufferPrivate *priv;
guint gap_packets_length;
GST_DEBUG_OBJECT (jitterbuffer,
"buffer too %s %d < %d, got 5 consecutive ones - reset",
(future ? "new" : "old"), gap,
- (future ? RTP_MAX_DROPOUT : -RTP_MAX_MISORDER));
+ (future ? max_dropout : -max_misorder));
reset = TRUE;
} else if (!all_consecutive) {
g_queue_foreach (&priv->gap_packets, (GFunc) gst_buffer_unref, NULL);
GST_DEBUG_OBJECT (jitterbuffer,
"buffer too %s %d < %d, got no 5 consecutive ones - dropping",
(future ? "new" : "old"), gap,
- (future ? RTP_MAX_DROPOUT : -RTP_MAX_MISORDER));
+ (future ? max_dropout : -max_misorder));
buffer = NULL;
} else {
GST_DEBUG_OBJECT (jitterbuffer,
"buffer too %s %d < %d, got %u consecutive ones - waiting",
(future ? "new" : "old"), gap,
- (future ? RTP_MAX_DROPOUT : -RTP_MAX_MISORDER),
- gap_packets_length + 1);
+ (future ? max_dropout : -max_misorder), gap_packets_length + 1);
buffer = NULL;
}
} else {
GST_DEBUG_OBJECT (jitterbuffer,
"buffer too %s %d < %d, first one - waiting", (future ? "new" : "old"),
- gap, -RTP_MAX_MISORDER);
+ gap, -max_misorder);
g_queue_push_tail (&priv->gap_packets, buffer);
buffer = NULL;
}
RTPJitterBufferItem *item;
GstMessage *msg = NULL;
gboolean estimated_dts = FALSE;
+ guint32 packet_rate, max_dropout, max_misorder;
jitterbuffer = GST_RTP_JITTER_BUFFER_CAST (parent);
expected = priv->next_in_seqnum;
+ packet_rate =
+ gst_rtp_packet_rate_ctx_update (&priv->packet_rate_ctx, seqnum, rtptime);
+ max_dropout =
+ gst_rtp_packet_rate_ctx_get_max_dropout (&priv->packet_rate_ctx,
+ priv->max_dropout_time);
+ max_misorder =
+ gst_rtp_packet_rate_ctx_get_max_misorder (&priv->packet_rate_ctx,
+ priv->max_misorder_time);
+ GST_TRACE_OBJECT (jitterbuffer,
+ "packet_rate: %d, max_dropout: %d, max_misorder: %d", packet_rate,
+ max_dropout, max_misorder);
+
/* now check against our expected seqnum */
if (G_LIKELY (expected != -1)) {
gint gap;
if (gap < 0) {
/* we received an old packet */
- if (G_UNLIKELY (gap != -1 && gap < -RTP_MAX_MISORDER)) {
+ if (G_UNLIKELY (gap != -1 && gap < -max_misorder)) {
reset =
handle_big_gap_buffer (jitterbuffer, FALSE, buffer, pt, seqnum,
- gap);
+ gap, max_dropout, max_misorder);
buffer = NULL;
} else {
GST_DEBUG_OBJECT (jitterbuffer, "old packet received");
}
} else {
/* new packet, we are missing some packets */
- if (G_UNLIKELY (priv->timers->len >= RTP_MAX_DROPOUT)) {
+ if (G_UNLIKELY (priv->timers->len >= max_dropout)) {
/* If we have timers for more than RTP_MAX_DROPOUT packets
* pending this means that we have a huge gap overall. We can
* reset the jitterbuffer at this point because there's
* next packet */
GST_WARNING_OBJECT (jitterbuffer,
"%d pending timers > %d - resetting", priv->timers->len,
- RTP_MAX_DROPOUT);
+ max_dropout);
reset = TRUE;
gst_buffer_unref (buffer);
buffer = NULL;
- } else if (G_UNLIKELY (gap >= RTP_MAX_DROPOUT)) {
+ } else if (G_UNLIKELY (gap >= max_dropout)) {
reset =
handle_big_gap_buffer (jitterbuffer, TRUE, buffer, pt, seqnum,
- gap);
+ gap, max_dropout, max_misorder);
buffer = NULL;
} else {
GST_DEBUG_OBJECT (jitterbuffer, "%d missing packets", gap);
GstClockTime timer_timeout = -1;
gint i, len;
- /* If we have a clock, update "now" now with the very latest running time
- * we have. It is used below when timeouts are triggered to calculate
- * any next possible timeout. If we only update it after waiting for the
- * clock, we would give a too old time to the timeout functions.
+ /* If we have a clock, update "now" now with the very
+ * latest running time we have. If timers are unscheduled below we
+ * otherwise wouldn't update now (it's only updated when timers
+ * expire), and also for the very first loop iteration now would
+ * otherwise always be 0
*/
GST_OBJECT_LOCK (jitterbuffer);
if (GST_ELEMENT_CLOCK (jitterbuffer)) {
}
if (ret != GST_CLOCK_UNSCHEDULED) {
+ now = timer_timeout + MAX (clock_jitter, 0);
GST_DEBUG_OBJECT (jitterbuffer, "sync done, %d, #%d, %" G_GINT64_FORMAT,
ret, priv->timer_seqnum, clock_jitter);
} else {
/* GStreamer
* Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
+ * Copyright (C) 2015 Kurento (http://kurento.org/)
+ * @author: Miguel París <mparisdiaz@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
GST_DEBUG ("got clock-rate %d", clock_rate);
src->clock_rate = clock_rate;
+ gst_rtp_packet_rate_ctx_reset (&src->packet_rate_ctx, clock_rate);
}
return src->clock_rate;
}
guint16 seqnr, expected;
RTPSourceStats *stats;
gint16 delta;
+ gint32 packet_rate, max_dropout, max_misorder;
stats = &src->stats;
seqnr = pinfo->seqnum;
+ packet_rate =
+ gst_rtp_packet_rate_ctx_update (&src->packet_rate_ctx, pinfo->seqnum,
+ pinfo->rtptime);
+ max_dropout =
+ gst_rtp_packet_rate_ctx_get_max_dropout (&src->packet_rate_ctx,
+ src->max_dropout_time);
+ max_misorder =
+ gst_rtp_packet_rate_ctx_get_max_misorder (&src->packet_rate_ctx,
+ src->max_misorder_time);
+ GST_TRACE ("SSRC %08x, packet_rate: %d, max_dropout: %d, max_misorder: %d",
+ src->ssrc, packet_rate, max_dropout, max_misorder);
+
if (stats->cycles == -1) {
GST_DEBUG ("received first packet");
/* first time we heard of this source */
/* unexpected seqnum in probation */
goto probation_seqnum;
}
- } else if (delta >= 0 && delta < RTP_MAX_DROPOUT) {
+ } else if (delta >= 0 && delta < max_dropout) {
/* Clear bad packets */
stats->bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */
g_queue_foreach (src->packets, (GFunc) gst_buffer_unref, NULL);
stats->cycles += RTP_SEQ_MOD;
}
stats->max_seq = seqnr;
- } else if (delta < -RTP_MAX_MISORDER || delta >= RTP_MAX_DROPOUT) {
+ } else if (delta < -max_misorder || delta >= max_dropout) {
/* the sequence number made a very large jump */
if (seqnr == stats->bad_seq && src->packets->head) {
/* two sequential packets -- assume that the other side
pinfo->data = NULL;
goto bad_sequence;
}
- } else { /* delta < 0 && delta >= -RTP_MAX_MISORDER */
+ } else { /* delta < 0 && delta >= -max_misorder */
/* Clear bad packets */
stats->bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */
g_queue_foreach (src->packets, (GFunc) gst_buffer_unref, NULL);
}
bad_sequence:
{
- GST_WARNING ("unacceptable seqnum received");
+ GST_WARNING
+ ("unacceptable seqnum received (seqnr %u, delta %d, packet_rate: %d, max_dropout: %d, max_misorder: %d)",
+ seqnr, delta, packet_rate, max_dropout, max_misorder);
return FALSE;
}
probation_seqnum:
/* GStreamer
* Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
+ * Copyright (C) 2015 Kurento (http://kurento.org/)
+ * @author: Miguel París <mparisdiaz@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
#define RTP_STATS_BYE_TIMEOUT (2 * GST_SECOND)
/*
- * The maximum number of missing packets we tolerate. These are packets with a
- * sequence number bigger than the last seen packet.
+ * The default and minimum values of the maximum number of missing packets we tolerate.
+ * These are packets with asequence number bigger than the last seen packet.
*/
-#define RTP_MAX_DROPOUT 3000
+#define RTP_DEF_DROPOUT 3000
+#define RTP_MIN_DROPOUT 30
+
/*
- * The maximum number of misordered packets we tolerate. These are packets with
- * a sequence number smaller than the last seen packet.
+ * The default and minimum values of the maximum number of misordered packets we tolerate.
+ * These are packets with a sequence number smaller than the last seen packet.
*/
-#define RTP_MAX_MISORDER 100
+#define RTP_DEF_MISORDER 100
+#define RTP_MIN_MISORDER 10
/**
* RTPPacketRateCtx:
void gst_rtp_packet_rate_ctx_reset (RTPPacketRateCtx * ctx, guint32 clock_rate);
guint32 gst_rtp_packet_rate_ctx_update (RTPPacketRateCtx *ctx, guint16 seqnum, guint32 ts);
guint32 gst_rtp_packet_rate_ctx_get (RTPPacketRateCtx *ctx);
+guint32 gst_rtp_packet_rate_ctx_get_max_dropout (RTPPacketRateCtx *ctx, gint32 time_ms);
+guint32 gst_rtp_packet_rate_ctx_get_max_misorder (RTPPacketRateCtx *ctx, gint32 time_ms);
/**
* RTPSessionStats: