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
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 174583 $")
00033
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <sys/types.h>
00038
00039 #include "jitterbuf.h"
00040 #include "asterisk/utils.h"
00041
00042
00043 #define JB_LONGMAX 2147483647L
00044 #define JB_LONGMIN (-JB_LONGMAX - 1L)
00045
00046 #define jb_warn(...) (warnf ? warnf(__VA_ARGS__) : (void)0)
00047 #define jb_err(...) (errf ? errf(__VA_ARGS__) : (void)0)
00048 #define jb_dbg(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
00049
00050 #ifdef DEEP_DEBUG
00051 #define jb_dbg2(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
00052 #else
00053 #define jb_dbg2(...) ((void)0)
00054 #endif
00055
00056 static jb_output_function_t warnf, errf, dbgf;
00057
00058 void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg)
00059 {
00060 errf = err;
00061 warnf = warn;
00062 dbgf = dbg;
00063 }
00064
00065 static void increment_losspct(jitterbuf *jb)
00066 {
00067 jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;
00068 }
00069
00070 static void decrement_losspct(jitterbuf *jb)
00071 {
00072 jb->info.losspct = (499 * jb->info.losspct)/500;
00073 }
00074
00075 void jb_reset(jitterbuf *jb)
00076 {
00077
00078 jb_conf s = jb->info.conf;
00079 memset(jb, 0, sizeof(*jb));
00080 jb->info.conf = s;
00081
00082
00083 jb->info.current = jb->info.target = JB_TARGET_EXTRA;
00084 jb->info.silence_begin_ts = -1;
00085 }
00086
00087 jitterbuf * jb_new()
00088 {
00089 jitterbuf *jb;
00090
00091 if (!(jb = ast_malloc(sizeof(*jb))))
00092 return NULL;
00093
00094 jb_reset(jb);
00095
00096 jb_dbg2("jb_new() = %x\n", jb);
00097 return jb;
00098 }
00099
00100 void jb_destroy(jitterbuf *jb)
00101 {
00102 jb_frame *frame;
00103 jb_dbg2("jb_destroy(%x)\n", jb);
00104
00105
00106 frame = jb->free;
00107 while (frame != NULL) {
00108 jb_frame *next = frame->next;
00109 free(frame);
00110 frame = next;
00111 }
00112
00113
00114 free(jb);
00115 }
00116
00117
00118
00119 #if 0
00120 static int longcmp(const void *a, const void *b)
00121 {
00122 return *(long *)a - *(long *)b;
00123 }
00124 #endif
00125
00126
00127
00128
00129
00130 static int history_put(jitterbuf *jb, long ts, long now, long ms)
00131 {
00132 long delay = now - (ts - jb->info.resync_offset);
00133 long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold;
00134 long kicked;
00135
00136
00137 if (ts <= 0)
00138 return 0;
00139
00140
00141 if (jb->info.conf.resync_threshold != -1) {
00142 if (abs(delay - jb->info.last_delay) > threshold) {
00143 jb->info.cnt_delay_discont++;
00144 if (jb->info.cnt_delay_discont > 3) {
00145
00146 jb->info.cnt_delay_discont = 0;
00147 jb->hist_ptr = 0;
00148 jb->hist_maxbuf_valid = 0;
00149
00150 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);
00151 jb->info.resync_offset = ts - now;
00152 jb->info.last_delay = delay = 0;
00153 } else {
00154 return -1;
00155 }
00156 } else {
00157 jb->info.last_delay = delay;
00158 jb->info.cnt_delay_discont = 0;
00159 }
00160 }
00161
00162 kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ];
00163
00164 jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay;
00165
00166
00167
00168
00169
00170
00171 if (!jb->hist_maxbuf_valid)
00172 return 0;
00173
00174
00175
00176 if (jb->hist_ptr < JB_HISTORY_SZ)
00177 goto invalidate;
00178
00179
00180 if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
00181 goto invalidate;
00182
00183
00184 if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
00185 goto invalidate;
00186
00187
00188 if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
00189 goto invalidate;
00190
00191 if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
00192 goto invalidate;
00193
00194
00195
00196 return 0;
00197
00198
00199
00200 invalidate:
00201 jb->hist_maxbuf_valid = 0;
00202 return 0;
00203 }
00204
00205 static void history_calc_maxbuf(jitterbuf *jb)
00206 {
00207 int i,j;
00208
00209 if (jb->hist_ptr == 0)
00210 return;
00211
00212
00213
00214 for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) {
00215
00216
00217
00218
00219 jb->hist_maxbuf[i] = JB_LONGMIN;
00220 jb->hist_minbuf[i] = JB_LONGMAX;
00221 }
00222
00223
00224
00225
00226
00227 i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0;
00228
00229 for (;i<jb->hist_ptr;i++) {
00230 long toins = jb->history[i % JB_HISTORY_SZ];
00231
00232
00233 if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) {
00234
00235
00236 for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
00237
00238 if (toins > jb->hist_maxbuf[j]) {
00239
00240 memmove(jb->hist_maxbuf + j + 1, jb->hist_maxbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_maxbuf[0]));
00241
00242 jb->hist_maxbuf[j] = toins;
00243
00244 break;
00245 }
00246 }
00247 }
00248
00249
00250 if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) {
00251
00252
00253 for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
00254
00255 if (toins < jb->hist_minbuf[j]) {
00256
00257 memmove(jb->hist_minbuf + j + 1, jb->hist_minbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_minbuf[0]));
00258
00259 jb->hist_minbuf[j] = toins;
00260
00261 break;
00262 }
00263 }
00264 }
00265
00266 if (0) {
00267 int k;
00268 fprintf(stderr, "toins = %ld\n", toins);
00269 fprintf(stderr, "maxbuf =");
00270 for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
00271 fprintf(stderr, "%ld ", jb->hist_maxbuf[k]);
00272 fprintf(stderr, "\nminbuf =");
00273 for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
00274 fprintf(stderr, "%ld ", jb->hist_minbuf[k]);
00275 fprintf(stderr, "\n");
00276 }
00277 }
00278
00279 jb->hist_maxbuf_valid = 1;
00280 }
00281
00282 static void history_get(jitterbuf *jb)
00283 {
00284 long max, min, jitter;
00285 int index;
00286 int count;
00287
00288 if (!jb->hist_maxbuf_valid)
00289 history_calc_maxbuf(jb);
00290
00291
00292 count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ;
00293
00294
00295 index = count * JB_HISTORY_DROPPCT / 100;
00296
00297
00298 if (index > (JB_HISTORY_MAXBUF_SZ - 1))
00299 index = JB_HISTORY_MAXBUF_SZ - 1;
00300
00301
00302 if (index < 0) {
00303 jb->info.min = 0;
00304 jb->info.jitter = 0;
00305 return;
00306 }
00307
00308 max = jb->hist_maxbuf[index];
00309 min = jb->hist_minbuf[index];
00310
00311 jitter = max - min;
00312
00313
00314
00315
00316
00317
00318
00319
00320 jb->info.min = min;
00321 jb->info.jitter = jitter;
00322 }
00323
00324
00325 static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts)
00326 {
00327 jb_frame *frame;
00328 jb_frame *p;
00329 int head = 0;
00330 long resync_ts = ts - jb->info.resync_offset;
00331
00332 if ((frame = jb->free)) {
00333 jb->free = frame->next;
00334 } else if (!(frame = ast_malloc(sizeof(*frame)))) {
00335 jb_err("cannot allocate frame\n");
00336 return 0;
00337 }
00338
00339 jb->info.frames_cur++;
00340
00341 frame->data = data;
00342 frame->ts = resync_ts;
00343 frame->ms = ms;
00344 frame->type = type;
00345
00346
00347
00348
00349
00350
00351 if (!jb->frames) {
00352 jb->frames = frame;
00353 frame->next = frame;
00354 frame->prev = frame;
00355 head = 1;
00356 } else if (resync_ts < jb->frames->ts) {
00357 frame->next = jb->frames;
00358 frame->prev = jb->frames->prev;
00359
00360 frame->next->prev = frame;
00361 frame->prev->next = frame;
00362
00363
00364 jb->info.frames_ooo++;
00365
00366 jb->frames = frame;
00367 head = 1;
00368 } else {
00369 p = jb->frames;
00370
00371
00372 if (resync_ts < p->prev->ts) jb->info.frames_ooo++;
00373
00374 while (resync_ts < p->prev->ts && p->prev != jb->frames)
00375 p = p->prev;
00376
00377 frame->next = p;
00378 frame->prev = p->prev;
00379
00380 frame->next->prev = frame;
00381 frame->prev->next = frame;
00382 }
00383 return head;
00384 }
00385
00386 static long queue_next(jitterbuf *jb)
00387 {
00388 if (jb->frames)
00389 return jb->frames->ts;
00390 else
00391 return -1;
00392 }
00393
00394 static long queue_last(jitterbuf *jb)
00395 {
00396 if (jb->frames)
00397 return jb->frames->prev->ts;
00398 else
00399 return -1;
00400 }
00401
00402 static jb_frame *_queue_get(jitterbuf *jb, long ts, int all)
00403 {
00404 jb_frame *frame;
00405 frame = jb->frames;
00406
00407 if (!frame)
00408 return NULL;
00409
00410
00411
00412 if (all || ts >= frame->ts) {
00413
00414 frame->prev->next = frame->next;
00415 frame->next->prev = frame->prev;
00416
00417 if (frame->next == frame)
00418 jb->frames = NULL;
00419 else
00420 jb->frames = frame->next;
00421
00422
00423
00424 frame->next = jb->free;
00425 jb->free = frame;
00426
00427 jb->info.frames_cur--;
00428
00429
00430
00431 return frame;
00432 }
00433
00434 return NULL;
00435 }
00436
00437 static jb_frame *queue_get(jitterbuf *jb, long ts)
00438 {
00439 return _queue_get(jb,ts,0);
00440 }
00441
00442 static jb_frame *queue_getall(jitterbuf *jb)
00443 {
00444 return _queue_get(jb,0,1);
00445 }
00446
00447 #if 0
00448
00449 static void jb_dbginfo(jitterbuf *jb)
00450 {
00451 if (dbgf == NULL)
00452 return;
00453
00454 jb_dbg("\njb info: fin=%ld fout=%ld flate=%ld flost=%ld fdrop=%ld fcur=%ld\n",
00455 jb->info.frames_in, jb->info.frames_out, jb->info.frames_late, jb->info.frames_lost, jb->info.frames_dropped, jb->info.frames_cur);
00456
00457 jb_dbg("jitter=%ld current=%ld target=%ld min=%ld sil=%d len=%d len/fcur=%ld\n",
00458 jb->info.jitter, jb->info.current, jb->info.target, jb->info.min, jb->info.silence_begin_ts, jb->info.current - jb->info.min,
00459 jb->info.frames_cur ? (jb->info.current - jb->info.min)/jb->info.frames_cur : -8);
00460 if (jb->info.frames_in > 0)
00461 jb_dbg("jb info: Loss PCT = %ld%%, Late PCT = %ld%%\n",
00462 jb->info.frames_lost * 100/(jb->info.frames_in + jb->info.frames_lost),
00463 jb->info.frames_late * 100/jb->info.frames_in);
00464 jb_dbg("jb info: queue %d -> %d. last_ts %d (queue len: %d) last_ms %d\n",
00465 queue_next(jb),
00466 queue_last(jb),
00467 jb->info.next_voice_ts,
00468 queue_last(jb) - queue_next(jb),
00469 jb->info.last_voice_ms);
00470 }
00471 #endif
00472
00473 #ifdef DEEP_DEBUG
00474 static void jb_chkqueue(jitterbuf *jb)
00475 {
00476 int i=0;
00477 jb_frame *p = jb->frames;
00478
00479 if (!p) {
00480 return;
00481 }
00482
00483 do {
00484 if (p->next == NULL) {
00485 jb_err("Queue is BROKEN at item [%d]", i);
00486 }
00487 i++;
00488 p=p->next;
00489 } while (p->next != jb->frames);
00490 }
00491
00492 static void jb_dbgqueue(jitterbuf *jb)
00493 {
00494 int i=0;
00495 jb_frame *p = jb->frames;
00496
00497 jb_dbg("queue: ");
00498
00499 if (!p) {
00500 jb_dbg("EMPTY\n");
00501 return;
00502 }
00503
00504 do {
00505 jb_dbg("[%d]=%ld ", i++, p->ts);
00506 p=p->next;
00507 } while (p->next != jb->frames);
00508
00509 jb_dbg("\n");
00510 }
00511 #endif
00512
00513 enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now)
00514 {
00515 long numts;
00516
00517 jb_dbg2("jb_put(%x,%x,%ld,%ld,%ld)\n", jb, data, ms, ts, now);
00518
00519 numts = 0;
00520 if (jb->frames)
00521 numts = jb->frames->prev->ts - jb->frames->ts;
00522
00523 if (numts >= jb->info.conf.max_jitterbuf) {
00524 if (!jb->dropem) {
00525 ast_log(LOG_DEBUG, "Attempting to exceed Jitterbuf max %ld timeslots\n",
00526 jb->info.conf.max_jitterbuf);
00527 jb->dropem = 1;
00528 }
00529 jb->info.frames_dropped++;
00530 return JB_DROP;
00531 } else {
00532 jb->dropem = 0;
00533 }
00534
00535 if (type == JB_TYPE_VOICE) {
00536
00537
00538 if (history_put(jb,ts,now,ms)) {
00539 jb->info.frames_dropped++;
00540 return JB_DROP;
00541 }
00542 }
00543
00544 jb->info.frames_in++;
00545
00546
00547 if (queue_put(jb,data,type,ms,ts)) {
00548 return JB_SCHED;
00549 }
00550 return JB_OK;
00551 }
00552
00553
00554 static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
00555 {
00556 jb_frame *frame;
00557 long diff;
00558 static int dbg_cnt = 0;
00559
00560
00561
00562 history_get(jb);
00563
00564 if (dbg_cnt && dbg_cnt % 50 == 0) {
00565 jb_dbg("\n");
00566 }
00567 dbg_cnt++;
00568
00569
00570 jb->info.target = jb->info.jitter + jb->info.min + JB_TARGET_EXTRA;
00571
00572
00573 if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) {
00574 jb_dbg("clamping target from %ld to %ld\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf);
00575 jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf;
00576 }
00577
00578 diff = jb->info.target - jb->info.current;
00579
00580
00581
00582
00583
00584 if (!jb->info.silence_begin_ts) {
00585
00586 if ((diff > 0) &&
00587
00588 (((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) ||
00589
00590 (diff > queue_last(jb) - queue_next(jb)) ) ) {
00591
00592 jb->info.current += interpl;
00593 jb->info.next_voice_ts += interpl;
00594 jb->info.last_voice_ms = interpl;
00595 jb->info.last_adjustment = now;
00596 jb->info.cnt_contig_interp++;
00597 if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
00598 jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
00599 }
00600 jb_dbg("G");
00601 return JB_INTERP;
00602 }
00603
00604 frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current);
00605
00606
00607 if (frame && frame->type != JB_TYPE_VOICE) {
00608 if (frame->type == JB_TYPE_SILENCE) {
00609 jb->info.silence_begin_ts = frame->ts;
00610 jb->info.cnt_contig_interp = 0;
00611 }
00612
00613 *frameout = *frame;
00614 jb->info.frames_out++;
00615 jb_dbg("o");
00616 return JB_OK;
00617 }
00618
00619
00620
00621 if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) {
00622 if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) {
00623
00624
00625 *frameout = *frame;
00626
00627 jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
00628 jb->info.frames_out++;
00629 decrement_losspct(jb);
00630 jb->info.cnt_contig_interp = 0;
00631 jb_dbg("v");
00632 return JB_OK;
00633 } else {
00634
00635 *frameout = *frame;
00636 jb->info.frames_out++;
00637 decrement_losspct(jb);
00638 jb->info.frames_late++;
00639 jb->info.frames_lost--;
00640 jb_dbg("l");
00641
00642
00643 return JB_DROP;
00644 }
00645 }
00646
00647
00648 if (frame && frame->ms > 0) {
00649 jb->info.last_voice_ms = frame->ms;
00650 }
00651
00652
00653
00654
00655
00656 if (diff < -JB_TARGET_EXTRA &&
00657 ((!frame && jb->info.last_adjustment + 80 < now) ||
00658 (jb->info.last_adjustment + 500 < now))) {
00659
00660 jb->info.last_adjustment = now;
00661 jb->info.cnt_contig_interp = 0;
00662
00663 if (frame) {
00664 *frameout = *frame;
00665
00666 jb->info.current -= frame->ms;
00667 jb->info.frames_out++;
00668 decrement_losspct(jb);
00669 jb->info.frames_dropped++;
00670 jb_dbg("s");
00671 return JB_DROP;
00672 } else {
00673
00674 jb->info.current -= jb->info.last_voice_ms;
00675 jb->info.frames_lost++;
00676 increment_losspct(jb);
00677 jb_dbg("S");
00678 return JB_NOFRAME;
00679 }
00680 }
00681
00682
00683 if (!frame) {
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 jb->info.frames_lost++;
00706 increment_losspct(jb);
00707 jb->info.next_voice_ts += interpl;
00708 jb->info.last_voice_ms = interpl;
00709 jb->info.cnt_contig_interp++;
00710 if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
00711 jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
00712 }
00713 jb_dbg("L");
00714 return JB_INTERP;
00715 }
00716
00717
00718 *frameout = *frame;
00719 jb->info.next_voice_ts += frame->ms;
00720 jb->info.frames_out++;
00721 jb->info.cnt_contig_interp = 0;
00722 decrement_losspct(jb);
00723 jb_dbg("v");
00724 return JB_OK;
00725 } else {
00726
00727
00728
00729
00730
00731
00732
00733
00734 if (diff < -JB_TARGET_EXTRA &&
00735 jb->info.last_adjustment + 10 <= now) {
00736 jb->info.current -= interpl;
00737 jb->info.last_adjustment = now;
00738 }
00739
00740 frame = queue_get(jb, now - jb->info.current);
00741 if (!frame) {
00742 return JB_NOFRAME;
00743 } else if (frame->type != JB_TYPE_VOICE) {
00744
00745 *frameout = *frame;
00746 jb->info.frames_out++;
00747 return JB_OK;
00748 }
00749 if (frame->ts < jb->info.silence_begin_ts) {
00750
00751 *frameout = *frame;
00752 jb->info.frames_out++;
00753 decrement_losspct(jb);
00754 jb->info.frames_late++;
00755 jb->info.frames_lost--;
00756 jb_dbg("l");
00757
00758
00759 return JB_DROP;
00760 } else {
00761
00762
00763 jb->info.current = jb->info.target;
00764 jb->info.silence_begin_ts = 0;
00765 jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
00766 jb->info.last_voice_ms = frame->ms;
00767 jb->info.frames_out++;
00768 decrement_losspct(jb);
00769 *frameout = *frame;
00770 jb_dbg("V");
00771 return JB_OK;
00772 }
00773 }
00774 }
00775
00776 long jb_next(jitterbuf *jb)
00777 {
00778 if (jb->info.silence_begin_ts) {
00779 if (jb->frames) {
00780 long next = queue_next(jb);
00781 history_get(jb);
00782
00783 if (jb->info.target - jb->info.current < -JB_TARGET_EXTRA)
00784 return jb->info.last_adjustment + 10;
00785 return next + jb->info.target;
00786 }
00787 else
00788 return JB_LONGMAX;
00789 } else {
00790 return jb->info.next_voice_ts;
00791 }
00792 }
00793
00794 enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
00795 {
00796 enum jb_return_code ret = _jb_get(jb, frameout, now, interpl);
00797 #if 0
00798 static int lastts=0;
00799 int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0;
00800 jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists);
00801 if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n");
00802 lastts = thists;
00803 #endif
00804 if(ret == JB_INTERP)
00805 frameout->ms = jb->info.last_voice_ms;
00806
00807 return ret;
00808 }
00809
00810 enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
00811 {
00812 jb_frame *frame;
00813 frame = queue_getall(jb);
00814
00815 if (!frame) {
00816 return JB_NOFRAME;
00817 }
00818
00819 *frameout = *frame;
00820 return JB_OK;
00821 }
00822
00823
00824 enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats)
00825 {
00826
00827 history_get(jb);
00828
00829 *stats = jb->info;
00830
00831 return JB_OK;
00832 }
00833
00834 enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
00835 {
00836
00837
00838 jb->info.conf.max_jitterbuf = conf->max_jitterbuf;
00839 jb->info.conf.resync_threshold = conf->resync_threshold;
00840 jb->info.conf.max_contig_interp = conf->max_contig_interp;
00841
00842 return JB_OK;
00843 }
00844
00845