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_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 68 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_FORCE "force" |
Definition at line 69 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_IMPL "impl" |
Definition at line 72 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_LOG "log" |
Definition at line 73 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_MAX_SIZE "maxsize" |
Definition at line 70 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_PREFIX "jb" |
Definition at line 67 of file abstract_jb.h.
Referenced by ast_jb_read_conf().
| #define AST_JB_CONF_RESYNCH_THRESHOLD "resyncthreshold" |
Definition at line 71 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 601 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 526 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_free().
00527 { 00528 struct ast_jb *jb = &chan->jb; 00529 struct ast_jb_impl *jbimpl = jb->impl; 00530 void *jbobj = jb->jbobj; 00531 struct ast_frame *f; 00532 00533 if (jb->logfile) { 00534 fclose(jb->logfile); 00535 jb->logfile = NULL; 00536 } 00537 00538 if (ast_test_flag(jb, JB_CREATED)) { 00539 /* Remove and free all frames still queued in jb */ 00540 while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) { 00541 ast_frfree(f); 00542 } 00543 00544 jbimpl->destroy(jbobj); 00545 jb->jbobj = NULL; 00546 00547 ast_clear_flag(jb, JB_CREATED); 00548 00549 ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name); 00550 } 00551 }
| 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 201 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().
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 /* Determine whether audio going to c0 needs a jitter buffer */ 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 /* Determine whether audio going to c1 needs a jitter buffer */ 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 }
| 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 612 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().
00613 { 00614 struct ast_jb *jb0 = &c0->jb; 00615 struct ast_jb *jb1 = &c1->jb; 00616 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00617 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00618 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00619 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00620 00621 if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) { 00622 jb0->impl->empty_and_reset(jb0->jbobj); 00623 } 00624 00625 if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) { 00626 jb1->impl->empty_and_reset(jb1->jbobj); 00627 } 00628 }
| 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 367 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().
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 }
| 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 607 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 262 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().
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 /* No time left - the bridge will be retried */ 00275 /* TODO: Test disable this */ 00276 /*return 0;*/ 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 /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */ 00295 wait = 1; 00296 } 00297 00298 return wait; 00299 }
| 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 302 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().
00303 { 00304 struct ast_jb *jb = &chan->jb; 00305 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 /* We consider an enabled jitterbuffer should receive frames with valid timing info. */ 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 /* Disable the jitterbuffer */ 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 /*return -1;*/ 00353 /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't 00354 be delivered at all */ 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 }
| 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 567 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_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, and ast_jb_conf::resync_threshold.
Referenced by _build_general_config(), gtalk_load_config(), jingle_load_config(), load_module(), process_dahdi(), reload_config(), store_config(), and store_config_core().
00568 { 00569 int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1; 00570 const char *name; 00571 int tmp; 00572 00573 if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) 00574 return -1; 00575 00576 name = varname + prefixlen; 00577 00578 if (!strcasecmp(name, AST_JB_CONF_ENABLE)) { 00579 ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED); 00580 } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) { 00581 ast_set2_flag(conf, ast_true(value), AST_JB_FORCED); 00582 } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) { 00583 if ((tmp = atoi(value)) > 0) 00584 conf->max_size = tmp; 00585 } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) { 00586 if ((tmp = atoi(value)) > 0) 00587 conf->resync_threshold = tmp; 00588 } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) { 00589 if (!ast_strlen_zero(value)) 00590 snprintf(conf->impl, sizeof(conf->impl), "%s", value); 00591 } else if (!strcasecmp(name, AST_JB_CONF_LOG)) { 00592 ast_set2_flag(conf, ast_true(value), AST_JB_LOG); 00593 } else { 00594 return -1; 00595 } 00596 00597 return 0; 00598 }
1.6.1