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