enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl) { enum jb_return_code ret = _jb_get(jb, frameout, now, interpl); #if 0 static int lastts=0; int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0; jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists); if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n"); lastts = thists; #endif return ret; }
int jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl) { int ret = _jb_get(jb,frameout,now,interpl); #if 0 static int lastts=0; int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0; jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists); if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n"); lastts = thists; #endif if(ret == JB_INTERP) frameout->ms = jb->info.last_voice_ms; return ret; }
static void resync(jitterbuf *jb, long ts, long now) { long delay = now - (ts - jb->info.resync_offset); long threshold = 2 * jb->info.jitter + jb->conf.resync_threshold; /* resync the jitterbuffer */ jb->info.cnt_delay_discont = 0; jb->hist_ptr = 0; jb->hist_maxbuf_valid = 0; jb->force_resync = 0; 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); jb->info.resync_offset = ts - now; jb->info.last_delay = 0; /* after resync, frame is right on time */ }
static int check_resync(jitterbuf *jb, long ts, long now, long ms, const enum jb_frame_type type, long *delay) { long numts = 0; long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold; /* Check for overfill of the buffer */ if (jb->frames) { numts = jb->frames->prev->ts - jb->frames->ts; } if (numts >= (jb->info.conf.max_jitterbuf)) { if (!jb->dropem) { ast_debug(1, "Attempting to exceed Jitterbuf max %ld timeslots\n", jb->info.conf.max_jitterbuf); jb->dropem = 1; } jb->info.frames_dropped++; return -1; } else { jb->dropem = 0; } /* check for drastic change in delay */ if (jb->info.conf.resync_threshold != -1) { if (abs(*delay - jb->info.last_delay) > threshold) { jb->info.cnt_delay_discont++; /* resync the jitterbuffer on 3 consecutive discontinuities, * or immediately if a control frame */ if ((jb->info.cnt_delay_discont > 3) || (type == JB_TYPE_CONTROL)) { jb->info.cnt_delay_discont = 0; jb->hist_ptr = 0; jb->hist_maxbuf_valid = 0; 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); jb->info.resync_offset = ts - now; jb->info.last_delay = *delay = 0; /* after resync, frame is right on time */ } else { jb->info.frames_dropped++; return -1; } } else { jb->info.last_delay = *delay; jb->info.cnt_delay_discont = 0; } } return 0; }
/* drop parameter determines whether we will drop outliers to minimize * delay */ static int history_put(jitterbuf *jb, long ts, long now, long ms) { long delay = now - (ts - jb->info.resync_offset); long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold; long kicked; /* don't add special/negative times to history */ if (ts <= 0) return 0; /* check for drastic change in delay */ if (jb->info.conf.resync_threshold != -1) { if (abs(delay - jb->info.last_delay) > threshold) { jb->info.cnt_delay_discont++; if (jb->info.cnt_delay_discont > 3) { /* resync the jitterbuffer */ jb->info.cnt_delay_discont = 0; jb->hist_ptr = 0; jb->hist_maxbuf_valid = 0; 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); jb->info.resync_offset = ts - now; jb->info.last_delay = delay = 0; /* after resync, frame is right on time */ } else { return -1; } } else { jb->info.last_delay = delay; jb->info.cnt_delay_discont = 0; } } kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ]; jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay; /* optimization; the max/min buffers don't need to be recalculated, if this packet's * entry doesn't change them. This happens if this packet is not involved, _and_ any packet * that got kicked out of the history is also not involved * We do a number of comparisons, but it's probably still worthwhile, because it will usually * succeed, and should be a lot faster than going through all 500 packets in history */ if (!jb->hist_maxbuf_valid) return 0; /* don't do this until we've filled history * (reduces some edge cases below) */ if (jb->hist_ptr < JB_HISTORY_SZ) goto invalidate; /* if the new delay would go into min */ if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) goto invalidate; /* or max.. */ if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) goto invalidate; /* or the kicked delay would be in min */ if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) goto invalidate; if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) goto invalidate; /* if we got here, we don't need to invalidate, 'cause this delay didn't * affect things */ return 0; /* end optimization */ invalidate: jb->hist_maxbuf_valid = 0; return 0; }