Fix a variety of potential buffer overflows
[asterisk/asterisk.git] / main / jitterbuf.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004-2005, Horizon Wimba, Inc.
5  *
6  * Contributors:
7  * Steve Kann <stevek@stevek.com>
8  *
9  * A license has been granted to Digium (via disclaimer) for the use of
10  * this code.
11  *
12  * See http://www.asterisk.org for more information about
13  * the Asterisk project. Please do not directly contact
14  * any of the maintainers of this project for assistance;
15  * the project provides a web site, mailing lists and IRC
16  * channels for your use.
17  *
18  * This program is free software, distributed under the terms of
19  * the GNU General Public License Version 2. See the LICENSE file
20  * at the top of the source tree.
21  */
22
23 /*! \file
24  *
25  * \brief jitterbuf: an application-independent jitterbuffer
26  * \author Steve Kann <stevek@stevek.com>
27  *
28  */
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "jitterbuf.h"
35 #include "asterisk/utils.h"
36
37 /*! define these here, just for ancient compiler systems */
38 #define JB_LONGMAX 2147483647L
39 #define JB_LONGMIN (-JB_LONGMAX - 1L)
40
41 #define jb_warn(...) (warnf ? warnf(__VA_ARGS__) : (void)0)
42 #define jb_err(...) (errf ? errf(__VA_ARGS__) : (void)0)
43 #define jb_dbg(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
44
45 #ifdef DEEP_DEBUG
46 #define jb_dbg2(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
47 #else
48 #define jb_dbg2(...) ((void)0)
49 #endif
50
51 static jb_output_function_t warnf, errf, dbgf;
52
53 void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg)
54 {
55         errf = err;
56         warnf = warn;
57         dbgf = dbg;
58 }
59
60 static void increment_losspct(jitterbuf *jb)
61 {
62         jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;
63 }
64
65 static void decrement_losspct(jitterbuf *jb)
66 {
67         jb->info.losspct = (499 * jb->info.losspct)/500;
68 }
69
70 void jb_reset(jitterbuf *jb)
71 {
72         /* only save settings */
73         jb_conf s = jb->info.conf;
74         memset(jb, 0, sizeof(*jb));
75         jb->info.conf = s;
76
77         /* initialize length, using the default value */
78         jb->info.current = jb->info.target = jb->info.conf.target_extra = JB_TARGET_EXTRA;
79         jb->info.silence_begin_ts = -1;
80 }
81
82 jitterbuf * jb_new()
83 {
84         jitterbuf *jb;
85
86         if (!(jb = ast_malloc(sizeof(*jb))))
87                 return NULL;
88
89         jb_reset(jb);
90
91         jb_dbg2("jb_new() = %x\n", jb);
92         return jb;
93 }
94
95 void jb_destroy(jitterbuf *jb)
96 {
97         jb_frame *frame;
98         jb_dbg2("jb_destroy(%x)\n", jb);
99
100         /* free all the frames on the "free list" */
101         frame = jb->free;
102         while (frame != NULL) {
103                 jb_frame *next = frame->next;
104                 ast_free(frame);
105                 frame = next;
106         }
107
108         /* free ourselves! */
109         ast_free(jb);
110 }
111
112 static int check_resync(jitterbuf *jb, long ts, long now, long ms, const enum jb_frame_type type, long *delay)
113 {
114         long numts = 0;
115         long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold;
116
117         /* Check for overfill of the buffer */
118         if (jb->frames) {
119                 numts = jb->frames->prev->ts - jb->frames->ts;
120         }
121
122         if (numts >= (jb->info.conf.max_jitterbuf)) {
123                 if (!jb->dropem) {
124                         ast_debug(1, "Attempting to exceed Jitterbuf max %ld timeslots\n",
125                                 jb->info.conf.max_jitterbuf);
126                         jb->dropem = 1;
127                 }
128                 jb->info.frames_dropped++;
129                 return -1;
130         } else {
131                 jb->dropem = 0;
132         }
133
134         /* check for drastic change in delay */
135         if (jb->info.conf.resync_threshold != -1) {
136                 if (abs(*delay - jb->info.last_delay) > threshold) {
137                         jb->info.cnt_delay_discont++;
138                         /* resync the jitterbuffer on 3 consecutive discontinuities,
139                          * or immediately if a control frame */
140                         if ((jb->info.cnt_delay_discont > 3) || (type == JB_TYPE_CONTROL)) {
141                                 jb->info.cnt_delay_discont = 0;
142                                 jb->hist_ptr = 0;
143                                 jb->hist_maxbuf_valid = 0;
144                                 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);
145                                 jb->info.resync_offset = ts - now;
146                                 jb->info.last_delay = *delay = 0; /* after resync, frame is right on time */
147                         } else {
148                                 jb->info.frames_dropped++;
149                                 return -1;
150                         }
151                 } else {
152                         jb->info.last_delay = *delay;
153                         jb->info.cnt_delay_discont = 0;
154                 }
155         }
156         return 0;
157 }
158
159 static int history_put(jitterbuf *jb, long ts, long now, long ms, long delay)
160 {
161         long kicked;
162
163         /* don't add special/negative times to history */
164         if (ts <= 0)
165                 return 0;
166
167         kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ];
168
169         jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay;
170
171         /* optimization; the max/min buffers don't need to be recalculated, if this packet's
172          * entry doesn't change them.  This happens if this packet is not involved, _and_ any packet
173          * that got kicked out of the history is also not involved
174          * We do a number of comparisons, but it's probably still worthwhile, because it will usually
175          * succeed, and should be a lot faster than going through all 500 packets in history */
176         if (!jb->hist_maxbuf_valid)
177                 return 0;
178
179         /* don't do this until we've filled history
180          * (reduces some edge cases below) */
181         if (jb->hist_ptr < JB_HISTORY_SZ)
182                 goto invalidate;
183
184         /* if the new delay would go into min */
185         if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
186                 goto invalidate;
187
188         /* or max.. */
189         if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
190                 goto invalidate;
191
192         /* or the kicked delay would be in min */
193         if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
194                 goto invalidate;
195
196         if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
197                 goto invalidate;
198
199         /* if we got here, we don't need to invalidate, 'cause this delay didn't
200          * affect things */
201         return 0;
202         /* end optimization */
203
204
205 invalidate:
206         jb->hist_maxbuf_valid = 0;
207         return 0;
208 }
209
210 static void history_calc_maxbuf(jitterbuf *jb)
211 {
212         int i,j;
213
214         if (jb->hist_ptr == 0)
215                 return;
216
217
218         /* initialize maxbuf/minbuf to the latest value */
219         for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) {
220 /*
221  * jb->hist_maxbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
222  * jb->hist_minbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
223  */
224                 jb->hist_maxbuf[i] = JB_LONGMIN;
225                 jb->hist_minbuf[i] = JB_LONGMAX;
226         }
227
228         /* use insertion sort to populate maxbuf */
229         /* we want it to be the top "n" values, in order */
230
231         /* start at the beginning, or JB_HISTORY_SZ frames ago */
232         i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0;
233
234         for (;i<jb->hist_ptr;i++) {
235                 long toins = jb->history[i % JB_HISTORY_SZ];
236
237                 /* if the maxbuf should get this */
238                 if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])  {
239
240                         /* insertion-sort it into the maxbuf */
241                         for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
242                                 /* found where it fits */
243                                 if (toins > jb->hist_maxbuf[j]) {
244                                         /* move over */
245                                         if (j != JB_HISTORY_MAXBUF_SZ - 1) {
246                                                 memmove(jb->hist_maxbuf + j + 1, jb->hist_maxbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_maxbuf[0]));
247                                         }
248                                         /* insert */
249                                         jb->hist_maxbuf[j] = toins;
250
251                                         break;
252                                 }
253                         }
254                 }
255
256                 /* if the minbuf should get this */
257                 if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])  {
258
259                         /* insertion-sort it into the maxbuf */
260                         for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
261                                 /* found where it fits */
262                                 if (toins < jb->hist_minbuf[j]) {
263                                         /* move over */
264                                         if (j != JB_HISTORY_MAXBUF_SZ - 1) {
265                                                 memmove(jb->hist_minbuf + j + 1, jb->hist_minbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_minbuf[0]));
266                                         }
267                                         /* insert */
268                                         jb->hist_minbuf[j] = toins;
269
270                                         break;
271                                 }
272                         }
273                 }
274
275                 if (0) {
276                         int k;
277                         fprintf(stderr, "toins = %ld\n", toins);
278                         fprintf(stderr, "maxbuf =");
279                         for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
280                                 fprintf(stderr, "%ld ", jb->hist_maxbuf[k]);
281                         fprintf(stderr, "\nminbuf =");
282                         for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
283                                 fprintf(stderr, "%ld ", jb->hist_minbuf[k]);
284                         fprintf(stderr, "\n");
285                 }
286         }
287
288         jb->hist_maxbuf_valid = 1;
289 }
290
291 static void history_get(jitterbuf *jb)
292 {
293         long max, min, jitter;
294         int idx;
295         int count;
296
297         if (!jb->hist_maxbuf_valid)
298                 history_calc_maxbuf(jb);
299
300         /* count is how many items in history we're examining */
301         count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ;
302
303         /* idx is the "n"ths highest/lowest that we'll look for */
304         idx = count * JB_HISTORY_DROPPCT / 100;
305
306         /* sanity checks for idx */
307         if (idx > (JB_HISTORY_MAXBUF_SZ - 1))
308                 idx = JB_HISTORY_MAXBUF_SZ - 1;
309
310         if (idx < 0) {
311                 jb->info.min = 0;
312                 jb->info.jitter = 0;
313                 return;
314         }
315
316         max = jb->hist_maxbuf[idx];
317         min = jb->hist_minbuf[idx];
318
319         jitter = max - min;
320
321         /* these debug stmts compare the difference between looking at the absolute jitter, and the
322          * values we get by throwing away the outliers */
323         /*
324         fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", index, min, max, jitter);
325         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]);
326         */
327
328         jb->info.min = min;
329         jb->info.jitter = jitter;
330 }
331
332 /* returns 1 if frame was inserted into head of queue, 0 otherwise */
333 static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts)
334 {
335         jb_frame *frame;
336         jb_frame *p;
337         int head = 0;
338         long resync_ts = ts - jb->info.resync_offset;
339
340         if ((frame = jb->free)) {
341                 jb->free = frame->next;
342         } else if (!(frame = ast_malloc(sizeof(*frame)))) {
343                 jb_err("cannot allocate frame\n");
344                 return 0;
345         }
346
347         jb->info.frames_cur++;
348
349         frame->data = data;
350         frame->ts = resync_ts;
351         frame->ms = ms;
352         frame->type = type;
353
354         /*
355          * frames are a circular list, jb-frames points to to the lowest ts,
356          * jb->frames->prev points to the highest ts
357          */
358
359         if (!jb->frames) {  /* queue is empty */
360                 jb->frames = frame;
361                 frame->next = frame;
362                 frame->prev = frame;
363                 head = 1;
364         } else if (resync_ts < jb->frames->ts) {
365                 frame->next = jb->frames;
366                 frame->prev = jb->frames->prev;
367
368                 frame->next->prev = frame;
369                 frame->prev->next = frame;
370
371                 /* frame is out of order */
372                 jb->info.frames_ooo++;
373
374                 jb->frames = frame;
375                 head = 1;
376         } else {
377                 p = jb->frames;
378
379                 /* frame is out of order */
380                 if (resync_ts < p->prev->ts) jb->info.frames_ooo++;
381
382                 while (resync_ts < p->prev->ts && p->prev != jb->frames)
383                         p = p->prev;
384
385                 frame->next = p;
386                 frame->prev = p->prev;
387
388                 frame->next->prev = frame;
389                 frame->prev->next = frame;
390         }
391         return head;
392 }
393
394 static long queue_next(jitterbuf *jb)
395 {
396         if (jb->frames)
397                 return jb->frames->ts;
398         else
399                 return -1;
400 }
401
402 static long queue_last(jitterbuf *jb)
403 {
404         if (jb->frames)
405                 return jb->frames->prev->ts;
406         else
407                 return -1;
408 }
409
410 static jb_frame *_queue_get(jitterbuf *jb, long ts, int all)
411 {
412         jb_frame *frame;
413         frame = jb->frames;
414
415         if (!frame)
416                 return NULL;
417
418         /*jb_warn("queue_get: ASK %ld FIRST %ld\n", ts, frame->ts); */
419
420         if (all || ts >= frame->ts) {
421                 /* remove this frame */
422                 frame->prev->next = frame->next;
423                 frame->next->prev = frame->prev;
424
425                 if (frame->next == frame)
426                         jb->frames = NULL;
427                 else
428                         jb->frames = frame->next;
429
430
431                 /* insert onto "free" single-linked list */
432                 frame->next = jb->free;
433                 jb->free = frame;
434
435                 jb->info.frames_cur--;
436
437                 /* we return the frame pointer, even though it's on free list,
438                  * but caller must copy data */
439                 return frame;
440         }
441
442         return NULL;
443 }
444
445 static jb_frame *queue_get(jitterbuf *jb, long ts)
446 {
447         return _queue_get(jb,ts,0);
448 }
449
450 static jb_frame *queue_getall(jitterbuf *jb)
451 {
452         return _queue_get(jb,0,1);
453 }
454
455 #if 0
456 /* some diagnostics */
457 static void jb_dbginfo(jitterbuf *jb)
458 {
459         if (dbgf == NULL)
460                 return;
461
462         jb_dbg("\njb info: fin=%ld fout=%ld flate=%ld flost=%ld fdrop=%ld fcur=%ld\n",
463                 jb->info.frames_in, jb->info.frames_out, jb->info.frames_late, jb->info.frames_lost, jb->info.frames_dropped, jb->info.frames_cur);
464
465         jb_dbg("jitter=%ld current=%ld target=%ld min=%ld sil=%d len=%d len/fcur=%ld\n",
466                 jb->info.jitter, jb->info.current, jb->info.target, jb->info.min, jb->info.silence_begin_ts, jb->info.current - jb->info.min,
467                 jb->info.frames_cur ? (jb->info.current - jb->info.min)/jb->info.frames_cur : -8);
468         if (jb->info.frames_in > 0)
469                 jb_dbg("jb info: Loss PCT = %ld%%, Late PCT = %ld%%\n",
470                         jb->info.frames_lost * 100/(jb->info.frames_in + jb->info.frames_lost),
471                         jb->info.frames_late * 100/jb->info.frames_in);
472         jb_dbg("jb info: queue %d -> %d.  last_ts %d (queue len: %d) last_ms %d\n",
473                 queue_next(jb),
474                 queue_last(jb),
475                 jb->info.next_voice_ts,
476                 queue_last(jb) - queue_next(jb),
477                 jb->info.last_voice_ms);
478 }
479 #endif
480
481 #ifdef DEEP_DEBUG
482 static void jb_chkqueue(jitterbuf *jb)
483 {
484         int i=0;
485         jb_frame *p = jb->frames;
486
487         if (!p) {
488                 return;
489         }
490
491         do {
492                 if (p->next == NULL)  {
493                         jb_err("Queue is BROKEN at item [%d]", i);
494                 }
495                 i++;
496                 p=p->next;
497         } while (p->next != jb->frames);
498 }
499
500 static void jb_dbgqueue(jitterbuf *jb)
501 {
502         int i=0;
503         jb_frame *p = jb->frames;
504
505         jb_dbg("queue: ");
506
507         if (!p) {
508                 jb_dbg("EMPTY\n");
509                 return;
510         }
511
512         do {
513                 jb_dbg("[%d]=%ld ", i++, p->ts);
514                 p=p->next;
515         } while (p->next != jb->frames);
516
517         jb_dbg("\n");
518 }
519 #endif
520
521 enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now)
522 {
523         long delay = now - (ts - jb->info.resync_offset);
524         jb_dbg2("jb_put(%x,%x,%ld,%ld,%ld)\n", jb, data, ms, ts, now);
525
526         if (check_resync(jb, ts, now, ms, type, &delay)) {
527                 return JB_DROP;
528         }
529
530         if (type == JB_TYPE_VOICE) {
531                 /* presently, I'm only adding VOICE frames to history and drift calculations; mostly because with the
532                  * IAX integrations, I'm sending retransmitted control frames with their awkward timestamps through */
533                 history_put(jb, ts, now, ms, delay);
534         }
535
536         jb->info.frames_in++;
537
538         /* if put into head of queue, caller needs to reschedule */
539         if (queue_put(jb,data,type,ms,ts)) {
540                 return JB_SCHED;
541         }
542         return JB_OK;
543 }
544
545
546 static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
547 {
548         jb_frame *frame;
549         long diff;
550         static int dbg_cnt = 0;
551
552         /* get jitter info */
553         history_get(jb);
554
555         if (dbg_cnt && dbg_cnt % 50 == 0) {
556                 jb_dbg("\n");
557         }
558         dbg_cnt++;
559
560         /* target */
561         jb->info.target = jb->info.jitter + jb->info.min + jb->info.conf.target_extra;
562
563         /* if a hard clamp was requested, use it */
564         if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) {
565                 jb_dbg("clamping target from %ld to %ld\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf);
566                 jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf;
567         }
568
569         diff = jb->info.target - jb->info.current;
570
571         /* jb_warn("diff = %d lms=%d last = %d now = %d\n", diff,  */
572         /*      jb->info.last_voice_ms, jb->info.last_adjustment, now); */
573
574         /* let's work on non-silent case first */
575         if (!jb->info.silence_begin_ts) {
576                 /* we want to grow */
577                 if ((diff > 0) &&
578                         /* we haven't grown in the delay length */
579                         (((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) ||
580                         /* we need to grow more than the "length" we have left */
581                         (diff > queue_last(jb)  - queue_next(jb)) ) ) {
582                         /* grow by interp frame length */
583                         jb->info.current += interpl;
584                         jb->info.next_voice_ts += interpl;
585                         jb->info.last_voice_ms = interpl;
586                         jb->info.last_adjustment = now;
587                         jb->info.cnt_contig_interp++;
588                         if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
589                                 jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
590                         }
591                         jb_dbg("G");
592                         return JB_INTERP;
593                 }
594
595                 frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current);
596
597                 /* not a voice frame; just return it. */
598                 if (frame && frame->type != JB_TYPE_VOICE) {
599                         if (frame->type == JB_TYPE_SILENCE) {
600                                 jb->info.silence_begin_ts = frame->ts;
601                                 jb->info.cnt_contig_interp = 0;
602                         }
603
604                         *frameout = *frame;
605                         jb->info.frames_out++;
606                         jb_dbg("o");
607                         return JB_OK;
608                 }
609
610
611                 /* voice frame is later than expected */
612                 if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) {
613                         if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) {
614                                 /* either we interpolated past this frame in the last jb_get */
615                                 /* or the frame is still in order, but came a little too quick */
616                                 *frameout = *frame;
617                                 /* reset expectation for next frame */
618                                 jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
619                                 jb->info.frames_out++;
620                                 decrement_losspct(jb);
621                                 jb->info.cnt_contig_interp = 0;
622                                 jb_dbg("v");
623                                 return JB_OK;
624                         } else {
625                                 /* voice frame is late */
626                                 *frameout = *frame;
627                                 jb->info.frames_out++;
628                                 decrement_losspct(jb);
629                                 jb->info.frames_late++;
630                                 jb->info.frames_lost--;
631                                 jb_dbg("l");
632                                 return JB_DROP;
633                         }
634                 }
635
636                 /* keep track of frame sizes, to allow for variable sized-frames */
637                 if (frame && frame->ms > 0) {
638                         jb->info.last_voice_ms = frame->ms;
639                 }
640
641                 /* we want to shrink; shrink at 1 frame / 500ms */
642                 /* unless we don't have a frame, then shrink 1 frame */
643                 /* every 80ms (though perhaps we can shrink even faster */
644                 /* in this case) */
645                 if (diff < -jb->info.conf.target_extra &&
646                         ((!frame && jb->info.last_adjustment + 80 < now) ||
647                         (jb->info.last_adjustment + 500 < now))) {
648
649                         jb->info.last_adjustment = now;
650                         jb->info.cnt_contig_interp = 0;
651
652                         if (frame) {
653                                 *frameout = *frame;
654                                 /* shrink by frame size we're throwing out */
655                                 jb->info.current -= frame->ms;
656                                 jb->info.frames_out++;
657                                 decrement_losspct(jb);
658                                 jb->info.frames_dropped++;
659                                 jb_dbg("s");
660                                 return JB_DROP;
661                         } else {
662                                 /* shrink by last_voice_ms */
663                                 jb->info.current -= jb->info.last_voice_ms;
664                                 jb->info.frames_lost++;
665                                 increment_losspct(jb);
666                                 jb_dbg("S");
667                                 return JB_NOFRAME;
668                         }
669                 }
670
671                 /* lost frame */
672                 if (!frame) {
673                         /* this is a bit of a hack for now, but if we're close to
674                          * target, and we find a missing frame, it makes sense to
675                          * grow, because the frame might just be a bit late;
676                          * otherwise, we presently get into a pattern where we return
677                          * INTERP for the lost frame, then it shows up next, and we
678                          * throw it away because it's late */
679                         /* I've recently only been able to replicate this using
680                          * iaxclient talking to app_echo on asterisk.  In this case,
681                          * my outgoing packets go through asterisk's (old)
682                          * jitterbuffer, and then might get an unusual increasing delay
683                          * there if it decides to grow?? */
684                         /* Update: that might have been a different bug, that has been fixed..
685                          * But, this still seemed like a good idea, except that it ended up making a single actual
686                          * lost frame get interpolated two or more times, when there was "room" to grow, so it might
687                          * be a bit of a bad idea overall */
688                         /*if (diff > -1 * jb->info.last_voice_ms) {
689                                 jb->info.current += jb->info.last_voice_ms;
690                                 jb->info.last_adjustment = now;
691                                 jb_warn("g");
692                                 return JB_INTERP;
693                         } */
694                         jb->info.frames_lost++;
695                         increment_losspct(jb);
696                         jb->info.next_voice_ts += interpl;
697                         jb->info.last_voice_ms = interpl;
698                         jb->info.cnt_contig_interp++;
699                         if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
700                                 jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
701                         }
702                         jb_dbg("L");
703                         return JB_INTERP;
704                 }
705
706                 /* normal case; return the frame, increment stuff */
707                 *frameout = *frame;
708                 jb->info.next_voice_ts += frame->ms;
709                 jb->info.frames_out++;
710                 jb->info.cnt_contig_interp = 0;
711                 decrement_losspct(jb);
712                 jb_dbg("v");
713                 return JB_OK;
714         } else {
715                 /* TODO: after we get the non-silent case down, we'll make the
716                  * silent case -- basically, we'll just grow and shrink faster
717                  * here, plus handle next_voice_ts a bit differently */
718
719                 /* to disable silent special case altogether, just uncomment this: */
720                 /* jb->info.silence_begin_ts = 0; */
721
722                 /* shrink interpl len every 10ms during silence */
723                 if (diff < -jb->info.conf.target_extra &&
724                         jb->info.last_adjustment + 10 <= now) {
725                         jb->info.current -= interpl;
726                         jb->info.last_adjustment = now;
727                 }
728
729                 frame = queue_get(jb, now - jb->info.current);
730                 if (!frame) {
731                         return JB_NOFRAME;
732                 } else if (frame->type != JB_TYPE_VOICE) {
733                         /* normal case; in silent mode, got a non-voice frame */
734                         *frameout = *frame;
735                         jb->info.frames_out++;
736                         return JB_OK;
737                 }
738                 if (frame->ts < jb->info.silence_begin_ts) {
739                         /* voice frame is late */
740                         *frameout = *frame;
741                         jb->info.frames_out++;
742                         decrement_losspct(jb);
743                         jb->info.frames_late++;
744                         jb->info.frames_lost--;
745                         jb_dbg("l");
746                         return JB_DROP;
747                 } else {
748                         /* voice frame */
749                         /* try setting current to target right away here */
750                         jb->info.current = jb->info.target;
751                         jb->info.silence_begin_ts = 0;
752                         jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
753                         jb->info.last_voice_ms = frame->ms;
754                         jb->info.frames_out++;
755                         decrement_losspct(jb);
756                         *frameout = *frame;
757                         jb_dbg("V");
758                         return JB_OK;
759                 }
760         }
761 }
762
763 long jb_next(jitterbuf *jb)
764 {
765         if (jb->info.silence_begin_ts) {
766                 if (jb->frames) {
767                         long next = queue_next(jb);
768                         history_get(jb);
769                         /* shrink during silence */
770                         if (jb->info.target - jb->info.current < -jb->info.conf.target_extra)
771                                 return jb->info.last_adjustment + 10;
772                         return next + jb->info.target;
773                 }
774                 else
775                         return JB_LONGMAX;
776         } else {
777                 return jb->info.next_voice_ts;
778         }
779 }
780
781 enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
782 {
783         enum jb_return_code ret = _jb_get(jb, frameout, now, interpl);
784 #if 0
785         static int lastts=0;
786         int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0;
787         jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists);
788         if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n");
789         lastts = thists;
790 #endif
791         if (ret == JB_INTERP)
792                 frameout->ms = jb->info.last_voice_ms;
793
794         return ret;
795 }
796
797 enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
798 {
799         jb_frame *frame;
800         frame = queue_getall(jb);
801
802         if (!frame) {
803                 return JB_NOFRAME;
804         }
805
806         *frameout = *frame;
807         return JB_OK;
808 }
809
810
811 enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats)
812 {
813
814         history_get(jb);
815
816         *stats = jb->info;
817
818         return JB_OK;
819 }
820
821 enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
822 {
823         /* take selected settings from the struct */
824
825         jb->info.conf.max_jitterbuf = conf->max_jitterbuf;
826         jb->info.conf.resync_threshold = conf->resync_threshold;
827         jb->info.conf.max_contig_interp = conf->max_contig_interp;
828
829         /* -1 indicates use of the default JB_TARGET_EXTRA value */
830         jb->info.conf.target_extra = ( conf->target_extra == -1 )
831                 ? JB_TARGET_EXTRA
832                 : conf->target_extra
833                 ;
834
835         /* update these to match new target_extra setting */
836         jb->info.current = jb->info.conf.target_extra;
837         jb->info.target = jb->info.conf.target_extra;
838
839         return JB_OK;
840 }
841
842