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