Asterisk - The Open Source Telephony Project GIT-master-f36a736
test_jitterbuf.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2012, Matt Jordan
5 *
6 * Matt Jordan <mjordan@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*!
20 * \file
21 * \brief Unit tests for jitterbuf.c
22 *
23 * \author\verbatim Matt Jordan <mjordan@digium.com> \endverbatim
24 *
25 * \ingroup tests
26 */
27
28/*** MODULEINFO
29 <depend>TEST_FRAMEWORK</depend>
30 <support_level>core</support_level>
31 ***/
32
33#include "asterisk.h"
34
35#include "asterisk/utils.h"
36#include "asterisk/module.h"
37#include "asterisk/test.h"
38#include "jitterbuf.h"
39
40#define DEFAULT_MAX_JITTERBUFFER 1000
41#define DEFAULT_RESYNCH_THRESHOLD 1000
42#define DEFAULT_MAX_CONTIG_INTERP 10
43#define DEFAULT_TARGET_EXTRA -1
44#define DEFAULT_CODEC_INTERP_LEN 20
45
46/*! \internal
47 * Test two numeric (long int) values. Failure automatically attempts
48 * to jump to a cleanup tag
49 */
50#define JB_NUMERIC_TEST(attribute, expected) do { \
51 if ((attribute) != (expected)) { \
52 ast_test_status_update(test, #attribute ": expected [%ld]; actual [%ld]\n", (long int)(expected), (attribute)); \
53 goto cleanup; \
54 } \
55} while (0)
56
57/*! \internal
58 * Print out as debug the frame related contents of a jb_info object
59 */
60#define JB_INFO_PRINT_FRAME_DEBUG(jbinfo) do { \
61 ast_debug(1, "JitterBuffer Frame Info:\n" \
62 "\tFrames In: %ld\n\tFrames Out: %ld\n" \
63 "\tDropped Frames: %ld\n\tLate Frames: %ld\n" \
64 "\tLost Frames: %ld\n\tOut of Order Frames: %ld\n" \
65 "\tCurrent Frame: %ld\n", jbinfo.frames_in, jbinfo.frames_out, \
66 jbinfo.frames_dropped, jbinfo.frames_late, jbinfo.frames_lost, \
67 jbinfo.frames_ooo, jbinfo.frames_cur); \
68} while (0)
69
70/*! \internal
71 * This macro installs the error, warning, and debug functions for a test. It is
72 * expected that at the end of a test, the functions are removed.
73 * Note that the debug statement is in here merely to aid in tracing in a log where
74 * the jitter buffer debug output begins.
75 */
76#define JB_TEST_BEGIN(test_name) do { \
77 jb_setoutput(test_jb_error_output, test_jb_warn_output, test_jb_debug_output); \
78 ast_debug(1, "Starting %s\n", test_name); \
79} while (0)
80
81/*! \internal
82 * Uninstall the error, warning, and debug functions from a test
83 */
84#define JB_TEST_END do { \
85 jb_setoutput(NULL, NULL, NULL); \
86} while (0)
87
88static const char *jitter_buffer_return_codes[] = {
89 "JB_OK", /* 0 */
90 "JB_EMPTY", /* 1 */
91 "JB_NOFRAME", /* 2 */
92 "JB_INTERP", /* 3 */
93 "JB_DROP", /* 4 */
94 "JB_SCHED" /* 5 */
95};
96
97/*!
98 * \internal
99 * \brief Make a default jitter buffer configuration
100 */
101static void test_jb_populate_config(struct jb_conf *jbconf)
102{
103 if (!jbconf) {
104 return;
105 }
106
110 jbconf->target_extra = 0;
111}
112
113/*!
114 * \internal
115 * \brief Debug callback function for the jitter buffer's jb_dbg function
116 */
117static void __attribute__((format(printf, 1, 2))) test_jb_debug_output(const char *fmt, ...)
118{
119 va_list args;
120 char buf[1024];
121
122 va_start(args, fmt);
123 vsnprintf(buf, sizeof(buf), fmt, args);
124 va_end(args);
125
126 ast_debug(1, "%s", buf);
127}
128
129/*!
130 * \internal
131 * \brief Warning callback function for the jitter buffer's jb_warn function
132 */
133static void __attribute__((format(printf, 1, 2))) test_jb_warn_output(const char *fmt, ...)
134{
135 va_list args;
136 char buf[1024];
137
138 va_start(args, fmt);
139 vsnprintf(buf, sizeof(buf), fmt, args);
140 va_end(args);
141
143}
144
145/*!
146 * \internal
147 * \brief Error callback function for the jitter buffer's jb_err function
148 */
149static void __attribute__((format(printf, 1, 2))) test_jb_error_output(const char *fmt, ...)
150{
151 va_list args;
152 char buf[1024];
153
154 va_start(args, fmt);
155 vsnprintf(buf, sizeof(buf), fmt, args);
156 va_end(args);
157
158 ast_log(AST_LOG_ERROR, "%s", buf);
159}
160
161/*!
162 * \internal
163 * \brief Insert frames into the jitter buffer for the nominal tests
164 */
165static int test_jb_nominal_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
166{
167 int i = 0, ret = 0;
168
169 for (i = 0; i < 40; i++) {
170 if (jb_put(jb, NULL, frame_type, 20, i * 20, i * 20 + 5) == JB_DROP) {
171 ast_test_status_update(test, "Jitter buffer dropped packet %d\n", i);
172 ret = 1;
173 break;
174 }
175 }
176
177 return ret;
178}
179
180AST_TEST_DEFINE(jitterbuffer_nominal_voice_frames)
181{
183 struct jitterbuf *jb = NULL;
184 struct jb_frame frame;
185 struct jb_conf jbconf;
186 struct jb_info jbinfo;
187 int i = 0;
188
189 switch (cmd) {
190 case TEST_INIT:
191 info->name = "jitterbuffer_nominal_voice_frames";
192 info->category = "/main/jitterbuf/";
193 info->summary = "Nominal operation of jitter buffer with audio data";
194 info->description =
195 "Tests the nominal case of putting audio data into a jitter buffer, "
196 "retrieving the frames, and querying for the next frame";
197 return AST_TEST_NOT_RUN;
198 case TEST_EXECUTE:
199 break;
200 }
201
202 JB_TEST_BEGIN("jitterbuffer_nominal_voice_frames");
203
204 if (!(jb = jb_new())) {
205 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
206 goto cleanup;
207 }
208
210 if (jb_setconf(jb, &jbconf) != JB_OK) {
211 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
212 goto cleanup;
213 }
214
216 goto cleanup;
217 }
218
219 for (i = 0; i < 40; i++) {
220 enum jb_return_code ret;
221 /* We should have a frame for each point in time */
222 if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
224 "Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
226 goto cleanup;
227 }
228 JB_NUMERIC_TEST(frame.ms, 20);
229 JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
230 JB_NUMERIC_TEST(jb_next(jb), (i + 1) * 20 + 5);
231 }
232
234
235 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
236 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
237 goto cleanup;
238 }
241 JB_NUMERIC_TEST(jbinfo.frames_in, 40);
242 JB_NUMERIC_TEST(jbinfo.frames_out, 40);
243 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
244 JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
245 JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
246
247cleanup:
248 if (jb) {
249 /* No need to do anything - this will put all frames on the 'free' list,
250 * so jb_destroy will dispose of them */
251 while (jb_getall(jb, &frame) == JB_OK) { }
252 jb_destroy(jb);
253 }
254
256
257 return result;
258}
259
260AST_TEST_DEFINE(jitterbuffer_nominal_control_frames)
261{
263 struct jitterbuf *jb = NULL;
264 struct jb_frame frame;
265 struct jb_conf jbconf;
266 struct jb_info jbinfo;
267 int i = 0;
268
269 switch (cmd) {
270 case TEST_INIT:
271 info->name = "jitterbuffer_nominal_control_frames";
272 info->category = "/main/jitterbuf/";
273 info->summary = "Nominal operation of jitter buffer with control frames";
274 info->description =
275 "Tests the nominal case of putting control frames into a jitter buffer, "
276 "retrieving the frames, and querying for the next frame";
277 return AST_TEST_NOT_RUN;
278 case TEST_EXECUTE:
279 break;
280 }
281
282 JB_TEST_BEGIN("jitterbuffer_nominal_control_frames");
283
284 if (!(jb = jb_new())) {
285 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
286 goto cleanup;
287 }
288
290 if (jb_setconf(jb, &jbconf) != JB_OK) {
291 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
292 goto cleanup;
293 }
294
296 goto cleanup;
297 }
298
299 for (i = 0; i < 40; i++) {
300 enum jb_return_code ret;
301 /* We should have a frame for each point in time */
302 if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
304 "Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
306 goto cleanup;
307 }
308 JB_NUMERIC_TEST(frame.ms, 20);
309 JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
310 }
311
312 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
313 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
314 goto cleanup;
315 }
318 JB_NUMERIC_TEST(jbinfo.frames_in, 40);
319 JB_NUMERIC_TEST(jbinfo.frames_out, 40);
320 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
321 JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
322 JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
323
325
326cleanup:
327 if (jb) {
328 /* No need to do anything - this will put all frames on the 'free' list,
329 * so jb_destroy will dispose of them */
330 while (jb_getall(jb, &frame) == JB_OK) { }
331 jb_destroy(jb);
332 }
333
335
336 return result;
337}
338
339/*!
340 * \internal
341 * \brief Insert frames into the jitter buffer for the out of order tests
342 */
343static int test_jb_out_of_order_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
344{
345 int i = 0, ret = 0;
346
347 for (i = 0; i < 40; i++) {
348 if (i % 4 == 0) {
349 /* Add the next frame */
350 if (jb_put(jb, NULL, frame_type, 20, (i + 1) * 20, (i + 1) * 20 + 5) == JB_DROP) {
351 ast_test_status_update(test, "Jitter buffer dropped packet %d\n", (i+1));
352 ret = 1;
353 break;
354 }
355 /* Add the current frame */
356 if (jb_put(jb, NULL, frame_type, 20, i * 20, i * 20 + 5) == JB_DROP) {
357 ast_test_status_update(test, "Jitter buffer dropped packet %d\n", i);
358 ret = 1;
359 break;
360 }
361 i++;
362 } else {
363 if (jb_put(jb, NULL, frame_type, 20, i * 20, i * 20 + 5) == JB_DROP) {
364 ast_test_status_update(test, "Jitter buffer dropped packet %d\n", i);
365 ret = 1;
366 break;
367 }
368 }
369 }
370
371 return ret;
372}
373
374AST_TEST_DEFINE(jitterbuffer_out_of_order_voice)
375{
377 struct jitterbuf *jb = NULL;
378 struct jb_frame frame;
379 struct jb_info jbinfo;
380 struct jb_conf jbconf;
381 int i;
382
383 switch (cmd) {
384 case TEST_INIT:
385 info->name = "jitterbuffer_out_of_order_voice";
386 info->category = "/main/jitterbuf/";
387 info->summary = "Tests sending out of order audio frames to a jitter buffer";
388 info->description =
389 "Every 5th frame sent to a jitter buffer is reversed with the previous "
390 "frame. The expected result is to have a jitter buffer with the frames "
391 "in order, while a total of 10 frames should be recorded as having been "
392 "received out of order.";
393 return AST_TEST_NOT_RUN;
394 case TEST_EXECUTE:
395 break;
396 }
397
398 JB_TEST_BEGIN("jitterbuffer_out_of_order_voice");
399
400 if (!(jb = jb_new())) {
401 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
402 goto cleanup;
403 }
404
406 if (jb_setconf(jb, &jbconf) != JB_OK) {
407 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
408 goto cleanup;
409 }
410
412 goto cleanup;
413 }
414
415 for (i = 0; i < 40; i++) {
416 enum jb_return_code ret;
417 /* We should have a frame for each point in time */
418 if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
420 "Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
422 goto cleanup;
423 }
424 JB_NUMERIC_TEST(frame.ms, 20);
425 JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
426 }
427
428 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
429 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
430 goto cleanup;
431 }
434 JB_NUMERIC_TEST(jbinfo.frames_in, 40);
435 JB_NUMERIC_TEST(jbinfo.frames_out, 40);
436 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
437 JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
438 JB_NUMERIC_TEST(jbinfo.frames_ooo, 10);
439
441
442cleanup:
443 if (jb) {
444 /* No need to do anything - this will put all frames on the 'free' list,
445 * so jb_destroy will dispose of them */
446 while (jb_getall(jb, &frame) == JB_OK) { }
447 jb_destroy(jb);
448 }
449
451
452 return result;
453}
454
455AST_TEST_DEFINE(jitterbuffer_out_of_order_control)
456{
458 struct jitterbuf *jb = NULL;
459 struct jb_frame frame;
460 struct jb_info jbinfo;
461 struct jb_conf jbconf;
462 int i;
463
464 switch (cmd) {
465 case TEST_INIT:
466 info->name = "jitterbuffer_out_of_order_voice";
467 info->category = "/main/jitterbuf/";
468 info->summary = "Tests sending out of order audio frames to a jitter buffer";
469 info->description =
470 "Every 5th frame sent to a jitter buffer is reversed with the previous "
471 "frame. The expected result is to have a jitter buffer with the frames "
472 "in order, while a total of 10 frames should be recorded as having been "
473 "received out of order.";
474 return AST_TEST_NOT_RUN;
475 case TEST_EXECUTE:
476 break;
477 }
478
479 JB_TEST_BEGIN("jitterbuffer_out_of_order_control");
480
481 if (!(jb = jb_new())) {
482 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
483 goto cleanup;
484 }
485
487 if (jb_setconf(jb, &jbconf) != JB_OK) {
488 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
489 goto cleanup;
490 }
491
493 goto cleanup;
494 }
495
496 for (i = 0; i < 40; i++) {
497 enum jb_return_code ret;
498 /* We should have a frame for each point in time */
499 if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
501 "Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
503 goto cleanup;
504 }
505 JB_NUMERIC_TEST(frame.ms, 20);
506 JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
507 }
508
509 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
510 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
511 goto cleanup;
512 }
515 JB_NUMERIC_TEST(jbinfo.frames_in, 40);
516 JB_NUMERIC_TEST(jbinfo.frames_out, 40);
517 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
518 JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
519 JB_NUMERIC_TEST(jbinfo.frames_ooo, 10);
520
522
523cleanup:
524 if (jb) {
525 /* No need to do anything - this will put all frames on the 'free' list,
526 * so jb_destroy will dispose of them */
527 while (jb_getall(jb, &frame) == JB_OK) { }
528 jb_destroy(jb);
529 }
530
532
533 return result;
534}
535
536/*!
537 * \internal
538 * \brief Insert frames into the jitter buffer for the lost frame tests
539 */
540static int test_jb_lost_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
541{
542 int i = 0, ret = 0;
543
544 for (i = 0; i < 40; i++) {
545 if (i % 5 == 0) {
546 i++;
547 }
548 if (jb_put(jb, NULL, frame_type, 20, i * 20, i * 20 + 5) == JB_DROP) {
549 ast_test_status_update(test, "Jitter buffer dropped packet %d\n", i);
550 ret = 1;
551 break;
552 }
553 }
554
555 return ret;
556}
557
558AST_TEST_DEFINE(jitterbuffer_lost_voice)
559{
561 struct jitterbuf *jb = NULL;
562 struct jb_frame frame;
563 struct jb_conf jbconf;
564 struct jb_info jbinfo;
565 int i;
566
567 switch (cmd) {
568 case TEST_INIT:
569 info->name = "jitterbuffer_lost_voice";
570 info->category = "/main/jitterbuf/";
571 info->summary = "Tests missing frames in the jitterbuffer";
572 info->description =
573 "Every 5th frame that would be sent to a jitter buffer is instead"
574 "dropped. When reading data from the jitter buffer, the jitter buffer"
575 "should interpolate the voice frame.";
576 return AST_TEST_NOT_RUN;
577 case TEST_EXECUTE:
578 break;
579 }
580
581 JB_TEST_BEGIN("jitterbuffer_lost_voice");
582
583 if (!(jb = jb_new())) {
584 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
585 goto cleanup;
586 }
587
589 if (jb_setconf(jb, &jbconf) != JB_OK) {
590 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
591 goto cleanup;
592 }
593
595 goto cleanup;
596 }
597
598 for (i = 0; i < 40; i++) {
599 enum jb_return_code ret;
600 if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
601 /* If we didn't get an OK, make sure that it was an expected lost frame */
602 if (!((ret == JB_INTERP && i % 5 == 0) || (ret == JB_NOFRAME && i == 0))) {
604 "Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
606 goto cleanup;
607 }
608 } else {
609 JB_NUMERIC_TEST(frame.ms, 20);
610 JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
611 }
612 }
613
614 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
615 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
616 goto cleanup;
617 }
619 /* Note: The first frame (at i = 0) never got added, so nothing existed at that point.
620 * Its neither dropped nor lost.
621 */
622 JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
623 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
624 JB_NUMERIC_TEST(jbinfo.frames_lost, 7);
625 JB_NUMERIC_TEST(jbinfo.frames_in, 32);
626 JB_NUMERIC_TEST(jbinfo.frames_out, 32);
628
630
631cleanup:
632 if (jb) {
633 /* No need to do anything - this will put all frames on the 'free' list,
634 * so jb_destroy will dispose of them */
635 while (jb_getall(jb, &frame) == JB_OK) { }
636 jb_destroy(jb);
637 }
638
640
641 return result;
642}
643
644AST_TEST_DEFINE(jitterbuffer_lost_control)
645{
647 struct jitterbuf *jb = NULL;
648 struct jb_frame frame;
649 struct jb_conf jbconf;
650 struct jb_info jbinfo;
651 int i;
652
653 switch (cmd) {
654 case TEST_INIT:
655 info->name = "jitterbuffer_lost_control";
656 info->category = "/main/jitterbuf/";
657 info->summary = "Tests missing frames in the jitterbuffer";
658 info->description =
659 "Every 5th frame that would be sent to a jitter buffer is instead"
660 "dropped. When reading data from the jitter buffer, the jitter buffer"
661 "simply reports that no frame exists for that time slot";
662 return AST_TEST_NOT_RUN;
663 case TEST_EXECUTE:
664 break;
665 }
666
667 JB_TEST_BEGIN("jitterbuffer_lost_control");
668
669 if (!(jb = jb_new())) {
670 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
671 goto cleanup;
672 }
673
675 if (jb_setconf(jb, &jbconf) != JB_OK) {
676 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
677 goto cleanup;
678 }
679
681 goto cleanup;
682 }
683
684 for (i = 0; i < 40; i++) {
685 enum jb_return_code ret;
686 if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
687 /* If we didn't get an OK, make sure that it was an expected lost frame */
688 if (!(ret == JB_NOFRAME && i % 5 == 0)) {
690 "Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
692 goto cleanup;
693 }
694 } else {
695 JB_NUMERIC_TEST(frame.ms, 20);
696 JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
697 }
698 }
699
700 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
701 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
702 goto cleanup;
703 }
705 /* Note: The first frame (at i = 0) never got added, so nothing existed at that point.
706 * Its neither dropped nor lost.
707 */
708 JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
709 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
710 JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
711 JB_NUMERIC_TEST(jbinfo.frames_in, 32);
712 JB_NUMERIC_TEST(jbinfo.frames_out, 32);
714
716
717cleanup:
718 if (jb) {
719 /* No need to do anything - this will put all frames on the 'free' list,
720 * so jb_destroy will dispose of them */
721 while (jb_getall(jb, &frame) == JB_OK) { }
722 jb_destroy(jb);
723 }
724
726
727 return result;
728}
729
730/*!
731 * \internal
732 * \brief Insert frames into the jitter buffer for the late frame tests
733 */
734static int test_jb_late_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
735{
736 int i = 0, ret = 0;
737
738 for (i = 0; i < 40; i++) {
739 if (i % 5 == 0) {
740 /* Add 5th frame */
741 if (jb_put(jb, NULL, frame_type, 20, i * 20, i * 20 + 20) == JB_DROP) {
742 ast_test_status_update(test, "Jitter buffer dropped packet %d\n", (i+1));
743 ret = 1;
744 break;
745 }
746 } else {
747 if (jb_put(jb, NULL, frame_type, 20, i * 20, i * 20 + 5) == JB_DROP) {
748 ast_test_status_update(test, "Jitter buffer dropped packet %d\n", i);
749 ret = 1;
750 break;
751 }
752 }
753 }
754
755 return ret;
756}
757
758AST_TEST_DEFINE(jitterbuffer_late_voice)
759{
761 struct jitterbuf *jb = NULL;
762 struct jb_frame frame;
763 struct jb_info jbinfo;
764 struct jb_conf jbconf;
765 int i;
766
767 switch (cmd) {
768 case TEST_INIT:
769 info->name = "jitterbuffer_late_voice";
770 info->category = "/main/jitterbuf/";
771 info->summary = "Tests sending frames to a jitter buffer that arrive late";
772 info->description =
773 "Every 5th frame sent to a jitter buffer arrives late, but still in "
774 "order with respect to the previous and next packet";
775 return AST_TEST_NOT_RUN;
776 case TEST_EXECUTE:
777 break;
778 }
779
780 JB_TEST_BEGIN("jitterbuffer_late_voice");
781
782 if (!(jb = jb_new())) {
783 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
784 goto cleanup;
785 }
786
788 if (jb_setconf(jb, &jbconf) != JB_OK) {
789 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
790 goto cleanup;
791 }
792
794 goto cleanup;
795 }
796
797 for (i = 0; i < 40; i++) {
798 enum jb_return_code ret;
799 /* We should have a frame for each point in time */
800 if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
802 "Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
804 goto cleanup;
805 }
806 JB_NUMERIC_TEST(frame.ms, 20);
807 JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
808 }
809
810 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
811 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
812 goto cleanup;
813 }
815 JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
816 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
817 JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
818 JB_NUMERIC_TEST(jbinfo.frames_in, 40);
819 JB_NUMERIC_TEST(jbinfo.frames_out, 40);
821
823
824cleanup:
825 if (jb) {
826 /* No need to do anything - this will put all frames on the 'free' list,
827 * so jb_destroy will dispose of them */
828 while (jb_getall(jb, &frame) == JB_OK) { }
829 jb_destroy(jb);
830 }
831
833
834 return result;
835}
836
837AST_TEST_DEFINE(jitterbuffer_late_control)
838{
840 struct jitterbuf *jb = NULL;
841 struct jb_frame frame;
842 struct jb_info jbinfo;
843 struct jb_conf jbconf;
844 int i;
845
846 switch (cmd) {
847 case TEST_INIT:
848 info->name = "jitterbuffer_late_control";
849 info->category = "/main/jitterbuf/";
850 info->summary = "Tests sending frames to a jitter buffer that arrive late";
851 info->description =
852 "Every 5th frame sent to a jitter buffer arrives late, but still in "
853 "order with respect to the previous and next packet";
854 return AST_TEST_NOT_RUN;
855 case TEST_EXECUTE:
856 break;
857 }
858
859 JB_TEST_BEGIN("jitterbuffer_late_voice");
860
861 if (!(jb = jb_new())) {
862 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
863 goto cleanup;
864 }
865
867 if (jb_setconf(jb, &jbconf) != JB_OK) {
868 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
869 goto cleanup;
870 }
871
873 goto cleanup;
874 }
875
876 for (i = 0; i < 40; i++) {
877 enum jb_return_code ret;
878 /* We should have a frame for each point in time */
879 if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
881 "Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
883 goto cleanup;
884 }
885 JB_NUMERIC_TEST(frame.ms, 20);
886 JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
887 }
888
889 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
890 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
891 goto cleanup;
892 }
894 JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
895 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
896 JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
897 JB_NUMERIC_TEST(jbinfo.frames_in, 40);
898 JB_NUMERIC_TEST(jbinfo.frames_out, 40);
900
902
903cleanup:
904 if (jb) {
905 /* No need to do anything - this will put all frames on the 'free' list,
906 * so jb_destroy will dispose of them */
907 while (jb_getall(jb, &frame) == JB_OK) { }
908 jb_destroy(jb);
909 }
910
912
913 return result;
914}
915
916/*!
917 * \internal
918 * \brief Insert frames into the jitter buffer for the overflow tests
919 */
921{
922 int i = 0;
923
924 for (i = 0; i < 100; i++) {
925 jb_put(jb, NULL, frame_type, 20, i * 20, i * 20 + 5);
926 }
927}
928
929AST_TEST_DEFINE(jitterbuffer_overflow_voice)
930{
932 struct jitterbuf *jb = NULL;
933 struct jb_frame frame;
934 struct jb_info jbinfo;
935 struct jb_conf jbconf;
936 int i = 0;
937
938 switch (cmd) {
939 case TEST_INIT:
940 info->name = "jitterbuffer_overflow_voice";
941 info->category = "/main/jitterbuf/";
942 info->summary = "Tests overfilling a jitter buffer with voice frames";
943 info->description = "Tests overfilling a jitter buffer with voice frames";
944 return AST_TEST_NOT_RUN;
945 case TEST_EXECUTE:
946 break;
947 }
948
949 JB_TEST_BEGIN("jitterbuffer_overflow_voice");
950
951 if (!(jb = jb_new())) {
952 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
953 goto cleanup;
954 }
955
957 if (jb_setconf(jb, &jbconf) != JB_OK) {
958 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
959 goto cleanup;
960 }
961
963
964 while (jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN) == JB_OK) {
965 JB_NUMERIC_TEST(frame.ms, 20);
966 JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
967 ++i;
968 }
969
970 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
971 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
972 goto cleanup;
973 }
974
977 JB_NUMERIC_TEST(jbinfo.frames_out, 51);
978 JB_NUMERIC_TEST(jbinfo.frames_in, 51);
979 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
980 /* Note that the last frame will be interpolated */
981 JB_NUMERIC_TEST(jbinfo.frames_lost, 1);
982 JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
983
985
986cleanup:
987 if (jb) {
988 /* No need to do anything - this will put all frames on the 'free' list,
989 * so jb_destroy will dispose of them */
990 while (jb_getall(jb, &frame) == JB_OK) { }
991 jb_destroy(jb);
992 }
993
995
996 return result;
997}
998
999AST_TEST_DEFINE(jitterbuffer_overflow_control)
1000{
1002 struct jitterbuf *jb = NULL;
1003 struct jb_frame frame;
1004 struct jb_info jbinfo;
1005 struct jb_conf jbconf;
1006 int i = 0;
1007
1008 switch (cmd) {
1009 case TEST_INIT:
1010 info->name = "jitterbuffer_overflow_control";
1011 info->category = "/main/jitterbuf/";
1012 info->summary = "Tests overfilling a jitter buffer with control frames";
1013 info->description = "Tests overfilling a jitter buffer with control frames";
1014 return AST_TEST_NOT_RUN;
1015 case TEST_EXECUTE:
1016 break;
1017 }
1018
1019 JB_TEST_BEGIN("jitterbuffer_overflow_control");
1020
1021 if (!(jb = jb_new())) {
1022 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
1023 goto cleanup;
1024 }
1025
1026 test_jb_populate_config(&jbconf);
1027 if (jb_setconf(jb, &jbconf) != JB_OK) {
1028 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
1029 goto cleanup;
1030 }
1031
1033
1034 while (jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN) == JB_OK) {
1035 JB_NUMERIC_TEST(frame.ms, 20);
1036 JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
1037 ++i;
1038 }
1039
1040 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
1041 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
1042 goto cleanup;
1043 }
1044
1046 JB_NUMERIC_TEST(jbinfo.frames_dropped, 49);
1047 JB_NUMERIC_TEST(jbinfo.frames_out, 51);
1048 JB_NUMERIC_TEST(jbinfo.frames_in, 51);
1049 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
1050 JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
1051 JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
1052
1054
1055cleanup:
1056 if (jb) {
1057 /* No need to do anything - this will put all frames on the 'free' list,
1058 * so jb_destroy will dispose of them */
1059 while (jb_getall(jb, &frame) == JB_OK) { }
1060 jb_destroy(jb);
1061 }
1062
1064
1065 return result;
1066}
1067
1068/*!
1069 * \internal
1070 * \brief Insert frames into the jitter buffer for the resynch tests
1071 */
1073{
1074 int i = 0;
1075
1076 for (i = 0; i < 20; i++) {
1077 jb_put(jb, NULL, frame_type, 20, i * 20, i * 20 + 5);
1078 }
1079
1080 for (i = 20; i < 40; i++) {
1081 jb_put(jb, NULL, frame_type, 20, i * 20 + 500, i * 20 + 5);
1082 }
1083}
1084
1085AST_TEST_DEFINE(jitterbuffer_resynch_control)
1086{
1088 struct jitterbuf *jb = NULL;
1089 struct jb_frame frame;
1090 struct jb_info jbinfo;
1091 struct jb_conf jbconf;
1092 int interpolated_frames = 0;
1093 int i;
1094
1095 switch (cmd) {
1096 case TEST_INIT:
1097 info->name = "jitterbuffer_resynch_control";
1098 info->category = "/main/jitterbuf/";
1099 info->summary = "Tests sending control frames that force a resynch";
1100 info->description = "Control frames are sent to a jitter buffer. After some "
1101 "number of frames, the source timestamps jump, forcing a resync of "
1102 "the jitter buffer. Since the frames are control, the resync happens "
1103 "immediately.";
1104 return AST_TEST_NOT_RUN;
1105 case TEST_EXECUTE:
1106 break;
1107 }
1108
1109 JB_TEST_BEGIN("jitterbuffer_resynch_control");
1110
1111 if (!(jb = jb_new())) {
1112 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
1113 goto cleanup;
1114 }
1115
1116 test_jb_populate_config(&jbconf);
1117 jbconf.resync_threshold = 200;
1118 if (jb_setconf(jb, &jbconf) != JB_OK) {
1119 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
1120 goto cleanup;
1121 }
1122
1124
1125 for (i = 0; i <= 40; i++) {
1126 if (jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN) == JB_INTERP) {
1127 ++interpolated_frames;
1128 }
1129 }
1130
1131 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
1132 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
1133 goto cleanup;
1134 }
1135 /* With control frames, a resync happens automatically */
1138 JB_NUMERIC_TEST(jbinfo.frames_out, 40);
1139 JB_NUMERIC_TEST(jbinfo.frames_in, 40);
1140 /* Verify that each of the interpolated frames is counted */
1141 JB_NUMERIC_TEST(jbinfo.frames_lost, interpolated_frames);
1142 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
1143 JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
1144
1146
1147cleanup:
1148 if (jb) {
1149 /* No need to do anything - this will put all frames on the 'free' list,
1150 * so jb_destroy will dispose of them */
1151 while (jb_getall(jb, &frame) == JB_OK) { }
1152 jb_destroy(jb);
1153 }
1154
1156
1157 return result;
1158}
1159
1160AST_TEST_DEFINE(jitterbuffer_resynch_voice)
1161{
1163 struct jitterbuf *jb = NULL;
1164 struct jb_frame frame;
1165 struct jb_info jbinfo;
1166 struct jb_conf jbconf;
1167 int interpolated_frames = 0;
1168 int i;
1169
1170 switch (cmd) {
1171 case TEST_INIT:
1172 info->name = "jitterbuffer_resynch_voice";
1173 info->category = "/main/jitterbuf/";
1174 info->summary = "Tests sending voice frames that force a resynch";
1175 info->description = "Voice frames are sent to a jitter buffer. After some "
1176 "number of frames, the source timestamps jump, forcing a resync of "
1177 "the jitter buffer. Since the frames are voice, the resync happens "
1178 "after observing three packets that break the resync threshold.";
1179 return AST_TEST_NOT_RUN;
1180 case TEST_EXECUTE:
1181 break;
1182 }
1183
1184 JB_TEST_BEGIN("jitterbuffer_resynch_voice");
1185
1186 if (!(jb = jb_new())) {
1187 ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
1188 goto cleanup;
1189 }
1190
1191 test_jb_populate_config(&jbconf);
1192 jbconf.resync_threshold = 200;
1193 if (jb_setconf(jb, &jbconf) != JB_OK) {
1194 ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
1195 goto cleanup;
1196 }
1197
1199
1200 for (i = 0; i <= 40; i++) {
1201 if (jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN) == JB_INTERP) {
1202 ++interpolated_frames;
1203 }
1204 }
1205
1206 if (jb_getinfo(jb, &jbinfo) != JB_OK) {
1207 ast_test_status_update(test, "Failed to get jitterbuffer information\n");
1208 goto cleanup;
1209 }
1210 /* The first three packets before the resync should be dropped */
1213 JB_NUMERIC_TEST(jbinfo.frames_out, 37);
1214 JB_NUMERIC_TEST(jbinfo.frames_in, 37);
1215 /* Verify that each of the interpolated frames is counted */
1216 JB_NUMERIC_TEST(jbinfo.frames_lost, interpolated_frames);
1217 JB_NUMERIC_TEST(jbinfo.frames_late, 0);
1218 JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
1219
1220
1222
1223cleanup:
1224 if (jb) {
1225 /* No need to do anything - this will put all frames on the 'free' list,
1226 * so jb_destroy will dispose of them */
1227 while (jb_getall(jb, &frame) == JB_OK) { }
1228 jb_destroy(jb);
1229 }
1230
1232
1233 return result;
1234}
1235
1236static int unload_module(void)
1237{
1238 AST_TEST_UNREGISTER(jitterbuffer_nominal_voice_frames);
1239 AST_TEST_UNREGISTER(jitterbuffer_nominal_control_frames);
1240 AST_TEST_UNREGISTER(jitterbuffer_out_of_order_voice);
1241 AST_TEST_UNREGISTER(jitterbuffer_out_of_order_control);
1242 AST_TEST_UNREGISTER(jitterbuffer_lost_voice);
1243 AST_TEST_UNREGISTER(jitterbuffer_lost_control);
1244 AST_TEST_UNREGISTER(jitterbuffer_late_voice);
1245 AST_TEST_UNREGISTER(jitterbuffer_late_control);
1246 AST_TEST_UNREGISTER(jitterbuffer_overflow_voice);
1247 AST_TEST_UNREGISTER(jitterbuffer_overflow_control);
1248 AST_TEST_UNREGISTER(jitterbuffer_resynch_voice);
1249 AST_TEST_UNREGISTER(jitterbuffer_resynch_control);
1250 return 0;
1251}
1252
1253static int load_module(void)
1254{
1255 /* Nominal - put / get frames */
1256 AST_TEST_REGISTER(jitterbuffer_nominal_voice_frames);
1257 AST_TEST_REGISTER(jitterbuffer_nominal_control_frames);
1258
1259 /* Out of order frame arrival */
1260 AST_TEST_REGISTER(jitterbuffer_out_of_order_voice);
1261 AST_TEST_REGISTER(jitterbuffer_out_of_order_control);
1262
1263 /* Lost frame arrival */
1264 AST_TEST_REGISTER(jitterbuffer_lost_voice);
1265 AST_TEST_REGISTER(jitterbuffer_lost_control);
1266
1267 /* Late frame arrival */
1268 AST_TEST_REGISTER(jitterbuffer_late_voice);
1269 AST_TEST_REGISTER(jitterbuffer_late_control);
1270
1271 /* Buffer overflow */
1272 AST_TEST_REGISTER(jitterbuffer_overflow_voice);
1273 AST_TEST_REGISTER(jitterbuffer_overflow_control);
1274
1275 /* Buffer resynch */
1276 AST_TEST_REGISTER(jitterbuffer_resynch_voice);
1277 AST_TEST_REGISTER(jitterbuffer_resynch_control);
1278
1280}
1281
Asterisk main include file. File version handling, generic pbx functions.
#define ast_log
Definition: astobj2.c:42
static PGresult * result
Definition: cel_pgsql.c:84
frame_type
Definition: codec_builtin.c:44
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_LOG_WARNING
#define AST_LOG_ERROR
#define ast_debug(level,...)
Log a DEBUG message.
jitterbuf: an application-independent jitterbuffer jitterbuf.c
void jb_destroy(jitterbuf *jb)
destroy jitterbuf
Definition: jitterbuf.c:99
enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frame, long now, long interpl)
get a frame for time now (receiver's time) return value is one of JB_OK: You've got frame!...
Definition: jitterbuf.c:785
jitterbuf * jb_new(void)
new jitterbuf
Definition: jitterbuf.c:86
enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now)
queue a frame
Definition: jitterbuf.c:525
long jb_next(jitterbuf *jb)
when is the next frame due out, in receiver's time (0=EMPTY) This value may change as frames are adde...
Definition: jitterbuf.c:767
jb_frame_type
Definition: jitterbuf.h:59
@ JB_TYPE_CONTROL
Definition: jitterbuf.h:61
@ JB_TYPE_VOICE
Definition: jitterbuf.h:62
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
set jitterbuf conf
Definition: jitterbuf.c:825
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
unconditionally get frames from jitterbuf until empty
Definition: jitterbuf.c:801
jb_return_code
Definition: jitterbuf.h:49
@ JB_DROP
Definition: jitterbuf.h:55
@ JB_NOFRAME
Definition: jitterbuf.h:53
@ JB_INTERP
Definition: jitterbuf.h:54
@ JB_OK
Definition: jitterbuf.h:51
enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats)
get jitterbuf info: only "statistics" may be valid
Definition: jitterbuf.c:815
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
#define NULL
Definition: resample.c:96
long target_extra
Definition: jitterbuf.h:72
long max_jitterbuf
Definition: jitterbuf.h:69
long resync_threshold
Definition: jitterbuf.h:70
long max_contig_interp
Definition: jitterbuf.h:71
long ms
Definition: jitterbuf.h:104
long ts
Definition: jitterbuf.h:103
long frames_out
Definition: jitterbuf.h:80
long resync_offset
Definition: jitterbuf.h:97
long frames_in
Definition: jitterbuf.h:79
long frames_lost
Definition: jitterbuf.h:82
long frames_ooo
Definition: jitterbuf.h:84
long frames_late
Definition: jitterbuf.h:81
long frames_dropped
Definition: jitterbuf.h:83
jb_info info
Definition: jitterbuf.h:110
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
ast_test_result_state
Definition: test.h:193
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
const char * args
#define JB_TEST_END
#define JB_TEST_BEGIN(test_name)
static void test_jb_warn_output(const char *fmt,...)
AST_TEST_DEFINE(jitterbuffer_nominal_voice_frames)
static void test_jb_resynch_frame_insertion(struct jitterbuf *jb, enum jb_frame_type frame_type)
static void test_jb_populate_config(struct jb_conf *jbconf)
static int test_jb_lost_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
static const char * jitter_buffer_return_codes[]
#define DEFAULT_MAX_CONTIG_INTERP
static void test_jb_error_output(const char *fmt,...)
#define JB_INFO_PRINT_FRAME_DEBUG(jbinfo)
#define DEFAULT_RESYNCH_THRESHOLD
static int test_jb_nominal_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
#define DEFAULT_MAX_JITTERBUFFER
#define DEFAULT_CODEC_INTERP_LEN
static int load_module(void)
static int test_jb_late_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
static int unload_module(void)
static int test_jb_out_of_order_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
static void test_jb_debug_output(const char *fmt,...)
static void test_jb_overflow_frame_insertion(struct jitterbuf *jb, enum jb_frame_type frame_type)
#define JB_NUMERIC_TEST(attribute, expected)
Utility functions.