Asterisk - The Open Source Telephony Project  GIT-master-a24979a
Macros | Functions | Variables
jitterbuf.c File Reference

jitterbuf: an application-independent jitterbuffer More...

#include "asterisk.h"
#include "jitterbuf.h"
#include "asterisk/utils.h"
Include dependency graph for jitterbuf.c:

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...
 
int jb_is_late (jitterbuf *jb, long ts)
 Checks if the given time stamp is late. 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

◆ jb_dbg

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

Definition at line 45 of file jitterbuf.c.

◆ jb_dbg2

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

Definition at line 50 of file jitterbuf.c.

◆ jb_err

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

Definition at line 44 of file jitterbuf.c.

◆ JB_LONGMAX

#define JB_LONGMAX   2147483647L

define these here, just for ancient compiler systems

Definition at line 40 of file jitterbuf.c.

◆ JB_LONGMIN

#define JB_LONGMIN   (-JB_LONGMAX - 1L)

Definition at line 41 of file jitterbuf.c.

◆ jb_warn

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

Definition at line 43 of file jitterbuf.c.

Function Documentation

◆ _jb_get()

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

Definition at line 454 of file jitterbuf.c.

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 }
static void history_get(jitterbuf *jb)
Definition: jitterbuf.c:295
static long queue_last(jitterbuf *jb)
Definition: jitterbuf.c:406
static long queue_next(jitterbuf *jb)
Definition: jitterbuf.c:398
#define jb_dbg(...)
Definition: jitterbuf.c:45
static void increment_losspct(jitterbuf *jb)
Definition: jitterbuf.c:62
static void decrement_losspct(jitterbuf *jb)
Definition: jitterbuf.c:67
static jb_frame * queue_get(jitterbuf *jb, long ts)
Definition: jitterbuf.c:449
#define JB_ADJUST_DELAY
Definition: jitterbuf.h:45
@ JB_TYPE_SILENCE
Definition: jitterbuf.h:64
@ JB_TYPE_VOICE
Definition: jitterbuf.h:62
@ JB_DROP
Definition: jitterbuf.h:55
@ JB_NOFRAME
Definition: jitterbuf.h:53
@ JB_INTERP
Definition: jitterbuf.h:54
@ JB_OK
Definition: jitterbuf.h:51
def info(msg)
long target_extra
Definition: jitterbuf.h:72
long max_jitterbuf
Definition: jitterbuf.h:69
long max_contig_interp
Definition: jitterbuf.h:71
long ms
Definition: jitterbuf.h:104
long ts
Definition: jitterbuf.h:103
enum jb_frame_type type
Definition: jitterbuf.h:105
long frames_out
Definition: jitterbuf.h:80
long target
Definition: jitterbuf.h:89
long cnt_contig_interp
Definition: jitterbuf.h:98
long min
Definition: jitterbuf.h:87
long current
Definition: jitterbuf.h:88
long silence_begin_ts
Definition: jitterbuf.h:93
jb_conf conf
Definition: jitterbuf.h:76
long frames_lost
Definition: jitterbuf.h:82
long frames_late
Definition: jitterbuf.h:81
long frames_dropped
Definition: jitterbuf.h:83
long last_adjustment
Definition: jitterbuf.h:94
long last_voice_ms
Definition: jitterbuf.h:92
long next_voice_ts
Definition: jitterbuf.h:91
long jitter
Definition: jitterbuf.h:86
jb_info info
Definition: jitterbuf.h:110

References _queue_get().

◆ _queue_get()

static jb_frame* _queue_get ( jitterbuf jb,
long  ts,
int  all 
)
static

Definition at line 414 of file jitterbuf.c.

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 }
#define NULL
Definition: resample.c:96
struct jb_frame * prev
Definition: jitterbuf.h:106
struct jb_frame * next
Definition: jitterbuf.h:106
long frames_cur
Definition: jitterbuf.h:85
jb_frame * free
Definition: jitterbuf.h:121
jb_frame * frames
Definition: jitterbuf.h:120

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

Referenced by _jb_get(), and queue_get().

◆ check_resync()

static int check_resync ( jitterbuf jb,
long  ts,
long  now,
long  ms,
const enum jb_frame_type  type,
long *  delay 
)
static

Definition at line 116 of file jitterbuf.c.

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 }
static const char type[]
Definition: chan_ooh323.c:109
threshold
Definition: dsp.h:71
#define ast_debug(level,...)
Log a DEBUG message.
#define jb_warn(...)
Definition: jitterbuf.c:43
@ JB_TYPE_CONTROL
Definition: jitterbuf.h:61
long resync_threshold
Definition: jitterbuf.h:70
long resync_offset
Definition: jitterbuf.h:97
long last_delay
Definition: jitterbuf.h:95
long cnt_delay_discont
Definition: jitterbuf.h:96
int hist_maxbuf_valid
Definition: jitterbuf.h:117
int hist_ptr
Definition: jitterbuf.h:114
unsigned int dropem
Definition: jitterbuf.h:118

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, jb_frame::ts, and type.

◆ decrement_losspct()

static void decrement_losspct ( jitterbuf jb)
static

Definition at line 67 of file jitterbuf.c.

68 {
69  jb->info.losspct = (499 * jb->info.losspct)/500;
70 }
long losspct
Definition: jitterbuf.h:90

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

◆ history_calc_maxbuf()

static void history_calc_maxbuf ( jitterbuf jb)
static

Definition at line 214 of file jitterbuf.c.

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 }
#define JB_LONGMIN
Definition: jitterbuf.c:41
#define JB_LONGMAX
Definition: jitterbuf.c:40
#define JB_HISTORY_SZ
Definition: jitterbuf.h:34
#define JB_HISTORY_MAXBUF_SZ
Definition: jitterbuf.h:41
long history[JB_HISTORY_SZ]
Definition: jitterbuf.h:113
long hist_maxbuf[JB_HISTORY_MAXBUF_SZ]
Definition: jitterbuf.h:115
long hist_minbuf[JB_HISTORY_MAXBUF_SZ]
Definition: jitterbuf.h:116

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().

◆ history_get()

static void history_get ( jitterbuf jb)
static

Definition at line 295 of file jitterbuf.c.

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 }
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
#define min(a, b)
Definition: f2c.h:197
#define max(a, b)
Definition: f2c.h:198
static void history_calc_maxbuf(jitterbuf *jb)
Definition: jitterbuf.c:214
#define JB_HISTORY_DROPPCT
Definition: jitterbuf.h:37

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, max, min, and jb_info::min.

Referenced by jb_get().

◆ history_put()

static int history_put ( jitterbuf jb,
long  ts,
long  now,
long  ms,
long  delay 
)
static

Definition at line 163 of file jitterbuf.c.

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 }

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

◆ increment_losspct()

static void increment_losspct ( jitterbuf jb)
static

Definition at line 62 of file jitterbuf.c.

63 {
64  jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;
65 }

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

◆ jb_destroy()

void jb_destroy ( jitterbuf jb)

destroy jitterbuf

Definition at line 99 of file jitterbuf.c.

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 }
#define ast_free(a)
Definition: astmm.h:180
#define jb_dbg2(...)
Definition: jitterbuf.c:50

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

Referenced by AST_TEST_DEFINE(), jb_destroy_adaptive(), and pvt_destructor().

◆ jb_get()

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 767 of file jitterbuf.c.

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 }
static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
Definition: jitterbuf.c:550
jb_return_code
Definition: jitterbuf.h:49

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(), AST_TEST_DEFINE(), and jb_get_adaptive().

◆ jb_getall()

enum jb_return_code jb_getall ( jitterbuf jb,
jb_frame frameout 
)

unconditionally get frames from jitterbuf until empty

Definition at line 767 of file jitterbuf.c.

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 }
static jb_frame * queue_getall(jitterbuf *jb)
Definition: jitterbuf.c:454

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

◆ jb_getinfo()

enum jb_return_code jb_getinfo ( jitterbuf jb,
jb_info stats 
)

get jitterbuf info: only "statistics" may be valid

Definition at line 767 of file jitterbuf.c.

816 {
817 
818  history_get(jb);
819 
820  *stats = jb->info;
821 
822  return JB_OK;
823 }

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

◆ jb_is_late()

int jb_is_late ( jitterbuf jb,
long  ts 
)

Checks if the given time stamp is late.

Definition at line 846 of file jitterbuf.c.

847 {
848  return ts + jb->info.current < jb->info.next_voice_ts;
849 }

References jb_info::current, jitterbuf::info, and jb_info::next_voice_ts.

Referenced by jb_is_late_adaptive().

◆ jb_new()

jitterbuf* jb_new ( void  )

new jitterbuf

Definition at line 86 of file jitterbuf.c.

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 }
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
void jb_reset(jitterbuf *jb)
reset jitterbuf
Definition: jitterbuf.c:72

References ast_calloc, jb_dbg2, jb_reset(), and NULL.

Referenced by AST_TEST_DEFINE(), jb_create_adaptive(), and new_iax().

◆ jb_next()

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 767 of file jitterbuf.c.

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 }

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

◆ jb_put()

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 454 of file jitterbuf.c.

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 }
static int history_put(jitterbuf *jb, long ts, long now, long ms, long delay)
Definition: jitterbuf.c:163
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 int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts)
Definition: jitterbuf.c:337
@ JB_SCHED
Definition: jitterbuf.h:56
long frames_in
Definition: jitterbuf.h:79

Referenced by jb_put_adaptive(), schedule_delivery(), test_jb_late_frame_insertion(), test_jb_lost_frame_insertion(), test_jb_nominal_frame_insertion(), test_jb_out_of_order_frame_insertion(), test_jb_overflow_frame_insertion(), and test_jb_resynch_frame_insertion().

◆ jb_reset()

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 72 of file jitterbuf.c.

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 }
#define JB_TARGET_EXTRA
Definition: jitterbuf.h:43

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(), and jb_new().

◆ jb_setconf()

enum jb_return_code jb_setconf ( jitterbuf jb,
jb_conf conf 
)

set jitterbuf conf

Definition at line 767 of file jitterbuf.c.

826 {
827  /* take selected settings from the struct */
828 
829  jb->info.conf.max_jitterbuf = conf->max_jitterbuf;
830  jb->info.conf.resync_threshold = conf->resync_threshold;
831  jb->info.conf.max_contig_interp = conf->max_contig_interp;
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 }
All configuration options for statsd client.
Definition: res_statsd.c:101

Referenced by AST_TEST_DEFINE(), jb_create_adaptive(), and new_iax().

◆ jb_setoutput()

void jb_setoutput ( jb_output_function_t  err,
jb_output_function_t  warn,
jb_output_function_t  dbg 
)

Definition at line 55 of file jitterbuf.c.

56 {
57  errf = err;
58  warnf = warn;
59  dbgf = dbg;
60 }
static jb_output_function_t dbgf
Definition: jitterbuf.c:53
static jb_output_function_t errf
Definition: jitterbuf.c:53
static jb_output_function_t warnf
Definition: jitterbuf.c:53

References dbgf, errf, and warnf.

Referenced by handle_cli_iax2_set_debug_jb().

◆ queue_get()

static jb_frame* queue_get ( jitterbuf jb,
long  ts 
)
static

Definition at line 449 of file jitterbuf.c.

450 {
451  return _queue_get(jb,ts,0);
452 }
static jb_frame * _queue_get(jitterbuf *jb, long ts, int all)
Definition: jitterbuf.c:414

References _queue_get().

◆ queue_getall()

static jb_frame* queue_getall ( jitterbuf jb)
static

Definition at line 454 of file jitterbuf.c.

455 {
456  return _queue_get(jb,0,1);
457 }

◆ queue_last()

static long queue_last ( jitterbuf jb)
static

Definition at line 406 of file jitterbuf.c.

407 {
408  if (jb->frames)
409  return jb->frames->prev->ts;
410  else
411  return -1;
412 }

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

◆ queue_next()

static long queue_next ( jitterbuf jb)
static

Definition at line 398 of file jitterbuf.c.

399 {
400  if (jb->frames)
401  return jb->frames->ts;
402  else
403  return -1;
404 }

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

Referenced by jb_get().

◆ queue_put()

static int queue_put ( jitterbuf jb,
void *  data,
const enum jb_frame_type  type,
long  ms,
long  ts 
)
static

Definition at line 337 of file jitterbuf.c.

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 }
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define jb_err(...)
Definition: jitterbuf.c:44
static int frames
Definition: parser.c:51
void * data
Definition: jitterbuf.h:102
long frames_ooo
Definition: jitterbuf.h:84

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.

Variable Documentation

◆ dbgf

jb_output_function_t dbgf
static

Definition at line 53 of file jitterbuf.c.

Referenced by jb_setoutput().

◆ errf

jb_output_function_t errf
static

Definition at line 53 of file jitterbuf.c.

Referenced by jb_setoutput().

◆ warnf

jb_output_function_t warnf
static

Definition at line 53 of file jitterbuf.c.

Referenced by jb_setoutput().