1 /* GStreamer
2 *
3 * Copyright (C) 2009 Nokia Corporation and its subsidiary(-ies)
4 * contact: <stefan.kost@nokia.com>
5 * Copyright (C) 2012 Cisco Systems, Inc
6 * Authors: Kelley Rogers <kelro@cisco.com>
7 * Havard Graff <hgraff@cisco.com>
8 * Copyright (C) 2013-2016 Pexip AS
9 * Stian Selnes <stian@pexip>
10 * Havard Graff <havard@pexip>
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with this library; if not, write to the
24 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 * Boston, MA 02110-1301, USA.
26 */
27
28 #include <gst/check/gstcheck.h>
29 #include <gst/check/gsttestclock.h>
30 #include <gst/check/gstharness.h>
31 #include <gst/rtp/gstrtpbuffer.h>
32
33 /* For ease of programming we use globals to keep refs for our floating
34 * src and sink pads we create; otherwise we always have to do get_pad,
35 * get_peer, and then remove references in every test function */
36 static GstPad *mysrcpad, *mysinkpad;
37 /* we also have a list of src buffers */
38 static GList *inbuffers = NULL;
39 static gint num_dropped = 0;
40
41 #define RTP_CAPS_STRING \
42 "application/x-rtp, " \
43 "media = (string)audio, " \
44 "payload = (int) 0, " \
45 "clock-rate = (int) 8000, " \
46 "encoding-name = (string)PCMU"
47
48 #define RTP_FRAME_SIZE 20
49
50 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
51 GST_PAD_SINK,
52 GST_PAD_ALWAYS,
53 GST_STATIC_CAPS ("application/x-rtp")
54 );
55 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
56 GST_PAD_SRC,
57 GST_PAD_ALWAYS,
58 GST_STATIC_CAPS ("application/x-rtp, "
59 "clock-rate = (int) [ 1, 2147483647 ]")
60 );
61
62 static void
buffer_dropped(G_GNUC_UNUSED gpointer data,GstMiniObject * obj)63 buffer_dropped (G_GNUC_UNUSED gpointer data, GstMiniObject * obj)
64 {
65 GST_DEBUG ("dropping buffer %p", obj);
66 num_dropped++;
67 }
68
69 static GstElement *
setup_jitterbuffer(gint num_buffers)70 setup_jitterbuffer (gint num_buffers)
71 {
72 GstElement *jitterbuffer;
73 GstClock *clock;
74 GstBuffer *buffer;
75 GstCaps *caps;
76 /* a 20 sample audio block (2,5 ms) generated with
77 * gst-launch audiotestsrc wave=silence blocksize=40 num-buffers=3 !
78 * "audio/x-raw,channels=1,rate=8000" ! mulawenc ! rtppcmupay !
79 * fakesink dump=1
80 */
81 guint8 in[] = {
82 /* first 4 bytes are rtp-header, next 4 bytes are timestamp */
83 0x80, 0x80, 0x1c, 0x24, 0x46, 0xcd, 0xb7, 0x11, 0x3c, 0x3a, 0x7c, 0x5b,
84 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
85 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
86 };
87 GstClockTime ts = G_GUINT64_CONSTANT (0);
88 GstClockTime tso = gst_util_uint64_scale (RTP_FRAME_SIZE, GST_SECOND, 8000);
89 /*guint latency = GST_TIME_AS_MSECONDS (num_buffers * tso); */
90 gint i;
91
92 GST_DEBUG ("setup_jitterbuffer");
93 jitterbuffer = gst_check_setup_element ("rtpjitterbuffer");
94 /* we need a clock here */
95 clock = gst_system_clock_obtain ();
96 gst_element_set_clock (jitterbuffer, clock);
97 gst_object_unref (clock);
98 /* setup latency */
99 /* latency would be 7 for 3 buffers here, default is 200
100 g_object_set (G_OBJECT (jitterbuffer), "latency", latency, NULL);
101 GST_INFO_OBJECT (jitterbuffer, "set latency to %u ms", latency);
102 */
103
104 mysrcpad = gst_check_setup_src_pad (jitterbuffer, &srctemplate);
105 mysinkpad = gst_check_setup_sink_pad (jitterbuffer, &sinktemplate);
106 gst_pad_set_active (mysrcpad, TRUE);
107 gst_pad_set_active (mysinkpad, TRUE);
108
109 /* create n buffers */
110 caps = gst_caps_from_string (RTP_CAPS_STRING);
111 gst_check_setup_events (mysrcpad, jitterbuffer, caps, GST_FORMAT_TIME);
112 gst_caps_unref (caps);
113
114 for (i = 0; i < num_buffers; i++) {
115 buffer = gst_buffer_new_and_alloc (sizeof (in));
116 gst_buffer_fill (buffer, 0, in, sizeof (in));
117 GST_BUFFER_DTS (buffer) = ts;
118 GST_BUFFER_PTS (buffer) = ts;
119 GST_BUFFER_DURATION (buffer) = tso;
120 gst_mini_object_weak_ref (GST_MINI_OBJECT (buffer), buffer_dropped, NULL);
121 GST_DEBUG ("created buffer: %p", buffer);
122
123 if (!i)
124 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
125
126 inbuffers = g_list_append (inbuffers, buffer);
127
128 /* hackish way to update the rtp header */
129 in[1] = 0x00;
130 in[3]++; /* seqnumber */
131 in[7] += RTP_FRAME_SIZE; /* inc. timestamp with framesize */
132 ts += tso;
133 }
134 num_dropped = 0;
135
136 return jitterbuffer;
137 }
138
139 static GstStateChangeReturn
start_jitterbuffer(GstElement * jitterbuffer)140 start_jitterbuffer (GstElement * jitterbuffer)
141 {
142 GstStateChangeReturn ret;
143 GstClockTime now;
144 GstClock *clock;
145
146 clock = gst_element_get_clock (jitterbuffer);
147 now = gst_clock_get_time (clock);
148 gst_object_unref (clock);
149
150 gst_element_set_base_time (jitterbuffer, now);
151 ret = gst_element_set_state (jitterbuffer, GST_STATE_PLAYING);
152
153 return ret;
154 }
155
156 static void
cleanup_jitterbuffer(GstElement * jitterbuffer)157 cleanup_jitterbuffer (GstElement * jitterbuffer)
158 {
159 GST_DEBUG ("cleanup_jitterbuffer");
160
161 g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
162 g_list_free (buffers);
163 buffers = NULL;
164
165 g_list_free (inbuffers);
166 inbuffers = NULL;
167
168 gst_pad_set_active (mysrcpad, FALSE);
169 gst_pad_set_active (mysinkpad, FALSE);
170 gst_element_set_state (jitterbuffer, GST_STATE_NULL);
171 gst_check_teardown_src_pad (jitterbuffer);
172 gst_check_teardown_sink_pad (jitterbuffer);
173 gst_check_teardown_element (jitterbuffer);
174 }
175
176 static void
check_jitterbuffer_results(gint num_buffers)177 check_jitterbuffer_results (gint num_buffers)
178 {
179 GstBuffer *buffer;
180 GList *node;
181 GstClockTime ts = G_GUINT64_CONSTANT (0);
182 GstClockTime tso = gst_util_uint64_scale (RTP_FRAME_SIZE, GST_SECOND, 8000);
183 GstMapInfo map;
184 guint16 prev_sn = 0, cur_sn;
185 guint32 prev_ts = 0, cur_ts;
186
187 /* sleep for twice the latency */
188 g_usleep (400 * 1000);
189
190 GST_INFO ("of %d buffer %d/%d received/dropped", num_buffers,
191 g_list_length (buffers), num_dropped);
192 /* if this fails, not all buffers have been processed */
193 fail_unless_equals_int ((g_list_length (buffers) + num_dropped), num_buffers);
194
195 /* check the buffer list */
196 fail_unless_equals_int (g_list_length (buffers), num_buffers);
197 for (node = buffers; node; node = g_list_next (node)) {
198 fail_if ((buffer = (GstBuffer *) node->data) == NULL);
199 fail_if (GST_BUFFER_PTS (buffer) != ts);
200 gst_buffer_map (buffer, &map, GST_MAP_READ);
201 cur_sn = ((guint16) map.data[2] << 8) | map.data[3];
202 cur_ts = ((guint32) map.data[4] << 24) | ((guint32) map.data[5] << 16) |
203 ((guint32) map.data[6] << 8) | map.data[7];
204 gst_buffer_unmap (buffer, &map);
205
206 if (node != buffers) {
207 fail_unless (cur_sn > prev_sn);
208 fail_unless (cur_ts > prev_ts);
209
210 prev_sn = cur_sn;
211 prev_ts = cur_ts;
212 }
213 ts += tso;
214 }
215 }
216
GST_START_TEST(test_push_forward_seq)217 GST_START_TEST (test_push_forward_seq)
218 {
219 GstElement *jitterbuffer;
220 const guint num_buffers = 3;
221 GstBuffer *buffer;
222 GList *node;
223
224 jitterbuffer = setup_jitterbuffer (num_buffers);
225 fail_unless (start_jitterbuffer (jitterbuffer)
226 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
227
228 /* push buffers: 0,1,2, */
229 for (node = inbuffers; node; node = g_list_next (node)) {
230 buffer = (GstBuffer *) node->data;
231 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
232 }
233
234 /* check the buffer list */
235 check_jitterbuffer_results (num_buffers);
236
237 /* cleanup */
238 cleanup_jitterbuffer (jitterbuffer);
239 }
240
241 GST_END_TEST;
242
GST_START_TEST(test_push_backward_seq)243 GST_START_TEST (test_push_backward_seq)
244 {
245 GstElement *jitterbuffer;
246 const guint num_buffers = 4;
247 GstBuffer *buffer;
248 GList *node;
249
250 jitterbuffer = setup_jitterbuffer (num_buffers);
251 fail_unless (start_jitterbuffer (jitterbuffer)
252 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
253
254 /* push buffers: 0,3,2,1 */
255 buffer = (GstBuffer *) inbuffers->data;
256 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
257 for (node = g_list_last (inbuffers); node != inbuffers;
258 node = g_list_previous (node)) {
259 buffer = (GstBuffer *) node->data;
260 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
261 }
262
263 /* check the buffer list */
264 check_jitterbuffer_results (num_buffers);
265
266 /* cleanup */
267 cleanup_jitterbuffer (jitterbuffer);
268 }
269
270 GST_END_TEST;
271
GST_START_TEST(test_push_unordered)272 GST_START_TEST (test_push_unordered)
273 {
274 GstElement *jitterbuffer;
275 const guint num_buffers = 4;
276 GstBuffer *buffer;
277
278 jitterbuffer = setup_jitterbuffer (num_buffers);
279 fail_unless (start_jitterbuffer (jitterbuffer)
280 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
281
282 /* push buffers; 0,2,1,3 */
283 buffer = (GstBuffer *) inbuffers->data;
284 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
285 buffer = g_list_nth_data (inbuffers, 2);
286 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
287 buffer = g_list_nth_data (inbuffers, 1);
288 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
289 buffer = g_list_nth_data (inbuffers, 3);
290 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
291
292 /* check the buffer list */
293 check_jitterbuffer_results (num_buffers);
294
295 /* cleanup */
296 cleanup_jitterbuffer (jitterbuffer);
297 }
298
299 GST_END_TEST;
300
301 gboolean is_eos;
302
303 static gboolean
eos_event_function(G_GNUC_UNUSED GstPad * pad,G_GNUC_UNUSED GstObject * parent,GstEvent * event)304 eos_event_function (G_GNUC_UNUSED GstPad * pad,
305 G_GNUC_UNUSED GstObject * parent, GstEvent * event)
306 {
307 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
308 g_mutex_lock (&check_mutex);
309 is_eos = TRUE;
310 g_cond_signal (&check_cond);
311 g_mutex_unlock (&check_mutex);
312 }
313 gst_event_unref (event);
314 return TRUE;
315 }
316
GST_START_TEST(test_push_eos)317 GST_START_TEST (test_push_eos)
318 {
319 GstElement *jitterbuffer;
320 const guint num_buffers = 5;
321 GList *node;
322 GstStructure *stats;
323 guint64 pushed, lost, late, duplicates;
324 int n = 0;
325
326 is_eos = FALSE;
327
328 jitterbuffer = setup_jitterbuffer (num_buffers);
329 gst_pad_set_event_function (mysinkpad, eos_event_function);
330
331 g_object_set (jitterbuffer, "latency", 1, NULL);
332
333 fail_unless (start_jitterbuffer (jitterbuffer)
334 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
335
336 /* push buffers: 0,1,2, */
337 for (node = inbuffers; node; node = g_list_next (node)) {
338 GstBuffer *buffer;
339
340 /* steal buffer from list */
341 buffer = node->data;
342 node->data = NULL;
343
344 n++;
345 /* Skip 1 */
346 if (n == 2) {
347 gst_buffer_unref (buffer);
348 continue;
349 }
350 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
351 }
352
353 gst_pad_push_event (mysrcpad, gst_event_new_eos ());
354
355 g_mutex_lock (&check_mutex);
356 while (!is_eos)
357 g_cond_wait (&check_cond, &check_mutex);
358 g_mutex_unlock (&check_mutex);
359
360 fail_unless_equals_int (g_list_length (buffers), num_buffers - 1);
361
362 /* Verify statistics */
363 g_object_get (jitterbuffer, "stats", &stats, NULL);
364 gst_structure_get (stats, "num-pushed", G_TYPE_UINT64, &pushed,
365 "num-lost", G_TYPE_UINT64, &lost,
366 "num-late", G_TYPE_UINT64, &late,
367 "num-duplicates", G_TYPE_UINT64, &duplicates, NULL);
368 fail_unless_equals_int (pushed, g_list_length (inbuffers) - 1);
369 fail_unless_equals_int (lost, 1);
370 fail_unless_equals_int (late, 0);
371 fail_unless_equals_int (duplicates, 0);
372 gst_structure_free (stats);
373
374 /* cleanup */
375 cleanup_jitterbuffer (jitterbuffer);
376 }
377
378 GST_END_TEST;
379
GST_START_TEST(test_basetime)380 GST_START_TEST (test_basetime)
381 {
382 GstElement *jitterbuffer;
383 const guint num_buffers = 3;
384 GstBuffer *buffer;
385 GList *node;
386 GstClockTime tso = gst_util_uint64_scale (RTP_FRAME_SIZE, GST_SECOND, 8000);
387
388 jitterbuffer = setup_jitterbuffer (num_buffers);
389 fail_unless (start_jitterbuffer (jitterbuffer)
390 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
391
392 /* push buffers: 2,1,0 */
393 for (node = g_list_last (inbuffers); node; node = g_list_previous (node)) {
394 buffer = (GstBuffer *) node->data;
395 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
396 }
397
398 /* sleep for twice the latency */
399 g_usleep (400 * 1000);
400
401 /* if this fails, not all buffers have been processed */
402 fail_unless_equals_int ((g_list_length (buffers) + num_dropped), num_buffers);
403
404 buffer = (GstBuffer *) buffers->data;
405 fail_unless (GST_BUFFER_DTS (buffer) != (num_buffers * tso));
406 fail_unless (GST_BUFFER_PTS (buffer) != (num_buffers * tso));
407
408 /* cleanup */
409 cleanup_jitterbuffer (jitterbuffer);
410 }
411
412 GST_END_TEST;
413
414 static GstCaps *
request_pt_map(G_GNUC_UNUSED GstElement * jitterbuffer,guint pt)415 request_pt_map (G_GNUC_UNUSED GstElement * jitterbuffer, guint pt)
416 {
417 fail_unless (pt == 0);
418
419 return gst_caps_from_string (RTP_CAPS_STRING);
420 }
421
GST_START_TEST(test_clear_pt_map)422 GST_START_TEST (test_clear_pt_map)
423 {
424 GstElement *jitterbuffer;
425 const guint num_buffers = 10;
426 gint i;
427 GstBuffer *buffer;
428 GList *node;
429
430 jitterbuffer = setup_jitterbuffer (num_buffers);
431 fail_unless (start_jitterbuffer (jitterbuffer)
432 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
433
434 g_signal_connect (jitterbuffer, "request-pt-map", (GCallback)
435 request_pt_map, NULL);
436
437 /* push buffers: 0,1,2, */
438 for (node = inbuffers, i = 0; node && i < 3; node = g_list_next (node), i++) {
439 buffer = (GstBuffer *) node->data;
440 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
441 }
442
443 g_usleep (400 * 1000);
444
445 g_signal_emit_by_name (jitterbuffer, "clear-pt-map", NULL);
446
447 for (; node && i < 10; node = g_list_next (node), i++) {
448 buffer = (GstBuffer *) node->data;
449 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
450 }
451
452 /* check the buffer list */
453 check_jitterbuffer_results (num_buffers);
454
455 /* cleanup */
456 cleanup_jitterbuffer (jitterbuffer);
457 }
458
459 GST_END_TEST;
460
461 #define TEST_BUF_CLOCK_RATE 8000
462 #define AS_TEST_BUF_RTP_TIME(gst_time) gst_util_uint64_scale_int (TEST_BUF_CLOCK_RATE, gst_time, GST_SECOND)
463 #define TEST_BUF_PT 0
464 #define TEST_BUF_SSRC 0x01BADBAD
465 #define TEST_BUF_MS 20
466 #define TEST_BUF_DURATION (TEST_BUF_MS * GST_MSECOND)
467 #define TEST_BUF_SIZE (64000 * TEST_BUF_MS / 1000)
468 #define TEST_RTP_TS_DURATION AS_TEST_BUF_RTP_TIME (TEST_BUF_DURATION)
469
470 static GstCaps *
generate_caps(void)471 generate_caps (void)
472 {
473 return gst_caps_new_simple ("application/x-rtp",
474 "media", G_TYPE_STRING, "audio",
475 "clock-rate", G_TYPE_INT, TEST_BUF_CLOCK_RATE,
476 "encoding-name", G_TYPE_STRING, "TEST",
477 "payload", G_TYPE_INT, TEST_BUF_PT,
478 "ssrc", G_TYPE_UINT, TEST_BUF_SSRC, NULL);
479 }
480
481 static GstBuffer *
generate_test_buffer_full(GstClockTime dts,guint seq_num,guint32 rtp_ts)482 generate_test_buffer_full (GstClockTime dts, guint seq_num, guint32 rtp_ts)
483 {
484 GstBuffer *buf;
485 guint8 *payload;
486 guint i;
487 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
488
489 buf = gst_rtp_buffer_new_allocate (TEST_BUF_SIZE, 0, 0);
490 GST_BUFFER_DTS (buf) = dts;
491
492 gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp);
493 gst_rtp_buffer_set_payload_type (&rtp, TEST_BUF_PT);
494 gst_rtp_buffer_set_seq (&rtp, seq_num);
495 gst_rtp_buffer_set_timestamp (&rtp, rtp_ts);
496 gst_rtp_buffer_set_ssrc (&rtp, TEST_BUF_SSRC);
497
498 payload = gst_rtp_buffer_get_payload (&rtp);
499 for (i = 0; i < TEST_BUF_SIZE; i++)
500 payload[i] = 0xff;
501
502 gst_rtp_buffer_unmap (&rtp);
503
504 return buf;
505 }
506
507 static GstBuffer *
generate_test_buffer(guint seq_num)508 generate_test_buffer (guint seq_num)
509 {
510 return generate_test_buffer_full (seq_num * TEST_BUF_DURATION,
511 seq_num, seq_num * TEST_RTP_TS_DURATION);
512 }
513
514 static GstBuffer *
generate_test_buffer_rtx(GstClockTime dts,guint seq_num)515 generate_test_buffer_rtx (GstClockTime dts, guint seq_num)
516 {
517 GstBuffer *buffer = generate_test_buffer_full (dts, seq_num,
518 seq_num * TEST_RTP_TS_DURATION);
519 GST_BUFFER_FLAG_SET (buffer, GST_RTP_BUFFER_FLAG_RETRANSMISSION);
520 return buffer;
521 }
522
523 static void
push_test_buffer(GstHarness * h,guint seq_num)524 push_test_buffer (GstHarness * h, guint seq_num)
525 {
526 gst_harness_set_time (h, seq_num * TEST_BUF_DURATION);
527 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
528 generate_test_buffer (seq_num)));
529 }
530
531 static void
push_test_buffer_now(GstHarness * h,guint seqnum,guint32 rtptime,gboolean rtx)532 push_test_buffer_now (GstHarness * h, guint seqnum, guint32 rtptime,
533 gboolean rtx)
534 {
535 GstClockTime now =
536 gst_clock_get_time (GST_ELEMENT_CLOCK (h->element)) -
537 h->element->base_time;
538 GstBuffer *buf = generate_test_buffer_full (now, seqnum, rtptime);
539 if (rtx)
540 GST_BUFFER_FLAG_SET (buf, GST_RTP_BUFFER_FLAG_RETRANSMISSION);
541 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, buf));
542 }
543
544 static gint
get_rtp_seq_num(GstBuffer * buf)545 get_rtp_seq_num (GstBuffer * buf)
546 {
547 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
548 gint seq;
549 gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
550 seq = gst_rtp_buffer_get_seq (&rtp);
551 gst_rtp_buffer_unmap (&rtp);
552 return seq;
553 }
554
555 static void
verify_lost_event(GstHarness * h,guint exp_seq,GstClockTime exp_ts,GstClockTime exp_dur)556 verify_lost_event (GstHarness * h, guint exp_seq, GstClockTime exp_ts,
557 GstClockTime exp_dur)
558 {
559 GstEvent *event;
560 const GstStructure *s;
561 const GValue *value;
562 guint seq;
563 GstClockTime ts;
564 GstClockTime dur;
565
566 event = gst_harness_pull_event (h);
567 fail_unless (event != NULL);
568
569 s = gst_event_get_structure (event);
570 fail_unless (s != NULL);
571 fail_unless (gst_structure_get_uint (s, "seqnum", &seq));
572
573 value = gst_structure_get_value (s, "timestamp");
574 fail_unless (value && G_VALUE_HOLDS_UINT64 (value));
575
576 ts = g_value_get_uint64 (value);
577 value = gst_structure_get_value (s, "duration");
578 fail_unless (value && G_VALUE_HOLDS_UINT64 (value));
579
580 dur = g_value_get_uint64 (value);
581 fail_unless_equals_int ((guint16) exp_seq, seq);
582 fail_unless_equals_uint64 (exp_ts, ts);
583 fail_unless_equals_uint64 (exp_dur, dur);
584
585 gst_event_unref (event);
586 }
587
588 static void
verify_rtx_event(GstHarness * h,guint exp_seq,GstClockTime exp_ts,gint exp_delay,GstClockTime exp_spacing)589 verify_rtx_event (GstHarness * h, guint exp_seq, GstClockTime exp_ts,
590 gint exp_delay, GstClockTime exp_spacing)
591 {
592 GstEvent *event;
593 const GstStructure *s;
594 const GValue *value;
595 guint seq;
596 GstClockTime ts;
597 guint delay;
598 GstClockTime spacing;
599
600 event = gst_harness_pull_upstream_event (h);
601 fail_unless (event != NULL);
602
603 s = gst_event_get_structure (event);
604 fail_unless (s != NULL);
605 fail_unless (gst_structure_get_uint (s, "seqnum", &seq));
606
607 value = gst_structure_get_value (s, "running-time");
608 fail_unless (value && G_VALUE_HOLDS_UINT64 (value));
609
610 ts = g_value_get_uint64 (value);
611 fail_unless (gst_structure_get_uint (s, "delay", &delay));
612 value = gst_structure_get_value (s, "packet-spacing");
613 fail_unless (value && G_VALUE_HOLDS_UINT64 (value));
614 spacing = g_value_get_uint64 (value);
615 fail_unless_equals_int ((guint16) exp_seq, seq);
616 fail_unless_equals_uint64 (exp_ts, ts);
617 fail_unless_equals_int (exp_delay, delay);
618 fail_unless_equals_uint64 (exp_spacing, spacing);
619
620 gst_event_unref (event);
621 }
622
623 static gboolean
verify_jb_stats(GstElement * jb,GstStructure * expected)624 verify_jb_stats (GstElement * jb, GstStructure * expected)
625 {
626 gboolean ret;
627 GstStructure *actual;
628 g_object_get (jb, "stats", &actual, NULL);
629
630 ret = gst_structure_is_subset (actual, expected);
631
632 if (!ret) {
633 gchar *e_str = gst_structure_to_string (expected);
634 gchar *a_str = gst_structure_to_string (actual);
635 fail_unless (ret, "%s is not a subset of %s", e_str, a_str);
636 g_free (e_str);
637 g_free (a_str);
638 }
639
640 gst_structure_free (expected);
641 gst_structure_free (actual);
642
643 return ret;
644 }
645
646 static guint
construct_deterministic_initial_state(GstHarness * h,gint latency_ms)647 construct_deterministic_initial_state (GstHarness * h, gint latency_ms)
648 {
649 guint next_seqnum = latency_ms / TEST_BUF_MS + 1;
650 guint seqnum;
651 gint i;
652
653 g_assert (latency_ms % TEST_BUF_MS == 0);
654
655 gst_harness_set_src_caps (h, generate_caps ());
656 g_object_set (h->element, "latency", latency_ms, NULL);
657
658 /* When the first packet arrives in the jitterbuffer, it will create a
659 * timeout for this packet equal to the latency of the jitterbuffer.
660 * This is known as DEADLINE internally, and is meant to allow the stream
661 * to buffer a bit before starting to push it out, to get some ideas about
662 * the nature of the stream. (packetspacing, jitter etc.)
663 *
664 * When writing tests using the test-clock, it it hence important to know
665 * that by simply advancing the clock to this timeout, you are basically
666 * describing a stream that had one initial packet, and then nothing at all
667 * for the duration of the latency (100ms in this test), which is not a very
668 * usual scenario.
669 *
670 * Instead, a pattern used throughout this test-suite, is to keep the buffers
671 * arriving at their optimal time, until the DEADLINE is reached, and that
672 * then becomes the "starting-point" for the test, because at this time
673 * there should now be no waiting timers (unless using rtx) and we have
674 * a "clean" state to craft the test from.
675 */
676
677 /* Packet 0 arrives at time 0ms, Packet 5 arrives at time 100ms */
678 for (seqnum = 0; seqnum < next_seqnum; seqnum++) {
679 push_test_buffer (h, seqnum);
680 gst_harness_wait_for_clock_id_waits (h, 1, 60);
681 }
682
683 /* We release the DEADLINE timer for packet 0, verify the time is indeed
684 * @latency_ms (100ms) and pull out all the buffers that have been released,
685 * and verify their PTS and sequence numbers.
686 */
687 gst_harness_crank_single_clock_wait (h);
688 fail_unless_equals_int64 (latency_ms * GST_MSECOND,
689 gst_clock_get_time (GST_ELEMENT_CLOCK (h->element)));
690 for (seqnum = 0; seqnum < next_seqnum; seqnum++) {
691 GstBuffer *buf = gst_harness_pull (h);
692 fail_unless_equals_uint64 (seqnum * TEST_BUF_DURATION,
693 GST_BUFFER_PTS (buf));
694 fail_unless_equals_int (seqnum, get_rtp_seq_num (buf));
695 gst_buffer_unref (buf);
696 }
697
698 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
699 for (i = 0; i < 3; i++)
700 gst_event_unref (gst_harness_pull_event (h));
701
702 /* drop reconfigure event */
703 gst_event_unref (gst_harness_pull_upstream_event (h));
704
705 /* Verify that at this point our queues are empty */
706 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h));
707 fail_unless_equals_int (0, gst_harness_events_in_queue (h));
708
709 return next_seqnum;
710 }
711
GST_START_TEST(test_lost_event)712 GST_START_TEST (test_lost_event)
713 {
714 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
715 GstBuffer *buf;
716 gint latency_ms = 100;
717 guint next_seqnum;
718 guint missing_seqnum;
719
720 g_object_set (h->element, "do-lost", TRUE, NULL);
721 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
722
723 /* We will now create a gap in the stream, by skipping one sequence-number,
724 * and push the following packet.
725 */
726 missing_seqnum = next_seqnum;
727 next_seqnum += 1;
728 push_test_buffer (h, next_seqnum);
729
730 /* This packet (@next_seqnum) will now be held back, awaiting the missing one,
731 * verify that this is the case:
732 */
733 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h));
734 fail_unless_equals_int (0, gst_harness_events_in_queue (h));
735
736 /* The lost-timeout for the missing packet will now be its pts + latency, so
737 * now we will simply crank the clock to advance to this point in time, and
738 * check that we get a lost-event, as well as the last packet we pushed in.
739 */
740 gst_harness_crank_single_clock_wait (h);
741 verify_lost_event (h, missing_seqnum,
742 missing_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION);
743
744 buf = gst_harness_pull (h);
745 fail_unless_equals_uint64 (next_seqnum * TEST_BUF_DURATION,
746 GST_BUFFER_PTS (buf));
747 fail_unless_equals_int (next_seqnum, get_rtp_seq_num (buf));
748 gst_buffer_unref (buf);
749
750 fail_unless (verify_jb_stats (h->element,
751 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
752 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
753 "num-lost", G_TYPE_UINT64, (guint64) 1, NULL)));
754
755 gst_harness_teardown (h);
756 }
757
758 GST_END_TEST;
759
GST_START_TEST(test_only_one_lost_event_on_large_gaps)760 GST_START_TEST (test_only_one_lost_event_on_large_gaps)
761 {
762 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
763 GstTestClock *testclock;
764 GstBuffer *out_buf;
765 guint next_seqnum;
766 gint latency_ms = 200;
767 gint num_lost_events = latency_ms / TEST_BUF_MS;
768 gint i;
769
770 testclock = gst_harness_get_testclock (h);
771 /* Need to set max-misorder-time and max-dropout-time to 0 so the
772 * jitterbuffer does not base them on packet rate calculations.
773 * If it does, out gap is big enough to be considered a new stream and
774 * we wait for a few consecutive packets just to be sure
775 */
776 g_object_set (h->element, "do-lost", TRUE,
777 "max-misorder-time", 0, "max-dropout-time", 0, NULL);
778 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
779
780 /* move time ahead to just before 10 seconds */
781 gst_harness_set_time (h, 10 * GST_SECOND - 1);
782
783 /* check that we have no pending waits */
784 fail_unless_equals_int (0, gst_test_clock_peek_id_count (testclock));
785
786 /* a buffer now arrives perfectly on time */
787 fail_unless_equals_int (GST_FLOW_OK,
788 gst_harness_push (h, generate_test_buffer (500)));
789
790 /* release the wait, advancing the clock to 10 sec */
791 fail_unless (gst_harness_crank_single_clock_wait (h));
792
793 /* we should now receive a packet-lost-event for buffers 11 through 489 ... */
794 verify_lost_event (h, next_seqnum,
795 next_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION * (490 - next_seqnum));
796
797 /* ... as well as 490 (since at 10 sec 490 is too late) */
798 verify_lost_event (h, 490, 490 * TEST_BUF_DURATION, TEST_BUF_DURATION);
799
800 /* we get as many lost events as the the number of *
801 * buffers the jitterbuffer is able to wait for */
802 for (i = 1; i < num_lost_events; i++) {
803 fail_unless (gst_harness_crank_single_clock_wait (h));
804 verify_lost_event (h, 490 + i, (490 + i) * TEST_BUF_DURATION,
805 TEST_BUF_DURATION);
806 }
807
808 /* and then the buffer is released */
809 out_buf = gst_harness_pull (h);
810 fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DISCONT));
811 fail_unless_equals_int (500, get_rtp_seq_num (out_buf));
812 fail_unless_equals_uint64 (10 * GST_SECOND, GST_BUFFER_PTS (out_buf));
813 gst_buffer_unref (out_buf);
814
815 fail_unless (verify_jb_stats (h->element,
816 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
817 "num-lost", G_TYPE_UINT64, (guint64) 489, NULL)));
818
819 gst_object_unref (testclock);
820 gst_harness_teardown (h);
821 }
822
823 GST_END_TEST;
824
GST_START_TEST(test_two_lost_one_arrives_in_time)825 GST_START_TEST (test_two_lost_one_arrives_in_time)
826 {
827 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
828 GstTestClock *testclock;
829 GstClockID id;
830 GstBuffer *buf;
831 gint latency_ms = 100;
832 guint next_seqnum;
833 guint first_missing;
834 guint second_missing;
835 guint current_arrived;
836
837 testclock = gst_harness_get_testclock (h);
838 g_object_set (h->element, "do-lost", TRUE, NULL);
839 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
840
841 /* hop over 2 packets and make another one (gap of 2) */
842 first_missing = next_seqnum;
843 second_missing = next_seqnum + 1;
844 current_arrived = next_seqnum + 2;
845 push_test_buffer (h, current_arrived);
846
847 /* verify that the jitterbuffer now wait for the latest moment it can push the
848 * @first_missing packet out.
849 */
850 gst_test_clock_wait_for_next_pending_id (testclock, &id);
851 fail_unless_equals_uint64 (first_missing * TEST_BUF_DURATION +
852 latency_ms * GST_MSECOND, gst_clock_id_get_time (id));
853 gst_clock_id_unref (id);
854
855 /* let the time expire... */
856 fail_unless (gst_harness_crank_single_clock_wait (h));
857
858 /* we should now receive a packet-lost-event */
859 verify_lost_event (h, first_missing,
860 first_missing * TEST_BUF_DURATION, TEST_BUF_DURATION);
861
862 /* @second_missing now arrives just in time */
863 fail_unless_equals_int (GST_FLOW_OK,
864 gst_harness_push (h, generate_test_buffer (second_missing)));
865
866 /* verify that @second_missing made it through! */
867 buf = gst_harness_pull (h);
868 fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
869 fail_unless_equals_int (second_missing, get_rtp_seq_num (buf));
870 gst_buffer_unref (buf);
871
872 /* and see that @current_arrived now also is pushed */
873 buf = gst_harness_pull (h);
874 fail_unless (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
875 fail_unless_equals_int (current_arrived, get_rtp_seq_num (buf));
876 gst_buffer_unref (buf);
877
878 fail_unless (verify_jb_stats (h->element,
879 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
880 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 2,
881 "num-lost", G_TYPE_UINT64, (guint64) 1, NULL)));
882
883 gst_object_unref (testclock);
884 gst_harness_teardown (h);
885 }
886
887 GST_END_TEST;
888
GST_START_TEST(test_late_packets_still_makes_lost_events)889 GST_START_TEST (test_late_packets_still_makes_lost_events)
890 {
891 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
892 GstBuffer *out_buf;
893 gint latency_ms = 100;
894 guint next_seqnum;
895 guint seqnum;
896 GstClockTime now;
897
898 g_object_set (h->element, "do-lost", TRUE, NULL);
899 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
900
901 /* jump 10 seconds forward in time */
902 now = 10 * GST_SECOND;
903 gst_harness_set_time (h, now);
904
905 /* push a packet with a gap of 2, that now is very late */
906 seqnum = next_seqnum + 2;
907 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
908 generate_test_buffer_full (now,
909 seqnum, seqnum * TEST_RTP_TS_DURATION)));
910
911 /* We get one "huge" lost-event accounting for all the missing time */
912 verify_lost_event (h, next_seqnum, 120 * GST_MSECOND, 9860 * GST_MSECOND);
913
914 /* and the next packet is optimistically expected to be the one
915 just prior to our current packet, so we time that out with a crank */
916 gst_harness_crank_single_clock_wait (h);
917
918 /* and we verify that indeed this lost event was thought to should
919 have arrived 20ms prior to the packet that actually arrived */
920 verify_lost_event (h, next_seqnum + 1, 9980 * GST_MSECOND, 20 * GST_MSECOND);
921
922 /* and finally verify that the super-late packet made it through! */
923 out_buf = gst_harness_pull (h);
924 fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DISCONT));
925 fail_unless_equals_int (seqnum, get_rtp_seq_num (out_buf));
926 gst_buffer_unref (out_buf);
927
928 fail_unless (verify_jb_stats (h->element,
929 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
930 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 1,
931 "num-lost", G_TYPE_UINT64, (guint64) 2, NULL)));
932
933 gst_harness_teardown (h);
934 }
935
936 GST_END_TEST;
937
938
GST_START_TEST(test_num_late_when_considered_lost_arrives)939 GST_START_TEST (test_num_late_when_considered_lost_arrives)
940 {
941 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
942 gboolean do_lost = __i__ != 0;
943 gint latency_ms = 100;
944 guint next_seqnum;
945
946 g_object_set (h->element, "do-lost", do_lost, NULL);
947 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
948
949 /* gap of 1 */
950 push_test_buffer (h, next_seqnum + 1);
951
952 /* crank to trigger lost-event */
953 gst_harness_crank_single_clock_wait (h);
954
955 if (do_lost) {
956 /* we should now receive packet-lost-events for the missing packet */
957 verify_lost_event (h, next_seqnum,
958 next_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION);
959 }
960
961 /* pull out the pushed packet */
962 gst_buffer_unref (gst_harness_pull (h));
963
964 /* we have one lost packet in the stats */
965 fail_unless (verify_jb_stats (h->element,
966 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
967 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 1,
968 "num-lost", G_TYPE_UINT64, (guint64) 1,
969 "num-late", G_TYPE_UINT64, (guint64) 0, NULL)));
970
971 /* the missing packet now arrives (too late) */
972 fail_unless_equals_int (GST_FLOW_OK,
973 gst_harness_push (h, generate_test_buffer (next_seqnum)));
974
975 /* and this increments num-late */
976 fail_unless (verify_jb_stats (h->element,
977 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
978 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 1,
979 "num-lost", G_TYPE_UINT64, (guint64) 1,
980 "num-late", G_TYPE_UINT64, (guint64) 1, NULL)));
981
982 gst_harness_teardown (h);
983 }
984
985 GST_END_TEST;
986
GST_START_TEST(test_lost_event_uses_pts)987 GST_START_TEST (test_lost_event_uses_pts)
988 {
989 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
990 GstClockTime now;
991 gint latency_ms = 100;
992 guint next_seqnum;
993 guint lost_seqnum;
994
995 g_object_set (h->element, "do-lost", TRUE, NULL);
996 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
997
998 /* hop over 1 packets and make another one (gap of 1), but due to
999 network delays, this packets is also grossly late */
1000 lost_seqnum = next_seqnum;
1001 next_seqnum += 1;
1002
1003 /* advance the clock to the latest time packet @next_seqnum could arrive */
1004 now = next_seqnum * TEST_BUF_DURATION + latency_ms * GST_MSECOND;
1005 gst_harness_set_time (h, now);
1006 gst_harness_push (h, generate_test_buffer_full (now, next_seqnum,
1007 next_seqnum * TEST_RTP_TS_DURATION));
1008
1009 /* we should now have received a packet-lost-event for buffer 3 */
1010 verify_lost_event (h, lost_seqnum,
1011 lost_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION);
1012
1013 /* and pull out packet 4 */
1014 gst_buffer_unref (gst_harness_pull (h));
1015
1016 fail_unless (verify_jb_stats (h->element,
1017 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1018 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1019 "num-lost", G_TYPE_UINT64, (guint64) 1, NULL)));
1020
1021 gst_harness_teardown (h);
1022 }
1023
1024 GST_END_TEST;
1025
GST_START_TEST(test_lost_event_with_backwards_rtptime)1026 GST_START_TEST (test_lost_event_with_backwards_rtptime)
1027 {
1028 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1029 gint latency_ms = 40;
1030
1031 g_object_set (h->element, "do-lost", TRUE, NULL);
1032 construct_deterministic_initial_state (h, latency_ms);
1033
1034 /*
1035 * For video using B-frames, an expected sequence
1036 * could be like this:
1037 * (I = I-frame, P = P-frame, B = B-frame)
1038 * ___ ___ ___ ___ ___
1039 * ... | 3 | | 4 | | 5 | | 6 | | 7 |
1040 * ––– ––– ––– ––– –––
1041 * rtptime: 3(I) 5(P) 5(P) 4(B) 6(P)
1042 * arrival(dts): 3 5 5 5 6
1043 *
1044 * Notice here that packet 6 (the B frame) make
1045 * the rtptime go backwards.
1046 *
1047 * But we get this:
1048 * ___ ___ _ _ ___ ___
1049 * ... | 3 | | 4 | | | | 6 | | 7 |
1050 * ––– ––– - - ––– –––
1051 * rtptime: 3(I) 5(P) 4(B) 6(P)
1052 * arrival(dts): 3 5 5 6
1053 *
1054 */
1055
1056 /* seqnum 3 */
1057 push_test_buffer (h, 3);
1058 gst_buffer_unref (gst_harness_pull (h));
1059
1060 /* seqnum 4, arriving at time 5 with rtptime 5 */
1061 gst_harness_push (h,
1062 generate_test_buffer_full (5 * TEST_BUF_DURATION,
1063 4, 5 * TEST_RTP_TS_DURATION));
1064 gst_buffer_unref (gst_harness_pull (h));
1065
1066 /* seqnum 6, arriving at time 5 with rtptime 4,
1067 making a gap for missing seqnum 5 */
1068 gst_harness_push (h,
1069 generate_test_buffer_full (5 * TEST_BUF_DURATION,
1070 6, 4 * TEST_RTP_TS_DURATION));
1071
1072 /* seqnum 7, arriving at time 6 with rtptime 6 */
1073 gst_harness_push (h,
1074 generate_test_buffer_full (6 * TEST_BUF_DURATION,
1075 7, 6 * TEST_RTP_TS_DURATION));
1076
1077 /* we should now have received a packet-lost-event for seqnum 5,
1078 with time 5 and 0 duration */
1079 gst_harness_crank_single_clock_wait (h);
1080 verify_lost_event (h, 5, 5 * TEST_BUF_DURATION, 0);
1081
1082 /* and pull out 6 and 7 */
1083 gst_buffer_unref (gst_harness_pull (h));
1084 gst_buffer_unref (gst_harness_pull (h));
1085
1086 fail_unless (verify_jb_stats (h->element,
1087 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1088 "num-pushed", G_TYPE_UINT64, (guint64) 7,
1089 "num-lost", G_TYPE_UINT64, (guint64) 1, NULL)));
1090
1091 gst_harness_teardown (h);
1092 }
1093
1094 GST_END_TEST;
1095
GST_START_TEST(test_all_packets_are_timestamped_zero)1096 GST_START_TEST (test_all_packets_are_timestamped_zero)
1097 {
1098 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1099 GstBuffer *out_buf;
1100 gint jb_latency_ms = 100;
1101 gint i, b;
1102
1103 gst_harness_set_src_caps (h, generate_caps ());
1104 g_object_set (h->element, "do-lost", TRUE, "latency", jb_latency_ms, NULL);
1105
1106 /* advance the clock with 10 seconds */
1107 gst_harness_set_time (h, 10 * GST_SECOND);
1108
1109 /* push the first buffer through */
1110 gst_buffer_unref (gst_harness_push_and_pull (h, generate_test_buffer (0)));
1111
1112 /* push some buffers in, all timestamped 0 */
1113 for (b = 1; b < 3; b++) {
1114 fail_unless_equals_int (GST_FLOW_OK,
1115 gst_harness_push (h,
1116 generate_test_buffer_full (0 * GST_MSECOND, b, 0)));
1117
1118 /* check for the buffer coming out that was pushed in */
1119 out_buf = gst_harness_pull (h);
1120 fail_unless_equals_uint64 (0, GST_BUFFER_PTS (out_buf));
1121 gst_buffer_unref (out_buf);
1122 }
1123
1124 /* hop over 2 packets and make another one (gap of 2) */
1125 b = 5;
1126 fail_unless_equals_int (GST_FLOW_OK,
1127 gst_harness_push (h, generate_test_buffer_full (0 * GST_MSECOND, b, 0)));
1128
1129 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
1130 for (i = 0; i < 3; i++)
1131 gst_event_unref (gst_harness_pull_event (h));
1132
1133 /* we should now receive packet-lost-events for buffer 3 and 4 */
1134 verify_lost_event (h, 3, 0, 0);
1135 verify_lost_event (h, 4, 0, 0);
1136
1137 /* verify that buffer 5 made it through! */
1138 out_buf = gst_harness_pull (h);
1139 fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DISCONT));
1140 fail_unless_equals_int (5, get_rtp_seq_num (out_buf));
1141 gst_buffer_unref (out_buf);
1142
1143 fail_unless (verify_jb_stats (h->element,
1144 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1145 "num-pushed", G_TYPE_UINT64, (guint64) 4,
1146 "num-lost", G_TYPE_UINT64, (guint64) 2, NULL)));
1147
1148 gst_harness_teardown (h);
1149 }
1150
1151 GST_END_TEST;
1152
GST_START_TEST(test_reorder_of_non_equidistant_packets)1153 GST_START_TEST (test_reorder_of_non_equidistant_packets)
1154 {
1155 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1156 GstTestClock *testclock;
1157 gint latency_ms = 5;
1158 GstClockID pending_id;
1159 GstClockTime time;
1160 gint seq, frame;
1161 gint num_init_frames = 1;
1162 const GstClockTime frame_dur = TEST_BUF_DURATION;
1163 const guint32 frame_rtp_ts_dur = TEST_RTP_TS_DURATION;
1164
1165 gst_harness_set_src_caps (h, generate_caps ());
1166 testclock = gst_harness_get_testclock (h);
1167 g_object_set (h->element, "do-lost", TRUE, "latency", latency_ms, NULL);
1168
1169 for (frame = 0, seq = 0; frame < num_init_frames; frame++, seq += 2) {
1170 /* Push a couple of packets with identical timestamp, typical for a video
1171 * stream where one frame generates multiple packets. */
1172 gst_harness_set_time (h, frame * frame_dur);
1173 gst_harness_push (h, generate_test_buffer_full (frame * frame_dur,
1174 seq, frame * frame_rtp_ts_dur));
1175 gst_harness_push (h, generate_test_buffer_full (frame * frame_dur,
1176 seq + 1, frame * frame_rtp_ts_dur));
1177
1178 if (frame == 0)
1179 /* deadline for buffer 0 expires */
1180 gst_harness_crank_single_clock_wait (h);
1181
1182 gst_buffer_unref (gst_harness_pull (h));
1183 gst_buffer_unref (gst_harness_pull (h));
1184 }
1185
1186 /* Finally push the last frame reordered */
1187 gst_harness_set_time (h, frame * frame_dur);
1188 gst_harness_push (h, generate_test_buffer_full (frame * frame_dur,
1189 seq + 1, frame * frame_rtp_ts_dur));
1190
1191 /* Check the scheduled lost timer. The expected arrival of this packet
1192 * should be assumed to be the same as the last packet received since we
1193 * don't know wether the missing packet belonged to this or previous
1194 * frame. */
1195 gst_test_clock_wait_for_next_pending_id (testclock, &pending_id);
1196 time = gst_clock_id_get_time (pending_id);
1197 fail_unless_equals_int64 (time, frame * frame_dur + latency_ms * GST_MSECOND);
1198 gst_clock_id_unref (pending_id);
1199
1200 /* And then missing packet arrives just in time */
1201 gst_harness_set_time (h, time - 1);
1202 gst_harness_push (h, generate_test_buffer_full (time - 1, seq,
1203 frame * frame_rtp_ts_dur));
1204
1205 gst_buffer_unref (gst_harness_pull (h));
1206 gst_buffer_unref (gst_harness_pull (h));
1207
1208 gst_object_unref (testclock);
1209 gst_harness_teardown (h);
1210 }
1211
1212 GST_END_TEST;
1213
GST_START_TEST(test_loss_equidistant_spacing_with_parameter_packets)1214 GST_START_TEST (test_loss_equidistant_spacing_with_parameter_packets)
1215 {
1216 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1217 gint latency_ms = 5;
1218 gint seq, frame;
1219 gint num_init_frames = 10;
1220 gint i;
1221
1222 gst_harness_set_src_caps (h, generate_caps ());
1223 g_object_set (h->element, "do-lost", TRUE, "latency", latency_ms, NULL);
1224
1225 /* drop stream-start, caps, segment */
1226 for (i = 0; i < 3; i++)
1227 gst_event_unref (gst_harness_pull_event (h));
1228
1229 for (frame = 0, seq = 0; frame < num_init_frames; frame++, seq++) {
1230 gst_harness_set_time (h, frame * TEST_BUF_DURATION);
1231 gst_harness_push (h, generate_test_buffer_full (frame * TEST_BUF_DURATION,
1232 seq, frame * TEST_RTP_TS_DURATION));
1233
1234 if (frame == 0)
1235 /* deadline for buffer 0 expires */
1236 gst_harness_crank_single_clock_wait (h);
1237
1238 gst_buffer_unref (gst_harness_pull (h));
1239 }
1240
1241 /* Push three packets with same rtptime, simulating parameter packets +
1242 * frame. This should not disable equidistant mode as it is common for
1243 * certain audio codecs. */
1244 for (i = 0; i < 3; i++) {
1245 gst_harness_set_time (h, frame * TEST_BUF_DURATION);
1246 gst_harness_push (h, generate_test_buffer_full (frame * TEST_BUF_DURATION,
1247 seq++, frame * TEST_RTP_TS_DURATION));
1248 gst_buffer_unref (gst_harness_pull (h));
1249 }
1250 frame++;
1251
1252 /* Finally push the last packet introducing a gap */
1253 gst_harness_set_time (h, frame * TEST_BUF_DURATION);
1254 gst_harness_push (h, generate_test_buffer_full (frame * TEST_BUF_DURATION,
1255 seq + 1, frame * TEST_RTP_TS_DURATION));
1256
1257 /* given that the last known PTS (pkt#12) was 200ms and this last PTS (pkt#14) was 220ms,
1258 and our current packet-spacing is 20ms, the lost-event gets a problem here:
1259 If we use our packet-spacing, the last pushed packet (#12) should have
1260 a duration of 20ms, meaning we would expect the missing packet (#13) to
1261 have a PTS of 220ms. However, packet #14 comes in at 220ms, so what is
1262 the best estimation for the missing packet here?
1263
1264 Given that we want to estimate the most optimistic PTS in order to give
1265 the packet as many chances as possible to arrive, we end up with a PTS
1266 of 220ms and a duration of 0, since that will be the most optimistic
1267 placement given that it has to be before pkt #14.
1268 */
1269
1270 /* timeout the lost-event */
1271 gst_harness_crank_single_clock_wait (h);
1272 verify_lost_event (h, seq, frame * TEST_BUF_DURATION, 0);
1273
1274 gst_buffer_unref (gst_harness_pull (h));
1275
1276 gst_harness_teardown (h);
1277 }
1278
1279 GST_END_TEST;
1280
1281
1282 typedef struct
1283 {
1284 guint gap;
1285 GstClockTime duration[3];
1286 } ThreeLostPackets;
1287
1288 ThreeLostPackets no_fractional_lost_event_durations_input[] = {
1289 {5, {60 * GST_MSECOND, 20 * GST_MSECOND, 20 * GST_MSECOND}},
1290 {4, {40 * GST_MSECOND, 20 * GST_MSECOND, 20 * GST_MSECOND}},
1291 {3, {20 * GST_MSECOND, 20 * GST_MSECOND, 20 * GST_MSECOND}},
1292 {2, {20 * GST_MSECOND, 20 * GST_MSECOND, 0 * GST_MSECOND}},
1293 {1, {20 * GST_MSECOND, 0 * GST_MSECOND, 0 * GST_MSECOND}},
1294 {0, {0 * GST_MSECOND, 0 * GST_MSECOND, 0 * GST_MSECOND}},
1295 };
1296
1297 /* This test looks after that fact that when we have equidistant
1298 packetspacing, we try and keep that spacing for the lost events,
1299 so we operate in "whole" packets.
1300 */
GST_START_TEST(test_no_fractional_lost_event_durations)1301 GST_START_TEST (test_no_fractional_lost_event_durations)
1302 {
1303 ThreeLostPackets *ctx = &no_fractional_lost_event_durations_input[__i__];
1304
1305 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1306 GstClockTime now;
1307 guint latency_ms = 100;
1308 guint16 seqnum, gap_seqnum;
1309 GstClockTime pts;
1310 GstClockTime duration;
1311
1312 g_object_set (h->element, "do-lost", TRUE, NULL);
1313 seqnum = construct_deterministic_initial_state (h, latency_ms);
1314 gap_seqnum = seqnum + ctx->gap;
1315
1316 now = gap_seqnum * TEST_BUF_DURATION;
1317 gst_harness_set_time (h, now);
1318 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1319 generate_test_buffer_full (now,
1320 seqnum + 3, gap_seqnum * TEST_RTP_TS_DURATION)));
1321
1322 pts = seqnum * TEST_BUF_DURATION;
1323 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1324 /* check if the lost-event has expired, if not
1325 crank to move the time ahead */
1326 if (pts + latency_ms * GST_MSECOND > now)
1327 gst_harness_crank_single_clock_wait (h);
1328 duration = ctx->duration[0];
1329 verify_lost_event (h, seqnum, pts, duration);
1330
1331 seqnum++;
1332 pts += duration;
1333 duration = ctx->duration[1];
1334 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1335 if (pts + latency_ms * GST_MSECOND > now)
1336 gst_harness_crank_single_clock_wait (h);
1337 verify_lost_event (h, seqnum, pts, duration);
1338
1339 seqnum++;
1340 pts += duration;
1341 duration = ctx->duration[2];
1342 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1343 if (pts + latency_ms * GST_MSECOND > now)
1344 gst_harness_crank_single_clock_wait (h);
1345 verify_lost_event (h, seqnum, pts, duration);
1346
1347 /* followed by the buffer */
1348 gst_buffer_unref (gst_harness_pull (h));
1349 /* verify that we have pulled out all waiting buffers and events */
1350 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h));
1351 fail_unless_equals_int (0, gst_harness_events_in_queue (h));
1352
1353 gst_harness_teardown (h);
1354 }
1355
1356 GST_END_TEST;
1357
GST_START_TEST(test_late_lost_with_same_pts)1358 GST_START_TEST (test_late_lost_with_same_pts)
1359 {
1360 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1361 GstClockTime dts, now;
1362 guint latency_ms = 40;
1363 guint16 seqnum;
1364 guint rtp_ts;
1365
1366 g_object_set (h->element, "do-lost", TRUE, NULL);
1367 seqnum = construct_deterministic_initial_state (h, latency_ms);
1368
1369 dts = seqnum * TEST_BUF_DURATION;
1370 rtp_ts = seqnum * TEST_RTP_TS_DURATION;
1371
1372 /* set the time on the clock one buffer-length after the
1373 length of the jitterbuffer */
1374 now = dts + latency_ms * GST_MSECOND + TEST_BUF_DURATION;
1375 gst_test_clock_set_time (GST_TEST_CLOCK (GST_ELEMENT_CLOCK (h->element)),
1376 now);
1377
1378 /* now two buffers arrive, same arrival time (in the past, must
1379 have spent a lot of time from udpsrc to jitterbuffer!),
1380 with the same rtptimestamp (typical of videobuffers),
1381 with a gap in between them */
1382 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1383 generate_test_buffer_full (dts, seqnum, rtp_ts)));
1384
1385 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1386 generate_test_buffer_full (dts, seqnum + 2, rtp_ts)));
1387
1388 /* the lost event is generated immediately since we are already
1389 too late to wait for anything */
1390 verify_lost_event (h, seqnum + 1, dts, 0);
1391 gst_buffer_unref (gst_harness_pull (h));
1392 gst_buffer_unref (gst_harness_pull (h));
1393
1394 /* verify that we have pulled out all waiting buffers and events */
1395 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h));
1396 fail_unless_equals_int (0, gst_harness_events_in_queue (h));
1397
1398 gst_harness_teardown (h);
1399 }
1400
1401 GST_END_TEST;
1402
1403 static void
gst_test_clock_set_time_and_process(GstTestClock * testclock,GstClockTime time)1404 gst_test_clock_set_time_and_process (GstTestClock * testclock,
1405 GstClockTime time)
1406 {
1407 GstClockID id, tid;
1408 gst_test_clock_wait_for_next_pending_id (testclock, &id);
1409 gst_test_clock_set_time (testclock, time);
1410 tid = gst_test_clock_process_next_clock_id (testclock);
1411 g_assert (tid == id);
1412 gst_clock_id_unref (tid);
1413 gst_clock_id_unref (id);
1414 }
1415
GST_START_TEST(test_rtx_expected_next)1416 GST_START_TEST (test_rtx_expected_next)
1417 {
1418 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1419 gint latency_ms = 200;
1420 guint next_seqnum;
1421 GstClockTime timeout;
1422 gint rtx_delay_ms;
1423 const GstClockTime rtx_retry_timeout_ms = 40;
1424
1425 g_object_set (h->element, "do-lost", TRUE, NULL);
1426 g_object_set (h->element, "do-retransmission", TRUE, NULL);
1427 g_object_set (h->element, "rtx-retry-period", 120, NULL);
1428 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1429
1430 /* At this point there is already existing a rtx-timer for @next_seqnum,
1431 * that will have a timeout of the expected arrival-time for that seqnum,
1432 * and a delay equal to 2*jitter==0 and 0.5*packet_spacing==10ms */
1433 timeout = next_seqnum * TEST_BUF_DURATION;
1434 rtx_delay_ms = TEST_BUF_MS / 2;
1435
1436 /* We crank the clock to time-out the next scheduled timer */
1437 gst_harness_crank_single_clock_wait (h);
1438 verify_rtx_event (h, next_seqnum, timeout, rtx_delay_ms, TEST_BUF_DURATION);
1439
1440 /* now we wait for the next timeout, all following timeouts 40ms in the
1441 * future because this is rtx-retry-timeout */
1442 rtx_delay_ms += rtx_retry_timeout_ms;
1443 gst_harness_crank_single_clock_wait (h);
1444 verify_rtx_event (h, next_seqnum, timeout, rtx_delay_ms, TEST_BUF_DURATION);
1445
1446 /* And a third time... */
1447 rtx_delay_ms += rtx_retry_timeout_ms;
1448 gst_harness_crank_single_clock_wait (h);
1449 verify_rtx_event (h, next_seqnum, timeout, rtx_delay_ms, TEST_BUF_DURATION);
1450
1451 /* we should now receive a packet-lost-event for packet @next_seqnum */
1452 gst_harness_crank_single_clock_wait (h);
1453 verify_lost_event (h, next_seqnum, timeout, TEST_BUF_DURATION);
1454
1455 gst_harness_teardown (h);
1456 }
1457
1458 GST_END_TEST;
1459
GST_START_TEST(test_rtx_not_bursting_requests)1460 GST_START_TEST (test_rtx_not_bursting_requests)
1461 {
1462 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1463 gint latency_ms = 200;
1464 guint next_seqnum;
1465 guint missing_seqnum;
1466 GstClockTime now;
1467
1468 g_object_set (h->element,
1469 "do-lost", TRUE,
1470 "do-retransmission", TRUE,
1471 "rtx-next-seqnum", FALSE, "rtx-max-retries", 3, NULL);
1472
1473 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1474 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1475
1476 /* skip a packet and move the time for the next one
1477 quite a bit forward */
1478 missing_seqnum = next_seqnum;
1479 next_seqnum++;
1480 now += 150 * GST_MSECOND;
1481 gst_harness_set_time (h, now);
1482
1483 push_test_buffer_now (h, next_seqnum, next_seqnum * TEST_RTP_TS_DURATION,
1484 FALSE);
1485
1486 /* note the delay here is 130. This is because we advanced the clock 150,
1487 and 20 of those were the duration of the missing seqnum, so this
1488 RTX event is in effect 130ms "late" compared to its ideal time */
1489 verify_rtx_event (h, missing_seqnum,
1490 missing_seqnum * TEST_BUF_DURATION, 130, TEST_BUF_DURATION);
1491
1492 /* verify we have not sent any other rtx events */
1493 fail_unless_equals_int (0, gst_harness_upstream_events_in_queue (h));
1494
1495 gst_harness_teardown (h);
1496 }
1497
1498 GST_END_TEST;
1499
GST_START_TEST(test_rtx_next_seqnum_disabled)1500 GST_START_TEST (test_rtx_next_seqnum_disabled)
1501 {
1502 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1503 gint latency_ms = 200;
1504 guint next_seqnum, missing_seqnum;
1505 GstTestClock *testclock;
1506 GstClockTime timeout, last_rtx_request;
1507 gint rtx_delay_ms;
1508 const GstClockTime rtx_retry_timeout_ms = 40;
1509
1510 testclock = gst_harness_get_testclock (h);
1511
1512 g_object_set (h->element, "do-lost", TRUE, NULL);
1513 g_object_set (h->element, "do-retransmission", TRUE, NULL);
1514 g_object_set (h->element, "rtx-retry-period", 120, NULL);
1515 g_object_set (h->element, "rtx-next-seqnum", FALSE, NULL);
1516
1517 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1518
1519 /* When rtx-next-seqnum is disabled there is no existing rtx-timer for
1520 * @next_seqnum until there is a gap and it's missing. */
1521
1522 /* Check that we have no pending waits */
1523 fail_unless_equals_int (0, gst_test_clock_peek_id_count (testclock));
1524
1525 /* Push next packet to create a gap and trigger rtx-timers */
1526 missing_seqnum = next_seqnum;
1527 next_seqnum += 1;
1528 push_test_buffer (h, next_seqnum);
1529
1530 /* Now there should exist a rtx-timer for @next_seqnum, that will have a
1531 * timeout of the expected arrival-time for that seqnum, and a delay equal
1532 * to the elapsed time since the timeout and until now (which is the
1533 * duration of one buffer, 20 ms). */
1534 timeout = missing_seqnum * TEST_BUF_DURATION;
1535 rtx_delay_ms = TEST_BUF_MS;
1536
1537 /* The first rtx-event is triggered immediately since the timeout + delay is
1538 * less than "now" */
1539 verify_rtx_event (h, missing_seqnum, timeout, rtx_delay_ms,
1540 TEST_BUF_DURATION);
1541 last_rtx_request = gst_clock_get_time (GST_CLOCK (testclock));
1542 fail_unless_equals_int64 (last_rtx_request,
1543 missing_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1544
1545 /* now we wait for the next timeout, all following timers timeout in 40ms
1546 * increments because this is rtx-retry-timeout */
1547 rtx_delay_ms += rtx_retry_timeout_ms;
1548 gst_harness_crank_single_clock_wait (h);
1549 verify_rtx_event (h, missing_seqnum, timeout, rtx_delay_ms,
1550 TEST_BUF_DURATION);
1551 last_rtx_request = gst_clock_get_time (GST_CLOCK (testclock));
1552 fail_unless_equals_int64 (last_rtx_request,
1553 missing_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1554
1555 /* And a third time... */
1556 rtx_delay_ms += rtx_retry_timeout_ms;
1557 gst_harness_crank_single_clock_wait (h);
1558 verify_rtx_event (h, missing_seqnum, timeout, rtx_delay_ms,
1559 TEST_BUF_DURATION);
1560 last_rtx_request = gst_clock_get_time (GST_CLOCK (testclock));
1561 fail_unless_equals_int64 (last_rtx_request,
1562 missing_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1563
1564 /* we should now receive a packet-lost-event for packet @missing_seqnum */
1565 gst_harness_crank_single_clock_wait (h);
1566 verify_lost_event (h, missing_seqnum, timeout, TEST_BUF_DURATION);
1567
1568 /* Finally pull out the next packet */
1569 gst_buffer_unref (gst_harness_pull (h));
1570
1571 gst_object_unref (testclock);
1572 gst_harness_teardown (h);
1573 }
1574
1575 GST_END_TEST;
1576
GST_START_TEST(test_rtx_two_missing)1577 GST_START_TEST (test_rtx_two_missing)
1578 {
1579 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1580 gint latency_ms = 200;
1581 guint next_seqnum;
1582 GstClockTime last_rtx_request, now;
1583 gint rtx_delay_ms_0 = TEST_BUF_MS / 2;
1584 gint rtx_delay_ms_1 = TEST_BUF_MS;
1585
1586 g_object_set (h->element, "do-retransmission", TRUE, NULL);
1587 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1588 fail_unless_equals_int (11, next_seqnum);
1589
1590 /*
1591 * The expected sequence of buffers is this:
1592 * ____ ____ ____ ____
1593 * ... | 10 | | 11 | | 12 | | 13 |
1594 * –––– –––– –––– ––––
1595 * 200ms 220ms 240ms 260ms
1596 *
1597 * But instead we get this:
1598 * ____ _ _ _ _ ____
1599 * ... | 10 | | | | | | 13 |
1600 * –––– - - - - ––––
1601 * 200ms 260ms
1602 *
1603 * Now it is important to note that the next thing that happens is that
1604 * the RTX timeout for packet 11 will happen at time 230ms, so we crank
1605 * the timer thread to advance the time to this:
1606 */
1607 gst_harness_crank_single_clock_wait (h);
1608 verify_rtx_event (h, 11, 11 * TEST_BUF_DURATION,
1609 rtx_delay_ms_0, TEST_BUF_DURATION);
1610 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1611 fail_unless_equals_int64 (last_rtx_request,
1612 11 * TEST_BUF_DURATION + rtx_delay_ms_0 * GST_MSECOND);
1613 gst_harness_wait_for_clock_id_waits (h, 1, 60);
1614
1615 /* The next scheduled RTX for packet 11 is now at 230 + 40 = 270ms,
1616 so the next thing that happens is that buffer 13 arrives in perfect time: */
1617 now = 13 * TEST_BUF_DURATION;
1618 gst_harness_set_time (h, now);
1619 fail_unless_equals_int (GST_FLOW_OK,
1620 gst_harness_push (h,
1621 generate_test_buffer_full (now, 13, 13 * TEST_RTP_TS_DURATION)));
1622
1623 /*
1624 *
1625 * This will estimate the dts on the two missing packets to:
1626 * ____ ____
1627 * ... | 11 | | 12 | ...
1628 * –––– ––––
1629 * 220ms 240ms
1630 *
1631 * And given their regular interspacing of 20ms, it will schedule two RTX
1632 * timers for them like so:
1633 *
1634 * ____ ____
1635 * ... | 11 | | 12 | ...
1636 * –––– ––––
1637 * 230ms 250ms
1638 *
1639 * There are however two problems, packet 11 we have already sent one RTX for
1640 * and its timeout is currently at 270ms, so we should not tamper with that,
1641 * and as for packet 12, 250ms has already expired, so we now expect to see
1642 * an rtx-event being sent for packet 12 immediately.
1643 *
1644 * Since the current time is 260 ms and packet 12 was expected at 240 ms,
1645 * the delay of the rtx-event is 20 ms.
1646 */
1647 verify_rtx_event (h, 12, 12 * TEST_BUF_DURATION,
1648 rtx_delay_ms_1, TEST_BUF_DURATION);
1649 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1650 fail_unless_equals_int64 (last_rtx_request,
1651 12 * TEST_BUF_DURATION + rtx_delay_ms_1 * GST_MSECOND);
1652
1653 /* and another crank will see the second RTX event being sent for packet 11 */
1654 gst_harness_crank_single_clock_wait (h);
1655 rtx_delay_ms_0 += 40;
1656 verify_rtx_event (h, 11, 11 * TEST_BUF_DURATION,
1657 rtx_delay_ms_0, TEST_BUF_DURATION);
1658 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1659 fail_unless_equals_int64 (last_rtx_request,
1660 11 * TEST_BUF_DURATION + rtx_delay_ms_0 * GST_MSECOND);
1661
1662 gst_harness_teardown (h);
1663 }
1664
1665 GST_END_TEST;
1666
GST_START_TEST(test_rtx_buffer_arrives_just_in_time)1667 GST_START_TEST (test_rtx_buffer_arrives_just_in_time)
1668 {
1669 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1670 gint latency_ms = 5 * TEST_BUF_MS;
1671 gint next_seqnum;
1672 GstBuffer *buffer;
1673 GstClockTime now, last_rtx_request;
1674 gint rtx_delay_ms = TEST_BUF_MS / 2;
1675
1676 g_object_set (h->element, "do-retransmission", TRUE,
1677 "rtx-max-retries", 1, NULL);
1678 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1679
1680 /* Crank clock to send retransmission events requesting seqnum 6 which has
1681 * not arrived yet. */
1682 gst_harness_crank_single_clock_wait (h);
1683 verify_rtx_event (h, next_seqnum,
1684 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1685
1686 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1687 fail_unless_equals_int64 (last_rtx_request,
1688 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1689
1690 /* seqnum 6 arrives just before it times out and is considered lost */
1691 now = 200 * GST_MSECOND;
1692 gst_harness_set_time (h, now);
1693 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1694 generate_test_buffer_rtx (now, next_seqnum)));
1695 buffer = gst_harness_pull (h);
1696 fail_unless_equals_int (next_seqnum, get_rtp_seq_num (buffer));
1697 gst_buffer_unref (buffer);
1698
1699 fail_unless (verify_jb_stats (h->element,
1700 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1701 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 1,
1702 "num-lost", G_TYPE_UINT64, (guint64) 0,
1703 "rtx-count", G_TYPE_UINT64, (guint64) 1,
1704 "rtx-success-count", G_TYPE_UINT64, (guint64) 1,
1705 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1706 "rtx-rtt", G_TYPE_UINT64, (guint64) (now - last_rtx_request),
1707 NULL)));
1708
1709 gst_harness_teardown (h);
1710 }
1711
1712 GST_END_TEST;
1713
GST_START_TEST(test_rtx_buffer_arrives_too_late)1714 GST_START_TEST (test_rtx_buffer_arrives_too_late)
1715 {
1716 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1717 gint latency_ms = 5 * TEST_BUF_MS;
1718 gint next_seqnum;
1719 GstClockTime now, last_rtx_request;
1720 gint rtx_delay_ms = TEST_BUF_MS / 2;
1721
1722 g_object_set (h->element, "do-retransmission", TRUE,
1723 "do-lost", TRUE, "rtx-max-retries", 1, NULL);
1724 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1725
1726 /* Crank clock to send retransmission events requesting seqnum 6 which has
1727 * not arrived yet. */
1728 gst_harness_crank_single_clock_wait (h);
1729 verify_rtx_event (h, next_seqnum,
1730 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1731
1732 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1733 fail_unless_equals_int64 (last_rtx_request,
1734 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1735
1736 /* packet @next_seqnum is considered lost */
1737 gst_harness_crank_single_clock_wait (h);
1738 verify_lost_event (h, next_seqnum,
1739 next_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION);
1740
1741 /* packet @next_seqnum arrives too late */
1742 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1743 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1744 generate_test_buffer_rtx (now, next_seqnum)));
1745
1746 fail_unless (verify_jb_stats (h->element,
1747 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1748 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1749 "num-lost", G_TYPE_UINT64, (guint64) 1,
1750 "num-late", G_TYPE_UINT64, (guint64) 1,
1751 "num-duplicates", G_TYPE_UINT64, (guint64) 0,
1752 "rtx-count", G_TYPE_UINT64, (guint64) 1,
1753 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1754 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1755 "rtx-rtt", G_TYPE_UINT64, (guint64) (now - last_rtx_request),
1756 NULL)));
1757
1758 gst_harness_teardown (h);
1759 }
1760
1761 GST_END_TEST;
1762
GST_START_TEST(test_rtx_original_buffer_does_not_update_rtx_stats)1763 GST_START_TEST (test_rtx_original_buffer_does_not_update_rtx_stats)
1764 {
1765 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1766 gint latency_ms = 100;
1767 gint next_seqnum;
1768 GstBuffer *buffer;
1769 GstClockTime now, last_rtx_request;
1770 gint rtx_delay_ms = TEST_BUF_MS / 2;
1771
1772 g_object_set (h->element, "do-retransmission", TRUE,
1773 "rtx-max-retries", 1, NULL);
1774 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1775 fail_unless_equals_int (6, next_seqnum);
1776
1777 /* Crank clock to send retransmission events requesting @next_seqnum which has
1778 * not arrived yet. */
1779 gst_harness_crank_single_clock_wait (h);
1780 verify_rtx_event (h, next_seqnum,
1781 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1782
1783 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1784 fail_unless_equals_int64 (last_rtx_request,
1785 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1786
1787 /* make sure the wait has settled before moving on */
1788 gst_harness_wait_for_clock_id_waits (h, 1, 1);
1789
1790 /* ORIGINAL seqnum 6 arrives just before it times out and is considered
1791 * lost. */
1792 now = 200 * GST_MSECOND;
1793 gst_harness_set_time (h, now);
1794 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1795 generate_test_buffer_full (now,
1796 next_seqnum, next_seqnum * TEST_RTP_TS_DURATION)));
1797 buffer = gst_harness_pull (h);
1798 fail_unless_equals_int (next_seqnum, get_rtp_seq_num (buffer));
1799 gst_buffer_unref (buffer);
1800
1801 /* due to the advance in time, we will now also have sent
1802 an rtx-request for 7 */
1803 next_seqnum++;
1804 verify_rtx_event (h, next_seqnum,
1805 next_seqnum * TEST_BUF_DURATION, 60, TEST_BUF_DURATION);
1806
1807 /* The original buffer does not count in the RTX stats. */
1808 fail_unless (verify_jb_stats (h->element,
1809 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1810 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1811 "num-lost", G_TYPE_UINT64, (guint64) 0,
1812 "num-late", G_TYPE_UINT64, (guint64) 0,
1813 "num-duplicates", G_TYPE_UINT64, (guint64) 0,
1814 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1815 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1816 "rtx-per-packet", G_TYPE_DOUBLE, 0.0,
1817 "rtx-rtt", G_TYPE_UINT64, (guint64) 0, NULL)));
1818
1819 /* Now the retransmitted packet arrives and stats should be updated. Note
1820 * that the buffer arrives in time and should not be considered late, but
1821 * a duplicate. */
1822 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1823 generate_test_buffer_rtx (now, 6)));
1824
1825 fail_unless (verify_jb_stats (h->element,
1826 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1827 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1828 "num-lost", G_TYPE_UINT64, (guint64) 0,
1829 "num-late", G_TYPE_UINT64, (guint64) 0,
1830 "num-duplicates", G_TYPE_UINT64, (guint64) 1,
1831 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1832 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1833 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1834 "rtx-rtt", G_TYPE_UINT64, (guint64) (now - last_rtx_request),
1835 NULL)));
1836
1837 gst_harness_teardown (h);
1838 }
1839
1840 GST_END_TEST;
1841
GST_START_TEST(test_rtx_duplicate_packet_updates_rtx_stats)1842 GST_START_TEST (test_rtx_duplicate_packet_updates_rtx_stats)
1843 {
1844 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1845 gint latency_ms = 100;
1846 gint next_seqnum;
1847 GstClockTime now, rtx_request_6, rtx_request_7;
1848 gint rtx_delay_ms = TEST_BUF_MS / 2;
1849 gint i;
1850
1851 g_object_set (h->element, "do-retransmission", TRUE, NULL);
1852 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1853 fail_unless_equals_int (6, next_seqnum);
1854
1855 /* Push packet 8 so that 6 and 7 is missing */
1856 fail_unless_equals_int (GST_FLOW_OK,
1857 gst_harness_push (h, generate_test_buffer (8)));
1858
1859 /* Wait for NACKs on 6 and 7 */
1860 gst_harness_crank_single_clock_wait (h);
1861 verify_rtx_event (h, 6, 6 * TEST_BUF_DURATION,
1862 rtx_delay_ms, TEST_BUF_DURATION);
1863 rtx_request_6 = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1864 fail_unless_equals_int64 (rtx_request_6,
1865 6 * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1866
1867 gst_harness_crank_single_clock_wait (h);
1868 verify_rtx_event (h,
1869 7, 7 * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1870 rtx_request_7 = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1871 fail_unless_equals_int64 (rtx_request_7,
1872 7 * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1873
1874 /* Original packet 7 arrives */
1875 now = 161 * GST_MSECOND;
1876 gst_harness_set_time (h, now);
1877 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1878 generate_test_buffer_full (now, 7, 7 * TEST_RTP_TS_DURATION)));
1879
1880 /* We're still waiting for packet 6, so 7 should not be pushed */
1881 gst_harness_wait_for_clock_id_waits (h, 1, 60);
1882 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1883
1884 /* The original buffer does not count in the RTX stats. */
1885 fail_unless (verify_jb_stats (h->element,
1886 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1887 "num-lost", G_TYPE_UINT64, (guint64) 0,
1888 "num-late", G_TYPE_UINT64, (guint64) 0,
1889 "num-duplicates", G_TYPE_UINT64, (guint64) 0,
1890 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1891 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1892 "rtx-per-packet", G_TYPE_DOUBLE, 0.0,
1893 "rtx-rtt", G_TYPE_UINT64, (guint64) 0, NULL)));
1894
1895 /* Push RTX packet 7. Should be dropped as duplicate but update RTX stats. */
1896 now = 162 * GST_MSECOND;
1897 gst_harness_set_time (h, now);
1898 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1899 generate_test_buffer_rtx (now, 7)));
1900 gst_harness_wait_for_clock_id_waits (h, 1, 60);
1901 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1902
1903 /* Check RTX stats with updated num-duplicates and rtx-rtt fields */
1904 fail_unless (verify_jb_stats (h->element,
1905 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1906 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1907 "num-lost", G_TYPE_UINT64, (guint64) 0,
1908 "num-late", G_TYPE_UINT64, (guint64) 0,
1909 "num-duplicates", G_TYPE_UINT64, (guint64) 1,
1910 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1911 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1912 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1913 "rtx-rtt", G_TYPE_UINT64, (guint64) (now - rtx_request_7),
1914 NULL)));
1915
1916 /* RTX packet 6 arrives, both 6, 7 and 8 is ready to be pulled */
1917 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1918 generate_test_buffer_rtx (now, 6)));
1919
1920 for (i = 6; i <= 8; i++) {
1921 GstBuffer *buf = gst_harness_pull (h);
1922 fail_unless_equals_int (i, get_rtp_seq_num (buf));
1923 gst_buffer_unref (buf);
1924 }
1925
1926 /* RTX stats is updated with success count increased. */
1927 fail_unless (verify_jb_stats (h->element,
1928 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1929 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 3,
1930 "num-lost", G_TYPE_UINT64, (guint64) 0,
1931 "num-late", G_TYPE_UINT64, (guint64) 0,
1932 "num-duplicates", G_TYPE_UINT64, (guint64) 1,
1933 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1934 "rtx-success-count", G_TYPE_UINT64, (guint64) 1,
1935 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1936 "rtx-rtt", G_TYPE_UINT64, (guint64)
1937 /* Use the rtx-rtt formula. Can be subject to change though. */
1938 ((now - rtx_request_6) + 47 * (now - rtx_request_7)) / 48,
1939 NULL)));
1940
1941 gst_harness_teardown (h);
1942 }
1943
1944 GST_END_TEST;
1945
GST_START_TEST(test_rtx_buffer_arrives_after_lost_updates_rtx_stats)1946 GST_START_TEST (test_rtx_buffer_arrives_after_lost_updates_rtx_stats)
1947 {
1948 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1949 gint latency_ms = 100;
1950 gint next_seqnum;
1951 GstClockTime now, last_rtx_request;
1952 gint rtx_delay_ms = TEST_BUF_MS / 2;
1953
1954 g_object_set (h->element, "do-retransmission", TRUE,
1955 "do-lost", TRUE, "rtx-max-retries", 1, NULL);
1956 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1957
1958 /* Crank clock to send retransmission events requesting seqnum 6 which has
1959 * not arrived yet. */
1960 gst_harness_crank_single_clock_wait (h);
1961 verify_rtx_event (h, next_seqnum,
1962 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1963
1964 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1965 fail_unless_equals_int64 (last_rtx_request,
1966 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1967
1968 /* seqnum 6 is considered lost */
1969 gst_harness_crank_single_clock_wait (h);
1970 verify_lost_event (h, next_seqnum,
1971 next_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION);
1972
1973 /* seqnum 6 arrives too late */
1974 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1975 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1976 generate_test_buffer_rtx (now, next_seqnum)));
1977
1978 fail_unless (verify_jb_stats (h->element,
1979 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1980 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1981 "num-lost", G_TYPE_UINT64, (guint64) 1,
1982 "num-late", G_TYPE_UINT64, (guint64) 1,
1983 "num-duplicates", G_TYPE_UINT64, (guint64) 0,
1984 "rtx-count", G_TYPE_UINT64, (guint64) 1,
1985 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1986 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1987 "rtx-rtt", G_TYPE_UINT64, (guint64) (now - last_rtx_request),
1988 NULL)));
1989
1990 gst_harness_teardown (h);
1991 }
1992
1993 GST_END_TEST;
1994
GST_START_TEST(test_rtx_rtt_larger_than_retry_timeout)1995 GST_START_TEST (test_rtx_rtt_larger_than_retry_timeout)
1996 {
1997 /* When RTT is larger than retry period we will send two or more requests
1998 * before receiving any retransmission packets */
1999 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2000 gint latency_ms = 100;
2001 gint next_seqnum;
2002 gint rtx_retry_timeout_ms = 20;
2003 gint rtx_delay_ms = TEST_BUF_MS / 2;
2004 gint rtt = rtx_retry_timeout_ms * GST_MSECOND + 1;
2005 GstClockTime now, first_request, second_request;
2006
2007 g_object_set (h->element, "do-retransmission", TRUE,
2008 "rtx-retry-timeout", rtx_retry_timeout_ms, NULL);
2009 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
2010
2011 /* Wait for first NACK on 6 */
2012 gst_harness_crank_single_clock_wait (h);
2013 verify_rtx_event (h, next_seqnum,
2014 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
2015 first_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
2016 fail_unless_equals_int64 (first_request,
2017 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
2018
2019 /* Packet @next_seqnum + 1 arrives in time (so that we avoid its EXPECTED
2020 * timers to interfer with our test) */
2021 push_test_buffer (h, next_seqnum + 1);
2022
2023 /* Simulating RTT > rtx-retry-timeout, we send a new NACK before receiving
2024 * the RTX packet. Wait for second NACK on @next_seqnum */
2025 gst_harness_crank_single_clock_wait (h);
2026 rtx_delay_ms += rtx_retry_timeout_ms;
2027 verify_rtx_event (h, next_seqnum,
2028 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
2029 second_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
2030 fail_unless_equals_int64 (second_request,
2031 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
2032
2033 /* The first retransmitted packet arrives */
2034 now = first_request + rtt;
2035 gst_harness_set_time (h, now);
2036 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
2037 generate_test_buffer_rtx (now, next_seqnum)));
2038
2039 /* Pull packets @next_seqnum and @next_seqnum + 1 */
2040 gst_buffer_unref (gst_harness_pull (h));
2041 gst_buffer_unref (gst_harness_pull (h));
2042
2043 /* Stats should be updated. Note that RTT is not updated since we cannot be
2044 * sure whether the RTX packet is in response to the first or second NACK. */
2045 fail_unless (verify_jb_stats (h->element,
2046 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
2047 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 2,
2048 "num-lost", G_TYPE_UINT64, (guint64) 0,
2049 "num-late", G_TYPE_UINT64, (guint64) 0,
2050 "num-duplicates", G_TYPE_UINT64, (guint64) 0,
2051 "rtx-count", G_TYPE_UINT64, (guint64) 2,
2052 "rtx-success-count", G_TYPE_UINT64, (guint64) 1,
2053 "rtx-per-packet", G_TYPE_DOUBLE, 2.0,
2054 "rtx-rtt", G_TYPE_UINT64, (guint64) 0, NULL)));
2055
2056 /* Packet @next_seqnum + 2 arrives in time */
2057 push_test_buffer (h, next_seqnum + 2);
2058 gst_buffer_unref (gst_harness_pull (h));
2059
2060 /* Now the second retransmitted packet arrives */
2061 now = second_request + rtt;
2062 gst_harness_set_time (h, now);
2063 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
2064 generate_test_buffer_rtx (now, next_seqnum)));
2065
2066 /* The stats is updated with the correct RTT. */
2067 fail_unless (verify_jb_stats (h->element,
2068 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
2069 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 3,
2070 "num-lost", G_TYPE_UINT64, (guint64) 0,
2071 "num-late", G_TYPE_UINT64, (guint64) 0,
2072 "num-duplicates", G_TYPE_UINT64, (guint64) 1,
2073 "rtx-count", G_TYPE_UINT64, (guint64) 2,
2074 "rtx-success-count", G_TYPE_UINT64, (guint64) 1,
2075 "rtx-per-packet", G_TYPE_DOUBLE, 2.0,
2076 "rtx-rtt", G_TYPE_UINT64, (guint64) rtt, NULL)));
2077
2078 gst_harness_teardown (h);
2079 }
2080
2081 GST_END_TEST;
2082
GST_START_TEST(test_rtx_no_request_if_time_past_retry_period)2083 GST_START_TEST (test_rtx_no_request_if_time_past_retry_period)
2084 {
2085 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2086 const gint latency_ms = 200;
2087 const gint retry_period_ms = 120;
2088 GstTestClock *testclock;
2089 GstClockID pending_id;
2090 GstClockTime time;
2091 gint i;
2092
2093 gst_harness_set_src_caps (h, generate_caps ());
2094 testclock = gst_harness_get_testclock (h);
2095
2096 g_object_set (h->element, "do-lost", TRUE, NULL);
2097 g_object_set (h->element, "do-retransmission", TRUE, NULL);
2098 g_object_set (h->element, "latency", latency_ms, NULL);
2099 g_object_set (h->element, "rtx-retry-period", retry_period_ms, NULL);
2100
2101 /* push the first couple of buffers */
2102 push_test_buffer (h, 0);
2103 push_test_buffer (h, 1);
2104
2105 /* drop reconfigure event */
2106 gst_event_unref (gst_harness_pull_upstream_event (h));
2107 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
2108 for (i = 0; i < 3; i++)
2109 gst_event_unref (gst_harness_pull_event (h));
2110
2111 /* Wait for the first EXPECTED timer to be scheduled */
2112 gst_test_clock_wait_for_next_pending_id (testclock, &pending_id);
2113 time = gst_clock_id_get_time (pending_id);
2114 gst_clock_id_unref (pending_id);
2115 fail_unless_equals_int64 (time, 2 * TEST_BUF_DURATION + 10 * GST_MSECOND);
2116
2117 /* Let the first EXPECTED timer time out and be sent. However, set the 'now'
2118 * time to be past the retry-period simulating that the jitterbuffer has too
2119 * much to do and is not able to process all timers in real-time. In this
2120 * case the jitterbuffer should not schedule a new EXPECTED timer as that
2121 * would just make matters worse (more unnecessary processing of a request
2122 * that is already too late to be valuable). In practice this typically
2123 * happens for high loss networks with low RTT. */
2124 gst_test_clock_set_time_and_process (testclock,
2125 2 * TEST_BUF_DURATION + retry_period_ms * GST_MSECOND + 1);
2126
2127 /* Verify the event. It could be argued that this request is already too
2128 * late and unnecessary. However, in order to keep things simple (for now)
2129 * we just keep the already scehduled EXPECTED timer, but refrain from
2130 * scheduled another EXPECTED timer */
2131 verify_rtx_event (h, 2, 2 * TEST_BUF_DURATION, 120, TEST_BUF_DURATION);
2132
2133 /* "crank" to reach the DEADLINE for packet 0 */
2134 gst_harness_crank_single_clock_wait (h);
2135 gst_buffer_unref (gst_harness_pull (h));
2136 gst_buffer_unref (gst_harness_pull (h));
2137
2138 fail_unless_equals_int (0, gst_harness_upstream_events_in_queue (h));
2139 fail_unless_equals_int (0, gst_harness_events_in_queue (h));
2140
2141 /* "crank" to time out the LOST event */
2142 gst_harness_crank_single_clock_wait (h);
2143 verify_lost_event (h, 2, 2 * TEST_BUF_DURATION, TEST_BUF_DURATION);
2144
2145 gst_object_unref (testclock);
2146 gst_harness_teardown (h);
2147 }
2148
2149 GST_END_TEST;
2150
GST_START_TEST(test_rtx_same_delay_and_retry_timeout)2151 GST_START_TEST (test_rtx_same_delay_and_retry_timeout)
2152 {
2153 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2154 gint latency_ms = 5 * TEST_BUF_MS;
2155 gint next_seqnum;
2156 gint rtx_delay_ms = 20;
2157 GstClockTime last_rtx_request;
2158
2159 g_object_set (h->element, "do-retransmission", TRUE,
2160 "rtx-max-retries", 3, "rtx-delay", rtx_delay_ms,
2161 "rtx-retry-timeout", rtx_delay_ms, NULL);
2162 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
2163
2164 /* Crank clock to send retransmission events requesting seqnum 6 which has
2165 * not arrived yet. */
2166 gst_harness_crank_single_clock_wait (h);
2167 verify_rtx_event (h, next_seqnum,
2168 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
2169 /* first rtx for packet @next_seqnum should arrive at the right time */
2170 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
2171 fail_unless_equals_int64 (last_rtx_request,
2172 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
2173
2174 /* verify we have pulled out all rtx-events */
2175 fail_unless_equals_int (0, gst_harness_upstream_events_in_queue (h));
2176
2177 /* now crank to get the second attempt at packet @next_seqnum */
2178 gst_harness_crank_single_clock_wait (h);
2179 verify_rtx_event (h, next_seqnum,
2180 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms * 2, TEST_BUF_DURATION);
2181
2182 /* second rtx for seqnum 6 should arrive at 140 + 20ms */
2183 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
2184 fail_unless_equals_int64 (last_rtx_request,
2185 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * 2 * GST_MSECOND);
2186
2187 /* verify we have pulled out all rtx-events */
2188 fail_unless_equals_int (0, gst_harness_upstream_events_in_queue (h));
2189
2190 fail_unless (verify_jb_stats (h->element,
2191 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
2192 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
2193 "num-lost", G_TYPE_UINT64, (guint64) 0,
2194 "rtx-count", G_TYPE_UINT64, (guint64) 2, NULL)));
2195
2196 gst_harness_teardown (h);
2197 }
2198
2199 GST_END_TEST;
2200
GST_START_TEST(test_rtx_with_backwards_rtptime)2201 GST_START_TEST (test_rtx_with_backwards_rtptime)
2202 {
2203 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2204 gint latency_ms = 40;
2205
2206 g_object_set (h->element, "do-retransmission", TRUE, NULL);
2207 construct_deterministic_initial_state (h, latency_ms);
2208
2209 /*
2210 * For video using B-frames, an expected sequence
2211 * could be like this:
2212 * (I = I-frame, P = P-frame, B = B-frame)
2213 * ___ ___ ___
2214 * ... | 3 | | 4 | | 5 |
2215 * ––– ––– –––
2216 * rtptime: 3(I) 5(P) 4(B)
2217 * arrival(dts): 3 5 5
2218 *
2219 * Notice here that packet 5 (the B frame) make
2220 * the rtptime go backwards.
2221 */
2222
2223 /* seqnum 3, arriving at time 3 with rtptime 3 */
2224 push_test_buffer (h, 3);
2225 gst_buffer_unref (gst_harness_pull (h));
2226
2227 /* seqnum 4, arriving at time 5 with rtptime 5 */
2228 gst_harness_push (h, generate_test_buffer_full (5 * TEST_BUF_DURATION,
2229 4, 5 * TEST_RTP_TS_DURATION));
2230 gst_buffer_unref (gst_harness_pull (h));
2231
2232 /* seqnum 5, arriving at time 5 with rtptime 4 */
2233 gst_harness_push (h, generate_test_buffer_full (5 * TEST_BUF_DURATION,
2234 5, 4 * TEST_RTP_TS_DURATION));
2235 gst_buffer_unref (gst_harness_pull (h));
2236
2237 /* crank to time-out the rtx-request for seqnum 6, the point here
2238 * being that the backwards rtptime did not mess up the timeout for
2239 * the rtx event.
2240 *
2241 * Note: the jitterbuffer no longer update early timers, as a result
2242 * we need to advance the clock to the expected point
2243 */
2244 gst_harness_wait_for_clock_id_waits (h, 1, 1);
2245 gst_harness_set_time (h, 6 * TEST_BUF_DURATION + 15 * GST_MSECOND);
2246 gst_harness_crank_single_clock_wait (h);
2247 verify_rtx_event (h, 6, 5 * TEST_BUF_DURATION + 15 * GST_MSECOND,
2248 20, 35 * GST_MSECOND);
2249
2250 fail_unless (verify_jb_stats (h->element,
2251 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
2252 "num-pushed", G_TYPE_UINT64, (guint64) 6,
2253 "rtx-count", G_TYPE_UINT64, (guint64) 1,
2254 "num-lost", G_TYPE_UINT64, (guint64) 0, NULL)));
2255
2256 gst_harness_teardown (h);
2257 }
2258
2259 GST_END_TEST;
2260
GST_START_TEST(test_rtx_timer_reuse)2261 GST_START_TEST (test_rtx_timer_reuse)
2262 {
2263 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2264 gint latency_ms = 5 * TEST_BUF_MS;
2265 gint rtx_delay_ms = TEST_BUF_MS / 2;
2266 guint next_seqnum;
2267
2268 g_object_set (h->element, "do-retransmission", TRUE,
2269 "do-lost", TRUE, "rtx-max-retries", 1, NULL);
2270 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
2271
2272 /* crank to timeout the only rtx-request, and the timer will
2273 * now reschedule as a lost-timer internally */
2274 gst_harness_crank_single_clock_wait (h);
2275 verify_rtx_event (h, next_seqnum,
2276 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
2277
2278 /* but now buffer 6 arrives, and this should now reuse the lost-timer
2279 * for 6, as an expected-timer for 7 */
2280 fail_unless_equals_int (GST_FLOW_OK,
2281 gst_harness_push (h, generate_test_buffer (next_seqnum)));
2282
2283 /* now crank to timeout the expected-timer for 7 and verify */
2284 next_seqnum++;
2285 gst_harness_crank_single_clock_wait (h);
2286 verify_rtx_event (h, next_seqnum,
2287 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
2288
2289 gst_harness_teardown (h);
2290 }
2291
2292 GST_END_TEST;
2293
2294
2295 static void
start_test_rtx_large_packet_spacing(GstHarness * h,gint latency_ms,gint frame_dur_ms,gint rtx_rtt_ms,guint16 * dst_lost_seq,GstClockTime * dst_now)2296 start_test_rtx_large_packet_spacing (GstHarness * h,
2297 gint latency_ms, gint frame_dur_ms, gint rtx_rtt_ms,
2298 guint16 * dst_lost_seq, GstClockTime * dst_now)
2299 {
2300 gint i, seq, frame;
2301 GstBuffer *buffer;
2302 GstClockTime now, lost_packet_time;
2303 GstClockTime frame_dur = frame_dur_ms * GST_MSECOND;
2304
2305 gst_harness_set_src_caps (h, generate_caps ());
2306 g_object_set (h->element,
2307 "do-lost", TRUE, "latency", latency_ms, "do-retransmission", TRUE, NULL);
2308
2309 /* Pushing 2 frames @frame_dur_ms ms apart from each other to initialize
2310 * packet_spacing and avg jitter */
2311 for (frame = 0, seq = 0, now = 0; frame < 2;
2312 frame++, seq += 2, now += frame_dur) {
2313 gst_harness_set_time (h, now);
2314 gst_harness_push (h, generate_test_buffer_full (now, seq,
2315 AS_TEST_BUF_RTP_TIME (now)));
2316 gst_harness_push (h, generate_test_buffer_full (now, seq + 1,
2317 AS_TEST_BUF_RTP_TIME (now)));
2318
2319 if (frame == 0)
2320 /* deadline for buffer 0 expires */
2321 gst_harness_crank_single_clock_wait (h);
2322
2323 gst_buffer_unref (gst_harness_pull (h));
2324 gst_buffer_unref (gst_harness_pull (h));
2325 }
2326
2327 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
2328 for (i = 0; i < 3; i++)
2329 gst_event_unref (gst_harness_pull_event (h));
2330 /* drop reconfigure event */
2331 gst_event_unref (gst_harness_pull_upstream_event (h));
2332
2333 /* The first packet (#@seq) of the 3rd frame is lost */
2334 lost_packet_time = now;
2335 gst_harness_set_time (h, now);
2336 gst_harness_push (h, generate_test_buffer_full (now, seq + 1,
2337 AS_TEST_BUF_RTP_TIME (now)));
2338
2339 /* RTX delay calculated as:
2340 * MIN(rtx_delay_max, MAX(2*avg_jitter, 0.5 * packet_spacing)).
2341 * Where rtx_delay_max:
2342 * rtx_delay_max = latency - rtx_rtt.
2343 * We have not used RTX yet, so rtx_rtt = 0, rtx_delay_max = latency.
2344 * Thus we expect the first RTX event to be sent in @latency_ms ms */
2345 gst_harness_crank_single_clock_wait (h);
2346 fail_unless_equals_int64 (now + latency_ms * GST_MSECOND,
2347 gst_clock_get_time (GST_ELEMENT_CLOCK (h->element)));
2348 verify_rtx_event (h, seq, now, latency_ms, frame_dur);
2349 verify_lost_event (h, seq, now, 0);
2350 gst_buffer_unref (gst_harness_pull (h));
2351 now += latency_ms * GST_MSECOND;
2352
2353 /* Sending lost packet as RTX to initialize rtx_rtt */
2354 now += rtx_rtt_ms * GST_MSECOND;
2355 gst_harness_set_time (h, now);
2356 buffer =
2357 generate_test_buffer_full (now, seq,
2358 AS_TEST_BUF_RTP_TIME (lost_packet_time));
2359 GST_BUFFER_FLAG_SET (buffer, GST_RTP_BUFFER_FLAG_RETRANSMISSION);
2360 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, buffer));
2361
2362 /* No buffers should be pushed through, as lost packet arrived too late */
2363 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h));
2364
2365 seq += 2;
2366 frame += 1;
2367 now = frame * frame_dur;
2368 gst_harness_set_time (h, now);
2369
2370 /* The first packet (#@seq) of the 4th frame is lost */
2371 gst_harness_push (h, generate_test_buffer_full (now, seq + 1,
2372 AS_TEST_BUF_RTP_TIME (now)));
2373 *dst_lost_seq = seq;
2374 *dst_now = now;
2375 }
2376
GST_START_TEST(test_rtx_large_packet_spacing_and_small_rtt)2377 GST_START_TEST (test_rtx_large_packet_spacing_and_small_rtt)
2378 {
2379 GstClockTime now;
2380 guint16 lost_seq;
2381 gint latency_ms = 20;
2382 gint frame_dur_ms = 50;
2383 gint rtx_rtt_ms = 5;
2384 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2385
2386 start_test_rtx_large_packet_spacing (h, latency_ms, frame_dur_ms, rtx_rtt_ms,
2387 &lost_seq, &now);
2388
2389 /* With small rtx_rtt, RTX event expected to be sent in
2390 (@latency_ms - @rtx_rtt_ms) ms */
2391 gst_harness_crank_single_clock_wait (h);
2392 fail_unless_equals_int64 (now + (latency_ms - rtx_rtt_ms) * GST_MSECOND,
2393 gst_clock_get_time (GST_ELEMENT_CLOCK (h->element)));
2394 verify_rtx_event (h, lost_seq, now, (latency_ms - rtx_rtt_ms),
2395 frame_dur_ms * GST_MSECOND);
2396
2397 /* After @latency ms the packet should be considered lost */
2398 gst_harness_crank_single_clock_wait (h);
2399 fail_unless_equals_int64 (now + latency_ms * GST_MSECOND,
2400 gst_clock_get_time (GST_ELEMENT_CLOCK (h->element)));
2401 verify_lost_event (h, lost_seq, now, 0);
2402 gst_buffer_unref (gst_harness_pull (h));
2403
2404 gst_harness_teardown (h);
2405 }
2406
2407 GST_END_TEST;
2408
GST_START_TEST(test_rtx_large_packet_spacing_and_large_rtt)2409 GST_START_TEST (test_rtx_large_packet_spacing_and_large_rtt)
2410 {
2411 GstClockTime now;
2412 guint16 lost_seq;
2413 gint latency_ms = 20;
2414 gint frame_dur_ms = 50;
2415 gint rtx_rtt_ms = 30;
2416 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2417
2418 start_test_rtx_large_packet_spacing (h, latency_ms, frame_dur_ms, rtx_rtt_ms,
2419 &lost_seq, &now);
2420
2421 /* With large rtx_rtt, RTX event expected to be sent in @latency_ms ms.
2422 The buffer considered lost. */
2423 gst_harness_crank_single_clock_wait (h);
2424 fail_unless_equals_int64 (now + latency_ms * GST_MSECOND,
2425 gst_clock_get_time (GST_ELEMENT_CLOCK (h->element)));
2426 verify_rtx_event (h, lost_seq, now, latency_ms, frame_dur_ms * GST_MSECOND);
2427 verify_lost_event (h, lost_seq, now, 0);
2428 gst_buffer_unref (gst_harness_pull (h));
2429
2430 gst_harness_teardown (h);
2431 }
2432
2433 GST_END_TEST;
2434
GST_START_TEST(test_rtx_large_packet_spacing_does_not_reset_jitterbuffer)2435 GST_START_TEST (test_rtx_large_packet_spacing_does_not_reset_jitterbuffer)
2436 {
2437 gint latency_ms = 20;
2438 gint frame_dur_ms = 50;
2439 gint rtx_rtt_ms = 5;
2440 gint i, seq;
2441 GstBuffer *buffer;
2442 GstClockTime now, lost_packet_time;
2443 GstClockTime frame_dur = frame_dur_ms * GST_MSECOND;
2444 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2445
2446 gst_harness_set_src_caps (h, generate_caps ());
2447 g_object_set (h->element,
2448 "do-lost", TRUE, "latency", latency_ms, "do-retransmission", TRUE, NULL);
2449
2450 /* Pushing 2 frames @frame_dur_ms ms apart from each other to initialize
2451 * packet_spacing and avg jitter */
2452 for (seq = 0, now = 0; seq < 2; ++seq, now += frame_dur) {
2453 gst_harness_set_time (h, now);
2454 gst_harness_push (h, generate_test_buffer_full (now, seq,
2455 AS_TEST_BUF_RTP_TIME (now)));
2456 if (seq == 0)
2457 gst_harness_crank_single_clock_wait (h);
2458 buffer = gst_harness_pull (h);
2459 fail_unless_equals_int64 (now, GST_BUFFER_PTS (buffer));
2460 gst_buffer_unref (buffer);
2461 }
2462
2463 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
2464 for (i = 0; i < 3; i++)
2465 gst_event_unref (gst_harness_pull_event (h));
2466 /* drop reconfigure event */
2467 gst_event_unref (gst_harness_pull_upstream_event (h));
2468
2469 /* Waiting for the RTX timer of packet #2 to timeout */
2470 lost_packet_time = now;
2471 gst_harness_crank_single_clock_wait (h);
2472 fail_unless_equals_int64 (now + latency_ms * GST_MSECOND,
2473 gst_clock_get_time (GST_ELEMENT_CLOCK (h->element)));
2474 verify_rtx_event (h, seq, now, latency_ms, frame_dur);
2475 verify_lost_event (h, seq, now, frame_dur);
2476 now += latency_ms * GST_MSECOND;
2477
2478 /* Pushing packet #2 as RTX */
2479 now += rtx_rtt_ms * GST_MSECOND;
2480 gst_harness_set_time (h, now);
2481 buffer =
2482 generate_test_buffer_full (now, seq,
2483 AS_TEST_BUF_RTP_TIME (lost_packet_time));
2484 GST_BUFFER_FLAG_SET (buffer, GST_RTP_BUFFER_FLAG_RETRANSMISSION);
2485 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, buffer));
2486 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h));
2487
2488 /* Packet #3 should have PTS not affected by clock skew logic */
2489 seq += 1;
2490 now = seq * frame_dur;
2491 gst_harness_set_time (h, now);
2492 gst_harness_push (h, generate_test_buffer_full (now, seq,
2493 AS_TEST_BUF_RTP_TIME (now)));
2494 buffer = gst_harness_pull (h);
2495 fail_unless_equals_int64 (now, GST_BUFFER_PTS (buffer));
2496 gst_buffer_unref (buffer);
2497
2498 gst_harness_teardown (h);
2499 }
2500
2501 GST_END_TEST;
2502
GST_START_TEST(test_minor_reorder_does_not_skew)2503 GST_START_TEST (test_minor_reorder_does_not_skew)
2504 {
2505 gint latency_ms = 20;
2506 gint frame_dur_ms = 50;
2507 guint rtx_min_delay_ms = 110;
2508 gint hickup_ms = 2;
2509 gint i, seq;
2510 GstBuffer *buffer;
2511 GstClockTime now;
2512 GstClockTime frame_dur = frame_dur_ms * GST_MSECOND;
2513 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2514
2515 gst_harness_set_src_caps (h, generate_caps ());
2516 g_object_set (h->element,
2517 "do-lost", TRUE, "latency", latency_ms, "do-retransmission", TRUE,
2518 "rtx-min-delay", rtx_min_delay_ms, NULL);
2519
2520 /* Pushing 2 frames @frame_dur_ms ms apart from each other to initialize
2521 * packet_spacing and avg jitter */
2522 for (seq = 0, now = 0; seq < 2; ++seq, now += frame_dur) {
2523 gst_harness_set_time (h, now);
2524 gst_harness_push (h, generate_test_buffer_full (now, seq,
2525 AS_TEST_BUF_RTP_TIME (now)));
2526 if (seq == 0)
2527 gst_harness_crank_single_clock_wait (h);
2528 buffer = gst_harness_pull (h);
2529 fail_unless_equals_int64 (now, GST_BUFFER_PTS (buffer));
2530 gst_buffer_unref (buffer);
2531 }
2532
2533 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
2534 for (i = 0; i < 3; i++)
2535 gst_event_unref (gst_harness_pull_event (h));
2536 /* drop reconfigure event */
2537 gst_event_unref (gst_harness_pull_upstream_event (h));
2538
2539 /* Pushing packet #4 before #3, shortly after #3 would have arrived normally */
2540 gst_harness_set_time (h, now + hickup_ms * GST_MSECOND);
2541 gst_harness_push (h, generate_test_buffer_full (now + hickup_ms * GST_MSECOND,
2542 seq + 1, AS_TEST_BUF_RTP_TIME (now + frame_dur)));
2543
2544 /* Pushing packet #3 after #4 when #4 would have normally arrived */
2545 gst_harness_set_time (h, now + frame_dur);
2546 gst_harness_push (h, generate_test_buffer_full (now + frame_dur, seq,
2547 AS_TEST_BUF_RTP_TIME (now)));
2548
2549 /* Pulling should be retrieving #3 first */
2550 buffer = gst_harness_pull (h);
2551 fail_unless_equals_int64 (now, GST_BUFFER_PTS (buffer));
2552 gst_buffer_unref (buffer);
2553
2554 /* Pulling should be retrieving #4 second */
2555 buffer = gst_harness_pull (h);
2556 fail_unless_equals_int64 (now + frame_dur, GST_BUFFER_PTS (buffer));
2557 gst_buffer_unref (buffer);
2558
2559 now += 2 * frame_dur;
2560 seq += 2;
2561
2562 /* Pushing packet #5 normal again */
2563 gst_harness_set_time (h, now);
2564 gst_harness_push (h, generate_test_buffer_full (now, seq,
2565 AS_TEST_BUF_RTP_TIME (now)));
2566 buffer = gst_harness_pull (h);
2567 fail_unless_equals_int64 (now, GST_BUFFER_PTS (buffer));
2568 gst_buffer_unref (buffer);
2569
2570 seq++;
2571 now += frame_dur;
2572
2573 /* Pushing packet #6 half a frame early to trigger clock skew */
2574 gst_harness_set_time (h, now);
2575 gst_harness_push (h, generate_test_buffer_full (now, seq,
2576 AS_TEST_BUF_RTP_TIME (now + frame_dur / 2)));
2577 buffer = gst_harness_pull (h);
2578 fail_unless (now + frame_dur / 2 > GST_BUFFER_PTS (buffer),
2579 "pts should have been adjusted due to clock skew");
2580 gst_buffer_unref (buffer);
2581
2582 gst_harness_teardown (h);
2583 }
2584
2585 GST_END_TEST;
2586
GST_START_TEST(test_deadline_ts_offset)2587 GST_START_TEST (test_deadline_ts_offset)
2588 {
2589 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2590 GstTestClock *testclock;
2591 GstClockID id;
2592 const gint jb_latency_ms = 10;
2593
2594 gst_harness_set_src_caps (h, generate_caps ());
2595 testclock = gst_harness_get_testclock (h);
2596
2597 g_object_set (h->element, "latency", jb_latency_ms, NULL);
2598
2599 /* push the first buffer in */
2600 fail_unless_equals_int (GST_FLOW_OK,
2601 gst_harness_push (h, generate_test_buffer (0)));
2602
2603 /* wait_next_timeout() syncs on the deadline timer */
2604 gst_test_clock_wait_for_next_pending_id (testclock, &id);
2605 fail_unless_equals_uint64 (jb_latency_ms * GST_MSECOND,
2606 gst_clock_id_get_time (id));
2607 gst_clock_id_unref (id);
2608
2609 /* add ts-offset while waiting */
2610 g_object_set (h->element, "ts-offset", 20 * GST_MSECOND, NULL);
2611
2612 gst_test_clock_set_time_and_process (testclock, jb_latency_ms * GST_MSECOND);
2613
2614 /* wait_next_timeout() syncs on the new deadline timer */
2615 gst_test_clock_wait_for_next_pending_id (testclock, &id);
2616 fail_unless_equals_uint64 ((20 + jb_latency_ms) * GST_MSECOND,
2617 gst_clock_id_get_time (id));
2618 gst_clock_id_unref (id);
2619
2620 /* now make deadline timer timeout */
2621 gst_test_clock_set_time_and_process (testclock,
2622 (20 + jb_latency_ms) * GST_MSECOND);
2623
2624 gst_buffer_unref (gst_harness_pull (h));
2625
2626 gst_object_unref (testclock);
2627 gst_harness_teardown (h);
2628 }
2629
2630 GST_END_TEST;
2631
GST_START_TEST(test_big_gap_seqnum)2632 GST_START_TEST (test_big_gap_seqnum)
2633 {
2634 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2635 const gint num_consecutive = 5;
2636 const guint gap = 20000;
2637 gint i;
2638 guint seqnum_org;
2639 GstClockTime dts_base;
2640 guint seqnum_base;
2641 guint32 rtpts_base;
2642 GstClockTime expected_ts;
2643
2644 g_object_set (h->element, "do-lost", TRUE, "do-retransmission", TRUE, NULL);
2645 seqnum_org = construct_deterministic_initial_state (h, 100);
2646
2647 /* a sudden jump in sequence-numbers (and rtptime), but packets keep arriving
2648 at the same pace */
2649 dts_base = seqnum_org * TEST_BUF_DURATION;
2650 seqnum_base = seqnum_org + gap;
2651 rtpts_base = seqnum_base * TEST_RTP_TS_DURATION;
2652
2653 for (i = 0; i < num_consecutive; i++) {
2654 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
2655 generate_test_buffer_full (dts_base + i * TEST_BUF_DURATION,
2656 seqnum_base + i, rtpts_base + i * TEST_RTP_TS_DURATION)));
2657 }
2658
2659 for (i = 0; i < num_consecutive; i++) {
2660 GstBuffer *buf = gst_harness_pull (h);
2661 guint expected_seqnum = seqnum_base + i;
2662 fail_unless_equals_int (expected_seqnum, get_rtp_seq_num (buf));
2663
2664 expected_ts = dts_base + i * TEST_BUF_DURATION;
2665 fail_unless_equals_int (expected_ts, GST_BUFFER_PTS (buf));
2666 gst_buffer_unref (buf);
2667 }
2668
2669 fail_unless_equals_int (0, gst_harness_events_in_queue (h));
2670
2671 gst_harness_teardown (h);
2672 }
2673
2674 GST_END_TEST;
2675
GST_START_TEST(test_big_gap_arrival_time)2676 GST_START_TEST (test_big_gap_arrival_time)
2677 {
2678 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2679 const gint num_consecutive = 5;
2680 const guint gap = 20000;
2681 gint i;
2682 guint seqnum_org;
2683 GstClockTime dts_base;
2684 guint seqnum_base;
2685 guint32 rtpts_base;
2686 GstClockTime expected_ts;
2687
2688 g_object_set (h->element, "do-lost", TRUE, "do-retransmission", TRUE, NULL);
2689 seqnum_org = construct_deterministic_initial_state (h, 100);
2690
2691 /* packets are being held back on the wire, then continues */
2692 dts_base = (seqnum_org + gap) * TEST_BUF_DURATION;
2693 seqnum_base = seqnum_org;
2694 rtpts_base = seqnum_base * TEST_RTP_TS_DURATION;
2695
2696 for (i = 0; i < num_consecutive; i++) {
2697 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
2698 generate_test_buffer_full (dts_base + i * TEST_BUF_DURATION,
2699 seqnum_base + i, rtpts_base + i * TEST_RTP_TS_DURATION)));
2700 }
2701
2702 for (i = 0; i < num_consecutive; i++) {
2703 GstBuffer *buf = gst_harness_pull (h);
2704 guint expected_seqnum = seqnum_base + i;
2705 fail_unless_equals_int (expected_seqnum, get_rtp_seq_num (buf));
2706
2707 expected_ts = dts_base + i * TEST_BUF_DURATION;
2708 fail_unless_equals_int (expected_ts, GST_BUFFER_PTS (buf));
2709 gst_buffer_unref (buf);
2710 }
2711
2712 fail_unless_equals_int (0, gst_harness_events_in_queue (h));
2713
2714 gst_harness_teardown (h);
2715 }
2716
2717 GST_END_TEST;
2718
2719 typedef struct
2720 {
2721 guint seqnum_offset;
2722 guint late_buffer;
2723 } TestLateArrivalInput;
2724
2725 static const TestLateArrivalInput
2726 test_considered_lost_packet_in_large_gap_arrives_input[] = {
2727 {0, 1}, {0, 2}, {65535, 1}, {65535, 2}, {65534, 1}, {65534, 2}
2728 };
2729
GST_START_TEST(test_considered_lost_packet_in_large_gap_arrives)2730 GST_START_TEST (test_considered_lost_packet_in_large_gap_arrives)
2731 {
2732 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2733 GstTestClock *testclock;
2734 GstBuffer *buffer;
2735 gint jb_latency_ms = 20;
2736 const TestLateArrivalInput *test_input =
2737 &test_considered_lost_packet_in_large_gap_arrives_input[__i__];
2738 guint seq_offset = test_input->seqnum_offset;
2739 guint late_buffer = test_input->late_buffer;
2740 gint i;
2741
2742 gst_harness_set_src_caps (h, generate_caps ());
2743 testclock = gst_harness_get_testclock (h);
2744 g_object_set (h->element, "do-lost", TRUE, "latency", jb_latency_ms, NULL);
2745
2746 /* first push buffer 0 */
2747 fail_unless_equals_int (GST_FLOW_OK,
2748 gst_harness_push (h, generate_test_buffer_full (0 * TEST_BUF_DURATION,
2749 0 + seq_offset, 0 * TEST_RTP_TS_DURATION)));
2750 fail_unless (gst_harness_crank_single_clock_wait (h));
2751 gst_buffer_unref (gst_harness_pull (h));
2752
2753 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
2754 for (i = 0; i < 3; i++)
2755 gst_event_unref (gst_harness_pull_event (h));
2756
2757 /* hop over 3 packets, and push buffer 4 (gap of 3) */
2758 gst_harness_set_time (h, 4 * TEST_BUF_DURATION);
2759 fail_unless_equals_int (GST_FLOW_OK,
2760 gst_harness_push (h, generate_test_buffer_full (4 * TEST_BUF_DURATION,
2761 4 + seq_offset, 4 * TEST_RTP_TS_DURATION)));
2762
2763 /* we get a "bundled" lost-event for the 2 packets now already too late */
2764 verify_lost_event (h, 1 + seq_offset, 1 * TEST_BUF_DURATION,
2765 2 * TEST_BUF_DURATION);
2766
2767 /* and another one for buffer 3 */
2768 verify_lost_event (h, 3 + seq_offset, 3 * TEST_BUF_DURATION,
2769 1 * TEST_BUF_DURATION);
2770
2771 /* A late buffer arrives */
2772 fail_unless_equals_int (GST_FLOW_OK,
2773 gst_harness_push (h,
2774 generate_test_buffer_full (late_buffer * TEST_BUF_DURATION,
2775 late_buffer + seq_offset, late_buffer * TEST_RTP_TS_DURATION)));
2776
2777 /* buffer 4 is pushed as normal */
2778 buffer = gst_harness_pull (h);
2779 fail_unless_equals_int ((4 + seq_offset) & 0xffff, get_rtp_seq_num (buffer));
2780 gst_buffer_unref (buffer);
2781
2782 /* we have lost 3, and one of them arrived eventually, but too late */
2783 fail_unless (verify_jb_stats (h->element,
2784 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
2785 "num-pushed", G_TYPE_UINT64, (guint64) 2,
2786 "num-lost", G_TYPE_UINT64, (guint64) 3,
2787 "num-late", G_TYPE_UINT64, (guint64) 1, NULL)));
2788
2789 gst_object_unref (testclock);
2790 gst_harness_teardown (h);
2791 }
2792
2793 GST_END_TEST;
2794
GST_START_TEST(test_performance)2795 GST_START_TEST (test_performance)
2796 {
2797 GstHarness *h =
2798 gst_harness_new_parse
2799 ("rtpjitterbuffer do-lost=1 do-retransmission=1 latency=1000");
2800 GTimer *timer = g_timer_new ();
2801 const gdouble test_duration = 2.0;
2802 guint buffers_pushed = 0;
2803 guint buffers_received;
2804
2805 gst_harness_set_src_caps (h, generate_caps ());
2806 gst_harness_use_systemclock (h);
2807
2808 while (g_timer_elapsed (timer, NULL) < test_duration) {
2809 /* Simulate 1ms packets */
2810 guint n = buffers_pushed * 2; // every packet also produces a gap
2811 guint16 seqnum = n & 0xffff;
2812 guint32 rtp_ts = n * 8;
2813 GstClockTime dts = n * GST_MSECOND;
2814 gst_harness_push (h, generate_test_buffer_full (dts, seqnum, rtp_ts));
2815 buffers_pushed++;
2816 g_usleep (G_USEC_PER_SEC / 10000);
2817 }
2818 g_timer_destroy (timer);
2819
2820 buffers_received = gst_harness_buffers_received (h);
2821 GST_INFO ("Pushed %d, received %d (%.1f%%)", buffers_pushed, buffers_received,
2822 100.0 * buffers_received / buffers_pushed);
2823
2824 gst_harness_teardown (h);
2825 }
2826
2827 GST_END_TEST;
2828
GST_START_TEST(test_fill_queue)2829 GST_START_TEST (test_fill_queue)
2830 {
2831 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2832 const gint num_consecutive = 40000;
2833 GstBuffer *buf;
2834 gint i;
2835
2836 gst_harness_use_testclock (h);
2837
2838 gst_harness_set_src_caps (h, generate_caps ());
2839
2840 gst_harness_play (h);
2841
2842 gst_harness_push (h, generate_test_buffer (1000));
2843 /* Skip 1001 */
2844 for (i = 2; i < num_consecutive; i++)
2845 gst_harness_push (h, generate_test_buffer (1000 + i));
2846
2847 buf = gst_harness_pull (h);
2848 fail_unless_equals_int (1000, get_rtp_seq_num (buf));
2849 gst_buffer_unref (buf);
2850 /* 1001 is skipped */
2851 for (i = 2; i < num_consecutive; i++) {
2852 GstBuffer *buf = gst_harness_pull (h);
2853 fail_unless_equals_int (1000 + i, get_rtp_seq_num (buf));
2854 gst_buffer_unref (buf);
2855 }
2856
2857 gst_harness_teardown (h);
2858 }
2859
2860 GST_END_TEST;
2861
2862 typedef struct
2863 {
2864 gint64 dts_skew;
2865 gint16 seqnum_skew;
2866 } RtxSkewCtx;
2867
2868 static const RtxSkewCtx rtx_does_not_affect_pts_calculation_input[] = {
2869 {0, 0},
2870 {20 * GST_MSECOND, -100},
2871 {20 * GST_MSECOND, 100},
2872 {-10 * GST_MSECOND, 1},
2873 {100 * GST_MSECOND, 0},
2874 };
2875
GST_START_TEST(test_rtx_does_not_affect_pts_calculation)2876 GST_START_TEST (test_rtx_does_not_affect_pts_calculation)
2877 {
2878 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2879 GstBuffer *buffer;
2880 guint next_seqnum;
2881 guint rtx_seqnum;
2882 GstClockTime now;
2883 const RtxSkewCtx *ctx = &rtx_does_not_affect_pts_calculation_input[__i__];
2884
2885 /* set up a deterministic state and take the time on the clock */
2886 g_object_set (h->element, "do-retransmission", TRUE, "do-lost", TRUE, NULL);
2887 next_seqnum = construct_deterministic_initial_state (h, 3000);
2888 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
2889
2890 /* push in a "bad" RTX buffer, arriving at various times / seqnums */
2891 rtx_seqnum = next_seqnum + ctx->seqnum_skew;
2892 buffer = generate_test_buffer_full (now + ctx->dts_skew, rtx_seqnum,
2893 rtx_seqnum * TEST_RTP_TS_DURATION);
2894 GST_BUFFER_FLAG_SET (buffer, GST_RTP_BUFFER_FLAG_RETRANSMISSION);
2895 gst_harness_push (h, buffer);
2896
2897 /* now push in the next regular buffer at its ideal time, and verify the
2898 rogue RTX-buffer did not mess things up */
2899 push_test_buffer (h, next_seqnum);
2900 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
2901 buffer = gst_harness_pull (h);
2902 fail_unless_equals_int64 (now, GST_BUFFER_PTS (buffer));
2903
2904 gst_buffer_unref (buffer);
2905
2906 gst_harness_teardown (h);
2907 }
2908
2909 GST_END_TEST;
2910
GST_START_TEST(test_dont_drop_packet_based_on_skew)2911 GST_START_TEST (test_dont_drop_packet_based_on_skew)
2912 {
2913 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2914 guint base_seqnum;
2915 GstClockTime now;
2916 guint i;
2917
2918 /* set up a deterministic state and take the time on the clock */
2919 g_object_set (h->element, "do-retransmission", TRUE, "do-lost", TRUE, NULL);
2920 base_seqnum = construct_deterministic_initial_state (h, 20);
2921 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
2922
2923 /* and after a delay of 50ms... */
2924 now += GST_MSECOND * 50;
2925 gst_test_clock_set_time (GST_TEST_CLOCK (GST_ELEMENT_CLOCK (h->element)),
2926 now);
2927
2928 /* ..two more buffers arrive in perfect order */
2929 for (i = 0; i < 2; i++) {
2930 gst_harness_push (h, generate_test_buffer_full (now + i * GST_MSECOND * 20,
2931 base_seqnum + i, (base_seqnum + i) * TEST_RTP_TS_DURATION));
2932 }
2933
2934 /* verify we did not drop any of them */
2935 for (i = 0; i < 2; i++) {
2936 gst_buffer_unref (gst_harness_pull (h));
2937 }
2938
2939 gst_harness_teardown (h);
2940 }
2941
2942 GST_END_TEST;
2943
2944 static gboolean
check_drop_message(GstMessage * drop_msg,const char * reason_check,guint seqnum_check,guint num_msg)2945 check_drop_message (GstMessage * drop_msg, const char *reason_check,
2946 guint seqnum_check, guint num_msg)
2947 {
2948
2949 const GstStructure *s = gst_message_get_structure (drop_msg);
2950 const gchar *reason_str;
2951 GstClockTime timestamp;
2952 guint seqnum;
2953 guint num_too_late;
2954 guint num_drop_on_latency;
2955
2956 guint num_too_late_check = 0;
2957 guint num_drop_on_latency_check = 0;
2958
2959 /* Check that fields exist */
2960 fail_unless (gst_structure_get_uint (s, "seqnum", &seqnum));
2961 fail_unless (gst_structure_get_uint64 (s, "timestamp", ×tamp));
2962 fail_unless (gst_structure_get_uint (s, "num-too-late", &num_too_late));
2963 fail_unless (gst_structure_get_uint (s, "num-drop-on-latency",
2964 &num_drop_on_latency));
2965 fail_unless (reason_str = gst_structure_get_string (s, "reason"));
2966
2967 /* Assing what to compare message fields to based on message reason */
2968 if (g_strcmp0 (reason_check, "too-late") == 0) {
2969 num_too_late_check += num_msg;
2970 } else if (g_strcmp0 (reason_check, "drop-on-latency") == 0) {
2971 num_drop_on_latency_check += num_msg;
2972 } else {
2973 return FALSE;
2974 }
2975
2976 /* Check that fields have correct value */
2977 fail_unless (seqnum == seqnum_check);
2978 fail_unless (g_strcmp0 (reason_str, reason_check) == 0);
2979 fail_unless (num_too_late == num_too_late_check);
2980 fail_unless (num_drop_on_latency == num_drop_on_latency_check);
2981
2982 return TRUE;
2983 }
2984
GST_START_TEST(test_drop_messages_too_late)2985 GST_START_TEST (test_drop_messages_too_late)
2986 {
2987 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2988 gint latency_ms = 100;
2989 guint next_seqnum;
2990 GstBus *bus;
2991 GstMessage *drop_msg;
2992 gboolean have_message = FALSE;
2993
2994 g_object_set (h->element, "post-drop-messages", TRUE, NULL);
2995 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
2996
2997 /* Create a bus to get the drop message on */
2998 bus = gst_bus_new ();
2999 gst_element_set_bus (h->element, bus);
3000
3001 /* Push test buffer resulting in gap of one */
3002 push_test_buffer (h, next_seqnum + 1);
3003
3004 /* Advance time to trigger timeout of the missing buffer */
3005 gst_harness_crank_single_clock_wait (h);
3006
3007 /* Pull out and unref pushed buffer */
3008 gst_buffer_unref (gst_harness_pull (h));
3009
3010 /* Push missing buffer, now arriving "too-late" */
3011 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
3012 generate_test_buffer (next_seqnum)));
3013
3014 /* Pop the resulting drop message and check its correctness */
3015 while (!have_message &&
3016 (drop_msg = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT)) != NULL) {
3017 if (gst_message_has_name (drop_msg, "drop-msg")) {
3018 fail_unless (check_drop_message (drop_msg, "too-late", next_seqnum, 1));
3019 have_message = TRUE;
3020 }
3021 gst_message_unref (drop_msg);
3022 }
3023 fail_unless (have_message);
3024
3025 /* Cleanup */
3026 gst_element_set_bus (h->element, NULL);
3027 gst_object_unref (bus);
3028 gst_harness_teardown (h);
3029 }
3030
3031 GST_END_TEST;
3032
GST_START_TEST(test_drop_messages_drop_on_latency)3033 GST_START_TEST (test_drop_messages_drop_on_latency)
3034 {
3035 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
3036 gint latency_ms = 20;
3037 guint next_seqnum;
3038 guint first_seqnum;
3039 guint final_seqnum;
3040 GstBus *bus;
3041 GstMessage *drop_msg;
3042 gboolean have_message = FALSE;
3043
3044 g_object_set (h->element, "post-drop-messages", TRUE, NULL);
3045 g_object_set (h->element, "drop-on-latency", TRUE, NULL);
3046 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
3047
3048 /* Create a bus to get the drop message on */
3049 bus = gst_bus_new ();
3050 gst_element_set_bus (h->element, bus);
3051
3052 /* Push 3 buffers in correct seqnum order with initial gap of 1, with the buffers
3053 * arriving simultaneously in harness time. First buffer will wait for gap buffer,
3054 * and the third arriving buffer will trigger the first to be dropped due to
3055 * drop-on-latency.
3056 */
3057 first_seqnum = ++next_seqnum;
3058 final_seqnum = next_seqnum + 2;
3059 for (; next_seqnum <= final_seqnum; next_seqnum++) {
3060 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
3061 generate_test_buffer_full (next_seqnum * TEST_BUF_DURATION,
3062 next_seqnum, next_seqnum * TEST_RTP_TS_DURATION)));
3063 }
3064
3065 /* Pop the resulting drop message and check its correctness */
3066 while (!have_message &&
3067 (drop_msg = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT)) != NULL) {
3068 if (gst_message_has_name (drop_msg, "drop-msg")) {
3069 fail_unless (check_drop_message (drop_msg, "drop-on-latency",
3070 first_seqnum, 1));
3071 have_message = TRUE;
3072 }
3073 gst_message_unref (drop_msg);
3074 }
3075 fail_unless (have_message);
3076
3077 /* Cleanup */
3078 gst_element_set_bus (h->element, NULL);
3079 gst_object_unref (bus);
3080 gst_buffer_unref (gst_harness_take_all_data_as_buffer (h));
3081 gst_harness_teardown (h);
3082 }
3083
3084 GST_END_TEST;
3085
GST_START_TEST(test_drop_messages_interval)3086 GST_START_TEST (test_drop_messages_interval)
3087 {
3088 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
3089 guint latency_ms = 100;
3090 GstClockTime interval = 10;
3091 guint next_seqnum;
3092 guint final_seqnum;
3093 GstBus *bus;
3094 GstMessage *drop_msg;
3095 GstClockTime now;
3096 guint num_late_not_sent = 0;
3097 guint num_sent_msg = 0;
3098
3099 g_object_set (h->element, "post-drop-messages", TRUE, NULL);
3100 g_object_set (h->element, "drop-messages-interval", interval, NULL);
3101 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
3102
3103 /* Create a bus to get the drop message on */
3104 bus = gst_bus_new ();
3105 gst_element_set_bus (h->element, bus);
3106
3107 /* Jump 1 second forward in time */
3108 now = 1 * GST_SECOND;
3109 gst_harness_set_time (h, now);
3110
3111 /* Push a packet with a gap of 3, that now is very late */
3112 final_seqnum = next_seqnum + 3;
3113
3114 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
3115 generate_test_buffer_full (now,
3116 final_seqnum, final_seqnum * TEST_RTP_TS_DURATION)));
3117
3118 /* Pull and unref pushed buffer */
3119 gst_buffer_unref (gst_harness_pull (h));
3120
3121 /* The 3 missing packets are now pushed with half the message "interval" between them.
3122 * When arriving they are considered as "too-late". Only the first and third should trigger
3123 * a drop_msg, as the second is dropped during the interval where no new messages will be sent.
3124 * The second should have num-too-late=2, as the "too-late" event that never sent a message
3125 * still increments the count of dropped "too-late" buffers.
3126 */
3127 for (; next_seqnum < final_seqnum; next_seqnum++) {
3128 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
3129 generate_test_buffer (next_seqnum)));
3130 num_late_not_sent++;
3131
3132 /* Pop a potential drop message and check its correctness */
3133 while ((drop_msg = gst_bus_pop (bus)) != NULL) {
3134 if (gst_message_has_name (drop_msg, "drop-msg")) {
3135 fail_unless (check_drop_message (drop_msg, "too-late", next_seqnum,
3136 num_late_not_sent));
3137
3138 num_late_not_sent = 0;
3139 num_sent_msg++;
3140 }
3141 gst_message_unref (drop_msg);
3142 }
3143 /* Advance time half the minimum interval of sending drop messages */
3144 now += (interval * GST_MSECOND) / 2;
3145 gst_harness_set_time (h, now);
3146 }
3147 /* Exactly two drop messages should have been sent */
3148 fail_unless (num_sent_msg == 2);
3149
3150 /* Cleanup */
3151 gst_element_set_bus (h->element, NULL);
3152 gst_object_unref (bus);
3153 gst_harness_teardown (h);
3154 }
3155
3156 GST_END_TEST;
3157
3158 typedef struct
3159 {
3160 gint seqnum_d;
3161 gint rtptime_d;
3162 gboolean rtx;
3163 gint sleep_us;
3164 } BufferArrayCtx;
3165
3166 static void
buffer_array_push(GstHarness * h,GArray * array,guint16 seqnum_base,guint32 rtptime_base)3167 buffer_array_push (GstHarness * h, GArray * array,
3168 guint16 seqnum_base, guint32 rtptime_base)
3169 {
3170 guint16 seqnum = seqnum_base;
3171 guint32 rtptime = rtptime_base;
3172 guint i;
3173
3174 for (i = 0; i < array->len; i++) {
3175 BufferArrayCtx *ctx = &g_array_index (array, BufferArrayCtx, i);
3176 seqnum += ctx->seqnum_d;
3177 rtptime += ctx->rtptime_d;
3178 push_test_buffer_now (h, seqnum, rtptime, ctx->rtx);
3179 g_usleep (ctx->sleep_us);
3180 }
3181 }
3182
3183 static gint
buffer_array_get_max_seqnum_delta(GArray * array)3184 buffer_array_get_max_seqnum_delta (GArray * array)
3185 {
3186 gint delta = 0;
3187 gint max_delta = 0;
3188 guint i;
3189
3190 for (i = 0; i < array->len; i++) {
3191 BufferArrayCtx *ctx = &g_array_index (array, BufferArrayCtx, i);
3192 delta += ctx->seqnum_d;
3193 if (delta > max_delta)
3194 max_delta = delta;
3195 }
3196 return max_delta;
3197 }
3198
3199 static void
buffer_array_append_sequential(GArray * array,guint num_bufs)3200 buffer_array_append_sequential (GArray * array, guint num_bufs)
3201 {
3202 guint i;
3203 for (i = 0; i < num_bufs; i++) {
3204 BufferArrayCtx ctx;
3205 ctx.seqnum_d = 1;
3206 ctx.rtptime_d = TEST_RTP_TS_DURATION; /* 20ms for 8KHz */
3207 ctx.rtx = FALSE;
3208 ctx.sleep_us = G_USEC_PER_SEC / 1000 * 20; /* 20ms */
3209 g_array_append_val (array, ctx);
3210 }
3211 }
3212
3213 static void
buffer_array_append_ctx(GArray * array,BufferArrayCtx * bufs,guint num_bufs)3214 buffer_array_append_ctx (GArray * array, BufferArrayCtx * bufs, guint num_bufs)
3215 {
3216 guint i;
3217 for (i = 0; i < num_bufs; i++) {
3218 g_array_append_val (array, bufs[i]);
3219 }
3220 }
3221
3222 static gboolean
check_for_stall(GstHarness * h,BufferArrayCtx * bufs,guint num_bufs)3223 check_for_stall (GstHarness * h, BufferArrayCtx * bufs, guint num_bufs)
3224 {
3225 guint latency_ms;
3226 guint initial_bufs;
3227 guint16 base_seqnum = 10000;
3228 guint32 base_rtptime = base_seqnum * TEST_RTP_TS_DURATION;
3229 guint16 max_seqnum;
3230 guint in_queue;
3231 GArray *array;
3232
3233 gst_harness_use_systemclock (h);
3234 gst_element_set_base_time (h->element,
3235 gst_clock_get_time (GST_ELEMENT_CLOCK (h->element)));
3236 gst_harness_set_src_caps (h, generate_caps ());
3237
3238 g_object_get (h->element, "latency", &latency_ms, NULL);
3239 initial_bufs = latency_ms / TEST_BUF_MS;
3240
3241 array = g_array_new (FALSE, FALSE, sizeof (BufferArrayCtx));
3242 buffer_array_append_sequential (array, initial_bufs);
3243 buffer_array_append_ctx (array, bufs, num_bufs);
3244 max_seqnum = base_seqnum + buffer_array_get_max_seqnum_delta (array);
3245 buffer_array_push (h, array, base_seqnum, base_rtptime);
3246 g_array_set_size (array, 0);
3247
3248 /* sleep a bit to settle things down, then find out
3249 how many buffers have been pushed out */
3250 g_usleep (G_USEC_PER_SEC);
3251 in_queue = gst_harness_buffers_in_queue (h);
3252
3253 /* push another 50 buffers normally */
3254 buffer_array_append_sequential (array, 50);
3255 base_seqnum = max_seqnum + 1;
3256 base_rtptime = base_seqnum * TEST_RTP_TS_DURATION;
3257 buffer_array_push (h, array, base_seqnum, base_rtptime);
3258 g_array_unref (array);
3259
3260 {
3261 gint64 start_time = g_get_monotonic_time ();
3262 gint64 timeout_s = 30;
3263 while (gst_harness_buffers_in_queue (h) <= in_queue) {
3264
3265 gint64 duration_s =
3266 (g_get_monotonic_time () - start_time) / G_USEC_PER_SEC;
3267 if (duration_s > timeout_s)
3268 break;
3269
3270 g_usleep (G_USEC_PER_SEC / 100);
3271 }
3272 }
3273
3274
3275 /* we expect at least some of those buffers to come through */
3276 return gst_harness_buffers_in_queue (h) > in_queue;
3277 }
3278
GST_START_TEST(test_reset_timers_does_not_stall)3279 GST_START_TEST (test_reset_timers_does_not_stall)
3280 {
3281 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
3282 BufferArrayCtx bufs[] = {
3283 /* *INDENT-OFF* */
3284 { 1, 0, FALSE, 0},
3285 { 2, 0, FALSE, 0},
3286 { 3, 0, FALSE, 0},
3287 { 4, 0, FALSE, 0},
3288 { 5, 0, FALSE, 0},
3289 { 6, 0, FALSE, 0},
3290 { 7, 0, FALSE, 0},
3291 { 8, 0, FALSE, 0},
3292 { 9, 0, FALSE, 0},
3293 {10, 0, FALSE, 0},
3294 /* *INDENT-ON* */
3295 };
3296
3297 g_object_set (h->element, "latency", 100,
3298 "do-retransmission", TRUE, "do-lost", TRUE, NULL);
3299 g_object_set (h->element, "max-dropout-time", 10, NULL);
3300 fail_unless (check_for_stall (h, bufs, G_N_ELEMENTS (bufs)));
3301 gst_harness_teardown (h);
3302 }
3303
3304 GST_END_TEST;
3305
GST_START_TEST(test_multiple_lost_do_not_stall)3306 GST_START_TEST (test_multiple_lost_do_not_stall)
3307 {
3308 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
3309 BufferArrayCtx bufs[] = {
3310 /* *INDENT-OFF* */
3311 { 39, 4960, FALSE, 58},
3312 {-28, -5280, FALSE, 1000},
3313 /* *INDENT-ON* */
3314 };
3315
3316 g_object_set (h->element, "latency", 200,
3317 "do-retransmission", TRUE, "do-lost", TRUE, NULL);
3318 fail_unless (check_for_stall (h, bufs, G_N_ELEMENTS (bufs)));
3319 gst_harness_teardown (h);
3320 }
3321
3322 GST_END_TEST;
3323
GST_START_TEST(test_reset_using_rtx_packets_does_not_stall)3324 GST_START_TEST (test_reset_using_rtx_packets_does_not_stall)
3325 {
3326 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
3327 BufferArrayCtx bufs[] = {
3328 /* *INDENT-OFF* */
3329 { 1, 1 * TEST_RTP_TS_DURATION, FALSE, 2000000},
3330 { 62, 62 * TEST_RTP_TS_DURATION, FALSE, 0},
3331 { -13, -13 * TEST_RTP_TS_DURATION, TRUE, 10000},
3332 { 1, 1 * TEST_RTP_TS_DURATION, TRUE, 0},
3333 { 1, 1 * TEST_RTP_TS_DURATION, TRUE, 0},
3334 { 1, 1 * TEST_RTP_TS_DURATION, TRUE, 0},
3335 { 1, 1 * TEST_RTP_TS_DURATION, TRUE, 0},
3336 { 1, 1 * TEST_RTP_TS_DURATION, TRUE, 0},
3337 /* *INDENT-ON* */
3338 };
3339
3340 g_object_set (h->element, "latency", 400,
3341 "do-retransmission", TRUE, "do-lost", TRUE, "max-misorder-time", 1, NULL);
3342 fail_unless (check_for_stall (h, bufs, G_N_ELEMENTS (bufs)));
3343 gst_harness_teardown (h);
3344 }
3345
3346 GST_END_TEST;
3347
GST_START_TEST(test_gap_using_rtx_does_not_stall)3348 GST_START_TEST (test_gap_using_rtx_does_not_stall)
3349 {
3350 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
3351
3352 BufferArrayCtx bufs[] = {
3353 /* *INDENT-OFF* */
3354 { 201, -1440, FALSE, 185591 },
3355 { 265, 1, FALSE, 0 },
3356 /* *INDENT-ON* */
3357 };
3358
3359 g_object_set (h->element, "do-lost", TRUE,
3360 "do-retransmission", TRUE,
3361 "rtx-next-seqnum", FALSE, "rtx-delay-reorder", 0, NULL);
3362
3363 fail_unless (check_for_stall (h, bufs, G_N_ELEMENTS (bufs)));
3364 gst_harness_teardown (h);
3365 }
3366
3367 GST_END_TEST;
3368
3369 static Suite *
rtpjitterbuffer_suite(void)3370 rtpjitterbuffer_suite (void)
3371 {
3372 Suite *s = suite_create ("rtpjitterbuffer");
3373 TCase *tc_chain = tcase_create ("general");
3374
3375 suite_add_tcase (s, tc_chain);
3376
3377 tcase_add_test (tc_chain, test_push_forward_seq);
3378 tcase_add_test (tc_chain, test_push_backward_seq);
3379 tcase_add_test (tc_chain, test_push_unordered);
3380 tcase_add_test (tc_chain, test_push_eos);
3381 tcase_add_test (tc_chain, test_basetime);
3382 tcase_add_test (tc_chain, test_clear_pt_map);
3383
3384 tcase_add_test (tc_chain, test_lost_event);
3385 tcase_add_test (tc_chain, test_only_one_lost_event_on_large_gaps);
3386 tcase_add_test (tc_chain, test_two_lost_one_arrives_in_time);
3387 tcase_add_test (tc_chain, test_late_packets_still_makes_lost_events);
3388 tcase_add_test (tc_chain, test_lost_event_uses_pts);
3389 tcase_add_test (tc_chain, test_lost_event_with_backwards_rtptime);
3390
3391 tcase_add_test (tc_chain, test_all_packets_are_timestamped_zero);
3392 tcase_add_loop_test (tc_chain, test_num_late_when_considered_lost_arrives, 0,
3393 2);
3394 tcase_add_test (tc_chain, test_reorder_of_non_equidistant_packets);
3395 tcase_add_test (tc_chain,
3396 test_loss_equidistant_spacing_with_parameter_packets);
3397 tcase_add_loop_test (tc_chain, test_no_fractional_lost_event_durations, 0,
3398 G_N_ELEMENTS (no_fractional_lost_event_durations_input));
3399 tcase_add_test (tc_chain, test_late_lost_with_same_pts);
3400
3401 tcase_add_test (tc_chain, test_rtx_expected_next);
3402 tcase_add_test (tc_chain, test_rtx_not_bursting_requests);
3403
3404 tcase_add_test (tc_chain, test_rtx_next_seqnum_disabled);
3405 tcase_add_test (tc_chain, test_rtx_two_missing);
3406 tcase_add_test (tc_chain, test_rtx_buffer_arrives_just_in_time);
3407 tcase_add_test (tc_chain, test_rtx_buffer_arrives_too_late);
3408 tcase_add_test (tc_chain, test_rtx_original_buffer_does_not_update_rtx_stats);
3409 tcase_add_test (tc_chain, test_rtx_duplicate_packet_updates_rtx_stats);
3410 tcase_add_test (tc_chain,
3411 test_rtx_buffer_arrives_after_lost_updates_rtx_stats);
3412 tcase_add_test (tc_chain, test_rtx_rtt_larger_than_retry_timeout);
3413 tcase_add_test (tc_chain, test_rtx_no_request_if_time_past_retry_period);
3414 tcase_add_test (tc_chain, test_rtx_same_delay_and_retry_timeout);
3415 tcase_add_test (tc_chain, test_rtx_with_backwards_rtptime);
3416 tcase_add_test (tc_chain, test_rtx_timer_reuse);
3417 tcase_add_test (tc_chain, test_rtx_large_packet_spacing_and_small_rtt);
3418 tcase_add_test (tc_chain, test_rtx_large_packet_spacing_and_large_rtt);
3419 tcase_add_test (tc_chain,
3420 test_rtx_large_packet_spacing_does_not_reset_jitterbuffer);
3421 tcase_add_test (tc_chain, test_minor_reorder_does_not_skew);
3422 tcase_add_loop_test (tc_chain, test_rtx_does_not_affect_pts_calculation, 0,
3423 G_N_ELEMENTS (rtx_does_not_affect_pts_calculation_input));
3424 tcase_add_test (tc_chain, test_dont_drop_packet_based_on_skew);
3425
3426 tcase_add_test (tc_chain, test_deadline_ts_offset);
3427 tcase_add_test (tc_chain, test_big_gap_seqnum);
3428 tcase_add_test (tc_chain, test_big_gap_arrival_time);
3429 tcase_add_test (tc_chain, test_fill_queue);
3430
3431 tcase_add_loop_test (tc_chain,
3432 test_considered_lost_packet_in_large_gap_arrives, 0,
3433 G_N_ELEMENTS (test_considered_lost_packet_in_large_gap_arrives_input));
3434
3435 tcase_add_test (tc_chain, test_performance);
3436
3437 tcase_add_test (tc_chain, test_drop_messages_too_late);
3438 tcase_add_test (tc_chain, test_drop_messages_drop_on_latency);
3439 tcase_add_test (tc_chain, test_drop_messages_interval);
3440
3441 tcase_add_test (tc_chain, test_reset_timers_does_not_stall);
3442 tcase_add_test (tc_chain, test_multiple_lost_do_not_stall);
3443 tcase_add_test (tc_chain, test_reset_using_rtx_packets_does_not_stall);
3444 tcase_add_test (tc_chain, test_gap_using_rtx_does_not_stall);
3445
3446
3447 return s;
3448 }
3449
3450 GST_CHECK_MAIN (rtpjitterbuffer);
3451