00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 10368 $")
00036
00037 #include "jitterbuf.h"
00038
00039
00040 #define JB_LONGMAX 2147483647L
00041 #define JB_LONGMIN (-JB_LONGMAX - 1L)
00042
00043 #define jb_warn(...) (warnf ? warnf(__VA_ARGS__) : (void)0)
00044 #define jb_err(...) (errf ? errf(__VA_ARGS__) : (void)0)
00045 #define jb_dbg(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
00046
00047 #ifdef DEEP_DEBUG
00048 #define jb_dbg2(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
00049 #else
00050 #define jb_dbg2(...) ((void)0)
00051 #endif
00052
00053 static jb_output_function_t warnf, errf, dbgf;
00054
00055 void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg)
00056 {
00057 errf = err;
00058 warnf = warn;
00059 dbgf = dbg;
00060 }
00061
00062 static void increment_losspct(jitterbuf *jb)
00063 {
00064 jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;
00065 }
00066
00067 static void decrement_losspct(jitterbuf *jb)
00068 {
00069 jb->info.losspct = (499 * jb->info.losspct)/500;
00070 }
00071
00072 void jb_reset(jitterbuf *jb)
00073 {
00074
00075 jb_conf s = jb->info.conf;
00076 memset(jb,0,sizeof(jitterbuf));
00077 jb->info.conf = s;
00078
00079
00080 jb->info.current = jb->info.target = JB_TARGET_EXTRA;
00081 jb->info.silence_begin_ts = -1;
00082 }
00083
00084 jitterbuf * jb_new()
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 }
00098
00099 void jb_destroy(jitterbuf *jb)
00100 {
00101 jb_frame *frame;
00102 jb_dbg2("jb_destroy(%x)\n", jb);
00103
00104
00105 frame = jb->free;
00106 while (frame != NULL) {
00107 jb_frame *next = frame->next;
00108 free(frame);
00109 frame = next;
00110 }
00111
00112
00113 free(jb);
00114 }
00115
00116
00117
00118 #if 0
00119 static int longcmp(const void *a, const void *b)
00120 {
00121 return *(long *)a - *(long *)b;
00122 }
00123 #endif
00124
00125
00126
00127
00128
00129 static int history_put(jitterbuf *jb, long ts, long now, long ms)
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
00136 if (ts <= 0)
00137 return 0;
00138
00139
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
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;
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
00166
00167
00168
00169
00170 if (!jb->hist_maxbuf_valid)
00171 return 0;
00172
00173
00174
00175 if (jb->hist_ptr < JB_HISTORY_SZ)
00176 goto invalidate;
00177
00178
00179 if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
00180 goto invalidate;
00181
00182
00183 if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
00184 goto invalidate;
00185
00186
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
00194
00195 return 0;
00196
00197
00198
00199 invalidate:
00200 jb->hist_maxbuf_valid = 0;
00201 return 0;
00202 }
00203
00204 static void history_calc_maxbuf(jitterbuf *jb)
00205 {
00206 int i,j;
00207
00208 if (jb->hist_ptr == 0)
00209 return;
00210
00211
00212
00213 for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) {
00214
00215
00216
00217
00218 jb->hist_maxbuf[i] = JB_LONGMIN;
00219 jb->hist_minbuf[i] = JB_LONGMAX;
00220 }
00221
00222
00223
00224
00225
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
00232 if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) {
00233
00234
00235 for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
00236
00237 if (toins > jb->hist_maxbuf[j]) {
00238
00239 memmove(jb->hist_maxbuf+j+1,jb->hist_maxbuf+j, (JB_HISTORY_MAXBUF_SZ-(j+1)) * sizeof(long));
00240
00241 jb->hist_maxbuf[j] = toins;
00242
00243 break;
00244 }
00245 }
00246 }
00247
00248
00249 if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) {
00250
00251
00252 for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
00253
00254 if (toins < jb->hist_minbuf[j]) {
00255
00256 memmove(jb->hist_minbuf+j+1,jb->hist_minbuf+j, (JB_HISTORY_MAXBUF_SZ-(j+1)) * sizeof(long));
00257
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 }
00280
00281 static void history_get(jitterbuf *jb)
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
00291 count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ;
00292
00293
00294 index = count * JB_HISTORY_DROPPCT / 100;
00295
00296
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
00313
00314
00315
00316
00317
00318
00319 jb->info.min = min;
00320 jb->info.jitter = jitter;
00321 }
00322
00323
00324 static int queue_put(jitterbuf *jb, void *data, int type, long ms, long ts)
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
00352
00353
00354
00355 if (!jb->frames) {
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
00368 jb->info.frames_ooo++;
00369
00370 jb->frames = frame;
00371 head = 1;
00372 } else {
00373 p = jb->frames;
00374
00375
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 }
00389
00390 static long queue_next(jitterbuf *jb)
00391 {
00392 if (jb->frames)
00393 return jb->frames->ts;
00394 else
00395 return -1;
00396 }
00397
00398 static long queue_last(jitterbuf *jb)
00399 {
00400 if (jb->frames)
00401 return jb->frames->prev->ts;
00402 else
00403 return -1;
00404 }
00405
00406 static jb_frame *_queue_get(jitterbuf *jb, long ts, int all)
00407 {
00408 jb_frame *frame;
00409 frame = jb->frames;
00410
00411 if (!frame)
00412 return NULL;
00413
00414
00415
00416 if (all || ts >= frame->ts) {
00417
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
00428 frame->next = jb->free;
00429 jb->free = frame;
00430
00431 jb->info.frames_cur--;
00432
00433
00434
00435 return frame;
00436 }
00437
00438 return NULL;
00439 }
00440
00441 static jb_frame *queue_get(jitterbuf *jb, long ts)
00442 {
00443 return _queue_get(jb,ts,0);
00444 }
00445
00446 static jb_frame *queue_getall(jitterbuf *jb)
00447 {
00448 return _queue_get(jb,0,1);
00449 }
00450
00451 #if 0
00452
00453 static void jb_dbginfo(jitterbuf *jb)
00454 {
00455 if (dbgf == NULL)
00456 return;
00457
00458 jb_dbg("\njb info: fin=%ld fout=%ld flate=%ld flost=%ld fdrop=%ld fcur=%ld\n",
00459 jb->info.frames_in, jb->info.frames_out, jb->info.frames_late, jb->info.frames_lost, jb->info.frames_dropped, jb->info.frames_cur);
00460
00461 jb_dbg("jitter=%ld current=%ld target=%ld min=%ld sil=%d len=%d len/fcur=%ld\n",
00462 jb->info.jitter, jb->info.current, jb->info.target, jb->info.min, jb->info.silence_begin_ts, jb->info.current - jb->info.min,
00463 jb->info.frames_cur ? (jb->info.current - jb->info.min)/jb->info.frames_cur : -8);
00464 if (jb->info.frames_in > 0)
00465 jb_dbg("jb info: Loss PCT = %ld%%, Late PCT = %ld%%\n",
00466 jb->info.frames_lost * 100/(jb->info.frames_in + jb->info.frames_lost),
00467 jb->info.frames_late * 100/jb->info.frames_in);
00468 jb_dbg("jb info: queue %d -> %d. last_ts %d (queue len: %d) last_ms %d\n",
00469 queue_next(jb),
00470 queue_last(jb),
00471 jb->info.next_voice_ts,
00472 queue_last(jb) - queue_next(jb),
00473 jb->info.last_voice_ms);
00474 }
00475 #endif
00476
00477 #ifdef DEEP_DEBUG
00478 static void jb_chkqueue(jitterbuf *jb)
00479 {
00480 int i=0;
00481 jb_frame *p = jb->frames;
00482
00483 if (!p) {
00484 return;
00485 }
00486
00487 do {
00488 if (p->next == NULL) {
00489 jb_err("Queue is BROKEN at item [%d]", i);
00490 }
00491 i++;
00492 p=p->next;
00493 } while (p->next != jb->frames);
00494 }
00495
00496 static void jb_dbgqueue(jitterbuf *jb)
00497 {
00498 int i=0;
00499 jb_frame *p = jb->frames;
00500
00501 jb_dbg("queue: ");
00502
00503 if (!p) {
00504 jb_dbg("EMPTY\n");
00505 return;
00506 }
00507
00508 do {
00509 jb_dbg("[%d]=%ld ", i++, p->ts);
00510 p=p->next;
00511 } while (p->next != jb->frames);
00512
00513 jb_dbg("\n");
00514 }
00515 #endif
00516
00517 int jb_put(jitterbuf *jb, void *data, int type, long ms, long ts, long now)
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
00525
00526 if (history_put(jb,ts,now,ms))
00527 return JB_DROP;
00528 }
00529
00530
00531 if (queue_put(jb,data,type,ms,ts)) {
00532 return JB_SCHED;
00533 }
00534 return JB_OK;
00535 }
00536
00537
00538 static int _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
00539 {
00540 jb_frame *frame;
00541 long diff;
00542 static int dbg_cnt = 0;
00543
00544
00545
00546 history_get(jb);
00547
00548 if (dbg_cnt && dbg_cnt % 50 == 0) {
00549 jb_dbg("\n");
00550 }
00551 dbg_cnt++;
00552
00553
00554 jb->info.target = jb->info.jitter + jb->info.min + JB_TARGET_EXTRA;
00555
00556
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
00565
00566
00567
00568 if (!jb->info.silence_begin_ts) {
00569
00570 if ((diff > 0) &&
00571
00572 (((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) ||
00573
00574 (diff > queue_last(jb) - queue_next(jb)) ) ) {
00575
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
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
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
00608
00609 *frameout = *frame;
00610
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
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
00626
00627 return JB_DROP;
00628 }
00629 }
00630
00631
00632 if (frame && frame->ms > 0) {
00633 jb->info.last_voice_ms = frame->ms;
00634 }
00635
00636
00637
00638
00639
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
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
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
00667 if (!frame) {
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
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
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
00711
00712
00713
00714
00715
00716
00717
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
00729 *frameout = *frame;
00730 jb->info.frames_out++;
00731 return JB_OK;
00732 }
00733 if (frame->ts < jb->info.silence_begin_ts) {
00734
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
00742
00743 return JB_DROP;
00744 } else {
00745
00746
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 }
00759
00760 long jb_next(jitterbuf *jb)
00761 {
00762 if (jb->info.silence_begin_ts) {
00763 long next = queue_next(jb);
00764 if (next > 0) {
00765 history_get(jb);
00766
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 }
00777
00778 int jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
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 }
00793
00794 int jb_getall(jitterbuf *jb, jb_frame *frameout)
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 }
00806
00807
00808 int jb_getinfo(jitterbuf *jb, jb_info *stats)
00809 {
00810
00811 history_get(jb);
00812
00813 *stats = jb->info;
00814
00815 return JB_OK;
00816 }
00817
00818 int jb_setconf(jitterbuf *jb, jb_conf *conf)
00819 {
00820
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 }
00828
00829