1 /* GStreamer
2 *
3 * Copyright (C) 2009 Nokia Corporation and its subsidary(-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
32 #include <gst/rtp/gstrtpbuffer.h>
33
34 /* For ease of programming we use globals to keep refs for our floating
35 * src and sink pads we create; otherwise we always have to do get_pad,
36 * get_peer, and then remove references in every test function */
37 static GstPad *mysrcpad, *mysinkpad;
38 /* we also have a list of src buffers */
39 static GList *inbuffers = NULL;
40 static gint num_dropped = 0;
41
42 #define RTP_CAPS_STRING \
43 "application/x-rtp, " \
44 "media = (string)audio, " \
45 "payload = (int) 0, " \
46 "clock-rate = (int) 8000, " \
47 "encoding-name = (string)PCMU"
48
49 #define RTP_FRAME_SIZE 20
50
51 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
52 GST_PAD_SINK,
53 GST_PAD_ALWAYS,
54 GST_STATIC_CAPS ("application/x-rtp")
55 );
56 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
57 GST_PAD_SRC,
58 GST_PAD_ALWAYS,
59 GST_STATIC_CAPS ("application/x-rtp, "
60 "clock-rate = (int) [ 1, 2147483647 ]")
61 );
62
63 static void
buffer_dropped(gpointer data,GstMiniObject * obj)64 buffer_dropped (gpointer data, GstMiniObject * obj)
65 {
66 GST_DEBUG ("dropping buffer %p", obj);
67 num_dropped++;
68 }
69
70 static GstElement *
setup_jitterbuffer(gint num_buffers)71 setup_jitterbuffer (gint num_buffers)
72 {
73 GstElement *jitterbuffer;
74 GstClock *clock;
75 GstBuffer *buffer;
76 GstCaps *caps;
77 /* a 20 sample audio block (2,5 ms) generated with
78 * gst-launch audiotestsrc wave=silence blocksize=40 num-buffers=3 !
79 * "audio/x-raw,channels=1,rate=8000" ! mulawenc ! rtppcmupay !
80 * fakesink dump=1
81 */
82 guint8 in[] = {
83 /* first 4 bytes are rtp-header, next 4 bytes are timestamp */
84 0x80, 0x80, 0x1c, 0x24, 0x46, 0xcd, 0xb7, 0x11, 0x3c, 0x3a, 0x7c, 0x5b,
85 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
86 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
87 };
88 GstClockTime ts = G_GUINT64_CONSTANT (0);
89 GstClockTime tso = gst_util_uint64_scale (RTP_FRAME_SIZE, GST_SECOND, 8000);
90 /*guint latency = GST_TIME_AS_MSECONDS (num_buffers * tso); */
91 gint i;
92
93 GST_DEBUG ("setup_jitterbuffer");
94 jitterbuffer = gst_check_setup_element ("rtpjitterbuffer");
95 /* we need a clock here */
96 clock = gst_system_clock_obtain ();
97 gst_element_set_clock (jitterbuffer, clock);
98 gst_object_unref (clock);
99 /* setup latency */
100 /* latency would be 7 for 3 buffers here, default is 200
101 g_object_set (G_OBJECT (jitterbuffer), "latency", latency, NULL);
102 GST_INFO_OBJECT (jitterbuffer, "set latency to %u ms", latency);
103 */
104
105 mysrcpad = gst_check_setup_src_pad (jitterbuffer, &srctemplate);
106 mysinkpad = gst_check_setup_sink_pad (jitterbuffer, &sinktemplate);
107 gst_pad_set_active (mysrcpad, TRUE);
108 gst_pad_set_active (mysinkpad, TRUE);
109
110 /* create n buffers */
111 caps = gst_caps_from_string (RTP_CAPS_STRING);
112 gst_check_setup_events (mysrcpad, jitterbuffer, caps, GST_FORMAT_TIME);
113 gst_caps_unref (caps);
114
115 for (i = 0; i < num_buffers; i++) {
116 buffer = gst_buffer_new_and_alloc (sizeof (in));
117 gst_buffer_fill (buffer, 0, in, sizeof (in));
118 GST_BUFFER_DTS (buffer) = ts;
119 GST_BUFFER_PTS (buffer) = ts;
120 GST_BUFFER_DURATION (buffer) = tso;
121 gst_mini_object_weak_ref (GST_MINI_OBJECT (buffer), buffer_dropped, NULL);
122 GST_DEBUG ("created buffer: %p", buffer);
123
124 if (!i)
125 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
126
127 inbuffers = g_list_append (inbuffers, buffer);
128
129 /* hackish way to update the rtp header */
130 in[1] = 0x00;
131 in[3]++; /* seqnumber */
132 in[7] += RTP_FRAME_SIZE; /* inc. timestamp with framesize */
133 ts += tso;
134 }
135 num_dropped = 0;
136
137 return jitterbuffer;
138 }
139
140 static GstStateChangeReturn
start_jitterbuffer(GstElement * jitterbuffer)141 start_jitterbuffer (GstElement * jitterbuffer)
142 {
143 GstStateChangeReturn ret;
144 GstClockTime now;
145 GstClock *clock;
146
147 clock = gst_element_get_clock (jitterbuffer);
148 now = gst_clock_get_time (clock);
149 gst_object_unref (clock);
150
151 gst_element_set_base_time (jitterbuffer, now);
152 ret = gst_element_set_state (jitterbuffer, GST_STATE_PLAYING);
153
154 return ret;
155 }
156
157 static void
cleanup_jitterbuffer(GstElement * jitterbuffer)158 cleanup_jitterbuffer (GstElement * jitterbuffer)
159 {
160 GST_DEBUG ("cleanup_jitterbuffer");
161
162 g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
163 g_list_free (buffers);
164 buffers = NULL;
165
166 g_list_free (inbuffers);
167 inbuffers = NULL;
168
169 gst_pad_set_active (mysrcpad, FALSE);
170 gst_pad_set_active (mysinkpad, FALSE);
171 gst_element_set_state (jitterbuffer, GST_STATE_NULL);
172 gst_check_teardown_src_pad (jitterbuffer);
173 gst_check_teardown_sink_pad (jitterbuffer);
174 gst_check_teardown_element (jitterbuffer);
175 }
176
177 static void
check_jitterbuffer_results(GstElement * jitterbuffer,gint num_buffers)178 check_jitterbuffer_results (GstElement * jitterbuffer, gint num_buffers)
179 {
180 GstBuffer *buffer;
181 GList *node;
182 GstClockTime ts = G_GUINT64_CONSTANT (0);
183 GstClockTime tso = gst_util_uint64_scale (RTP_FRAME_SIZE, GST_SECOND, 8000);
184 GstMapInfo map;
185 guint16 prev_sn = 0, cur_sn;
186 guint32 prev_ts = 0, cur_ts;
187
188 /* sleep for twice the latency */
189 g_usleep (400 * 1000);
190
191 GST_INFO ("of %d buffer %d/%d received/dropped", num_buffers,
192 g_list_length (buffers), num_dropped);
193 /* if this fails, not all buffers have been processed */
194 fail_unless_equals_int ((g_list_length (buffers) + num_dropped), num_buffers);
195
196 /* check the buffer list */
197 fail_unless_equals_int (g_list_length (buffers), num_buffers);
198 for (node = buffers; node; node = g_list_next (node)) {
199 fail_if ((buffer = (GstBuffer *) node->data) == NULL);
200 fail_if (GST_BUFFER_PTS (buffer) != ts);
201 fail_if (GST_BUFFER_DTS (buffer) != ts);
202 gst_buffer_map (buffer, &map, GST_MAP_READ);
203 cur_sn = ((guint16) map.data[2] << 8) | map.data[3];
204 cur_ts = ((guint32) map.data[4] << 24) | ((guint32) map.data[5] << 16) |
205 ((guint32) map.data[6] << 8) | map.data[7];
206 gst_buffer_unmap (buffer, &map);
207
208 if (node != buffers) {
209 fail_unless (cur_sn > prev_sn);
210 fail_unless (cur_ts > prev_ts);
211
212 prev_sn = cur_sn;
213 prev_ts = cur_ts;
214 }
215 ts += tso;
216 }
217 }
218
GST_START_TEST(test_push_forward_seq)219 GST_START_TEST (test_push_forward_seq)
220 {
221 GstElement *jitterbuffer;
222 const guint num_buffers = 3;
223 GstBuffer *buffer;
224 GList *node;
225
226 jitterbuffer = setup_jitterbuffer (num_buffers);
227 fail_unless (start_jitterbuffer (jitterbuffer)
228 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
229
230 /* push buffers: 0,1,2, */
231 for (node = inbuffers; node; node = g_list_next (node)) {
232 buffer = (GstBuffer *) node->data;
233 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
234 }
235
236 /* check the buffer list */
237 check_jitterbuffer_results (jitterbuffer, num_buffers);
238
239 /* cleanup */
240 cleanup_jitterbuffer (jitterbuffer);
241 }
242
243 GST_END_TEST;
244
GST_START_TEST(test_push_backward_seq)245 GST_START_TEST (test_push_backward_seq)
246 {
247 GstElement *jitterbuffer;
248 const guint num_buffers = 4;
249 GstBuffer *buffer;
250 GList *node;
251
252 jitterbuffer = setup_jitterbuffer (num_buffers);
253 fail_unless (start_jitterbuffer (jitterbuffer)
254 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
255
256 /* push buffers: 0,3,2,1 */
257 buffer = (GstBuffer *) inbuffers->data;
258 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
259 for (node = g_list_last (inbuffers); node != inbuffers;
260 node = g_list_previous (node)) {
261 buffer = (GstBuffer *) node->data;
262 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
263 }
264
265 /* check the buffer list */
266 check_jitterbuffer_results (jitterbuffer, num_buffers);
267
268 /* cleanup */
269 cleanup_jitterbuffer (jitterbuffer);
270 }
271
272 GST_END_TEST;
273
GST_START_TEST(test_push_unordered)274 GST_START_TEST (test_push_unordered)
275 {
276 GstElement *jitterbuffer;
277 const guint num_buffers = 4;
278 GstBuffer *buffer;
279
280 jitterbuffer = setup_jitterbuffer (num_buffers);
281 fail_unless (start_jitterbuffer (jitterbuffer)
282 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
283
284 /* push buffers; 0,2,1,3 */
285 buffer = (GstBuffer *) inbuffers->data;
286 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
287 buffer = g_list_nth_data (inbuffers, 2);
288 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
289 buffer = g_list_nth_data (inbuffers, 1);
290 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
291 buffer = g_list_nth_data (inbuffers, 3);
292 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
293
294 /* check the buffer list */
295 check_jitterbuffer_results (jitterbuffer, num_buffers);
296
297 /* cleanup */
298 cleanup_jitterbuffer (jitterbuffer);
299 }
300
301 GST_END_TEST;
302
303 gboolean is_eos;
304
305 static gboolean
eos_event_function(GstPad * pad,GstObject * parent,GstEvent * event)306 eos_event_function (GstPad * pad, GstObject * parent, GstEvent * event)
307 {
308 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
309 g_mutex_lock (&check_mutex);
310 is_eos = TRUE;
311 g_cond_signal (&check_cond);
312 g_mutex_unlock (&check_mutex);
313 }
314 gst_event_unref (event);
315 return TRUE;
316 }
317
GST_START_TEST(test_push_eos)318 GST_START_TEST (test_push_eos)
319 {
320 GstElement *jitterbuffer;
321 const guint num_buffers = 5;
322 GList *node;
323 GstStructure *stats;
324 guint64 pushed, lost, late, duplicates;
325 int n = 0;
326
327 is_eos = FALSE;
328
329 jitterbuffer = setup_jitterbuffer (num_buffers);
330 gst_pad_set_event_function (mysinkpad, eos_event_function);
331
332 g_object_set (jitterbuffer, "latency", 1, NULL);
333
334 fail_unless (start_jitterbuffer (jitterbuffer)
335 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
336
337 /* push buffers: 0,1,2, */
338 for (node = inbuffers; node; node = g_list_next (node)) {
339 GstBuffer *buffer;
340
341 /* steal buffer from list */
342 buffer = node->data;
343 node->data = NULL;
344
345 n++;
346 /* Skip 1 */
347 if (n == 2) {
348 gst_buffer_unref (buffer);
349 continue;
350 }
351 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
352 }
353
354 gst_pad_push_event (mysrcpad, gst_event_new_eos ());
355
356 g_mutex_lock (&check_mutex);
357 while (!is_eos)
358 g_cond_wait (&check_cond, &check_mutex);
359 g_mutex_unlock (&check_mutex);
360
361 fail_unless_equals_int (g_list_length (buffers), num_buffers - 1);
362
363 /* Verify statistics */
364 g_object_get (jitterbuffer, "stats", &stats, NULL);
365 gst_structure_get (stats, "num-pushed", G_TYPE_UINT64, &pushed,
366 "num-lost", G_TYPE_UINT64, &lost,
367 "num-late", G_TYPE_UINT64, &late,
368 "num-duplicates", G_TYPE_UINT64, &duplicates, NULL);
369 fail_unless_equals_int (pushed, g_list_length (inbuffers) - 1);
370 fail_unless_equals_int (lost, 1);
371 fail_unless_equals_int (late, 0);
372 fail_unless_equals_int (duplicates, 0);
373 gst_structure_free (stats);
374
375 /* cleanup */
376 cleanup_jitterbuffer (jitterbuffer);
377 }
378
379 GST_END_TEST;
380
GST_START_TEST(test_basetime)381 GST_START_TEST (test_basetime)
382 {
383 GstElement *jitterbuffer;
384 const guint num_buffers = 3;
385 GstBuffer *buffer;
386 GList *node;
387 GstClockTime tso = gst_util_uint64_scale (RTP_FRAME_SIZE, GST_SECOND, 8000);
388
389 jitterbuffer = setup_jitterbuffer (num_buffers);
390 fail_unless (start_jitterbuffer (jitterbuffer)
391 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
392
393 /* push buffers: 2,1,0 */
394 for (node = g_list_last (inbuffers); node; node = g_list_previous (node)) {
395 buffer = (GstBuffer *) node->data;
396 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
397 }
398
399 /* sleep for twice the latency */
400 g_usleep (400 * 1000);
401
402 /* if this fails, not all buffers have been processed */
403 fail_unless_equals_int ((g_list_length (buffers) + num_dropped), num_buffers);
404
405 buffer = (GstBuffer *) buffers->data;
406 fail_unless (GST_BUFFER_DTS (buffer) != (num_buffers * tso));
407 fail_unless (GST_BUFFER_PTS (buffer) != (num_buffers * tso));
408
409 /* cleanup */
410 cleanup_jitterbuffer (jitterbuffer);
411 }
412
413 GST_END_TEST;
414
415 static GstCaps *
request_pt_map(GstElement * jitterbuffer,guint pt)416 request_pt_map (GstElement * jitterbuffer, guint pt)
417 {
418 fail_unless (pt == 0);
419
420 return gst_caps_from_string (RTP_CAPS_STRING);
421 }
422
GST_START_TEST(test_clear_pt_map)423 GST_START_TEST (test_clear_pt_map)
424 {
425 GstElement *jitterbuffer;
426 const guint num_buffers = 10;
427 gint i;
428 GstBuffer *buffer;
429 GList *node;
430
431 jitterbuffer = setup_jitterbuffer (num_buffers);
432 fail_unless (start_jitterbuffer (jitterbuffer)
433 == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
434
435 g_signal_connect (jitterbuffer, "request-pt-map", (GCallback)
436 request_pt_map, NULL);
437
438 /* push buffers: 0,1,2, */
439 for (node = inbuffers, i = 0; node && i < 3; node = g_list_next (node), i++) {
440 buffer = (GstBuffer *) node->data;
441 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
442 }
443
444 g_usleep (400 * 1000);
445
446 g_signal_emit_by_name (jitterbuffer, "clear-pt-map", NULL);
447
448 for (; node && i < 10; node = g_list_next (node), i++) {
449 buffer = (GstBuffer *) node->data;
450 fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
451 }
452
453 /* check the buffer list */
454 check_jitterbuffer_results (jitterbuffer, num_buffers);
455
456 /* cleanup */
457 cleanup_jitterbuffer (jitterbuffer);
458 }
459
460 GST_END_TEST;
461
462 #define TEST_BUF_CLOCK_RATE 8000
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 (TEST_BUF_CLOCK_RATE * TEST_BUF_MS / 1000)
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 gint
get_rtp_seq_num(GstBuffer * buf)532 get_rtp_seq_num (GstBuffer * buf)
533 {
534 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
535 gint seq;
536 gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
537 seq = gst_rtp_buffer_get_seq (&rtp);
538 gst_rtp_buffer_unmap (&rtp);
539 return seq;
540 }
541
542 #define verify_lost_event(h, exp_seq, exp_ts, exp_dur) \
543 G_STMT_START { \
544 GstEvent *_event; \
545 const GstStructure *_s; \
546 const GValue *_value; \
547 guint _seq; \
548 GstClockTime _ts; \
549 GstClockTime _dur; \
550 _event = gst_harness_pull_event (h); \
551 fail_unless (_event != NULL); \
552 _s = gst_event_get_structure (_event); \
553 fail_unless (_s != NULL); \
554 fail_unless (gst_structure_get_uint (_s, "seqnum", &_seq)); \
555 _value = gst_structure_get_value (_s, "timestamp"); \
556 fail_unless (_value && G_VALUE_HOLDS_UINT64 (_value)); \
557 _ts = g_value_get_uint64 (_value); \
558 _value = gst_structure_get_value (_s, "duration"); \
559 fail_unless (_value && G_VALUE_HOLDS_UINT64 (_value)); \
560 _dur = g_value_get_uint64 (_value); \
561 fail_unless_equals_int ((guint16)(exp_seq), _seq); \
562 fail_unless_equals_uint64 (exp_ts, _ts); \
563 fail_unless_equals_uint64 (exp_dur, _dur); \
564 gst_event_unref (_event); \
565 } G_STMT_END
566
567
568 #define verify_rtx_event(h, exp_seq, exp_ts, exp_delay, exp_spacing) \
569 G_STMT_START { \
570 GstEvent *_event; \
571 const GstStructure *_s; \
572 const GValue *_value; \
573 guint _seq; \
574 GstClockTime _ts; \
575 guint _delay; \
576 GstClockTime _spacing; \
577 _event = gst_harness_pull_upstream_event (h); \
578 fail_unless (_event != NULL); \
579 _s = gst_event_get_structure (_event); \
580 fail_unless (_s != NULL); \
581 fail_unless (gst_structure_get_uint (_s, "seqnum", &_seq)); \
582 _value = gst_structure_get_value (_s, "running-time"); \
583 fail_unless (_value && G_VALUE_HOLDS_UINT64 (_value)); \
584 _ts = g_value_get_uint64 (_value); \
585 fail_unless (gst_structure_get_uint (_s, "delay", &_delay)); \
586 _value = gst_structure_get_value (_s, "packet-spacing"); \
587 fail_unless (_value && G_VALUE_HOLDS_UINT64 (_value)); \
588 _spacing = g_value_get_uint64 (_value); \
589 fail_unless_equals_int ((guint16)(exp_seq), _seq); \
590 fail_unless_equals_uint64 (exp_ts, _ts); \
591 fail_unless_equals_int (exp_delay, _delay); \
592 fail_unless_equals_uint64 (exp_spacing, _spacing); \
593 gst_event_unref (_event); \
594 } G_STMT_END
595
596 static gboolean
verify_jb_stats(GstElement * jb,GstStructure * expected)597 verify_jb_stats (GstElement * jb, GstStructure * expected)
598 {
599 gboolean ret;
600 GstStructure *actual;
601 g_object_get (jb, "stats", &actual, NULL);
602
603 ret = gst_structure_is_subset (actual, expected);
604
605 if (!ret) {
606 gchar *e_str = gst_structure_to_string (expected);
607 gchar *a_str = gst_structure_to_string (actual);
608 fail_unless (ret, "%s is not a subset of %s", e_str, a_str);
609 g_free (e_str);
610 g_free (a_str);
611 }
612
613 gst_structure_free (expected);
614 gst_structure_free (actual);
615
616 return ret;
617 }
618
619 static guint
construct_deterministic_initial_state(GstHarness * h,gint latency_ms)620 construct_deterministic_initial_state (GstHarness * h, gint latency_ms)
621 {
622 guint next_seqnum = latency_ms / TEST_BUF_MS + 1;
623 guint seqnum;
624 gint i;
625
626 g_assert (latency_ms % TEST_BUF_MS == 0);
627
628 gst_harness_set_src_caps (h, generate_caps ());
629 g_object_set (h->element, "latency", latency_ms, NULL);
630
631 /* When the first packet arrives in the jitterbuffer, it will create a
632 * timeout for this packet equal to the latency of the jitterbuffer.
633 * This is known as DEADLINE internally, and is meant to allow the stream
634 * to buffer a bit before starting to push it out, to get some ideas about
635 * the nature of the stream. (packetspacing, jitter etc.)
636 *
637 * When writing tests using the test-clock, it it hence important to know
638 * that by simply advancing the clock to this timeout, you are basically
639 * describing a stream that had one initial packet, and then nothing at all
640 * for the duration of the latency (100ms in this test), which is not a very
641 * usual scenario.
642 *
643 * Instead, a pattern used throughout this test-suite, is to keep the buffers
644 * arriving at their optimal time, until the DEADLINE is reached, and that
645 * then becomes the "starting-point" for the test, because at this time
646 * there should now be no waiting timers (unless using rtx) and we have
647 * a "clean" state to craft the test from.
648 */
649
650 /* Packet 0 arrives at time 0ms, Packet 5 arrives at time 100ms */
651 for (seqnum = 0; seqnum < next_seqnum; seqnum++) {
652 push_test_buffer (h, seqnum);
653 gst_harness_wait_for_clock_id_waits (h, 1, 60);
654 }
655
656 /* We release the DEADLINE timer for packet 0, verify the time is indeed
657 * @latency_ms (100ms) and pull out all the buffers that have been released,
658 * and verify their PTS and sequence numbers.
659 */
660 gst_harness_crank_single_clock_wait (h);
661 fail_unless_equals_int64 (latency_ms * GST_MSECOND,
662 gst_clock_get_time (GST_ELEMENT_CLOCK (h->element)));
663 for (seqnum = 0; seqnum < next_seqnum; seqnum++) {
664 GstBuffer *buf = gst_harness_pull (h);
665 fail_unless_equals_uint64 (seqnum * TEST_BUF_DURATION,
666 GST_BUFFER_PTS (buf));
667 fail_unless_equals_int (seqnum, get_rtp_seq_num (buf));
668 gst_buffer_unref (buf);
669 }
670
671 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
672 for (i = 0; i < 3; i++)
673 gst_event_unref (gst_harness_pull_event (h));
674
675 /* drop reconfigure event */
676 gst_event_unref (gst_harness_pull_upstream_event (h));
677
678 /* Verify that at this point our queues are empty */
679 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h));
680 fail_unless_equals_int (0, gst_harness_events_in_queue (h));
681
682 return next_seqnum;
683 }
684
GST_START_TEST(test_lost_event)685 GST_START_TEST (test_lost_event)
686 {
687 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
688 GstBuffer *buf;
689 gint latency_ms = 100;
690 guint next_seqnum;
691 guint missing_seqnum;
692
693 g_object_set (h->element, "do-lost", TRUE, NULL);
694 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
695
696 /* We will now create a gap in the stream, by skipping one sequence-number,
697 * and push the following packet.
698 */
699 missing_seqnum = next_seqnum;
700 next_seqnum += 1;
701 push_test_buffer (h, next_seqnum);
702
703 /* This packet (@next_seqnum) will now be held back, awaiting the missing one,
704 * verify that this is the case:
705 */
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 /* The lost-timeout for the missing packet will now be its pts + latency, so
710 * now we will simply crank the clock to advance to this point in time, and
711 * check that we get a lost-event, as well as the last packet we pushed in.
712 */
713 gst_harness_crank_single_clock_wait (h);
714 verify_lost_event (h, missing_seqnum,
715 missing_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION);
716
717 buf = gst_harness_pull (h);
718 fail_unless_equals_uint64 (next_seqnum * TEST_BUF_DURATION,
719 GST_BUFFER_PTS (buf));
720 fail_unless_equals_int (next_seqnum, get_rtp_seq_num (buf));
721 gst_buffer_unref (buf);
722
723 fail_unless (verify_jb_stats (h->element,
724 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
725 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
726 "num-lost", G_TYPE_UINT64, (guint64) 1, NULL)));
727
728 gst_harness_teardown (h);
729 }
730
731 GST_END_TEST;
732
GST_START_TEST(test_only_one_lost_event_on_large_gaps)733 GST_START_TEST (test_only_one_lost_event_on_large_gaps)
734 {
735 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
736 GstTestClock *testclock;
737 GstBuffer *out_buf;
738 guint next_seqnum;
739 gint latency_ms = 200;
740 gint num_lost_events = latency_ms / TEST_BUF_MS;
741 gint i;
742
743 testclock = gst_harness_get_testclock (h);
744 /* Need to set max-misorder-time and max-dropout-time to 0 so the
745 * jitterbuffer does not base them on packet rate calculations.
746 * If it does, out gap is big enough to be considered a new stream and
747 * we wait for a few consecutive packets just to be sure
748 */
749 g_object_set (h->element, "do-lost", TRUE,
750 "max-misorder-time", 0, "max-dropout-time", 0, NULL);
751 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
752
753 /* move time ahead to just before 10 seconds */
754 gst_harness_set_time (h, 10 * GST_SECOND - 1);
755
756 /* check that we have no pending waits */
757 fail_unless_equals_int (0, gst_test_clock_peek_id_count (testclock));
758
759 /* a buffer now arrives perfectly on time */
760 fail_unless_equals_int (GST_FLOW_OK,
761 gst_harness_push (h, generate_test_buffer (500)));
762
763 /* release the wait, advancing the clock to 10 sec */
764 fail_unless (gst_harness_crank_single_clock_wait (h));
765
766 /* we should now receive a packet-lost-event for buffers 11 through 489 ... */
767 verify_lost_event (h, next_seqnum,
768 next_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION * (490 - next_seqnum));
769
770 /* ... as well as 490 (since at 10 sec 490 is too late) */
771 verify_lost_event (h, 490, 490 * TEST_BUF_DURATION, TEST_BUF_DURATION);
772
773 /* we get as many lost events as the the number of *
774 * buffers the jitterbuffer is able to wait for */
775 for (i = 1; i < num_lost_events; i++) {
776 fail_unless (gst_harness_crank_single_clock_wait (h));
777 verify_lost_event (h, 490 + i, (490 + i) * TEST_BUF_DURATION,
778 TEST_BUF_DURATION);
779 }
780
781 /* and then the buffer is released */
782 out_buf = gst_harness_pull (h);
783 fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DISCONT));
784 fail_unless_equals_int (500, get_rtp_seq_num (out_buf));
785 fail_unless_equals_uint64 (10 * GST_SECOND, GST_BUFFER_DTS (out_buf));
786 fail_unless_equals_uint64 (10 * GST_SECOND, GST_BUFFER_PTS (out_buf));
787 gst_buffer_unref (out_buf);
788
789 fail_unless (verify_jb_stats (h->element,
790 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
791 "num-lost", G_TYPE_UINT64, (guint64) 489, NULL)));
792
793 gst_object_unref (testclock);
794 gst_harness_teardown (h);
795 }
796
797 GST_END_TEST;
798
GST_START_TEST(test_two_lost_one_arrives_in_time)799 GST_START_TEST (test_two_lost_one_arrives_in_time)
800 {
801 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
802 GstTestClock *testclock;
803 GstClockID id;
804 GstBuffer *buf;
805 gint latency_ms = 100;
806 guint next_seqnum;
807 guint first_missing;
808 guint second_missing;
809 guint current_arrived;
810
811 testclock = gst_harness_get_testclock (h);
812 g_object_set (h->element, "do-lost", TRUE, NULL);
813 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
814
815 /* hop over 2 packets and make another one (gap of 2) */
816 first_missing = next_seqnum;
817 second_missing = next_seqnum + 1;
818 current_arrived = next_seqnum + 2;
819 push_test_buffer (h, current_arrived);
820
821 /* verify that the jitterbuffer now wait for the latest moment it can push the
822 * @first_missing packet out.
823 */
824 gst_test_clock_wait_for_next_pending_id (testclock, &id);
825 fail_unless_equals_uint64 (first_missing * TEST_BUF_DURATION +
826 latency_ms * GST_MSECOND, gst_clock_id_get_time (id));
827 gst_clock_id_unref (id);
828
829 /* let the time expire... */
830 fail_unless (gst_harness_crank_single_clock_wait (h));
831
832 /* we should now receive a packet-lost-event */
833 verify_lost_event (h, first_missing,
834 first_missing * TEST_BUF_DURATION, TEST_BUF_DURATION);
835
836 /* @second_missing now arrives just in time */
837 fail_unless_equals_int (GST_FLOW_OK,
838 gst_harness_push (h, generate_test_buffer (second_missing)));
839
840 /* verify that @second_missing made it through! */
841 buf = gst_harness_pull (h);
842 fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
843 fail_unless_equals_int (second_missing, get_rtp_seq_num (buf));
844 gst_buffer_unref (buf);
845
846 /* and see that @current_arrived now also is pushed */
847 buf = gst_harness_pull (h);
848 fail_unless (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
849 fail_unless_equals_int (current_arrived, get_rtp_seq_num (buf));
850 gst_buffer_unref (buf);
851
852 fail_unless (verify_jb_stats (h->element,
853 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
854 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 2,
855 "num-lost", G_TYPE_UINT64, (guint64) 1, NULL)));
856
857 gst_object_unref (testclock);
858 gst_harness_teardown (h);
859 }
860
861 GST_END_TEST;
862
GST_START_TEST(test_late_packets_still_makes_lost_events)863 GST_START_TEST (test_late_packets_still_makes_lost_events)
864 {
865 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
866 GstBuffer *out_buf;
867 gint latency_ms = 100;
868 guint next_seqnum;
869 guint seqnum;
870 GstClockTime now;
871
872 g_object_set (h->element, "do-lost", TRUE, NULL);
873 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
874
875 /* jump 10 seconds forward in time */
876 now = 10 * GST_SECOND;
877 gst_harness_set_time (h, now);
878
879 /* push a packet with a gap of 2, that now is very late */
880 seqnum = next_seqnum + 2;
881 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
882 generate_test_buffer_full (now,
883 seqnum, seqnum * TEST_RTP_TS_DURATION)));
884
885 /* we should now receive packet-lost-events for the gap
886 * FIXME: The timeout and duration here are a bit crap...
887 */
888 verify_lost_event (h, next_seqnum, 3400 * GST_MSECOND, 6500 * GST_MSECOND);
889 verify_lost_event (h, next_seqnum + 1,
890 9900 * GST_MSECOND, 3300 * GST_MSECOND);
891
892 /* verify that packet @seqnum made it through! */
893 out_buf = gst_harness_pull (h);
894 fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DISCONT));
895 fail_unless_equals_int (seqnum, get_rtp_seq_num (out_buf));
896 gst_buffer_unref (out_buf);
897
898 fail_unless (verify_jb_stats (h->element,
899 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
900 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 1,
901 "num-lost", G_TYPE_UINT64, (guint64) 2, NULL)));
902
903 gst_harness_teardown (h);
904 }
905
906 GST_END_TEST;
907
908
GST_START_TEST(test_num_late_when_considered_lost_arrives)909 GST_START_TEST (test_num_late_when_considered_lost_arrives)
910 {
911 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
912 gboolean do_lost = __i__ != 0;
913 gint latency_ms = 100;
914 guint next_seqnum;
915
916 g_object_set (h->element, "do-lost", do_lost, NULL);
917 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
918
919 /* gap of 1 */
920 push_test_buffer (h, next_seqnum + 1);
921
922 /* crank to trigger lost-event */
923 gst_harness_crank_single_clock_wait (h);
924
925 if (do_lost) {
926 /* we should now receive packet-lost-events for the missing packet */
927 verify_lost_event (h, next_seqnum,
928 next_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION);
929 }
930
931 /* pull out the pushed packet */
932 gst_buffer_unref (gst_harness_pull (h));
933
934 /* we have one lost packet in the stats */
935 fail_unless (verify_jb_stats (h->element,
936 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
937 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 1,
938 "num-lost", G_TYPE_UINT64, (guint64) 1,
939 "num-late", G_TYPE_UINT64, (guint64) 0, NULL)));
940
941 /* the missing packet now arrives (too late) */
942 fail_unless_equals_int (GST_FLOW_OK,
943 gst_harness_push (h, generate_test_buffer (next_seqnum)));
944
945 /* and this increments num-late */
946 fail_unless (verify_jb_stats (h->element,
947 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
948 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 1,
949 "num-lost", G_TYPE_UINT64, (guint64) 1,
950 "num-late", G_TYPE_UINT64, (guint64) 1, NULL)));
951
952 gst_harness_teardown (h);
953 }
954
955 GST_END_TEST;
956
GST_START_TEST(test_lost_event_uses_pts)957 GST_START_TEST (test_lost_event_uses_pts)
958 {
959 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
960 GstClockTime now;
961 gint latency_ms = 100;
962 guint next_seqnum;
963 guint lost_seqnum;
964
965 g_object_set (h->element, "do-lost", TRUE, NULL);
966 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
967
968 /* hop over 1 packets and make another one (gap of 1), but due to
969 network delays, this packets is also grossly late */
970 lost_seqnum = next_seqnum;
971 next_seqnum += 1;
972
973 /* advance the clock to the latest time packet @next_seqnum could arrive */
974 now = next_seqnum * TEST_BUF_DURATION + latency_ms * GST_MSECOND;
975 gst_harness_set_time (h, now);
976 gst_harness_push (h, generate_test_buffer_full (now, next_seqnum,
977 next_seqnum * TEST_RTP_TS_DURATION));
978
979 /* we should now have received a packet-lost-event for buffer 3 */
980 verify_lost_event (h, lost_seqnum,
981 lost_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION);
982
983 /* and pull out packet 4 */
984 gst_buffer_unref (gst_harness_pull (h));
985
986 fail_unless (verify_jb_stats (h->element,
987 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
988 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
989 "num-lost", G_TYPE_UINT64, (guint64) 1, NULL)));
990
991 gst_harness_teardown (h);
992 }
993
994 GST_END_TEST;
995
GST_START_TEST(test_lost_event_with_backwards_rtptime)996 GST_START_TEST (test_lost_event_with_backwards_rtptime)
997 {
998 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
999 gint latency_ms = 40;
1000
1001 g_object_set (h->element, "do-lost", TRUE, NULL);
1002 construct_deterministic_initial_state (h, latency_ms);
1003
1004 /*
1005 * For video using B-frames, an expected sequence
1006 * could be like this:
1007 * (I = I-frame, P = P-frame, B = B-frame)
1008 * ___ ___ ___ ___ ___
1009 * ... | 3 | | 4 | | 5 | | 6 | | 7 |
1010 * ––– ––– ––– ––– –––
1011 * rtptime: 3(I) 5(P) 5(P) 4(B) 6(P)
1012 * arrival(dts): 3 5 5 5 6
1013 *
1014 * Notice here that packet 6 (the B frame) make
1015 * the rtptime go backwards.
1016 *
1017 * But we get this:
1018 * ___ ___ _ _ ___ ___
1019 * ... | 3 | | 4 | | | | 6 | | 7 |
1020 * ––– ––– - - ––– –––
1021 * rtptime: 3(I) 5(P) 4(B) 6(P)
1022 * arrival(dts): 3 5 5 6
1023 *
1024 */
1025
1026 /* seqnum 3 */
1027 push_test_buffer (h, 3);
1028 gst_buffer_unref (gst_harness_pull (h));
1029
1030 /* seqnum 4, arriving at time 5 with rtptime 5 */
1031 gst_harness_push (h,
1032 generate_test_buffer_full (5 * TEST_BUF_DURATION,
1033 4, 5 * TEST_RTP_TS_DURATION));
1034 gst_buffer_unref (gst_harness_pull (h));
1035
1036 /* seqnum 6, arriving at time 5 with rtptime 4,
1037 making a gap for missing seqnum 5 */
1038 gst_harness_push (h,
1039 generate_test_buffer_full (5 * TEST_BUF_DURATION,
1040 6, 4 * TEST_RTP_TS_DURATION));
1041
1042 /* seqnum 7, arriving at time 6 with rtptime 6 */
1043 gst_harness_push (h,
1044 generate_test_buffer_full (6 * TEST_BUF_DURATION,
1045 7, 6 * TEST_RTP_TS_DURATION));
1046
1047 /* we should now have received a packet-lost-event for seqnum 5,
1048 with time 5 and 0 duration */
1049 gst_harness_crank_single_clock_wait (h);
1050 verify_lost_event (h, 5, 5 * TEST_BUF_DURATION, 0);
1051
1052 /* and pull out 6 and 7 */
1053 gst_buffer_unref (gst_harness_pull (h));
1054 gst_buffer_unref (gst_harness_pull (h));
1055
1056 fail_unless (verify_jb_stats (h->element,
1057 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1058 "num-pushed", G_TYPE_UINT64, (guint64) 7,
1059 "num-lost", G_TYPE_UINT64, (guint64) 1, NULL)));
1060
1061 gst_harness_teardown (h);
1062 }
1063
1064 GST_END_TEST;
1065
GST_START_TEST(test_all_packets_are_timestamped_zero)1066 GST_START_TEST (test_all_packets_are_timestamped_zero)
1067 {
1068 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1069 GstBuffer *out_buf;
1070 gint jb_latency_ms = 100;
1071 gint i, b;
1072
1073 gst_harness_set_src_caps (h, generate_caps ());
1074 g_object_set (h->element, "do-lost", TRUE, "latency", jb_latency_ms, NULL);
1075
1076 /* advance the clock with 10 seconds */
1077 gst_harness_set_time (h, 10 * GST_SECOND);
1078
1079 /* push the first buffer through */
1080 gst_buffer_unref (gst_harness_push_and_pull (h, generate_test_buffer (0)));
1081
1082 /* push some buffers in, all timestamped 0 */
1083 for (b = 1; b < 3; b++) {
1084 fail_unless_equals_int (GST_FLOW_OK,
1085 gst_harness_push (h,
1086 generate_test_buffer_full (0 * GST_MSECOND, b, 0)));
1087
1088 /* check for the buffer coming out that was pushed in */
1089 out_buf = gst_harness_pull (h);
1090 fail_unless_equals_uint64 (0, GST_BUFFER_DTS (out_buf));
1091 fail_unless_equals_uint64 (0, GST_BUFFER_PTS (out_buf));
1092 gst_buffer_unref (out_buf);
1093 }
1094
1095 /* hop over 2 packets and make another one (gap of 2) */
1096 b = 5;
1097 fail_unless_equals_int (GST_FLOW_OK,
1098 gst_harness_push (h, generate_test_buffer_full (0 * GST_MSECOND, b, 0)));
1099
1100 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
1101 for (i = 0; i < 3; i++)
1102 gst_event_unref (gst_harness_pull_event (h));
1103
1104 /* we should now receive packet-lost-events for buffer 3 and 4 */
1105 verify_lost_event (h, 3, 0, 0);
1106 verify_lost_event (h, 4, 0, 0);
1107
1108 /* verify that buffer 5 made it through! */
1109 out_buf = gst_harness_pull (h);
1110 fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DISCONT));
1111 fail_unless_equals_int (5, get_rtp_seq_num (out_buf));
1112 gst_buffer_unref (out_buf);
1113
1114 fail_unless (verify_jb_stats (h->element,
1115 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1116 "num-pushed", G_TYPE_UINT64, (guint64) 4,
1117 "num-lost", G_TYPE_UINT64, (guint64) 2, NULL)));
1118
1119 gst_harness_teardown (h);
1120 }
1121
1122 GST_END_TEST;
1123
GST_START_TEST(test_reorder_of_non_equidistant_packets)1124 GST_START_TEST (test_reorder_of_non_equidistant_packets)
1125 {
1126 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1127 GstTestClock *testclock;
1128 gint latency_ms = 5;
1129 GstClockID pending_id;
1130 GstClockTime time;
1131 gint seq, frame;
1132 gint num_init_frames = 1;
1133 const GstClockTime frame_dur = TEST_BUF_DURATION;
1134 const guint32 frame_rtp_ts_dur = TEST_RTP_TS_DURATION;
1135
1136 gst_harness_set_src_caps (h, generate_caps ());
1137 testclock = gst_harness_get_testclock (h);
1138 g_object_set (h->element, "do-lost", TRUE, "latency", latency_ms, NULL);
1139
1140 for (frame = 0, seq = 0; frame < num_init_frames; frame++, seq += 2) {
1141 /* Push a couple of packets with identical timestamp, typical for a video
1142 * stream where one frame generates multiple packets. */
1143 gst_harness_set_time (h, frame * frame_dur);
1144 gst_harness_push (h, generate_test_buffer_full (frame * frame_dur,
1145 seq, frame * frame_rtp_ts_dur));
1146 gst_harness_push (h, generate_test_buffer_full (frame * frame_dur,
1147 seq + 1, frame * frame_rtp_ts_dur));
1148
1149 if (frame == 0)
1150 /* deadline for buffer 0 expires */
1151 gst_harness_crank_single_clock_wait (h);
1152
1153 gst_buffer_unref (gst_harness_pull (h));
1154 gst_buffer_unref (gst_harness_pull (h));
1155 }
1156
1157 /* Finally push the last frame reordered */
1158 gst_harness_set_time (h, frame * frame_dur);
1159 gst_harness_push (h, generate_test_buffer_full (frame * frame_dur,
1160 seq + 1, frame * frame_rtp_ts_dur));
1161
1162 /* Check the scheduled lost timer. The expected arrival of this packet
1163 * should be assumed to be the same as the last packet received since we
1164 * don't know wether the missing packet belonged to this or previous
1165 * frame. */
1166 gst_test_clock_wait_for_next_pending_id (testclock, &pending_id);
1167 time = gst_clock_id_get_time (pending_id);
1168 fail_unless_equals_int64 (time, frame * frame_dur + latency_ms * GST_MSECOND);
1169 gst_clock_id_unref (pending_id);
1170
1171 /* And then missing packet arrives just in time */
1172 gst_harness_set_time (h, time - 1);
1173 gst_harness_push (h, generate_test_buffer_full (time - 1, seq,
1174 frame * frame_rtp_ts_dur));
1175
1176 gst_buffer_unref (gst_harness_pull (h));
1177 gst_buffer_unref (gst_harness_pull (h));
1178
1179 gst_object_unref (testclock);
1180 gst_harness_teardown (h);
1181 }
1182
1183 GST_END_TEST;
1184
GST_START_TEST(test_loss_equidistant_spacing_with_parameter_packets)1185 GST_START_TEST (test_loss_equidistant_spacing_with_parameter_packets)
1186 {
1187 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1188 gint latency_ms = 5;
1189 gint seq, frame;
1190 gint num_init_frames = 10;
1191 gint i;
1192
1193 gst_harness_set_src_caps (h, generate_caps ());
1194 g_object_set (h->element, "do-lost", TRUE, "latency", latency_ms, NULL);
1195
1196 /* drop stream-start, caps, segment */
1197 for (i = 0; i < 3; i++)
1198 gst_event_unref (gst_harness_pull_event (h));
1199
1200 for (frame = 0, seq = 0; frame < num_init_frames; frame++, seq++) {
1201 gst_harness_set_time (h, frame * TEST_BUF_DURATION);
1202 gst_harness_push (h, generate_test_buffer_full (frame * TEST_BUF_DURATION,
1203 seq, frame * TEST_RTP_TS_DURATION));
1204
1205 if (frame == 0)
1206 /* deadline for buffer 0 expires */
1207 gst_harness_crank_single_clock_wait (h);
1208
1209 gst_buffer_unref (gst_harness_pull (h));
1210 }
1211
1212 /* Push three packets with same rtptime, simulating parameter packets +
1213 * frame. This should not disable equidistant mode as it is common for
1214 * certain audio codecs. */
1215 for (i = 0; i < 3; i++) {
1216 gst_harness_set_time (h, frame * TEST_BUF_DURATION);
1217 gst_harness_push (h, generate_test_buffer_full (frame * TEST_BUF_DURATION,
1218 seq++, frame * TEST_RTP_TS_DURATION));
1219 gst_buffer_unref (gst_harness_pull (h));
1220 }
1221 frame++;
1222
1223 /* Finally push the last packet introducing a gap */
1224 gst_harness_set_time (h, frame * TEST_BUF_DURATION);
1225 gst_harness_push (h, generate_test_buffer_full (frame * TEST_BUF_DURATION,
1226 seq + 1, frame * TEST_RTP_TS_DURATION));
1227
1228 /* Check that the lost event has been generated assuming equidistant
1229 * spacing. */
1230 verify_lost_event (h, seq,
1231 frame * TEST_BUF_DURATION - TEST_BUF_DURATION / 2, TEST_BUF_DURATION / 2);
1232
1233 gst_buffer_unref (gst_harness_pull (h));
1234
1235 gst_harness_teardown (h);
1236 }
1237
1238 GST_END_TEST;
1239
1240
1241 static void
gst_test_clock_set_time_and_process(GstTestClock * testclock,GstClockTime time)1242 gst_test_clock_set_time_and_process (GstTestClock * testclock,
1243 GstClockTime time)
1244 {
1245 GstClockID id, tid;
1246 gst_test_clock_wait_for_next_pending_id (testclock, &id);
1247 gst_test_clock_set_time (testclock, time);
1248 tid = gst_test_clock_process_next_clock_id (testclock);
1249 g_assert (tid == id);
1250 gst_clock_id_unref (tid);
1251 gst_clock_id_unref (id);
1252 }
1253
GST_START_TEST(test_rtx_expected_next)1254 GST_START_TEST (test_rtx_expected_next)
1255 {
1256 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1257 gint latency_ms = 200;
1258 guint next_seqnum;
1259 GstClockTime timeout;
1260 gint rtx_delay_ms;
1261 const GstClockTime rtx_retry_timeout_ms = 40;
1262
1263 g_object_set (h->element, "do-lost", TRUE, NULL);
1264 g_object_set (h->element, "do-retransmission", TRUE, NULL);
1265 g_object_set (h->element, "rtx-retry-period", 120, NULL);
1266 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1267
1268 /* At this point there is already existing a rtx-timer for @next_seqnum,
1269 * that will have a timeout of the expected arrival-time for that seqnum,
1270 * and a delay equal to 2*jitter==0 and 0.5*packet_spacing==10ms */
1271 timeout = next_seqnum * TEST_BUF_DURATION;
1272 rtx_delay_ms = 0.5 * TEST_BUF_MS;
1273
1274 /* We crank the clock to time-out the next scheduled timer */
1275 gst_harness_crank_single_clock_wait (h);
1276 verify_rtx_event (h, next_seqnum, timeout, rtx_delay_ms, TEST_BUF_DURATION);
1277
1278 /* now we wait for the next timeout, all following timeouts 40ms in the
1279 * future because this is rtx-retry-timeout */
1280 rtx_delay_ms += rtx_retry_timeout_ms;
1281 gst_harness_crank_single_clock_wait (h);
1282 verify_rtx_event (h, next_seqnum, timeout, rtx_delay_ms, TEST_BUF_DURATION);
1283
1284 /* And a third time... */
1285 rtx_delay_ms += rtx_retry_timeout_ms;
1286 gst_harness_crank_single_clock_wait (h);
1287 verify_rtx_event (h, next_seqnum, timeout, rtx_delay_ms, TEST_BUF_DURATION);
1288
1289 /* we should now receive a packet-lost-event for packet @next_seqnum */
1290 gst_harness_crank_single_clock_wait (h);
1291 verify_lost_event (h, next_seqnum, timeout, TEST_BUF_DURATION);
1292
1293 gst_harness_teardown (h);
1294 }
1295
1296 GST_END_TEST;
1297
GST_START_TEST(test_rtx_two_missing)1298 GST_START_TEST (test_rtx_two_missing)
1299 {
1300 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1301 gint latency_ms = 200;
1302 guint next_seqnum;
1303 GstClockTime last_rtx_request, now;
1304 gint rtx_delay_ms = 0.5 * TEST_BUF_MS;
1305
1306 g_object_set (h->element, "do-retransmission", TRUE, NULL);
1307 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1308 fail_unless_equals_int (11, next_seqnum);
1309
1310 /*
1311 * The expected sequence of buffers is this:
1312 * ____ ____ ____ ____
1313 * ... | 10 | | 11 | | 12 | | 13 |
1314 * –––– –––– –––– ––––
1315 * 200ms 220ms 240ms 260ms
1316 *
1317 * But instead we get this:
1318 * ____ _ _ _ _ ____
1319 * ... | 10 | | | | | | 13 |
1320 * –––– - - - - ––––
1321 * 200ms 260ms
1322 *
1323 * Now it is important to note that the next thing that happens is that
1324 * the RTX timeout for packet 11 will happen at time 230ms, so we crank
1325 * the timer thread to advance the time to this:
1326 */
1327 gst_harness_crank_single_clock_wait (h);
1328 verify_rtx_event (h, 11, 11 * TEST_BUF_DURATION,
1329 rtx_delay_ms, TEST_BUF_DURATION);
1330 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1331 fail_unless_equals_int64 (last_rtx_request,
1332 11 * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1333 gst_harness_wait_for_clock_id_waits (h, 1, 60);
1334
1335 /* The next scheduled RTX for packet 11 is now at 230 + 40 = 270ms,
1336 so the next thing that happens is that buffer 13 arrives in perfect time: */
1337 now = 13 * TEST_BUF_DURATION;
1338 gst_harness_set_time (h, now);
1339 fail_unless_equals_int (GST_FLOW_OK,
1340 gst_harness_push (h,
1341 generate_test_buffer_full (now, 13, 13 * TEST_RTP_TS_DURATION)));
1342
1343 /*
1344 *
1345 * This will estimate the dts on the two missing packets to:
1346 * ____ ____
1347 * ... | 11 | | 12 | ...
1348 * –––– ––––
1349 * 220ms 240ms
1350 *
1351 * And given their regular interspacing of 20ms, it will schedule two RTX
1352 * timers for them like so:
1353 *
1354 * ____ ____
1355 * ... | 11 | | 12 | ...
1356 * –––– ––––
1357 * 230ms 250ms
1358 *
1359 * There are however two problems, packet 11 we have already sent one RTX for
1360 * and its timeout is currently at 270ms, so we should not tamper with that,
1361 * and as for packet 12, 250ms has already expired, so we now expect to see
1362 * an rtx-event being sent for packet 12 immediately:
1363 */
1364 verify_rtx_event (h, 12, 12 * TEST_BUF_DURATION,
1365 rtx_delay_ms, TEST_BUF_DURATION);
1366
1367 /* and another crank will see the second RTX event being sent for packet 11 */
1368 gst_harness_crank_single_clock_wait (h);
1369 rtx_delay_ms += 40;
1370 verify_rtx_event (h, 11, 11 * TEST_BUF_DURATION,
1371 rtx_delay_ms, TEST_BUF_DURATION);
1372 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1373 fail_unless_equals_int64 (last_rtx_request,
1374 11 * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1375
1376 gst_harness_teardown (h);
1377 }
1378
1379 GST_END_TEST;
1380
GST_START_TEST(test_rtx_buffer_arrives_just_in_time)1381 GST_START_TEST (test_rtx_buffer_arrives_just_in_time)
1382 {
1383 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1384 gint latency_ms = 5 * TEST_BUF_MS;
1385 gint next_seqnum;
1386 GstBuffer *buffer;
1387 GstClockTime now, last_rtx_request;
1388 gint rtx_delay_ms = 0.5 * TEST_BUF_MS;
1389
1390 g_object_set (h->element, "do-retransmission", TRUE,
1391 "rtx-max-retries", 1, NULL);
1392 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1393
1394 /* Crank clock to send retransmission events requesting seqnum 6 which has
1395 * not arrived yet. */
1396 gst_harness_crank_single_clock_wait (h);
1397 verify_rtx_event (h, next_seqnum,
1398 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1399
1400 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1401 fail_unless_equals_int64 (last_rtx_request,
1402 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1403
1404 /* seqnum 6 arrives just before it times out and is considered lost */
1405 now = 200 * GST_MSECOND;
1406 gst_harness_set_time (h, now);
1407 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1408 generate_test_buffer_rtx (now, next_seqnum)));
1409 buffer = gst_harness_pull (h);
1410 fail_unless_equals_int (next_seqnum, get_rtp_seq_num (buffer));
1411 gst_buffer_unref (buffer);
1412
1413 fail_unless (verify_jb_stats (h->element,
1414 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1415 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 1,
1416 "num-lost", G_TYPE_UINT64, (guint64) 0,
1417 "rtx-count", G_TYPE_UINT64, (guint64) 1,
1418 "rtx-success-count", G_TYPE_UINT64, (guint64) 1,
1419 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1420 "rtx-rtt", G_TYPE_UINT64, (guint64) (now - last_rtx_request),
1421 NULL)));
1422
1423 gst_harness_teardown (h);
1424 }
1425
1426 GST_END_TEST;
1427
GST_START_TEST(test_rtx_buffer_arrives_too_late)1428 GST_START_TEST (test_rtx_buffer_arrives_too_late)
1429 {
1430 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1431 gint latency_ms = 5 * TEST_BUF_MS;
1432 gint next_seqnum;
1433 GstClockTime now, last_rtx_request;
1434 gint rtx_delay_ms = 0.5 * TEST_BUF_MS;
1435
1436 g_object_set (h->element, "do-retransmission", TRUE,
1437 "do-lost", TRUE, "rtx-max-retries", 1, NULL);
1438 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1439
1440 /* Crank clock to send retransmission events requesting seqnum 6 which has
1441 * not arrived yet. */
1442 gst_harness_crank_single_clock_wait (h);
1443 verify_rtx_event (h, next_seqnum,
1444 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1445
1446 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1447 fail_unless_equals_int64 (last_rtx_request,
1448 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1449
1450 /* packet @next_seqnum is considered lost */
1451 gst_harness_crank_single_clock_wait (h);
1452 verify_lost_event (h, next_seqnum,
1453 next_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION);
1454
1455 /* packet @next_seqnum arrives too late */
1456 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1457 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1458 generate_test_buffer_rtx (now, next_seqnum)));
1459
1460 fail_unless (verify_jb_stats (h->element,
1461 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1462 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1463 "num-lost", G_TYPE_UINT64, (guint64) 1,
1464 "num-late", G_TYPE_UINT64, (guint64) 1,
1465 "num-duplicates", G_TYPE_UINT64, (guint64) 0,
1466 "rtx-count", G_TYPE_UINT64, (guint64) 1,
1467 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1468 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1469 "rtx-rtt", G_TYPE_UINT64, (guint64) (now - last_rtx_request),
1470 NULL)));
1471
1472 gst_harness_teardown (h);
1473 }
1474
1475 GST_END_TEST;
1476
GST_START_TEST(test_rtx_original_buffer_does_not_update_rtx_stats)1477 GST_START_TEST (test_rtx_original_buffer_does_not_update_rtx_stats)
1478 {
1479 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1480 gint latency_ms = 100;
1481 gint next_seqnum;
1482 GstBuffer *buffer;
1483 GstClockTime now, last_rtx_request;
1484 gint rtx_delay_ms = 0.5 * TEST_BUF_MS;
1485
1486 g_object_set (h->element, "do-retransmission", TRUE,
1487 "rtx-max-retries", 1, NULL);
1488 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1489 fail_unless_equals_int (6, next_seqnum);
1490
1491 /* Crank clock to send retransmission events requesting @next_seqnum which has
1492 * not arrived yet. */
1493 gst_harness_crank_single_clock_wait (h);
1494 verify_rtx_event (h, next_seqnum,
1495 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1496
1497 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1498 fail_unless_equals_int64 (last_rtx_request,
1499 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1500
1501 /* ORIGINAL seqnum 6 arrives just before it times out and is considered
1502 * lost. */
1503 now = 200 * GST_MSECOND;
1504 gst_harness_set_time (h, now);
1505 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1506 generate_test_buffer_full (now,
1507 next_seqnum, next_seqnum * TEST_RTP_TS_DURATION)));
1508 buffer = gst_harness_pull (h);
1509 fail_unless_equals_int (next_seqnum, get_rtp_seq_num (buffer));
1510 gst_buffer_unref (buffer);
1511
1512 /* due to the advance in time, we will now also have sent
1513 an rtx-request for 7 */
1514 next_seqnum++;
1515 verify_rtx_event (h, next_seqnum,
1516 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1517
1518 /* The original buffer does not count in the RTX stats. */
1519 fail_unless (verify_jb_stats (h->element,
1520 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1521 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1522 "num-lost", G_TYPE_UINT64, (guint64) 0,
1523 "num-late", G_TYPE_UINT64, (guint64) 0,
1524 "num-duplicates", G_TYPE_UINT64, (guint64) 0,
1525 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1526 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1527 "rtx-per-packet", G_TYPE_DOUBLE, 0.0,
1528 "rtx-rtt", G_TYPE_UINT64, (guint64) 0, NULL)));
1529
1530 /* Now the retransmitted packet arrives and stats should be updated. Note
1531 * that the buffer arrives in time and should not be considered late, but
1532 * a duplicate. */
1533 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1534 generate_test_buffer_rtx (now, 6)));
1535
1536 fail_unless (verify_jb_stats (h->element,
1537 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1538 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1539 "num-lost", G_TYPE_UINT64, (guint64) 0,
1540 "num-late", G_TYPE_UINT64, (guint64) 0,
1541 "num-duplicates", G_TYPE_UINT64, (guint64) 1,
1542 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1543 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1544 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1545 "rtx-rtt", G_TYPE_UINT64, (guint64) (now - last_rtx_request),
1546 NULL)));
1547
1548 gst_harness_teardown (h);
1549 }
1550
1551 GST_END_TEST;
1552
GST_START_TEST(test_rtx_duplicate_packet_updates_rtx_stats)1553 GST_START_TEST (test_rtx_duplicate_packet_updates_rtx_stats)
1554 {
1555 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1556 gint latency_ms = 100;
1557 gint next_seqnum;
1558 GstClockTime now, rtx_request_6, rtx_request_7;
1559 gint rtx_delay_ms = 0.5 * TEST_BUF_MS;
1560 gint i;
1561
1562 g_object_set (h->element, "do-retransmission", TRUE, NULL);
1563 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1564 fail_unless_equals_int (6, next_seqnum);
1565
1566 /* Push packet 8 so that 6 and 7 is missing */
1567 fail_unless_equals_int (GST_FLOW_OK,
1568 gst_harness_push (h, generate_test_buffer (8)));
1569
1570 /* Wait for NACKs on 6 and 7 */
1571 gst_harness_crank_single_clock_wait (h);
1572 verify_rtx_event (h, 6, 6 * TEST_BUF_DURATION,
1573 rtx_delay_ms, TEST_BUF_DURATION);
1574 rtx_request_6 = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1575 fail_unless_equals_int64 (rtx_request_6,
1576 6 * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1577
1578 gst_harness_crank_single_clock_wait (h);
1579 verify_rtx_event (h,
1580 7, 7 * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1581 rtx_request_7 = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1582 fail_unless_equals_int64 (rtx_request_7,
1583 7 * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1584
1585 /* Original packet 7 arrives */
1586 now = 150 * GST_MSECOND;
1587 gst_harness_set_time (h, now);
1588 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1589 generate_test_buffer_full (now, 7, 7 * TEST_RTP_TS_DURATION)));
1590
1591 /* We're still waiting for packet 6, so 7 should not be pushed */
1592 gst_harness_wait_for_clock_id_waits (h, 1, 60);
1593 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1594
1595 /* The original buffer does not count in the RTX stats. */
1596 fail_unless (verify_jb_stats (h->element,
1597 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1598 "num-lost", G_TYPE_UINT64, (guint64) 0,
1599 "num-late", G_TYPE_UINT64, (guint64) 0,
1600 "num-duplicates", G_TYPE_UINT64, (guint64) 0,
1601 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1602 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1603 "rtx-per-packet", G_TYPE_DOUBLE, 0.0,
1604 "rtx-rtt", G_TYPE_UINT64, (guint64) 0, NULL)));
1605
1606 /* Push RTX packet 7. Should be dropped as duplicate but update RTX stats. */
1607 now = 160 * GST_MSECOND;
1608 gst_harness_set_time (h, now);
1609 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1610 generate_test_buffer_rtx (now, 7)));
1611 gst_harness_wait_for_clock_id_waits (h, 1, 60);
1612 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1613
1614 /* Check RTX stats with updated num-duplicates and rtx-rtt fields */
1615 fail_unless (verify_jb_stats (h->element,
1616 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1617 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1618 "num-lost", G_TYPE_UINT64, (guint64) 0,
1619 "num-late", G_TYPE_UINT64, (guint64) 0,
1620 "num-duplicates", G_TYPE_UINT64, (guint64) 1,
1621 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1622 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1623 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1624 "rtx-rtt", G_TYPE_UINT64, (guint64) (now - rtx_request_7),
1625 NULL)));
1626
1627 /* RTX packet 6 arrives, both 6, 7 and 8 is ready to be pulled */
1628 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1629 generate_test_buffer_rtx (now, 6)));
1630
1631 for (i = 6; i <= 8; i++) {
1632 GstBuffer *buf = gst_harness_pull (h);
1633 fail_unless_equals_int (i, get_rtp_seq_num (buf));
1634 gst_buffer_unref (buf);
1635 }
1636
1637 /* RTX stats is updated with success count increased. */
1638 fail_unless (verify_jb_stats (h->element,
1639 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1640 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 3,
1641 "num-lost", G_TYPE_UINT64, (guint64) 0,
1642 "num-late", G_TYPE_UINT64, (guint64) 0,
1643 "num-duplicates", G_TYPE_UINT64, (guint64) 1,
1644 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1645 "rtx-success-count", G_TYPE_UINT64, (guint64) 1,
1646 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1647 "rtx-rtt", G_TYPE_UINT64, (guint64)
1648 /* Use the rtx-rtt formula. Can be subject to change though. */
1649 ((now - rtx_request_6) + 47 * (now - rtx_request_7)) / 48,
1650 NULL)));
1651
1652 gst_harness_teardown (h);
1653 }
1654
1655 GST_END_TEST;
1656
GST_START_TEST(test_rtx_buffer_arrives_after_lost_updates_rtx_stats)1657 GST_START_TEST (test_rtx_buffer_arrives_after_lost_updates_rtx_stats)
1658 {
1659 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1660 gint latency_ms = 100;
1661 gint next_seqnum;
1662 GstClockTime now, last_rtx_request;
1663 gint rtx_delay_ms = 0.5 * TEST_BUF_MS;
1664
1665 g_object_set (h->element, "do-retransmission", TRUE,
1666 "do-lost", TRUE, "rtx-max-retries", 1, NULL);
1667 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1668
1669 /* Crank clock to send retransmission events requesting seqnum 6 which has
1670 * not arrived yet. */
1671 gst_harness_crank_single_clock_wait (h);
1672 verify_rtx_event (h, next_seqnum,
1673 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1674
1675 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1676 fail_unless_equals_int64 (last_rtx_request,
1677 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1678
1679 /* seqnum 6 is considered lost */
1680 gst_harness_crank_single_clock_wait (h);
1681 verify_lost_event (h, next_seqnum,
1682 next_seqnum * TEST_BUF_DURATION, TEST_BUF_DURATION);
1683
1684 /* seqnum 6 arrives too late */
1685 now = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1686 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1687 generate_test_buffer_rtx (now, next_seqnum)));
1688
1689 fail_unless (verify_jb_stats (h->element,
1690 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1691 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1692 "num-lost", G_TYPE_UINT64, (guint64) 1,
1693 "num-late", G_TYPE_UINT64, (guint64) 1,
1694 "num-duplicates", G_TYPE_UINT64, (guint64) 0,
1695 "rtx-count", G_TYPE_UINT64, (guint64) 1,
1696 "rtx-success-count", G_TYPE_UINT64, (guint64) 0,
1697 "rtx-per-packet", G_TYPE_DOUBLE, 1.0,
1698 "rtx-rtt", G_TYPE_UINT64, (guint64) (now - last_rtx_request),
1699 NULL)));
1700
1701 gst_harness_teardown (h);
1702 }
1703
1704 GST_END_TEST;
1705
GST_START_TEST(test_rtx_rtt_larger_than_retry_timeout)1706 GST_START_TEST (test_rtx_rtt_larger_than_retry_timeout)
1707 {
1708 /* When RTT is larger than retry period we will send two or more requests
1709 * before receiving any retransmission packets */
1710 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1711 gint latency_ms = 100;
1712 gint next_seqnum;
1713 gint rtx_retry_timeout_ms = 20;
1714 gint rtx_delay_ms = 0.5 * TEST_BUF_MS;
1715 gint rtt = rtx_retry_timeout_ms * GST_MSECOND + 1;
1716 GstClockTime now, first_request, second_request;
1717
1718 g_object_set (h->element, "do-retransmission", TRUE,
1719 "rtx-retry-timeout", rtx_retry_timeout_ms, NULL);
1720 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1721
1722 /* Wait for first NACK on 6 */
1723 gst_harness_crank_single_clock_wait (h);
1724 verify_rtx_event (h, next_seqnum,
1725 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1726 first_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1727 fail_unless_equals_int64 (first_request,
1728 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1729
1730 /* Packet @next_seqnum + 1 arrives in time (so that we avoid its EXPECTED
1731 * timers to interfer with our test) */
1732 push_test_buffer (h, next_seqnum + 1);
1733
1734 /* Simulating RTT > rtx-retry-timeout, we send a new NACK before receiving
1735 * the RTX packet. Wait for second NACK on @next_seqnum */
1736 gst_harness_crank_single_clock_wait (h);
1737 rtx_delay_ms += rtx_retry_timeout_ms;
1738 verify_rtx_event (h, next_seqnum,
1739 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1740 second_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1741 fail_unless_equals_int64 (second_request,
1742 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1743
1744 /* The first retransmitted packet arrives */
1745 now = first_request + rtt;
1746 gst_harness_set_time (h, now);
1747 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1748 generate_test_buffer_rtx (now, next_seqnum)));
1749
1750 /* Pull packets @next_seqnum and @next_seqnum + 1 */
1751 gst_buffer_unref (gst_harness_pull (h));
1752 gst_buffer_unref (gst_harness_pull (h));
1753
1754 /* Stats should be updated. Note that RTT is not updated since we cannot be
1755 * sure whether the RTX packet is in response to the first or second NACK. */
1756 fail_unless (verify_jb_stats (h->element,
1757 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1758 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 2,
1759 "num-lost", G_TYPE_UINT64, (guint64) 0,
1760 "num-late", G_TYPE_UINT64, (guint64) 0,
1761 "num-duplicates", G_TYPE_UINT64, (guint64) 0,
1762 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1763 "rtx-success-count", G_TYPE_UINT64, (guint64) 1,
1764 "rtx-per-packet", G_TYPE_DOUBLE, 2.0,
1765 "rtx-rtt", G_TYPE_UINT64, (guint64) 0, NULL)));
1766
1767 /* Packet @next_seqnum + 2 arrives in time */
1768 push_test_buffer (h, next_seqnum + 2);
1769 gst_buffer_unref (gst_harness_pull (h));
1770
1771 /* Now the second retransmitted packet arrives */
1772 now = second_request + rtt;
1773 gst_harness_set_time (h, now);
1774 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h,
1775 generate_test_buffer_rtx (now, next_seqnum)));
1776
1777 /* The stats is updated with the correct RTT. */
1778 fail_unless (verify_jb_stats (h->element,
1779 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1780 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum + 3,
1781 "num-lost", G_TYPE_UINT64, (guint64) 0,
1782 "num-late", G_TYPE_UINT64, (guint64) 0,
1783 "num-duplicates", G_TYPE_UINT64, (guint64) 1,
1784 "rtx-count", G_TYPE_UINT64, (guint64) 2,
1785 "rtx-success-count", G_TYPE_UINT64, (guint64) 1,
1786 "rtx-per-packet", G_TYPE_DOUBLE, 2.0,
1787 "rtx-rtt", G_TYPE_UINT64, (guint64) rtt, NULL)));
1788
1789 gst_harness_teardown (h);
1790 }
1791
1792 GST_END_TEST;
1793
GST_START_TEST(test_rtx_no_request_if_time_past_retry_period)1794 GST_START_TEST (test_rtx_no_request_if_time_past_retry_period)
1795 {
1796 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1797 const gint latency_ms = 200;
1798 const gint retry_period_ms = 120;
1799 GstTestClock *testclock;
1800 GstClockID pending_id;
1801 GstClockTime time;
1802 gint i;
1803
1804 gst_harness_set_src_caps (h, generate_caps ());
1805 testclock = gst_harness_get_testclock (h);
1806
1807 g_object_set (h->element, "do-lost", TRUE, NULL);
1808 g_object_set (h->element, "do-retransmission", TRUE, NULL);
1809 g_object_set (h->element, "latency", latency_ms, NULL);
1810 g_object_set (h->element, "rtx-retry-period", retry_period_ms, NULL);
1811
1812 /* push the first couple of buffers */
1813 push_test_buffer (h, 0);
1814 push_test_buffer (h, 1);
1815
1816 /* drop reconfigure event */
1817 gst_event_unref (gst_harness_pull_upstream_event (h));
1818 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
1819 for (i = 0; i < 3; i++)
1820 gst_event_unref (gst_harness_pull_event (h));
1821
1822 /* Wait for the first EXPECTED timer to be scheduled */
1823 gst_test_clock_wait_for_next_pending_id (testclock, &pending_id);
1824 time = gst_clock_id_get_time (pending_id);
1825 gst_clock_id_unref (pending_id);
1826 fail_unless_equals_int64 (time, 2 * TEST_BUF_DURATION + 10 * GST_MSECOND);
1827
1828 /* Let the first EXPECTED timer time out and be sent. However, set the 'now'
1829 * time to be past the retry-period simulating that the jitterbuffer has too
1830 * much to do and is not able to process all timers in real-time. In this
1831 * case the jitterbuffer should not schedule a new EXPECTED timer as that
1832 * would just make matters worse (more unnecessary processing of a request
1833 * that is already too late to be valuable). In practice this typically
1834 * happens for high loss networks with low RTT. */
1835 gst_test_clock_set_time_and_process (testclock,
1836 2 * TEST_BUF_DURATION + retry_period_ms * GST_MSECOND + 1);
1837
1838 /* Verify the event. It could be argued that this request is already too
1839 * late and unnecessary. However, in order to keep things simple (for now)
1840 * we just keep the already scehduled EXPECTED timer, but refrain from
1841 * scheduled another EXPECTED timer */
1842 verify_rtx_event (h, 2, 2 * TEST_BUF_DURATION, 10, TEST_BUF_DURATION);
1843
1844 /* "crank" to reach the DEADLINE for packet 0 */
1845 gst_harness_crank_single_clock_wait (h);
1846 gst_buffer_unref (gst_harness_pull (h));
1847 gst_buffer_unref (gst_harness_pull (h));
1848
1849 fail_unless_equals_int (0, gst_harness_upstream_events_in_queue (h));
1850 fail_unless_equals_int (0, gst_harness_events_in_queue (h));
1851
1852 /* "crank" to time out the LOST event */
1853 gst_harness_crank_single_clock_wait (h);
1854 verify_lost_event (h, 2, 2 * TEST_BUF_DURATION, TEST_BUF_DURATION);
1855
1856 gst_object_unref (testclock);
1857 gst_harness_teardown (h);
1858 }
1859
1860 GST_END_TEST;
1861
GST_START_TEST(test_rtx_same_delay_and_retry_timeout)1862 GST_START_TEST (test_rtx_same_delay_and_retry_timeout)
1863 {
1864 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1865 gint latency_ms = 5 * TEST_BUF_MS;
1866 gint next_seqnum;
1867 gint rtx_delay_ms = 20;
1868 GstClockTime last_rtx_request;
1869
1870 g_object_set (h->element, "do-retransmission", TRUE,
1871 "rtx-max-retries", 3, "rtx-delay", rtx_delay_ms,
1872 "rtx-retry-timeout", rtx_delay_ms, NULL);
1873 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1874
1875 /* Crank clock to send retransmission events requesting seqnum 6 which has
1876 * not arrived yet. */
1877 gst_harness_crank_single_clock_wait (h);
1878 verify_rtx_event (h, next_seqnum,
1879 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1880 /* first rtx for packet @next_seqnum should arrive at the right time */
1881 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1882 fail_unless_equals_int64 (last_rtx_request,
1883 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * GST_MSECOND);
1884
1885 /* verify we have pulled out all rtx-events */
1886 fail_unless_equals_int (0, gst_harness_upstream_events_in_queue (h));
1887
1888 /* now crank to get the second attempt at packet @next_seqnum */
1889 gst_harness_crank_single_clock_wait (h);
1890 verify_rtx_event (h, next_seqnum,
1891 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms * 2, TEST_BUF_DURATION);
1892
1893 /* second rtx for seqnum 6 should arrive at 140 + 20ms */
1894 last_rtx_request = gst_clock_get_time (GST_ELEMENT_CLOCK (h->element));
1895 fail_unless_equals_int64 (last_rtx_request,
1896 next_seqnum * TEST_BUF_DURATION + rtx_delay_ms * 2 * GST_MSECOND);
1897
1898 /* verify we have pulled out all rtx-events */
1899 fail_unless_equals_int (0, gst_harness_upstream_events_in_queue (h));
1900
1901 fail_unless (verify_jb_stats (h->element,
1902 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1903 "num-pushed", G_TYPE_UINT64, (guint64) next_seqnum,
1904 "num-lost", G_TYPE_UINT64, (guint64) 0,
1905 "rtx-count", G_TYPE_UINT64, (guint64) 2, NULL)));
1906
1907 gst_harness_teardown (h);
1908 }
1909
1910 GST_END_TEST;
1911
GST_START_TEST(test_rtx_with_backwards_rtptime)1912 GST_START_TEST (test_rtx_with_backwards_rtptime)
1913 {
1914 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1915 gint latency_ms = 40;
1916
1917 g_object_set (h->element, "do-retransmission", TRUE, NULL);
1918 construct_deterministic_initial_state (h, latency_ms);
1919
1920 /*
1921 * For video using B-frames, an expected sequence
1922 * could be like this:
1923 * (I = I-frame, P = P-frame, B = B-frame)
1924 * ___ ___ ___
1925 * ... | 3 | | 4 | | 5 |
1926 * ––– ––– –––
1927 * rtptime: 3(I) 5(P) 4(B)
1928 * arrival(dts): 3 5 5
1929 *
1930 * Notice here that packet 5 (the B frame) make
1931 * the rtptime go backwards.
1932 */
1933
1934 /* seqnum 3, arriving at time 3 with rtptime 3 */
1935 push_test_buffer (h, 3);
1936 gst_buffer_unref (gst_harness_pull (h));
1937
1938 /* seqnum 4, arriving at time 5 with rtptime 5 */
1939 gst_harness_push (h, generate_test_buffer_full (5 * TEST_BUF_DURATION,
1940 4, 5 * TEST_RTP_TS_DURATION));
1941 gst_buffer_unref (gst_harness_pull (h));
1942
1943 /* seqnum 5, arriving at time 5 with rtptime 4 */
1944 gst_harness_push (h, generate_test_buffer_full (5 * TEST_BUF_DURATION,
1945 5, 4 * TEST_RTP_TS_DURATION));
1946 gst_buffer_unref (gst_harness_pull (h));
1947
1948 /* crank to time-out the rtx-request for seqnum 6, the point here
1949 being that the backwards rtptime did not mess up the timeout for
1950 the rtx event */
1951 gst_harness_crank_single_clock_wait (h);
1952 verify_rtx_event (h, 6, 5 * TEST_BUF_DURATION + 15 * GST_MSECOND,
1953 17, 35 * GST_MSECOND);
1954
1955 fail_unless (verify_jb_stats (h->element,
1956 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
1957 "num-pushed", G_TYPE_UINT64, (guint64) 6,
1958 "rtx-count", G_TYPE_UINT64, (guint64) 1,
1959 "num-lost", G_TYPE_UINT64, (guint64) 0, NULL)));
1960
1961 gst_harness_teardown (h);
1962 }
1963
1964 GST_END_TEST;
1965
GST_START_TEST(test_rtx_timer_reuse)1966 GST_START_TEST (test_rtx_timer_reuse)
1967 {
1968 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
1969 gint latency_ms = 5 * TEST_BUF_MS;
1970 gint rtx_delay_ms = 0.5 * TEST_BUF_MS;
1971 guint next_seqnum;
1972
1973 g_object_set (h->element, "do-retransmission", TRUE,
1974 "do-lost", TRUE, "rtx-max-retries", 1, NULL);
1975 next_seqnum = construct_deterministic_initial_state (h, latency_ms);
1976
1977 /* crank to timeout the only rtx-request, and the timer will
1978 * now reschedule as a lost-timer internally */
1979 gst_harness_crank_single_clock_wait (h);
1980 verify_rtx_event (h, next_seqnum,
1981 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1982
1983 /* but now buffer 6 arrives, and this should now reuse the lost-timer
1984 * for 6, as an expected-timer for 7 */
1985 fail_unless_equals_int (GST_FLOW_OK,
1986 gst_harness_push (h, generate_test_buffer (next_seqnum)));
1987
1988 /* now crank to timeout the expected-timer for 7 and verify */
1989 next_seqnum++;
1990 gst_harness_crank_single_clock_wait (h);
1991 verify_rtx_event (h, next_seqnum,
1992 next_seqnum * TEST_BUF_DURATION, rtx_delay_ms, TEST_BUF_DURATION);
1993
1994 gst_harness_teardown (h);
1995 }
1996
1997 GST_END_TEST;
1998
GST_START_TEST(test_deadline_ts_offset)1999 GST_START_TEST (test_deadline_ts_offset)
2000 {
2001 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2002 GstTestClock *testclock;
2003 GstClockID id;
2004 const gint jb_latency_ms = 10;
2005
2006 gst_harness_set_src_caps (h, generate_caps ());
2007 testclock = gst_harness_get_testclock (h);
2008
2009 g_object_set (h->element, "latency", jb_latency_ms, NULL);
2010
2011 /* push the first buffer in */
2012 fail_unless_equals_int (GST_FLOW_OK,
2013 gst_harness_push (h, generate_test_buffer (0)));
2014
2015 /* wait_next_timeout() syncs on the deadline timer */
2016 gst_test_clock_wait_for_next_pending_id (testclock, &id);
2017 fail_unless_equals_uint64 (jb_latency_ms * GST_MSECOND,
2018 gst_clock_id_get_time (id));
2019 gst_clock_id_unref (id);
2020
2021 /* add ts-offset while waiting */
2022 g_object_set (h->element, "ts-offset", 20 * GST_MSECOND, NULL);
2023
2024 gst_test_clock_set_time_and_process (testclock, jb_latency_ms * GST_MSECOND);
2025
2026 /* wait_next_timeout() syncs on the new deadline timer */
2027 gst_test_clock_wait_for_next_pending_id (testclock, &id);
2028 fail_unless_equals_uint64 ((20 + jb_latency_ms) * GST_MSECOND,
2029 gst_clock_id_get_time (id));
2030 gst_clock_id_unref (id);
2031
2032 /* now make deadline timer timeout */
2033 gst_test_clock_set_time_and_process (testclock,
2034 (20 + jb_latency_ms) * GST_MSECOND);
2035
2036 gst_buffer_unref (gst_harness_pull (h));
2037
2038 gst_object_unref (testclock);
2039 gst_harness_teardown (h);
2040 }
2041
2042 GST_END_TEST;
2043
GST_START_TEST(test_push_big_gap)2044 GST_START_TEST (test_push_big_gap)
2045 {
2046 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2047 GstBuffer *buf;
2048 const gint num_consecutive = 5;
2049 gint i;
2050
2051 gst_harness_set_src_caps (h, generate_caps ());
2052
2053 for (i = 0; i < num_consecutive; i++)
2054 fail_unless_equals_int (GST_FLOW_OK,
2055 gst_harness_push (h, generate_test_buffer (1000 + i)));
2056
2057 fail_unless (gst_harness_crank_single_clock_wait (h));
2058
2059 for (i = 0; i < num_consecutive; i++) {
2060 GstBuffer *buf = gst_harness_pull (h);
2061 fail_unless_equals_int (1000 + i, get_rtp_seq_num (buf));
2062 gst_buffer_unref (buf);
2063 }
2064
2065 /* Push more packets from a different sequence number domain
2066 * to trigger "big gap" logic. */
2067 for (i = 0; i < num_consecutive; i++)
2068 fail_unless_equals_int (GST_FLOW_OK,
2069 gst_harness_push (h, generate_test_buffer (20000 + i)));
2070
2071 fail_unless (gst_harness_crank_single_clock_wait (h));
2072
2073 for (i = 0; i < num_consecutive; i++) {
2074 GstBuffer *buf = gst_harness_pull (h);
2075 fail_unless_equals_int (20000 + i, get_rtp_seq_num (buf));
2076 gst_buffer_unref (buf);
2077 }
2078
2079 /* Final buffer should be pushed straight through */
2080 fail_unless_equals_int (GST_FLOW_OK,
2081 gst_harness_push (h, generate_test_buffer (20000 + num_consecutive)));
2082 buf = gst_harness_pull (h);
2083 fail_unless_equals_int (20000 + num_consecutive, get_rtp_seq_num (buf));
2084 gst_buffer_unref (buf);
2085
2086 gst_harness_teardown (h);
2087 }
2088
2089 GST_END_TEST;
2090
2091 typedef struct
2092 {
2093 guint seqnum_offset;
2094 guint late_buffer;
2095 } TestLateArrivalInput;
2096
2097 static const TestLateArrivalInput
2098 test_considered_lost_packet_in_large_gap_arrives_input[] = {
2099 {0, 1}, {0, 2}, {65535, 1}, {65535, 2}, {65534, 1}, {65534, 2}
2100 };
2101
GST_START_TEST(test_considered_lost_packet_in_large_gap_arrives)2102 GST_START_TEST (test_considered_lost_packet_in_large_gap_arrives)
2103 {
2104 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2105 GstTestClock *testclock;
2106 GstClockID id;
2107 GstBuffer *buffer;
2108 gint jb_latency_ms = 20;
2109 const TestLateArrivalInput *test_input =
2110 &test_considered_lost_packet_in_large_gap_arrives_input[__i__];
2111 guint seq_offset = test_input->seqnum_offset;
2112 guint late_buffer = test_input->late_buffer;
2113 gint i;
2114
2115 gst_harness_set_src_caps (h, generate_caps ());
2116 testclock = gst_harness_get_testclock (h);
2117 g_object_set (h->element, "do-lost", TRUE, "latency", jb_latency_ms, NULL);
2118
2119 /* first push buffer 0 */
2120 fail_unless_equals_int (GST_FLOW_OK,
2121 gst_harness_push (h, generate_test_buffer_full (0 * TEST_BUF_DURATION,
2122 0 + seq_offset, 0 * TEST_RTP_TS_DURATION)));
2123 fail_unless (gst_harness_crank_single_clock_wait (h));
2124 gst_buffer_unref (gst_harness_pull (h));
2125
2126 /* drop GstEventStreamStart & GstEventCaps & GstEventSegment */
2127 for (i = 0; i < 3; i++)
2128 gst_event_unref (gst_harness_pull_event (h));
2129
2130 /* hop over 3 packets, and push buffer 4 (gap of 3) */
2131 fail_unless_equals_int (GST_FLOW_OK,
2132 gst_harness_push (h, generate_test_buffer_full (4 * TEST_BUF_DURATION,
2133 4 + seq_offset, 4 * TEST_RTP_TS_DURATION)));
2134
2135 /* the jitterbuffer should be waiting for the timeout of a "large gap timer"
2136 * for buffer 1 and 2 */
2137 gst_test_clock_wait_for_next_pending_id (testclock, &id);
2138 fail_unless_equals_uint64 (1 * TEST_BUF_DURATION +
2139 jb_latency_ms * GST_MSECOND, gst_clock_id_get_time (id));
2140 gst_clock_id_unref (id);
2141
2142 /* now buffer 1 sneaks in before the lost event for buffer 1 and 2 is
2143 * processed */
2144 fail_unless_equals_int (GST_FLOW_OK,
2145 gst_harness_push (h,
2146 generate_test_buffer_full (late_buffer * TEST_BUF_DURATION,
2147 late_buffer + seq_offset, late_buffer * TEST_RTP_TS_DURATION)));
2148
2149 /* time out for lost packets 1 and 2 (one event, double duration) */
2150 fail_unless (gst_harness_crank_single_clock_wait (h));
2151 verify_lost_event (h, 1 + seq_offset, 1 * TEST_BUF_DURATION,
2152 2 * TEST_BUF_DURATION);
2153
2154 /* time out for lost packets 3 */
2155 fail_unless (gst_harness_crank_single_clock_wait (h));
2156 verify_lost_event (h, 3 + seq_offset, 3 * TEST_BUF_DURATION,
2157 1 * TEST_BUF_DURATION);
2158
2159 /* buffer 4 is pushed as normal */
2160 buffer = gst_harness_pull (h);
2161 fail_unless_equals_int ((4 + seq_offset) & 0xffff, get_rtp_seq_num (buffer));
2162 gst_buffer_unref (buffer);
2163
2164 /* we have lost 3, and one of them arrived eventually, but too late */
2165 fail_unless (verify_jb_stats (h->element,
2166 gst_structure_new ("application/x-rtp-jitterbuffer-stats",
2167 "num-pushed", G_TYPE_UINT64, (guint64) 2,
2168 "num-lost", G_TYPE_UINT64, (guint64) 3,
2169 "num-late", G_TYPE_UINT64, (guint64) 1, NULL)));
2170
2171 gst_object_unref (testclock);
2172 gst_harness_teardown (h);
2173 }
2174
2175 GST_END_TEST;
2176
GST_START_TEST(test_performance)2177 GST_START_TEST (test_performance)
2178 {
2179 GstHarness *h =
2180 gst_harness_new_parse
2181 ("rtpjitterbuffer do-lost=1 do-retransmission=1 latency=1000");
2182 GTimer *timer = g_timer_new ();
2183 const gdouble test_duration = 2.0;
2184 guint buffers_pushed = 0;
2185 guint buffers_received;
2186
2187 gst_harness_set_src_caps (h, generate_caps ());
2188 gst_harness_use_systemclock (h);
2189
2190 while (g_timer_elapsed (timer, NULL) < test_duration) {
2191 /* Simulate 1ms packets */
2192 guint n = buffers_pushed * 2; // every packet also produces a gap
2193 guint16 seqnum = n & 0xffff;
2194 guint32 rtp_ts = n * 8;
2195 GstClockTime dts = n * GST_MSECOND;
2196 gst_harness_push (h, generate_test_buffer_full (dts, seqnum, rtp_ts));
2197 buffers_pushed++;
2198 g_usleep (G_USEC_PER_SEC / 10000);
2199 }
2200 g_timer_destroy (timer);
2201
2202 buffers_received = gst_harness_buffers_received (h);
2203 GST_INFO ("Pushed %d, received %d (%.1f%%)", buffers_pushed, buffers_received,
2204 100.0 * buffers_received / buffers_pushed);
2205
2206 gst_harness_teardown (h);
2207 }
2208
2209 GST_END_TEST;
2210
2211 static gpointer
generate_harness_buffer(gpointer data)2212 generate_harness_buffer (gpointer data)
2213 {
2214 GstHarness *h = data;
2215 guint i;
2216
2217 for (i = 32766; i < 41000; i++)
2218 gst_harness_push (h, generate_test_buffer (1000 + i));
2219
2220 return NULL;
2221 }
2222
2223
GST_START_TEST(test_fill_queue)2224 GST_START_TEST (test_fill_queue)
2225 {
2226 GstHarness *h = gst_harness_new ("rtpjitterbuffer");
2227 const gint num_consecutive = 40000;
2228 gint i;
2229 GstSegment segment;
2230 GThread *t;
2231 GstBuffer *buf;
2232
2233 gst_segment_init (&segment, GST_FORMAT_TIME);
2234 gst_harness_set_src_caps (h, generate_caps ());
2235
2236 gst_harness_play (h);
2237
2238 gst_harness_push (h, generate_test_buffer (1000));
2239 gst_harness_push (h, generate_test_buffer (1002));
2240
2241 for (i = 3; i < 32766; i++)
2242 gst_harness_push (h, generate_test_buffer (1000 + i));
2243
2244 t = g_thread_new ("fill-queue-test-push", generate_harness_buffer, h);
2245
2246 /* Just give a chance to the thread to start and to try to push one packet */
2247 g_usleep (100 * 1000);
2248
2249 fail_unless (gst_harness_crank_single_clock_wait (h));
2250
2251 buf = gst_harness_pull (h);
2252 fail_unless_equals_int (1000, get_rtp_seq_num (buf));
2253 gst_buffer_unref (buf);
2254
2255 /* Gap at 1001 here */
2256 fail_unless (gst_harness_crank_single_clock_wait (h));
2257
2258 buf = gst_harness_pull (h);
2259 fail_unless_equals_int (1002, get_rtp_seq_num (buf));
2260 gst_buffer_unref (buf);
2261
2262 for (i = 3; i < num_consecutive; i++) {
2263 GstBuffer *buf = gst_harness_pull (h);
2264 fail_unless_equals_int (1000 + i, get_rtp_seq_num (buf));
2265 gst_buffer_unref (buf);
2266 }
2267
2268 g_thread_join (t);
2269
2270 gst_harness_teardown (h);
2271 }
2272
2273 GST_END_TEST;
2274
2275 static Suite *
rtpjitterbuffer_suite(void)2276 rtpjitterbuffer_suite (void)
2277 {
2278 Suite *s = suite_create ("rtpjitterbuffer");
2279 TCase *tc_chain = tcase_create ("general");
2280
2281 suite_add_tcase (s, tc_chain);
2282 tcase_add_test (tc_chain, test_push_forward_seq);
2283 tcase_add_test (tc_chain, test_push_backward_seq);
2284 tcase_add_test (tc_chain, test_push_unordered);
2285 tcase_add_test (tc_chain, test_push_eos);
2286 tcase_add_test (tc_chain, test_basetime);
2287 tcase_add_test (tc_chain, test_clear_pt_map);
2288
2289 tcase_add_test (tc_chain, test_lost_event);
2290 tcase_add_test (tc_chain, test_only_one_lost_event_on_large_gaps);
2291 tcase_add_test (tc_chain, test_two_lost_one_arrives_in_time);
2292 tcase_add_test (tc_chain, test_late_packets_still_makes_lost_events);
2293 tcase_add_test (tc_chain, test_lost_event_uses_pts);
2294 tcase_add_test (tc_chain, test_lost_event_with_backwards_rtptime);
2295
2296 tcase_add_test (tc_chain, test_all_packets_are_timestamped_zero);
2297 tcase_add_loop_test (tc_chain, test_num_late_when_considered_lost_arrives, 0,
2298 2);
2299 tcase_add_test (tc_chain, test_reorder_of_non_equidistant_packets);
2300 tcase_add_test (tc_chain,
2301 test_loss_equidistant_spacing_with_parameter_packets);
2302
2303 tcase_add_test (tc_chain, test_rtx_expected_next);
2304 tcase_add_test (tc_chain, test_rtx_two_missing);
2305 tcase_add_test (tc_chain, test_rtx_buffer_arrives_just_in_time);
2306 tcase_add_test (tc_chain, test_rtx_buffer_arrives_too_late);
2307 tcase_add_test (tc_chain, test_rtx_original_buffer_does_not_update_rtx_stats);
2308 tcase_add_test (tc_chain, test_rtx_duplicate_packet_updates_rtx_stats);
2309 tcase_add_test (tc_chain,
2310 test_rtx_buffer_arrives_after_lost_updates_rtx_stats);
2311 tcase_add_test (tc_chain, test_rtx_rtt_larger_than_retry_timeout);
2312 tcase_add_test (tc_chain, test_rtx_no_request_if_time_past_retry_period);
2313 tcase_add_test (tc_chain, test_rtx_same_delay_and_retry_timeout);
2314 tcase_add_test (tc_chain, test_rtx_with_backwards_rtptime);
2315 tcase_add_test (tc_chain, test_rtx_timer_reuse);
2316
2317 tcase_add_test (tc_chain, test_deadline_ts_offset);
2318 tcase_add_test (tc_chain, test_push_big_gap);
2319 tcase_add_test (tc_chain, test_fill_queue);
2320
2321 tcase_add_loop_test (tc_chain,
2322 test_considered_lost_packet_in_large_gap_arrives, 0,
2323 G_N_ELEMENTS (test_considered_lost_packet_in_large_gap_arrives_input));
2324
2325 tcase_add_test (tc_chain, test_performance);
2326
2327 return s;
2328 }
2329
2330 GST_CHECK_MAIN (rtpjitterbuffer);
2331