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