mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 01:30:38 +00:00
jitterbuffer: add support for retransmission retry
When we didn't receive a packet after requesting retransmission, retry asking for retransmission for a certain period.
This commit is contained in:
parent
e9ad5126db
commit
9a13267e85
1 changed files with 86 additions and 4 deletions
|
@ -92,6 +92,8 @@ enum
|
||||||
#define DEFAULT_DO_RETRANSMISSION FALSE
|
#define DEFAULT_DO_RETRANSMISSION FALSE
|
||||||
#define DEFAULT_RTX_DELAY 20
|
#define DEFAULT_RTX_DELAY 20
|
||||||
#define DEFAULT_RTX_DELAY_REORDER 3
|
#define DEFAULT_RTX_DELAY_REORDER 3
|
||||||
|
#define DEFAULT_RTX_RETRY_TIMEOUT 40
|
||||||
|
#define DEFAULT_RTX_RETRY_PERIOD 200
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -105,6 +107,8 @@ enum
|
||||||
PROP_DO_RETRANSMISSION,
|
PROP_DO_RETRANSMISSION,
|
||||||
PROP_RTX_DELAY,
|
PROP_RTX_DELAY,
|
||||||
PROP_RTX_DELAY_REORDER,
|
PROP_RTX_DELAY_REORDER,
|
||||||
|
PROP_RTX_RETRY_TIMEOUT,
|
||||||
|
PROP_RTX_RETRY_PERIOD,
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -150,6 +154,8 @@ struct _GstRtpJitterBufferPrivate
|
||||||
gboolean do_retransmission;
|
gboolean do_retransmission;
|
||||||
gint rtx_delay;
|
gint rtx_delay;
|
||||||
gint rtx_delay_reorder;
|
gint rtx_delay_reorder;
|
||||||
|
gint rtx_retry_timeout;
|
||||||
|
gint rtx_retry_period;
|
||||||
|
|
||||||
/* the last seqnum we pushed out */
|
/* the last seqnum we pushed out */
|
||||||
guint32 last_popped_seqnum;
|
guint32 last_popped_seqnum;
|
||||||
|
@ -220,6 +226,8 @@ typedef struct
|
||||||
guint16 seqnum;
|
guint16 seqnum;
|
||||||
TimerType type;
|
TimerType type;
|
||||||
GstClockTime timeout;
|
GstClockTime timeout;
|
||||||
|
GstClockTime rtx_base;
|
||||||
|
GstClockTime rtx_retry;
|
||||||
} TimerData;
|
} TimerData;
|
||||||
|
|
||||||
#define GST_RTP_JITTER_BUFFER_GET_PRIVATE(o) \
|
#define GST_RTP_JITTER_BUFFER_GET_PRIVATE(o) \
|
||||||
|
@ -438,6 +446,37 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass)
|
||||||
"Sending retransmission event when this much reordering (-1 automatic)",
|
"Sending retransmission event when this much reordering (-1 automatic)",
|
||||||
-1, G_MAXUINT, DEFAULT_RTX_DELAY_REORDER,
|
-1, G_MAXUINT, DEFAULT_RTX_DELAY_REORDER,
|
||||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
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:
|
* GstRtpJitterBuffer::request-pt-map:
|
||||||
|
@ -552,6 +591,8 @@ gst_rtp_jitter_buffer_init (GstRtpJitterBuffer * jitterbuffer)
|
||||||
priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
|
priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
|
||||||
priv->rtx_delay = DEFAULT_RTX_DELAY;
|
priv->rtx_delay = DEFAULT_RTX_DELAY;
|
||||||
priv->rtx_delay_reorder = DEFAULT_RTX_DELAY_REORDER;
|
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->timers = g_array_new (FALSE, TRUE, sizeof (TimerData));
|
||||||
priv->jbuf = rtp_jitter_buffer_new ();
|
priv->jbuf = rtp_jitter_buffer_new ();
|
||||||
|
@ -1556,7 +1597,8 @@ update_timers (GstRtpJitterBuffer * jitterbuffer, guint16 seqnum,
|
||||||
} else if (gap > priv->rtx_delay_reorder) {
|
} else if (gap > priv->rtx_delay_reorder) {
|
||||||
/* max gap, we exceeded the max reorder distance and we don't expect the
|
/* max gap, we exceeded the max reorder distance and we don't expect the
|
||||||
* missing packet to be this reordered */
|
* 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1571,6 +1613,9 @@ update_timers (GstRtpJitterBuffer * jitterbuffer, guint16 seqnum,
|
||||||
else
|
else
|
||||||
timer = add_timer (jitterbuffer, TIMER_TYPE_EXPECTED,
|
timer = add_timer (jitterbuffer, TIMER_TYPE_EXPECTED,
|
||||||
priv->next_in_seqnum, expected);
|
priv->next_in_seqnum, expected);
|
||||||
|
|
||||||
|
timer->rtx_base = timer->timeout;
|
||||||
|
timer->rtx_retry = 0;
|
||||||
} else if (timer) {
|
} else if (timer) {
|
||||||
/* if we had a timer, remove it, we don't know when to expect the next
|
/* if we had a timer, remove it, we don't know when to expect the next
|
||||||
* packet. */
|
* packet. */
|
||||||
|
@ -2103,6 +2148,25 @@ wait:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
/* a packet is lost */
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
do_lost_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
do_lost_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
||||||
|
@ -2298,9 +2362,7 @@ wait_next_timeout (GstRtpJitterBuffer * jitterbuffer)
|
||||||
do_timeout:
|
do_timeout:
|
||||||
switch (timer->type) {
|
switch (timer->type) {
|
||||||
case TIMER_TYPE_EXPECTED:
|
case TIMER_TYPE_EXPECTED:
|
||||||
GST_DEBUG_OBJECT (jitterbuffer, "expected %d didn't arrive",
|
result = do_expected_timeout (jitterbuffer, timer, clock_jitter);
|
||||||
timer->seqnum);
|
|
||||||
remove_timer (jitterbuffer, timer);
|
|
||||||
break;
|
break;
|
||||||
case TIMER_TYPE_LOST:
|
case TIMER_TYPE_LOST:
|
||||||
result = do_lost_timeout (jitterbuffer, timer, clock_jitter);
|
result = do_lost_timeout (jitterbuffer, timer, clock_jitter);
|
||||||
|
@ -2740,6 +2802,16 @@ gst_rtp_jitter_buffer_set_property (GObject * object,
|
||||||
priv->rtx_delay_reorder = g_value_get_int (value);
|
priv->rtx_delay_reorder = g_value_get_int (value);
|
||||||
JBUF_UNLOCK (priv);
|
JBUF_UNLOCK (priv);
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -2811,6 +2883,16 @@ gst_rtp_jitter_buffer_get_property (GObject * object,
|
||||||
g_value_set_int (value, priv->rtx_delay_reorder);
|
g_value_set_int (value, priv->rtx_delay_reorder);
|
||||||
JBUF_UNLOCK (priv);
|
JBUF_UNLOCK (priv);
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue