Wed Jan 8 2020 09:50:14

Asterisk developer's documentation


jitterbuf.c File Reference

jitterbuf: an application-independent jitterbuffer More...

#include "asterisk.h"
#include "jitterbuf.h"
#include "asterisk/utils.h"

Go to the source code of this file.

Macros

#define jb_dbg(...)   (dbgf ? dbgf(__VA_ARGS__) : (void)0)
 
#define jb_dbg2(...)   ((void)0)
 
#define jb_err(...)   (errf ? errf(__VA_ARGS__) : (void)0)
 
#define JB_LONGMAX   2147483647L
 
#define JB_LONGMIN   (-JB_LONGMAX - 1L)
 
#define jb_warn(...)   (warnf ? warnf(__VA_ARGS__) : (void)0)
 

Functions

static enum jb_return_code _jb_get (jitterbuf *jb, jb_frame *frameout, long now, long interpl)
 
static jb_frame_queue_get (jitterbuf *jb, long ts, int all)
 
static int check_resync (jitterbuf *jb, long ts, long now, long ms, const enum jb_frame_type type, long *delay)
 
static void decrement_losspct (jitterbuf *jb)
 
static void history_calc_maxbuf (jitterbuf *jb)
 
static void history_get (jitterbuf *jb)
 
static int history_put (jitterbuf *jb, long ts, long now, long ms, long delay)
 
static void increment_losspct (jitterbuf *jb)
 
void jb_destroy (jitterbuf *jb)
 destroy jitterbuf More...
 
enum jb_return_code jb_get (jitterbuf *jb, jb_frame *frameout, long now, long interpl)
 get a frame for time now (receiver's time) return value is one of JB_OK: You've got frame! JB_DROP: Here's an audio frame you should just drop. Ask me again for this time.. JB_NOFRAME: There's no frame scheduled for this time. JB_INTERP: Please interpolate an interpl-length frame for this time (either we need to grow, or there was a lost frame) JB_EMPTY: The jb is empty. More...
 
enum jb_return_code jb_getall (jitterbuf *jb, jb_frame *frameout)
 unconditionally get frames from jitterbuf until empty More...
 
enum jb_return_code jb_getinfo (jitterbuf *jb, jb_info *stats)
 get jitterbuf info: only "statistics" may be valid More...
 
jitterbufjb_new ()
 new jitterbuf More...
 
long jb_next (jitterbuf *jb)
 when is the next frame due out, in receiver's time (0=EMPTY) This value may change as frames are added (esp non-audio frames) More...
 
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 More...
 
void jb_reset (jitterbuf *jb)
 reset jitterbuf More...
 
enum jb_return_code jb_setconf (jitterbuf *jb, jb_conf *conf)
 set jitterbuf conf More...
 
void jb_setoutput (jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg)
 
static jb_framequeue_get (jitterbuf *jb, long ts)
 
static jb_framequeue_getall (jitterbuf *jb)
 
static long queue_last (jitterbuf *jb)
 
static long queue_next (jitterbuf *jb)
 
static int queue_put (jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts)
 

Variables

static jb_output_function_t dbgf
 
static jb_output_function_t errf
 
static jb_output_function_t warnf
 

Detailed Description

jitterbuf: an application-independent jitterbuffer

Author
Steve Kann steve.nosp@m.k@st.nosp@m.evek..nosp@m.com

Definition in file jitterbuf.c.

Macro Definition Documentation

#define jb_dbg (   ...)    (dbgf ? dbgf(__VA_ARGS__) : (void)0)

Definition at line 47 of file jitterbuf.c.

Referenced by _jb_get().

#define jb_dbg2 (   ...)    ((void)0)

Definition at line 52 of file jitterbuf.c.

Referenced by jb_destroy(), jb_new(), and jb_put().

#define jb_err (   ...)    (errf ? errf(__VA_ARGS__) : (void)0)

Definition at line 46 of file jitterbuf.c.

Referenced by queue_put().

#define JB_LONGMAX   2147483647L

define these here, just for ancient compiler systems

Definition at line 42 of file jitterbuf.c.

Referenced by history_calc_maxbuf(), and jb_next().

#define JB_LONGMIN   (-JB_LONGMAX - 1L)

Definition at line 43 of file jitterbuf.c.

Referenced by history_calc_maxbuf().

#define jb_warn (   ...)    (warnf ? warnf(__VA_ARGS__) : (void)0)

Definition at line 45 of file jitterbuf.c.

Referenced by check_resync(), and jb_get().

Function Documentation

static enum jb_return_code _jb_get ( jitterbuf jb,
jb_frame frameout,
long  now,
long  interpl 
)
static

Definition at line 552 of file jitterbuf.c.

References jb_info::cnt_contig_interp, jb_info::conf, jb_info::current, decrement_losspct(), jb_info::frames_dropped, jb_info::frames_late, jb_info::frames_lost, jb_info::frames_out, history_get(), increment_losspct(), jitterbuf::info, JB_ADJUST_DELAY, jb_dbg, JB_DROP, JB_INTERP, JB_NOFRAME, JB_OK, JB_TYPE_SILENCE, JB_TYPE_VOICE, jb_info::jitter, jb_info::last_adjustment, jb_info::last_voice_ms, jb_conf::max_contig_interp, jb_conf::max_jitterbuf, jb_info::min, jb_frame::ms, jb_info::next_voice_ts, queue_get(), queue_last(), queue_next(), jb_info::silence_begin_ts, jb_info::target, jb_conf::target_extra, jb_frame::ts, and jb_frame::type.

Referenced by jb_get().

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 }
long max_jitterbuf
Definition: jitterbuf.h:67
static void decrement_losspct(jitterbuf *jb)
Definition: jitterbuf.c:69
enum jb_frame_type type
Definition: jitterbuf.h:103
long silence_begin_ts
Definition: jitterbuf.h:91
#define jb_dbg(...)
Definition: jitterbuf.c:47
#define JB_ADJUST_DELAY
Definition: jitterbuf.h:44
long frames_lost
Definition: jitterbuf.h:80
static long queue_last(jitterbuf *jb)
Definition: jitterbuf.c:408
long last_adjustment
Definition: jitterbuf.h:92
static void increment_losspct(jitterbuf *jb)
Definition: jitterbuf.c:64
long frames_dropped
Definition: jitterbuf.h:81
jb_info info
Definition: jitterbuf.h:108
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
long target
Definition: jitterbuf.h:87
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
static long queue_next(jitterbuf *jb)
Definition: jitterbuf.c:400
long next_voice_ts
Definition: jitterbuf.h:89
long cnt_contig_interp
Definition: jitterbuf.h:96
long min
Definition: jitterbuf.h:85
long frames_out
Definition: jitterbuf.h:78
long jitter
Definition: jitterbuf.h:84
static void history_get(jitterbuf *jb)
Definition: jitterbuf.c:297
long current
Definition: jitterbuf.h:86
long max_contig_interp
Definition: jitterbuf.h:69
static jb_frame* _queue_get ( jitterbuf jb,
long  ts,
int  all 
)
static

Definition at line 416 of file jitterbuf.c.

References jitterbuf::frames, jb_info::frames_cur, jitterbuf::free, jitterbuf::info, jb_frame::next, jb_frame::prev, and jb_frame::ts.

Referenced by queue_get(), and queue_getall().

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 }
jb_frame * frames
Definition: jitterbuf.h:118
struct jb_frame * prev
Definition: jitterbuf.h:104
jb_frame * free
Definition: jitterbuf.h:119
jb_info info
Definition: jitterbuf.h:108
long ts
Definition: jitterbuf.h:101
struct jb_frame * next
Definition: jitterbuf.h:104
long frames_cur
Definition: jitterbuf.h:83
static int check_resync ( jitterbuf jb,
long  ts,
long  now,
long  ms,
const enum jb_frame_type  type,
long *  delay 
)
static

Definition at line 118 of file jitterbuf.c.

References ast_debug, jb_info::cnt_delay_discont, jb_info::conf, jitterbuf::dropem, jitterbuf::frames, jb_info::frames_dropped, jitterbuf::hist_maxbuf_valid, jitterbuf::hist_ptr, jitterbuf::info, JB_TYPE_CONTROL, jb_warn, jb_info::jitter, jb_info::last_delay, jb_conf::max_jitterbuf, jb_frame::prev, jb_info::resync_offset, jb_conf::resync_threshold, and jb_frame::ts.

Referenced by jb_put().

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 }
long max_jitterbuf
Definition: jitterbuf.h:67
int hist_maxbuf_valid
Definition: jitterbuf.h:115
jb_frame * frames
Definition: jitterbuf.h:118
long cnt_delay_discont
Definition: jitterbuf.h:94
long last_delay
Definition: jitterbuf.h:93
struct jb_frame * prev
Definition: jitterbuf.h:104
int hist_ptr
Definition: jitterbuf.h:112
threshold
Definition: dsp.h:62
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
long resync_threshold
Definition: jitterbuf.h:68
long frames_dropped
Definition: jitterbuf.h:81
jb_info info
Definition: jitterbuf.h:108
jb_conf conf
Definition: jitterbuf.h:74
long ts
Definition: jitterbuf.h:101
static const char type[]
Definition: chan_nbs.c:57
unsigned int dropem
Definition: jitterbuf.h:116
long resync_offset
Definition: jitterbuf.h:95
long jitter
Definition: jitterbuf.h:84
#define jb_warn(...)
Definition: jitterbuf.c:45
static void decrement_losspct ( jitterbuf jb)
static

Definition at line 69 of file jitterbuf.c.

References jitterbuf::info, and jb_info::losspct.

Referenced by _jb_get().

70 {
71  jb->info.losspct = (499 * jb->info.losspct)/500;
72 }
long losspct
Definition: jitterbuf.h:88
jb_info info
Definition: jitterbuf.h:108
static void history_calc_maxbuf ( jitterbuf jb)
static

Definition at line 216 of file jitterbuf.c.

References jitterbuf::hist_maxbuf, jitterbuf::hist_maxbuf_valid, jitterbuf::hist_minbuf, jitterbuf::hist_ptr, jitterbuf::history, JB_HISTORY_MAXBUF_SZ, JB_HISTORY_SZ, JB_LONGMAX, and JB_LONGMIN.

Referenced by history_get().

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 }
long hist_minbuf[JB_HISTORY_MAXBUF_SZ]
Definition: jitterbuf.h:114
int hist_maxbuf_valid
Definition: jitterbuf.h:115
#define JB_LONGMAX
Definition: jitterbuf.c:42
int hist_ptr
Definition: jitterbuf.h:112
#define JB_LONGMIN
Definition: jitterbuf.c:43
long hist_maxbuf[JB_HISTORY_MAXBUF_SZ]
Definition: jitterbuf.h:113
#define JB_HISTORY_SZ
Definition: jitterbuf.h:33
#define JB_HISTORY_MAXBUF_SZ
Definition: jitterbuf.h:40
long history[JB_HISTORY_SZ]
Definition: jitterbuf.h:111
static void history_get ( jitterbuf jb)
static

Definition at line 297 of file jitterbuf.c.

References jitterbuf::hist_maxbuf, jitterbuf::hist_maxbuf_valid, jitterbuf::hist_minbuf, jitterbuf::hist_ptr, history_calc_maxbuf(), if(), jitterbuf::info, JB_HISTORY_DROPPCT, JB_HISTORY_MAXBUF_SZ, JB_HISTORY_SZ, jb_info::jitter, and jb_info::min.

Referenced by _jb_get(), jb_getinfo(), and jb_next().

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 }
long hist_minbuf[JB_HISTORY_MAXBUF_SZ]
Definition: jitterbuf.h:114
#define JB_HISTORY_DROPPCT
Definition: jitterbuf.h:36
int hist_maxbuf_valid
Definition: jitterbuf.h:115
int hist_ptr
Definition: jitterbuf.h:112
long hist_maxbuf[JB_HISTORY_MAXBUF_SZ]
Definition: jitterbuf.h:113
#define JB_HISTORY_SZ
Definition: jitterbuf.h:33
#define JB_HISTORY_MAXBUF_SZ
Definition: jitterbuf.h:40
jb_info info
Definition: jitterbuf.h:108
if(yyss+yystacksize-1<=yyssp)
Definition: ast_expr2.c:1874
long min
Definition: jitterbuf.h:85
static void history_calc_maxbuf(jitterbuf *jb)
Definition: jitterbuf.c:216
long jitter
Definition: jitterbuf.h:84
static int history_put ( jitterbuf jb,
long  ts,
long  now,
long  ms,
long  delay 
)
static

Definition at line 165 of file jitterbuf.c.

References jitterbuf::hist_maxbuf, jitterbuf::hist_maxbuf_valid, jitterbuf::hist_ptr, jitterbuf::history, JB_HISTORY_MAXBUF_SZ, and JB_HISTORY_SZ.

Referenced by jb_put().

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 }
int hist_maxbuf_valid
Definition: jitterbuf.h:115
int hist_ptr
Definition: jitterbuf.h:112
long hist_maxbuf[JB_HISTORY_MAXBUF_SZ]
Definition: jitterbuf.h:113
#define JB_HISTORY_SZ
Definition: jitterbuf.h:33
#define JB_HISTORY_MAXBUF_SZ
Definition: jitterbuf.h:40
long history[JB_HISTORY_SZ]
Definition: jitterbuf.h:111
static void increment_losspct ( jitterbuf jb)
static

Definition at line 64 of file jitterbuf.c.

References jitterbuf::info, and jb_info::losspct.

Referenced by _jb_get().

65 {
66  jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;
67 }
long losspct
Definition: jitterbuf.h:88
jb_info info
Definition: jitterbuf.h:108
void jb_destroy ( jitterbuf jb)

destroy jitterbuf

Definition at line 101 of file jitterbuf.c.

References ast_free, jitterbuf::free, jb_dbg2, and jb_frame::next.

Referenced by jb_destroy_adaptive(), and pvt_destructor().

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 }
#define jb_dbg2(...)
Definition: jitterbuf.c:52
jb_frame * free
Definition: jitterbuf.h:119
#define ast_free(a)
Definition: astmm.h:97
struct jb_frame * next
Definition: jitterbuf.h:104
enum jb_return_code jb_get ( jitterbuf jb,
jb_frame frameout,
long  now,
long  interpl 
)

get a frame for time now (receiver's time) return value is one of JB_OK: You've got frame! JB_DROP: Here's an audio frame you should just drop. Ask me again for this time.. JB_NOFRAME: There's no frame scheduled for this time. JB_INTERP: Please interpolate an interpl-length frame for this time (either we need to grow, or there was a lost frame) JB_EMPTY: The jb is empty.

Definition at line 787 of file jitterbuf.c.

References _jb_get(), jitterbuf::info, JB_DROP, JB_INTERP, JB_OK, jb_warn, jb_info::last_voice_ms, jb_frame::ms, and jb_frame::ts.

Referenced by __get_from_jb(), and jb_get_adaptive().

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 }
jb_return_code
Definition: jitterbuf.h:47
jb_info info
Definition: jitterbuf.h:108
long last_voice_ms
Definition: jitterbuf.h:90
long ts
Definition: jitterbuf.h:101
long ms
Definition: jitterbuf.h:102
static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
Definition: jitterbuf.c:552
#define jb_warn(...)
Definition: jitterbuf.c:45
enum jb_return_code jb_getall ( jitterbuf jb,
jb_frame frameout 
)

unconditionally get frames from jitterbuf until empty

Definition at line 803 of file jitterbuf.c.

References JB_NOFRAME, JB_OK, and queue_getall().

Referenced by complete_transfer(), jb_empty_and_reset_adaptive(), jb_remove_adaptive(), pvt_destructor(), and schedule_delivery().

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 }
static jb_frame * queue_getall(jitterbuf *jb)
Definition: jitterbuf.c:456
enum jb_return_code jb_getinfo ( jitterbuf jb,
jb_info stats 
)

get jitterbuf info: only "statistics" may be valid

Definition at line 817 of file jitterbuf.c.

References history_get(), jitterbuf::info, and JB_OK.

Referenced by ast_cli_netstats(), construct_rr(), handle_cli_iax2_show_channels(), and log_jitterstats().

818 {
819 
820  history_get(jb);
821 
822  *stats = jb->info;
823 
824  return JB_OK;
825 }
jb_info info
Definition: jitterbuf.h:108
static void history_get(jitterbuf *jb)
Definition: jitterbuf.c:297
jitterbuf* jb_new ( void  )

new jitterbuf

Definition at line 88 of file jitterbuf.c.

References ast_calloc, jb_dbg2, and jb_reset().

Referenced by jb_create_adaptive(), and new_iax().

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 }
#define jb_dbg2(...)
Definition: jitterbuf.c:52
#define ast_calloc(a, b)
Definition: astmm.h:82
void jb_reset(jitterbuf *jb)
reset jitterbuf
Definition: jitterbuf.c:74
long jb_next ( jitterbuf jb)

when is the next frame due out, in receiver's time (0=EMPTY) This value may change as frames are added (esp non-audio frames)

Definition at line 769 of file jitterbuf.c.

References jb_info::conf, jb_info::current, jitterbuf::frames, history_get(), jitterbuf::info, JB_LONGMAX, jb_info::last_adjustment, jb_info::next_voice_ts, queue_next(), jb_info::silence_begin_ts, jb_info::target, and jb_conf::target_extra.

Referenced by __get_from_jb(), jb_next_adaptive(), and update_jbsched().

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 }
long silence_begin_ts
Definition: jitterbuf.h:91
jb_frame * frames
Definition: jitterbuf.h:118
#define JB_LONGMAX
Definition: jitterbuf.c:42
long last_adjustment
Definition: jitterbuf.h:92
jb_info info
Definition: jitterbuf.h:108
long target_extra
Definition: jitterbuf.h:70
jb_conf conf
Definition: jitterbuf.h:74
long target
Definition: jitterbuf.h:87
static long queue_next(jitterbuf *jb)
Definition: jitterbuf.c:400
long next_voice_ts
Definition: jitterbuf.h:89
static void history_get(jitterbuf *jb)
Definition: jitterbuf.c:297
long current
Definition: jitterbuf.h:86
enum jb_return_code jb_put ( jitterbuf jb,
void *  data,
const enum jb_frame_type  type,
long  ms,
long  ts,
long  now 
)

queue a frame

data=frame data, timings (in ms): ms=length of frame (for voice), ts=ts (sender's time) now=now (in receiver's time) return value is one of JB_OK: Frame added. Last call to jb_next() still valid JB_DROP: Drop this frame immediately JB_SCHED: Frame added. Call jb_next() to get a new time for the next frame

Definition at line 527 of file jitterbuf.c.

References check_resync(), jb_info::frames_in, history_put(), jitterbuf::info, jb_dbg2, JB_DROP, JB_OK, JB_SCHED, JB_TYPE_VOICE, queue_put(), and jb_info::resync_offset.

Referenced by jb_put_adaptive(), and schedule_delivery().

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 }
#define jb_dbg2(...)
Definition: jitterbuf.c:52
long frames_in
Definition: jitterbuf.h:77
static int history_put(jitterbuf *jb, long ts, long now, long ms, long delay)
Definition: jitterbuf.c:165
static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts)
Definition: jitterbuf.c:339
jb_info info
Definition: jitterbuf.h:108
static const char type[]
Definition: chan_nbs.c:57
long resync_offset
Definition: jitterbuf.h:95
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_reset ( jitterbuf jb)

reset jitterbuf

Note
The jitterbuffer should be empty before you call this, otherwise you will leak queued frames, and some internal structures

Definition at line 74 of file jitterbuf.c.

References jb_info::conf, jb_info::current, jitterbuf::free, jitterbuf::info, JB_TARGET_EXTRA, jb_info::silence_begin_ts, jb_info::target, and jb_conf::target_extra.

Referenced by complete_transfer(), jb_empty_and_reset_adaptive(), jb_new(), and schedule_delivery().

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 }
#define JB_TARGET_EXTRA
Definition: jitterbuf.h:42
long silence_begin_ts
Definition: jitterbuf.h:91
jb_frame * free
Definition: jitterbuf.h:119
jb_info info
Definition: jitterbuf.h:108
long target_extra
Definition: jitterbuf.h:70
jb_conf conf
Definition: jitterbuf.h:74
long target
Definition: jitterbuf.h:87
long current
Definition: jitterbuf.h:86
enum jb_return_code jb_setconf ( jitterbuf jb,
jb_conf conf 
)

set jitterbuf conf

Definition at line 827 of file jitterbuf.c.

References jb_info::conf, jb_info::current, jitterbuf::info, JB_OK, JB_TARGET_EXTRA, jb_conf::max_contig_interp, jb_conf::max_jitterbuf, jb_conf::resync_threshold, jb_info::target, and jb_conf::target_extra.

Referenced by jb_create_adaptive(), and new_iax().

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 }
long max_jitterbuf
Definition: jitterbuf.h:67
#define JB_TARGET_EXTRA
Definition: jitterbuf.h:42
long resync_threshold
Definition: jitterbuf.h:68
jb_info info
Definition: jitterbuf.h:108
long target_extra
Definition: jitterbuf.h:70
jb_conf conf
Definition: jitterbuf.h:74
long target
Definition: jitterbuf.h:87
long current
Definition: jitterbuf.h:86
long max_contig_interp
Definition: jitterbuf.h:69
void jb_setoutput ( jb_output_function_t  err,
jb_output_function_t  warn,
jb_output_function_t  dbg 
)

Definition at line 57 of file jitterbuf.c.

Referenced by handle_cli_iax2_set_debug_jb(), and load_module().

58 {
59  errf = err;
60  warnf = warn;
61  dbgf = dbg;
62 }
static jb_output_function_t dbgf
Definition: jitterbuf.c:55
static jb_output_function_t warnf
Definition: jitterbuf.c:55
static jb_output_function_t errf
Definition: jitterbuf.c:55
static jb_frame* queue_get ( jitterbuf jb,
long  ts 
)
static

Definition at line 451 of file jitterbuf.c.

References _queue_get().

Referenced by _jb_get().

452 {
453  return _queue_get(jb,ts,0);
454 }
static jb_frame * _queue_get(jitterbuf *jb, long ts, int all)
Definition: jitterbuf.c:416
static jb_frame* queue_getall ( jitterbuf jb)
static

Definition at line 456 of file jitterbuf.c.

References _queue_get().

Referenced by jb_getall().

457 {
458  return _queue_get(jb,0,1);
459 }
static jb_frame * _queue_get(jitterbuf *jb, long ts, int all)
Definition: jitterbuf.c:416
static long queue_last ( jitterbuf jb)
static

Definition at line 408 of file jitterbuf.c.

References jitterbuf::frames, jb_frame::prev, and jb_frame::ts.

Referenced by _jb_get().

409 {
410  if (jb->frames)
411  return jb->frames->prev->ts;
412  else
413  return -1;
414 }
jb_frame * frames
Definition: jitterbuf.h:118
struct jb_frame * prev
Definition: jitterbuf.h:104
long ts
Definition: jitterbuf.h:101
static long queue_next ( jitterbuf jb)
static

Definition at line 400 of file jitterbuf.c.

References jitterbuf::frames, and jb_frame::ts.

Referenced by _jb_get(), and jb_next().

401 {
402  if (jb->frames)
403  return jb->frames->ts;
404  else
405  return -1;
406 }
jb_frame * frames
Definition: jitterbuf.h:118
long ts
Definition: jitterbuf.h:101
static int queue_put ( jitterbuf jb,
void *  data,
const enum jb_frame_type  type,
long  ms,
long  ts 
)
static

Definition at line 339 of file jitterbuf.c.

References ast_malloc, jb_frame::data, frames, jitterbuf::frames, jb_info::frames_cur, jb_info::frames_ooo, jitterbuf::free, jitterbuf::info, jb_err, jb_frame::ms, jb_frame::next, jb_frame::prev, jb_info::resync_offset, jb_frame::ts, type, and jb_frame::type.

Referenced by jb_put().

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 }
enum jb_frame_type type
Definition: jitterbuf.h:103
jb_frame * frames
Definition: jitterbuf.h:118
struct jb_frame * prev
Definition: jitterbuf.h:104
static int frames
Definition: iax2-parser.c:49
jb_frame * free
Definition: jitterbuf.h:119
long frames_ooo
Definition: jitterbuf.h:82
jb_info info
Definition: jitterbuf.h:108
long ts
Definition: jitterbuf.h:101
void * data
Definition: jitterbuf.h:100
long ms
Definition: jitterbuf.h:102
#define jb_err(...)
Definition: jitterbuf.c:46
static const char type[]
Definition: chan_nbs.c:57
long resync_offset
Definition: jitterbuf.h:95
struct jb_frame * next
Definition: jitterbuf.h:104
long frames_cur
Definition: jitterbuf.h:83
#define ast_malloc(a)
Definition: astmm.h:91

Variable Documentation

jb_output_function_t dbgf
static

Definition at line 55 of file jitterbuf.c.

jb_output_function_t errf
static

Definition at line 55 of file jitterbuf.c.

jb_output_function_t warnf
static

Definition at line 55 of file jitterbuf.c.