Asterisk - The Open Source Telephony Project  18.5.0
jitterbuf.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004-2005, Horizon Wimba, Inc.
5  *
6  * Contributors:
7  * Steve Kann <[email protected]>
8  *
9  * A license has been granted to Digium (via disclaimer) for the use of
10  * this code.
11  *
12  * See http://www.asterisk.org for more information about
13  * the Asterisk project. Please do not directly contact
14  * any of the maintainers of this project for assistance;
15  * the project provides a web site, mailing lists and IRC
16  * channels for your use.
17  *
18  * This program is free software, distributed under the terms of
19  * the GNU General Public License Version 2. See the LICENSE file
20  * at the top of the source tree.
21  */
22 
23 /*! \file
24  *
25  * \brief jitterbuf: an application-independent jitterbuffer
26  * \author Steve Kann <[email protected]>
27  *
28  */
29 
30 /*** MODULEINFO
31  <support_level>core</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 #include "jitterbuf.h"
37 #include "asterisk/utils.h"
38 
39 /*! define these here, just for ancient compiler systems */
40 #define JB_LONGMAX 2147483647L
41 #define JB_LONGMIN (-JB_LONGMAX - 1L)
42 
43 #define jb_warn(...) (warnf ? warnf(__VA_ARGS__) : (void)0)
44 #define jb_err(...) (errf ? errf(__VA_ARGS__) : (void)0)
45 #define jb_dbg(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
46 
47 #ifdef DEEP_DEBUG
48 #define jb_dbg2(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
49 #else
50 #define jb_dbg2(...) ((void)0)
51 #endif
52 
54 
56 {
57  errf = err;
58  warnf = warn;
59  dbgf = dbg;
60 }
61 
62 static void increment_losspct(jitterbuf *jb)
63 {
64  jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;
65 }
66 
67 static void decrement_losspct(jitterbuf *jb)
68 {
69  jb->info.losspct = (499 * jb->info.losspct)/500;
70 }
71 
73 {
74  /* only save settings and free list */
75  jb_conf s = jb->info.conf;
76  jb_frame *fr = jb->free;
77  memset(jb, 0, sizeof(*jb));
78  jb->info.conf = s;
79  jb->free = fr;
80 
81  /* initialize length, using the default value */
83  jb->info.silence_begin_ts = -1;
84 }
85 
87 {
88  jitterbuf *jb;
89 
90  if (!(jb = ast_calloc(1, sizeof(*jb))))
91  return NULL;
92 
93  jb_reset(jb);
94 
95  jb_dbg2("jb_new() = %x\n", jb);
96  return jb;
97 }
98 
100 {
101  jb_frame *frame;
102  jb_dbg2("jb_destroy(%x)\n", jb);
103 
104  /* free all the frames on the "free list" */
105  frame = jb->free;
106  while (frame != NULL) {
107  jb_frame *next = frame->next;
108  ast_free(frame);
109  frame = next;
110  }
111 
112  /* free ourselves! */
113  ast_free(jb);
114 }
115 
116 static int check_resync(jitterbuf *jb, long ts, long now, long ms, const enum jb_frame_type type, long *delay)
117 {
118  long numts = 0;
119  long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold;
120 
121  /* Check for overfill of the buffer */
122  if (jb->frames) {
123  numts = jb->frames->prev->ts - jb->frames->ts;
124  }
125 
126  if (numts >= (jb->info.conf.max_jitterbuf)) {
127  if (!jb->dropem) {
128  ast_debug(1, "Attempting to exceed Jitterbuf max %ld timeslots\n",
129  jb->info.conf.max_jitterbuf);
130  jb->dropem = 1;
131  }
132  jb->info.frames_dropped++;
133  return -1;
134  } else {
135  jb->dropem = 0;
136  }
137 
138  /* check for drastic change in delay */
139  if (jb->info.conf.resync_threshold != -1) {
140  if (labs(*delay - jb->info.last_delay) > threshold) {
141  jb->info.cnt_delay_discont++;
142  /* resync the jitterbuffer on 3 consecutive discontinuities,
143  * or immediately if a control frame */
144  if ((jb->info.cnt_delay_discont > 3) || (type == JB_TYPE_CONTROL)) {
145  jb->info.cnt_delay_discont = 0;
146  jb->hist_ptr = 0;
147  jb->hist_maxbuf_valid = 0;
148  jb_warn("Resyncing the jb. last_delay %ld, this delay %ld, threshold %ld, new offset %ld\n", jb->info.last_delay, *delay, threshold, ts - now);
149  jb->info.resync_offset = ts - now;
150  jb->info.last_delay = *delay = 0; /* after resync, frame is right on time */
151  } else {
152  jb->info.frames_dropped++;
153  return -1;
154  }
155  } else {
156  jb->info.last_delay = *delay;
157  jb->info.cnt_delay_discont = 0;
158  }
159  }
160  return 0;
161 }
162 
163 static int history_put(jitterbuf *jb, long ts, long now, long ms, long delay)
164 {
165  long kicked;
166 
167  /* don't add special/negative times to history */
168  if (ts <= 0)
169  return 0;
170 
171  kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ];
172 
173  jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay;
174 
175  /* optimization; the max/min buffers don't need to be recalculated, if this packet's
176  * entry doesn't change them. This happens if this packet is not involved, _and_ any packet
177  * that got kicked out of the history is also not involved
178  * We do a number of comparisons, but it's probably still worthwhile, because it will usually
179  * succeed, and should be a lot faster than going through all 500 packets in history */
180  if (!jb->hist_maxbuf_valid)
181  return 0;
182 
183  /* don't do this until we've filled history
184  * (reduces some edge cases below) */
185  if (jb->hist_ptr < JB_HISTORY_SZ)
186  goto invalidate;
187 
188  /* if the new delay would go into min */
189  if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
190  goto invalidate;
191 
192  /* or max.. */
193  if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
194  goto invalidate;
195 
196  /* or the kicked delay would be in min */
197  if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
198  goto invalidate;
199 
200  if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
201  goto invalidate;
202 
203  /* if we got here, we don't need to invalidate, 'cause this delay didn't
204  * affect things */
205  return 0;
206  /* end optimization */
207 
208 
209 invalidate:
210  jb->hist_maxbuf_valid = 0;
211  return 0;
212 }
213 
215 {
216  int i,j;
217 
218  if (jb->hist_ptr == 0)
219  return;
220 
221 
222  /* initialize maxbuf/minbuf to the latest value */
223  for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) {
224 /*
225  * jb->hist_maxbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
226  * jb->hist_minbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
227  */
228  jb->hist_maxbuf[i] = JB_LONGMIN;
229  jb->hist_minbuf[i] = JB_LONGMAX;
230  }
231 
232  /* use insertion sort to populate maxbuf */
233  /* we want it to be the top "n" values, in order */
234 
235  /* start at the beginning, or JB_HISTORY_SZ frames ago */
236  i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0;
237 
238  for (;i<jb->hist_ptr;i++) {
239  long toins = jb->history[i % JB_HISTORY_SZ];
240 
241  /* if the maxbuf should get this */
242  if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) {
243 
244  /* insertion-sort it into the maxbuf */
245  for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
246  /* found where it fits */
247  if (toins > jb->hist_maxbuf[j]) {
248  /* move over */
249  if (j != JB_HISTORY_MAXBUF_SZ - 1) {
250  memmove(jb->hist_maxbuf + j + 1, jb->hist_maxbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_maxbuf[0]));
251  }
252  /* insert */
253  jb->hist_maxbuf[j] = toins;
254 
255  break;
256  }
257  }
258  }
259 
260  /* if the minbuf should get this */
261  if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) {
262 
263  /* insertion-sort it into the maxbuf */
264  for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
265  /* found where it fits */
266  if (toins < jb->hist_minbuf[j]) {
267  /* move over */
268  if (j != JB_HISTORY_MAXBUF_SZ - 1) {
269  memmove(jb->hist_minbuf + j + 1, jb->hist_minbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_minbuf[0]));
270  }
271  /* insert */
272  jb->hist_minbuf[j] = toins;
273 
274  break;
275  }
276  }
277  }
278 
279  if (0) {
280  int k;
281  fprintf(stderr, "toins = %ld\n", toins);
282  fprintf(stderr, "maxbuf =");
283  for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
284  fprintf(stderr, "%ld ", jb->hist_maxbuf[k]);
285  fprintf(stderr, "\nminbuf =");
286  for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
287  fprintf(stderr, "%ld ", jb->hist_minbuf[k]);
288  fprintf(stderr, "\n");
289  }
290  }
291 
292  jb->hist_maxbuf_valid = 1;
293 }
294 
295 static void history_get(jitterbuf *jb)
296 {
297  long max, min, jitter;
298  int idx;
299  int count;
300 
301  if (!jb->hist_maxbuf_valid)
303 
304  /* count is how many items in history we're examining */
305  count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ;
306 
307  /* idx is the "n"ths highest/lowest that we'll look for */
308  idx = count * JB_HISTORY_DROPPCT / 100;
309 
310  /* sanity checks for idx */
311  if (idx > (JB_HISTORY_MAXBUF_SZ - 1))
312  idx = JB_HISTORY_MAXBUF_SZ - 1;
313 
314  if (idx < 0) {
315  jb->info.min = 0;
316  jb->info.jitter = 0;
317  return;
318  }
319 
320  max = jb->hist_maxbuf[idx];
321  min = jb->hist_minbuf[idx];
322 
323  jitter = max - min;
324 
325  /* these debug stmts compare the difference between looking at the absolute jitter, and the
326  * values we get by throwing away the outliers */
327  /*
328  fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", index, min, max, jitter);
329  fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", 0, jb->hist_minbuf[0], jb->hist_maxbuf[0], jb->hist_maxbuf[0]-jb->hist_minbuf[0]);
330  */
331 
332  jb->info.min = min;
333  jb->info.jitter = jitter;
334 }
335 
336 /* returns 1 if frame was inserted into head of queue, 0 otherwise */
337 static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts)
338 {
339  jb_frame *frame;
340  jb_frame *p;
341  int head = 0;
342  long resync_ts = ts - jb->info.resync_offset;
343 
344  if ((frame = jb->free)) {
345  jb->free = frame->next;
346  } else if (!(frame = ast_malloc(sizeof(*frame)))) {
347  jb_err("cannot allocate frame\n");
348  return 0;
349  }
350 
351  jb->info.frames_cur++;
352 
353  frame->data = data;
354  frame->ts = resync_ts;
355  frame->ms = ms;
356  frame->type = type;
357 
358  /*
359  * frames are a circular list, jb-frames points to the lowest ts,
360  * jb->frames->prev points to the highest ts
361  */
362 
363  if (!jb->frames) { /* queue is empty */
364  jb->frames = frame;
365  frame->next = frame;
366  frame->prev = frame;
367  head = 1;
368  } else if (resync_ts < jb->frames->ts) {
369  frame->next = jb->frames;
370  frame->prev = jb->frames->prev;
371 
372  frame->next->prev = frame;
373  frame->prev->next = frame;
374 
375  /* frame is out of order */
376  jb->info.frames_ooo++;
377 
378  jb->frames = frame;
379  head = 1;
380  } else {
381  p = jb->frames;
382 
383  /* frame is out of order */
384  if (resync_ts < p->prev->ts) jb->info.frames_ooo++;
385 
386  while (resync_ts < p->prev->ts && p->prev != jb->frames)
387  p = p->prev;
388 
389  frame->next = p;
390  frame->prev = p->prev;
391 
392  frame->next->prev = frame;
393  frame->prev->next = frame;
394  }
395  return head;
396 }
397 
398 static long queue_next(jitterbuf *jb)
399 {
400  if (jb->frames)
401  return jb->frames->ts;
402  else
403  return -1;
404 }
405 
406 static long queue_last(jitterbuf *jb)
407 {
408  if (jb->frames)
409  return jb->frames->prev->ts;
410  else
411  return -1;
412 }
413 
414 static jb_frame *_queue_get(jitterbuf *jb, long ts, int all)
415 {
416  jb_frame *frame;
417  frame = jb->frames;
418 
419  if (!frame)
420  return NULL;
421 
422  /*jb_warn("queue_get: ASK %ld FIRST %ld\n", ts, frame->ts); */
423 
424  if (all || ts >= frame->ts) {
425  /* remove this frame */
426  frame->prev->next = frame->next;
427  frame->next->prev = frame->prev;
428 
429  if (frame->next == frame)
430  jb->frames = NULL;
431  else
432  jb->frames = frame->next;
433 
434 
435  /* insert onto "free" single-linked list */
436  frame->next = jb->free;
437  jb->free = frame;
438 
439  jb->info.frames_cur--;
440 
441  /* we return the frame pointer, even though it's on free list,
442  * but caller must copy data */
443  return frame;
444  }
445 
446  return NULL;
447 }
448 
449 static jb_frame *queue_get(jitterbuf *jb, long ts)
450 {
451  return _queue_get(jb,ts,0);
452 }
453 
455 {
456  return _queue_get(jb,0,1);
457 }
458 
459 #if 0
460 /* some diagnostics */
461 static void jb_dbginfo(jitterbuf *jb)
462 {
463  if (dbgf == NULL)
464  return;
465 
466  jb_dbg("\njb info: fin=%ld fout=%ld flate=%ld flost=%ld fdrop=%ld fcur=%ld\n",
468 
469  jb_dbg("jitter=%ld current=%ld target=%ld min=%ld sil=%d len=%d len/fcur=%ld\n",
470  jb->info.jitter, jb->info.current, jb->info.target, jb->info.min, jb->info.silence_begin_ts, jb->info.current - jb->info.min,
471  jb->info.frames_cur ? (jb->info.current - jb->info.min)/jb->info.frames_cur : -8);
472  if (jb->info.frames_in > 0)
473  jb_dbg("jb info: Loss PCT = %ld%%, Late PCT = %ld%%\n",
474  jb->info.frames_lost * 100/(jb->info.frames_in + jb->info.frames_lost),
475  jb->info.frames_late * 100/jb->info.frames_in);
476  jb_dbg("jb info: queue %d -> %d. last_ts %d (queue len: %d) last_ms %d\n",
477  queue_next(jb),
478  queue_last(jb),
479  jb->info.next_voice_ts,
480  queue_last(jb) - queue_next(jb),
481  jb->info.last_voice_ms);
482 }
483 #endif
484 
485 #ifdef DEEP_DEBUG
486 static void jb_chkqueue(jitterbuf *jb)
487 {
488  int i=0;
489  jb_frame *p = jb->frames;
490 
491  if (!p) {
492  return;
493  }
494 
495  do {
496  if (p->next == NULL) {
497  jb_err("Queue is BROKEN at item [%d]", i);
498  }
499  i++;
500  p=p->next;
501  } while (p->next != jb->frames);
502 }
503 
504 static void jb_dbgqueue(jitterbuf *jb)
505 {
506  int i=0;
507  jb_frame *p = jb->frames;
508 
509  jb_dbg("queue: ");
510 
511  if (!p) {
512  jb_dbg("EMPTY\n");
513  return;
514  }
515 
516  do {
517  jb_dbg("[%d]=%ld ", i++, p->ts);
518  p=p->next;
519  } while (p->next != jb->frames);
520 
521  jb_dbg("\n");
522 }
523 #endif
524 
525 enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now)
526 {
527  long delay = now - (ts - jb->info.resync_offset);
528  jb_dbg2("jb_put(%x,%x,%ld,%ld,%ld)\n", jb, data, ms, ts, now);
529 
530  if (check_resync(jb, ts, now, ms, type, &delay)) {
531  return JB_DROP;
532  }
533 
534  if (type == JB_TYPE_VOICE) {
535  /* presently, I'm only adding VOICE frames to history and drift calculations; mostly because with the
536  * IAX integrations, I'm sending retransmitted control frames with their awkward timestamps through */
537  history_put(jb, ts, now, ms, delay);
538  }
539 
540  jb->info.frames_in++;
541 
542  /* if put into head of queue, caller needs to reschedule */
543  if (queue_put(jb,data,type,ms,ts)) {
544  return JB_SCHED;
545  }
546  return JB_OK;
547 }
548 
549 
550 static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
551 {
552  jb_frame *frame;
553  long diff;
554  static int dbg_cnt = 0;
555 
556  /* get jitter info */
557  history_get(jb);
558 
559  if (dbg_cnt && dbg_cnt % 50 == 0) {
560  jb_dbg("\n");
561  }
562  dbg_cnt++;
563 
564  /* target */
565  jb->info.target = jb->info.jitter + jb->info.min + jb->info.conf.target_extra;
566 
567  /* if a hard clamp was requested, use it */
568  if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) {
569  jb_dbg("clamping target from %ld to %ld\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf);
570  jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf;
571  }
572 
573  diff = jb->info.target - jb->info.current;
574 
575  /* jb_warn("diff = %d lms=%d last = %d now = %d\n", diff, */
576  /* jb->info.last_voice_ms, jb->info.last_adjustment, now); */
577 
578  /* let's work on non-silent case first */
579  if (!jb->info.silence_begin_ts) {
580  /* we want to grow */
581  if ((diff > 0) &&
582  /* we haven't grown in the delay length */
583  (((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) ||
584  /* we need to grow more than the "length" we have left */
585  (diff > queue_last(jb) - queue_next(jb)) ) ) {
586  /* grow by interp frame length */
587  jb->info.current += interpl;
588  jb->info.next_voice_ts += interpl;
589  jb->info.last_voice_ms = interpl;
590  jb->info.last_adjustment = now;
591  jb->info.cnt_contig_interp++;
594  }
595  jb_dbg("G");
596  return JB_INTERP;
597  }
598 
599  frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current);
600 
601  /* not a voice frame; just return it. */
602  if (frame && frame->type != JB_TYPE_VOICE) {
603  if (frame->type == JB_TYPE_SILENCE) {
604  jb->info.silence_begin_ts = frame->ts;
605  jb->info.cnt_contig_interp = 0;
606  }
607 
608  *frameout = *frame;
609  jb->info.frames_out++;
610  jb_dbg("o");
611  return JB_OK;
612  }
613 
614 
615  /* voice frame is later than expected */
616  if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) {
617  if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) {
618  /* either we interpolated past this frame in the last jb_get */
619  /* or the frame is still in order, but came a little too quick */
620  *frameout = *frame;
621  /* reset expectation for next frame */
622  jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
623  jb->info.frames_out++;
624  decrement_losspct(jb);
625  jb->info.cnt_contig_interp = 0;
626  jb_dbg("v");
627  return JB_OK;
628  } else {
629  /* voice frame is late */
630  *frameout = *frame;
631  jb->info.frames_out++;
632  decrement_losspct(jb);
633  jb->info.frames_late++;
634  jb->info.frames_lost--;
635  jb_dbg("l");
636  return JB_DROP;
637  }
638  }
639 
640  /* keep track of frame sizes, to allow for variable sized-frames */
641  if (frame && frame->ms > 0) {
642  jb->info.last_voice_ms = frame->ms;
643  }
644 
645  /* we want to shrink; shrink at 1 frame / 500ms */
646  /* unless we don't have a frame, then shrink 1 frame */
647  /* every 80ms (though perhaps we can shrink even faster */
648  /* in this case) */
649  if (diff < -jb->info.conf.target_extra &&
650  ((!frame && jb->info.last_adjustment + 80 < now) ||
651  (jb->info.last_adjustment + 500 < now))) {
652 
653  jb->info.last_adjustment = now;
654  jb->info.cnt_contig_interp = 0;
655 
656  if (frame) {
657  *frameout = *frame;
658  /* shrink by frame size we're throwing out */
659  jb->info.current -= frame->ms;
660  jb->info.frames_out++;
661  decrement_losspct(jb);
662  jb->info.frames_dropped++;
663  jb_dbg("s");
664  return JB_DROP;
665  } else {
666  /* shrink by last_voice_ms */
667  jb->info.current -= jb->info.last_voice_ms;
668  jb->info.frames_lost++;
669  increment_losspct(jb);
670  jb_dbg("S");
671  return JB_NOFRAME;
672  }
673  }
674 
675  /* lost frame */
676  if (!frame) {
677  /* this is a bit of a hack for now, but if we're close to
678  * target, and we find a missing frame, it makes sense to
679  * grow, because the frame might just be a bit late;
680  * otherwise, we presently get into a pattern where we return
681  * INTERP for the lost frame, then it shows up next, and we
682  * throw it away because it's late */
683  /* I've recently only been able to replicate this using
684  * iaxclient talking to app_echo on asterisk. In this case,
685  * my outgoing packets go through asterisk's (old)
686  * jitterbuffer, and then might get an unusual increasing delay
687  * there if it decides to grow?? */
688  /* Update: that might have been a different bug, that has been fixed..
689  * But, this still seemed like a good idea, except that it ended up making a single actual
690  * lost frame get interpolated two or more times, when there was "room" to grow, so it might
691  * be a bit of a bad idea overall */
692  /*if (diff > -1 * jb->info.last_voice_ms) {
693  jb->info.current += jb->info.last_voice_ms;
694  jb->info.last_adjustment = now;
695  jb_warn("g");
696  return JB_INTERP;
697  } */
698  jb->info.frames_lost++;
699  increment_losspct(jb);
700  jb->info.next_voice_ts += interpl;
701  jb->info.last_voice_ms = interpl;
702  jb->info.cnt_contig_interp++;
705  }
706  jb_dbg("L");
707  return JB_INTERP;
708  }
709 
710  /* normal case; return the frame, increment stuff */
711  *frameout = *frame;
712  jb->info.next_voice_ts += frame->ms;
713  jb->info.frames_out++;
714  jb->info.cnt_contig_interp = 0;
715  decrement_losspct(jb);
716  jb_dbg("v");
717  return JB_OK;
718  } else {
719  /* TODO: after we get the non-silent case down, we'll make the
720  * silent case -- basically, we'll just grow and shrink faster
721  * here, plus handle next_voice_ts a bit differently */
722 
723  /* to disable silent special case altogether, just uncomment this: */
724  /* jb->info.silence_begin_ts = 0; */
725 
726  /* shrink interpl len every 10ms during silence */
727  if (diff < -jb->info.conf.target_extra &&
728  jb->info.last_adjustment + 10 <= now) {
729  jb->info.current -= interpl;
730  jb->info.last_adjustment = now;
731  }
732 
733  frame = queue_get(jb, now - jb->info.current);
734  if (!frame) {
735  return JB_NOFRAME;
736  } else if (frame->type != JB_TYPE_VOICE) {
737  /* normal case; in silent mode, got a non-voice frame */
738  *frameout = *frame;
739  jb->info.frames_out++;
740  return JB_OK;
741  }
742  if (frame->ts < jb->info.silence_begin_ts) {
743  /* voice frame is late */
744  *frameout = *frame;
745  jb->info.frames_out++;
746  decrement_losspct(jb);
747  jb->info.frames_late++;
748  jb->info.frames_lost--;
749  jb_dbg("l");
750  return JB_DROP;
751  } else {
752  /* voice frame */
753  /* try setting current to target right away here */
754  jb->info.current = jb->info.target;
755  jb->info.silence_begin_ts = 0;
756  jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
757  jb->info.last_voice_ms = frame->ms;
758  jb->info.frames_out++;
759  decrement_losspct(jb);
760  *frameout = *frame;
761  jb_dbg("V");
762  return JB_OK;
763  }
764  }
765 }
766 
768 {
769  if (jb->info.silence_begin_ts) {
770  if (jb->frames) {
771  long next = queue_next(jb);
772  history_get(jb);
773  /* shrink during silence */
774  if (jb->info.target - jb->info.current < -jb->info.conf.target_extra)
775  return jb->info.last_adjustment + 10;
776  return next + jb->info.target;
777  }
778  else
779  return JB_LONGMAX;
780  } else {
781  return jb->info.next_voice_ts;
782  }
783 }
784 
785 enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
786 {
787  enum jb_return_code ret = _jb_get(jb, frameout, now, interpl);
788 #if 0
789  static int lastts=0;
790  int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0;
791  jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists);
792  if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n");
793  lastts = thists;
794 #endif
795  if (ret == JB_INTERP)
796  frameout->ms = jb->info.last_voice_ms;
797 
798  return ret;
799 }
800 
802 {
803  jb_frame *frame;
804  frame = queue_getall(jb);
805 
806  if (!frame) {
807  return JB_NOFRAME;
808  }
809 
810  *frameout = *frame;
811  return JB_OK;
812 }
813 
814 
816 {
817 
818  history_get(jb);
819 
820  *stats = jb->info;
821 
822  return JB_OK;
823 }
824 
826 {
827  /* take selected settings from the struct */
828 
829  jb->info.conf.max_jitterbuf = conf->max_jitterbuf;
832 
833  /* -1 indicates use of the default JB_TARGET_EXTRA value */
834  jb->info.conf.target_extra = ( conf->target_extra == -1 )
836  : conf->target_extra
837  ;
838 
839  /* update these to match new target_extra setting */
840  jb->info.current = jb->info.conf.target_extra;
841  jb->info.target = jb->info.conf.target_extra;
842 
843  return JB_OK;
844 }
845 
846 int jb_is_late(jitterbuf *jb, long ts)
847 {
848  return ts + jb->info.current < jb->info.next_voice_ts;
849 }
long max_jitterbuf
Definition: jitterbuf.h:67
static const char type[]
Definition: chan_ooh323.c:109
static void decrement_losspct(jitterbuf *jb)
Definition: jitterbuf.c:67
jb_return_code
Definition: jitterbuf.h:47
long hist_minbuf[JB_HISTORY_MAXBUF_SZ]
Definition: jitterbuf.h:114
Asterisk main include file. File version handling, generic pbx functions.
#define JB_TARGET_EXTRA
Definition: jitterbuf.h:42
#define JB_HISTORY_DROPPCT
Definition: jitterbuf.h:36
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
unconditionally get frames from jitterbuf until empty
Definition: jitterbuf.c:801
jb_frame_type
Definition: jitterbuf.h:57
enum jb_frame_type type
Definition: jitterbuf.h:103
int hist_maxbuf_valid
Definition: jitterbuf.h:115
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 silence_begin_ts
Definition: jitterbuf.h:91
#define jb_dbg(...)
Definition: jitterbuf.c:45
#define jb_dbg2(...)
Definition: jitterbuf.c:50
static jb_output_function_t dbgf
Definition: jitterbuf.c:53
jb_frame * frames
Definition: jitterbuf.h:118
#define JB_ADJUST_DELAY
Definition: jitterbuf.h:44
long losspct
Definition: jitterbuf.h:88
void(* jb_output_function_t)(const char *fmt,...)
Definition: jitterbuf.h:166
long frames_lost
Definition: jitterbuf.h:80
long cnt_delay_discont
Definition: jitterbuf.h:94
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
static jb_frame * _queue_get(jitterbuf *jb, long ts, int all)
Definition: jitterbuf.c:414
static long queue_last(jitterbuf *jb)
Definition: jitterbuf.c:406
#define JB_LONGMAX
Definition: jitterbuf.c:40
long last_delay
Definition: jitterbuf.h:93
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
#define NULL
Definition: resample.c:96
struct jb_frame * prev
Definition: jitterbuf.h:104
int hist_ptr
Definition: jitterbuf.h:112
#define JB_LONGMIN
Definition: jitterbuf.c:41
enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats)
get jitterbuf info: only "statistics" may be valid
Definition: jitterbuf.c:815
Utility functions.
threshold
Definition: dsp.h:71
All configuration options for statsd client.
Definition: res_statsd.c:95
enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frameout, 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
long last_adjustment
Definition: jitterbuf.h:92
long frames_in
Definition: jitterbuf.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
long resync_threshold
Definition: jitterbuf.h:68
jb_frame * free
Definition: jitterbuf.h:119
long hist_maxbuf[JB_HISTORY_MAXBUF_SZ]
Definition: jitterbuf.h:113
static int history_put(jitterbuf *jb, long ts, long now, long ms, long delay)
Definition: jitterbuf.c:163
long frames_ooo
Definition: jitterbuf.h:82
static int frames
Definition: parser.c:51
static void increment_losspct(jitterbuf *jb)
Definition: jitterbuf.c:62
static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts)
Definition: jitterbuf.c:337
#define JB_HISTORY_SZ
Definition: jitterbuf.h:33
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
long frames_dropped
Definition: jitterbuf.h:81
#define JB_HISTORY_MAXBUF_SZ
Definition: jitterbuf.h:40
jb_info info
Definition: jitterbuf.h:108
long history[JB_HISTORY_SZ]
Definition: jitterbuf.h:111
long last_voice_ms
Definition: jitterbuf.h:90
long target_extra
Definition: jitterbuf.h:70
jitterbuf: an application-independent jitterbuffer jitterbuf.c
jb_conf conf
Definition: jitterbuf.h:74
long ts
Definition: jitterbuf.h:101
static jb_output_function_t warnf
Definition: jitterbuf.c:53
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
set jitterbuf conf
Definition: jitterbuf.c:825
long target
Definition: jitterbuf.h:87
int jb_is_late(jitterbuf *jb, long ts)
Checks if the given time stamp is late.
Definition: jitterbuf.c:846
void * data
Definition: jitterbuf.h:100
def info(msg)
static jb_frame * queue_get(jitterbuf *jb, long ts)
Definition: jitterbuf.c:449
long frames_late
Definition: jitterbuf.h:79
long ms
Definition: jitterbuf.h:102
void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg)
Definition: jitterbuf.c:55
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define jb_err(...)
Definition: jitterbuf.c:44
static jb_frame * queue_getall(jitterbuf *jb)
Definition: jitterbuf.c:454
static long queue_next(jitterbuf *jb)
Definition: jitterbuf.c:398
long next_voice_ts
Definition: jitterbuf.h:89
unsigned int dropem
Definition: jitterbuf.h:116
long cnt_contig_interp
Definition: jitterbuf.h:96
static jb_output_function_t errf
Definition: jitterbuf.c:53
long resync_offset
Definition: jitterbuf.h:95
long min
Definition: jitterbuf.h:85
long frames_out
Definition: jitterbuf.h:78
void jb_destroy(jitterbuf *jb)
destroy jitterbuf
Definition: jitterbuf.c:99
struct jb_frame * next
Definition: jitterbuf.h:104
void jb_reset(jitterbuf *jb)
reset jitterbuf
Definition: jitterbuf.c:72
static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
Definition: jitterbuf.c:550
long frames_cur
Definition: jitterbuf.h:83
static void history_calc_maxbuf(jitterbuf *jb)
Definition: jitterbuf.c:214
long jitter
Definition: jitterbuf.h:84
#define jb_warn(...)
Definition: jitterbuf.c:43
static int check_resync(jitterbuf *jb, long ts, long now, long ms, const enum jb_frame_type type, long *delay)
Definition: jitterbuf.c:116
static void history_get(jitterbuf *jb)
Definition: jitterbuf.c:295
jitterbuf * jb_new()
new jitterbuf
Definition: jitterbuf.c:86
#define min(a, b)
Definition: f2c.h:197
long current
Definition: jitterbuf.h:86
long max_contig_interp
Definition: jitterbuf.h:69
#define max(a, b)
Definition: f2c.h:198