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: 135841 $")
00033
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036
00037 #include "asterisk/frame.h"
00038 #include "asterisk/channel.h"
00039 #include "asterisk/logger.h"
00040 #include "asterisk/term.h"
00041 #include "asterisk/options.h"
00042 #include "asterisk/utils.h"
00043
00044 #include "asterisk/abstract_jb.h"
00045 #include "fixedjitterbuf.h"
00046 #include "jitterbuf.h"
00047
00048
00049 enum {
00050 JB_USE = (1 << 0),
00051 JB_TIMEBASE_INITIALIZED = (1 << 1),
00052 JB_CREATED = (1 << 2)
00053 };
00054
00055
00056
00057
00058 typedef void * (*jb_create_impl)(struct ast_jb_conf *general_config, long resynch_threshold);
00059
00060 typedef void (*jb_destroy_impl)(void *jb);
00061
00062 typedef int (*jb_put_first_impl)(void *jb, struct ast_frame *fin, long now);
00063
00064 typedef int (*jb_put_impl)(void *jb, struct ast_frame *fin, long now);
00065
00066 typedef int (*jb_get_impl)(void *jb, struct ast_frame **fout, long now, long interpl);
00067
00068 typedef long (*jb_next_impl)(void *jb);
00069
00070 typedef int (*jb_remove_impl)(void *jb, struct ast_frame **fout);
00071
00072 typedef void (*jb_force_resynch_impl)(void *jb);
00073
00074 typedef void (*jb_empty_and_reset_impl)(void *jb);
00075
00076
00077
00078
00079 struct ast_jb_impl
00080 {
00081 char name[AST_JB_IMPL_NAME_SIZE];
00082 jb_create_impl create;
00083 jb_destroy_impl destroy;
00084 jb_put_first_impl put_first;
00085 jb_put_impl put;
00086 jb_get_impl get;
00087 jb_next_impl next;
00088 jb_remove_impl remove;
00089 jb_force_resynch_impl force_resync;
00090 jb_empty_and_reset_impl empty_and_reset;
00091 };
00092
00093
00094
00095 static void * jb_create_fixed(struct ast_jb_conf *general_config, long resynch_threshold);
00096 static void jb_destroy_fixed(void *jb);
00097 static int jb_put_first_fixed(void *jb, struct ast_frame *fin, long now);
00098 static int jb_put_fixed(void *jb, struct ast_frame *fin, long now);
00099 static int jb_get_fixed(void *jb, struct ast_frame **fout, long now, long interpl);
00100 static long jb_next_fixed(void *jb);
00101 static int jb_remove_fixed(void *jb, struct ast_frame **fout);
00102 static void jb_force_resynch_fixed(void *jb);
00103 static void jb_empty_and_reset_fixed(void *jb);
00104
00105 static void * jb_create_adaptive(struct ast_jb_conf *general_config, long resynch_threshold);
00106 static void jb_destroy_adaptive(void *jb);
00107 static int jb_put_first_adaptive(void *jb, struct ast_frame *fin, long now);
00108 static int jb_put_adaptive(void *jb, struct ast_frame *fin, long now);
00109 static int jb_get_adaptive(void *jb, struct ast_frame **fout, long now, long interpl);
00110 static long jb_next_adaptive(void *jb);
00111 static int jb_remove_adaptive(void *jb, struct ast_frame **fout);
00112 static void jb_force_resynch_adaptive(void *jb);
00113 static void jb_empty_and_reset_adaptive(void *jb);
00114
00115
00116 static struct ast_jb_impl avail_impl[] =
00117 {
00118 {
00119 .name = "fixed",
00120 .create = jb_create_fixed,
00121 .destroy = jb_destroy_fixed,
00122 .put_first = jb_put_first_fixed,
00123 .put = jb_put_fixed,
00124 .get = jb_get_fixed,
00125 .next = jb_next_fixed,
00126 .remove = jb_remove_fixed,
00127 .force_resync = jb_force_resynch_fixed,
00128 .empty_and_reset = jb_empty_and_reset_fixed,
00129 },
00130 {
00131 .name = "adaptive",
00132 .create = jb_create_adaptive,
00133 .destroy = jb_destroy_adaptive,
00134 .put_first = jb_put_first_adaptive,
00135 .put = jb_put_adaptive,
00136 .get = jb_get_adaptive,
00137 .next = jb_next_adaptive,
00138 .remove = jb_remove_adaptive,
00139 .force_resync = jb_force_resynch_adaptive,
00140 .empty_and_reset = jb_empty_and_reset_adaptive,
00141 }
00142 };
00143
00144 static int default_impl = 0;
00145
00146
00147
00148 enum {
00149 JB_IMPL_OK,
00150 JB_IMPL_DROP,
00151 JB_IMPL_INTERP,
00152 JB_IMPL_NOFRAME
00153 };
00154
00155
00156 static int fixed_to_abstract_code[] =
00157 {JB_IMPL_OK, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME};
00158 static int adaptive_to_abstract_code[] =
00159 {JB_IMPL_OK, JB_IMPL_NOFRAME, JB_IMPL_NOFRAME, JB_IMPL_INTERP, JB_IMPL_DROP, JB_IMPL_OK};
00160
00161
00162 static char *jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"};
00163
00164
00165 #define jb_framelog(...) do { \
00166 if (jb->logfile) { \
00167 fprintf(jb->logfile, __VA_ARGS__); \
00168 fflush(jb->logfile); \
00169 } \
00170 } while (0)
00171
00172
00173
00174 static void jb_choose_impl(struct ast_channel *chan);
00175 static void jb_get_and_deliver(struct ast_channel *chan);
00176 static int create_jb(struct ast_channel *chan, struct ast_frame *first_frame);
00177 static long get_now(struct ast_jb *jb, struct timeval *tv);
00178
00179
00180
00181
00182
00183 static void jb_choose_impl(struct ast_channel *chan)
00184 {
00185 struct ast_jb *jb = &chan->jb;
00186 struct ast_jb_conf *jbconf = &jb->conf;
00187 struct ast_jb_impl *test_impl;
00188 int i, avail_impl_count = sizeof(avail_impl) / sizeof(avail_impl[0]);
00189
00190 jb->impl = &avail_impl[default_impl];
00191
00192 if (ast_strlen_zero(jbconf->impl))
00193 return;
00194
00195 for (i = 0; i < avail_impl_count; i++) {
00196 test_impl = &avail_impl[i];
00197 if (!strcasecmp(jbconf->impl, test_impl->name)) {
00198 jb->impl = test_impl;
00199 return;
00200 }
00201 }
00202 }
00203
00204 int ast_jb_do_usecheck(struct ast_channel *c0, struct ast_channel *c1)
00205 {
00206 struct ast_jb *jb0 = &c0->jb;
00207 struct ast_jb *jb1 = &c1->jb;
00208 struct ast_jb_conf *conf0 = &jb0->conf;
00209 struct ast_jb_conf *conf1 = &jb1->conf;
00210 int c0_wants_jitter = c0->tech->properties & AST_CHAN_TP_WANTSJITTER;
00211 int c0_creates_jitter = c0->tech->properties & AST_CHAN_TP_CREATESJITTER;
00212 int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED);
00213 int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED);
00214 int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED);
00215 int c0_jb_created = ast_test_flag(jb0, JB_CREATED);
00216 int c1_wants_jitter = c1->tech->properties & AST_CHAN_TP_WANTSJITTER;
00217 int c1_creates_jitter = c1->tech->properties & AST_CHAN_TP_CREATESJITTER;
00218 int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED);
00219 int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED);
00220 int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED);
00221 int c1_jb_created = ast_test_flag(jb1, JB_CREATED);
00222 int inuse = 0;
00223
00224
00225 if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) {
00226 ast_set_flag(jb0, JB_USE);
00227 if (!c0_jb_timebase_initialized) {
00228 if (c1_jb_timebase_initialized) {
00229 memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval));
00230 } else {
00231 gettimeofday(&jb0->timebase, NULL);
00232 }
00233 ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED);
00234 }
00235
00236 if (!c0_jb_created) {
00237 jb_choose_impl(c0);
00238 }
00239
00240 inuse = 1;
00241 }
00242
00243
00244 if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) {
00245 ast_set_flag(jb1, JB_USE);
00246 if (!c1_jb_timebase_initialized) {
00247 if (c0_jb_timebase_initialized) {
00248 memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval));
00249 } else {
00250 gettimeofday(&jb1->timebase, NULL);
00251 }
00252 ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED);
00253 }
00254
00255 if (!c1_jb_created) {
00256 jb_choose_impl(c1);
00257 }
00258
00259 inuse = 1;
00260 }
00261
00262 return inuse;
00263 }
00264
00265 int ast_jb_get_when_to_wakeup(struct ast_channel *c0, struct ast_channel *c1, int time_left)
00266 {
00267 struct ast_jb *jb0 = &c0->jb;
00268 struct ast_jb *jb1 = &c1->jb;
00269 int c0_use_jb = ast_test_flag(jb0, JB_USE);
00270 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00271 int c1_use_jb = ast_test_flag(jb1, JB_USE);
00272 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00273 int wait, wait0, wait1;
00274 struct timeval tv_now;
00275
00276 if (time_left == 0) {
00277
00278
00279
00280 }
00281
00282 if (time_left < 0) {
00283 time_left = INT_MAX;
00284 }
00285
00286 gettimeofday(&tv_now, NULL);
00287
00288 wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left;
00289 wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left;
00290
00291 wait = wait0 < wait1 ? wait0 : wait1;
00292 wait = wait < time_left ? wait : time_left;
00293
00294 if (wait == INT_MAX) {
00295 wait = -1;
00296 } else if (wait < 1) {
00297
00298 wait = 1;
00299 }
00300
00301 return wait;
00302 }
00303
00304
00305 int ast_jb_put(struct ast_channel *chan, struct ast_frame *f)
00306 {
00307 struct ast_jb *jb = &chan->jb;
00308 struct ast_jb_impl *jbimpl = jb->impl;
00309 void *jbobj = jb->jbobj;
00310 struct ast_frame *frr;
00311 long now = 0;
00312
00313 if (!ast_test_flag(jb, JB_USE))
00314 return -1;
00315
00316 if (f->frametype != AST_FRAME_VOICE) {
00317 if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) {
00318 jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now);
00319 jbimpl->force_resync(jbobj);
00320 }
00321
00322 return -1;
00323 }
00324
00325
00326 if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) {
00327 ast_log(LOG_WARNING, "%s recieved frame with invalid timing info: "
00328 "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n",
00329 chan->name, ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO), f->len, f->ts, f->src);
00330 return -1;
00331 }
00332
00333 frr = ast_frdup(f);
00334
00335 if (!frr) {
00336 ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan->name);
00337 return -1;
00338 }
00339
00340 if (!ast_test_flag(jb, JB_CREATED)) {
00341 if (create_jb(chan, frr)) {
00342 ast_frfree(frr);
00343
00344 ast_clear_flag(jb, JB_USE);
00345 return -1;
00346 }
00347
00348 ast_set_flag(jb, JB_CREATED);
00349 return 0;
00350 } else {
00351 now = get_now(jb, NULL);
00352 if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) {
00353 jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
00354 ast_frfree(frr);
00355
00356
00357
00358 return 0;
00359 }
00360
00361 jb->next = jbimpl->next(jbobj);
00362
00363 jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
00364
00365 return 0;
00366 }
00367 }
00368
00369
00370 void ast_jb_get_and_deliver(struct ast_channel *c0, struct ast_channel *c1)
00371 {
00372 struct ast_jb *jb0 = &c0->jb;
00373 struct ast_jb *jb1 = &c1->jb;
00374 int c0_use_jb = ast_test_flag(jb0, JB_USE);
00375 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00376 int c1_use_jb = ast_test_flag(jb1, JB_USE);
00377 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00378
00379 if (c0_use_jb && c0_jb_is_created)
00380 jb_get_and_deliver(c0);
00381
00382 if (c1_use_jb && c1_jb_is_created)
00383 jb_get_and_deliver(c1);
00384 }
00385
00386
00387 static void jb_get_and_deliver(struct ast_channel *chan)
00388 {
00389 struct ast_jb *jb = &chan->jb;
00390 struct ast_jb_impl *jbimpl = jb->impl;
00391 void *jbobj = jb->jbobj;
00392 struct ast_frame *f, finterp;
00393 long now;
00394 int interpolation_len, res;
00395
00396 now = get_now(jb, NULL);
00397 jb->next = jbimpl->next(jbobj);
00398 if (now < jb->next) {
00399 jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next);
00400 return;
00401 }
00402
00403 while (now >= jb->next) {
00404 interpolation_len = ast_codec_interp_len(jb->last_format);
00405
00406 res = jbimpl->get(jbobj, &f, now, interpolation_len);
00407
00408 switch(res) {
00409 case JB_IMPL_OK:
00410
00411 ast_write(chan, f);
00412 case JB_IMPL_DROP:
00413 jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
00414 now, jb_get_actions[res], f->ts, f->len);
00415 jb->last_format = f->subclass;
00416 ast_frfree(f);
00417 break;
00418 case JB_IMPL_INTERP:
00419
00420 f = &finterp;
00421 f->frametype = AST_FRAME_VOICE;
00422 f->subclass = jb->last_format;
00423 f->datalen = 0;
00424 f->samples = interpolation_len * 8;
00425 f->mallocd = 0;
00426 f->src = "JB interpolation";
00427 f->data = NULL;
00428 f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000));
00429 f->offset = AST_FRIENDLY_OFFSET;
00430
00431 ast_write(chan, f);
00432 jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
00433 break;
00434 case JB_IMPL_NOFRAME:
00435 ast_log(LOG_WARNING,
00436 "JB_IMPL_NOFRAME is retuned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
00437 jbimpl->name, now, jb->next, jbimpl->next(jbobj));
00438 jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now);
00439 return;
00440 default:
00441 ast_log(LOG_ERROR, "This should never happen!\n");
00442 ast_assert("JB type unknown" == NULL);
00443 break;
00444 }
00445
00446 jb->next = jbimpl->next(jbobj);
00447 }
00448 }
00449
00450
00451 static int create_jb(struct ast_channel *chan, struct ast_frame *frr)
00452 {
00453 struct ast_jb *jb = &chan->jb;
00454 struct ast_jb_conf *jbconf = &jb->conf;
00455 struct ast_jb_impl *jbimpl = jb->impl;
00456 void *jbobj;
00457 struct ast_channel *bridged;
00458 long now;
00459 char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1];
00460 char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp;
00461 int res;
00462
00463 jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold);
00464 if (!jbobj) {
00465 ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name);
00466 return -1;
00467 }
00468
00469 now = get_now(jb, NULL);
00470 res = jbimpl->put_first(jbobj, frr, now);
00471
00472
00473
00474 if (res != JB_IMPL_OK) {
00475 ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name);
00476
00477
00478
00479
00480 }
00481
00482
00483 jb->next = jbimpl->next(jbobj);
00484
00485
00486 jb->last_format = frr->subclass;
00487
00488
00489 if (ast_test_flag(jbconf, AST_JB_LOG)) {
00490 snprintf(name2, sizeof(name2), "%s", chan->name);
00491 tmp = strchr(name2, '/');
00492 if (tmp)
00493 *tmp = '#';
00494
00495 bridged = ast_bridged_channel(chan);
00496
00497 ast_assert(bridged != NULL);
00498
00499 snprintf(name1, sizeof(name1), "%s", bridged->name);
00500 tmp = strchr(name1, '/');
00501 if (tmp)
00502 *tmp = '#';
00503
00504 snprintf(logfile_pathname, sizeof(logfile_pathname),
00505 "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2);
00506 jb->logfile = fopen(logfile_pathname, "w+b");
00507
00508 if (!jb->logfile)
00509 ast_log(LOG_WARNING, "Failed to create frame log file with pathname '%s'\n", logfile_pathname);
00510
00511 if (res == JB_IMPL_OK)
00512 jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
00513 now, frr->ts, frr->len);
00514 else
00515 jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
00516 now, frr->ts, frr->len);
00517 }
00518
00519 if (option_verbose > 2)
00520 ast_verbose(VERBOSE_PREFIX_3 "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name);
00521
00522
00523 if (res != JB_IMPL_OK)
00524 ast_frfree(frr);
00525
00526 return 0;
00527 }
00528
00529
00530 void ast_jb_destroy(struct ast_channel *chan)
00531 {
00532 struct ast_jb *jb = &chan->jb;
00533 struct ast_jb_impl *jbimpl = jb->impl;
00534 void *jbobj = jb->jbobj;
00535 struct ast_frame *f;
00536
00537 if (jb->logfile) {
00538 fclose(jb->logfile);
00539 jb->logfile = NULL;
00540 }
00541
00542 if (ast_test_flag(jb, JB_CREATED)) {
00543
00544 while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) {
00545 ast_frfree(f);
00546 }
00547
00548 jbimpl->destroy(jbobj);
00549 jb->jbobj = NULL;
00550
00551 ast_clear_flag(jb, JB_CREATED);
00552
00553 if (option_verbose > 2)
00554 ast_verbose(VERBOSE_PREFIX_3 "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name);
00555 }
00556 }
00557
00558
00559 static long get_now(struct ast_jb *jb, struct timeval *tv)
00560 {
00561 struct timeval now;
00562
00563 if (!tv) {
00564 tv = &now;
00565 gettimeofday(tv, NULL);
00566 }
00567
00568 return ast_tvdiff_ms(*tv, jb->timebase);
00569 }
00570
00571
00572 int ast_jb_read_conf(struct ast_jb_conf *conf, char *varname, char *value)
00573 {
00574 int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1;
00575 char *name;
00576 int tmp;
00577
00578 if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen))
00579 return -1;
00580
00581 name = varname + prefixlen;
00582
00583 if (!strcasecmp(name, AST_JB_CONF_ENABLE)) {
00584 ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED);
00585 } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) {
00586 ast_set2_flag(conf, ast_true(value), AST_JB_FORCED);
00587 } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) {
00588 if ((tmp = atoi(value)) > 0)
00589 conf->max_size = tmp;
00590 } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) {
00591 if ((tmp = atoi(value)) > 0)
00592 conf->resync_threshold = tmp;
00593 } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) {
00594 if (!ast_strlen_zero(value))
00595 snprintf(conf->impl, sizeof(conf->impl), "%s", value);
00596 } else if (!strcasecmp(name, AST_JB_CONF_LOG)) {
00597 ast_set2_flag(conf, ast_true(value), AST_JB_LOG);
00598 } else {
00599 return -1;
00600 }
00601
00602 return 0;
00603 }
00604
00605
00606 void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
00607 {
00608 memcpy(&chan->jb.conf, conf, sizeof(*conf));
00609 }
00610
00611
00612 void ast_jb_get_config(const struct ast_channel *chan, struct ast_jb_conf *conf)
00613 {
00614 memcpy(conf, &chan->jb.conf, sizeof(*conf));
00615 }
00616
00617 void ast_jb_empty_and_reset(struct ast_channel *c0, struct ast_channel *c1)
00618 {
00619 struct ast_jb *jb0 = &c0->jb;
00620 struct ast_jb *jb1 = &c1->jb;
00621 int c0_use_jb = ast_test_flag(jb0, JB_USE);
00622 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00623 int c1_use_jb = ast_test_flag(jb1, JB_USE);
00624 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00625
00626 if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) {
00627 jb0->impl->empty_and_reset(jb0->jbobj);
00628 }
00629
00630 if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) {
00631 jb1->impl->empty_and_reset(jb1->jbobj);
00632 }
00633 }
00634
00635
00636
00637
00638 static void * jb_create_fixed(struct ast_jb_conf *general_config, long resynch_threshold)
00639 {
00640 struct fixed_jb_conf conf;
00641
00642 conf.jbsize = general_config->max_size;
00643 conf.resync_threshold = resynch_threshold;
00644
00645 return fixed_jb_new(&conf);
00646 }
00647
00648 static void jb_destroy_fixed(void *jb)
00649 {
00650 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00651
00652
00653 fixed_jb_destroy(fixedjb);
00654 }
00655
00656
00657 static int jb_put_first_fixed(void *jb, struct ast_frame *fin, long now)
00658 {
00659 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00660 int res;
00661
00662 res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now);
00663
00664 return fixed_to_abstract_code[res];
00665 }
00666
00667
00668 static int jb_put_fixed(void *jb, struct ast_frame *fin, long now)
00669 {
00670 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00671 int res;
00672
00673 res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now);
00674
00675 return fixed_to_abstract_code[res];
00676 }
00677
00678
00679 static int jb_get_fixed(void *jb, struct ast_frame **fout, long now, long interpl)
00680 {
00681 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00682 struct fixed_jb_frame frame;
00683 int res;
00684
00685 res = fixed_jb_get(fixedjb, &frame, now, interpl);
00686 *fout = frame.data;
00687
00688 return fixed_to_abstract_code[res];
00689 }
00690
00691
00692 static long jb_next_fixed(void *jb)
00693 {
00694 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00695
00696 return fixed_jb_next(fixedjb);
00697 }
00698
00699
00700 static int jb_remove_fixed(void *jb, struct ast_frame **fout)
00701 {
00702 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00703 struct fixed_jb_frame frame;
00704 int res;
00705
00706 res = fixed_jb_remove(fixedjb, &frame);
00707 *fout = frame.data;
00708
00709 return fixed_to_abstract_code[res];
00710 }
00711
00712
00713 static void jb_force_resynch_fixed(void *jb)
00714 {
00715 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00716
00717 fixed_jb_set_force_resynch(fixedjb);
00718 }
00719
00720 static void jb_empty_and_reset_fixed(void *jb)
00721 {
00722 struct fixed_jb *fixedjb = jb;
00723 struct fixed_jb_frame f;
00724
00725 while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) {
00726 ast_frfree(f.data);
00727 }
00728 }
00729
00730
00731
00732 static void *jb_create_adaptive(struct ast_jb_conf *general_config, long resynch_threshold)
00733 {
00734 jb_conf jbconf;
00735 jitterbuf *adaptivejb;
00736
00737 adaptivejb = jb_new();
00738 if (adaptivejb) {
00739 jbconf.max_jitterbuf = general_config->max_size;
00740 jbconf.resync_threshold = general_config->resync_threshold;
00741 jbconf.max_contig_interp = 10;
00742 jb_setconf(adaptivejb, &jbconf);
00743 }
00744
00745 return adaptivejb;
00746 }
00747
00748
00749 static void jb_destroy_adaptive(void *jb)
00750 {
00751 jitterbuf *adaptivejb = (jitterbuf *) jb;
00752
00753 jb_destroy(adaptivejb);
00754 }
00755
00756
00757 static int jb_put_first_adaptive(void *jb, struct ast_frame *fin, long now)
00758 {
00759 return jb_put_adaptive(jb, fin, now);
00760 }
00761
00762
00763 static int jb_put_adaptive(void *jb, struct ast_frame *fin, long now)
00764 {
00765 jitterbuf *adaptivejb = (jitterbuf *) jb;
00766 int res;
00767
00768 res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
00769
00770 return adaptive_to_abstract_code[res];
00771 }
00772
00773
00774 static int jb_get_adaptive(void *jb, struct ast_frame **fout, long now, long interpl)
00775 {
00776 jitterbuf *adaptivejb = (jitterbuf *) jb;
00777 jb_frame frame;
00778 int res;
00779
00780 res = jb_get(adaptivejb, &frame, now, interpl);
00781 *fout = frame.data;
00782
00783 return adaptive_to_abstract_code[res];
00784 }
00785
00786
00787 static long jb_next_adaptive(void *jb)
00788 {
00789 jitterbuf *adaptivejb = (jitterbuf *) jb;
00790
00791 return jb_next(adaptivejb);
00792 }
00793
00794
00795 static int jb_remove_adaptive(void *jb, struct ast_frame **fout)
00796 {
00797 jitterbuf *adaptivejb = (jitterbuf *) jb;
00798 jb_frame frame;
00799 int res;
00800
00801 res = jb_getall(adaptivejb, &frame);
00802 *fout = frame.data;
00803
00804 return adaptive_to_abstract_code[res];
00805 }
00806
00807
00808 static void jb_force_resynch_adaptive(void *jb)
00809 {
00810 }
00811
00812 static void jb_empty_and_reset_adaptive(void *jb)
00813 {
00814 jitterbuf *adaptivejb = jb;
00815 jb_frame f;
00816
00817 while (jb_getall(adaptivejb, &f) == JB_OK) {
00818 ast_frfree(f.data);
00819 }
00820
00821 jb_reset(adaptivejb);
00822 }