jitterbuffer: install timer for expected arrival
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 1 Aug 2013 13:05:35 +0000 (15:05 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 1 Aug 2013 13:11:13 +0000 (15:11 +0200)
Install a timer that is triggered when the expected arrival time of a packet
expired.

gst/rtpmanager/gstrtpjitterbuffer.c

index 4fccf59..e1f8580 100644 (file)
@@ -1380,6 +1380,9 @@ remove_timer (GstRtpJitterBuffer * jitterbuffer, TimerData * timer)
   GstRtpJitterBufferPrivate *priv = jitterbuffer->priv;
   guint idx;
 
+  if (timer == NULL)
+    return;
+
   idx = timer->idx;
   GST_DEBUG_OBJECT (jitterbuffer, "removed index %d", idx);
   g_array_remove_index_fast (priv->timers, idx);
@@ -1410,6 +1413,7 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent,
   gint percent = -1;
   guint8 pt;
   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
+  TimerData *timer;
 
   jitterbuffer = GST_RTP_JITTER_BUFFER (parent);
 
@@ -1529,6 +1533,23 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstObject * parent,
   }
   priv->next_in_seqnum = (seqnum + 1) & 0xffff;
 
+  /* find the timer for the current seqnum. */
+  timer = find_timer (jitterbuffer, TIMER_TYPE_EXPECTED, seqnum);
+  if (priv->packet_spacing > 0) {
+    GstClockTime expected;
+
+    /* calculate expected arrival time of the next seqnum */
+    expected = dts + priv->packet_spacing + 20 * GST_MSECOND;
+    /* and update/install timer for next seqnum */
+    if (timer)
+      reschedule_timer (jitterbuffer, timer, priv->next_in_seqnum, expected);
+    else
+      timer = add_timer (jitterbuffer, TIMER_TYPE_EXPECTED,
+          priv->next_in_seqnum, expected);
+  } else {
+    remove_timer (jitterbuffer, timer);
+  }
+
   /* let's check if this buffer is too late, we can only accept packets with
    * bigger seqnum than the one we last pushed. */
   if (G_LIKELY (priv->last_popped_seqnum != -1)) {
@@ -2050,13 +2071,22 @@ wait_next_timeout (GstRtpJitterBuffer * jitterbuffer)
         i, test->seqnum, GST_TIME_ARGS (test->timeout));
 
     test_timeout = test->timeout;
+    if (test_timeout == -1) {
+      timer = test;
+      timer_timeout = test_timeout;
+      break;
+    }
+
+    if (test->type != TIMER_TYPE_EXPECTED) {
+      /* add our latency and offset to get output times. */
+      test_timeout = apply_offset (jitterbuffer, test_timeout);
+      test_timeout += priv->latency_ns;
+    }
+
     /* find the smallest timeout */
-    if (timer == NULL || test_timeout == -1 || test_timeout < timer->timeout) {
+    if (timer == NULL || test_timeout < timer_timeout) {
       timer = test;
       timer_timeout = test_timeout;
-      /* no timeout set, we can stop searching */
-      if (test_timeout == -1)
-        break;
     }
   }
   if (timer) {
@@ -2084,10 +2114,6 @@ wait_next_timeout (GstRtpJitterBuffer * jitterbuffer)
     /* add latency of peer to get input time */
     sync_time += priv->peer_latency;
 
-    /* add our latency and offset to get output times. */
-    sync_time = apply_offset (jitterbuffer, sync_time);
-    sync_time += priv->latency_ns;
-
     GST_DEBUG_OBJECT (jitterbuffer, "sync to timestamp %" GST_TIME_FORMAT
         " with sync time %" GST_TIME_FORMAT,
         GST_TIME_ARGS (timer_timeout), GST_TIME_ARGS (sync_time));
@@ -2131,6 +2157,8 @@ wait_next_timeout (GstRtpJitterBuffer * jitterbuffer)
   do_timeout:
     switch (timer->type) {
       case TIMER_TYPE_EXPECTED:
+        GST_DEBUG_OBJECT (jitterbuffer, "expected %d didn't arrive",
+            timer->seqnum);
         remove_timer (jitterbuffer, timer);
         break;
       case TIMER_TYPE_LOST: