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.
{ JB_USE = (1 << 0), JB_TIMEBASE_INITIALIZED = (1 << 1), JB_CREATED = (1 << 2) };
anonymous enum |
Abstract return codes
Definition at line 145 of file abstract_jb.c.
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 612 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 532 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().
{ struct ast_jb *jb = &chan->jb; struct ast_jb_impl *jbimpl = jb->impl; void *jbobj = jb->jbobj; struct ast_frame *f; if (jb->logfile) { fclose(jb->logfile); jb->logfile = NULL; } if (ast_test_flag(jb, JB_CREATED)) { /* Remove and free all frames still queued in jb */ while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) { ast_frfree(f); } jbimpl->destroy(jbobj); jb->jbobj = NULL; ast_clear_flag(jb, JB_CREATED); ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name); } }
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().
{ struct ast_jb *jb0 = &c0->jb; struct ast_jb *jb1 = &c1->jb; struct ast_jb_conf *conf0 = &jb0->conf; struct ast_jb_conf *conf1 = &jb1->conf; int c0_wants_jitter = c0->tech->properties & AST_CHAN_TP_WANTSJITTER; int c0_creates_jitter = c0->tech->properties & AST_CHAN_TP_CREATESJITTER; int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED); int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED); int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED); int c0_jb_created = ast_test_flag(jb0, JB_CREATED); int c1_wants_jitter = c1->tech->properties & AST_CHAN_TP_WANTSJITTER; int c1_creates_jitter = c1->tech->properties & AST_CHAN_TP_CREATESJITTER; int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED); int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED); int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED); int c1_jb_created = ast_test_flag(jb1, JB_CREATED); int inuse = 0; /* Determine whether audio going to c0 needs a jitter buffer */ if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) { ast_set_flag(jb0, JB_USE); if (!c0_jb_timebase_initialized) { if (c1_jb_timebase_initialized) { memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval)); } else { gettimeofday(&jb0->timebase, NULL); } ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED); } if (!c0_jb_created) { jb_choose_impl(c0); } inuse = 1; } /* Determine whether audio going to c1 needs a jitter buffer */ if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) { ast_set_flag(jb1, JB_USE); if (!c1_jb_timebase_initialized) { if (c0_jb_timebase_initialized) { memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval)); } else { gettimeofday(&jb1->timebase, NULL); } ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED); } if (!c1_jb_created) { jb_choose_impl(c1); } inuse = 1; } return inuse; }
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 623 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().
{ struct ast_jb *jb0 = &c0->jb; struct ast_jb *jb1 = &c1->jb; int c0_use_jb = ast_test_flag(jb0, JB_USE); int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); int c1_use_jb = ast_test_flag(jb1, JB_USE); int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) { jb0->impl->empty_and_reset(jb0->jbobj); } if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) { jb1->impl->empty_and_reset(jb1->jbobj); } }
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().
{ struct ast_jb *jb0 = &c0->jb; struct ast_jb *jb1 = &c1->jb; int c0_use_jb = ast_test_flag(jb0, JB_USE); int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); int c1_use_jb = ast_test_flag(jb1, JB_USE); int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); if (c0_use_jb && c0_jb_is_created) jb_get_and_deliver(c0); if (c1_use_jb && c1_jb_is_created) jb_get_and_deliver(c1); }
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 618 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().
{ struct ast_jb *jb0 = &c0->jb; struct ast_jb *jb1 = &c1->jb; int c0_use_jb = ast_test_flag(jb0, JB_USE); int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); int c1_use_jb = ast_test_flag(jb1, JB_USE); int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); int wait, wait0, wait1; struct timeval tv_now; if (time_left == 0) { /* No time left - the bridge will be retried */ /* TODO: Test disable this */ /*return 0;*/ } if (time_left < 0) { time_left = INT_MAX; } gettimeofday(&tv_now, NULL); wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left; wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left; wait = wait0 < wait1 ? wait0 : wait1; wait = wait < time_left ? wait : time_left; if (wait == INT_MAX) { wait = -1; } else if (wait < 1) { /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */ wait = 1; } return wait; }
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().
{ struct ast_jb *jb = &chan->jb; struct ast_jb_impl *jbimpl = jb->impl; void *jbobj = jb->jbobj; struct ast_frame *frr; long now = 0; if (!ast_test_flag(jb, JB_USE)) return -1; if (f->frametype != AST_FRAME_VOICE) { if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) { jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now); jbimpl->force_resync(jbobj); } return -1; } /* We consider an enabled jitterbuffer should receive frames with valid timing info. */ if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) { ast_log(LOG_WARNING, "%s received frame with invalid timing info: " "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n", chan->name, ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO), f->len, f->ts, f->src); return -1; } frr = ast_frdup(f); if (!frr) { ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan->name); return -1; } if (!ast_test_flag(jb, JB_CREATED)) { if (create_jb(chan, frr)) { ast_frfree(frr); /* Disable the jitterbuffer */ ast_clear_flag(jb, JB_USE); return -1; } ast_set_flag(jb, JB_CREATED); return 0; } else { now = get_now(jb, NULL); if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) { jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); ast_frfree(frr); /*return -1;*/ /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't be delivered at all */ return 0; } jb->next = jbimpl->next(jbobj); jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); return 0; } }
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 573 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().
{ int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1; const char *name; int tmp; if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) { return -1; } name = varname + prefixlen; if (!strcasecmp(name, AST_JB_CONF_ENABLE)) { ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED); } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) { ast_set2_flag(conf, ast_true(value), AST_JB_FORCED); } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) { if ((tmp = atoi(value)) > 0) conf->max_size = tmp; } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) { if ((tmp = atoi(value)) > 0) conf->resync_threshold = tmp; } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) { if (!ast_strlen_zero(value)) snprintf(conf->impl, sizeof(conf->impl), "%s", value); } else if (!strcasecmp(name, AST_JB_CONF_TARGET_EXTRA)) { if (sscanf(value, "%30d", &tmp) == 1) { conf->target_extra = tmp; } } else if (!strcasecmp(name, AST_JB_CONF_LOG)) { ast_set2_flag(conf, ast_true(value), AST_JB_LOG); } else { return -1; } return 0; }
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().
{ struct ast_jb *jb = &chan->jb; struct ast_jb_conf *jbconf = &jb->conf; struct ast_jb_impl *jbimpl = jb->impl; void *jbobj; struct ast_channel *bridged; long now; char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1]; char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp; int res; jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold); if (!jbobj) { ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name); return -1; } now = get_now(jb, NULL); res = jbimpl->put_first(jbobj, frr, now); /* The result of putting the first frame should not differ from OK. However, its possible some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */ if (res != JB_IMPL_OK) { ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name); /* jbimpl->destroy(jbobj); return -1; */ } /* Init next */ jb->next = jbimpl->next(jbobj); /* Init last format for a first time. */ jb->last_format = frr->subclass; /* Create a frame log file */ if (ast_test_flag(jbconf, AST_JB_LOG)) { char safe_logfile[30] = "/tmp/logfile-XXXXXX"; int safe_fd; snprintf(name2, sizeof(name2), "%s", chan->name); if ((tmp = strchr(name2, '/'))) { *tmp = '#'; } bridged = ast_bridged_channel(chan); /* We should always have bridged chan if a jitterbuffer is in use */ ast_assert(bridged != NULL); snprintf(name1, sizeof(name1), "%s", bridged->name); if ((tmp = strchr(name1, '/'))) { *tmp = '#'; } snprintf(logfile_pathname, sizeof(logfile_pathname), "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2); unlink(logfile_pathname); safe_fd = mkstemp(safe_logfile); if (safe_fd < 0 || link(safe_logfile, logfile_pathname) || unlink(safe_logfile) || !(jb->logfile = fdopen(safe_fd, "w+b"))) { ast_log(LOG_ERROR, "Failed to create frame log file with pathname '%s': %s\n", logfile_pathname, strerror(errno)); jb->logfile = NULL; if (safe_fd > -1) { close(safe_fd); } } if (res == JB_IMPL_OK) { jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); } else { jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); } } ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name); /* Free the frame if it has not been queued in the jb */ if (res != JB_IMPL_OK) { ast_frfree(frr); } return 0; }
static long get_now | ( | struct ast_jb * | jb, |
struct timeval * | tv | ||
) | [static] |
Definition at line 560 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().
{ struct timeval now; if (!when) { when = &now; gettimeofday(when, NULL); } return ast_tvdiff_ms(*when, jb->timebase); }
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, default_impl, ast_jb_conf::impl, ast_jb::impl, ast_channel::jb, and ast_jb_impl::name.
Referenced by ast_jb_do_usecheck().
{ struct ast_jb *jb = &chan->jb; struct ast_jb_conf *jbconf = &jb->conf; struct ast_jb_impl *test_impl; int i, avail_impl_count = ARRAY_LEN(avail_impl); jb->impl = &avail_impl[default_impl]; if (ast_strlen_zero(jbconf->impl)) { return; } for (i = 0; i < avail_impl_count; i++) { test_impl = &avail_impl[i]; if (!strcasecmp(jbconf->impl, test_impl->name)) { jb->impl = test_impl; return; } } }
static void * jb_create_adaptive | ( | struct ast_jb_conf * | general_config, |
long | resynch_threshold | ||
) | [static] |
Definition at line 738 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.
{ jb_conf jbconf; jitterbuf *adaptivejb; adaptivejb = jb_new(); if (adaptivejb) { jbconf.max_jitterbuf = general_config->max_size; jbconf.resync_threshold = general_config->resync_threshold; jbconf.max_contig_interp = 10; jbconf.target_extra = general_config->target_extra; jb_setconf(adaptivejb, &jbconf); } return adaptivejb; }
static void * jb_create_fixed | ( | struct ast_jb_conf * | general_config, |
long | resynch_threshold | ||
) | [static] |
Definition at line 644 of file abstract_jb.c.
References fixed_jb_new(), fixed_jb_conf::jbsize, ast_jb_conf::max_size, and fixed_jb_conf::resync_threshold.
{ struct fixed_jb_conf conf; conf.jbsize = general_config->max_size; conf.resync_threshold = resynch_threshold; return fixed_jb_new(&conf); }
static void jb_destroy_adaptive | ( | void * | jb | ) | [static] |
Definition at line 756 of file abstract_jb.c.
References jb_destroy().
{ jitterbuf *adaptivejb = (jitterbuf *) jb; jb_destroy(adaptivejb); }
static void jb_destroy_fixed | ( | void * | jb | ) | [static] |
Definition at line 654 of file abstract_jb.c.
References fixed_jb_destroy().
{ struct fixed_jb *fixedjb = (struct fixed_jb *) jb; /* destroy the jb */ fixed_jb_destroy(fixedjb); }
static void jb_empty_and_reset_adaptive | ( | void * | jb | ) | [static] |
Definition at line 824 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 726 of file abstract_jb.c.
References ast_frfree, fixed_jb_frame::data, FIXED_JB_OK, and fixed_jb_remove().
{ struct fixed_jb *fixedjb = jb; struct fixed_jb_frame f; while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) { ast_frfree(f.data); } }
static void jb_force_resynch_adaptive | ( | void * | jb | ) | [static] |
Definition at line 820 of file abstract_jb.c.
{ }
static void jb_force_resynch_fixed | ( | void * | jb | ) | [static] |
Definition at line 719 of file abstract_jb.c.
References fixed_jb_set_force_resynch().
{ struct fixed_jb *fixedjb = (struct fixed_jb *) jb; fixed_jb_set_force_resynch(fixedjb); }
static int jb_get_adaptive | ( | void * | jb, |
struct ast_frame ** | fout, | ||
long | now, | ||
long | interpl | ||
) | [static] |
Definition at line 786 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().
{ struct ast_jb *jb = &chan->jb; struct ast_jb_impl *jbimpl = jb->impl; void *jbobj = jb->jbobj; struct ast_frame *f, finterp = { .frametype = AST_FRAME_VOICE, }; long now; int interpolation_len, res; now = get_now(jb, NULL); jb->next = jbimpl->next(jbobj); if (now < jb->next) { jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next); return; } while (now >= jb->next) { interpolation_len = ast_codec_interp_len(jb->last_format); res = jbimpl->get(jbobj, &f, now, interpolation_len); switch (res) { case JB_IMPL_OK: /* deliver the frame */ ast_write(chan, f); case JB_IMPL_DROP: jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n", now, jb_get_actions[res], f->ts, f->len); jb->last_format = f->subclass; ast_frfree(f); break; case JB_IMPL_INTERP: /* interpolate a frame */ f = &finterp; f->subclass = jb->last_format; f->samples = interpolation_len * 8; f->src = "JB interpolation"; f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000)); f->offset = AST_FRIENDLY_OFFSET; /* deliver the interpolated frame */ ast_write(chan, f); jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len); break; case JB_IMPL_NOFRAME: ast_log(LOG_WARNING, "JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n", jbimpl->name, now, jb->next, jbimpl->next(jbobj)); jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now); return; default: ast_log(LOG_ERROR, "This should never happen!\n"); ast_assert("JB type unknown" == NULL); break; } jb->next = jbimpl->next(jbobj); } }
static int jb_get_fixed | ( | void * | jb, |
struct ast_frame ** | fout, | ||
long | now, | ||
long | interpl | ||
) | [static] |
Definition at line 685 of file abstract_jb.c.
References fixed_jb_frame::data, and fixed_jb_get().
{ struct fixed_jb *fixedjb = (struct fixed_jb *) jb; struct fixed_jb_frame frame; int res; res = fixed_jb_get(fixedjb, &frame, now, interpl); *fout = frame.data; return fixed_to_abstract_code[res]; }
static long jb_next_adaptive | ( | void * | jb | ) | [static] |
static long jb_next_fixed | ( | void * | jb | ) | [static] |
Definition at line 698 of file abstract_jb.c.
References fixed_jb_next().
{ struct fixed_jb *fixedjb = (struct fixed_jb *) jb; return fixed_jb_next(fixedjb); }
static int jb_put_adaptive | ( | void * | jb, |
struct ast_frame * | fin, | ||
long | now | ||
) | [static] |
Definition at line 775 of file abstract_jb.c.
References jb_put(), JB_TYPE_VOICE, ast_frame::len, and ast_frame::ts.
Referenced by jb_put_first_adaptive().
{ jitterbuf *adaptivejb = (jitterbuf *) jb; int res; res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now); return adaptive_to_abstract_code[res]; }
static int jb_put_first_adaptive | ( | void * | jb, |
struct ast_frame * | fin, | ||
long | now | ||
) | [static] |
Definition at line 764 of file abstract_jb.c.
References jitterbuf::info, jb_put_adaptive(), jb_info::resync_offset, and ast_frame::ts.
{ jitterbuf *adaptivejb = (jitterbuf *) jb; /* Initialize the offset to that of the first frame's timestamp */ adaptivejb->info.resync_offset = fin->ts; return jb_put_adaptive(jb, fin, now); }
static int jb_put_first_fixed | ( | void * | jb, |
struct ast_frame * | fin, | ||
long | now | ||
) | [static] |
Definition at line 663 of file abstract_jb.c.
References fixed_jb_put_first(), ast_frame::len, and ast_frame::ts.
{ struct fixed_jb *fixedjb = (struct fixed_jb *) jb; int res; res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now); return fixed_to_abstract_code[res]; }
static int jb_put_fixed | ( | void * | jb, |
struct ast_frame * | fin, | ||
long | now | ||
) | [static] |
Definition at line 674 of file abstract_jb.c.
References fixed_jb_put(), ast_frame::len, and ast_frame::ts.
{ struct fixed_jb *fixedjb = (struct fixed_jb *) jb; int res; res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now); return fixed_to_abstract_code[res]; }
static int jb_remove_adaptive | ( | void * | jb, |
struct ast_frame ** | fout | ||
) | [static] |
Definition at line 807 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 706 of file abstract_jb.c.
References fixed_jb_frame::data, and fixed_jb_remove().
{ struct fixed_jb *fixedjb = (struct fixed_jb *) jb; struct fixed_jb_frame frame; int res; res = fixed_jb_remove(fixedjb, &frame); *fout = frame.data; return fixed_to_abstract_code[res]; }
int adaptive_to_abstract_code[] [static] |
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.
Referenced by jb_choose_impl().
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.