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: 299002 $")
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 received 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 = { .frametype = AST_FRAME_VOICE, };
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->subclass = jb->last_format;
00422 f->samples = interpolation_len * 8;
00423 f->src = "JB interpolation";
00424 f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000));
00425 f->offset = AST_FRIENDLY_OFFSET;
00426
00427 ast_write(chan, f);
00428 jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
00429 break;
00430 case JB_IMPL_NOFRAME:
00431 ast_log(LOG_WARNING,
00432 "JB_IMPL_NOFRAME is retuned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
00433 jbimpl->name, now, jb->next, jbimpl->next(jbobj));
00434 jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now);
00435 return;
00436 default:
00437 ast_log(LOG_ERROR, "This should never happen!\n");
00438 ast_assert("JB type unknown" == NULL);
00439 break;
00440 }
00441
00442 jb->next = jbimpl->next(jbobj);
00443 }
00444 }
00445
00446
00447 static int create_jb(struct ast_channel *chan, struct ast_frame *frr)
00448 {
00449 struct ast_jb *jb = &chan->jb;
00450 struct ast_jb_conf *jbconf = &jb->conf;
00451 struct ast_jb_impl *jbimpl = jb->impl;
00452 void *jbobj;
00453 struct ast_channel *bridged;
00454 long now;
00455 char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1];
00456 char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp;
00457 int res;
00458
00459 jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold);
00460 if (!jbobj) {
00461 ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name);
00462 return -1;
00463 }
00464
00465 now = get_now(jb, NULL);
00466 res = jbimpl->put_first(jbobj, frr, now);
00467
00468
00469
00470 if (res != JB_IMPL_OK) {
00471 ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name);
00472
00473
00474
00475
00476 }
00477
00478
00479 jb->next = jbimpl->next(jbobj);
00480
00481
00482 jb->last_format = frr->subclass;
00483
00484
00485 if (ast_test_flag(jbconf, AST_JB_LOG)) {
00486 snprintf(name2, sizeof(name2), "%s", chan->name);
00487 tmp = strchr(name2, '/');
00488 if (tmp)
00489 *tmp = '#';
00490
00491 bridged = ast_bridged_channel(chan);
00492
00493 ast_assert(bridged != NULL);
00494
00495 snprintf(name1, sizeof(name1), "%s", bridged->name);
00496 tmp = strchr(name1, '/');
00497 if (tmp)
00498 *tmp = '#';
00499
00500 snprintf(logfile_pathname, sizeof(logfile_pathname),
00501 "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2);
00502 jb->logfile = fopen(logfile_pathname, "w+b");
00503
00504 if (!jb->logfile)
00505 ast_log(LOG_WARNING, "Failed to create frame log file with pathname '%s'\n", logfile_pathname);
00506
00507 if (res == JB_IMPL_OK)
00508 jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
00509 now, frr->ts, frr->len);
00510 else
00511 jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
00512 now, frr->ts, frr->len);
00513 }
00514
00515 if (option_verbose > 2)
00516 ast_verbose(VERBOSE_PREFIX_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 if (option_verbose > 2)
00550 ast_verbose(VERBOSE_PREFIX_3 "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name);
00551 }
00552 }
00553
00554
00555 static long get_now(struct ast_jb *jb, struct timeval *tv)
00556 {
00557 struct timeval now;
00558
00559 if (!tv) {
00560 tv = &now;
00561 gettimeofday(tv, NULL);
00562 }
00563
00564 return ast_tvdiff_ms(*tv, jb->timebase);
00565 }
00566
00567
00568 int ast_jb_read_conf(struct ast_jb_conf *conf, char *varname, char *value)
00569 {
00570 int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1;
00571 char *name;
00572 int tmp;
00573
00574 if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen))
00575 return -1;
00576
00577 name = varname + prefixlen;
00578
00579 if (!strcasecmp(name, AST_JB_CONF_ENABLE)) {
00580 ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED);
00581 } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) {
00582 ast_set2_flag(conf, ast_true(value), AST_JB_FORCED);
00583 } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) {
00584 if ((tmp = atoi(value)) > 0)
00585 conf->max_size = tmp;
00586 } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) {
00587 if ((tmp = atoi(value)) > 0)
00588 conf->resync_threshold = tmp;
00589 } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) {
00590 if (!ast_strlen_zero(value))
00591 snprintf(conf->impl, sizeof(conf->impl), "%s", value);
00592 } else if (!strcasecmp(name, AST_JB_CONF_LOG)) {
00593 ast_set2_flag(conf, ast_true(value), AST_JB_LOG);
00594 } else {
00595 return -1;
00596 }
00597
00598 return 0;
00599 }
00600
00601
00602 void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
00603 {
00604 memcpy(&chan->jb.conf, conf, sizeof(*conf));
00605 }
00606
00607
00608 void ast_jb_get_config(const struct ast_channel *chan, struct ast_jb_conf *conf)
00609 {
00610 memcpy(conf, &chan->jb.conf, sizeof(*conf));
00611 }
00612
00613 void ast_jb_empty_and_reset(struct ast_channel *c0, struct ast_channel *c1)
00614 {
00615 struct ast_jb *jb0 = &c0->jb;
00616 struct ast_jb *jb1 = &c1->jb;
00617 int c0_use_jb = ast_test_flag(jb0, JB_USE);
00618 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00619 int c1_use_jb = ast_test_flag(jb1, JB_USE);
00620 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00621
00622 if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) {
00623 jb0->impl->empty_and_reset(jb0->jbobj);
00624 }
00625
00626 if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) {
00627 jb1->impl->empty_and_reset(jb1->jbobj);
00628 }
00629 }
00630
00631
00632
00633
00634 static void * jb_create_fixed(struct ast_jb_conf *general_config, long resynch_threshold)
00635 {
00636 struct fixed_jb_conf conf;
00637
00638 conf.jbsize = general_config->max_size;
00639 conf.resync_threshold = resynch_threshold;
00640
00641 return fixed_jb_new(&conf);
00642 }
00643
00644 static void jb_destroy_fixed(void *jb)
00645 {
00646 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00647
00648
00649 fixed_jb_destroy(fixedjb);
00650 }
00651
00652
00653 static int jb_put_first_fixed(void *jb, struct ast_frame *fin, long now)
00654 {
00655 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00656 int res;
00657
00658 res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now);
00659
00660 return fixed_to_abstract_code[res];
00661 }
00662
00663
00664 static int jb_put_fixed(void *jb, struct ast_frame *fin, long now)
00665 {
00666 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00667 int res;
00668
00669 res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now);
00670
00671 return fixed_to_abstract_code[res];
00672 }
00673
00674
00675 static int jb_get_fixed(void *jb, struct ast_frame **fout, long now, long interpl)
00676 {
00677 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00678 struct fixed_jb_frame frame;
00679 int res;
00680
00681 res = fixed_jb_get(fixedjb, &frame, now, interpl);
00682 *fout = frame.data;
00683
00684 return fixed_to_abstract_code[res];
00685 }
00686
00687
00688 static long jb_next_fixed(void *jb)
00689 {
00690 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00691
00692 return fixed_jb_next(fixedjb);
00693 }
00694
00695
00696 static int jb_remove_fixed(void *jb, struct ast_frame **fout)
00697 {
00698 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00699 struct fixed_jb_frame frame;
00700 int res;
00701
00702 res = fixed_jb_remove(fixedjb, &frame);
00703 *fout = frame.data;
00704
00705 return fixed_to_abstract_code[res];
00706 }
00707
00708
00709 static void jb_force_resynch_fixed(void *jb)
00710 {
00711 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00712
00713 fixed_jb_set_force_resynch(fixedjb);
00714 }
00715
00716 static void jb_empty_and_reset_fixed(void *jb)
00717 {
00718 struct fixed_jb *fixedjb = jb;
00719 struct fixed_jb_frame f;
00720
00721 while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) {
00722 ast_frfree(f.data);
00723 }
00724 }
00725
00726
00727
00728 static void *jb_create_adaptive(struct ast_jb_conf *general_config, long resynch_threshold)
00729 {
00730 jb_conf jbconf;
00731 jitterbuf *adaptivejb;
00732
00733 adaptivejb = jb_new();
00734 if (adaptivejb) {
00735 jbconf.max_jitterbuf = general_config->max_size;
00736 jbconf.resync_threshold = general_config->resync_threshold;
00737 jbconf.max_contig_interp = 10;
00738 jb_setconf(adaptivejb, &jbconf);
00739 }
00740
00741 return adaptivejb;
00742 }
00743
00744
00745 static void jb_destroy_adaptive(void *jb)
00746 {
00747 jitterbuf *adaptivejb = (jitterbuf *) jb;
00748
00749 jb_destroy(adaptivejb);
00750 }
00751
00752
00753 static int jb_put_first_adaptive(void *jb, struct ast_frame *fin, long now)
00754 {
00755 jitterbuf *adaptivejb = (jitterbuf *) jb;
00756
00757
00758 adaptivejb->info.resync_offset = fin->ts;
00759
00760 return jb_put_adaptive(jb, fin, now);
00761 }
00762
00763
00764 static int jb_put_adaptive(void *jb, struct ast_frame *fin, long now)
00765 {
00766 jitterbuf *adaptivejb = (jitterbuf *) jb;
00767 int res;
00768
00769 res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
00770
00771 return adaptive_to_abstract_code[res];
00772 }
00773
00774
00775 static int jb_get_adaptive(void *jb, struct ast_frame **fout, long now, long interpl)
00776 {
00777 jitterbuf *adaptivejb = (jitterbuf *) jb;
00778 jb_frame frame;
00779 int res;
00780
00781 res = jb_get(adaptivejb, &frame, now, interpl);
00782 *fout = frame.data;
00783
00784 return adaptive_to_abstract_code[res];
00785 }
00786
00787
00788 static long jb_next_adaptive(void *jb)
00789 {
00790 jitterbuf *adaptivejb = (jitterbuf *) jb;
00791
00792 return jb_next(adaptivejb);
00793 }
00794
00795
00796 static int jb_remove_adaptive(void *jb, struct ast_frame **fout)
00797 {
00798 jitterbuf *adaptivejb = (jitterbuf *) jb;
00799 jb_frame frame;
00800 int res;
00801
00802 res = jb_getall(adaptivejb, &frame);
00803 *fout = frame.data;
00804
00805 return adaptive_to_abstract_code[res];
00806 }
00807
00808
00809 static void jb_force_resynch_adaptive(void *jb)
00810 {
00811 }
00812
00813 static void jb_empty_and_reset_adaptive(void *jb)
00814 {
00815 jitterbuf *adaptivejb = jb;
00816 jb_frame f;
00817
00818 while (jb_getall(adaptivejb, &f) == JB_OK) {
00819 ast_frfree(f.data);
00820 }
00821
00822 jb_reset(adaptivejb);
00823 }