Asterisk - The Open Source Telephony Project GIT-master-57e2743
Loading...
Searching...
No Matches
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
 
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.
 
enum jb_return_code jb_getall (jitterbuf *jb, jb_frame *frameout)
 unconditionally get frames from jitterbuf until empty
 
enum jb_return_code jb_getinfo (jitterbuf *jb, jb_info *stats)
 get jitterbuf info: only "statistics" may be valid
 
int jb_is_late (jitterbuf *jb, long ts)
 Checks if the given time stamp is late.
 
jitterbuf * jb_new ()
 new jitterbuf
 
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)
 
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
 
void jb_reset (jitterbuf *jb)
 reset jitterbuf
 
enum jb_return_code jb_setconf (jitterbuf *jb, jb_conf *conf)
 set jitterbuf conf
 
void jb_setoutput (jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg)
 
static jb_frame * queue_get (jitterbuf *jb, long ts)
 
static jb_frame * queue_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 550 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;
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++;
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++;
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++;
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++;
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++;
700 jb->info.next_voice_ts += interpl;
701 jb->info.last_voice_ms = interpl;
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;
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++;
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++;
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 jb_frame * queue_get(jitterbuf *jb, long ts)
Definition jitterbuf.c:449
static void decrement_losspct(jitterbuf *jb)
Definition jitterbuf.c:67
#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
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 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().

◆ _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 queue_get(), and queue_getall().

◆ 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",
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) {
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[]
threshold
Definition dsp.h:73
#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.

Referenced by jb_put().

◆ 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.

Referenced by _jb_get().

◆ 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}
#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(), 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(), jb_getinfo(), and jb_next().

◆ 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
209invalidate:
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.

Referenced by jb_put().

◆ 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.

Referenced by _jb_get().

◆ 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(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), 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 785 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_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(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), 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 801 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

References JB_NOFRAME, JB_OK, and queue_getall().

Referenced by AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), 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 
)

◆ 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(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), 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}

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(), 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 525 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

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

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 825 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 */
841 jb->info.target = jb->info.conf.target_extra;
842
843 return JB_OK;
844}
All configuration options for http media cache.

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

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

Referenced by _jb_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}

References _queue_get().

Referenced by jb_getall().

◆ 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.

Referenced by _jb_get().

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

◆ 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.

Referenced by jb_put().

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