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