#define DEFAULT_DO_RETRANSMISSION FALSE
#define DEFAULT_RTX_DELAY 20
#define DEFAULT_RTX_DELAY_REORDER 3
+#define DEFAULT_RTX_RETRY_TIMEOUT 40
+#define DEFAULT_RTX_RETRY_PERIOD 200
enum
{
PROP_DO_RETRANSMISSION,
PROP_RTX_DELAY,
PROP_RTX_DELAY_REORDER,
+ PROP_RTX_RETRY_TIMEOUT,
+ PROP_RTX_RETRY_PERIOD,
PROP_LAST
};
gboolean do_retransmission;
gint rtx_delay;
gint rtx_delay_reorder;
+ gint rtx_retry_timeout;
+ gint rtx_retry_period;
/* the last seqnum we pushed out */
guint32 last_popped_seqnum;
guint16 seqnum;
TimerType type;
GstClockTime timeout;
+ GstClockTime rtx_base;
+ GstClockTime rtx_retry;
} TimerData;
#define GST_RTP_JITTER_BUFFER_GET_PRIVATE(o) \
"Sending retransmission event when this much reordering (-1 automatic)",
-1, G_MAXUINT, DEFAULT_RTX_DELAY_REORDER,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstRtpJitterBuffer::rtx-retry-timeout:
+ *
+ * When no packet has been received after sending a retransmission event
+ * for this time, retry sending a retransmission event.
+ *
+ * When -1 is used, the value will be estimated based on observed round
+ * trip time.
+ *
+ * Since: 1.2
+ */
+ g_object_class_install_property (gobject_class, PROP_RTX_RETRY_TIMEOUT,
+ g_param_spec_int ("rtx-retry-timeout", "RTX Retry Timeout",
+ "Retry sending a transmission event after this timeout in "
+ "ms (-1 automatic)", -1, G_MAXUINT, DEFAULT_RTX_RETRY_TIMEOUT,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstRtpJitterBuffer::rtx-retry-period:
+ *
+ * The amount of time to try to get a retransmission.
+ *
+ * When -1 is used, the value will be estimated based on the jitterbuffer
+ * latency and the observed round trip time.
+ *
+ * Since: 1.2
+ */
+ g_object_class_install_property (gobject_class, PROP_RTX_RETRY_PERIOD,
+ g_param_spec_int ("rtx-retry-period", "RTX Retry Period",
+ "Try to get a retransmission for this many ms "
+ "(-1 automatic)", -1, G_MAXUINT, DEFAULT_RTX_RETRY_PERIOD,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
* GstRtpJitterBuffer::request-pt-map:
priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
priv->rtx_delay = DEFAULT_RTX_DELAY;
priv->rtx_delay_reorder = DEFAULT_RTX_DELAY_REORDER;
+ priv->rtx_retry_timeout = DEFAULT_RTX_RETRY_TIMEOUT;
+ priv->rtx_retry_period = DEFAULT_RTX_RETRY_PERIOD;
priv->timers = g_array_new (FALSE, TRUE, sizeof (TimerData));
priv->jbuf = rtp_jitter_buffer_new ();
} else if (gap > priv->rtx_delay_reorder) {
/* max gap, we exceeded the max reorder distance and we don't expect the
* missing packet to be this reordered */
- reschedule_timer (jitterbuffer, test, test->seqnum, -1);
+ if (test->rtx_retry == 0)
+ reschedule_timer (jitterbuffer, test, test->seqnum, -1);
}
}
else
timer = add_timer (jitterbuffer, TIMER_TYPE_EXPECTED,
priv->next_in_seqnum, expected);
+
+ timer->rtx_base = timer->timeout;
+ timer->rtx_retry = 0;
} else if (timer) {
/* if we had a timer, remove it, we don't know when to expect the next
* packet. */
}
}
+/* the timeout for when we expected a packet expired */
+static GstFlowReturn
+do_expected_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
+ GstClockTimeDiff clock_jitter)
+{
+ GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
+
+ GST_DEBUG_OBJECT (jitterbuffer, "expected %d didn't arrive", timer->seqnum);
+
+ timer->rtx_retry += (priv->rtx_retry_timeout * GST_MSECOND);
+ if (timer->rtx_retry > (priv->rtx_retry_period * GST_MSECOND))
+ remove_timer (jitterbuffer, timer);
+ else
+ reschedule_timer (jitterbuffer, timer, timer->seqnum,
+ timer->rtx_base + timer->rtx_retry);
+
+ return GST_FLOW_OK;
+}
+
/* a packet is lost */
static GstFlowReturn
do_lost_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
do_timeout:
switch (timer->type) {
case TIMER_TYPE_EXPECTED:
- GST_DEBUG_OBJECT (jitterbuffer, "expected %d didn't arrive",
- timer->seqnum);
- remove_timer (jitterbuffer, timer);
+ result = do_expected_timeout (jitterbuffer, timer, clock_jitter);
break;
case TIMER_TYPE_LOST:
result = do_lost_timeout (jitterbuffer, timer, clock_jitter);
priv->rtx_delay_reorder = g_value_get_int (value);
JBUF_UNLOCK (priv);
break;
+ case PROP_RTX_RETRY_TIMEOUT:
+ JBUF_LOCK (priv);
+ priv->rtx_retry_timeout = g_value_get_int (value);
+ JBUF_UNLOCK (priv);
+ break;
+ case PROP_RTX_RETRY_PERIOD:
+ JBUF_LOCK (priv);
+ priv->rtx_retry_period = g_value_get_int (value);
+ JBUF_UNLOCK (priv);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
g_value_set_int (value, priv->rtx_delay_reorder);
JBUF_UNLOCK (priv);
break;
+ case PROP_RTX_RETRY_TIMEOUT:
+ JBUF_LOCK (priv);
+ g_value_set_int (value, priv->rtx_retry_timeout);
+ JBUF_UNLOCK (priv);
+ break;
+ case PROP_RTX_RETRY_PERIOD:
+ JBUF_LOCK (priv);
+ g_value_set_int (value, priv->rtx_retry_period);
+ JBUF_UNLOCK (priv);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;