Common implementation-independent jitterbuffer stuff. More...
#include <sys/time.h>
#include "asterisk/frame_defs.h"
Go to the source code of this file.
Data Structures | |
struct | ast_jb |
General jitterbuffer state. More... | |
struct | ast_jb_conf |
General jitterbuffer configuration. More... | |
Defines | |
#define | AST_JB_CONF_ENABLE "enable" |
#define | AST_JB_CONF_FORCE "force" |
#define | AST_JB_CONF_IMPL "impl" |
#define | AST_JB_CONF_LOG "log" |
#define | AST_JB_CONF_MAX_SIZE "maxsize" |
#define | AST_JB_CONF_PREFIX "jb" |
#define | AST_JB_CONF_RESYNCH_THRESHOLD "resyncthreshold" |
#define | AST_JB_CONF_TARGET_EXTRA "targetextra" |
#define | AST_JB_IMPL_NAME_SIZE 12 |
Enumerations | |
enum | { AST_JB_ENABLED = (1 << 0), AST_JB_FORCED = (1 << 1), AST_JB_LOG = (1 << 2) } |
Functions | |
void | ast_jb_configure (struct ast_channel *chan, const struct ast_jb_conf *conf) |
Configures a jitterbuffer on a channel. | |
void | ast_jb_destroy (struct ast_channel *chan) |
Destroys jitterbuffer on a channel. | |
int | ast_jb_do_usecheck (struct ast_channel *c0, struct ast_channel *c1) |
Checks the need of a jb use in a generic bridge. | |
void | ast_jb_empty_and_reset (struct ast_channel *c0, struct ast_channel *c1) |
drops all frames from a jitterbuffer and resets it | |
void | ast_jb_get_and_deliver (struct ast_channel *c0, struct ast_channel *c1) |
Deliver the queued frames that should be delivered now for both channels. | |
void | ast_jb_get_config (const struct ast_channel *chan, struct ast_jb_conf *conf) |
Copies a channel's jitterbuffer configuration. | |
int | ast_jb_get_when_to_wakeup (struct ast_channel *c0, struct ast_channel *c1, int time_left) |
Calculates the time, left to the closest delivery moment in a bridge. | |
int | ast_jb_put (struct ast_channel *chan, struct ast_frame *f) |
Puts a frame into a channel jitterbuffer. | |
int | ast_jb_read_conf (struct ast_jb_conf *conf, const char *varname, const char *value) |
Sets jitterbuffer configuration property. |
Common implementation-independent jitterbuffer stuff.
Definition in file abstract_jb.h.
#define AST_JB_CONF_ENABLE "enable" |
Definition at line 72 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
#define AST_JB_CONF_FORCE "force" |
Definition at line 73 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
#define AST_JB_CONF_IMPL "impl" |
Definition at line 77 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
#define AST_JB_CONF_LOG "log" |
Definition at line 78 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
#define AST_JB_CONF_MAX_SIZE "maxsize" |
Definition at line 74 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
#define AST_JB_CONF_PREFIX "jb" |
Definition at line 71 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
#define AST_JB_CONF_RESYNCH_THRESHOLD "resyncthreshold" |
Definition at line 75 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
#define AST_JB_CONF_TARGET_EXTRA "targetextra" |
Definition at line 76 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
#define AST_JB_IMPL_NAME_SIZE 12 |
Definition at line 50 of file abstract_jb.h.
Referenced by create_jb().
anonymous enum |
Definition at line 44 of file abstract_jb.h.
00044 { 00045 AST_JB_ENABLED = (1 << 0), 00046 AST_JB_FORCED = (1 << 1), 00047 AST_JB_LOG = (1 << 2) 00048 };
void ast_jb_configure | ( | struct ast_channel * | chan, | |
const struct ast_jb_conf * | conf | |||
) |
Configures a jitterbuffer on a channel.
chan | channel to configure. | |
conf | configuration to apply. |
Called from a channel driver when a channel is created and its jitterbuffer needs to be configured.
Definition at line 616 of file abstract_jb.c.
References ast_jb::conf, and ast_channel::jb.
Referenced by __oh323_rtp_create(), __oh323_update_info(), alsa_new(), console_new(), dahdi_new(), gtalk_new(), jingle_new(), local_new(), mgcp_new(), misdn_new(), oss_new(), sip_new(), skinny_new(), and unistim_new().
void ast_jb_destroy | ( | struct ast_channel * | chan | ) |
Destroys jitterbuffer on a channel.
chan | channel. |
Called from ast_channel_free() when a channel is destroyed.
Definition at line 536 of file abstract_jb.c.
References ast_clear_flag, ast_frfree, ast_test_flag, ast_verb, ast_jb_impl::destroy, f, ast_jb::impl, ast_channel::jb, JB_CREATED, JB_IMPL_OK, ast_jb::jbobj, ast_jb::logfile, ast_jb_impl::name, and ast_jb_impl::remove.
Referenced by ast_channel_destructor().
00537 { 00538 struct ast_jb *jb = &chan->jb; 00539 const struct ast_jb_impl *jbimpl = jb->impl; 00540 void *jbobj = jb->jbobj; 00541 struct ast_frame *f; 00542 00543 if (jb->logfile) { 00544 fclose(jb->logfile); 00545 jb->logfile = NULL; 00546 } 00547 00548 if (ast_test_flag(jb, JB_CREATED)) { 00549 /* Remove and free all frames still queued in jb */ 00550 while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) { 00551 ast_frfree(f); 00552 } 00553 00554 jbimpl->destroy(jbobj); 00555 jb->jbobj = NULL; 00556 00557 ast_clear_flag(jb, JB_CREATED); 00558 00559 ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name); 00560 } 00561 }
int ast_jb_do_usecheck | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) |
Checks the need of a jb use in a generic bridge.
c0 | first bridged channel. | |
c1 | second bridged channel. |
Called from ast_generic_bridge() when two channels are entering in a bridge. The function checks the need of a jitterbuffer, depending on both channel's configuration and technology properties. As a result, this function sets appropriate internal jb flags to the channels, determining further behaviour of the bridged jitterbuffers.
zero | if there are no jitter buffers in use | |
non-zero | if there are |
Definition at line 205 of file abstract_jb.c.
References AST_CHAN_TP_CREATESJITTER, AST_CHAN_TP_WANTSJITTER, AST_JB_ENABLED, AST_JB_FORCED, ast_set_flag, ast_test_flag, ast_jb::conf, ast_channel::jb, jb_choose_impl(), JB_CREATED, JB_TIMEBASE_INITIALIZED, JB_USE, ast_channel_tech::properties, ast_channel::tech, and ast_jb::timebase.
Referenced by ast_generic_bridge().
00206 { 00207 struct ast_jb *jb0 = &c0->jb; 00208 struct ast_jb *jb1 = &c1->jb; 00209 struct ast_jb_conf *conf0 = &jb0->conf; 00210 struct ast_jb_conf *conf1 = &jb1->conf; 00211 int c0_wants_jitter = c0->tech->properties & AST_CHAN_TP_WANTSJITTER; 00212 int c0_creates_jitter = c0->tech->properties & AST_CHAN_TP_CREATESJITTER; 00213 int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED); 00214 int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED); 00215 int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED); 00216 int c0_jb_created = ast_test_flag(jb0, JB_CREATED); 00217 int c1_wants_jitter = c1->tech->properties & AST_CHAN_TP_WANTSJITTER; 00218 int c1_creates_jitter = c1->tech->properties & AST_CHAN_TP_CREATESJITTER; 00219 int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED); 00220 int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED); 00221 int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED); 00222 int c1_jb_created = ast_test_flag(jb1, JB_CREATED); 00223 int inuse = 0; 00224 00225 /* Determine whether audio going to c0 needs a jitter buffer */ 00226 if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) { 00227 ast_set_flag(jb0, JB_USE); 00228 if (!c0_jb_timebase_initialized) { 00229 if (c1_jb_timebase_initialized) { 00230 memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval)); 00231 } else { 00232 gettimeofday(&jb0->timebase, NULL); 00233 } 00234 ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED); 00235 } 00236 00237 if (!c0_jb_created) { 00238 jb_choose_impl(c0); 00239 } 00240 00241 inuse = 1; 00242 } 00243 00244 /* Determine whether audio going to c1 needs a jitter buffer */ 00245 if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) { 00246 ast_set_flag(jb1, JB_USE); 00247 if (!c1_jb_timebase_initialized) { 00248 if (c0_jb_timebase_initialized) { 00249 memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval)); 00250 } else { 00251 gettimeofday(&jb1->timebase, NULL); 00252 } 00253 ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED); 00254 } 00255 00256 if (!c1_jb_created) { 00257 jb_choose_impl(c1); 00258 } 00259 00260 inuse = 1; 00261 } 00262 00263 return inuse; 00264 }
void ast_jb_empty_and_reset | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) |
drops all frames from a jitterbuffer and resets it
c0 | one channel of a bridge | |
c1 | the other channel of the bridge |
Definition at line 627 of file abstract_jb.c.
References ast_test_flag, ast_jb_impl::empty_and_reset, ast_jb::impl, ast_channel::jb, JB_CREATED, JB_USE, and ast_jb::jbobj.
Referenced by ast_generic_bridge().
00628 { 00629 struct ast_jb *jb0 = &c0->jb; 00630 struct ast_jb *jb1 = &c1->jb; 00631 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00632 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00633 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00634 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00635 00636 if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) { 00637 jb0->impl->empty_and_reset(jb0->jbobj); 00638 } 00639 00640 if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) { 00641 jb1->impl->empty_and_reset(jb1->jbobj); 00642 } 00643 }
void ast_jb_get_and_deliver | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) |
Deliver the queued frames that should be delivered now for both channels.
c0 | first bridged channel. | |
c1 | second bridged channel. |
Called from ast_generic_bridge() to deliver any frames, that should be delivered for the moment of invocation. Does nothing if neihter of the channels is using jb or has any frames currently queued in. The function delivers frames usig ast_write() each of the channels.
Definition at line 371 of file abstract_jb.c.
References ast_test_flag, ast_channel::jb, JB_CREATED, jb_get_and_deliver(), and JB_USE.
Referenced by ast_generic_bridge().
00372 { 00373 struct ast_jb *jb0 = &c0->jb; 00374 struct ast_jb *jb1 = &c1->jb; 00375 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00376 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00377 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00378 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00379 00380 if (c0_use_jb && c0_jb_is_created) 00381 jb_get_and_deliver(c0); 00382 00383 if (c1_use_jb && c1_jb_is_created) 00384 jb_get_and_deliver(c1); 00385 }
void ast_jb_get_config | ( | const struct ast_channel * | chan, | |
struct ast_jb_conf * | conf | |||
) |
Copies a channel's jitterbuffer configuration.
chan | channel. | |
conf | destination. |
Definition at line 622 of file abstract_jb.c.
References ast_jb::conf, and ast_channel::jb.
int ast_jb_get_when_to_wakeup | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
int | time_left | |||
) |
Calculates the time, left to the closest delivery moment in a bridge.
c0 | first bridged channel. | |
c1 | second bridged channel. | |
time_left | bridge time limit, or -1 if not set. |
Called from ast_generic_bridge() to determine the maximum time to wait for activity in ast_waitfor_n() call. If neihter of the channels is using jb, this function returns the time limit passed.
Definition at line 266 of file abstract_jb.c.
References ast_test_flag, get_now(), ast_channel::jb, JB_CREATED, JB_USE, and ast_jb::next.
Referenced by ast_generic_bridge().
00267 { 00268 struct ast_jb *jb0 = &c0->jb; 00269 struct ast_jb *jb1 = &c1->jb; 00270 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00271 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00272 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00273 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00274 int wait, wait0, wait1; 00275 struct timeval tv_now; 00276 00277 if (time_left == 0) { 00278 /* No time left - the bridge will be retried */ 00279 /* TODO: Test disable this */ 00280 /*return 0;*/ 00281 } 00282 00283 if (time_left < 0) { 00284 time_left = INT_MAX; 00285 } 00286 00287 gettimeofday(&tv_now, NULL); 00288 00289 wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left; 00290 wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left; 00291 00292 wait = wait0 < wait1 ? wait0 : wait1; 00293 wait = wait < time_left ? wait : time_left; 00294 00295 if (wait == INT_MAX) { 00296 wait = -1; 00297 } else if (wait < 1) { 00298 /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */ 00299 wait = 1; 00300 } 00301 00302 return wait; 00303 }
int ast_jb_put | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) |
Puts a frame into a channel jitterbuffer.
chan | channel. | |
f | frame. |
Called from ast_generic_bridge() to put a frame into a channel's jitterbuffer. The function will successfuly enqueue a frame if and only if: 1. the channel is using a jitterbuffer (as determined by ast_jb_do_usecheck()), 2. the frame's type is AST_FRAME_VOICE, 3. the frame has timing info set and has length >= 2 ms, 4. there is no some internal error happened (like failed memory allocation). Frames, successfuly queued, should be delivered by the channel's jitterbuffer, when their delivery time has came. Frames, not successfuly queued, should be delivered immediately. Dropped by the jb implementation frames are considered successfuly enqueued as far as they should not be delivered at all.
0 | if the frame was queued | |
-1 | if not |
Definition at line 306 of file abstract_jb.c.
References ast_clear_flag, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frdup(), AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_log(), ast_set_flag, ast_test_flag, create_jb(), ast_jb_impl::force_resync, ast_frame::frametype, get_now(), ast_jb::impl, ast_channel::jb, JB_CREATED, jb_framelog, JB_IMPL_OK, JB_USE, ast_jb::jbobj, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb_impl::next, ast_jb::next, ast_jb_impl::put, ast_frame::src, and ast_frame::ts.
Referenced by ast_generic_bridge().
00307 { 00308 struct ast_jb *jb = &chan->jb; 00309 const struct ast_jb_impl *jbimpl = jb->impl; 00310 void *jbobj = jb->jbobj; 00311 struct ast_frame *frr; 00312 long now = 0; 00313 00314 if (!ast_test_flag(jb, JB_USE)) 00315 return -1; 00316 00317 if (f->frametype != AST_FRAME_VOICE) { 00318 if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) { 00319 jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now); 00320 jbimpl->force_resync(jbobj); 00321 } 00322 00323 return -1; 00324 } 00325 00326 /* We consider an enabled jitterbuffer should receive frames with valid timing info. */ 00327 if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) { 00328 ast_log(LOG_WARNING, "%s received frame with invalid timing info: " 00329 "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n", 00330 chan->name, ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO), f->len, f->ts, f->src); 00331 return -1; 00332 } 00333 00334 frr = ast_frdup(f); 00335 00336 if (!frr) { 00337 ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan->name); 00338 return -1; 00339 } 00340 00341 if (!ast_test_flag(jb, JB_CREATED)) { 00342 if (create_jb(chan, frr)) { 00343 ast_frfree(frr); 00344 /* Disable the jitterbuffer */ 00345 ast_clear_flag(jb, JB_USE); 00346 return -1; 00347 } 00348 00349 ast_set_flag(jb, JB_CREATED); 00350 return 0; 00351 } else { 00352 now = get_now(jb, NULL); 00353 if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) { 00354 jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); 00355 ast_frfree(frr); 00356 /*return -1;*/ 00357 /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't 00358 be delivered at all */ 00359 return 0; 00360 } 00361 00362 jb->next = jbimpl->next(jbobj); 00363 00364 jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); 00365 00366 return 0; 00367 } 00368 }
int ast_jb_read_conf | ( | struct ast_jb_conf * | conf, | |
const char * | varname, | |||
const char * | value | |||
) |
Sets jitterbuffer configuration property.
conf | configuration to store the property in. | |
varname | property name. | |
value | property value. |
Called from a channel driver to build a jitterbuffer configuration typically when reading a configuration file. It is not necessary for a channel driver to know each of the jb configuration property names. The jitterbuffer itself knows them. The channel driver can pass each config var it reads through this function. It will return 0 if the variable was consumed from the jb conf.
Definition at line 577 of file abstract_jb.c.
References AST_JB_CONF_ENABLE, AST_JB_CONF_FORCE, AST_JB_CONF_IMPL, AST_JB_CONF_LOG, AST_JB_CONF_MAX_SIZE, AST_JB_CONF_PREFIX, AST_JB_CONF_RESYNCH_THRESHOLD, AST_JB_CONF_TARGET_EXTRA, AST_JB_ENABLED, AST_JB_FORCED, AST_JB_LOG, ast_set2_flag, ast_strlen_zero(), ast_true(), ast_jb_conf::impl, ast_jb_conf::max_size, name, ast_jb_conf::resync_threshold, and ast_jb_conf::target_extra.
Referenced by _build_general_config(), config_parse_variables(), gtalk_load_config(), jingle_load_config(), load_module(), process_dahdi(), reload_config(), and store_config_core().
00578 { 00579 int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1; 00580 const char *name; 00581 int tmp; 00582 00583 if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) { 00584 return -1; 00585 } 00586 00587 name = varname + prefixlen; 00588 00589 if (!strcasecmp(name, AST_JB_CONF_ENABLE)) { 00590 ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED); 00591 } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) { 00592 ast_set2_flag(conf, ast_true(value), AST_JB_FORCED); 00593 } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) { 00594 if ((tmp = atoi(value)) > 0) 00595 conf->max_size = tmp; 00596 } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) { 00597 if ((tmp = atoi(value)) > 0) 00598 conf->resync_threshold = tmp; 00599 } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) { 00600 if (!ast_strlen_zero(value)) 00601 snprintf(conf->impl, sizeof(conf->impl), "%s", value); 00602 } else if (!strcasecmp(name, AST_JB_CONF_TARGET_EXTRA)) { 00603 if (sscanf(value, "%30d", &tmp) == 1) { 00604 conf->target_extra = tmp; 00605 } 00606 } else if (!strcasecmp(name, AST_JB_CONF_LOG)) { 00607 ast_set2_flag(conf, ast_true(value), AST_JB_LOG); 00608 } else { 00609 return -1; 00610 } 00611 00612 return 0; 00613 }