From 047021c4439fc1f8d5035c8deced36028ed92f60 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 17 Sep 2013 23:03:45 +0200 Subject: [PATCH] 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. --- gst/rtpmanager/gstrtpjitterbuffer.c | 92 ++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 52 deletions(-) diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index f14bebd..fd7649f 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -216,7 +216,6 @@ struct _GstRtpJitterBufferPrivate GstClockID clock_id; GstClockTime timer_timeout; guint16 timer_seqnum; - gboolean unscheduled; /* the latency of the upstream peer, we have to take this into account when * synchronizing the buffers. */ GstClockTime peer_latency; @@ -1448,7 +1447,6 @@ unschedule_current_timer (GstRtpJitterBuffer * jitterbuffer) if (priv->clock_id) { GST_DEBUG_OBJECT (jitterbuffer, "unschedule current timer"); gst_clock_id_unschedule (priv->clock_id); - priv->unscheduled = TRUE; } } @@ -2224,7 +2222,7 @@ wait: /* the timeout for when we expected a packet expired */ static void do_expected_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer, - GstClockTimeDiff clock_jitter) + GstClockTime now) { GstRtpJitterBufferPrivate *priv = jitterbuffer->priv; GstEvent *event; @@ -2261,7 +2259,7 @@ do_expected_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer, /* a packet is lost */ static void do_lost_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer, - GstClockTimeDiff clock_jitter) + GstClockTime now) { GstRtpJitterBufferPrivate *priv = jitterbuffer->priv; GstClockTime duration = GST_CLOCK_TIME_NONE; @@ -2331,7 +2329,8 @@ do_lost_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer, } static void -do_eos_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer) +do_eos_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer, + GstClockTime now) { GstRtpJitterBufferPrivate *priv = jitterbuffer->priv; @@ -2342,7 +2341,7 @@ do_eos_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer) static void do_deadline_timeout (GstRtpJitterBuffer * jitterbuffer, TimerData * timer, - GstClockTimeDiff clock_jitter) + GstClockTime now) { GstRtpJitterBufferPrivate *priv = jitterbuffer->priv; @@ -2364,13 +2363,16 @@ static void wait_next_timeout (GstRtpJitterBuffer * jitterbuffer) { GstRtpJitterBufferPrivate *priv = jitterbuffer->priv; + GstClockTime now = 0; JBUF_LOCK (priv); while (priv->timer_running) { TimerData *timer = NULL; GstClockTime timer_timeout = -1; gint i, len; - gint timer_idx; + + GST_DEBUG_OBJECT (jitterbuffer, "now %" GST_TIME_FORMAT, + GST_TIME_ARGS (now)); len = priv->timers->len; 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, i, test->type, test->seqnum, GST_TIME_ARGS (test_timeout)); - /* find the smallest timeout */ - if (timer == NULL || test_timeout == -1 || test_timeout < timer_timeout) { - timer = test; - timer_timeout = test_timeout; - if (timer_timeout == -1) - break; + /* no timestamp, timeout immeditately */ + if (test_timeout == -1 || test_timeout <= now) { + switch (test->type) { + case TIMER_TYPE_EXPECTED: + do_expected_timeout (jitterbuffer, test, now); + 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) { @@ -2395,17 +2419,14 @@ wait_next_timeout (GstRtpJitterBuffer * jitterbuffer) GstClockReturn ret; GstClockTimeDiff clock_jitter; - /* no timestamp, timeout immeditately */ - if (timer_timeout == -1) - goto do_timeout; - GST_OBJECT_LOCK (jitterbuffer); clock = GST_ELEMENT_CLOCK (jitterbuffer); if (!clock) { GST_OBJECT_UNLOCK (jitterbuffer); /* let's just push if there is no clock */ GST_DEBUG_OBJECT (jitterbuffer, "No clock, timeout right away"); - goto do_timeout; + now = timer_timeout; + continue; } /* prepare for sync against clock */ @@ -2419,10 +2440,8 @@ wait_next_timeout (GstRtpJitterBuffer * jitterbuffer) /* create an entry for the clock */ id = priv->clock_id = gst_clock_new_single_shot_id (clock, sync_time); - priv->unscheduled = FALSE; priv->timer_timeout = timer_timeout; priv->timer_seqnum = timer->seqnum; - timer_idx = timer->idx; GST_OBJECT_UNLOCK (jitterbuffer); /* 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); priv->clock_id = NULL; - if (priv->timers->len <= timer_idx) - 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; - } + now = timer_timeout + MAX (clock_jitter, 0); } else { /* no timers, wait for activity */ GST_DEBUG_OBJECT (jitterbuffer, "waiting"); -- 2.7.4