jitterbuffer: simplify the timeout code
Keep track of the current time in the timeout loop. Loop over all timers and trigger all the expired ones, we can do this in the same loop that selects the new best timer.
This commit is contained in:
parent
fa1ef3328b
commit
047021c443
@ -216,7 +216,6 @@ struct _GstRtpJitterBufferPrivate
|
|||||||
GstClockID clock_id;
|
GstClockID clock_id;
|
||||||
GstClockTime timer_timeout;
|
GstClockTime timer_timeout;
|
||||||
guint16 timer_seqnum;
|
guint16 timer_seqnum;
|
||||||
gboolean unscheduled;
|
|
||||||
/* the latency of the upstream peer, we have to take this into account when
|
/* the latency of the upstream peer, we have to take this into account when
|
||||||
* synchronizing the buffers. */
|
* synchronizing the buffers. */
|
||||||
GstClockTime peer_latency;
|
GstClockTime peer_latency;
|
||||||
@ -1448,7 +1447,6 @@ unschedule_current_timer (GstRtpJitterBuffer * jitterbuffer)
|
|||||||
if (priv->clock_id) {
|
if (priv->clock_id) {
|
||||||
GST_DEBUG_OBJECT (jitterbuffer, "unschedule current timer");
|
GST_DEBUG_OBJECT (jitterbuffer, "unschedule current timer");
|
||||||
gst_clock_id_unschedule (priv->clock_id);
|
gst_clock_id_unschedule (priv->clock_id);
|
||||||
priv->unscheduled = TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2224,7 +2222,7 @@ wait:
|
|||||||
/* the timeout for when we expected a packet expired */
|
/* the timeout for when we expected a packet expired */
|
||||||
static void
|
static void
|
||||||
do_expected_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
do_expected_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
||||||
GstClockTimeDiff clock_jitter)
|
GstClockTime now)
|
||||||
{
|
{
|
||||||
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
@ -2261,7 +2259,7 @@ do_expected_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
|||||||
/* a packet is lost */
|
/* a packet is lost */
|
||||||
static void
|
static void
|
||||||
do_lost_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
do_lost_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
||||||
GstClockTimeDiff clock_jitter)
|
GstClockTime now)
|
||||||
{
|
{
|
||||||
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
||||||
GstClockTime duration = GST_CLOCK_TIME_NONE;
|
GstClockTime duration = GST_CLOCK_TIME_NONE;
|
||||||
@ -2331,7 +2329,8 @@ do_lost_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_eos_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer)
|
do_eos_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
||||||
|
GstClockTime now)
|
||||||
{
|
{
|
||||||
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
||||||
|
|
||||||
@ -2342,7 +2341,7 @@ do_eos_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
do_deadline_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
do_deadline_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer,
|
||||||
GstClockTimeDiff clock_jitter)
|
GstClockTime now)
|
||||||
{
|
{
|
||||||
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
||||||
|
|
||||||
@ -2364,13 +2363,16 @@ static void
|
|||||||
wait_next_timeout (GstRtpJitterBuffer * jitterbuffer)
|
wait_next_timeout (GstRtpJitterBuffer * jitterbuffer)
|
||||||
{
|
{
|
||||||
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
|
||||||
|
GstClockTime now = 0;
|
||||||
|
|
||||||
JBUF_LOCK (priv);
|
JBUF_LOCK (priv);
|
||||||
while (priv->timer_running) {
|
while (priv->timer_running) {
|
||||||
TimerData *timer = NULL;
|
TimerData *timer = NULL;
|
||||||
GstClockTime timer_timeout = -1;
|
GstClockTime timer_timeout = -1;
|
||||||
gint i, len;
|
gint i, len;
|
||||||
gint timer_idx;
|
|
||||||
|
GST_DEBUG_OBJECT (jitterbuffer, "now %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (now));
|
||||||
|
|
||||||
len = priv->timers->len;
|
len = priv->timers->len;
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
@ -2380,12 +2382,34 @@ wait_next_timeout (GstRtpJitterBuffer * jitterbuffer)
|
|||||||
GST_DEBUG_OBJECT (jitterbuffer, "%d, %d, %d, %" GST_TIME_FORMAT,
|
GST_DEBUG_OBJECT (jitterbuffer, "%d, %d, %d, %" GST_TIME_FORMAT,
|
||||||
i, test->type, test->seqnum, GST_TIME_ARGS (test_timeout));
|
i, test->type, test->seqnum, GST_TIME_ARGS (test_timeout));
|
||||||
|
|
||||||
/* find the smallest timeout */
|
/* no timestamp, timeout immeditately */
|
||||||
if (timer == NULL || test_timeout == -1 || test_timeout < timer_timeout) {
|
if (test_timeout == -1 || test_timeout <= now) {
|
||||||
timer = test;
|
switch (test->type) {
|
||||||
timer_timeout = test_timeout;
|
case TIMER_TYPE_EXPECTED:
|
||||||
if (timer_timeout == -1)
|
do_expected_timeout (jitterbuffer, test, now);
|
||||||
break;
|
break;
|
||||||
|
case TIMER_TYPE_LOST:
|
||||||
|
do_lost_timeout (jitterbuffer, test, now);
|
||||||
|
i--;
|
||||||
|
len--;
|
||||||
|
break;
|
||||||
|
case TIMER_TYPE_DEADLINE:
|
||||||
|
do_deadline_timeout (jitterbuffer, test, now);
|
||||||
|
i--;
|
||||||
|
len--;
|
||||||
|
break;
|
||||||
|
case TIMER_TYPE_EOS:
|
||||||
|
do_eos_timeout (jitterbuffer, test, now);
|
||||||
|
i--;
|
||||||
|
len--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* find the smallest timeout */
|
||||||
|
if (timer == NULL || test_timeout < timer_timeout) {
|
||||||
|
timer = test;
|
||||||
|
timer_timeout = test_timeout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (timer) {
|
if (timer) {
|
||||||
@ -2395,17 +2419,14 @@ wait_next_timeout (GstRtpJitterBuffer * jitterbuffer)
|
|||||||
GstClockReturn ret;
|
GstClockReturn ret;
|
||||||
GstClockTimeDiff clock_jitter;
|
GstClockTimeDiff clock_jitter;
|
||||||
|
|
||||||
/* no timestamp, timeout immeditately */
|
|
||||||
if (timer_timeout == -1)
|
|
||||||
goto do_timeout;
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (jitterbuffer);
|
GST_OBJECT_LOCK (jitterbuffer);
|
||||||
clock = GST_ELEMENT_CLOCK (jitterbuffer);
|
clock = GST_ELEMENT_CLOCK (jitterbuffer);
|
||||||
if (!clock) {
|
if (!clock) {
|
||||||
GST_OBJECT_UNLOCK (jitterbuffer);
|
GST_OBJECT_UNLOCK (jitterbuffer);
|
||||||
/* let's just push if there is no clock */
|
/* let's just push if there is no clock */
|
||||||
GST_DEBUG_OBJECT (jitterbuffer, "No clock, timeout right away");
|
GST_DEBUG_OBJECT (jitterbuffer, "No clock, timeout right away");
|
||||||
goto do_timeout;
|
now = timer_timeout;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prepare for sync against clock */
|
/* prepare for sync against clock */
|
||||||
@ -2419,10 +2440,8 @@ wait_next_timeout (GstRtpJitterBuffer * jitterbuffer)
|
|||||||
|
|
||||||
/* create an entry for the clock */
|
/* create an entry for the clock */
|
||||||
id = priv->clock_id = gst_clock_new_single_shot_id (clock, sync_time);
|
id = priv->clock_id = gst_clock_new_single_shot_id (clock, sync_time);
|
||||||
priv->unscheduled = FALSE;
|
|
||||||
priv->timer_timeout = timer_timeout;
|
priv->timer_timeout = timer_timeout;
|
||||||
priv->timer_seqnum = timer->seqnum;
|
priv->timer_seqnum = timer->seqnum;
|
||||||
timer_idx = timer->idx;
|
|
||||||
GST_OBJECT_UNLOCK (jitterbuffer);
|
GST_OBJECT_UNLOCK (jitterbuffer);
|
||||||
|
|
||||||
/* release the lock so that the other end can push stuff or unlock */
|
/* release the lock so that the other end can push stuff or unlock */
|
||||||
@ -2440,38 +2459,7 @@ wait_next_timeout (GstRtpJitterBuffer * jitterbuffer)
|
|||||||
gst_clock_id_unref (id);
|
gst_clock_id_unref (id);
|
||||||
priv->clock_id = NULL;
|
priv->clock_id = NULL;
|
||||||
|
|
||||||
if (priv->timers->len <= timer_idx)
|
now = timer_timeout + MAX (clock_jitter, 0);
|
||||||
continue;
|
|
||||||
|
|
||||||
/* we released the lock, the array might have changed */
|
|
||||||
timer = &g_array_index (priv->timers, TimerData, timer_idx);
|
|
||||||
/* if changed to timeout immediately, do so */
|
|
||||||
if (timer->timeout == -1)
|
|
||||||
goto do_timeout;
|
|
||||||
|
|
||||||
/* if we got unscheduled and we are not flushing, it's because a new tail
|
|
||||||
* element became available in the queue or we flushed the queue.
|
|
||||||
* Grab it and try to push or sync. */
|
|
||||||
if (ret == GST_CLOCK_UNSCHEDULED || priv->unscheduled) {
|
|
||||||
GST_DEBUG_OBJECT (jitterbuffer, "Wait got unscheduled");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
do_timeout:
|
|
||||||
switch (timer->type) {
|
|
||||||
case TIMER_TYPE_EXPECTED:
|
|
||||||
do_expected_timeout (jitterbuffer, timer, clock_jitter);
|
|
||||||
break;
|
|
||||||
case TIMER_TYPE_LOST:
|
|
||||||
do_lost_timeout (jitterbuffer, timer, clock_jitter);
|
|
||||||
break;
|
|
||||||
case TIMER_TYPE_DEADLINE:
|
|
||||||
do_deadline_timeout (jitterbuffer, timer, clock_jitter);
|
|
||||||
break;
|
|
||||||
case TIMER_TYPE_EOS:
|
|
||||||
do_eos_timeout (jitterbuffer, timer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* no timers, wait for activity */
|
/* no timers, wait for activity */
|
||||||
GST_DEBUG_OBJECT (jitterbuffer, "waiting");
|
GST_DEBUG_OBJECT (jitterbuffer, "waiting");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user