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