Common implementation-independent jitterbuffer stuff. More...
#include "asterisk.h"#include "asterisk/frame.h"#include "asterisk/channel.h"#include "asterisk/term.h"#include "asterisk/utils.h"#include "asterisk/abstract_jb.h"#include "fixedjitterbuf.h"#include "jitterbuf.h"
Go to the source code of this file.
Data Structures | |
| struct | ast_jb_impl |
| Jitterbuffer implementation private struct. More... | |
Defines | |
| #define | jb_framelog(...) |
| Macros for the frame log files. | |
Typedefs | |
| typedef void *(* | jb_create_impl )(struct ast_jb_conf *general_config, long resynch_threshold) |
| Create. | |
| typedef void(* | jb_destroy_impl )(void *jb) |
| Destroy. | |
| typedef void(* | jb_empty_and_reset_impl )(void *jb) |
| Empty and reset jb. | |
| typedef void(* | jb_force_resynch_impl )(void *jb) |
| Force resynch. | |
| typedef int(* | jb_get_impl )(void *jb, struct ast_frame **fout, long now, long interpl) |
| Get frame for now. | |
| typedef long(* | jb_next_impl )(void *jb) |
| Get next. | |
| typedef int(* | jb_put_first_impl )(void *jb, struct ast_frame *fin, long now) |
| Put first frame. | |
| typedef int(* | jb_put_impl )(void *jb, struct ast_frame *fin, long now) |
| Put frame. | |
| typedef int(* | jb_remove_impl )(void *jb, struct ast_frame **fout) |
| Remove first frame. | |
Enumerations | |
| enum | { JB_USE = (1 << 0), JB_TIMEBASE_INITIALIZED = (1 << 1), JB_CREATED = (1 << 2) } |
| enum | { JB_IMPL_OK, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME } |
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. | |
| static int | create_jb (struct ast_channel *chan, struct ast_frame *first_frame) |
| static long | get_now (struct ast_jb *jb, struct timeval *tv) |
| static void | jb_choose_impl (struct ast_channel *chan) |
| static void * | jb_create_adaptive (struct ast_jb_conf *general_config, long resynch_threshold) |
| static void * | jb_create_fixed (struct ast_jb_conf *general_config, long resynch_threshold) |
| static void | jb_destroy_adaptive (void *jb) |
| static void | jb_destroy_fixed (void *jb) |
| static void | jb_empty_and_reset_adaptive (void *jb) |
| static void | jb_empty_and_reset_fixed (void *jb) |
| static void | jb_force_resynch_adaptive (void *jb) |
| static void | jb_force_resynch_fixed (void *jb) |
| static int | jb_get_adaptive (void *jb, struct ast_frame **fout, long now, long interpl) |
| static void | jb_get_and_deliver (struct ast_channel *chan) |
| static int | jb_get_fixed (void *jb, struct ast_frame **fout, long now, long interpl) |
| static long | jb_next_adaptive (void *jb) |
| static long | jb_next_fixed (void *jb) |
| static int | jb_put_adaptive (void *jb, struct ast_frame *fin, long now) |
| static int | jb_put_first_adaptive (void *jb, struct ast_frame *fin, long now) |
| static int | jb_put_first_fixed (void *jb, struct ast_frame *fin, long now) |
| static int | jb_put_fixed (void *jb, struct ast_frame *fin, long now) |
| static int | jb_remove_adaptive (void *jb, struct ast_frame **fout) |
| static int | jb_remove_fixed (void *jb, struct ast_frame **fout) |
Variables | |
| static int | adaptive_to_abstract_code [] |
| static struct ast_jb_impl | avail_impl [] |
| static int | default_impl = 0 |
| static int | fixed_to_abstract_code [] |
| static char * | jb_get_actions [] = {"Delivered", "Dropped", "Interpolated", "No"} |
Common implementation-independent jitterbuffer stuff.
Definition in file abstract_jb.c.
| #define jb_framelog | ( | ... | ) |
Macros for the frame log files.
Definition at line 162 of file abstract_jb.c.
Referenced by ast_jb_put(), create_jb(), and jb_get_and_deliver().
| typedef void*(* jb_create_impl)(struct ast_jb_conf *general_config, long resynch_threshold) |
Create.
Definition at line 55 of file abstract_jb.c.
| typedef void(* jb_destroy_impl)(void *jb) |
Destroy.
Definition at line 57 of file abstract_jb.c.
| typedef void(* jb_empty_and_reset_impl)(void *jb) |
Empty and reset jb.
Definition at line 71 of file abstract_jb.c.
| typedef void(* jb_force_resynch_impl)(void *jb) |
Force resynch.
Definition at line 69 of file abstract_jb.c.
| typedef int(* jb_get_impl)(void *jb, struct ast_frame **fout, long now, long interpl) |
Get frame for now.
Definition at line 63 of file abstract_jb.c.
| typedef long(* jb_next_impl)(void *jb) |
Get next.
Definition at line 65 of file abstract_jb.c.
| typedef int(* jb_put_first_impl)(void *jb, struct ast_frame *fin, long now) |
Put first frame.
Definition at line 59 of file abstract_jb.c.
| typedef int(* jb_put_impl)(void *jb, struct ast_frame *fin, long now) |
Put frame.
Definition at line 61 of file abstract_jb.c.
| typedef int(* jb_remove_impl)(void *jb, struct ast_frame **fout) |
Remove first frame.
Definition at line 67 of file abstract_jb.c.
| anonymous enum |
Internal jb flags
Definition at line 46 of file abstract_jb.c.
00046 { 00047 JB_USE = (1 << 0), 00048 JB_TIMEBASE_INITIALIZED = (1 << 1), 00049 JB_CREATED = (1 << 2) 00050 };
| anonymous enum |
Abstract return codes
Definition at line 145 of file abstract_jb.c.
00145 { 00146 JB_IMPL_OK, 00147 JB_IMPL_DROP, 00148 JB_IMPL_INTERP, 00149 JB_IMPL_NOFRAME 00150 };
| 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 }
| static int create_jb | ( | struct ast_channel * | chan, | |
| struct ast_frame * | first_frame | |||
| ) | [static] |
Definition at line 445 of file abstract_jb.c.
References ast_assert, ast_bridged_channel(), AST_CHANNEL_NAME, ast_frfree, AST_JB_IMPL_NAME_SIZE, AST_JB_LOG, ast_log(), ast_test_flag, ast_verb, ast_jb::conf, ast_jb_impl::create, errno, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, JB_IMPL_OK, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb::logfile, ast_jb_impl::name, ast_channel::name, ast_jb_impl::next, ast_jb::next, ast_jb_impl::put_first, ast_jb_conf::resync_threshold, ast_frame::subclass, and ast_frame::ts.
Referenced by ast_jb_put().
00446 { 00447 struct ast_jb *jb = &chan->jb; 00448 struct ast_jb_conf *jbconf = &jb->conf; 00449 struct ast_jb_impl *jbimpl = jb->impl; 00450 void *jbobj; 00451 struct ast_channel *bridged; 00452 long now; 00453 char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1]; 00454 char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp; 00455 int res; 00456 00457 jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold); 00458 if (!jbobj) { 00459 ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name); 00460 return -1; 00461 } 00462 00463 now = get_now(jb, NULL); 00464 res = jbimpl->put_first(jbobj, frr, now); 00465 00466 /* The result of putting the first frame should not differ from OK. However, its possible 00467 some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */ 00468 if (res != JB_IMPL_OK) { 00469 ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name); 00470 /* 00471 jbimpl->destroy(jbobj); 00472 return -1; 00473 */ 00474 } 00475 00476 /* Init next */ 00477 jb->next = jbimpl->next(jbobj); 00478 00479 /* Init last format for a first time. */ 00480 jb->last_format = frr->subclass; 00481 00482 /* Create a frame log file */ 00483 if (ast_test_flag(jbconf, AST_JB_LOG)) { 00484 char safe_logfile[30] = "/tmp/logfile-XXXXXX"; 00485 int safe_fd; 00486 snprintf(name2, sizeof(name2), "%s", chan->name); 00487 if ((tmp = strchr(name2, '/'))) { 00488 *tmp = '#'; 00489 } 00490 00491 bridged = ast_bridged_channel(chan); 00492 /* We should always have bridged chan if a jitterbuffer is in use */ 00493 ast_assert(bridged != NULL); 00494 00495 snprintf(name1, sizeof(name1), "%s", bridged->name); 00496 if ((tmp = strchr(name1, '/'))) { 00497 *tmp = '#'; 00498 } 00499 00500 snprintf(logfile_pathname, sizeof(logfile_pathname), 00501 "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2); 00502 if (!(safe_fd = mkstemp(safe_logfile)) > -1 || unlink(logfile_pathname) || link(safe_logfile, logfile_pathname) || unlink(safe_logfile) || !(jb->logfile = fdopen(safe_fd, "w+b"))) { 00503 jb->logfile = NULL; 00504 if (safe_fd > -1) { 00505 close(safe_fd); 00506 } 00507 ast_log(LOG_ERROR, "Failed to create frame log file with pathname '%s': %s\n", logfile_pathname, strerror(errno)); 00508 } 00509 00510 if (res == JB_IMPL_OK) { 00511 jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n", 00512 now, frr->ts, frr->len); 00513 } else { 00514 jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", 00515 now, frr->ts, frr->len); 00516 } 00517 } 00518 00519 ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name); 00520 00521 /* Free the frame if it has not been queued in the jb */ 00522 if (res != JB_IMPL_OK) { 00523 ast_frfree(frr); 00524 } 00525 00526 return 0; 00527 }
| static long get_now | ( | struct ast_jb * | jb, | |
| struct timeval * | tv | |||
| ) | [static] |
Definition at line 558 of file abstract_jb.c.
References ast_tvdiff_ms(), and ast_jb::timebase.
Referenced by ast_jb_get_when_to_wakeup(), ast_jb_put(), create_jb(), and jb_get_and_deliver().
00559 { 00560 struct timeval now; 00561 00562 if (!when) { 00563 when = &now; 00564 gettimeofday(when, NULL); 00565 } 00566 00567 return ast_tvdiff_ms(*when, jb->timebase); 00568 }
| static void jb_choose_impl | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 180 of file abstract_jb.c.
References ARRAY_LEN, ast_strlen_zero(), ast_jb::conf, ast_jb_conf::impl, ast_jb::impl, ast_channel::jb, and ast_jb_impl::name.
Referenced by ast_jb_do_usecheck().
00181 { 00182 struct ast_jb *jb = &chan->jb; 00183 struct ast_jb_conf *jbconf = &jb->conf; 00184 struct ast_jb_impl *test_impl; 00185 int i, avail_impl_count = ARRAY_LEN(avail_impl); 00186 00187 jb->impl = &avail_impl[default_impl]; 00188 00189 if (ast_strlen_zero(jbconf->impl)) { 00190 return; 00191 } 00192 00193 for (i = 0; i < avail_impl_count; i++) { 00194 test_impl = &avail_impl[i]; 00195 if (!strcasecmp(jbconf->impl, test_impl->name)) { 00196 jb->impl = test_impl; 00197 return; 00198 } 00199 } 00200 }
| static void * jb_create_adaptive | ( | struct ast_jb_conf * | general_config, | |
| long | resynch_threshold | |||
| ) | [static] |
Definition at line 736 of file abstract_jb.c.
References jb_new(), jb_setconf(), jb_conf::max_contig_interp, jb_conf::max_jitterbuf, ast_jb_conf::max_size, ast_jb_conf::resync_threshold, jb_conf::resync_threshold, ast_jb_conf::target_extra, and jb_conf::target_extra.
00737 { 00738 jb_conf jbconf; 00739 jitterbuf *adaptivejb; 00740 00741 adaptivejb = jb_new(); 00742 if (adaptivejb) { 00743 jbconf.max_jitterbuf = general_config->max_size; 00744 jbconf.resync_threshold = general_config->resync_threshold; 00745 jbconf.max_contig_interp = 10; 00746 jbconf.target_extra = general_config->target_extra; 00747 jb_setconf(adaptivejb, &jbconf); 00748 } 00749 00750 return adaptivejb; 00751 }
| static void * jb_create_fixed | ( | struct ast_jb_conf * | general_config, | |
| long | resynch_threshold | |||
| ) | [static] |
Definition at line 642 of file abstract_jb.c.
References fixed_jb_new(), fixed_jb_conf::jbsize, ast_jb_conf::max_size, and fixed_jb_conf::resync_threshold.
00643 { 00644 struct fixed_jb_conf conf; 00645 00646 conf.jbsize = general_config->max_size; 00647 conf.resync_threshold = resynch_threshold; 00648 00649 return fixed_jb_new(&conf); 00650 }
| static void jb_destroy_adaptive | ( | void * | jb | ) | [static] |
Definition at line 754 of file abstract_jb.c.
References jb_destroy().
00755 { 00756 jitterbuf *adaptivejb = (jitterbuf *) jb; 00757 00758 jb_destroy(adaptivejb); 00759 }
| static void jb_destroy_fixed | ( | void * | jb | ) | [static] |
Definition at line 652 of file abstract_jb.c.
References fixed_jb_destroy().
00653 { 00654 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00655 00656 /* destroy the jb */ 00657 fixed_jb_destroy(fixedjb); 00658 }
| static void jb_empty_and_reset_adaptive | ( | void * | jb | ) | [static] |
Definition at line 817 of file abstract_jb.c.
References ast_frfree, jb_frame::data, f, jb_getall(), JB_OK, and jb_reset().
| static void jb_empty_and_reset_fixed | ( | void * | jb | ) | [static] |
Definition at line 724 of file abstract_jb.c.
References ast_frfree, fixed_jb_frame::data, FIXED_JB_OK, and fixed_jb_remove().
00725 { 00726 struct fixed_jb *fixedjb = jb; 00727 struct fixed_jb_frame f; 00728 00729 while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) { 00730 ast_frfree(f.data); 00731 } 00732 }
| static void jb_force_resynch_adaptive | ( | void * | jb | ) | [static] |
Definition at line 813 of file abstract_jb.c.
| static void jb_force_resynch_fixed | ( | void * | jb | ) | [static] |
Definition at line 717 of file abstract_jb.c.
References fixed_jb_set_force_resynch().
00718 { 00719 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00720 00721 fixed_jb_set_force_resynch(fixedjb); 00722 }
| static int jb_get_adaptive | ( | void * | jb, | |
| struct ast_frame ** | fout, | |||
| long | now, | |||
| long | interpl | |||
| ) | [static] |
Definition at line 779 of file abstract_jb.c.
References jb_frame::data, and jb_get().
| static void jb_get_and_deliver | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 385 of file abstract_jb.c.
References ast_assert, ast_codec_interp_len(), AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), ast_samp2tv(), ast_tvadd(), ast_write(), ast_frame::delivery, f, ast_jb_impl::get, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME, JB_IMPL_OK, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb_impl::name, ast_frame::next, ast_jb_impl::next, ast_jb::next, ast_frame::offset, ast_frame::samples, ast_frame::src, ast_frame::subclass, ast_jb::timebase, and ast_frame::ts.
Referenced by ast_jb_get_and_deliver().
00386 { 00387 struct ast_jb *jb = &chan->jb; 00388 struct ast_jb_impl *jbimpl = jb->impl; 00389 void *jbobj = jb->jbobj; 00390 struct ast_frame *f, finterp = { .frametype = AST_FRAME_VOICE, }; 00391 long now; 00392 int interpolation_len, res; 00393 00394 now = get_now(jb, NULL); 00395 jb->next = jbimpl->next(jbobj); 00396 if (now < jb->next) { 00397 jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next); 00398 return; 00399 } 00400 00401 while (now >= jb->next) { 00402 interpolation_len = ast_codec_interp_len(jb->last_format); 00403 00404 res = jbimpl->get(jbobj, &f, now, interpolation_len); 00405 00406 switch (res) { 00407 case JB_IMPL_OK: 00408 /* deliver the frame */ 00409 ast_write(chan, f); 00410 case JB_IMPL_DROP: 00411 jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n", 00412 now, jb_get_actions[res], f->ts, f->len); 00413 jb->last_format = f->subclass; 00414 ast_frfree(f); 00415 break; 00416 case JB_IMPL_INTERP: 00417 /* interpolate a frame */ 00418 f = &finterp; 00419 f->subclass = jb->last_format; 00420 f->samples = interpolation_len * 8; 00421 f->src = "JB interpolation"; 00422 f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000)); 00423 f->offset = AST_FRIENDLY_OFFSET; 00424 /* deliver the interpolated frame */ 00425 ast_write(chan, f); 00426 jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len); 00427 break; 00428 case JB_IMPL_NOFRAME: 00429 ast_log(LOG_WARNING, 00430 "JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n", 00431 jbimpl->name, now, jb->next, jbimpl->next(jbobj)); 00432 jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now); 00433 return; 00434 default: 00435 ast_log(LOG_ERROR, "This should never happen!\n"); 00436 ast_assert("JB type unknown" == NULL); 00437 break; 00438 } 00439 00440 jb->next = jbimpl->next(jbobj); 00441 } 00442 }
| static int jb_get_fixed | ( | void * | jb, | |
| struct ast_frame ** | fout, | |||
| long | now, | |||
| long | interpl | |||
| ) | [static] |
Definition at line 683 of file abstract_jb.c.
References fixed_jb_frame::data, and fixed_jb_get().
00684 { 00685 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00686 struct fixed_jb_frame frame; 00687 int res; 00688 00689 res = fixed_jb_get(fixedjb, &frame, now, interpl); 00690 *fout = frame.data; 00691 00692 return fixed_to_abstract_code[res]; 00693 }
| static long jb_next_adaptive | ( | void * | jb | ) | [static] |
| static long jb_next_fixed | ( | void * | jb | ) | [static] |
Definition at line 696 of file abstract_jb.c.
References fixed_jb_next().
00697 { 00698 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00699 00700 return fixed_jb_next(fixedjb); 00701 }
| static int jb_put_adaptive | ( | void * | jb, | |
| struct ast_frame * | fin, | |||
| long | now | |||
| ) | [static] |
Definition at line 768 of file abstract_jb.c.
References jb_put(), JB_TYPE_VOICE, ast_frame::len, and ast_frame::ts.
Referenced by jb_put_first_adaptive().
00769 { 00770 jitterbuf *adaptivejb = (jitterbuf *) jb; 00771 int res; 00772 00773 res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now); 00774 00775 return adaptive_to_abstract_code[res]; 00776 }
| static int jb_put_first_adaptive | ( | void * | jb, | |
| struct ast_frame * | fin, | |||
| long | now | |||
| ) | [static] |
Definition at line 762 of file abstract_jb.c.
References jb_put_adaptive().
00763 { 00764 return jb_put_adaptive(jb, fin, now); 00765 }
| static int jb_put_first_fixed | ( | void * | jb, | |
| struct ast_frame * | fin, | |||
| long | now | |||
| ) | [static] |
Definition at line 661 of file abstract_jb.c.
References fixed_jb_put_first(), ast_frame::len, and ast_frame::ts.
00662 { 00663 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00664 int res; 00665 00666 res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now); 00667 00668 return fixed_to_abstract_code[res]; 00669 }
| static int jb_put_fixed | ( | void * | jb, | |
| struct ast_frame * | fin, | |||
| long | now | |||
| ) | [static] |
Definition at line 672 of file abstract_jb.c.
References fixed_jb_put(), ast_frame::len, and ast_frame::ts.
00673 { 00674 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00675 int res; 00676 00677 res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now); 00678 00679 return fixed_to_abstract_code[res]; 00680 }
| static int jb_remove_adaptive | ( | void * | jb, | |
| struct ast_frame ** | fout | |||
| ) | [static] |
Definition at line 800 of file abstract_jb.c.
References jb_frame::data, and jb_getall().
| static int jb_remove_fixed | ( | void * | jb, | |
| struct ast_frame ** | fout | |||
| ) | [static] |
Definition at line 704 of file abstract_jb.c.
References fixed_jb_frame::data, and fixed_jb_remove().
00705 { 00706 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00707 struct fixed_jb_frame frame; 00708 int res; 00709 00710 res = fixed_jb_remove(fixedjb, &frame); 00711 *fout = frame.data; 00712 00713 return fixed_to_abstract_code[res]; 00714 }
int adaptive_to_abstract_code[] [static] |
{JB_IMPL_OK, JB_IMPL_NOFRAME, JB_IMPL_NOFRAME, JB_IMPL_INTERP, JB_IMPL_DROP, JB_IMPL_OK}
Definition at line 155 of file abstract_jb.c.
struct ast_jb_impl avail_impl[] [static] |
Definition at line 113 of file abstract_jb.c.
int default_impl = 0 [static] |
Definition at line 141 of file abstract_jb.c.
int fixed_to_abstract_code[] [static] |
Definition at line 153 of file abstract_jb.c.
char* jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"} [static] |
Definition at line 159 of file abstract_jb.c.
1.6.2