Wed Jan 8 2020 09:49:48

Asterisk developer's documentation


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