Sat Feb 11 06:33:25 2012

Asterisk developer's documentation


abstract_jb.c File Reference

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"

Include dependency graph for abstract_jb.c:

Go to the source code of this file.

Defines

#define jb_framelog(...)
 Macros for the frame log files.

Enumerations

enum  { JB_USE = (1 << 0), JB_TIMEBASE_INITIALIZED = (1 << 1), JB_CREATED = (1 << 2) }

Functions

void ast_jb_configure (struct ast_channel *chan, const struct ast_jb_conf *conf)
 Configures a jitterbuffer on a channel.
void ast_jb_destroy (struct ast_channel *chan)
 Destroys jitterbuffer on a channel.
int ast_jb_do_usecheck (struct ast_channel *c0, struct ast_channel *c1)
 Checks the need of a jb use in a generic bridge.
void ast_jb_empty_and_reset (struct ast_channel *c0, struct ast_channel *c1)
 drops all frames from a jitterbuffer and resets it
void ast_jb_get_and_deliver (struct ast_channel *c0, struct ast_channel *c1)
 Deliver the queued frames that should be delivered now for both channels.
void ast_jb_get_config (const struct ast_channel *chan, struct ast_jb_conf *conf)
 Copies a channel's jitterbuffer configuration.
struct ast_jb_implast_jb_get_impl (enum ast_jb_type type)
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"}


Detailed Description

Common implementation-independent jitterbuffer stuff.

Author:
Slav Klenov <slav@securax.org>

Definition in file abstract_jb.c.


Define Documentation

#define jb_framelog ( ...   ) 

Macros for the frame log files.

Definition at line 117 of file abstract_jb.c.

Referenced by ast_jb_put(), create_jb(), and jb_get_and_deliver().


Enumeration Type Documentation

anonymous enum

Internal jb flags

Enumerator:
JB_USE 
JB_TIMEBASE_INITIALIZED 
JB_CREATED 

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 };


Function Documentation

void ast_jb_configure ( struct ast_channel chan,
const struct ast_jb_conf conf 
)

Configures a jitterbuffer on a channel.

Parameters:
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 567 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().

00568 {
00569    memcpy(&chan->jb.conf, conf, sizeof(*conf));
00570 }

void ast_jb_destroy ( struct ast_channel chan  ) 

Destroys jitterbuffer on a channel.

Parameters:
chan channel.
Called from ast_channel_free() when a channel is destroyed.

Definition at line 487 of file abstract_jb.c.

References ast_channel_name(), ast_clear_flag, ast_frfree, AST_JB_IMPL_OK, ast_test_flag, ast_verb, ast_jb_impl::destroy, f, ast_jb::impl, ast_channel::jb, JB_CREATED, ast_jb::jbobj, ast_jb::logfile, ast_jb_impl::name, and ast_jb_impl::remove.

Referenced by ast_channel_destructor().

00488 {
00489    struct ast_jb *jb = &chan->jb;
00490    const struct ast_jb_impl *jbimpl = jb->impl;
00491    void *jbobj = jb->jbobj;
00492    struct ast_frame *f;
00493 
00494    if (jb->logfile) {
00495       fclose(jb->logfile);
00496       jb->logfile = NULL;
00497    }
00498 
00499    if (ast_test_flag(jb, JB_CREATED)) {
00500       /* Remove and free all frames still queued in jb */
00501       while (jbimpl->remove(jbobj, &f) == AST_JB_IMPL_OK) {
00502          ast_frfree(f);
00503       }
00504 
00505       jbimpl->destroy(jbobj);
00506       jb->jbobj = NULL;
00507 
00508       ast_clear_flag(jb, JB_CREATED);
00509 
00510       ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, ast_channel_name(chan));
00511    }
00512 }

int ast_jb_do_usecheck ( struct ast_channel c0,
struct ast_channel c1 
)

Checks the need of a jb use in a generic bridge.

Parameters:
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.

Return values:
zero if there are no jitter buffers in use
non-zero if there are

Definition at line 157 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().

00158 {
00159    struct ast_jb *jb0 = &c0->jb;
00160    struct ast_jb *jb1 = &c1->jb;
00161    struct ast_jb_conf *conf0 = &jb0->conf;
00162    struct ast_jb_conf *conf1 = &jb1->conf;
00163    int c0_wants_jitter = c0->tech->properties & AST_CHAN_TP_WANTSJITTER;
00164    int c0_creates_jitter = c0->tech->properties & AST_CHAN_TP_CREATESJITTER;
00165    int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED);
00166    int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED);
00167    int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED);
00168    int c0_jb_created = ast_test_flag(jb0, JB_CREATED);
00169    int c1_wants_jitter = c1->tech->properties & AST_CHAN_TP_WANTSJITTER;
00170    int c1_creates_jitter = c1->tech->properties & AST_CHAN_TP_CREATESJITTER;
00171    int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED);
00172    int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED);
00173    int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED);
00174    int c1_jb_created = ast_test_flag(jb1, JB_CREATED);
00175    int inuse = 0;
00176 
00177    /* Determine whether audio going to c0 needs a jitter buffer */
00178    if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) {
00179       ast_set_flag(jb0, JB_USE);
00180       if (!c0_jb_timebase_initialized) {
00181          if (c1_jb_timebase_initialized) {
00182             memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval));
00183          } else {
00184             gettimeofday(&jb0->timebase, NULL);
00185          }
00186          ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED);
00187       }
00188 
00189       if (!c0_jb_created) {
00190          jb_choose_impl(c0);
00191       }
00192 
00193       inuse = 1;
00194    }
00195 
00196    /* Determine whether audio going to c1 needs a jitter buffer */
00197    if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) {
00198       ast_set_flag(jb1, JB_USE);
00199       if (!c1_jb_timebase_initialized) {
00200          if (c0_jb_timebase_initialized) {
00201             memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval));
00202          } else {
00203             gettimeofday(&jb1->timebase, NULL);
00204          }
00205          ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED);
00206       }
00207 
00208       if (!c1_jb_created) {
00209          jb_choose_impl(c1);
00210       }
00211 
00212       inuse = 1;
00213    }
00214 
00215    return inuse;
00216 }

void ast_jb_empty_and_reset ( struct ast_channel c0,
struct ast_channel c1 
)

drops all frames from a jitterbuffer and resets it

Parameters:
c0 one channel of a bridge
c1 the other channel of the bridge

Definition at line 578 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().

00579 {
00580    struct ast_jb *jb0 = &c0->jb;
00581    struct ast_jb *jb1 = &c1->jb;
00582    int c0_use_jb = ast_test_flag(jb0, JB_USE);
00583    int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00584    int c1_use_jb = ast_test_flag(jb1, JB_USE);
00585    int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00586 
00587    if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) {
00588       jb0->impl->empty_and_reset(jb0->jbobj);
00589    }
00590 
00591    if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) {
00592       jb1->impl->empty_and_reset(jb1->jbobj);
00593    }
00594 }

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.

Parameters:
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 323 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().

00324 {
00325    struct ast_jb *jb0 = &c0->jb;
00326    struct ast_jb *jb1 = &c1->jb;
00327    int c0_use_jb = ast_test_flag(jb0, JB_USE);
00328    int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00329    int c1_use_jb = ast_test_flag(jb1, JB_USE);
00330    int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00331 
00332    if (c0_use_jb && c0_jb_is_created)
00333       jb_get_and_deliver(c0);
00334 
00335    if (c1_use_jb && c1_jb_is_created)
00336       jb_get_and_deliver(c1);
00337 }

void ast_jb_get_config ( const struct ast_channel chan,
struct ast_jb_conf conf 
)

Copies a channel's jitterbuffer configuration.

Parameters:
chan channel.
conf destination.

Definition at line 573 of file abstract_jb.c.

References ast_jb::conf, and ast_channel::jb.

00574 {
00575    memcpy(conf, &chan->jb.conf, sizeof(*conf));
00576 }

struct ast_jb_impl* ast_jb_get_impl ( enum ast_jb_type  type  )  [read]

Definition at line 791 of file abstract_jb.c.

References ARRAY_LEN.

Referenced by jb_framedata_init().

00792 {
00793    int i;
00794    for (i = 0; i < ARRAY_LEN(avail_impl); i++) {
00795       if (avail_impl[i].type == type) {
00796          return &avail_impl[i];
00797       }
00798    }
00799    return NULL;
00800 }

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.

Parameters:
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.

Returns:
maximum time to wait.

Definition at line 218 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().

00219 {
00220    struct ast_jb *jb0 = &c0->jb;
00221    struct ast_jb *jb1 = &c1->jb;
00222    int c0_use_jb = ast_test_flag(jb0, JB_USE);
00223    int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00224    int c1_use_jb = ast_test_flag(jb1, JB_USE);
00225    int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00226    int wait, wait0, wait1;
00227    struct timeval tv_now;
00228 
00229    if (time_left == 0) {
00230       /* No time left - the bridge will be retried */
00231       /* TODO: Test disable this */
00232       /*return 0;*/
00233    }
00234 
00235    if (time_left < 0) {
00236       time_left = INT_MAX;
00237    }
00238 
00239    gettimeofday(&tv_now, NULL);
00240 
00241    wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left;
00242    wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left;
00243 
00244    wait = wait0 < wait1 ? wait0 : wait1;
00245    wait = wait < time_left ? wait : time_left;
00246 
00247    if (wait == INT_MAX) {
00248       wait = -1;
00249    } else if (wait < 1) {
00250       /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */
00251       wait = 1;
00252    }
00253 
00254    return wait;
00255 }

int ast_jb_put ( struct ast_channel chan,
struct ast_frame f 
)

Puts a frame into a channel jitterbuffer.

Parameters:
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.

Return values:
0 if the frame was queued
-1 if not

Definition at line 258 of file abstract_jb.c.

References ast_channel_name(), ast_clear_flag, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frdup(), AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, AST_JB_IMPL_OK, 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_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().

00259 {
00260    struct ast_jb *jb = &chan->jb;
00261    const struct ast_jb_impl *jbimpl = jb->impl;
00262    void *jbobj = jb->jbobj;
00263    struct ast_frame *frr;
00264    long now = 0;
00265 
00266    if (!ast_test_flag(jb, JB_USE))
00267       return -1;
00268 
00269    if (f->frametype != AST_FRAME_VOICE) {
00270       if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) {
00271          jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now);
00272          jbimpl->force_resync(jbobj);
00273       }
00274 
00275       return -1;
00276    }
00277 
00278    /* We consider an enabled jitterbuffer should receive frames with valid timing info. */
00279    if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) {
00280       ast_log(LOG_WARNING, "%s received frame with invalid timing info: "
00281          "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n",
00282          ast_channel_name(chan), ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO), f->len, f->ts, f->src);
00283       return -1;
00284    }
00285 
00286    frr = ast_frdup(f);
00287 
00288    if (!frr) {
00289       ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", ast_channel_name(chan));
00290       return -1;
00291    }
00292 
00293    if (!ast_test_flag(jb, JB_CREATED)) {
00294       if (create_jb(chan, frr)) {
00295          ast_frfree(frr);
00296          /* Disable the jitterbuffer */
00297          ast_clear_flag(jb, JB_USE);
00298          return -1;
00299       }
00300 
00301       ast_set_flag(jb, JB_CREATED);
00302       return 0;
00303    } else {
00304       now = get_now(jb, NULL);
00305       if (jbimpl->put(jbobj, frr, now) != AST_JB_IMPL_OK) {
00306          jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
00307          ast_frfree(frr);
00308          /*return -1;*/
00309          /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't
00310             be delivered at all */
00311          return 0;
00312       }
00313 
00314       jb->next = jbimpl->next(jbobj);
00315 
00316       jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
00317 
00318       return 0;
00319    }
00320 }

int ast_jb_read_conf ( struct ast_jb_conf conf,
const char *  varname,
const char *  value 
)

Sets jitterbuffer configuration property.

Parameters:
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.

Returns:
zero if the property was set to the configuration, -1 if not.

Definition at line 528 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(), jb_framedata_init(), jingle_load_config(), load_module(), process_dahdi(), reload_config(), store_config(), and store_config_core().

00529 {
00530    int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1;
00531    const char *name;
00532    int tmp;
00533 
00534    if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) {
00535       return -1;
00536    }
00537 
00538    name = varname + prefixlen;
00539 
00540    if (!strcasecmp(name, AST_JB_CONF_ENABLE)) {
00541       ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED);
00542    } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) {
00543       ast_set2_flag(conf, ast_true(value), AST_JB_FORCED);
00544    } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) {
00545       if ((tmp = atoi(value)) > 0)
00546          conf->max_size = tmp;
00547    } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) {
00548       if ((tmp = atoi(value)) > 0)
00549          conf->resync_threshold = tmp;
00550    } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) {
00551       if (!ast_strlen_zero(value))
00552          snprintf(conf->impl, sizeof(conf->impl), "%s", value);
00553    } else if (!strcasecmp(name, AST_JB_CONF_TARGET_EXTRA)) {
00554       if (sscanf(value, "%30d", &tmp) == 1) {
00555          conf->target_extra = tmp;
00556       }
00557    } else if (!strcasecmp(name, AST_JB_CONF_LOG)) {
00558       ast_set2_flag(conf, ast_true(value), AST_JB_LOG);
00559    } else {
00560       return -1;
00561    }
00562 
00563    return 0;
00564 }

static int create_jb ( struct ast_channel chan,
struct ast_frame first_frame 
) [static]

Definition at line 400 of file abstract_jb.c.

References ast_assert, ast_bridged_channel(), ast_channel_name(), AST_CHANNEL_NAME, ast_format_copy(), ast_frfree, AST_JB_IMPL_NAME_SIZE, AST_JB_IMPL_OK, AST_JB_LOG, ast_log(), ast_test_flag, ast_verb, ast_jb::conf, ast_jb_impl::create, errno, ast_frame_subclass::format, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, 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().

00401 {
00402    struct ast_jb *jb = &chan->jb;
00403    struct ast_jb_conf *jbconf = &jb->conf;
00404    const struct ast_jb_impl *jbimpl = jb->impl;
00405    void *jbobj;
00406    struct ast_channel *bridged;
00407    long now;
00408    char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1];
00409    char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp;
00410    int res;
00411 
00412    jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold);
00413    if (!jbobj) {
00414       ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", ast_channel_name(chan));
00415       return -1;
00416    }
00417 
00418    now = get_now(jb, NULL);
00419    res = jbimpl->put_first(jbobj, frr, now);
00420 
00421    /* The result of putting the first frame should not differ from OK. However, its possible
00422       some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */
00423    if (res != AST_JB_IMPL_OK) {
00424       ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", ast_channel_name(chan));
00425       /*
00426       jbimpl->destroy(jbobj);
00427       return -1;
00428       */
00429    }
00430 
00431    /* Init next */
00432    jb->next = jbimpl->next(jbobj);
00433 
00434    /* Init last format for a first time. */
00435    ast_format_copy(&jb->last_format, &frr->subclass.format);
00436 
00437    /* Create a frame log file */
00438    if (ast_test_flag(jbconf, AST_JB_LOG)) {
00439       char safe_logfile[30] = "/tmp/logfile-XXXXXX";
00440       int safe_fd;
00441       snprintf(name2, sizeof(name2), "%s", ast_channel_name(chan));
00442       if ((tmp = strchr(name2, '/'))) {
00443          *tmp = '#';
00444       }
00445 
00446       bridged = ast_bridged_channel(chan);
00447       /* We should always have bridged chan if a jitterbuffer is in use */
00448       ast_assert(bridged != NULL);
00449 
00450       snprintf(name1, sizeof(name1), "%s", ast_channel_name(bridged));
00451       if ((tmp = strchr(name1, '/'))) {
00452          *tmp = '#';
00453       }
00454 
00455       snprintf(logfile_pathname, sizeof(logfile_pathname),
00456          "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2);
00457       unlink(logfile_pathname);
00458       safe_fd = mkstemp(safe_logfile);
00459       if (safe_fd < 0 || link(safe_logfile, logfile_pathname) || unlink(safe_logfile) || !(jb->logfile = fdopen(safe_fd, "w+b"))) {
00460          ast_log(LOG_ERROR, "Failed to create frame log file with pathname '%s': %s\n", logfile_pathname, strerror(errno));
00461          jb->logfile = NULL;
00462          if (safe_fd > -1) {
00463             close(safe_fd);
00464          }
00465       }
00466 
00467       if (res == AST_JB_IMPL_OK) {
00468          jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
00469             now, frr->ts, frr->len);
00470       } else {
00471          jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
00472             now, frr->ts, frr->len);
00473       }
00474    }
00475 
00476    ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, ast_channel_name(chan));
00477 
00478    /* Free the frame if it has not been queued in the jb */
00479    if (res != AST_JB_IMPL_OK) {
00480       ast_frfree(frr);
00481    }
00482 
00483    return 0;
00484 }

static long get_now ( struct ast_jb jb,
struct timeval *  tv 
) [static]

Definition at line 515 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().

00516 {
00517    struct timeval now;
00518 
00519    if (!when) {
00520       when = &now;
00521       gettimeofday(when, NULL);
00522    }
00523 
00524    return ast_tvdiff_ms(*when, jb->timebase);
00525 }

static void jb_choose_impl ( struct ast_channel chan  )  [static]

Definition at line 135 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().

00136 {
00137    struct ast_jb *jb = &chan->jb;
00138    struct ast_jb_conf *jbconf = &jb->conf;
00139    const struct ast_jb_impl *test_impl;
00140    int i, avail_impl_count = ARRAY_LEN(avail_impl);
00141 
00142    jb->impl = &avail_impl[default_impl];
00143 
00144    if (ast_strlen_zero(jbconf->impl)) {
00145       return;
00146    }
00147 
00148    for (i = 0; i < avail_impl_count; i++) {
00149       test_impl = &avail_impl[i];
00150       if (!strcasecmp(jbconf->impl, test_impl->name)) {
00151          jb->impl = test_impl;
00152          return;
00153       }
00154    }
00155 }

static void * jb_create_adaptive ( struct ast_jb_conf general_config,
long  resynch_threshold 
) [static]

Definition at line 693 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.

00694 {
00695    jb_conf jbconf;
00696    jitterbuf *adaptivejb;
00697 
00698    adaptivejb = jb_new();
00699    if (adaptivejb) {
00700       jbconf.max_jitterbuf = general_config->max_size;
00701       jbconf.resync_threshold = general_config->resync_threshold;
00702       jbconf.max_contig_interp = 10;
00703       jbconf.target_extra = general_config->target_extra;
00704       jb_setconf(adaptivejb, &jbconf);
00705    }
00706 
00707    return adaptivejb;
00708 }

static void * jb_create_fixed ( struct ast_jb_conf general_config,
long  resynch_threshold 
) [static]

Definition at line 599 of file abstract_jb.c.

References fixed_jb_new(), fixed_jb_conf::jbsize, ast_jb_conf::max_size, and fixed_jb_conf::resync_threshold.

00600 {
00601    struct fixed_jb_conf conf;
00602 
00603    conf.jbsize = general_config->max_size;
00604    conf.resync_threshold = resynch_threshold;
00605 
00606    return fixed_jb_new(&conf);
00607 }

static void jb_destroy_adaptive ( void *  jb  )  [static]

Definition at line 711 of file abstract_jb.c.

References jb_destroy().

00712 {
00713    jitterbuf *adaptivejb = (jitterbuf *) jb;
00714 
00715    jb_destroy(adaptivejb);
00716 }

static void jb_destroy_fixed ( void *  jb  )  [static]

Definition at line 609 of file abstract_jb.c.

References fixed_jb_destroy().

00610 {
00611    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00612 
00613    /* destroy the jb */
00614    fixed_jb_destroy(fixedjb);
00615 }

static void jb_empty_and_reset_adaptive ( void *  jb  )  [static]

Definition at line 779 of file abstract_jb.c.

References ast_frfree, jb_frame::data, f, jb_getall(), JB_OK, and jb_reset().

00780 {
00781    jitterbuf *adaptivejb = jb;
00782    jb_frame f;
00783 
00784    while (jb_getall(adaptivejb, &f) == JB_OK) {
00785       ast_frfree(f.data);
00786    }
00787 
00788    jb_reset(adaptivejb);
00789 }

static void jb_empty_and_reset_fixed ( void *  jb  )  [static]

Definition at line 681 of file abstract_jb.c.

References ast_frfree, fixed_jb_frame::data, FIXED_JB_OK, and fixed_jb_remove().

00682 {
00683    struct fixed_jb *fixedjb = jb;
00684    struct fixed_jb_frame f;
00685 
00686    while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) {
00687       ast_frfree(f.data);
00688    }
00689 }

static void jb_force_resynch_adaptive ( void *  jb  )  [static]

Definition at line 775 of file abstract_jb.c.

00776 {
00777 }

static void jb_force_resynch_fixed ( void *  jb  )  [static]

Definition at line 674 of file abstract_jb.c.

References fixed_jb_set_force_resynch().

00675 {
00676    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00677 
00678    fixed_jb_set_force_resynch(fixedjb);
00679 }

static int jb_get_adaptive ( void *  jb,
struct ast_frame **  fout,
long  now,
long  interpl 
) [static]

Definition at line 741 of file abstract_jb.c.

References jb_frame::data, and jb_get().

00742 {
00743    jitterbuf *adaptivejb = (jitterbuf *) jb;
00744    jb_frame frame;
00745    int res;
00746 
00747    res = jb_get(adaptivejb, &frame, now, interpl);
00748    *fout = frame.data;
00749 
00750    return adaptive_to_abstract_code[res];
00751 }

static void jb_get_and_deliver ( struct ast_channel chan  )  [static]

Definition at line 340 of file abstract_jb.c.

References ast_assert, ast_codec_interp_len(), ast_format_copy(), AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, AST_JB_IMPL_DROP, AST_JB_IMPL_INTERP, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_OK, ast_log(), ast_samp2tv(), ast_tvadd(), ast_write(), ast_frame::delivery, f, ast_frame_subclass::format, ast_jb_impl::get, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, 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().

00341 {
00342    struct ast_jb *jb = &chan->jb;
00343    const struct ast_jb_impl *jbimpl = jb->impl;
00344    void *jbobj = jb->jbobj;
00345    struct ast_frame *f, finterp = { .frametype = AST_FRAME_VOICE, };
00346    long now;
00347    int interpolation_len, res;
00348 
00349    now = get_now(jb, NULL);
00350    jb->next = jbimpl->next(jbobj);
00351    if (now < jb->next) {
00352       jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next);
00353       return;
00354    }
00355 
00356    while (now >= jb->next) {
00357       interpolation_len = ast_codec_interp_len(&jb->last_format);
00358 
00359       res = jbimpl->get(jbobj, &f, now, interpolation_len);
00360 
00361       switch (res) {
00362       case AST_JB_IMPL_OK:
00363          /* deliver the frame */
00364          ast_write(chan, f);
00365       case AST_JB_IMPL_DROP:
00366          jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
00367             now, jb_get_actions[res], f->ts, f->len);
00368          ast_format_copy(&jb->last_format, &f->subclass.format);
00369          ast_frfree(f);
00370          break;
00371       case AST_JB_IMPL_INTERP:
00372          /* interpolate a frame */
00373          f = &finterp;
00374          ast_format_copy(&f->subclass.format, &jb->last_format);
00375          f->samples  = interpolation_len * 8;
00376          f->src  = "JB interpolation";
00377          f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000));
00378          f->offset = AST_FRIENDLY_OFFSET;
00379          /* deliver the interpolated frame */
00380          ast_write(chan, f);
00381          jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
00382          break;
00383       case AST_JB_IMPL_NOFRAME:
00384          ast_log(LOG_WARNING,
00385             "AST_JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
00386             jbimpl->name, now, jb->next, jbimpl->next(jbobj));
00387          jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now);
00388          return;
00389       default:
00390          ast_log(LOG_ERROR, "This should never happen!\n");
00391          ast_assert("JB type unknown" == NULL);
00392          break;
00393       }
00394 
00395       jb->next = jbimpl->next(jbobj);
00396    }
00397 }

static int jb_get_fixed ( void *  jb,
struct ast_frame **  fout,
long  now,
long  interpl 
) [static]

Definition at line 640 of file abstract_jb.c.

References fixed_jb_frame::data, and fixed_jb_get().

00641 {
00642    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00643    struct fixed_jb_frame frame;
00644    int res;
00645 
00646    res = fixed_jb_get(fixedjb, &frame, now, interpl);
00647    *fout = frame.data;
00648 
00649    return fixed_to_abstract_code[res];
00650 }

static long jb_next_adaptive ( void *  jb  )  [static]

Definition at line 754 of file abstract_jb.c.

References jb_next().

00755 {
00756    jitterbuf *adaptivejb = (jitterbuf *) jb;
00757 
00758    return jb_next(adaptivejb);
00759 }

static long jb_next_fixed ( void *  jb  )  [static]

Definition at line 653 of file abstract_jb.c.

References fixed_jb_next().

00654 {
00655    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00656 
00657    return fixed_jb_next(fixedjb);
00658 }

static int jb_put_adaptive ( void *  jb,
struct ast_frame fin,
long  now 
) [static]

Definition at line 730 of file abstract_jb.c.

References jb_put(), JB_TYPE_VOICE, ast_frame::len, and ast_frame::ts.

Referenced by jb_put_first_adaptive().

00731 {
00732    jitterbuf *adaptivejb = (jitterbuf *) jb;
00733    int res;
00734 
00735    res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
00736 
00737    return adaptive_to_abstract_code[res];
00738 }

static int jb_put_first_adaptive ( void *  jb,
struct ast_frame fin,
long  now 
) [static]

Definition at line 719 of file abstract_jb.c.

References jitterbuf::info, jb_put_adaptive(), jb_info::resync_offset, and ast_frame::ts.

00720 {
00721    jitterbuf *adaptivejb = (jitterbuf *) jb;
00722 
00723    /* Initialize the offset to that of the first frame's timestamp */
00724    adaptivejb->info.resync_offset = fin->ts;
00725 
00726    return jb_put_adaptive(jb, fin, now);
00727 }

static int jb_put_first_fixed ( void *  jb,
struct ast_frame fin,
long  now 
) [static]

Definition at line 618 of file abstract_jb.c.

References fixed_jb_put_first(), ast_frame::len, and ast_frame::ts.

00619 {
00620    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00621    int res;
00622 
00623    res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now);
00624 
00625    return fixed_to_abstract_code[res];
00626 }

static int jb_put_fixed ( void *  jb,
struct ast_frame fin,
long  now 
) [static]

Definition at line 629 of file abstract_jb.c.

References fixed_jb_put(), ast_frame::len, and ast_frame::ts.

00630 {
00631    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00632    int res;
00633 
00634    res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now);
00635 
00636    return fixed_to_abstract_code[res];
00637 }

static int jb_remove_adaptive ( void *  jb,
struct ast_frame **  fout 
) [static]

Definition at line 762 of file abstract_jb.c.

References jb_frame::data, and jb_getall().

00763 {
00764    jitterbuf *adaptivejb = (jitterbuf *) jb;
00765    jb_frame frame;
00766    int res;
00767 
00768    res = jb_getall(adaptivejb, &frame);
00769    *fout = frame.data;
00770 
00771    return adaptive_to_abstract_code[res];
00772 }

static int jb_remove_fixed ( void *  jb,
struct ast_frame **  fout 
) [static]

Definition at line 661 of file abstract_jb.c.

References fixed_jb_frame::data, and fixed_jb_remove().

00662 {
00663    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00664    struct fixed_jb_frame frame;
00665    int res;
00666 
00667    res = fixed_jb_remove(fixedjb, &frame);
00668    *fout = frame.data;
00669 
00670    return fixed_to_abstract_code[res];
00671 }


Variable Documentation

const int adaptive_to_abstract_code[] [static]

Initial value:

Definition at line 110 of file abstract_jb.c.

struct ast_jb_impl avail_impl[] [static]

Definition at line 76 of file abstract_jb.c.

int default_impl = 0 [static]

Definition at line 105 of file abstract_jb.c.

const int fixed_to_abstract_code[] [static]

const char* const jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"} [static]

Definition at line 114 of file abstract_jb.c.


Generated on Sat Feb 11 06:33:26 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6