#include "asterisk.h"
#include "jitterbuf.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Defines | |
#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 | |
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 |
Definition in file jitterbuf.c.
#define jb_dbg2 | ( | ) | ((void)0) |
#define JB_LONGMAX 2147483647L |
define these here, just for ancient compiler systems
Definition at line 42 of file jitterbuf.c.
Referenced by history_calc_maxbuf(), and jb_next().
#define JB_LONGMIN (-JB_LONGMAX - 1L) |
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.
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().
00551 { 00552 jb_frame *frame; 00553 long diff; 00554 static int dbg_cnt = 0; 00555 00556 /* get jitter info */ 00557 history_get(jb); 00558 00559 if (dbg_cnt && dbg_cnt % 50 == 0) { 00560 jb_dbg("\n"); 00561 } 00562 dbg_cnt++; 00563 00564 /* target */ 00565 jb->info.target = jb->info.jitter + jb->info.min + jb->info.conf.target_extra; 00566 00567 /* if a hard clamp was requested, use it */ 00568 if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) { 00569 jb_dbg("clamping target from %ld to %ld\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf); 00570 jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf; 00571 } 00572 00573 diff = jb->info.target - jb->info.current; 00574 00575 /* jb_warn("diff = %d lms=%d last = %d now = %d\n", diff, */ 00576 /* jb->info.last_voice_ms, jb->info.last_adjustment, now); */ 00577 00578 /* let's work on non-silent case first */ 00579 if (!jb->info.silence_begin_ts) { 00580 /* we want to grow */ 00581 if ((diff > 0) && 00582 /* we haven't grown in the delay length */ 00583 (((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) || 00584 /* we need to grow more than the "length" we have left */ 00585 (diff > queue_last(jb) - queue_next(jb)) ) ) { 00586 /* grow by interp frame length */ 00587 jb->info.current += interpl; 00588 jb->info.next_voice_ts += interpl; 00589 jb->info.last_voice_ms = interpl; 00590 jb->info.last_adjustment = now; 00591 jb->info.cnt_contig_interp++; 00592 if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) { 00593 jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current; 00594 } 00595 jb_dbg("G"); 00596 return JB_INTERP; 00597 } 00598 00599 frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current); 00600 00601 /* not a voice frame; just return it. */ 00602 if (frame && frame->type != JB_TYPE_VOICE) { 00603 if (frame->type == JB_TYPE_SILENCE) { 00604 jb->info.silence_begin_ts = frame->ts; 00605 jb->info.cnt_contig_interp = 0; 00606 } 00607 00608 *frameout = *frame; 00609 jb->info.frames_out++; 00610 jb_dbg("o"); 00611 return JB_OK; 00612 } 00613 00614 00615 /* voice frame is later than expected */ 00616 if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) { 00617 if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) { 00618 /* either we interpolated past this frame in the last jb_get */ 00619 /* or the frame is still in order, but came a little too quick */ 00620 *frameout = *frame; 00621 /* reset expectation for next frame */ 00622 jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms; 00623 jb->info.frames_out++; 00624 decrement_losspct(jb); 00625 jb->info.cnt_contig_interp = 0; 00626 jb_dbg("v"); 00627 return JB_OK; 00628 } else { 00629 /* voice frame is late */ 00630 *frameout = *frame; 00631 jb->info.frames_out++; 00632 decrement_losspct(jb); 00633 jb->info.frames_late++; 00634 jb->info.frames_lost--; 00635 jb_dbg("l"); 00636 return JB_DROP; 00637 } 00638 } 00639 00640 /* keep track of frame sizes, to allow for variable sized-frames */ 00641 if (frame && frame->ms > 0) { 00642 jb->info.last_voice_ms = frame->ms; 00643 } 00644 00645 /* we want to shrink; shrink at 1 frame / 500ms */ 00646 /* unless we don't have a frame, then shrink 1 frame */ 00647 /* every 80ms (though perhaps we can shrink even faster */ 00648 /* in this case) */ 00649 if (diff < -jb->info.conf.target_extra && 00650 ((!frame && jb->info.last_adjustment + 80 < now) || 00651 (jb->info.last_adjustment + 500 < now))) { 00652 00653 jb->info.last_adjustment = now; 00654 jb->info.cnt_contig_interp = 0; 00655 00656 if (frame) { 00657 *frameout = *frame; 00658 /* shrink by frame size we're throwing out */ 00659 jb->info.current -= frame->ms; 00660 jb->info.frames_out++; 00661 decrement_losspct(jb); 00662 jb->info.frames_dropped++; 00663 jb_dbg("s"); 00664 return JB_DROP; 00665 } else { 00666 /* shrink by last_voice_ms */ 00667 jb->info.current -= jb->info.last_voice_ms; 00668 jb->info.frames_lost++; 00669 increment_losspct(jb); 00670 jb_dbg("S"); 00671 return JB_NOFRAME; 00672 } 00673 } 00674 00675 /* lost frame */ 00676 if (!frame) { 00677 /* this is a bit of a hack for now, but if we're close to 00678 * target, and we find a missing frame, it makes sense to 00679 * grow, because the frame might just be a bit late; 00680 * otherwise, we presently get into a pattern where we return 00681 * INTERP for the lost frame, then it shows up next, and we 00682 * throw it away because it's late */ 00683 /* I've recently only been able to replicate this using 00684 * iaxclient talking to app_echo on asterisk. In this case, 00685 * my outgoing packets go through asterisk's (old) 00686 * jitterbuffer, and then might get an unusual increasing delay 00687 * there if it decides to grow?? */ 00688 /* Update: that might have been a different bug, that has been fixed.. 00689 * But, this still seemed like a good idea, except that it ended up making a single actual 00690 * lost frame get interpolated two or more times, when there was "room" to grow, so it might 00691 * be a bit of a bad idea overall */ 00692 /*if (diff > -1 * jb->info.last_voice_ms) { 00693 jb->info.current += jb->info.last_voice_ms; 00694 jb->info.last_adjustment = now; 00695 jb_warn("g"); 00696 return JB_INTERP; 00697 } */ 00698 jb->info.frames_lost++; 00699 increment_losspct(jb); 00700 jb->info.next_voice_ts += interpl; 00701 jb->info.last_voice_ms = interpl; 00702 jb->info.cnt_contig_interp++; 00703 if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) { 00704 jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current; 00705 } 00706 jb_dbg("L"); 00707 return JB_INTERP; 00708 } 00709 00710 /* normal case; return the frame, increment stuff */ 00711 *frameout = *frame; 00712 jb->info.next_voice_ts += frame->ms; 00713 jb->info.frames_out++; 00714 jb->info.cnt_contig_interp = 0; 00715 decrement_losspct(jb); 00716 jb_dbg("v"); 00717 return JB_OK; 00718 } else { 00719 /* TODO: after we get the non-silent case down, we'll make the 00720 * silent case -- basically, we'll just grow and shrink faster 00721 * here, plus handle next_voice_ts a bit differently */ 00722 00723 /* to disable silent special case altogether, just uncomment this: */ 00724 /* jb->info.silence_begin_ts = 0; */ 00725 00726 /* shrink interpl len every 10ms during silence */ 00727 if (diff < -jb->info.conf.target_extra && 00728 jb->info.last_adjustment + 10 <= now) { 00729 jb->info.current -= interpl; 00730 jb->info.last_adjustment = now; 00731 } 00732 00733 frame = queue_get(jb, now - jb->info.current); 00734 if (!frame) { 00735 return JB_NOFRAME; 00736 } else if (frame->type != JB_TYPE_VOICE) { 00737 /* normal case; in silent mode, got a non-voice frame */ 00738 *frameout = *frame; 00739 jb->info.frames_out++; 00740 return JB_OK; 00741 } 00742 if (frame->ts < jb->info.silence_begin_ts) { 00743 /* voice frame is late */ 00744 *frameout = *frame; 00745 jb->info.frames_out++; 00746 decrement_losspct(jb); 00747 jb->info.frames_late++; 00748 jb->info.frames_lost--; 00749 jb_dbg("l"); 00750 return JB_DROP; 00751 } else { 00752 /* voice frame */ 00753 /* try setting current to target right away here */ 00754 jb->info.current = jb->info.target; 00755 jb->info.silence_begin_ts = 0; 00756 jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms; 00757 jb->info.last_voice_ms = frame->ms; 00758 jb->info.frames_out++; 00759 decrement_losspct(jb); 00760 *frameout = *frame; 00761 jb_dbg("V"); 00762 return JB_OK; 00763 } 00764 } 00765 }
Definition at line 414 of file jitterbuf.c.
References jitterbuf::frames, jb_info::frames_cur, jitterbuf::free, jitterbuf::info, jb_frame::next, jb_frame::prev, and jb_frame::ts.
Referenced by queue_get(), and queue_getall().
00415 { 00416 jb_frame *frame; 00417 frame = jb->frames; 00418 00419 if (!frame) 00420 return NULL; 00421 00422 /*jb_warn("queue_get: ASK %ld FIRST %ld\n", ts, frame->ts); */ 00423 00424 if (all || ts >= frame->ts) { 00425 /* remove this frame */ 00426 frame->prev->next = frame->next; 00427 frame->next->prev = frame->prev; 00428 00429 if (frame->next == frame) 00430 jb->frames = NULL; 00431 else 00432 jb->frames = frame->next; 00433 00434 00435 /* insert onto "free" single-linked list */ 00436 frame->next = jb->free; 00437 jb->free = frame; 00438 00439 jb->info.frames_cur--; 00440 00441 /* we return the frame pointer, even though it's on free list, 00442 * but caller must copy data */ 00443 return frame; 00444 } 00445 00446 return NULL; 00447 }
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.
References ast_debug, jb_info::cnt_delay_discont, jb_info::conf, jitterbuf::dropem, jitterbuf::frames, jb_info::frames_dropped, jitterbuf::hist_maxbuf_valid, jitterbuf::hist_ptr, jitterbuf::info, JB_TYPE_CONTROL, jb_warn, jb_info::jitter, jb_info::last_delay, jb_conf::max_jitterbuf, jb_frame::prev, jb_info::resync_offset, jb_conf::resync_threshold, and jb_frame::ts.
Referenced by jb_put().
00117 { 00118 long numts = 0; 00119 long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold; 00120 00121 /* Check for overfill of the buffer */ 00122 if (jb->frames) { 00123 numts = jb->frames->prev->ts - jb->frames->ts; 00124 } 00125 00126 if (numts >= (jb->info.conf.max_jitterbuf)) { 00127 if (!jb->dropem) { 00128 ast_debug(1, "Attempting to exceed Jitterbuf max %ld timeslots\n", 00129 jb->info.conf.max_jitterbuf); 00130 jb->dropem = 1; 00131 } 00132 jb->info.frames_dropped++; 00133 return -1; 00134 } else { 00135 jb->dropem = 0; 00136 } 00137 00138 /* check for drastic change in delay */ 00139 if (jb->info.conf.resync_threshold != -1) { 00140 if (abs(*delay - jb->info.last_delay) > threshold) { 00141 jb->info.cnt_delay_discont++; 00142 /* resync the jitterbuffer on 3 consecutive discontinuities, 00143 * or immediately if a control frame */ 00144 if ((jb->info.cnt_delay_discont > 3) || (type == JB_TYPE_CONTROL)) { 00145 jb->info.cnt_delay_discont = 0; 00146 jb->hist_ptr = 0; 00147 jb->hist_maxbuf_valid = 0; 00148 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); 00149 jb->info.resync_offset = ts - now; 00150 jb->info.last_delay = *delay = 0; /* after resync, frame is right on time */ 00151 } else { 00152 jb->info.frames_dropped++; 00153 return -1; 00154 } 00155 } else { 00156 jb->info.last_delay = *delay; 00157 jb->info.cnt_delay_discont = 0; 00158 } 00159 } 00160 return 0; 00161 }
static void decrement_losspct | ( | jitterbuf * | jb | ) | [static] |
Definition at line 69 of file jitterbuf.c.
References jitterbuf::info, and jb_info::losspct.
Referenced by _jb_get().
static void history_calc_maxbuf | ( | jitterbuf * | jb | ) | [static] |
Definition at line 214 of file jitterbuf.c.
References jitterbuf::hist_maxbuf, jitterbuf::hist_minbuf, jitterbuf::hist_ptr, jitterbuf::history, JB_HISTORY_MAXBUF_SZ, JB_HISTORY_SZ, JB_LONGMAX, and JB_LONGMIN.
Referenced by history_get().
00215 { 00216 int i,j; 00217 00218 if (jb->hist_ptr == 0) 00219 return; 00220 00221 00222 /* initialize maxbuf/minbuf to the latest value */ 00223 for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) { 00224 /* 00225 * jb->hist_maxbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ]; 00226 * jb->hist_minbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ]; 00227 */ 00228 jb->hist_maxbuf[i] = JB_LONGMIN; 00229 jb->hist_minbuf[i] = JB_LONGMAX; 00230 } 00231 00232 /* use insertion sort to populate maxbuf */ 00233 /* we want it to be the top "n" values, in order */ 00234 00235 /* start at the beginning, or JB_HISTORY_SZ frames ago */ 00236 i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0; 00237 00238 for (;i<jb->hist_ptr;i++) { 00239 long toins = jb->history[i % JB_HISTORY_SZ]; 00240 00241 /* if the maxbuf should get this */ 00242 if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) { 00243 00244 /* insertion-sort it into the maxbuf */ 00245 for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) { 00246 /* found where it fits */ 00247 if (toins > jb->hist_maxbuf[j]) { 00248 /* move over */ 00249 if (j != JB_HISTORY_MAXBUF_SZ - 1) { 00250 memmove(jb->hist_maxbuf + j + 1, jb->hist_maxbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_maxbuf[0])); 00251 } 00252 /* insert */ 00253 jb->hist_maxbuf[j] = toins; 00254 00255 break; 00256 } 00257 } 00258 } 00259 00260 /* if the minbuf should get this */ 00261 if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) { 00262 00263 /* insertion-sort it into the maxbuf */ 00264 for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) { 00265 /* found where it fits */ 00266 if (toins < jb->hist_minbuf[j]) { 00267 /* move over */ 00268 if (j != JB_HISTORY_MAXBUF_SZ - 1) { 00269 memmove(jb->hist_minbuf + j + 1, jb->hist_minbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_minbuf[0])); 00270 } 00271 /* insert */ 00272 jb->hist_minbuf[j] = toins; 00273 00274 break; 00275 } 00276 } 00277 } 00278 00279 if (0) { 00280 int k; 00281 fprintf(stderr, "toins = %ld\n", toins); 00282 fprintf(stderr, "maxbuf ="); 00283 for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++) 00284 fprintf(stderr, "%ld ", jb->hist_maxbuf[k]); 00285 fprintf(stderr, "\nminbuf ="); 00286 for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++) 00287 fprintf(stderr, "%ld ", jb->hist_minbuf[k]); 00288 fprintf(stderr, "\n"); 00289 } 00290 } 00291 00292 jb->hist_maxbuf_valid = 1; 00293 }
static void history_get | ( | jitterbuf * | jb | ) | [static] |
Definition at line 295 of file jitterbuf.c.
References jitterbuf::hist_maxbuf, jitterbuf::hist_maxbuf_valid, jitterbuf::hist_minbuf, jitterbuf::hist_ptr, history_calc_maxbuf(), jitterbuf::info, JB_HISTORY_DROPPCT, JB_HISTORY_SZ, jb_info::jitter, and jb_info::min.
Referenced by _jb_get(), jb_getinfo(), and jb_next().
00296 { 00297 long max, min, jitter; 00298 int idx; 00299 int count; 00300 00301 if (!jb->hist_maxbuf_valid) 00302 history_calc_maxbuf(jb); 00303 00304 /* count is how many items in history we're examining */ 00305 count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ; 00306 00307 /* idx is the "n"ths highest/lowest that we'll look for */ 00308 idx = count * JB_HISTORY_DROPPCT / 100; 00309 00310 /* sanity checks for idx */ 00311 if (idx > (JB_HISTORY_MAXBUF_SZ - 1)) 00312 idx = JB_HISTORY_MAXBUF_SZ - 1; 00313 00314 if (idx < 0) { 00315 jb->info.min = 0; 00316 jb->info.jitter = 0; 00317 return; 00318 } 00319 00320 max = jb->hist_maxbuf[idx]; 00321 min = jb->hist_minbuf[idx]; 00322 00323 jitter = max - min; 00324 00325 /* these debug stmts compare the difference between looking at the absolute jitter, and the 00326 * values we get by throwing away the outliers */ 00327 /* 00328 fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", index, min, max, jitter); 00329 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]); 00330 */ 00331 00332 jb->info.min = min; 00333 jb->info.jitter = jitter; 00334 }
static int history_put | ( | jitterbuf * | jb, | |
long | ts, | |||
long | now, | |||
long | ms, | |||
long | delay | |||
) | [static] |
Definition at line 163 of file jitterbuf.c.
References jitterbuf::hist_maxbuf, jitterbuf::hist_maxbuf_valid, jitterbuf::hist_ptr, jitterbuf::history, JB_HISTORY_MAXBUF_SZ, and JB_HISTORY_SZ.
Referenced by jb_put().
00164 { 00165 long kicked; 00166 00167 /* don't add special/negative times to history */ 00168 if (ts <= 0) 00169 return 0; 00170 00171 kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ]; 00172 00173 jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay; 00174 00175 /* optimization; the max/min buffers don't need to be recalculated, if this packet's 00176 * entry doesn't change them. This happens if this packet is not involved, _and_ any packet 00177 * that got kicked out of the history is also not involved 00178 * We do a number of comparisons, but it's probably still worthwhile, because it will usually 00179 * succeed, and should be a lot faster than going through all 500 packets in history */ 00180 if (!jb->hist_maxbuf_valid) 00181 return 0; 00182 00183 /* don't do this until we've filled history 00184 * (reduces some edge cases below) */ 00185 if (jb->hist_ptr < JB_HISTORY_SZ) 00186 goto invalidate; 00187 00188 /* if the new delay would go into min */ 00189 if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) 00190 goto invalidate; 00191 00192 /* or max.. */ 00193 if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) 00194 goto invalidate; 00195 00196 /* or the kicked delay would be in min */ 00197 if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) 00198 goto invalidate; 00199 00200 if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) 00201 goto invalidate; 00202 00203 /* if we got here, we don't need to invalidate, 'cause this delay didn't 00204 * affect things */ 00205 return 0; 00206 /* end optimization */ 00207 00208 00209 invalidate: 00210 jb->hist_maxbuf_valid = 0; 00211 return 0; 00212 }
static void increment_losspct | ( | jitterbuf * | jb | ) | [static] |
Definition at line 64 of file jitterbuf.c.
References jitterbuf::info, and jb_info::losspct.
Referenced by _jb_get().
void jb_destroy | ( | jitterbuf * | jb | ) |
destroy jitterbuf
Definition at line 99 of file jitterbuf.c.
References ast_free, jitterbuf::free, jb_dbg2, and jb_frame::next.
Referenced by jb_destroy_adaptive(), and pvt_destructor().
00100 { 00101 jb_frame *frame; 00102 jb_dbg2("jb_destroy(%x)\n", jb); 00103 00104 /* free all the frames on the "free list" */ 00105 frame = jb->free; 00106 while (frame != NULL) { 00107 jb_frame *next = frame->next; 00108 ast_free(frame); 00109 frame = next; 00110 } 00111 00112 /* free ourselves! */ 00113 ast_free(jb); 00114 }
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.
References _jb_get(), jitterbuf::info, JB_DROP, JB_INTERP, JB_OK, jb_warn, jb_info::last_voice_ms, jb_frame::ms, and jb_frame::ts.
Referenced by __get_from_jb(), and jb_get_adaptive().
00786 { 00787 enum jb_return_code ret = _jb_get(jb, frameout, now, interpl); 00788 #if 0 00789 static int lastts=0; 00790 int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0; 00791 jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists); 00792 if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n"); 00793 lastts = thists; 00794 #endif 00795 if (ret == JB_INTERP) 00796 frameout->ms = jb->info.last_voice_ms; 00797 00798 return ret; 00799 }
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.
References JB_NOFRAME, JB_OK, and queue_getall().
Referenced by complete_transfer(), jb_empty_and_reset_adaptive(), jb_remove_adaptive(), pvt_destructor(), and schedule_delivery().
00802 { 00803 jb_frame *frame; 00804 frame = queue_getall(jb); 00805 00806 if (!frame) { 00807 return JB_NOFRAME; 00808 } 00809 00810 *frameout = *frame; 00811 return JB_OK; 00812 }
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.
References history_get(), jitterbuf::info, and JB_OK.
Referenced by ast_cli_netstats(), construct_rr(), handle_cli_iax2_show_channels(), and log_jitterstats().
00816 { 00817 00818 history_get(jb); 00819 00820 *stats = jb->info; 00821 00822 return JB_OK; 00823 }
jitterbuf* jb_new | ( | void | ) |
new jitterbuf
Definition at line 86 of file jitterbuf.c.
References ast_malloc, jb_dbg2, and jb_reset().
Referenced by jb_create_adaptive(), and new_iax().
00087 { 00088 jitterbuf *jb; 00089 00090 if (!(jb = ast_malloc(sizeof(*jb)))) 00091 return NULL; 00092 00093 jb_reset(jb); 00094 00095 jb_dbg2("jb_new() = %x\n", jb); 00096 return jb; 00097 }
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.
References jb_info::conf, jb_info::current, jitterbuf::frames, history_get(), jitterbuf::info, JB_LONGMAX, jb_info::last_adjustment, jb_info::next_voice_ts, queue_next(), jb_info::silence_begin_ts, jb_info::target, and jb_conf::target_extra.
Referenced by __get_from_jb(), jb_next_adaptive(), and update_jbsched().
00768 { 00769 if (jb->info.silence_begin_ts) { 00770 if (jb->frames) { 00771 long next = queue_next(jb); 00772 history_get(jb); 00773 /* shrink during silence */ 00774 if (jb->info.target - jb->info.current < -jb->info.conf.target_extra) 00775 return jb->info.last_adjustment + 10; 00776 return next + jb->info.target; 00777 } 00778 else 00779 return JB_LONGMAX; 00780 } else { 00781 return jb->info.next_voice_ts; 00782 } 00783 }
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.
References check_resync(), jb_info::frames_in, history_put(), jitterbuf::info, jb_dbg2, JB_DROP, JB_OK, JB_SCHED, JB_TYPE_VOICE, queue_put(), and jb_info::resync_offset.
Referenced by jb_put_adaptive(), and schedule_delivery().
00526 { 00527 long delay = now - (ts - jb->info.resync_offset); 00528 jb_dbg2("jb_put(%x,%x,%ld,%ld,%ld)\n", jb, data, ms, ts, now); 00529 00530 if (check_resync(jb, ts, now, ms, type, &delay)) { 00531 return JB_DROP; 00532 } 00533 00534 if (type == JB_TYPE_VOICE) { 00535 /* presently, I'm only adding VOICE frames to history and drift calculations; mostly because with the 00536 * IAX integrations, I'm sending retransmitted control frames with their awkward timestamps through */ 00537 history_put(jb, ts, now, ms, delay); 00538 } 00539 00540 jb->info.frames_in++; 00541 00542 /* if put into head of queue, caller needs to reschedule */ 00543 if (queue_put(jb,data,type,ms,ts)) { 00544 return JB_SCHED; 00545 } 00546 return JB_OK; 00547 }
void jb_reset | ( | jitterbuf * | jb | ) |
reset jitterbuf
Definition at line 74 of file jitterbuf.c.
References jb_info::conf, jitterbuf::info, JB_TARGET_EXTRA, and jb_conf::target_extra.
Referenced by complete_transfer(), jb_empty_and_reset_adaptive(), jb_new(), and schedule_delivery().
00075 { 00076 /* only save settings */ 00077 jb_conf s = jb->info.conf; 00078 memset(jb, 0, sizeof(*jb)); 00079 jb->info.conf = s; 00080 00081 /* initialize length, using the default value */ 00082 jb->info.current = jb->info.target = jb->info.conf.target_extra = JB_TARGET_EXTRA; 00083 jb->info.silence_begin_ts = -1; 00084 }
enum jb_return_code jb_setconf | ( | jitterbuf * | jb, | |
jb_conf * | conf | |||
) |
set jitterbuf conf
Definition at line 825 of file jitterbuf.c.
References jb_info::conf, jb_info::current, jitterbuf::info, JB_OK, JB_TARGET_EXTRA, jb_conf::max_contig_interp, jb_conf::max_jitterbuf, jb_conf::resync_threshold, jb_info::target, and jb_conf::target_extra.
Referenced by jb_create_adaptive(), and new_iax().
00826 { 00827 /* take selected settings from the struct */ 00828 00829 jb->info.conf.max_jitterbuf = conf->max_jitterbuf; 00830 jb->info.conf.resync_threshold = conf->resync_threshold; 00831 jb->info.conf.max_contig_interp = conf->max_contig_interp; 00832 00833 /* -1 indicates use of the default JB_TARGET_EXTRA value */ 00834 jb->info.conf.target_extra = ( conf->target_extra == -1 ) 00835 ? JB_TARGET_EXTRA 00836 : conf->target_extra 00837 ; 00838 00839 /* update these to match new target_extra setting */ 00840 jb->info.current = jb->info.conf.target_extra; 00841 jb->info.target = jb->info.conf.target_extra; 00842 00843 return JB_OK; 00844 }
void jb_setoutput | ( | jb_output_function_t | err, | |
jb_output_function_t | warn, | |||
jb_output_function_t | dbg | |||
) |
Definition at line 57 of file jitterbuf.c.
Referenced by handle_cli_iax2_set_debug_jb(), and load_module().
Definition at line 449 of file jitterbuf.c.
References _queue_get().
Referenced by _jb_get().
00450 { 00451 return _queue_get(jb,ts,0); 00452 }
Definition at line 454 of file jitterbuf.c.
References _queue_get().
Referenced by jb_getall().
00455 { 00456 return _queue_get(jb,0,1); 00457 }
static long queue_last | ( | jitterbuf * | jb | ) | [static] |
Definition at line 406 of file jitterbuf.c.
References jitterbuf::frames, jb_frame::prev, and jb_frame::ts.
Referenced by _jb_get().
00407 { 00408 if (jb->frames) 00409 return jb->frames->prev->ts; 00410 else 00411 return -1; 00412 }
static long queue_next | ( | jitterbuf * | jb | ) | [static] |
Definition at line 398 of file jitterbuf.c.
References jitterbuf::frames, and jb_frame::ts.
Referenced by _jb_get(), and jb_next().
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.
References ast_malloc, frames, jitterbuf::frames, jb_info::frames_cur, jb_info::frames_ooo, jitterbuf::free, jitterbuf::info, jb_err, jb_frame::next, jb_frame::prev, and jb_info::resync_offset.
Referenced by jb_put().
00338 { 00339 jb_frame *frame; 00340 jb_frame *p; 00341 int head = 0; 00342 long resync_ts = ts - jb->info.resync_offset; 00343 00344 if ((frame = jb->free)) { 00345 jb->free = frame->next; 00346 } else if (!(frame = ast_malloc(sizeof(*frame)))) { 00347 jb_err("cannot allocate frame\n"); 00348 return 0; 00349 } 00350 00351 jb->info.frames_cur++; 00352 00353 frame->data = data; 00354 frame->ts = resync_ts; 00355 frame->ms = ms; 00356 frame->type = type; 00357 00358 /* 00359 * frames are a circular list, jb-frames points to to the lowest ts, 00360 * jb->frames->prev points to the highest ts 00361 */ 00362 00363 if (!jb->frames) { /* queue is empty */ 00364 jb->frames = frame; 00365 frame->next = frame; 00366 frame->prev = frame; 00367 head = 1; 00368 } else if (resync_ts < jb->frames->ts) { 00369 frame->next = jb->frames; 00370 frame->prev = jb->frames->prev; 00371 00372 frame->next->prev = frame; 00373 frame->prev->next = frame; 00374 00375 /* frame is out of order */ 00376 jb->info.frames_ooo++; 00377 00378 jb->frames = frame; 00379 head = 1; 00380 } else { 00381 p = jb->frames; 00382 00383 /* frame is out of order */ 00384 if (resync_ts < p->prev->ts) jb->info.frames_ooo++; 00385 00386 while (resync_ts < p->prev->ts && p->prev != jb->frames) 00387 p = p->prev; 00388 00389 frame->next = p; 00390 frame->prev = p->prev; 00391 00392 frame->next->prev = frame; 00393 frame->prev->next = frame; 00394 } 00395 return head; 00396 }
jb_output_function_t dbgf [static] |
Definition at line 55 of file jitterbuf.c.
jb_output_function_t errf [static] |
Definition at line 55 of file jitterbuf.c.
jb_output_function_t warnf [static] |
Definition at line 55 of file jitterbuf.c.