Asterisk - The Open Source Telephony Project GIT-master-7921072
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 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
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 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(), sip_to_pjsip::info(), 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[]
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.

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}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
#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(), 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(), 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(), 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(), 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 815 of file jitterbuf.c.

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

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

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}

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