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