Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]> \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 
88 static 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  */
101 static 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  */
117 static 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  */
133 static 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 
142  ast_log(AST_LOG_WARNING, "%s", buf);
143 }
144 
145 /*!
146  * \internal
147  * \brief Error callback function for the jitter buffer's jb_err function
148  */
149 static 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  */
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 
180 AST_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 
209  test_jb_populate_config(&jbconf);
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 
233  result = AST_TEST_PASS;
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  }
240  JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
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 
247 cleanup:
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 
255  JB_TEST_END;
256 
257  return result;
258 }
259 
260 AST_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 
289  test_jb_populate_config(&jbconf);
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  }
317  JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
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 
324  result = AST_TEST_PASS;
325 
326 cleanup:
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 
334  JB_TEST_END;
335 
336  return result;
337 }
338 
339 /*!
340  * \internal
341  * \brief Insert frames into the jitter buffer for the out of order tests
342  */
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 
374 AST_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 
405  test_jb_populate_config(&jbconf);
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  }
433  JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
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 
440  result = AST_TEST_PASS;
441 
442 cleanup:
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 
450  JB_TEST_END;
451 
452  return result;
453 }
454 
455 AST_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 
486  test_jb_populate_config(&jbconf);
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  }
514  JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
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 
521  result = AST_TEST_PASS;
522 
523 cleanup:
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 
531  JB_TEST_END;
532 
533  return result;
534 }
535 
536 /*!
537  * \internal
538  * \brief Insert frames into the jitter buffer for the lost frame tests
539  */
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 
558 AST_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 
588  test_jb_populate_config(&jbconf);
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);
627  JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
628 
629  result = AST_TEST_PASS;
630 
631 cleanup:
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 
639  JB_TEST_END;
640 
641  return result;
642 }
643 
644 AST_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 
674  test_jb_populate_config(&jbconf);
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);
713  JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
714 
715  result = AST_TEST_PASS;
716 
717 cleanup:
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 
725  JB_TEST_END;
726 
727  return result;
728 }
729 
730 /*!
731  * \internal
732  * \brief Insert frames into the jitter buffer for the late frame tests
733  */
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 
758 AST_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 
787  test_jb_populate_config(&jbconf);
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);
820  JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
821 
822  result = AST_TEST_PASS;
823 
824 cleanup:
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 
832  JB_TEST_END;
833 
834  return result;
835 }
836 
837 AST_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 
866  test_jb_populate_config(&jbconf);
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);
899  JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
900 
901  result = AST_TEST_PASS;
902 
903 cleanup:
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 
911  JB_TEST_END;
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 
929 AST_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 
956  test_jb_populate_config(&jbconf);
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 
976  JB_NUMERIC_TEST(jbinfo.frames_dropped, 49);
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 
984  result = AST_TEST_PASS;
985 
986 cleanup:
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 
994  JB_TEST_END;
995 
996  return result;
997 }
998 
999 AST_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 
1045  JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
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 
1053  result = AST_TEST_PASS;
1054 
1055 cleanup:
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 
1063  JB_TEST_END;
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 
1085 AST_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 */
1136  JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
1137  JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
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 
1145  result = AST_TEST_PASS;
1146 
1147 cleanup:
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 
1155  JB_TEST_END;
1156 
1157  return result;
1158 }
1159 
1160 AST_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 */
1211  JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
1212  JB_NUMERIC_TEST(jbinfo.frames_dropped, 3);
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 
1221  result = AST_TEST_PASS;
1222 
1223 cleanup:
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 
1231  JB_TEST_END;
1232 
1233  return result;
1234 }
1235 
1236 static 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 
1253 static 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 
1279  return AST_MODULE_LOAD_SUCCESS;
1280 }
1281 
long max_jitterbuf
Definition: jitterbuf.h:67
#define JB_NUMERIC_TEST(attribute, expected)
#define DEFAULT_CODEC_INTERP_LEN
jb_return_code
Definition: jitterbuf.h:47
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk main include file. File version handling, generic pbx functions.
jb_frame_type
Definition: jitterbuf.h:57
AST_TEST_DEFINE(jitterbuffer_nominal_voice_frames)
static void test_jb_populate_config(struct jb_conf *jbconf)
#define DEFAULT_MAX_JITTERBUFFER
#define JB_INFO_PRINT_FRAME_DEBUG(jbinfo)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static void test_jb_resynch_frame_insertion(struct jitterbuf *jb, enum jb_frame_type frame_type)
#define AST_LOG_WARNING
Definition: logger.h:279
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 frames_lost
Definition: jitterbuf.h:80
Test Framework API.
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
const char * args
#define NULL
Definition: resample.c:96
enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frame, long now, long interpl)
get a frame for time now (receiver&#39;s time) return value is one of JB_OK: You&#39;ve got frame! JB_DROP: H...
Definition: jitterbuf.c:785
Utility functions.
#define JB_TEST_BEGIN(test_name)
jitterbuf * jb_new(void)
new jitterbuf
Definition: jitterbuf.c:86
static int test_jb_lost_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
long frames_in
Definition: jitterbuf.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
long jb_next(jitterbuf *jb)
when is the next frame due out, in receiver&#39;s time (0=EMPTY) This value may change as frames are adde...
Definition: jitterbuf.c:767
long resync_threshold
Definition: jitterbuf.h:68
#define JB_TEST_END
#define AST_LOG_ERROR
Definition: logger.h:290
long frames_ooo
Definition: jitterbuf.h:82
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define DEFAULT_MAX_CONTIG_INTERP
long frames_dropped
Definition: jitterbuf.h:81
static void test_jb_warn_output(const char *fmt,...)
jb_info info
Definition: jitterbuf.h:108
long target_extra
Definition: jitterbuf.h:70
jitterbuf: an application-independent jitterbuffer jitterbuf.c
long ts
Definition: jitterbuf.h:101
static void test_jb_error_output(const char *fmt,...)
static int load_module(void)
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
set jitterbuf conf
Definition: jitterbuf.c:825
def info(msg)
frame_type
Definition: codec_builtin.c:44
long frames_late
Definition: jitterbuf.h:79
long ms
Definition: jitterbuf.h:102
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_overflow_frame_insertion(struct jitterbuf *jb, enum jb_frame_type frame_type)
static const char * jitter_buffer_return_codes[]
static int test_jb_nominal_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
static int unload_module(void)
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
Definition: test.c:65
#define DEFAULT_RESYNCH_THRESHOLD
enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats)
get jitterbuf info: only "statistics" may be valid
Definition: jitterbuf.c:815
static void test_jb_debug_output(const char *fmt,...)
static PGresult * result
Definition: cel_pgsql.c:88
static int test_jb_late_frame_insertion(struct ast_test *test, struct jitterbuf *jb, enum jb_frame_type frame_type)
long resync_offset
Definition: jitterbuf.h:95
long frames_out
Definition: jitterbuf.h:78
void jb_destroy(jitterbuf *jb)
destroy jitterbuf
Definition: jitterbuf.c:99
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
unconditionally get frames from jitterbuf until empty
Definition: jitterbuf.c:801
static snd_pcm_format_t format
Definition: chan_alsa.c:102
long max_contig_interp
Definition: jitterbuf.h:69
ast_test_result_state
Definition: test.h:200