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
rtp_jitter_buffer_mode_get_type(void)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 ("TsRTPJitterBufferMode", 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
rtp_jitter_buffer_class_init(RTPJitterBufferClass * klass)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
rtp_jitter_buffer_init(RTPJitterBuffer * jbuf)86 rtp_jitter_buffer_init (RTPJitterBuffer * jbuf)
87 {
88   g_mutex_init (&jbuf->clock_lock);
89 
90   jbuf->packets = g_queue_new ();
91   jbuf->mode = RTP_JITTER_BUFFER_MODE_SLAVE;
92 
93   rtp_jitter_buffer_reset_skew (jbuf);
94 }
95 
96 static void
rtp_jitter_buffer_finalize(GObject * object)97 rtp_jitter_buffer_finalize (GObject * object)
98 {
99   RTPJitterBuffer *jbuf;
100   RTPJitterBufferItem *item;
101 
102   jbuf = RTP_JITTER_BUFFER_CAST (object);
103 
104   if (jbuf->media_clock_synced_id)
105     g_signal_handler_disconnect (jbuf->media_clock,
106         jbuf->media_clock_synced_id);
107   if (jbuf->media_clock) {
108     /* Make sure to clear any clock master before releasing the clock */
109     gst_clock_set_master (jbuf->media_clock, NULL);
110     gst_object_unref (jbuf->media_clock);
111   }
112 
113   if (jbuf->pipeline_clock)
114     gst_object_unref (jbuf->pipeline_clock);
115 
116   /* Free any remaining items manually here. We can't let g_queue_free() take
117    * care of this because the items are not actually GList but
118    * RTPJitterBufferItem, and g_slice_free() explodes if the allocation is not
119    * from the expected block size.
120    */
121   while ((item = (RTPJitterBufferItem *) g_queue_pop_head_link (jbuf->packets))) {
122     if (item->data)
123       gst_mini_object_unref (item->data);
124     g_slice_free (RTPJitterBufferItem, item);
125   }
126   g_queue_free (jbuf->packets);
127 
128   g_mutex_clear (&jbuf->clock_lock);
129 
130   G_OBJECT_CLASS (rtp_jitter_buffer_parent_class)->finalize (object);
131 }
132 
133 /**
134  * rtp_jitter_buffer_new:
135  *
136  * Create an #RTPJitterBuffer.
137  *
138  * Returns: a new #RTPJitterBuffer. Use g_object_unref() after usage.
139  */
140 RTPJitterBuffer *
rtp_jitter_buffer_new(void)141 rtp_jitter_buffer_new (void)
142 {
143   RTPJitterBuffer *jbuf;
144 
145   jbuf = g_object_new (RTP_TYPE_JITTER_BUFFER, NULL);
146 
147   return jbuf;
148 }
149 
150 /**
151  * rtp_jitter_buffer_get_mode:
152  * @jbuf: an #RTPJitterBuffer
153  *
154  * Get the current jitterbuffer mode.
155  *
156  * Returns: the current jitterbuffer mode.
157  */
158 RTPJitterBufferMode
rtp_jitter_buffer_get_mode(RTPJitterBuffer * jbuf)159 rtp_jitter_buffer_get_mode (RTPJitterBuffer * jbuf)
160 {
161   return jbuf->mode;
162 }
163 
164 /**
165  * rtp_jitter_buffer_set_mode:
166  * @jbuf: an #RTPJitterBuffer
167  * @mode: a #RTPJitterBufferMode
168  *
169  * Set the buffering and clock slaving algorithm used in the @jbuf.
170  */
171 void
rtp_jitter_buffer_set_mode(RTPJitterBuffer * jbuf,RTPJitterBufferMode mode)172 rtp_jitter_buffer_set_mode (RTPJitterBuffer * jbuf, RTPJitterBufferMode mode)
173 {
174   jbuf->mode = mode;
175 }
176 
177 GstClockTime
rtp_jitter_buffer_get_delay(RTPJitterBuffer * jbuf)178 rtp_jitter_buffer_get_delay (RTPJitterBuffer * jbuf)
179 {
180   g_print ("%p getting delay (%" G_GUINT64_FORMAT ")\n", jbuf, jbuf->delay);
181   return jbuf->delay;
182 }
183 
184 void
rtp_jitter_buffer_set_delay(RTPJitterBuffer * jbuf,GstClockTime delay)185 rtp_jitter_buffer_set_delay (RTPJitterBuffer * jbuf, GstClockTime delay)
186 {
187   jbuf->delay = delay;
188   jbuf->low_level = (delay * 15) / 100;
189   /* the high level is at 90% in order to release packets before we fill up the
190    * buffer up to the latency */
191   jbuf->high_level = (delay * 90) / 100;
192 
193   GST_DEBUG ("delay %" GST_TIME_FORMAT ", min %" GST_TIME_FORMAT ", max %"
194       GST_TIME_FORMAT, GST_TIME_ARGS (jbuf->delay),
195       GST_TIME_ARGS (jbuf->low_level), GST_TIME_ARGS (jbuf->high_level));
196 }
197 
198 /**
199  * rtp_jitter_buffer_set_clock_rate:
200  * @jbuf: an #RTPJitterBuffer
201  * @clock_rate: the new clock rate
202  *
203  * Set the clock rate in the jitterbuffer.
204  */
205 void
rtp_jitter_buffer_set_clock_rate(RTPJitterBuffer * jbuf,guint32 clock_rate)206 rtp_jitter_buffer_set_clock_rate (RTPJitterBuffer * jbuf, guint32 clock_rate)
207 {
208   if (jbuf->clock_rate != clock_rate) {
209     GST_DEBUG ("Clock rate changed from %" G_GUINT32_FORMAT " to %"
210         G_GUINT32_FORMAT, jbuf->clock_rate, clock_rate);
211     jbuf->clock_rate = clock_rate;
212     rtp_jitter_buffer_reset_skew (jbuf);
213   }
214 }
215 
216 /**
217  * rtp_jitter_buffer_get_clock_rate:
218  * @jbuf: an #RTPJitterBuffer
219  *
220  * Get the currently configure clock rate in @jbuf.
221  *
222  * Returns: the current clock-rate
223  */
224 guint32
rtp_jitter_buffer_get_clock_rate(RTPJitterBuffer * jbuf)225 rtp_jitter_buffer_get_clock_rate (RTPJitterBuffer * jbuf)
226 {
227   return jbuf->clock_rate;
228 }
229 
230 static void
media_clock_synced_cb(GstClock * clock G_GNUC_UNUSED,gboolean synced G_GNUC_UNUSED,RTPJitterBuffer * jbuf)231 media_clock_synced_cb (GstClock * clock G_GNUC_UNUSED,
232     gboolean synced G_GNUC_UNUSED, RTPJitterBuffer * jbuf)
233 {
234   GstClockTime internal, external;
235 
236   g_mutex_lock (&jbuf->clock_lock);
237   if (jbuf->pipeline_clock) {
238     internal = gst_clock_get_internal_time (jbuf->media_clock);
239     external = gst_clock_get_time (jbuf->pipeline_clock);
240 
241     gst_clock_set_calibration (jbuf->media_clock, internal, external, 1, 1);
242   }
243   g_mutex_unlock (&jbuf->clock_lock);
244 }
245 
246 /**
247  * rtp_jitter_buffer_set_media_clock:
248  * @jbuf: an #RTPJitterBuffer
249  * @clock: (transfer full): media #GstClock
250  * @clock_offset: RTP time at clock epoch or -1
251  *
252  * Sets the media clock for the media and the clock offset
253  *
254  */
255 void
rtp_jitter_buffer_set_media_clock(RTPJitterBuffer * jbuf,GstClock * clock,guint64 clock_offset)256 rtp_jitter_buffer_set_media_clock (RTPJitterBuffer * jbuf, GstClock * clock,
257     guint64 clock_offset)
258 {
259   g_mutex_lock (&jbuf->clock_lock);
260   if (jbuf->media_clock) {
261     if (jbuf->media_clock_synced_id)
262       g_signal_handler_disconnect (jbuf->media_clock,
263           jbuf->media_clock_synced_id);
264     jbuf->media_clock_synced_id = 0;
265     gst_object_unref (jbuf->media_clock);
266   }
267   jbuf->media_clock = clock;
268   jbuf->media_clock_offset = clock_offset;
269 
270   if (jbuf->pipeline_clock && jbuf->media_clock &&
271       jbuf->pipeline_clock != jbuf->media_clock) {
272     jbuf->media_clock_synced_id =
273         g_signal_connect (jbuf->media_clock, "synced",
274         G_CALLBACK (media_clock_synced_cb), jbuf);
275     if (gst_clock_is_synced (jbuf->media_clock)) {
276       GstClockTime internal, external;
277 
278       internal = gst_clock_get_internal_time (jbuf->media_clock);
279       external = gst_clock_get_time (jbuf->pipeline_clock);
280 
281       gst_clock_set_calibration (jbuf->media_clock, internal, external, 1, 1);
282     }
283 
284     gst_clock_set_master (jbuf->media_clock, jbuf->pipeline_clock);
285   }
286   g_mutex_unlock (&jbuf->clock_lock);
287 }
288 
289 /**
290  * rtp_jitter_buffer_set_pipeline_clock:
291  * @jbuf: an #RTPJitterBuffer
292  * @clock: pipeline #GstClock
293  *
294  * Sets the pipeline clock
295  *
296  */
297 void
rtp_jitter_buffer_set_pipeline_clock(RTPJitterBuffer * jbuf,GstClock * clock)298 rtp_jitter_buffer_set_pipeline_clock (RTPJitterBuffer * jbuf, GstClock * clock)
299 {
300   g_mutex_lock (&jbuf->clock_lock);
301   if (jbuf->pipeline_clock)
302     gst_object_unref (jbuf->pipeline_clock);
303   jbuf->pipeline_clock = clock ? gst_object_ref (clock) : NULL;
304 
305   if (jbuf->pipeline_clock && jbuf->media_clock &&
306       jbuf->pipeline_clock != jbuf->media_clock) {
307     if (gst_clock_is_synced (jbuf->media_clock)) {
308       GstClockTime internal, external;
309 
310       internal = gst_clock_get_internal_time (jbuf->media_clock);
311       external = gst_clock_get_time (jbuf->pipeline_clock);
312 
313       gst_clock_set_calibration (jbuf->media_clock, internal, external, 1, 1);
314     }
315 
316     gst_clock_set_master (jbuf->media_clock, jbuf->pipeline_clock);
317   }
318   g_mutex_unlock (&jbuf->clock_lock);
319 }
320 
321 gboolean
rtp_jitter_buffer_get_rfc7273_sync(RTPJitterBuffer * jbuf)322 rtp_jitter_buffer_get_rfc7273_sync (RTPJitterBuffer * jbuf)
323 {
324   return jbuf->rfc7273_sync;
325 }
326 
327 void
rtp_jitter_buffer_set_rfc7273_sync(RTPJitterBuffer * jbuf,gboolean rfc7273_sync)328 rtp_jitter_buffer_set_rfc7273_sync (RTPJitterBuffer * jbuf,
329     gboolean rfc7273_sync)
330 {
331   jbuf->rfc7273_sync = rfc7273_sync;
332 }
333 
334 /**
335  * rtp_jitter_buffer_reset_skew:
336  * @jbuf: an #RTPJitterBuffer
337  *
338  * Reset the skew calculations in @jbuf.
339  */
340 void
rtp_jitter_buffer_reset_skew(RTPJitterBuffer * jbuf)341 rtp_jitter_buffer_reset_skew (RTPJitterBuffer * jbuf)
342 {
343   jbuf->base_time = -1;
344   jbuf->base_rtptime = -1;
345   jbuf->base_extrtp = -1;
346   jbuf->media_clock_base_time = -1;
347   jbuf->ext_rtptime = -1;
348   jbuf->last_rtptime = -1;
349   jbuf->window_pos = 0;
350   jbuf->window_filling = TRUE;
351   jbuf->window_min = 0;
352   jbuf->skew = 0;
353   jbuf->prev_send_diff = -1;
354   jbuf->prev_out_time = -1;
355   jbuf->need_resync = TRUE;
356 
357   GST_DEBUG ("reset skew correction");
358 }
359 
360 /**
361  * rtp_jitter_buffer_disable_buffering:
362  * @jbuf: an #RTPJitterBuffer
363  * @disabled: the new state
364  *
365  * Enable or disable buffering on @jbuf.
366  */
367 void
rtp_jitter_buffer_disable_buffering(RTPJitterBuffer * jbuf,gboolean disabled)368 rtp_jitter_buffer_disable_buffering (RTPJitterBuffer * jbuf, gboolean disabled)
369 {
370   jbuf->buffering_disabled = disabled;
371 }
372 
373 static void
rtp_jitter_buffer_resync(RTPJitterBuffer * jbuf,GstClockTime time,GstClockTime gstrtptime,guint64 ext_rtptime,gboolean reset_skew)374 rtp_jitter_buffer_resync (RTPJitterBuffer * jbuf, GstClockTime time,
375     GstClockTime gstrtptime, guint64 ext_rtptime, gboolean reset_skew)
376 {
377   jbuf->base_time = time;
378   jbuf->media_clock_base_time = -1;
379   jbuf->base_rtptime = gstrtptime;
380   jbuf->base_extrtp = ext_rtptime;
381   jbuf->prev_out_time = -1;
382   jbuf->prev_send_diff = -1;
383   if (reset_skew) {
384     jbuf->window_filling = TRUE;
385     jbuf->window_pos = 0;
386     jbuf->window_min = 0;
387     jbuf->window_size = 0;
388     jbuf->skew = 0;
389   }
390   jbuf->need_resync = FALSE;
391 }
392 
393 static guint64
get_buffer_level(RTPJitterBuffer * jbuf)394 get_buffer_level (RTPJitterBuffer * jbuf)
395 {
396   RTPJitterBufferItem *high_buf = NULL, *low_buf = NULL;
397   guint64 level;
398 
399   /* first buffer with timestamp */
400   high_buf = (RTPJitterBufferItem *) g_queue_peek_tail_link (jbuf->packets);
401   while (high_buf) {
402     if (high_buf->dts != GST_CLOCK_TIME_NONE
403         || high_buf->pts != GST_CLOCK_TIME_NONE)
404       break;
405 
406     high_buf = (RTPJitterBufferItem *) g_list_previous (high_buf);
407   }
408 
409   low_buf = (RTPJitterBufferItem *) g_queue_peek_head_link (jbuf->packets);
410   while (low_buf) {
411     if (low_buf->dts != GST_CLOCK_TIME_NONE
412         || low_buf->pts != GST_CLOCK_TIME_NONE)
413       break;
414 
415     low_buf = (RTPJitterBufferItem *) g_list_next (low_buf);
416   }
417 
418   if (!high_buf || !low_buf || high_buf == low_buf) {
419     level = 0;
420   } else {
421     guint64 high_ts, low_ts;
422 
423     high_ts =
424         high_buf->dts != GST_CLOCK_TIME_NONE ? high_buf->dts : high_buf->pts;
425     low_ts = low_buf->dts != GST_CLOCK_TIME_NONE ? low_buf->dts : low_buf->pts;
426 
427     if (high_ts > low_ts)
428       level = high_ts - low_ts;
429     else
430       level = 0;
431 
432     GST_LOG_OBJECT (jbuf,
433         "low %" GST_TIME_FORMAT " high %" GST_TIME_FORMAT " level %"
434         G_GUINT64_FORMAT, GST_TIME_ARGS (low_ts), GST_TIME_ARGS (high_ts),
435         level);
436   }
437   return level;
438 }
439 
440 static void
update_buffer_level(RTPJitterBuffer * jbuf,gint * percent)441 update_buffer_level (RTPJitterBuffer * jbuf, gint * percent)
442 {
443   gboolean post = FALSE;
444   guint64 level;
445 
446   level = get_buffer_level (jbuf);
447   GST_DEBUG ("buffer level %" GST_TIME_FORMAT, GST_TIME_ARGS (level));
448 
449   if (jbuf->buffering_disabled) {
450     GST_DEBUG ("buffering is disabled");
451     level = jbuf->high_level;
452   }
453 
454   if (jbuf->buffering) {
455     post = TRUE;
456     if (level >= jbuf->high_level) {
457       GST_DEBUG ("buffering finished");
458       jbuf->buffering = FALSE;
459     }
460   } else {
461     if (level < jbuf->low_level) {
462       GST_DEBUG ("buffering started");
463       jbuf->buffering = TRUE;
464       post = TRUE;
465     }
466   }
467   if (post) {
468     gint perc;
469 
470     if (jbuf->buffering && (jbuf->high_level != 0)) {
471       perc = (level * 100 / jbuf->high_level);
472       perc = MIN (perc, 100);
473     } else {
474       perc = 100;
475     }
476 
477     if (percent)
478       *percent = perc;
479 
480     GST_DEBUG ("buffering %d", perc);
481   }
482 }
483 
484 /* For the clock skew we use a windowed low point averaging algorithm as can be
485  * found in Fober, Orlarey and Letz, 2005, "Real Time Clock Skew Estimation
486  * over Network Delays":
487  * http://www.grame.fr/Ressources/pub/TR-050601.pdf
488  * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.102.1546
489  *
490  * The idea is that the jitter is composed of:
491  *
492  *  J = N + n
493  *
494  *   N   : a constant network delay.
495  *   n   : random added noise. The noise is concentrated around 0
496  *
497  * In the receiver we can track the elapsed time at the sender with:
498  *
499  *  send_diff(i) = (Tsi - Ts0);
500  *
501  *   Tsi : The time at the sender at packet i
502  *   Ts0 : The time at the sender at the first packet
503  *
504  * This is the difference between the RTP timestamp in the first received packet
505  * and the current packet.
506  *
507  * At the receiver we have to deal with the jitter introduced by the network.
508  *
509  *  recv_diff(i) = (Tri - Tr0)
510  *
511  *   Tri : The time at the receiver at packet i
512  *   Tr0 : The time at the receiver at the first packet
513  *
514  * Both of these values contain a jitter Ji, a jitter for packet i, so we can
515  * write:
516  *
517  *  recv_diff(i) = (Cri + D + ni) - (Cr0 + D + n0))
518  *
519  *    Cri    : The time of the clock at the receiver for packet i
520  *    D + ni : The jitter when receiving packet i
521  *
522  * We see that the network delay is irrelevant here as we can elliminate D:
523  *
524  *  recv_diff(i) = (Cri + ni) - (Cr0 + n0))
525  *
526  * The drift is now expressed as:
527  *
528  *  Drift(i) = recv_diff(i) - send_diff(i);
529  *
530  * We now keep the W latest values of Drift and find the minimum (this is the
531  * one with the lowest network jitter and thus the one which is least affected
532  * by it). We average this lowest value to smooth out the resulting network skew.
533  *
534  * Both the window and the weighting used for averaging influence the accuracy
535  * of the drift estimation. Finding the correct parameters turns out to be a
536  * compromise between accuracy and inertia.
537  *
538  * We use a 2 second window or up to 512 data points, which is statistically big
539  * enough to catch spikes (FIXME, detect spikes).
540  * We also use a rather large weighting factor (125) to smoothly adapt. During
541  * startup, when filling the window, we use a parabolic weighting factor, the
542  * more the window is filled, the faster we move to the detected possible skew.
543  *
544  * Returns: @time adjusted with the clock skew.
545  */
546 static GstClockTime
calculate_skew(RTPJitterBuffer * jbuf,guint64 ext_rtptime,GstClockTime gstrtptime,GstClockTime time,gint gap,gboolean is_rtx)547 calculate_skew (RTPJitterBuffer * jbuf, guint64 ext_rtptime,
548     GstClockTime gstrtptime, GstClockTime time, gint gap, gboolean is_rtx)
549 {
550   guint64 send_diff, recv_diff;
551   gint64 delta;
552   gint64 old;
553   guint pos, i;
554   GstClockTime out_time;
555   guint64 slope;
556 
557   /* elapsed time at sender */
558   send_diff = gstrtptime - jbuf->base_rtptime;
559 
560   /* we don't have an arrival timestamp so we can't do skew detection. we
561    * should still apply a timestamp based on RTP timestamp and base_time */
562   if (time == GST_CLOCK_TIME_NONE || jbuf->base_time == GST_CLOCK_TIME_NONE
563       || is_rtx)
564     goto no_skew;
565 
566   /* elapsed time at receiver, includes the jitter */
567   recv_diff = time - jbuf->base_time;
568 
569   /* measure the diff */
570   delta = ((gint64) recv_diff) - ((gint64) send_diff);
571 
572   /* measure the slope, this gives a rought estimate between the sender speed
573    * and the receiver speed. This should be approximately 8, higher values
574    * indicate a burst (especially when the connection starts) */
575   if (recv_diff > 0)
576     slope = (send_diff * 8) / recv_diff;
577   else
578     slope = 8;
579 
580   GST_DEBUG ("time %" GST_TIME_FORMAT ", base %" GST_TIME_FORMAT ", recv_diff %"
581       GST_TIME_FORMAT ", slope %" G_GUINT64_FORMAT, GST_TIME_ARGS (time),
582       GST_TIME_ARGS (jbuf->base_time), GST_TIME_ARGS (recv_diff), slope);
583 
584   /* if the difference between the sender timeline and the receiver timeline
585    * changed too quickly we have to resync because the server likely restarted
586    * its timestamps. */
587   if (ABS (delta - jbuf->skew) > GST_SECOND) {
588     GST_WARNING ("delta - skew: %" GST_TIME_FORMAT " too big, reset skew",
589         GST_TIME_ARGS (ABS (delta - jbuf->skew)));
590     rtp_jitter_buffer_resync (jbuf, time, gstrtptime, ext_rtptime, TRUE);
591     send_diff = 0;
592     delta = 0;
593     gap = 0;
594   }
595 
596   /* only do skew calculations if we didn't have a gap. if too much time
597    * has elapsed despite there being a gap, we resynced already. */
598   if (G_UNLIKELY (gap != 0))
599     goto no_skew;
600 
601   pos = jbuf->window_pos;
602 
603   if (G_UNLIKELY (jbuf->window_filling)) {
604     /* we are filling the window */
605     GST_DEBUG ("filling %d, delta %" G_GINT64_FORMAT, pos, delta);
606     jbuf->window[pos++] = delta;
607     /* calc the min delta we observed */
608     if (G_UNLIKELY (pos == 1 || delta < jbuf->window_min))
609       jbuf->window_min = delta;
610 
611     if (G_UNLIKELY (send_diff >= MAX_TIME || pos >= MAX_WINDOW)) {
612       jbuf->window_size = pos;
613 
614       /* window filled */
615       GST_DEBUG ("min %" G_GINT64_FORMAT, jbuf->window_min);
616 
617       /* the skew is now the min */
618       jbuf->skew = jbuf->window_min;
619       jbuf->window_filling = FALSE;
620     } else {
621       gint perc_time, perc_window, perc;
622 
623       /* figure out how much we filled the window, this depends on the amount of
624        * time we have or the max number of points we keep. */
625       perc_time = send_diff * 100 / MAX_TIME;
626       perc_window = pos * 100 / MAX_WINDOW;
627       perc = MAX (perc_time, perc_window);
628 
629       /* make a parabolic function, the closer we get to the MAX, the more value
630        * we give to the scaling factor of the new value */
631       perc = perc * perc;
632 
633       /* quickly go to the min value when we are filling up, slowly when we are
634        * just starting because we're not sure it's a good value yet. */
635       jbuf->skew =
636           (perc * jbuf->window_min + ((10000 - perc) * jbuf->skew)) / 10000;
637       jbuf->window_size = pos + 1;
638     }
639   } else {
640     /* pick old value and store new value. We keep the previous value in order
641      * to quickly check if the min of the window changed */
642     old = jbuf->window[pos];
643     jbuf->window[pos++] = delta;
644 
645     if (G_UNLIKELY (delta <= jbuf->window_min)) {
646       /* if the new value we inserted is smaller or equal to the current min,
647        * it becomes the new min */
648       jbuf->window_min = delta;
649     } else if (G_UNLIKELY (old == jbuf->window_min)) {
650       gint64 min = G_MAXINT64;
651 
652       /* if we removed the old min, we have to find a new min */
653       for (i = 0; i < jbuf->window_size; i++) {
654         /* we found another value equal to the old min, we can stop searching now */
655         if (jbuf->window[i] == old) {
656           min = old;
657           break;
658         }
659         if (jbuf->window[i] < min)
660           min = jbuf->window[i];
661       }
662       jbuf->window_min = min;
663     }
664     /* average the min values */
665     jbuf->skew = (jbuf->window_min + (124 * jbuf->skew)) / 125;
666     GST_DEBUG ("delta %" G_GINT64_FORMAT ", new min: %" G_GINT64_FORMAT,
667         delta, jbuf->window_min);
668   }
669   /* wrap around in the window */
670   if (G_UNLIKELY (pos >= jbuf->window_size))
671     pos = 0;
672   jbuf->window_pos = pos;
673 
674 no_skew:
675   /* the output time is defined as the base timestamp plus the RTP time
676    * adjusted for the clock skew .*/
677   if (jbuf->base_time != GST_CLOCK_TIME_NONE) {
678     out_time = jbuf->base_time + send_diff;
679     /* skew can be negative and we don't want to make invalid timestamps */
680     if (jbuf->skew < 0 && out_time < (GstClockTime) - jbuf->skew) {
681       out_time = 0;
682     } else {
683       out_time += jbuf->skew;
684     }
685   } else
686     out_time = -1;
687 
688   GST_DEBUG ("skew %" G_GINT64_FORMAT ", out %" GST_TIME_FORMAT,
689       jbuf->skew, GST_TIME_ARGS (out_time));
690 
691   return out_time;
692 }
693 
694 static void
queue_do_insert(RTPJitterBuffer * jbuf,GList * list,GList * item)695 queue_do_insert (RTPJitterBuffer * jbuf, GList * list, GList * item)
696 {
697   GQueue *queue = jbuf->packets;
698 
699   /* It's more likely that the packet was inserted at the tail of the queue */
700   if (G_LIKELY (list)) {
701     item->prev = list;
702     item->next = list->next;
703     list->next = item;
704   } else {
705     item->prev = NULL;
706     item->next = queue->head;
707     queue->head = item;
708   }
709   if (item->next)
710     item->next->prev = item;
711   else
712     queue->tail = item;
713   queue->length++;
714 }
715 
716 GstClockTime
rtp_jitter_buffer_calculate_pts(RTPJitterBuffer * jbuf,GstClockTime dts,gboolean estimated_dts,guint32 rtptime,GstClockTime base_time,gint gap,gboolean is_rtx)717 rtp_jitter_buffer_calculate_pts (RTPJitterBuffer * jbuf, GstClockTime dts,
718     gboolean estimated_dts, guint32 rtptime, GstClockTime base_time,
719     gint gap, gboolean is_rtx)
720 {
721   guint64 ext_rtptime;
722   GstClockTime gstrtptime, pts;
723   GstClock *media_clock, *pipeline_clock;
724   guint64 media_clock_offset;
725   gboolean rfc7273_mode;
726 
727   /* rtp time jumps are checked for during skew calculation, but bypassed
728    * in other mode, so mind those here and reset jb if needed.
729    * Only reset if valid input time, which is likely for UDP input
730    * where we expect this might happen due to async thread effects
731    * (in seek and state change cycles), but not so much for TCP input */
732   if (GST_CLOCK_TIME_IS_VALID (dts) && !estimated_dts &&
733       jbuf->mode != RTP_JITTER_BUFFER_MODE_SLAVE &&
734       jbuf->base_time != GST_CLOCK_TIME_NONE
735       && jbuf->last_rtptime != GST_CLOCK_TIME_NONE) {
736     GstClockTime ext_rtptime = jbuf->ext_rtptime;
737 
738     ext_rtptime = gst_rtp_buffer_ext_timestamp (&ext_rtptime, rtptime);
739     if (ext_rtptime > jbuf->last_rtptime + 3 * jbuf->clock_rate ||
740         ext_rtptime + 3 * jbuf->clock_rate < jbuf->last_rtptime) {
741       if (!is_rtx) {
742         /* reset even if we don't have valid incoming time;
743          * still better than producing possibly very bogus output timestamp */
744         GST_WARNING ("rtp delta too big, reset skew");
745         rtp_jitter_buffer_reset_skew (jbuf);
746       } else {
747         GST_WARNING ("rtp delta too big: ignore rtx packet");
748         media_clock = NULL;
749         pipeline_clock = NULL;
750         pts = GST_CLOCK_TIME_NONE;
751         goto done;
752       }
753     }
754   }
755 
756   /* Return the last time if we got the same RTP timestamp again */
757   ext_rtptime = gst_rtp_buffer_ext_timestamp (&jbuf->ext_rtptime, rtptime);
758   if (jbuf->last_rtptime != GST_CLOCK_TIME_NONE
759       && ext_rtptime == jbuf->last_rtptime) {
760     return jbuf->prev_out_time;
761   }
762 
763   /* keep track of the last extended rtptime */
764   jbuf->last_rtptime = ext_rtptime;
765 
766   g_mutex_lock (&jbuf->clock_lock);
767   media_clock = jbuf->media_clock ? gst_object_ref (jbuf->media_clock) : NULL;
768   pipeline_clock =
769       jbuf->pipeline_clock ? gst_object_ref (jbuf->pipeline_clock) : NULL;
770   media_clock_offset = jbuf->media_clock_offset;
771   g_mutex_unlock (&jbuf->clock_lock);
772 
773   gstrtptime =
774       gst_util_uint64_scale_int (ext_rtptime, GST_SECOND, jbuf->clock_rate);
775 
776   if (G_LIKELY (jbuf->base_rtptime != GST_CLOCK_TIME_NONE)) {
777     /* check elapsed time in RTP units */
778     if (gstrtptime < jbuf->base_rtptime) {
779       if (!is_rtx) {
780         /* elapsed time at sender, timestamps can go backwards and thus be
781          * smaller than our base time, schedule to take a new base time in
782          * that case. */
783         GST_WARNING ("backward timestamps at server, schedule resync");
784         jbuf->need_resync = TRUE;
785       } else {
786         GST_WARNING ("backward timestamps: ignore rtx packet");
787         pts = GST_CLOCK_TIME_NONE;
788         goto done;
789       }
790     }
791   }
792 
793   switch (jbuf->mode) {
794     case RTP_JITTER_BUFFER_MODE_NONE:
795     case RTP_JITTER_BUFFER_MODE_BUFFER:
796       /* send 0 as the first timestamp and -1 for the other ones. This will
797        * interpolate them from the RTP timestamps with a 0 origin. In buffering
798        * mode we will adjust the outgoing timestamps according to the amount of
799        * time we spent buffering. */
800       if (jbuf->base_time == GST_CLOCK_TIME_NONE)
801         dts = 0;
802       else
803         dts = -1;
804       break;
805     case RTP_JITTER_BUFFER_MODE_SYNCED:
806       /* synchronized clocks, take first timestamp as base, use RTP timestamps
807        * to interpolate */
808       if (jbuf->base_time != GST_CLOCK_TIME_NONE && !jbuf->need_resync)
809         dts = -1;
810       break;
811     case RTP_JITTER_BUFFER_MODE_SLAVE:
812     default:
813       break;
814   }
815 
816   /* need resync, lock on to time and gstrtptime if we can, otherwise we
817    * do with the previous values */
818   if (G_UNLIKELY (jbuf->need_resync && dts != GST_CLOCK_TIME_NONE)) {
819     if (is_rtx) {
820       GST_DEBUG ("not resyncing on rtx packet, discard");
821       pts = GST_CLOCK_TIME_NONE;
822       goto done;
823     }
824     GST_INFO ("resync to time %" GST_TIME_FORMAT ", rtptime %"
825         GST_TIME_FORMAT, GST_TIME_ARGS (dts), GST_TIME_ARGS (gstrtptime));
826     rtp_jitter_buffer_resync (jbuf, dts, gstrtptime, ext_rtptime, FALSE);
827   }
828 
829   GST_DEBUG ("extrtp %" G_GUINT64_FORMAT ", gstrtp %" GST_TIME_FORMAT ", base %"
830       GST_TIME_FORMAT ", send_diff %" GST_TIME_FORMAT, ext_rtptime,
831       GST_TIME_ARGS (gstrtptime), GST_TIME_ARGS (jbuf->base_rtptime),
832       GST_TIME_ARGS (gstrtptime - jbuf->base_rtptime));
833 
834   rfc7273_mode = media_clock && pipeline_clock
835       && gst_clock_is_synced (media_clock);
836 
837   if (rfc7273_mode && jbuf->mode == RTP_JITTER_BUFFER_MODE_SLAVE
838       && (media_clock_offset == GST_CLOCK_TIME_NONE || !jbuf->rfc7273_sync)) {
839     GstClockTime internal, external;
840     GstClockTime rate_num, rate_denom;
841     GstClockTime nsrtptimediff, rtpntptime, rtpsystime;
842 
843     gst_clock_get_calibration (media_clock, &internal, &external, &rate_num,
844         &rate_denom);
845 
846     /* Slave to the RFC7273 media clock instead of trying to estimate it
847      * based on receive times and RTP timestamps */
848 
849     if (jbuf->media_clock_base_time == GST_CLOCK_TIME_NONE) {
850       if (jbuf->base_time != GST_CLOCK_TIME_NONE) {
851         jbuf->media_clock_base_time =
852             gst_clock_unadjust_with_calibration (media_clock,
853             jbuf->base_time + base_time, internal, external, rate_num,
854             rate_denom);
855       } else {
856         if (dts != GST_CLOCK_TIME_NONE)
857           jbuf->media_clock_base_time =
858               gst_clock_unadjust_with_calibration (media_clock, dts + base_time,
859               internal, external, rate_num, rate_denom);
860         else
861           jbuf->media_clock_base_time =
862               gst_clock_get_internal_time (media_clock);
863         jbuf->base_rtptime = gstrtptime;
864       }
865     }
866 
867     if (gstrtptime > jbuf->base_rtptime)
868       nsrtptimediff = gstrtptime - jbuf->base_rtptime;
869     else
870       nsrtptimediff = 0;
871 
872     rtpntptime = nsrtptimediff + jbuf->media_clock_base_time;
873 
874     rtpsystime =
875         gst_clock_adjust_with_calibration (media_clock, rtpntptime, internal,
876         external, rate_num, rate_denom);
877 
878     if (rtpsystime > base_time)
879       pts = rtpsystime - base_time;
880     else
881       pts = 0;
882 
883     GST_DEBUG ("RFC7273 clock time %" GST_TIME_FORMAT ", out %" GST_TIME_FORMAT,
884         GST_TIME_ARGS (rtpsystime), GST_TIME_ARGS (pts));
885   } else if (rfc7273_mode && (jbuf->mode == RTP_JITTER_BUFFER_MODE_SLAVE
886           || jbuf->mode == RTP_JITTER_BUFFER_MODE_SYNCED)
887       && media_clock_offset != GST_CLOCK_TIME_NONE && jbuf->rfc7273_sync) {
888     GstClockTime ntptime, rtptime_tmp;
889     GstClockTime ntprtptime, rtpsystime;
890     GstClockTime internal, external;
891     GstClockTime rate_num, rate_denom;
892 
893     /* Don't do any of the dts related adjustments further down */
894     dts = -1;
895 
896     /* Calculate the actual clock time on the sender side based on the
897      * RFC7273 clock and convert it to our pipeline clock
898      */
899 
900     gst_clock_get_calibration (media_clock, &internal, &external, &rate_num,
901         &rate_denom);
902 
903     ntptime = gst_clock_get_internal_time (media_clock);
904 
905     ntprtptime = gst_util_uint64_scale (ntptime, jbuf->clock_rate, GST_SECOND);
906     ntprtptime += media_clock_offset;
907     ntprtptime &= 0xffffffff;
908 
909     rtptime_tmp = rtptime;
910     /* Check for wraparounds, we assume that the diff between current RTP
911      * timestamp and current media clock time can't be bigger than
912      * 2**31 clock units */
913     if (ntprtptime > rtptime_tmp && ntprtptime - rtptime_tmp >= 0x80000000)
914       rtptime_tmp += G_GUINT64_CONSTANT (0x100000000);
915     else if (rtptime_tmp > ntprtptime && rtptime_tmp - ntprtptime >= 0x80000000)
916       ntprtptime += G_GUINT64_CONSTANT (0x100000000);
917 
918     if (ntprtptime > rtptime_tmp)
919       ntptime -=
920           gst_util_uint64_scale (ntprtptime - rtptime_tmp, jbuf->clock_rate,
921           GST_SECOND);
922     else
923       ntptime +=
924           gst_util_uint64_scale (rtptime_tmp - ntprtptime, jbuf->clock_rate,
925           GST_SECOND);
926 
927     rtpsystime =
928         gst_clock_adjust_with_calibration (media_clock, ntptime, internal,
929         external, rate_num, rate_denom);
930     /* All this assumes that the pipeline has enough additional
931      * latency to cover for the network delay */
932     if (rtpsystime > base_time)
933       pts = rtpsystime - base_time;
934     else
935       pts = 0;
936 
937     GST_DEBUG ("RFC7273 clock time %" GST_TIME_FORMAT ", out %" GST_TIME_FORMAT,
938         GST_TIME_ARGS (rtpsystime), GST_TIME_ARGS (pts));
939   } else {
940     /* If we used the RFC7273 clock before and not anymore,
941      * we need to resync it later again */
942     jbuf->media_clock_base_time = -1;
943 
944     /* do skew calculation by measuring the difference between rtptime and the
945      * receive dts, this function will return the skew corrected rtptime. */
946     pts = calculate_skew (jbuf, ext_rtptime, gstrtptime, dts, gap, is_rtx);
947   }
948 
949   /* check if timestamps are not going backwards, we can only check this if we
950    * have a previous out time and a previous send_diff */
951   if (G_LIKELY (pts != GST_CLOCK_TIME_NONE
952           && jbuf->prev_out_time != GST_CLOCK_TIME_NONE
953           && jbuf->prev_send_diff != -1)) {
954     /* now check for backwards timestamps */
955     if (G_UNLIKELY (
956             /* if the server timestamps went up and the out_time backwards */
957             ((gint64) (gstrtptime - jbuf->base_rtptime) > jbuf->prev_send_diff
958                 && pts < jbuf->prev_out_time) ||
959             /* if the server timestamps went backwards and the out_time forwards */
960             ((gint64) (gstrtptime - jbuf->base_rtptime) < jbuf->prev_send_diff
961                 && pts > jbuf->prev_out_time) ||
962             /* if the server timestamps did not change */
963             (gint64) (gstrtptime - jbuf->base_rtptime) == jbuf->prev_send_diff)) {
964       GST_DEBUG ("backwards timestamps, using previous time");
965       pts = jbuf->prev_out_time;
966     }
967   }
968 
969   if (gap == 0 && dts != GST_CLOCK_TIME_NONE && pts + jbuf->delay < dts) {
970     /* if we are going to produce a timestamp that is later than the input
971      * timestamp, we need to reset the jitterbuffer. Likely the server paused
972      * temporarily */
973     GST_DEBUG ("out %" GST_TIME_FORMAT " + %" G_GUINT64_FORMAT " < time %"
974         GST_TIME_FORMAT ", reset jitterbuffer and discard", GST_TIME_ARGS (pts),
975         jbuf->delay, GST_TIME_ARGS (dts));
976     rtp_jitter_buffer_reset_skew (jbuf);
977     pts = GST_CLOCK_TIME_NONE;
978     goto done;
979   }
980 
981   jbuf->prev_out_time = pts;
982   jbuf->prev_send_diff = gstrtptime - jbuf->base_rtptime;
983 
984 done:
985   if (media_clock)
986     gst_object_unref (media_clock);
987   if (pipeline_clock)
988     gst_object_unref (pipeline_clock);
989 
990   return pts;
991 }
992 
993 
994 /**
995  * rtp_jitter_buffer_insert:
996  * @jbuf: an #RTPJitterBuffer
997  * @item: an #RTPJitterBufferItem to insert
998  * @head: TRUE when the head element changed.
999  * @percent: the buffering percent after insertion
1000  *
1001  * Inserts @item into the packet queue of @jbuf. The sequence number of the
1002  * packet will be used to sort the packets. This function takes ownerhip of
1003  * @buf when the function returns %TRUE.
1004  *
1005  * When @head is %TRUE, the new packet was added at the head of the queue and
1006  * will be available with the next call to rtp_jitter_buffer_pop() and
1007  * rtp_jitter_buffer_peek().
1008  *
1009  * Returns: %FALSE if a packet with the same number already existed.
1010  */
1011 gboolean
rtp_jitter_buffer_insert(RTPJitterBuffer * jbuf,RTPJitterBufferItem * item,gboolean * head,gint * percent)1012 rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, RTPJitterBufferItem * item,
1013     gboolean * head, gint * percent)
1014 {
1015   GList *list, *event = NULL;
1016   guint16 seqnum;
1017 
1018   g_return_val_if_fail (jbuf != NULL, FALSE);
1019   g_return_val_if_fail (item != NULL, FALSE);
1020 
1021   list = jbuf->packets->tail;
1022 
1023   /* no seqnum, simply append then */
1024   if (item->seqnum == G_MAXUINT)
1025     goto append;
1026 
1027   seqnum = item->seqnum;
1028 
1029   /* loop the list to skip strictly larger seqnum buffers */
1030   for (; list; list = g_list_previous (list)) {
1031     guint16 qseq;
1032     gint gap;
1033     RTPJitterBufferItem *qitem = (RTPJitterBufferItem *) list;
1034 
1035     if (qitem->seqnum == G_MAXUINT) {
1036       /* keep a pointer to the first consecutive event if not already
1037        * set. we will insert the packet after the event if we can't find
1038        * a packet with lower sequence number before the event. */
1039       if (event == NULL)
1040         event = list;
1041       continue;
1042     }
1043 
1044     qseq = qitem->seqnum;
1045 
1046     /* compare the new seqnum to the one in the buffer */
1047     gap = gst_rtp_buffer_compare_seqnum (seqnum, qseq);
1048 
1049     /* we hit a packet with the same seqnum, notify a duplicate */
1050     if (G_UNLIKELY (gap == 0))
1051       goto duplicate;
1052 
1053     /* seqnum > qseq, we can stop looking */
1054     if (G_LIKELY (gap < 0))
1055       break;
1056 
1057     /* if we've found a packet with greater sequence number, cleanup the
1058      * event pointer as the packet will be inserted before the event */
1059     event = NULL;
1060   }
1061 
1062   /* if event is set it means that packets before the event had smaller
1063    * sequence number, so we will insert our packet after the event */
1064   if (event)
1065     list = event;
1066 
1067 append:
1068   queue_do_insert (jbuf, list, (GList *) item);
1069 
1070   /* buffering mode, update buffer stats */
1071   if (jbuf->mode == RTP_JITTER_BUFFER_MODE_BUFFER)
1072     update_buffer_level (jbuf, percent);
1073   else if (percent)
1074     *percent = -1;
1075 
1076   /* head was changed when we did not find a previous packet, we set the return
1077    * flag when requested. */
1078   if (G_LIKELY (head))
1079     *head = (list == NULL);
1080 
1081   return TRUE;
1082 
1083   /* ERRORS */
1084 duplicate:
1085   {
1086     GST_DEBUG ("duplicate packet %d found", (gint) seqnum);
1087     if (G_LIKELY (head))
1088       *head = FALSE;
1089     return FALSE;
1090   }
1091 }
1092 
1093 /**
1094  * rtp_jitter_buffer_pop:
1095  * @jbuf: an #RTPJitterBuffer
1096  * @percent: the buffering percent
1097  *
1098  * Pops the oldest buffer from the packet queue of @jbuf. The popped buffer will
1099  * have its timestamp adjusted with the incoming running_time and the detected
1100  * clock skew.
1101  *
1102  * Returns: a #GstBuffer or %NULL when there was no packet in the queue.
1103  */
1104 RTPJitterBufferItem *
rtp_jitter_buffer_pop(RTPJitterBuffer * jbuf,gint * percent)1105 rtp_jitter_buffer_pop (RTPJitterBuffer * jbuf, gint * percent)
1106 {
1107   GList *item = NULL;
1108   GQueue *queue;
1109 
1110   g_return_val_if_fail (jbuf != NULL, NULL);
1111 
1112   queue = jbuf->packets;
1113 
1114   item = queue->head;
1115   if (item) {
1116     queue->head = item->next;
1117     if (queue->head)
1118       queue->head->prev = NULL;
1119     else
1120       queue->tail = NULL;
1121     queue->length--;
1122   }
1123 
1124   /* buffering mode, update buffer stats */
1125   if (jbuf->mode == RTP_JITTER_BUFFER_MODE_BUFFER)
1126     update_buffer_level (jbuf, percent);
1127   else if (percent)
1128     *percent = -1;
1129 
1130   return (RTPJitterBufferItem *) item;
1131 }
1132 
1133 /**
1134  * rtp_jitter_buffer_peek:
1135  * @jbuf: an #RTPJitterBuffer
1136  *
1137  * Peek the oldest buffer from the packet queue of @jbuf.
1138  *
1139  * See rtp_jitter_buffer_insert() to check when an older packet was
1140  * added.
1141  *
1142  * Returns: a #GstBuffer or %NULL when there was no packet in the queue.
1143  */
1144 RTPJitterBufferItem *
rtp_jitter_buffer_peek(RTPJitterBuffer * jbuf)1145 rtp_jitter_buffer_peek (RTPJitterBuffer * jbuf)
1146 {
1147   g_return_val_if_fail (jbuf != NULL, NULL);
1148 
1149   return (RTPJitterBufferItem *) jbuf->packets->head;
1150 }
1151 
1152 /**
1153  * rtp_jitter_buffer_flush:
1154  * @jbuf: an #RTPJitterBuffer
1155  * @free_func: function to free each item
1156  * @user_data: user data passed to @free_func
1157  *
1158  * Flush all packets from the jitterbuffer.
1159  */
1160 void
rtp_jitter_buffer_flush(RTPJitterBuffer * jbuf,GFunc free_func,gpointer user_data)1161 rtp_jitter_buffer_flush (RTPJitterBuffer * jbuf, GFunc free_func,
1162     gpointer user_data)
1163 {
1164   GList *item;
1165 
1166   g_return_if_fail (jbuf != NULL);
1167   g_return_if_fail (free_func != NULL);
1168 
1169   while ((item = g_queue_pop_head_link (jbuf->packets)))
1170     free_func ((RTPJitterBufferItem *) item, user_data);
1171 }
1172 
1173 /**
1174  * rtp_jitter_buffer_is_buffering:
1175  * @jbuf: an #RTPJitterBuffer
1176  *
1177  * Check if @jbuf is buffering currently. Users of the jitterbuffer should not
1178  * pop packets while in buffering mode.
1179  *
1180  * Returns: the buffering state of @jbuf
1181  */
1182 gboolean
rtp_jitter_buffer_is_buffering(RTPJitterBuffer * jbuf)1183 rtp_jitter_buffer_is_buffering (RTPJitterBuffer * jbuf)
1184 {
1185   return jbuf->buffering && !jbuf->buffering_disabled;
1186 }
1187 
1188 /**
1189  * rtp_jitter_buffer_set_buffering:
1190  * @jbuf: an #RTPJitterBuffer
1191  * @buffering: the new buffering state
1192  *
1193  * Forces @jbuf to go into the buffering state.
1194  */
1195 void
rtp_jitter_buffer_set_buffering(RTPJitterBuffer * jbuf,gboolean buffering)1196 rtp_jitter_buffer_set_buffering (RTPJitterBuffer * jbuf, gboolean buffering)
1197 {
1198   jbuf->buffering = buffering;
1199 }
1200 
1201 /**
1202  * rtp_jitter_buffer_get_percent:
1203  * @jbuf: an #RTPJitterBuffer
1204  *
1205  * Get the buffering percent of the jitterbuffer.
1206  *
1207  * Returns: the buffering percent
1208  */
1209 gint
rtp_jitter_buffer_get_percent(RTPJitterBuffer * jbuf)1210 rtp_jitter_buffer_get_percent (RTPJitterBuffer * jbuf)
1211 {
1212   gint percent;
1213   guint64 level;
1214 
1215   if (G_UNLIKELY (jbuf->high_level == 0))
1216     return 100;
1217 
1218   if (G_UNLIKELY (jbuf->buffering_disabled))
1219     return 100;
1220 
1221   level = get_buffer_level (jbuf);
1222   percent = (level * 100 / jbuf->high_level);
1223   percent = MIN (percent, 100);
1224 
1225   return percent;
1226 }
1227 
1228 /**
1229  * rtp_jitter_buffer_num_packets:
1230  * @jbuf: an #RTPJitterBuffer
1231  *
1232  * Get the number of packets currently in "jbuf.
1233  *
1234  * Returns: The number of packets in @jbuf.
1235  */
1236 guint
rtp_jitter_buffer_num_packets(RTPJitterBuffer * jbuf)1237 rtp_jitter_buffer_num_packets (RTPJitterBuffer * jbuf)
1238 {
1239   g_return_val_if_fail (jbuf != NULL, 0);
1240 
1241   return jbuf->packets->length;
1242 }
1243 
1244 /**
1245  * rtp_jitter_buffer_get_ts_diff:
1246  * @jbuf: an #RTPJitterBuffer
1247  *
1248  * Get the difference between the timestamps of first and last packet in the
1249  * jitterbuffer.
1250  *
1251  * Returns: The difference expressed in the timestamp units of the packets.
1252  */
1253 guint32
rtp_jitter_buffer_get_ts_diff(RTPJitterBuffer * jbuf)1254 rtp_jitter_buffer_get_ts_diff (RTPJitterBuffer * jbuf)
1255 {
1256   guint64 high_ts, low_ts;
1257   RTPJitterBufferItem *high_buf, *low_buf;
1258   guint32 result;
1259 
1260   g_return_val_if_fail (jbuf != NULL, 0);
1261 
1262   high_buf = (RTPJitterBufferItem *) g_queue_peek_tail_link (jbuf->packets);
1263   low_buf = (RTPJitterBufferItem *) g_queue_peek_head_link (jbuf->packets);
1264 
1265   if (!high_buf || !low_buf || high_buf == low_buf)
1266     return 0;
1267 
1268   high_ts = high_buf->rtptime;
1269   low_ts = low_buf->rtptime;
1270 
1271   /* it needs to work if ts wraps */
1272   if (high_ts >= low_ts) {
1273     result = (guint32) (high_ts - low_ts);
1274   } else {
1275     result = (guint32) (high_ts + G_MAXUINT32 + 1 - low_ts);
1276   }
1277   return result;
1278 }
1279 
1280 
1281 /*
1282  * rtp_jitter_buffer_get_seqnum_diff:
1283  * @jbuf: an #RTPJitterBuffer
1284  *
1285  * Get the difference between the seqnum of first and last packet in the
1286  * jitterbuffer.
1287  *
1288  * Returns: The difference expressed in seqnum.
1289  */
1290 static guint16
rtp_jitter_buffer_get_seqnum_diff(RTPJitterBuffer * jbuf)1291 rtp_jitter_buffer_get_seqnum_diff (RTPJitterBuffer * jbuf)
1292 {
1293   guint32 high_seqnum, low_seqnum;
1294   RTPJitterBufferItem *high_buf, *low_buf;
1295   guint16 result;
1296 
1297   g_return_val_if_fail (jbuf != NULL, 0);
1298 
1299   high_buf = (RTPJitterBufferItem *) g_queue_peek_tail_link (jbuf->packets);
1300   low_buf = (RTPJitterBufferItem *) g_queue_peek_head_link (jbuf->packets);
1301 
1302   while (high_buf && high_buf->seqnum == G_MAXUINT)
1303     high_buf = (RTPJitterBufferItem *) high_buf->prev;
1304 
1305   while (low_buf && low_buf->seqnum == G_MAXUINT)
1306     low_buf = (RTPJitterBufferItem *) low_buf->next;
1307 
1308   if (!high_buf || !low_buf || high_buf == low_buf)
1309     return 0;
1310 
1311   high_seqnum = high_buf->seqnum;
1312   low_seqnum = low_buf->seqnum;
1313 
1314   /* it needs to work if ts wraps */
1315   if (high_seqnum >= low_seqnum) {
1316     result = (guint32) (high_seqnum - low_seqnum);
1317   } else {
1318     result = (guint32) (high_seqnum + G_MAXUINT16 + 1 - low_seqnum);
1319   }
1320   return result;
1321 }
1322 
1323 /**
1324  * rtp_jitter_buffer_get_sync:
1325  * @jbuf: an #RTPJitterBuffer
1326  * @rtptime: result RTP time
1327  * @timestamp: result GStreamer timestamp
1328  * @clock_rate: clock-rate of @rtptime
1329  * @last_rtptime: last seen rtptime.
1330  *
1331  * Calculates the relation between the RTP timestamp and the GStreamer timestamp
1332  * used for constructing timestamps.
1333  *
1334  * For extended RTP timestamp @rtptime with a clock-rate of @clock_rate,
1335  * the GStreamer timestamp is currently @timestamp.
1336  *
1337  * The last seen extended RTP timestamp with clock-rate @clock-rate is returned in
1338  * @last_rtptime.
1339  */
1340 void
rtp_jitter_buffer_get_sync(RTPJitterBuffer * jbuf,guint64 * rtptime,guint64 * timestamp,guint32 * clock_rate,guint64 * last_rtptime)1341 rtp_jitter_buffer_get_sync (RTPJitterBuffer * jbuf, guint64 * rtptime,
1342     guint64 * timestamp, guint32 * clock_rate, guint64 * last_rtptime)
1343 {
1344   if (rtptime)
1345     *rtptime = jbuf->base_extrtp;
1346   if (timestamp)
1347     *timestamp = jbuf->base_time + jbuf->skew;
1348   if (clock_rate)
1349     *clock_rate = jbuf->clock_rate;
1350   if (last_rtptime)
1351     *last_rtptime = jbuf->last_rtptime;
1352 }
1353 
1354 /**
1355  * rtp_jitter_buffer_can_fast_start:
1356  * @jbuf: an #RTPJitterBuffer
1357  * @num_packets: Number of consecutive packets needed
1358  *
1359  * Check if in the queue if there is enough packets with consecutive seqnum in
1360  * order to start delivering them.
1361  *
1362  * Returns: %TRUE if the required number of consecutive packets was found.
1363  */
1364 gboolean
rtp_jitter_buffer_can_fast_start(RTPJitterBuffer * jbuf,gint num_packet)1365 rtp_jitter_buffer_can_fast_start (RTPJitterBuffer * jbuf, gint num_packet)
1366 {
1367   gboolean ret = TRUE;
1368   RTPJitterBufferItem *last_item = NULL, *item;
1369   gint i;
1370 
1371   if (rtp_jitter_buffer_num_packets (jbuf) < (guint) num_packet)
1372     return FALSE;
1373 
1374   item = rtp_jitter_buffer_peek (jbuf);
1375   for (i = 0; i < num_packet; i++) {
1376     if (G_LIKELY (last_item)) {
1377       guint16 expected_seqnum = last_item->seqnum + 1;
1378 
1379       if (expected_seqnum != item->seqnum) {
1380         ret = FALSE;
1381         break;
1382       }
1383     }
1384 
1385     last_item = item;
1386     item = (RTPJitterBufferItem *) last_item->next;
1387   }
1388 
1389   return ret;
1390 }
1391 
1392 gboolean
rtp_jitter_buffer_is_full(RTPJitterBuffer * jbuf)1393 rtp_jitter_buffer_is_full (RTPJitterBuffer * jbuf)
1394 {
1395   return rtp_jitter_buffer_get_seqnum_diff (jbuf) >= 32765 &&
1396       rtp_jitter_buffer_num_packets (jbuf) > 10000;
1397 }
1398 
1399 void
rtp_jitter_buffer_find_earliest(RTPJitterBuffer * jbuf,GstClockTime * pts,guint * seqnum)1400 rtp_jitter_buffer_find_earliest (RTPJitterBuffer * jbuf, GstClockTime * pts,
1401     guint * seqnum)
1402 {
1403   GList *tmp;
1404   RTPJitterBufferItem *earliest = NULL;
1405 
1406   *pts = GST_CLOCK_TIME_NONE;
1407   *seqnum = 0;
1408 
1409   for (tmp = jbuf->packets->head; tmp; tmp = tmp->next) {
1410     RTPJitterBufferItem *item = (RTPJitterBufferItem *) tmp;
1411 
1412     if (!earliest || item->pts <= earliest->pts)
1413       earliest = item;
1414   }
1415 
1416   if (earliest) {
1417     *pts = earliest->pts;
1418     *seqnum = earliest->seqnum;
1419   }
1420 }
1421