Common implementation-independent jitterbuffer stuff. More...
#include <sys/time.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 70 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_FORCE "force" |
Definition at line 71 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_IMPL "impl" |
Definition at line 75 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_LOG "log" |
Definition at line 76 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_MAX_SIZE "maxsize" |
Definition at line 72 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_PREFIX "jb" |
Definition at line 69 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_RESYNCH_THRESHOLD "resyncthreshold" |
Definition at line 73 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_TARGET_EXTRA "targetextra" |
Definition at line 74 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_IMPL_NAME_SIZE 12 |
Definition at line 48 of file abstract_jb.h.
Referenced by create_jb().
| anonymous enum |
Definition at line 42 of file abstract_jb.h.
00042 { 00043 AST_JB_ENABLED = (1 << 0), 00044 AST_JB_FORCED = (1 << 1), 00045 AST_JB_LOG = (1 << 2) 00046 };
| 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 610 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(), unistim_new(), and usbradio_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 530 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_channel::name, ast_jb_impl::name, and ast_jb_impl::remove.
Referenced by ast_channel_free().
00531 { 00532 struct ast_jb *jb = &chan->jb; 00533 struct ast_jb_impl *jbimpl = jb->impl; 00534 void *jbobj = jb->jbobj; 00535 struct ast_frame *f; 00536 00537 if (jb->logfile) { 00538 fclose(jb->logfile); 00539 jb->logfile = NULL; 00540 } 00541 00542 if (ast_test_flag(jb, JB_CREATED)) { 00543 /* Remove and free all frames still queued in jb */ 00544 while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) { 00545 ast_frfree(f); 00546 } 00547 00548 jbimpl->destroy(jbobj); 00549 jb->jbobj = NULL; 00550 00551 ast_clear_flag(jb, JB_CREATED); 00552 00553 ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name); 00554 } 00555 }
| 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 202 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, inuse, 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().
00203 { 00204 struct ast_jb *jb0 = &c0->jb; 00205 struct ast_jb *jb1 = &c1->jb; 00206 struct ast_jb_conf *conf0 = &jb0->conf; 00207 struct ast_jb_conf *conf1 = &jb1->conf; 00208 int c0_wants_jitter = c0->tech->properties & AST_CHAN_TP_WANTSJITTER; 00209 int c0_creates_jitter = c0->tech->properties & AST_CHAN_TP_CREATESJITTER; 00210 int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED); 00211 int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED); 00212 int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED); 00213 int c0_jb_created = ast_test_flag(jb0, JB_CREATED); 00214 int c1_wants_jitter = c1->tech->properties & AST_CHAN_TP_WANTSJITTER; 00215 int c1_creates_jitter = c1->tech->properties & AST_CHAN_TP_CREATESJITTER; 00216 int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED); 00217 int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED); 00218 int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED); 00219 int c1_jb_created = ast_test_flag(jb1, JB_CREATED); 00220 int inuse = 0; 00221 00222 /* Determine whether audio going to c0 needs a jitter buffer */ 00223 if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) { 00224 ast_set_flag(jb0, JB_USE); 00225 if (!c0_jb_timebase_initialized) { 00226 if (c1_jb_timebase_initialized) { 00227 memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval)); 00228 } else { 00229 gettimeofday(&jb0->timebase, NULL); 00230 } 00231 ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED); 00232 } 00233 00234 if (!c0_jb_created) { 00235 jb_choose_impl(c0); 00236 } 00237 00238 inuse = 1; 00239 } 00240 00241 /* Determine whether audio going to c1 needs a jitter buffer */ 00242 if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) { 00243 ast_set_flag(jb1, JB_USE); 00244 if (!c1_jb_timebase_initialized) { 00245 if (c0_jb_timebase_initialized) { 00246 memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval)); 00247 } else { 00248 gettimeofday(&jb1->timebase, NULL); 00249 } 00250 ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED); 00251 } 00252 00253 if (!c1_jb_created) { 00254 jb_choose_impl(c1); 00255 } 00256 00257 inuse = 1; 00258 } 00259 00260 return inuse; 00261 }
| 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 621 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().
00622 { 00623 struct ast_jb *jb0 = &c0->jb; 00624 struct ast_jb *jb1 = &c1->jb; 00625 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00626 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00627 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00628 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00629 00630 if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) { 00631 jb0->impl->empty_and_reset(jb0->jbobj); 00632 } 00633 00634 if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) { 00635 jb1->impl->empty_and_reset(jb1->jbobj); 00636 } 00637 }
| 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 368 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().
00369 { 00370 struct ast_jb *jb0 = &c0->jb; 00371 struct ast_jb *jb1 = &c1->jb; 00372 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00373 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00374 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00375 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00376 00377 if (c0_use_jb && c0_jb_is_created) 00378 jb_get_and_deliver(c0); 00379 00380 if (c1_use_jb && c1_jb_is_created) 00381 jb_get_and_deliver(c1); 00382 }
| 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 616 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 263 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().
00264 { 00265 struct ast_jb *jb0 = &c0->jb; 00266 struct ast_jb *jb1 = &c1->jb; 00267 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00268 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00269 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00270 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00271 int wait, wait0, wait1; 00272 struct timeval tv_now; 00273 00274 if (time_left == 0) { 00275 /* No time left - the bridge will be retried */ 00276 /* TODO: Test disable this */ 00277 /*return 0;*/ 00278 } 00279 00280 if (time_left < 0) { 00281 time_left = INT_MAX; 00282 } 00283 00284 gettimeofday(&tv_now, NULL); 00285 00286 wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left; 00287 wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left; 00288 00289 wait = wait0 < wait1 ? wait0 : wait1; 00290 wait = wait < time_left ? wait : time_left; 00291 00292 if (wait == INT_MAX) { 00293 wait = -1; 00294 } else if (wait < 1) { 00295 /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */ 00296 wait = 1; 00297 } 00298 00299 return wait; 00300 }
| 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 303 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_channel::name, ast_jb_impl::next, ast_jb::next, ast_jb_impl::put, ast_frame::src, and ast_frame::ts.
Referenced by ast_generic_bridge().
00304 { 00305 struct ast_jb *jb = &chan->jb; 00306 struct ast_jb_impl *jbimpl = jb->impl; 00307 void *jbobj = jb->jbobj; 00308 struct ast_frame *frr; 00309 long now = 0; 00310 00311 if (!ast_test_flag(jb, JB_USE)) 00312 return -1; 00313 00314 if (f->frametype != AST_FRAME_VOICE) { 00315 if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) { 00316 jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now); 00317 jbimpl->force_resync(jbobj); 00318 } 00319 00320 return -1; 00321 } 00322 00323 /* We consider an enabled jitterbuffer should receive frames with valid timing info. */ 00324 if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) { 00325 ast_log(LOG_WARNING, "%s received frame with invalid timing info: " 00326 "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n", 00327 chan->name, ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO), f->len, f->ts, f->src); 00328 return -1; 00329 } 00330 00331 frr = ast_frdup(f); 00332 00333 if (!frr) { 00334 ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan->name); 00335 return -1; 00336 } 00337 00338 if (!ast_test_flag(jb, JB_CREATED)) { 00339 if (create_jb(chan, frr)) { 00340 ast_frfree(frr); 00341 /* Disable the jitterbuffer */ 00342 ast_clear_flag(jb, JB_USE); 00343 return -1; 00344 } 00345 00346 ast_set_flag(jb, JB_CREATED); 00347 return 0; 00348 } else { 00349 now = get_now(jb, NULL); 00350 if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) { 00351 jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); 00352 ast_frfree(frr); 00353 /*return -1;*/ 00354 /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't 00355 be delivered at all */ 00356 return 0; 00357 } 00358 00359 jb->next = jbimpl->next(jbobj); 00360 00361 jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); 00362 00363 return 0; 00364 } 00365 }
| 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 571 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(), store_config(), and store_config_core().
00572 { 00573 int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1; 00574 const char *name; 00575 int tmp; 00576 00577 if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) { 00578 return -1; 00579 } 00580 00581 name = varname + prefixlen; 00582 00583 if (!strcasecmp(name, AST_JB_CONF_ENABLE)) { 00584 ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED); 00585 } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) { 00586 ast_set2_flag(conf, ast_true(value), AST_JB_FORCED); 00587 } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) { 00588 if ((tmp = atoi(value)) > 0) 00589 conf->max_size = tmp; 00590 } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) { 00591 if ((tmp = atoi(value)) > 0) 00592 conf->resync_threshold = tmp; 00593 } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) { 00594 if (!ast_strlen_zero(value)) 00595 snprintf(conf->impl, sizeof(conf->impl), "%s", value); 00596 } else if (!strcasecmp(name, AST_JB_CONF_TARGET_EXTRA)) { 00597 if (sscanf(value, "%30d", &tmp) == 1) { 00598 conf->target_extra = tmp; 00599 } 00600 } else if (!strcasecmp(name, AST_JB_CONF_LOG)) { 00601 ast_set2_flag(conf, ast_true(value), AST_JB_LOG); 00602 } else { 00603 return -1; 00604 } 00605 00606 return 0; 00607 }
1.6.2