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