aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-05-19 00:34:28 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-05-19 00:34:28 +0000
commita84d39781c293a131b6ae9c6ea63bc00f8b69982 (patch)
tree28da8caf914873bb7d3ecf42261e790984e8f049
parentd11f57ef942239a8e308c4b0bbd6c049df5060ac (diff)
More jitter buffer fixes for large resync (bug #4311)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@5719 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-xchannels/chan_iax2.c15
-rwxr-xr-xconfigs/iax.conf.sample10
-rwxr-xr-xjitterbuf.c48
-rwxr-xr-xjitterbuf.h4
4 files changed, 62 insertions, 15 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index aae841665..37c305890 100755
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -129,6 +129,9 @@ static int lagrq_time = 10;
static int maxtrunkcall = TRUNK_CALL_START;
static int maxnontrunkcall = 1;
static int maxjitterbuffer=1000;
+#ifdef NEWJB
+static int resyncthreshold=1000;
+#endif
static int jittershrinkrate=2;
static int trunkfreq = 20;
static int send_trunktimestamps = 1;
@@ -859,6 +862,7 @@ static struct chan_iax2_pvt *new_iax(struct sockaddr_in *sin, int lockpeer, cons
tmp->jb = jb_new();
tmp->jbid = -1;
jbinfo.max_jitterbuf = maxjitterbuffer;
+ jbinfo.resync_threshold = resyncthreshold;
jb_setinfo(tmp->jb,&jbinfo);
}
#endif
@@ -2216,10 +2220,10 @@ static int get_from_jb(void *p) {
* make preprocessor swiss-cheese out of this one. I'm not sure which is less revolting.. */
static int schedule_delivery(struct iax_frame *fr, int reallydeliver, int updatehistory, int fromtrunk)
{
- int x;
#ifdef NEWJB
int type, len;
#else
+ int x;
int ms;
int delay;
unsigned int orig_ts;
@@ -2242,6 +2246,7 @@ static int schedule_delivery(struct iax_frame *fr, int reallydeliver, int update
unwrap_timestamp(fr);
if (updatehistory) {
+#ifndef NEWJB
/* Attempt to spot a change of timebase on timestamps coming from the other side
We detect by noticing a jump in consecutive timestamps that can't reasonably be explained
@@ -2263,7 +2268,6 @@ static int schedule_delivery(struct iax_frame *fr, int reallydeliver, int update
iaxs[fr->callno]->last = 0;
/* should we also empty history? */
}
-#ifndef NEWJB
/* ms is a measure of the "lateness" of the frame relative to the "reference"
frame we received. (initially the very first, but also see code just above here).
Understand that "ms" can easily be -ve if lag improves since the reference frame.
@@ -2386,8 +2390,9 @@ static int schedule_delivery(struct iax_frame *fr, int reallydeliver, int update
if(jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
calc_rxstamp(iaxs[fr->callno],fr->ts)) == JB_DROP) {
iax2_frame_free(fr);
+ } else {
+ update_jbsched(iaxs[fr->callno]);
}
- update_jbsched(iaxs[fr->callno]);
#else
/* Just for reference, keep the "jitter" value, the difference between the
earliest and the latest. */
@@ -8411,6 +8416,10 @@ static int set_config(char *config_file, int reload)
}
else if (!strcasecmp(v->name, "maxjitterbuffer"))
maxjitterbuffer = atoi(v->value);
+#ifdef NEWJB
+ else if (!strcasecmp(v->name, "resyncthreshold"))
+ resyncthreshold = atoi(v->value);
+#endif
else if (!strcasecmp(v->name, "jittershrinkrate"))
jittershrinkrate = atoi(v->value);
else if (!strcasecmp(v->name, "maxexcessbuffer"))
diff --git a/configs/iax.conf.sample b/configs/iax.conf.sample
index 09001ea9f..5cf8a5be4 100755
--- a/configs/iax.conf.sample
+++ b/configs/iax.conf.sample
@@ -103,6 +103,13 @@ disallow=lpc10 ; Icky sound quality... Mr. Roboto.
; from rising to silly values in extreme situations; you'll hear
; SOMETHING, even though it will be jittery.
;
+; resyncthreshold: when the jitterbuffer notices a significant change in delay
+; that continues over a few frames, it will resync, assuming that the change in
+; delay was caused by a timestamping mix-up. The threshold for noticing a change
+; in delay is measured as twice the measured jitter plus this resync threshold.
+; Resycning can be disabled by setting this parameter to -1.
+; [This option presently applies only to the new jitterbuffer implementation]
+;
; maxexcessbuffer: If conditions improve after a period of high jitter,
; the jitter buffer can end up bigger than necessary. If it ends up
; more than "maxexcessbuffer" bigger than needed, Asterisk will start
@@ -124,7 +131,8 @@ disallow=lpc10 ; Icky sound quality... Mr. Roboto.
jitterbuffer=no
forcejitterbuffer=no
;dropcount=2
-;maxjitterbuffer=500
+;maxjitterbuffer=1000
+;resyncthreshold=1000
;maxexcessbuffer=80
;minexcessbuffer=10
;jittershrinkrate=1
diff --git a/jitterbuf.c b/jitterbuf.c
index 96dff632d..9611048e0 100755
--- a/jitterbuf.c
+++ b/jitterbuf.c
@@ -106,14 +106,37 @@ static int longcmp(const void *a, const void *b)
}
#endif
-static void history_put(jitterbuf *jb, long ts, long now)
+static int history_put(jitterbuf *jb, long ts, long now, long ms)
{
- long delay = now - ts;
+ long delay = now - (ts - jb->info.resync_offset);
+ long threshold = 2 * jb->info.jitter + jb->info.resync_threshold;
long kicked;
/* don't add special/negative times to history */
if (ts <= 0)
- return;
+ return 0;
+
+ /* check for drastic change in delay */
+ if (jb->info.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 = 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];
@@ -125,7 +148,7 @@ static void history_put(jitterbuf *jb, long ts, long now)
* 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;
+ return 0;
/* don't do this until we've filled history
* (reduces some edge cases below) */
@@ -149,13 +172,13 @@ static void history_put(jitterbuf *jb, long ts, long now)
/* if we got here, we don't need to invalidate, 'cause this delay didn't
* affect things */
- return;
+ return 0;
/* end optimization */
invalidate:
jb->hist_maxbuf_valid = 0;
- return;
+ return 0;
}
static void history_calc_maxbuf(jitterbuf *jb)
@@ -281,6 +304,7 @@ static void queue_put(jitterbuf *jb, void *data, int type, long ms, long ts)
{
jb_frame *frame;
jb_frame *p;
+ long resync_ts = ts - jb->info.resync_offset;
frame = jb->free;
if (frame) {
@@ -297,7 +321,7 @@ static void queue_put(jitterbuf *jb, void *data, int type, long ms, long ts)
jb->info.frames_cur++;
frame->data = data;
- frame->ts = ts;
+ frame->ts = resync_ts;
frame->ms = ms;
frame->type = type;
@@ -310,7 +334,7 @@ static void queue_put(jitterbuf *jb, void *data, int type, long ms, long ts)
jb->frames = frame;
frame->next = frame;
frame->prev = frame;
- } else if (ts < jb->frames->ts) {
+ } else if (resync_ts < jb->frames->ts) {
frame->next = jb->frames;
frame->prev = jb->frames->prev;
@@ -325,9 +349,9 @@ static void queue_put(jitterbuf *jb, void *data, int type, long ms, long ts)
p = jb->frames;
/* frame is out of order */
- if (ts < p->prev->ts) jb->info.frames_ooo++;
+ if (resync_ts < p->prev->ts) jb->info.frames_ooo++;
- while (ts < p->prev->ts && p->prev != jb->frames)
+ while (resync_ts < p->prev->ts && p->prev != jb->frames)
p = p->prev;
frame->next = p;
@@ -474,7 +498,8 @@ int jb_put(jitterbuf *jb, void *data, int type, long ms, long ts, long now)
if (type == JB_TYPE_VOICE) {
/* presently, I'm only adding VOICE frames to history and drift calculations; mostly because with the
* IAX integrations, I'm sending retransmitted control frames with their awkward timestamps through */
- history_put(jb,ts,now);
+ if (history_put(jb,ts,now,ms))
+ return JB_DROP;
}
queue_put(jb,data,type,ms,ts);
@@ -750,6 +775,7 @@ int jb_setinfo(jitterbuf *jb, jb_info *settings)
/* take selected settings from the struct */
jb->info.max_jitterbuf = settings->max_jitterbuf;
+ jb->info.resync_threshold = settings->resync_threshold;
return JB_OK;
}
diff --git a/jitterbuf.h b/jitterbuf.h
index 839120290..1cec72643 100755
--- a/jitterbuf.h
+++ b/jitterbuf.h
@@ -67,9 +67,13 @@ typedef struct jb_info {
long last_voice_ms; /* the duration of the last voice frame */
long silence_begin_ts; /* the time of the last CNG frame, when in silence */
long last_adjustment; /* the time of the last adjustment */
+ long last_delay; /* the last now added to history */
+ long cnt_delay_discont; /* the count of discontinuous delays */
+ long resync_offset; /* the amount to offset ts to support resyncs */
/* settings */
long max_jitterbuf; /* defines a hard clamp to use in setting the jitter buffer delay */
+ long resync_threshold; /* the jb will resync when delay increases to (2 * jitter) + this param */
} jb_info;
typedef struct jb_frame {