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 const int | adaptive_to_abstract_code [] |
static struct ast_jb_impl | avail_impl [] |
static int | default_impl = 0 |
static const int | fixed_to_abstract_code [] |
static const char *const | 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 165 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 59 of file abstract_jb.c.
typedef void(* jb_destroy_impl)(void *jb) |
Destroy.
Definition at line 61 of file abstract_jb.c.
typedef void(* jb_empty_and_reset_impl)(void *jb) |
Empty and reset jb.
Definition at line 75 of file abstract_jb.c.
typedef void(* jb_force_resynch_impl)(void *jb) |
Force resynch.
Definition at line 73 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 67 of file abstract_jb.c.
typedef long(* jb_next_impl)(void *jb) |
Get next.
Definition at line 69 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 63 of file abstract_jb.c.
typedef int(* jb_put_impl)(void *jb, struct ast_frame *fin, long now) |
Put frame.
Definition at line 65 of file abstract_jb.c.
typedef int(* jb_remove_impl)(void *jb, struct ast_frame **fout) |
Remove first frame.
Definition at line 71 of file abstract_jb.c.
anonymous enum |
Internal jb flags
Definition at line 50 of file abstract_jb.c.
00050 { 00051 JB_USE = (1 << 0), 00052 JB_TIMEBASE_INITIALIZED = (1 << 1), 00053 JB_CREATED = (1 << 2) 00054 };
anonymous enum |
Abstract return codes
Definition at line 148 of file abstract_jb.c.
00148 { 00149 JB_IMPL_OK, 00150 JB_IMPL_DROP, 00151 JB_IMPL_INTERP, 00152 JB_IMPL_NOFRAME 00153 };
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=%u, 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 }
static int create_jb | ( | struct ast_channel * | chan, | |
struct ast_frame * | first_frame | |||
) | [static] |
Definition at line 449 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_frame_subclass::codec, 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_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().
00450 { 00451 struct ast_jb *jb = &chan->jb; 00452 struct ast_jb_conf *jbconf = &jb->conf; 00453 const struct ast_jb_impl *jbimpl = jb->impl; 00454 void *jbobj; 00455 struct ast_channel *bridged; 00456 long now; 00457 char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1]; 00458 char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp; 00459 int res; 00460 00461 jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold); 00462 if (!jbobj) { 00463 ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name); 00464 return -1; 00465 } 00466 00467 now = get_now(jb, NULL); 00468 res = jbimpl->put_first(jbobj, frr, now); 00469 00470 /* The result of putting the first frame should not differ from OK. However, its possible 00471 some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */ 00472 if (res != JB_IMPL_OK) { 00473 ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name); 00474 /* 00475 jbimpl->destroy(jbobj); 00476 return -1; 00477 */ 00478 } 00479 00480 /* Init next */ 00481 jb->next = jbimpl->next(jbobj); 00482 00483 /* Init last format for a first time. */ 00484 jb->last_format = frr->subclass.codec; 00485 00486 /* Create a frame log file */ 00487 if (ast_test_flag(jbconf, AST_JB_LOG)) { 00488 char safe_logfile[30] = "/tmp/logfile-XXXXXX"; 00489 int safe_fd; 00490 snprintf(name2, sizeof(name2), "%s", chan->name); 00491 while ((tmp = strchr(name2, '/'))) { 00492 *tmp = '#'; 00493 } 00494 00495 bridged = ast_bridged_channel(chan); 00496 /* We should always have bridged chan if a jitterbuffer is in use */ 00497 ast_assert(bridged != NULL); 00498 00499 snprintf(name1, sizeof(name1), "%s", bridged->name); 00500 while ((tmp = strchr(name1, '/'))) { 00501 *tmp = '#'; 00502 } 00503 00504 snprintf(logfile_pathname, sizeof(logfile_pathname), 00505 "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2); 00506 unlink(logfile_pathname); 00507 safe_fd = mkstemp(safe_logfile); 00508 if (safe_fd < 0 || link(safe_logfile, logfile_pathname) || unlink(safe_logfile) || !(jb->logfile = fdopen(safe_fd, "w+b"))) { 00509 ast_log(LOG_ERROR, "Failed to create frame log file with pathname '%s': %s\n", logfile_pathname, strerror(errno)); 00510 jb->logfile = NULL; 00511 if (safe_fd > -1) { 00512 close(safe_fd); 00513 } 00514 } 00515 00516 if (res == JB_IMPL_OK) { 00517 jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n", 00518 now, frr->ts, frr->len); 00519 } else { 00520 jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", 00521 now, frr->ts, frr->len); 00522 } 00523 } 00524 00525 ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name); 00526 00527 /* Free the frame if it has not been queued in the jb */ 00528 if (res != JB_IMPL_OK) { 00529 ast_frfree(frr); 00530 } 00531 00532 return 0; 00533 }
static long get_now | ( | struct ast_jb * | jb, | |
struct timeval * | tv | |||
) | [static] |
Definition at line 564 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().
00565 { 00566 struct timeval now; 00567 00568 if (!when) { 00569 when = &now; 00570 gettimeofday(when, NULL); 00571 } 00572 00573 return ast_tvdiff_ms(*when, jb->timebase); 00574 }
static void jb_choose_impl | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 183 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().
00184 { 00185 struct ast_jb *jb = &chan->jb; 00186 struct ast_jb_conf *jbconf = &jb->conf; 00187 const struct ast_jb_impl *test_impl; 00188 int i, avail_impl_count = ARRAY_LEN(avail_impl); 00189 00190 jb->impl = &avail_impl[default_impl]; 00191 00192 if (ast_strlen_zero(jbconf->impl)) { 00193 return; 00194 } 00195 00196 for (i = 0; i < avail_impl_count; i++) { 00197 test_impl = &avail_impl[i]; 00198 if (!strcasecmp(jbconf->impl, test_impl->name)) { 00199 jb->impl = test_impl; 00200 return; 00201 } 00202 } 00203 }
static void * jb_create_adaptive | ( | struct ast_jb_conf * | general_config, | |
long | resynch_threshold | |||
) | [static] |
Definition at line 742 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.
00743 { 00744 jb_conf jbconf; 00745 jitterbuf *adaptivejb; 00746 00747 adaptivejb = jb_new(); 00748 if (adaptivejb) { 00749 jbconf.max_jitterbuf = general_config->max_size; 00750 jbconf.resync_threshold = general_config->resync_threshold; 00751 jbconf.max_contig_interp = 10; 00752 jbconf.target_extra = general_config->target_extra; 00753 jb_setconf(adaptivejb, &jbconf); 00754 } 00755 00756 return adaptivejb; 00757 }
static void * jb_create_fixed | ( | struct ast_jb_conf * | general_config, | |
long | resynch_threshold | |||
) | [static] |
Definition at line 648 of file abstract_jb.c.
References fixed_jb_new(), fixed_jb_conf::jbsize, ast_jb_conf::max_size, and fixed_jb_conf::resync_threshold.
00649 { 00650 struct fixed_jb_conf conf; 00651 00652 conf.jbsize = general_config->max_size; 00653 conf.resync_threshold = resynch_threshold; 00654 00655 return fixed_jb_new(&conf); 00656 }
static void jb_destroy_adaptive | ( | void * | jb | ) | [static] |
Definition at line 760 of file abstract_jb.c.
References jb_destroy().
00761 { 00762 jitterbuf *adaptivejb = (jitterbuf *) jb; 00763 00764 jb_destroy(adaptivejb); 00765 }
static void jb_destroy_fixed | ( | void * | jb | ) | [static] |
Definition at line 658 of file abstract_jb.c.
References fixed_jb_destroy().
00659 { 00660 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00661 00662 /* destroy the jb */ 00663 fixed_jb_destroy(fixedjb); 00664 }
static void jb_empty_and_reset_adaptive | ( | void * | jb | ) | [static] |
Definition at line 828 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 730 of file abstract_jb.c.
References ast_frfree, fixed_jb_frame::data, FIXED_JB_OK, and fixed_jb_remove().
00731 { 00732 struct fixed_jb *fixedjb = jb; 00733 struct fixed_jb_frame f; 00734 00735 while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) { 00736 ast_frfree(f.data); 00737 } 00738 }
static void jb_force_resynch_adaptive | ( | void * | jb | ) | [static] |
Definition at line 824 of file abstract_jb.c.
static void jb_force_resynch_fixed | ( | void * | jb | ) | [static] |
Definition at line 723 of file abstract_jb.c.
References fixed_jb_set_force_resynch().
00724 { 00725 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00726 00727 fixed_jb_set_force_resynch(fixedjb); 00728 }
static int jb_get_adaptive | ( | void * | jb, | |
struct ast_frame ** | fout, | |||
long | now, | |||
long | interpl | |||
) | [static] |
Definition at line 790 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 388 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_subclass::codec, 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_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().
00389 { 00390 struct ast_jb *jb = &chan->jb; 00391 const struct ast_jb_impl *jbimpl = jb->impl; 00392 void *jbobj = jb->jbobj; 00393 struct ast_frame *f, finterp = { .frametype = AST_FRAME_VOICE, }; 00394 long now; 00395 int interpolation_len, res; 00396 00397 now = get_now(jb, NULL); 00398 jb->next = jbimpl->next(jbobj); 00399 if (now < jb->next) { 00400 jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next); 00401 return; 00402 } 00403 00404 while (now >= jb->next) { 00405 interpolation_len = ast_codec_interp_len(jb->last_format); 00406 00407 res = jbimpl->get(jbobj, &f, now, interpolation_len); 00408 00409 switch (res) { 00410 case JB_IMPL_OK: 00411 /* deliver the frame */ 00412 ast_write(chan, f); 00413 /* Fall through intentionally */ 00414 case JB_IMPL_DROP: 00415 jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n", 00416 now, jb_get_actions[res], f->ts, f->len); 00417 jb->last_format = f->subclass.codec; 00418 ast_frfree(f); 00419 break; 00420 case JB_IMPL_INTERP: 00421 /* interpolate a frame */ 00422 f = &finterp; 00423 f->subclass.codec = jb->last_format; 00424 f->samples = interpolation_len * 8; 00425 f->src = "JB interpolation"; 00426 f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000)); 00427 f->offset = AST_FRIENDLY_OFFSET; 00428 /* deliver the interpolated frame */ 00429 ast_write(chan, f); 00430 jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len); 00431 break; 00432 case JB_IMPL_NOFRAME: 00433 ast_log(LOG_WARNING, 00434 "JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n", 00435 jbimpl->name, now, jb->next, jbimpl->next(jbobj)); 00436 jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now); 00437 return; 00438 default: 00439 ast_log(LOG_ERROR, "This should never happen!\n"); 00440 ast_assert("JB type unknown" == NULL); 00441 break; 00442 } 00443 00444 jb->next = jbimpl->next(jbobj); 00445 } 00446 }
static int jb_get_fixed | ( | void * | jb, | |
struct ast_frame ** | fout, | |||
long | now, | |||
long | interpl | |||
) | [static] |
Definition at line 689 of file abstract_jb.c.
References fixed_jb_frame::data, and fixed_jb_get().
00690 { 00691 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00692 struct fixed_jb_frame frame; 00693 int res; 00694 00695 res = fixed_jb_get(fixedjb, &frame, now, interpl); 00696 *fout = frame.data; 00697 00698 return fixed_to_abstract_code[res]; 00699 }
static long jb_next_adaptive | ( | void * | jb | ) | [static] |
static long jb_next_fixed | ( | void * | jb | ) | [static] |
Definition at line 702 of file abstract_jb.c.
References fixed_jb_next().
00703 { 00704 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00705 00706 return fixed_jb_next(fixedjb); 00707 }
static int jb_put_adaptive | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 779 of file abstract_jb.c.
References jb_put(), JB_TYPE_VOICE, ast_frame::len, and ast_frame::ts.
Referenced by jb_put_first_adaptive().
00780 { 00781 jitterbuf *adaptivejb = (jitterbuf *) jb; 00782 int res; 00783 00784 res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now); 00785 00786 return adaptive_to_abstract_code[res]; 00787 }
static int jb_put_first_adaptive | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 768 of file abstract_jb.c.
References jitterbuf::info, jb_put_adaptive(), jb_info::resync_offset, and ast_frame::ts.
00769 { 00770 jitterbuf *adaptivejb = (jitterbuf *) jb; 00771 00772 /* Initialize the offset to that of the first frame's timestamp */ 00773 adaptivejb->info.resync_offset = fin->ts; 00774 00775 return jb_put_adaptive(jb, fin, now); 00776 }
static int jb_put_first_fixed | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 667 of file abstract_jb.c.
References fixed_jb_put_first(), ast_frame::len, and ast_frame::ts.
00668 { 00669 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00670 int res; 00671 00672 res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now); 00673 00674 return fixed_to_abstract_code[res]; 00675 }
static int jb_put_fixed | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 678 of file abstract_jb.c.
References fixed_jb_put(), ast_frame::len, and ast_frame::ts.
00679 { 00680 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00681 int res; 00682 00683 res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now); 00684 00685 return fixed_to_abstract_code[res]; 00686 }
static int jb_remove_adaptive | ( | void * | jb, | |
struct ast_frame ** | fout | |||
) | [static] |
Definition at line 811 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 710 of file abstract_jb.c.
References fixed_jb_frame::data, and fixed_jb_remove().
00711 { 00712 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00713 struct fixed_jb_frame frame; 00714 int res; 00715 00716 res = fixed_jb_remove(fixedjb, &frame); 00717 *fout = frame.data; 00718 00719 return fixed_to_abstract_code[res]; 00720 }
const 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 158 of file abstract_jb.c.
struct ast_jb_impl avail_impl[] [static] |
Definition at line 117 of file abstract_jb.c.
int default_impl = 0 [static] |
Definition at line 144 of file abstract_jb.c.
const int fixed_to_abstract_code[] [static] |
Definition at line 156 of file abstract_jb.c.
const char* const jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"} [static] |
Definition at line 162 of file abstract_jb.c.