jitterbuffer: add new timestamp mode
[platform/upstream/gst-plugins-good.git] / gst / rtpmanager / rtpjitterbuffer.c
1 /* GStreamer
2  * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 #include <string.h>
20 #include <stdlib.h>
21
22 #include <gst/rtp/gstrtpbuffer.h>
23 #include <gst/rtp/gstrtcpbuffer.h>
24
25 #include "rtpjitterbuffer.h"
26
27 GST_DEBUG_CATEGORY_STATIC (rtp_jitter_buffer_debug);
28 #define GST_CAT_DEFAULT rtp_jitter_buffer_debug
29
30 #define MAX_WINDOW      RTP_JITTER_BUFFER_MAX_WINDOW
31 #define MAX_TIME        (2 * GST_SECOND)
32
33 /* signals and args */
34 enum
35 {
36   LAST_SIGNAL
37 };
38
39 enum
40 {
41   PROP_0
42 };
43
44 /* GObject vmethods */
45 static void rtp_jitter_buffer_finalize (GObject * object);
46
47 GType
48 rtp_jitter_buffer_mode_get_type (void)
49 {
50   static GType jitter_buffer_mode_type = 0;
51   static const GEnumValue jitter_buffer_modes[] = {
52     {RTP_JITTER_BUFFER_MODE_NONE, "Only use RTP timestamps", "none"},
53     {RTP_JITTER_BUFFER_MODE_SLAVE, "Slave receiver to sender clock", "slave"},
54     {RTP_JITTER_BUFFER_MODE_BUFFER, "Do low/high watermark buffering",
55         "buffer"},
56     {RTP_JITTER_BUFFER_MODE_SYNCED, "Synchronized sender and receiver clocks",
57         "synced"},
58     {0, NULL, NULL},
59   };
60
61   if (!jitter_buffer_mode_type) {
62     jitter_buffer_mode_type =
63         g_enum_register_static ("RTPJitterBufferMode", jitter_buffer_modes);
64   }
65   return jitter_buffer_mode_type;
66 }
67
68 /* static guint rtp_jitter_buffer_signals[LAST_SIGNAL] = { 0 }; */
69
70 G_DEFINE_TYPE (RTPJitterBuffer, rtp_jitter_buffer, G_TYPE_OBJECT);
71
72 static void
73 rtp_jitter_buffer_class_init (RTPJitterBufferClass * klass)
74 {
75   GObjectClass *gobject_class;
76
77   gobject_class = (GObjectClass *) klass;
78
79   gobject_class->finalize = rtp_jitter_buffer_finalize;
80
81   GST_DEBUG_CATEGORY_INIT (rtp_jitter_buffer_debug, "rtpjitterbuffer", 0,
82       "RTP Jitter Buffer");
83 }
84
85 static void
86 rtp_jitter_buffer_init (RTPJitterBuffer * jbuf)
87 {
88   jbuf->packets = g_queue_new ();
89   jbuf->mode = RTP_JITTER_BUFFER_MODE_SLAVE;
90
91   rtp_jitter_buffer_reset_skew (jbuf);
92 }
93
94 static void
95 rtp_jitter_buffer_finalize (GObject * object)
96 {
97   RTPJitterBuffer *jbuf;
98
99   jbuf = RTP_JITTER_BUFFER_CAST (object);
100
101   g_queue_free (jbuf->packets);
102
103   G_OBJECT_CLASS (rtp_jitter_buffer_parent_class)->finalize (object);
104 }
105
106 /**
107  * rtp_jitter_buffer_new:
108  *
109  * Create an #RTPJitterBuffer.
110  *
111  * Returns: a new #RTPJitterBuffer. Use g_object_unref() after usage.
112  */
113 RTPJitterBuffer *
114 rtp_jitter_buffer_new (void)
115 {
116   RTPJitterBuffer *jbuf;
117
118   jbuf = g_object_new (RTP_TYPE_JITTER_BUFFER, NULL);
119
120   return jbuf;
121 }
122
123 /**
124  * rtp_jitter_buffer_get_mode:
125  * @jbuf: an #RTPJitterBuffer
126  *
127  * Get the current jitterbuffer mode.
128  *
129  * Returns: the current jitterbuffer mode.
130  */
131 RTPJitterBufferMode
132 rtp_jitter_buffer_get_mode (RTPJitterBuffer * jbuf)
133 {
134   return jbuf->mode;
135 }
136
137 /**
138  * rtp_jitter_buffer_set_mode:
139  * @jbuf: an #RTPJitterBuffer
140  * @mode: a #RTPJitterBufferMode
141  *
142  * Set the buffering and clock slaving algorithm used in the @jbuf.
143  */
144 void
145 rtp_jitter_buffer_set_mode (RTPJitterBuffer * jbuf, RTPJitterBufferMode mode)
146 {
147   jbuf->mode = mode;
148 }
149
150 GstClockTime
151 rtp_jitter_buffer_get_delay (RTPJitterBuffer * jbuf)
152 {
153   return jbuf->delay;
154 }
155
156 void
157 rtp_jitter_buffer_set_delay (RTPJitterBuffer * jbuf, GstClockTime delay)
158 {
159   jbuf->delay = delay;
160   jbuf->low_level = (delay * 15) / 100;
161   /* the high level is at 90% in order to release packets before we fill up the
162    * buffer up to the latency */
163   jbuf->high_level = (delay * 90) / 100;
164
165   GST_DEBUG ("delay %" GST_TIME_FORMAT ", min %" GST_TIME_FORMAT ", max %"
166       GST_TIME_FORMAT, GST_TIME_ARGS (jbuf->delay),
167       GST_TIME_ARGS (jbuf->low_level), GST_TIME_ARGS (jbuf->high_level));
168 }
169
170 /**
171  * rtp_jitter_buffer_set_clock_rate:
172  * @jbuf: an #RTPJitterBuffer
173  *
174  * Set the clock rate in the jitterbuffer.
175  */
176 void
177 rtp_jitter_buffer_set_clock_rate (RTPJitterBuffer * jbuf, guint32 clock_rate)
178 {
179   if (jbuf->clock_rate != clock_rate) {
180     if (jbuf->clock_rate == -1) {
181       GST_DEBUG ("Clock rate changed from %" G_GUINT32_FORMAT " to %"
182           G_GUINT32_FORMAT, jbuf->clock_rate, clock_rate);
183     } else {
184       GST_WARNING ("Clock rate changed from %" G_GUINT32_FORMAT " to %"
185           G_GUINT32_FORMAT, jbuf->clock_rate, clock_rate);
186     }
187     jbuf->clock_rate = clock_rate;
188     rtp_jitter_buffer_reset_skew (jbuf);
189   }
190 }
191
192 /**
193  * rtp_jitter_buffer_get_clock_rate:
194  * @jbuf: an #RTPJitterBuffer
195  *
196  * Get the currently configure clock rate in @jbuf.
197  *
198  * Returns: the current clock-rate
199  */
200 guint32
201 rtp_jitter_buffer_get_clock_rate (RTPJitterBuffer * jbuf)
202 {
203   return jbuf->clock_rate;
204 }
205
206 /**
207  * rtp_jitter_buffer_reset_skew:
208  * @jbuf: an #RTPJitterBuffer
209  *
210  * Reset the skew calculations in @jbuf.
211  */
212 void
213 rtp_jitter_buffer_reset_skew (RTPJitterBuffer * jbuf)
214 {
215   jbuf->base_time = -1;
216   jbuf->base_rtptime = -1;
217   jbuf->base_extrtp = -1;
218   jbuf->ext_rtptime = -1;
219   jbuf->last_rtptime = -1;
220   jbuf->window_pos = 0;
221   jbuf->window_filling = TRUE;
222   jbuf->window_min = 0;
223   jbuf->skew = 0;
224   jbuf->prev_send_diff = -1;
225   jbuf->prev_out_time = -1;
226   GST_DEBUG ("reset skew correction");
227 }
228
229 static void
230 rtp_jitter_buffer_resync (RTPJitterBuffer * jbuf, GstClockTime time,
231     GstClockTime gstrtptime, guint64 ext_rtptime, gboolean reset_skew)
232 {
233   jbuf->base_time = time;
234   jbuf->base_rtptime = gstrtptime;
235   jbuf->base_extrtp = ext_rtptime;
236   jbuf->prev_out_time = -1;
237   jbuf->prev_send_diff = -1;
238   if (reset_skew) {
239     jbuf->window_filling = TRUE;
240     jbuf->window_pos = 0;
241     jbuf->window_min = 0;
242     jbuf->window_size = 0;
243     jbuf->skew = 0;
244   }
245 }
246
247 static guint64
248 get_buffer_level (RTPJitterBuffer * jbuf)
249 {
250   RTPJitterBufferItem *high_buf = NULL, *low_buf = NULL;
251   guint64 level;
252
253   /* first first buffer with timestamp */
254   high_buf = (RTPJitterBufferItem *) g_queue_peek_head_link (jbuf->packets);
255   while (high_buf) {
256     if (high_buf->dts != -1)
257       break;
258
259     high_buf = (RTPJitterBufferItem *) g_list_next (high_buf);
260   }
261
262   low_buf = (RTPJitterBufferItem *) g_queue_peek_tail_link (jbuf->packets);
263   while (low_buf) {
264     if (low_buf->dts != -1)
265       break;
266
267     low_buf = (RTPJitterBufferItem *) g_list_previous (low_buf);
268   }
269
270   if (!high_buf || !low_buf || high_buf == low_buf) {
271     level = 0;
272   } else {
273     guint64 high_ts, low_ts;
274
275     high_ts = high_buf->dts;
276     low_ts = low_buf->dts;
277
278     if (high_ts > low_ts)
279       level = high_ts - low_ts;
280     else
281       level = 0;
282
283     GST_LOG_OBJECT (jbuf,
284         "low %" GST_TIME_FORMAT " high %" GST_TIME_FORMAT " level %"
285         G_GUINT64_FORMAT, GST_TIME_ARGS (low_ts), GST_TIME_ARGS (high_ts),
286         level);
287   }
288   return level;
289 }
290
291 static void
292 update_buffer_level (RTPJitterBuffer * jbuf, gint * percent)
293 {
294   gboolean post = FALSE;
295   guint64 level;
296
297   level = get_buffer_level (jbuf);
298   GST_DEBUG ("buffer level %" GST_TIME_FORMAT, GST_TIME_ARGS (level));
299
300   if (jbuf->buffering) {
301     post = TRUE;
302     if (level > jbuf->high_level) {
303       GST_DEBUG ("buffering finished");
304       jbuf->buffering = FALSE;
305     }
306   } else {
307     if (level < jbuf->low_level) {
308       GST_DEBUG ("buffering started");
309       jbuf->buffering = TRUE;
310       post = TRUE;
311     }
312   }
313   if (post) {
314     gint perc;
315
316     if (jbuf->buffering && (jbuf->high_level != 0)) {
317       perc = (level * 100 / jbuf->high_level);
318       perc = MIN (perc, 100);
319     } else {
320       perc = 100;
321     }
322
323     if (percent)
324       *percent = perc;
325
326     GST_DEBUG ("buffering %d", perc);
327   }
328 }
329
330 /* For the clock skew we use a windowed low point averaging algorithm as can be
331  * found in Fober, Orlarey and Letz, 2005, "Real Time Clock Skew Estimation
332  * over Network Delays":
333  * http://www.grame.fr/Ressources/pub/TR-050601.pdf
334  * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.102.1546
335  *
336  * The idea is that the jitter is composed of:
337  *
338  *  J = N + n
339  *
340  *   N   : a constant network delay.
341  *   n   : random added noise. The noise is concentrated around 0
342  *
343  * In the receiver we can track the elapsed time at the sender with:
344  *
345  *  send_diff(i) = (Tsi - Ts0);
346  *
347  *   Tsi : The time at the sender at packet i
348  *   Ts0 : The time at the sender at the first packet
349  *
350  * This is the difference between the RTP timestamp in the first received packet
351  * and the current packet.
352  *
353  * At the receiver we have to deal with the jitter introduced by the network.
354  *
355  *  recv_diff(i) = (Tri - Tr0)
356  *
357  *   Tri : The time at the receiver at packet i
358  *   Tr0 : The time at the receiver at the first packet
359  *
360  * Both of these values contain a jitter Ji, a jitter for packet i, so we can
361  * write:
362  *
363  *  recv_diff(i) = (Cri + D + ni) - (Cr0 + D + n0))
364  *
365  *    Cri    : The time of the clock at the receiver for packet i
366  *    D + ni : The jitter when receiving packet i
367  *
368  * We see that the network delay is irrelevant here as we can elliminate D:
369  *
370  *  recv_diff(i) = (Cri + ni) - (Cr0 + n0))
371  *
372  * The drift is now expressed as:
373  *
374  *  Drift(i) = recv_diff(i) - send_diff(i);
375  *
376  * We now keep the W latest values of Drift and find the minimum (this is the
377  * one with the lowest network jitter and thus the one which is least affected
378  * by it). We average this lowest value to smooth out the resulting network skew.
379  *
380  * Both the window and the weighting used for averaging influence the accuracy
381  * of the drift estimation. Finding the correct parameters turns out to be a
382  * compromise between accuracy and inertia.
383  *
384  * We use a 2 second window or up to 512 data points, which is statistically big
385  * enough to catch spikes (FIXME, detect spikes).
386  * We also use a rather large weighting factor (125) to smoothly adapt. During
387  * startup, when filling the window, we use a parabolic weighting factor, the
388  * more the window is filled, the faster we move to the detected possible skew.
389  *
390  * Returns: @time adjusted with the clock skew.
391  */
392 static GstClockTime
393 calculate_skew (RTPJitterBuffer * jbuf, guint32 rtptime, GstClockTime time)
394 {
395   guint64 ext_rtptime;
396   guint64 send_diff, recv_diff;
397   gint64 delta;
398   gint64 old;
399   gint pos, i;
400   GstClockTime gstrtptime, out_time;
401   guint64 slope;
402
403   ext_rtptime = gst_rtp_buffer_ext_timestamp (&jbuf->ext_rtptime, rtptime);
404
405   if (jbuf->last_rtptime != -1 && ext_rtptime == jbuf->last_rtptime)
406     return jbuf->prev_out_time;
407
408   gstrtptime =
409       gst_util_uint64_scale_int (ext_rtptime, GST_SECOND, jbuf->clock_rate);
410
411   /* keep track of the last extended rtptime */
412   jbuf->last_rtptime = ext_rtptime;
413
414   /* first time, lock on to time and gstrtptime */
415   if (G_UNLIKELY (jbuf->base_time == -1)) {
416     jbuf->base_time = time;
417     jbuf->prev_out_time = -1;
418     GST_DEBUG ("Taking new base time %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
419   }
420   if (G_UNLIKELY (jbuf->base_rtptime == -1)) {
421     jbuf->base_rtptime = gstrtptime;
422     jbuf->base_extrtp = ext_rtptime;
423     jbuf->prev_send_diff = -1;
424     GST_DEBUG ("Taking new base rtptime %" GST_TIME_FORMAT,
425         GST_TIME_ARGS (gstrtptime));
426   }
427
428   if (G_LIKELY (gstrtptime >= jbuf->base_rtptime))
429     send_diff = gstrtptime - jbuf->base_rtptime;
430   else if (time != -1) {
431     /* elapsed time at sender, timestamps can go backwards and thus be smaller
432      * than our base time, take a new base time in that case. */
433     GST_WARNING ("backward timestamps at server, taking new base time");
434     rtp_jitter_buffer_resync (jbuf, time, gstrtptime, ext_rtptime, FALSE);
435     send_diff = 0;
436   } else {
437     GST_WARNING ("backward timestamps at server but no timestamps");
438     send_diff = 0;
439     /* at least try to get a new timestamp.. */
440     jbuf->base_time = -1;
441   }
442
443   GST_DEBUG ("extrtp %" G_GUINT64_FORMAT ", gstrtp %" GST_TIME_FORMAT ", base %"
444       GST_TIME_FORMAT ", send_diff %" GST_TIME_FORMAT, ext_rtptime,
445       GST_TIME_ARGS (gstrtptime), GST_TIME_ARGS (jbuf->base_rtptime),
446       GST_TIME_ARGS (send_diff));
447
448   /* we don't have an arrival timestamp so we can't do skew detection. we
449    * should still apply a timestamp based on RTP timestamp and base_time */
450   if (time == -1 || jbuf->base_time == -1)
451     goto no_skew;
452
453   /* elapsed time at receiver, includes the jitter */
454   recv_diff = time - jbuf->base_time;
455
456   /* measure the diff */
457   delta = ((gint64) recv_diff) - ((gint64) send_diff);
458
459   /* measure the slope, this gives a rought estimate between the sender speed
460    * and the receiver speed. This should be approximately 8, higher values
461    * indicate a burst (especially when the connection starts) */
462   if (recv_diff > 0)
463     slope = (send_diff * 8) / recv_diff;
464   else
465     slope = 8;
466
467   GST_DEBUG ("time %" GST_TIME_FORMAT ", base %" GST_TIME_FORMAT ", recv_diff %"
468       GST_TIME_FORMAT ", slope %" G_GUINT64_FORMAT, GST_TIME_ARGS (time),
469       GST_TIME_ARGS (jbuf->base_time), GST_TIME_ARGS (recv_diff), slope);
470
471   /* if the difference between the sender timeline and the receiver timeline
472    * changed too quickly we have to resync because the server likely restarted
473    * its timestamps. */
474   if (ABS (delta - jbuf->skew) > GST_SECOND) {
475     GST_WARNING ("delta - skew: %" GST_TIME_FORMAT " too big, reset skew",
476         GST_TIME_ARGS (ABS (delta - jbuf->skew)));
477     rtp_jitter_buffer_resync (jbuf, time, gstrtptime, ext_rtptime, TRUE);
478     send_diff = 0;
479     delta = 0;
480   }
481
482   pos = jbuf->window_pos;
483
484   if (G_UNLIKELY (jbuf->window_filling)) {
485     /* we are filling the window */
486     GST_DEBUG ("filling %d, delta %" G_GINT64_FORMAT, pos, delta);
487     jbuf->window[pos++] = delta;
488     /* calc the min delta we observed */
489     if (G_UNLIKELY (pos == 1 || delta < jbuf->window_min))
490       jbuf->window_min = delta;
491
492     if (G_UNLIKELY (send_diff >= MAX_TIME || pos >= MAX_WINDOW)) {
493       jbuf->window_size = pos;
494
495       /* window filled */
496       GST_DEBUG ("min %" G_GINT64_FORMAT, jbuf->window_min);
497
498       /* the skew is now the min */
499       jbuf->skew = jbuf->window_min;
500       jbuf->window_filling = FALSE;
501     } else {
502       gint perc_time, perc_window, perc;
503
504       /* figure out how much we filled the window, this depends on the amount of
505        * time we have or the max number of points we keep. */
506       perc_time = send_diff * 100 / MAX_TIME;
507       perc_window = pos * 100 / MAX_WINDOW;
508       perc = MAX (perc_time, perc_window);
509
510       /* make a parabolic function, the closer we get to the MAX, the more value
511        * we give to the scaling factor of the new value */
512       perc = perc * perc;
513
514       /* quickly go to the min value when we are filling up, slowly when we are
515        * just starting because we're not sure it's a good value yet. */
516       jbuf->skew =
517           (perc * jbuf->window_min + ((10000 - perc) * jbuf->skew)) / 10000;
518       jbuf->window_size = pos + 1;
519     }
520   } else {
521     /* pick old value and store new value. We keep the previous value in order
522      * to quickly check if the min of the window changed */
523     old = jbuf->window[pos];
524     jbuf->window[pos++] = delta;
525
526     if (G_UNLIKELY (delta <= jbuf->window_min)) {
527       /* if the new value we inserted is smaller or equal to the current min,
528        * it becomes the new min */
529       jbuf->window_min = delta;
530     } else if (G_UNLIKELY (old == jbuf->window_min)) {
531       gint64 min = G_MAXINT64;
532
533       /* if we removed the old min, we have to find a new min */
534       for (i = 0; i < jbuf->window_size; i++) {
535         /* we found another value equal to the old min, we can stop searching now */
536         if (jbuf->window[i] == old) {
537           min = old;
538           break;
539         }
540         if (jbuf->window[i] < min)
541           min = jbuf->window[i];
542       }
543       jbuf->window_min = min;
544     }
545     /* average the min values */
546     jbuf->skew = (jbuf->window_min + (124 * jbuf->skew)) / 125;
547     GST_DEBUG ("delta %" G_GINT64_FORMAT ", new min: %" G_GINT64_FORMAT,
548         delta, jbuf->window_min);
549   }
550   /* wrap around in the window */
551   if (G_UNLIKELY (pos >= jbuf->window_size))
552     pos = 0;
553   jbuf->window_pos = pos;
554
555 no_skew:
556   /* the output time is defined as the base timestamp plus the RTP time
557    * adjusted for the clock skew .*/
558   if (jbuf->base_time != -1) {
559     out_time = jbuf->base_time + send_diff;
560     /* skew can be negative and we don't want to make invalid timestamps */
561     if (jbuf->skew < 0 && out_time < -jbuf->skew) {
562       out_time = 0;
563     } else {
564       out_time += jbuf->skew;
565     }
566     /* check if timestamps are not going backwards, we can only check this if we
567      * have a previous out time and a previous send_diff */
568     if (G_LIKELY (jbuf->prev_out_time != -1 && jbuf->prev_send_diff != -1)) {
569       /* now check for backwards timestamps */
570       if (G_UNLIKELY (
571               /* if the server timestamps went up and the out_time backwards */
572               (send_diff > jbuf->prev_send_diff
573                   && out_time < jbuf->prev_out_time) ||
574               /* if the server timestamps went backwards and the out_time forwards */
575               (send_diff < jbuf->prev_send_diff
576                   && out_time > jbuf->prev_out_time) ||
577               /* if the server timestamps did not change */
578               send_diff == jbuf->prev_send_diff)) {
579         GST_DEBUG ("backwards timestamps, using previous time");
580         out_time = jbuf->prev_out_time;
581       }
582     }
583     if (time != -1 && out_time + jbuf->delay < time) {
584       /* if we are going to produce a timestamp that is later than the input
585        * timestamp, we need to reset the jitterbuffer. Likely the server paused
586        * temporarily */
587       GST_DEBUG ("out %" GST_TIME_FORMAT " + %" G_GUINT64_FORMAT " < time %"
588           GST_TIME_FORMAT ", reset jitterbuffer", GST_TIME_ARGS (out_time),
589           jbuf->delay, GST_TIME_ARGS (time));
590       rtp_jitter_buffer_resync (jbuf, time, gstrtptime, ext_rtptime, TRUE);
591       out_time = time;
592       send_diff = 0;
593     }
594   } else
595     out_time = -1;
596
597   jbuf->prev_out_time = out_time;
598   jbuf->prev_send_diff = send_diff;
599
600   GST_DEBUG ("skew %" G_GINT64_FORMAT ", out %" GST_TIME_FORMAT,
601       jbuf->skew, GST_TIME_ARGS (out_time));
602
603   return out_time;
604 }
605
606 static void
607 queue_do_insert (RTPJitterBuffer * jbuf, GList * list, GList * item)
608 {
609   GQueue *queue = jbuf->packets;
610
611   /* It's more likely that the packet was inserted in the front of the buffer */
612   if (G_LIKELY (list)) {
613     item->prev = list->prev;
614     item->next = list;
615     list->prev = item;
616     if (item->prev) {
617       item->prev->next = item;
618     } else {
619       queue->head = item;
620     }
621   } else {
622     queue->tail = g_list_concat (queue->tail, item);
623     if (queue->tail->next)
624       queue->tail = queue->tail->next;
625     else
626       queue->head = queue->tail;
627   }
628   queue->length++;
629 }
630
631 /**
632  * rtp_jitter_buffer_insert:
633  * @jbuf: an #RTPJitterBuffer
634  * @item: an #RTPJitterBufferItem to insert
635  * @tail: TRUE when the tail element changed.
636  * @percent: the buffering percent after insertion
637  *
638  * Inserts @item into the packet queue of @jbuf. The sequence number of the
639  * packet will be used to sort the packets. This function takes ownerhip of
640  * @buf when the function returns %TRUE.
641  *
642  * Returns: %FALSE if a packet with the same number already existed.
643  */
644 gboolean
645 rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, RTPJitterBufferItem * item,
646     gboolean * tail, gint * percent)
647 {
648   GList *list = NULL;
649   guint32 rtptime;
650   guint16 seqnum;
651   GstClockTime dts;
652
653   g_return_val_if_fail (jbuf != NULL, FALSE);
654   g_return_val_if_fail (item != NULL, FALSE);
655
656   seqnum = item->seqnum;
657   /* no seqnum, simply append then */
658   if (seqnum == -1)
659     goto append;
660
661   /* loop the list to skip strictly smaller seqnum buffers */
662   for (list = jbuf->packets->head; list; list = g_list_next (list)) {
663     guint16 qseq;
664     gint gap;
665     RTPJitterBufferItem *qitem = (RTPJitterBufferItem *) list;
666
667     qseq = qitem->seqnum;
668     if (qseq == -1)
669       continue;
670
671     /* compare the new seqnum to the one in the buffer */
672     gap = gst_rtp_buffer_compare_seqnum (seqnum, qseq);
673
674     /* we hit a packet with the same seqnum, notify a duplicate */
675     if (G_UNLIKELY (gap == 0))
676       goto duplicate;
677
678     /* seqnum > qseq, we can stop looking */
679     if (G_LIKELY (gap < 0))
680       break;
681   }
682
683   dts = item->dts;
684   rtptime = item->rtptime;
685
686   if (rtptime == -1)
687     goto append;
688
689   /* rtp time jumps are checked for during skew calculation, but bypassed
690    * in other mode, so mind those here and reset jb if needed.
691    * Only reset if valid input time, which is likely for UDP input
692    * where we expect this might happen due to async thread effects
693    * (in seek and state change cycles), but not so much for TCP input */
694   if (GST_CLOCK_TIME_IS_VALID (dts) &&
695       jbuf->mode != RTP_JITTER_BUFFER_MODE_SLAVE &&
696       jbuf->base_time != -1 && jbuf->last_rtptime != -1) {
697     GstClockTime ext_rtptime = jbuf->ext_rtptime;
698
699     ext_rtptime = gst_rtp_buffer_ext_timestamp (&ext_rtptime, rtptime);
700     if (ext_rtptime > jbuf->last_rtptime + 3 * jbuf->clock_rate ||
701         ext_rtptime + 3 * jbuf->clock_rate < jbuf->last_rtptime) {
702       /* reset even if we don't have valid incoming time;
703        * still better than producing possibly very bogus output timestamp */
704       GST_WARNING ("rtp delta too big, reset skew");
705       rtp_jitter_buffer_reset_skew (jbuf);
706     }
707   }
708
709   switch (jbuf->mode) {
710     case RTP_JITTER_BUFFER_MODE_NONE:
711     case RTP_JITTER_BUFFER_MODE_BUFFER:
712       /* send 0 as the first timestamp and -1 for the other ones. This will
713        * interpollate them from the RTP timestamps with a 0 origin. In buffering
714        * mode we will adjust the outgoing timestamps according to the amount of
715        * time we spent buffering. */
716       if (jbuf->base_time == -1)
717         dts = 0;
718       else
719         dts = -1;
720       break;
721     case RTP_JITTER_BUFFER_MODE_SYNCED:
722       /* synchronized clocks, take first timestamp as base, use RTP timestamps
723        * to interpolate */
724       if (jbuf->base_time != -1)
725         dts = -1;
726       break;
727     case RTP_JITTER_BUFFER_MODE_SLAVE:
728     default:
729       break;
730   }
731   /* do skew calculation by measuring the difference between rtptime and the
732    * receive dts, this function will return the skew corrected rtptime. */
733   item->pts = calculate_skew (jbuf, rtptime, dts);
734
735 append:
736   queue_do_insert (jbuf, list, (GList *) item);
737
738   /* buffering mode, update buffer stats */
739   if (jbuf->mode == RTP_JITTER_BUFFER_MODE_BUFFER)
740     update_buffer_level (jbuf, percent);
741   else if (percent)
742     *percent = -1;
743
744   /* tail was changed when we did not find a previous packet, we set the return
745    * flag when requested. */
746   if (G_LIKELY (tail))
747     *tail = (list == NULL);
748
749   return TRUE;
750
751   /* ERRORS */
752 duplicate:
753   {
754     GST_WARNING ("duplicate packet %d found", (gint) seqnum);
755     return FALSE;
756   }
757 }
758
759 /**
760  * rtp_jitter_buffer_pop:
761  * @jbuf: an #RTPJitterBuffer
762  * @percent: the buffering percent
763  *
764  * Pops the oldest buffer from the packet queue of @jbuf. The popped buffer will
765  * have its timestamp adjusted with the incomming running_time and the detected
766  * clock skew.
767  *
768  * Returns: a #GstBuffer or %NULL when there was no packet in the queue.
769  */
770 RTPJitterBufferItem *
771 rtp_jitter_buffer_pop (RTPJitterBuffer * jbuf, gint * percent)
772 {
773   GList *item = NULL;
774   GQueue *queue;
775
776   g_return_val_if_fail (jbuf != NULL, NULL);
777
778   queue = jbuf->packets;
779
780   item = queue->tail;
781   if (item) {
782     queue->tail = item->prev;
783     if (queue->tail)
784       queue->tail->next = NULL;
785     else
786       queue->head = NULL;
787     queue->length--;
788   }
789
790   /* buffering mode, update buffer stats */
791   if (jbuf->mode == RTP_JITTER_BUFFER_MODE_BUFFER)
792     update_buffer_level (jbuf, percent);
793   else if (percent)
794     *percent = -1;
795
796   return (RTPJitterBufferItem *) item;
797 }
798
799 /**
800  * rtp_jitter_buffer_peek:
801  * @jbuf: an #RTPJitterBuffer
802  *
803  * Peek the oldest buffer from the packet queue of @jbuf. Register a callback
804  * with rtp_jitter_buffer_set_tail_changed() to be notified when an older packet
805  * was inserted in the queue.
806  *
807  * Returns: a #GstBuffer or %NULL when there was no packet in the queue.
808  */
809 RTPJitterBufferItem *
810 rtp_jitter_buffer_peek (RTPJitterBuffer * jbuf)
811 {
812   g_return_val_if_fail (jbuf != NULL, NULL);
813
814   return (RTPJitterBufferItem *) jbuf->packets->tail;
815 }
816
817 /**
818  * rtp_jitter_buffer_flush:
819  * @jbuf: an #RTPJitterBuffer
820  * @free_func: function to free each item
821  * @user_data: user data passed to @free_func
822  *
823  * Flush all packets from the jitterbuffer.
824  */
825 void
826 rtp_jitter_buffer_flush (RTPJitterBuffer * jbuf, GFunc free_func,
827     gpointer user_data)
828 {
829   GList *item;
830
831   g_return_if_fail (jbuf != NULL);
832   g_return_if_fail (free_func != NULL);
833
834   while ((item = g_queue_pop_head_link (jbuf->packets)))
835     free_func ((RTPJitterBufferItem *) item, user_data);
836 }
837
838 /**
839  * rtp_jitter_buffer_is_buffering:
840  * @jbuf: an #RTPJitterBuffer
841  *
842  * Check if @jbuf is buffering currently. Users of the jitterbuffer should not
843  * pop packets while in buffering mode.
844  *
845  * Returns: the buffering state of @jbuf
846  */
847 gboolean
848 rtp_jitter_buffer_is_buffering (RTPJitterBuffer * jbuf)
849 {
850   return jbuf->buffering;
851 }
852
853 /**
854  * rtp_jitter_buffer_set_buffering:
855  * @jbuf: an #RTPJitterBuffer
856  * @buffering: the new buffering state
857  *
858  * Forces @jbuf to go into the buffering state.
859  */
860 void
861 rtp_jitter_buffer_set_buffering (RTPJitterBuffer * jbuf, gboolean buffering)
862 {
863   jbuf->buffering = buffering;
864 }
865
866 /**
867  * rtp_jitter_buffer_get_percent:
868  * @jbuf: an #RTPJitterBuffer
869  *
870  * Get the buffering percent of the jitterbuffer.
871  *
872  * Returns: the buffering percent
873  */
874 gint
875 rtp_jitter_buffer_get_percent (RTPJitterBuffer * jbuf)
876 {
877   gint percent;
878   guint64 level;
879
880   if (G_UNLIKELY (jbuf->high_level == 0))
881     return 100;
882
883   level = get_buffer_level (jbuf);
884   percent = (level * 100 / jbuf->high_level);
885   percent = MIN (percent, 100);
886
887   return percent;
888 }
889
890 /**
891  * rtp_jitter_buffer_num_packets:
892  * @jbuf: an #RTPJitterBuffer
893  *
894  * Get the number of packets currently in "jbuf.
895  *
896  * Returns: The number of packets in @jbuf.
897  */
898 guint
899 rtp_jitter_buffer_num_packets (RTPJitterBuffer * jbuf)
900 {
901   g_return_val_if_fail (jbuf != NULL, 0);
902
903   return jbuf->packets->length;
904 }
905
906 /**
907  * rtp_jitter_buffer_get_ts_diff:
908  * @jbuf: an #RTPJitterBuffer
909  *
910  * Get the difference between the timestamps of first and last packet in the
911  * jitterbuffer.
912  *
913  * Returns: The difference expressed in the timestamp units of the packets.
914  */
915 guint32
916 rtp_jitter_buffer_get_ts_diff (RTPJitterBuffer * jbuf)
917 {
918   guint64 high_ts, low_ts;
919   GstBuffer *high_buf, *low_buf;
920   guint32 result;
921   GstRTPBuffer rtp = { NULL };
922
923   g_return_val_if_fail (jbuf != NULL, 0);
924
925   high_buf = g_queue_peek_head (jbuf->packets);
926   low_buf = g_queue_peek_tail (jbuf->packets);
927
928   if (!high_buf || !low_buf || high_buf == low_buf)
929     return 0;
930
931   gst_rtp_buffer_map (high_buf, GST_MAP_READ, &rtp);
932   high_ts = gst_rtp_buffer_get_timestamp (&rtp);
933   gst_rtp_buffer_unmap (&rtp);
934   gst_rtp_buffer_map (low_buf, GST_MAP_READ, &rtp);
935   low_ts = gst_rtp_buffer_get_timestamp (&rtp);
936   gst_rtp_buffer_unmap (&rtp);
937
938   /* it needs to work if ts wraps */
939   if (high_ts >= low_ts) {
940     result = (guint32) (high_ts - low_ts);
941   } else {
942     result = (guint32) (high_ts + G_MAXUINT32 + 1 - low_ts);
943   }
944   return result;
945 }
946
947 /**
948  * rtp_jitter_buffer_get_sync:
949  * @jbuf: an #RTPJitterBuffer
950  * @rtptime: result RTP time
951  * @timestamp: result GStreamer timestamp
952  * @clock_rate: clock-rate of @rtptime
953  * @last_rtptime: last seen rtptime.
954  *
955  * Calculates the relation between the RTP timestamp and the GStreamer timestamp
956  * used for constructing timestamps.
957  *
958  * For extended RTP timestamp @rtptime with a clock-rate of @clock_rate,
959  * the GStreamer timestamp is currently @timestamp.
960  *
961  * The last seen extended RTP timestamp with clock-rate @clock-rate is returned in
962  * @last_rtptime.
963  */
964 void
965 rtp_jitter_buffer_get_sync (RTPJitterBuffer * jbuf, guint64 * rtptime,
966     guint64 * timestamp, guint32 * clock_rate, guint64 * last_rtptime)
967 {
968   if (rtptime)
969     *rtptime = jbuf->base_extrtp;
970   if (timestamp)
971     *timestamp = jbuf->base_time + jbuf->skew;
972   if (clock_rate)
973     *clock_rate = jbuf->clock_rate;
974   if (last_rtptime)
975     *last_rtptime = jbuf->last_rtptime;
976 }