Fri May 26 01:49:10 2006

Asterisk developer's documentation


jitterbuf.c File Reference

jitterbuf: an application-independent jitterbuffer More...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asterisk.h"
#include "jitterbuf.h"

Include dependency graph for jitterbuf.c:

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 int _jb_get (jitterbuf *jb, jb_frame *frameout, long now, long interpl)
static jb_frame_queue_get (jitterbuf *jb, long ts, int all)
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)
 simple history manipulation
static void increment_losspct (jitterbuf *jb)
void jb_destroy (jitterbuf *jb)
int jb_get (jitterbuf *jb, jb_frame *frameout, long now, long interpl)
int jb_getall (jitterbuf *jb, jb_frame *frameout)
int jb_getinfo (jitterbuf *jb, jb_info *stats)
jitterbufjb_new ()
long jb_next (jitterbuf *jb)
int jb_put (jitterbuf *jb, void *data, int type, long ms, long ts, long now)
void jb_reset (jitterbuf *jb)
int jb_setconf (jitterbuf *jb, jb_conf *conf)
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, int 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 <stevek@stevek.com>

Definition in file jitterbuf.c.


Define Documentation

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

Definition at line 45 of file jitterbuf.c.

Referenced by _jb_get().

 
#define jb_dbg2  )     ((void)0)
 

Definition at line 50 of file jitterbuf.c.

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

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

Definition at line 44 of file jitterbuf.c.

Referenced by queue_put().

#define JB_LONGMAX   2147483647L
 

define these here, just for ancient compiler systems

Definition at line 40 of file jitterbuf.c.

Referenced by history_calc_maxbuf(), and jb_next().

#define JB_LONGMIN   (-JB_LONGMAX - 1L)
 

Definition at line 41 of file jitterbuf.c.

Referenced by history_calc_maxbuf().

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

Definition at line 43 of file jitterbuf.c.

Referenced by history_put(), and jb_get().


Function Documentation

static int _jb_get jitterbuf jb,
jb_frame frameout,
long  now,
long  interpl
[static]
 

Definition at line 538 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_TARGET_EXTRA, 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_frame::ts, and jb_frame::type.

Referenced by jb_get().

00539 {
00540    jb_frame *frame;
00541    long diff;
00542    static int dbg_cnt = 0;
00543 
00544    /*if ((now - jb_next(jb)) > 2 * jb->info.last_voice_ms) jb_warn("SCHED: %ld", (now - jb_next(jb))); */
00545    /* get jitter info */
00546    history_get(jb);
00547 
00548    if (dbg_cnt && dbg_cnt % 50 == 0) {
00549       jb_dbg("\n");
00550    }
00551    dbg_cnt++;
00552 
00553    /* target */
00554    jb->info.target = jb->info.jitter + jb->info.min + JB_TARGET_EXTRA; 
00555 
00556    /* if a hard clamp was requested, use it */
00557    if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) {
00558       jb_dbg("clamping target from %d to %d\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf);
00559       jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf;
00560    }
00561 
00562    diff = jb->info.target - jb->info.current;
00563 
00564    /* jb_warn("diff = %d lms=%d last = %d now = %d\n", diff,  */
00565    /* jb->info.last_voice_ms, jb->info.last_adjustment, now); */
00566 
00567    /* let's work on non-silent case first */
00568    if (!jb->info.silence_begin_ts) { 
00569       /* we want to grow */
00570       if ((diff > 0) && 
00571          /* we haven't grown in the delay length */
00572          (((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) || 
00573          /* we need to grow more than the "length" we have left */
00574          (diff > queue_last(jb)  - queue_next(jb)) ) ) {
00575          /* grow by interp frame length */
00576          jb->info.current += interpl;
00577          jb->info.next_voice_ts += interpl;
00578          jb->info.last_voice_ms = interpl;
00579          jb->info.last_adjustment = now;
00580          jb->info.cnt_contig_interp++;
00581          if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
00582             jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
00583          }
00584          jb_dbg("G");
00585          return JB_INTERP;
00586       }
00587 
00588       frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current);
00589 
00590       /* not a voice frame; just return it. */
00591       if (frame && frame->type != JB_TYPE_VOICE) {
00592          if (frame->type == JB_TYPE_SILENCE) {
00593             jb->info.silence_begin_ts = frame->ts;
00594             jb->info.cnt_contig_interp = 0;
00595          }
00596 
00597          *frameout = *frame;
00598          jb->info.frames_out++;
00599          jb_dbg("o");
00600          return JB_OK;
00601       }
00602 
00603 
00604       /* voice frame is later than expected */
00605       if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) {
00606          if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) {
00607             /* either we interpolated past this frame in the last jb_get */
00608             /* or the frame is still in order, but came a little too quick */ 
00609             *frameout = *frame;
00610             /* reset expectation for next frame */
00611             jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
00612             jb->info.frames_out++;
00613             decrement_losspct(jb);
00614             jb->info.cnt_contig_interp = 0;
00615             jb_dbg("v");
00616             return JB_OK;
00617          } else {
00618             /* voice frame is late */
00619             *frameout = *frame;
00620             jb->info.frames_out++;
00621             decrement_losspct(jb);
00622             jb->info.frames_late++;
00623             jb->info.frames_lost--;
00624             jb_dbg("l");
00625             /*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb));
00626             jb_warninfo(jb); */
00627             return JB_DROP;
00628          }
00629       }
00630 
00631       /* keep track of frame sizes, to allow for variable sized-frames */
00632       if (frame && frame->ms > 0) {
00633          jb->info.last_voice_ms = frame->ms;
00634       }
00635 
00636       /* we want to shrink; shrink at 1 frame / 500ms */
00637       /* unless we don't have a frame, then shrink 1 frame */
00638       /* every 80ms (though perhaps we can shrink even faster */
00639       /* in this case) */
00640       if (diff < -JB_TARGET_EXTRA && 
00641          ((!frame && jb->info.last_adjustment + 80 < now) || 
00642          (jb->info.last_adjustment + 500 < now))) {
00643 
00644          jb->info.last_adjustment = now;
00645          jb->info.cnt_contig_interp = 0;
00646 
00647          if (frame) {
00648             *frameout = *frame;
00649             /* shrink by frame size we're throwing out */
00650             jb->info.current -= frame->ms;
00651             jb->info.frames_out++;
00652             decrement_losspct(jb);
00653             jb->info.frames_dropped++;
00654             jb_dbg("s");
00655             return JB_DROP;
00656          } else {
00657             /* shrink by last_voice_ms */
00658             jb->info.current -= jb->info.last_voice_ms;
00659             jb->info.frames_lost++;
00660             increment_losspct(jb);
00661             jb_dbg("S");
00662             return JB_NOFRAME;
00663          }
00664       }
00665 
00666       /* lost frame */
00667       if (!frame) {
00668          /* this is a bit of a hack for now, but if we're close to
00669           * target, and we find a missing frame, it makes sense to
00670           * grow, because the frame might just be a bit late;
00671           * otherwise, we presently get into a pattern where we return
00672           * INTERP for the lost frame, then it shows up next, and we
00673           * throw it away because it's late */
00674          /* I've recently only been able to replicate this using
00675           * iaxclient talking to app_echo on asterisk.  In this case,
00676           * my outgoing packets go through asterisk's (old)
00677           * jitterbuffer, and then might get an unusual increasing delay 
00678           * there if it decides to grow?? */
00679          /* Update: that might have been a different bug, that has been fixed..
00680           * But, this still seemed like a good idea, except that it ended up making a single actual
00681           * lost frame get interpolated two or more times, when there was "room" to grow, so it might
00682           * be a bit of a bad idea overall */
00683          /*if (diff > -1 * jb->info.last_voice_ms) { 
00684             jb->info.current += jb->info.last_voice_ms;
00685             jb->info.last_adjustment = now;
00686             jb_warn("g");
00687             return JB_INTERP;
00688          } */
00689          jb->info.frames_lost++;
00690          increment_losspct(jb);
00691          jb->info.next_voice_ts += interpl;
00692          jb->info.last_voice_ms = interpl;
00693          jb->info.cnt_contig_interp++;
00694          if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
00695             jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
00696          }
00697          jb_dbg("L");
00698          return JB_INTERP;
00699       }
00700 
00701       /* normal case; return the frame, increment stuff */
00702       *frameout = *frame;
00703       jb->info.next_voice_ts += frame->ms;
00704       jb->info.frames_out++;
00705       jb->info.cnt_contig_interp = 0;
00706       decrement_losspct(jb);
00707       jb_dbg("v");
00708       return JB_OK;
00709    } else {     
00710       /* TODO: after we get the non-silent case down, we'll make the
00711        * silent case -- basically, we'll just grow and shrink faster
00712        * here, plus handle next_voice_ts a bit differently */
00713       
00714       /* to disable silent special case altogether, just uncomment this: */
00715       /* jb->info.silence_begin_ts = 0; */
00716 
00717       /* shrink interpl len every 10ms during silence */
00718       if (diff < -JB_TARGET_EXTRA &&
00719          jb->info.last_adjustment + 10 <= now) {
00720          jb->info.current -= interpl;
00721          jb->info.last_adjustment = now;
00722       }
00723 
00724       frame = queue_get(jb, now - jb->info.current);
00725       if (!frame) {
00726          return JB_NOFRAME;
00727       } else if (frame->type != JB_TYPE_VOICE) {
00728          /* normal case; in silent mode, got a non-voice frame */
00729          *frameout = *frame;
00730          jb->info.frames_out++;
00731          return JB_OK;
00732       }
00733       if (frame->ts < jb->info.silence_begin_ts) {
00734          /* voice frame is late */
00735          *frameout = *frame;
00736          jb->info.frames_out++;
00737          decrement_losspct(jb);
00738          jb->info.frames_late++;
00739          jb->info.frames_lost--;
00740          jb_dbg("l");
00741          /*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb));
00742          jb_warninfo(jb); */
00743          return JB_DROP;
00744       } else {
00745          /* voice frame */
00746          /* try setting current to target right away here */
00747          jb->info.current = jb->info.target;
00748          jb->info.silence_begin_ts = 0;
00749          jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
00750          jb->info.last_voice_ms = frame->ms;
00751          jb->info.frames_out++;
00752          decrement_losspct(jb);
00753          *frameout = *frame;
00754          jb_dbg("V");
00755          return JB_OK;
00756       }
00757    }
00758 }

static jb_frame* _queue_get jitterbuf jb,
long  ts,
int  all
[static]
 

Definition at line 406 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().

00407 {
00408    jb_frame *frame;
00409    frame = jb->frames;
00410 
00411    if (!frame)
00412       return NULL;
00413 
00414    /*jb_warn("queue_get: ASK %ld FIRST %ld\n", ts, frame->ts); */
00415 
00416    if (all || ts >= frame->ts) {
00417       /* remove this frame */
00418       frame->prev->next = frame->next;
00419       frame->next->prev = frame->prev;
00420 
00421       if (frame->next == frame)
00422          jb->frames = NULL;
00423       else
00424          jb->frames = frame->next;
00425 
00426 
00427       /* insert onto "free" single-linked list */
00428       frame->next = jb->free;
00429       jb->free = frame;
00430 
00431       jb->info.frames_cur--;
00432 
00433       /* we return the frame pointer, even though it's on free list, 
00434        * but caller must copy data */
00435       return frame;
00436    } 
00437 
00438    return NULL;
00439 }

static void decrement_losspct jitterbuf jb  )  [static]
 

Definition at line 67 of file jitterbuf.c.

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

Referenced by _jb_get().

00068 {
00069    jb->info.losspct = (499 * jb->info.losspct)/500;    
00070 }

static void history_calc_maxbuf jitterbuf jb  )  [static]
 

Definition at line 204 of file jitterbuf.c.

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

Referenced by history_get().

00205 {
00206    int i,j;
00207 
00208    if (jb->hist_ptr == 0) 
00209       return;
00210 
00211 
00212    /* initialize maxbuf/minbuf to the latest value */
00213    for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) {
00214 /*
00215  * jb->hist_maxbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
00216  * jb->hist_minbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
00217  */
00218       jb->hist_maxbuf[i] = JB_LONGMIN;
00219       jb->hist_minbuf[i] = JB_LONGMAX;
00220    }
00221 
00222    /* use insertion sort to populate maxbuf */
00223    /* we want it to be the top "n" values, in order */
00224 
00225    /* start at the beginning, or JB_HISTORY_SZ frames ago */
00226    i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0; 
00227 
00228    for (;i<jb->hist_ptr;i++) {
00229       long toins = jb->history[i % JB_HISTORY_SZ];
00230 
00231       /* if the maxbuf should get this */
00232       if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])  {
00233 
00234          /* insertion-sort it into the maxbuf */
00235          for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
00236             /* found where it fits */
00237             if (toins > jb->hist_maxbuf[j]) {
00238                /* move over */
00239                memmove(jb->hist_maxbuf+j+1,jb->hist_maxbuf+j, (JB_HISTORY_MAXBUF_SZ-(j+1)) * sizeof(long));
00240                /* insert */
00241                jb->hist_maxbuf[j] = toins;
00242 
00243                break;
00244             }
00245          }
00246       }
00247 
00248       /* if the minbuf should get this */
00249       if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])  {
00250 
00251          /* insertion-sort it into the maxbuf */
00252          for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
00253             /* found where it fits */
00254             if (toins < jb->hist_minbuf[j]) {
00255                /* move over */
00256                memmove(jb->hist_minbuf+j+1,jb->hist_minbuf+j, (JB_HISTORY_MAXBUF_SZ-(j+1)) * sizeof(long));
00257                /* insert */
00258                jb->hist_minbuf[j] = toins;
00259 
00260                break;
00261             }
00262          }
00263       }
00264 
00265       if (0) { 
00266          int k;
00267          fprintf(stderr, "toins = %ld\n", toins);
00268          fprintf(stderr, "maxbuf =");
00269          for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++) 
00270             fprintf(stderr, "%ld ", jb->hist_maxbuf[k]);
00271          fprintf(stderr, "\nminbuf =");
00272          for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++) 
00273             fprintf(stderr, "%ld ", jb->hist_minbuf[k]);
00274          fprintf(stderr, "\n");
00275       }
00276    }
00277 
00278    jb->hist_maxbuf_valid = 1;
00279 }

static void history_get jitterbuf jb  )  [static]
 

Definition at line 281 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().

00282 {
00283    long max, min, jitter;
00284    int index;
00285    int count;
00286 
00287    if (!jb->hist_maxbuf_valid) 
00288       history_calc_maxbuf(jb);
00289 
00290    /* count is how many items in history we're examining */
00291    count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ;
00292 
00293    /* index is the "n"ths highest/lowest that we'll look for */
00294    index = count * JB_HISTORY_DROPPCT / 100;
00295 
00296    /* sanity checks for index */
00297    if (index > (JB_HISTORY_MAXBUF_SZ - 1)) 
00298       index = JB_HISTORY_MAXBUF_SZ - 1;
00299 
00300 
00301    if (index < 0) {
00302       jb->info.min = 0;
00303       jb->info.jitter = 0;
00304       return;
00305    }
00306 
00307    max = jb->hist_maxbuf[index];
00308    min = jb->hist_minbuf[index];
00309 
00310    jitter = max - min;
00311 
00312    /* these debug stmts compare the difference between looking at the absolute jitter, and the
00313     * values we get by throwing away the outliers */
00314    /*
00315    fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", index, min, max, jitter);
00316    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]);
00317    */
00318 
00319    jb->info.min = min;
00320    jb->info.jitter = jitter;
00321 }

static int history_put jitterbuf jb,
long  ts,
long  now,
long  ms
[static]
 

simple history manipulation

Note:
maybe later we can make the history buckets variable size, or something?

Definition at line 129 of file jitterbuf.c.

References jb_info::cnt_delay_discont, jb_info::conf, jitterbuf::hist_maxbuf, jitterbuf::hist_maxbuf_valid, jitterbuf::hist_ptr, jitterbuf::history, jitterbuf::info, JB_HISTORY_MAXBUF_SZ, JB_HISTORY_SZ, jb_warn, jb_info::jitter, jb_info::last_delay, jb_info::resync_offset, and jb_conf::resync_threshold.

Referenced by jb_put().

00130 {
00131    long delay = now - (ts - jb->info.resync_offset);
00132    long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold;
00133    long kicked;
00134 
00135    /* don't add special/negative times to history */
00136    if (ts <= 0) 
00137       return 0;
00138 
00139    /* check for drastic change in delay */
00140    if (jb->info.conf.resync_threshold != -1) {
00141       if (abs(delay - jb->info.last_delay) > threshold) {
00142          jb->info.cnt_delay_discont++;
00143          if (jb->info.cnt_delay_discont > 3) {
00144             /* resync the jitterbuffer */
00145             jb->info.cnt_delay_discont = 0;
00146             jb->hist_ptr = 0;
00147             jb->hist_maxbuf_valid = 0;
00148 
00149             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);
00150             jb->info.resync_offset = ts - now;
00151             jb->info.last_delay = delay = 0; /* after resync, frame is right on time */
00152          } else {
00153             return -1;
00154          }
00155       } else {
00156          jb->info.last_delay = delay;
00157          jb->info.cnt_delay_discont = 0;
00158       }
00159    }
00160 
00161    kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ];
00162 
00163    jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay;
00164 
00165    /* optimization; the max/min buffers don't need to be recalculated, if this packet's
00166     * entry doesn't change them.  This happens if this packet is not involved, _and_ any packet
00167     * that got kicked out of the history is also not involved 
00168     * We do a number of comparisons, but it's probably still worthwhile, because it will usually
00169     * succeed, and should be a lot faster than going through all 500 packets in history */
00170    if (!jb->hist_maxbuf_valid)
00171       return 0;
00172 
00173    /* don't do this until we've filled history 
00174     * (reduces some edge cases below) */
00175    if (jb->hist_ptr < JB_HISTORY_SZ)
00176       goto invalidate;
00177 
00178    /* if the new delay would go into min */
00179    if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
00180       goto invalidate;
00181     
00182    /* or max.. */
00183    if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
00184       goto invalidate;
00185 
00186    /* or the kicked delay would be in min */
00187    if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) 
00188       goto invalidate;
00189 
00190    if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) 
00191       goto invalidate;
00192 
00193    /* if we got here, we don't need to invalidate, 'cause this delay didn't 
00194     * affect things */
00195    return 0;
00196    /* end optimization */
00197 
00198 
00199 invalidate:
00200    jb->hist_maxbuf_valid = 0;
00201    return 0;
00202 }

static void increment_losspct jitterbuf jb  )  [static]
 

Definition at line 62 of file jitterbuf.c.

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

Referenced by _jb_get().

00063 {
00064    jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;    
00065 }

void jb_destroy jitterbuf jb  ) 
 

Definition at line 99 of file jitterbuf.c.

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

Referenced by iax2_destroy().

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       free(frame);
00109       frame = next;
00110    }
00111 
00112    /* free ourselves! */ 
00113    free(jb);
00114 }

int jb_get jitterbuf jb,
jb_frame frameout,
long  now,
long  interpl
 

Definition at line 778 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().

00779 {
00780    int ret = _jb_get(jb,frameout,now,interpl);
00781 #if 0
00782    static int lastts=0;
00783    int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0;
00784    jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists);
00785    if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n");
00786    lastts = thists;
00787 #endif
00788    if(ret == JB_INTERP) 
00789       frameout->ms = jb->info.last_voice_ms;
00790    
00791    return ret;
00792 }

int jb_getall jitterbuf jb,
jb_frame frameout
 

Definition at line 794 of file jitterbuf.c.

References JB_NOFRAME, JB_OK, and queue_getall().

Referenced by complete_transfer(), and iax2_destroy().

00795 {
00796    jb_frame *frame;
00797    frame = queue_getall(jb);
00798 
00799    if (!frame) {
00800       return JB_NOFRAME;
00801    }
00802 
00803    *frameout = *frame;
00804    return JB_OK;
00805 }

int jb_getinfo jitterbuf jb,
jb_info stats
 

Definition at line 808 of file jitterbuf.c.

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

Referenced by construct_rr(), and iax2_show_channels().

00809 {
00810 
00811    history_get(jb);
00812 
00813    *stats = jb->info;
00814 
00815    return JB_OK;
00816 }

jitterbuf* jb_new void   ) 
 

Definition at line 84 of file jitterbuf.c.

References jb_dbg2, jb_reset(), and malloc.

Referenced by new_iax().

00085 {
00086    jitterbuf *jb;
00087 
00088 
00089    jb = malloc(sizeof(jitterbuf));
00090    if (!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  ) 
 

Definition at line 760 of file jitterbuf.c.

References jb_info::current, history_get(), jitterbuf::info, JB_LONGMAX, JB_TARGET_EXTRA, jb_info::last_adjustment, jb_info::next_voice_ts, queue_next(), jb_info::silence_begin_ts, and jb_info::target.

Referenced by get_from_jb(), and update_jbsched().

00761 {
00762    if (jb->info.silence_begin_ts) {
00763       long next = queue_next(jb);
00764       if (next > 0) { 
00765          history_get(jb);
00766          /* shrink during silence */
00767          if (jb->info.target - jb->info.current < -JB_TARGET_EXTRA)
00768             return jb->info.last_adjustment + 10;
00769          return next + jb->info.target;
00770       }
00771       else 
00772          return JB_LONGMAX;
00773    } else {
00774       return jb->info.next_voice_ts;
00775    }
00776 }

int jb_put jitterbuf jb,
void *  data,
int  type,
long  ms,
long  ts,
long  now
 

Definition at line 517 of file jitterbuf.c.

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

00518 {
00519    jb_dbg2("jb_put(%x,%x,%ld,%ld,%ld)\n", jb, data, ms, ts, now);
00520 
00521    jb->info.frames_in++;
00522 
00523    if (type == JB_TYPE_VOICE) {
00524       /* presently, I'm only adding VOICE frames to history and drift calculations; mostly because with the
00525        * IAX integrations, I'm sending retransmitted control frames with their awkward timestamps through */
00526       if (history_put(jb,ts,now,ms))
00527          return JB_DROP;
00528    }
00529 
00530    /* if put into head of queue, caller needs to reschedule */
00531    if (queue_put(jb,data,type,ms,ts)) {
00532       return JB_SCHED;
00533    }
00534    return JB_OK;
00535 }

void jb_reset jitterbuf jb  ) 
 

Definition at line 72 of file jitterbuf.c.

References jb_info::conf, jb_info::current, jitterbuf::info, JB_TARGET_EXTRA, s, jb_info::silence_begin_ts, and jb_info::target.

Referenced by complete_transfer(), and jb_new().

00073 {
00074    /* only save settings */
00075    jb_conf s = jb->info.conf;
00076    memset(jb,0,sizeof(jitterbuf));
00077    jb->info.conf = s;
00078 
00079    /* initialize length */
00080    jb->info.current = jb->info.target = JB_TARGET_EXTRA; 
00081    jb->info.silence_begin_ts = -1; 
00082 }

int jb_setconf jitterbuf jb,
jb_conf conf
 

Definition at line 818 of file jitterbuf.c.

References jb_info::conf, jitterbuf::info, JB_OK, jb_conf::max_contig_interp, jb_conf::max_jitterbuf, and jb_conf::resync_threshold.

Referenced by new_iax().

00819 {
00820    /* take selected settings from the struct */
00821 
00822    jb->info.conf.max_jitterbuf = conf->max_jitterbuf;
00823    jb->info.conf.resync_threshold = conf->resync_threshold;
00824    jb->info.conf.max_contig_interp = conf->max_contig_interp;
00825 
00826    return JB_OK;
00827 }

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.

Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().

00056 {
00057    errf = err;
00058    warnf = warn;
00059    dbgf = dbg;
00060 }

static jb_frame* queue_get jitterbuf jb,
long  ts
[static]
 

Definition at line 441 of file jitterbuf.c.

References _queue_get().

Referenced by _jb_get().

00442 {
00443    return _queue_get(jb,ts,0);
00444 }

static jb_frame* queue_getall jitterbuf jb  )  [static]
 

Definition at line 446 of file jitterbuf.c.

References _queue_get().

Referenced by jb_getall().

00447 {
00448    return _queue_get(jb,0,1);
00449 }

static long queue_last jitterbuf jb  )  [static]
 

Definition at line 398 of file jitterbuf.c.

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

Referenced by _jb_get().

00399 {
00400    if (jb->frames) 
00401       return jb->frames->prev->ts;
00402    else 
00403       return -1;
00404 }

static long queue_next jitterbuf jb  )  [static]
 

Definition at line 390 of file jitterbuf.c.

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

Referenced by _jb_get(), and jb_next().

00391 {
00392    if (jb->frames) 
00393       return jb->frames->ts;
00394    else 
00395       return -1;
00396 }

static int queue_put jitterbuf jb,
void *  data,
int  type,
long  ms,
long  ts
[static]
 

Definition at line 324 of file jitterbuf.c.

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

Referenced by jb_put().

00325 {
00326    jb_frame *frame;
00327    jb_frame *p;
00328    int head = 0;
00329    long resync_ts = ts - jb->info.resync_offset;
00330 
00331    frame = jb->free;
00332    if (frame) {
00333       jb->free = frame->next;
00334    } else {
00335       frame = malloc(sizeof(jb_frame));
00336    }
00337 
00338    if (!frame) {
00339       jb_err("cannot allocate frame\n");
00340       return 0;
00341    }
00342 
00343    jb->info.frames_cur++;
00344 
00345    frame->data = data;
00346    frame->ts = resync_ts;
00347    frame->ms = ms;
00348    frame->type = type;
00349 
00350    /* 
00351     * frames are a circular list, jb-frames points to to the lowest ts, 
00352     * jb->frames->prev points to the highest ts
00353     */
00354 
00355    if (!jb->frames) {  /* queue is empty */
00356       jb->frames = frame;
00357       frame->next = frame;
00358       frame->prev = frame;
00359       head = 1;
00360    } else if (resync_ts < jb->frames->ts) {
00361       frame->next = jb->frames;
00362       frame->prev = jb->frames->prev;
00363 
00364       frame->next->prev = frame;
00365       frame->prev->next = frame;
00366 
00367       /* frame is out of order */
00368       jb->info.frames_ooo++;
00369 
00370       jb->frames = frame;
00371       head = 1;
00372    } else { 
00373       p = jb->frames;
00374 
00375       /* frame is out of order */
00376       if (resync_ts < p->prev->ts) jb->info.frames_ooo++;
00377 
00378       while (resync_ts < p->prev->ts && p->prev != jb->frames) 
00379          p = p->prev;
00380 
00381       frame->next = p;
00382       frame->prev = p->prev;
00383 
00384       frame->next->prev = frame;
00385       frame->prev->next = frame;
00386    }
00387    return head;
00388 }


Variable Documentation

jb_output_function_t dbgf [static]
 

Definition at line 53 of file jitterbuf.c.

jb_output_function_t errf [static]
 

Definition at line 53 of file jitterbuf.c.

jb_output_function_t warnf [static]
 

Definition at line 53 of file jitterbuf.c.


Generated on Fri May 26 01:49:10 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6