Fri Nov 12 11:47:25 2010

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.

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

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 162 of file abstract_jb.c.

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


Typedef Documentation

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.


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

anonymous enum

Abstract return codes

Enumerator:
JB_IMPL_OK 
JB_IMPL_DROP 
JB_IMPL_INTERP 
JB_IMPL_NOFRAME 

Definition at line 145 of file abstract_jb.c.

00145      {
00146    JB_IMPL_OK,
00147    JB_IMPL_DROP,
00148    JB_IMPL_INTERP,
00149    JB_IMPL_NOFRAME
00150 };


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 610 of file abstract_jb.c.

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

Referenced by __oh323_rtp_create(), __oh323_update_info(), alsa_new(), console_new(), dahdi_new(), gtalk_new(), jingle_new(), local_new(), mgcp_new(), misdn_new(), oss_new(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().

00611 {
00612    memcpy(&chan->jb.conf, conf, sizeof(*conf));
00613 }

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 530 of file abstract_jb.c.

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

Referenced by ast_channel_free().

00531 {
00532    struct ast_jb *jb = &chan->jb;
00533    struct ast_jb_impl *jbimpl = jb->impl;
00534    void *jbobj = jb->jbobj;
00535    struct ast_frame *f;
00536 
00537    if (jb->logfile) {
00538       fclose(jb->logfile);
00539       jb->logfile = NULL;
00540    }
00541 
00542    if (ast_test_flag(jb, JB_CREATED)) {
00543       /* Remove and free all frames still queued in jb */
00544       while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) {
00545          ast_frfree(f);
00546       }
00547 
00548       jbimpl->destroy(jbobj);
00549       jb->jbobj = NULL;
00550 
00551       ast_clear_flag(jb, JB_CREATED);
00552 
00553       ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name);
00554    }
00555 }

int ast_jb_do_usecheck ( struct ast_channel c0,
struct ast_channel c1 
)

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

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 202 of file abstract_jb.c.

References AST_CHAN_TP_CREATESJITTER, AST_CHAN_TP_WANTSJITTER, AST_JB_ENABLED, AST_JB_FORCED, ast_set_flag, ast_test_flag, ast_jb::conf, inuse, ast_channel::jb, jb_choose_impl(), JB_CREATED, JB_TIMEBASE_INITIALIZED, JB_USE, ast_channel_tech::properties, ast_channel::tech, and ast_jb::timebase.

Referenced by ast_generic_bridge().

00203 {
00204    struct ast_jb *jb0 = &c0->jb;
00205    struct ast_jb *jb1 = &c1->jb;
00206    struct ast_jb_conf *conf0 = &jb0->conf;
00207    struct ast_jb_conf *conf1 = &jb1->conf;
00208    int c0_wants_jitter = c0->tech->properties & AST_CHAN_TP_WANTSJITTER;
00209    int c0_creates_jitter = c0->tech->properties & AST_CHAN_TP_CREATESJITTER;
00210    int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED);
00211    int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED);
00212    int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED);
00213    int c0_jb_created = ast_test_flag(jb0, JB_CREATED);
00214    int c1_wants_jitter = c1->tech->properties & AST_CHAN_TP_WANTSJITTER;
00215    int c1_creates_jitter = c1->tech->properties & AST_CHAN_TP_CREATESJITTER;
00216    int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED);
00217    int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED);
00218    int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED);
00219    int c1_jb_created = ast_test_flag(jb1, JB_CREATED);
00220    int inuse = 0;
00221 
00222    /* Determine whether audio going to c0 needs a jitter buffer */
00223    if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) {
00224       ast_set_flag(jb0, JB_USE);
00225       if (!c0_jb_timebase_initialized) {
00226          if (c1_jb_timebase_initialized) {
00227             memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval));
00228          } else {
00229             gettimeofday(&jb0->timebase, NULL);
00230          }
00231          ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED);
00232       }
00233 
00234       if (!c0_jb_created) {
00235          jb_choose_impl(c0);
00236       }
00237 
00238       inuse = 1;
00239    }
00240 
00241    /* Determine whether audio going to c1 needs a jitter buffer */
00242    if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) {
00243       ast_set_flag(jb1, JB_USE);
00244       if (!c1_jb_timebase_initialized) {
00245          if (c0_jb_timebase_initialized) {
00246             memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval));
00247          } else {
00248             gettimeofday(&jb1->timebase, NULL);
00249          }
00250          ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED);
00251       }
00252 
00253       if (!c1_jb_created) {
00254          jb_choose_impl(c1);
00255       }
00256 
00257       inuse = 1;
00258    }
00259 
00260    return inuse;
00261 }

void ast_jb_empty_and_reset ( struct ast_channel c0,
struct ast_channel c1 
)

drops all frames from a jitterbuffer and resets it

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

Definition at line 621 of file abstract_jb.c.

References ast_test_flag, ast_jb_impl::empty_and_reset, ast_jb::impl, ast_channel::jb, JB_CREATED, JB_USE, and ast_jb::jbobj.

Referenced by ast_generic_bridge().

00622 {
00623    struct ast_jb *jb0 = &c0->jb;
00624    struct ast_jb *jb1 = &c1->jb;
00625    int c0_use_jb = ast_test_flag(jb0, JB_USE);
00626    int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00627    int c1_use_jb = ast_test_flag(jb1, JB_USE);
00628    int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00629 
00630    if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) {
00631       jb0->impl->empty_and_reset(jb0->jbobj);
00632    }
00633 
00634    if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) {
00635       jb1->impl->empty_and_reset(jb1->jbobj);
00636    }
00637 }

void ast_jb_get_and_deliver ( struct ast_channel c0,
struct ast_channel c1 
)

Deliver the queued frames that should be delivered now for both channels.

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 368 of file abstract_jb.c.

References ast_test_flag, ast_channel::jb, JB_CREATED, jb_get_and_deliver(), and JB_USE.

Referenced by ast_generic_bridge().

00369 {
00370    struct ast_jb *jb0 = &c0->jb;
00371    struct ast_jb *jb1 = &c1->jb;
00372    int c0_use_jb = ast_test_flag(jb0, JB_USE);
00373    int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00374    int c1_use_jb = ast_test_flag(jb1, JB_USE);
00375    int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00376 
00377    if (c0_use_jb && c0_jb_is_created)
00378       jb_get_and_deliver(c0);
00379 
00380    if (c1_use_jb && c1_jb_is_created)
00381       jb_get_and_deliver(c1);
00382 }

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

Copies a channel's jitterbuffer configuration.

Parameters:
chan channel.
conf destination.

Definition at line 616 of file abstract_jb.c.

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

00617 {
00618    memcpy(conf, &chan->jb.conf, sizeof(*conf));
00619 }

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 263 of file abstract_jb.c.

References ast_test_flag, get_now(), ast_channel::jb, JB_CREATED, JB_USE, and ast_jb::next.

Referenced by ast_generic_bridge().

00264 {
00265    struct ast_jb *jb0 = &c0->jb;
00266    struct ast_jb *jb1 = &c1->jb;
00267    int c0_use_jb = ast_test_flag(jb0, JB_USE);
00268    int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00269    int c1_use_jb = ast_test_flag(jb1, JB_USE);
00270    int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00271    int wait, wait0, wait1;
00272    struct timeval tv_now;
00273 
00274    if (time_left == 0) {
00275       /* No time left - the bridge will be retried */
00276       /* TODO: Test disable this */
00277       /*return 0;*/
00278    }
00279 
00280    if (time_left < 0) {
00281       time_left = INT_MAX;
00282    }
00283 
00284    gettimeofday(&tv_now, NULL);
00285 
00286    wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left;
00287    wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left;
00288 
00289    wait = wait0 < wait1 ? wait0 : wait1;
00290    wait = wait < time_left ? wait : time_left;
00291 
00292    if (wait == INT_MAX) {
00293       wait = -1;
00294    } else if (wait < 1) {
00295       /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */
00296       wait = 1;
00297    }
00298 
00299    return wait;
00300 }

int ast_jb_put ( struct ast_channel chan,
struct ast_frame f 
)

Puts a frame into a channel jitterbuffer.

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 303 of file abstract_jb.c.

References ast_clear_flag, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frdup(), AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_log(), ast_set_flag, ast_test_flag, create_jb(), ast_jb_impl::force_resync, ast_frame::frametype, get_now(), ast_jb::impl, ast_channel::jb, JB_CREATED, jb_framelog, JB_IMPL_OK, JB_USE, ast_jb::jbobj, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_channel::name, ast_jb_impl::next, ast_jb::next, ast_jb_impl::put, ast_frame::src, and ast_frame::ts.

Referenced by ast_generic_bridge().

00304 {
00305    struct ast_jb *jb = &chan->jb;
00306    struct ast_jb_impl *jbimpl = jb->impl;
00307    void *jbobj = jb->jbobj;
00308    struct ast_frame *frr;
00309    long now = 0;
00310 
00311    if (!ast_test_flag(jb, JB_USE))
00312       return -1;
00313 
00314    if (f->frametype != AST_FRAME_VOICE) {
00315       if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) {
00316          jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now);
00317          jbimpl->force_resync(jbobj);
00318       }
00319 
00320       return -1;
00321    }
00322 
00323    /* We consider an enabled jitterbuffer should receive frames with valid timing info. */
00324    if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) {
00325       ast_log(LOG_WARNING, "%s received frame with invalid timing info: "
00326          "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n",
00327          chan->name, ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO), f->len, f->ts, f->src);
00328       return -1;
00329    }
00330 
00331    frr = ast_frdup(f);
00332 
00333    if (!frr) {
00334       ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan->name);
00335       return -1;
00336    }
00337 
00338    if (!ast_test_flag(jb, JB_CREATED)) {
00339       if (create_jb(chan, frr)) {
00340          ast_frfree(frr);
00341          /* Disable the jitterbuffer */
00342          ast_clear_flag(jb, JB_USE);
00343          return -1;
00344       }
00345 
00346       ast_set_flag(jb, JB_CREATED);
00347       return 0;
00348    } else {
00349       now = get_now(jb, NULL);
00350       if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) {
00351          jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
00352          ast_frfree(frr);
00353          /*return -1;*/
00354          /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't
00355             be delivered at all */
00356          return 0;
00357       }
00358 
00359       jb->next = jbimpl->next(jbobj);
00360 
00361       jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
00362 
00363       return 0;
00364    }
00365 }

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

Sets jitterbuffer configuration property.

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 571 of file abstract_jb.c.

References AST_JB_CONF_ENABLE, AST_JB_CONF_FORCE, AST_JB_CONF_IMPL, AST_JB_CONF_LOG, AST_JB_CONF_MAX_SIZE, AST_JB_CONF_PREFIX, AST_JB_CONF_RESYNCH_THRESHOLD, AST_JB_CONF_TARGET_EXTRA, AST_JB_ENABLED, AST_JB_FORCED, AST_JB_LOG, ast_set2_flag, ast_strlen_zero(), ast_true(), ast_jb_conf::impl, ast_jb_conf::max_size, name, ast_jb_conf::resync_threshold, and ast_jb_conf::target_extra.

Referenced by _build_general_config(), config_parse_variables(), gtalk_load_config(), jingle_load_config(), load_module(), process_dahdi(), reload_config(), store_config(), and store_config_core().

00572 {
00573    int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1;
00574    const char *name;
00575    int tmp;
00576 
00577    if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) {
00578       return -1;
00579    }
00580 
00581    name = varname + prefixlen;
00582 
00583    if (!strcasecmp(name, AST_JB_CONF_ENABLE)) {
00584       ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED);
00585    } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) {
00586       ast_set2_flag(conf, ast_true(value), AST_JB_FORCED);
00587    } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) {
00588       if ((tmp = atoi(value)) > 0)
00589          conf->max_size = tmp;
00590    } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) {
00591       if ((tmp = atoi(value)) > 0)
00592          conf->resync_threshold = tmp;
00593    } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) {
00594       if (!ast_strlen_zero(value))
00595          snprintf(conf->impl, sizeof(conf->impl), "%s", value);
00596    } else if (!strcasecmp(name, AST_JB_CONF_TARGET_EXTRA)) {
00597       if (sscanf(value, "%30d", &tmp) == 1) {
00598          conf->target_extra = tmp;
00599       }
00600    } else if (!strcasecmp(name, AST_JB_CONF_LOG)) {
00601       ast_set2_flag(conf, ast_true(value), AST_JB_LOG);
00602    } else {
00603       return -1;
00604    }
00605 
00606    return 0;
00607 }

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

Definition at line 445 of file abstract_jb.c.

References ast_assert, ast_bridged_channel(), AST_CHANNEL_NAME, ast_frfree, AST_JB_IMPL_NAME_SIZE, AST_JB_LOG, ast_log(), ast_test_flag, ast_verb, ast_jb::conf, ast_jb_impl::create, errno, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, JB_IMPL_OK, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb::logfile, ast_jb_impl::name, ast_channel::name, ast_jb_impl::next, ast_jb::next, ast_jb_impl::put_first, ast_jb_conf::resync_threshold, ast_frame::subclass, and ast_frame::ts.

Referenced by ast_jb_put().

00446 {
00447    struct ast_jb *jb = &chan->jb;
00448    struct ast_jb_conf *jbconf = &jb->conf;
00449    struct ast_jb_impl *jbimpl = jb->impl;
00450    void *jbobj;
00451    struct ast_channel *bridged;
00452    long now;
00453    char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1];
00454    char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp;
00455    int res;
00456 
00457    jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold);
00458    if (!jbobj) {
00459       ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name);
00460       return -1;
00461    }
00462 
00463    now = get_now(jb, NULL);
00464    res = jbimpl->put_first(jbobj, frr, now);
00465 
00466    /* The result of putting the first frame should not differ from OK. However, its possible
00467       some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */
00468    if (res != JB_IMPL_OK) {
00469       ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name);
00470       /*
00471       jbimpl->destroy(jbobj);
00472       return -1;
00473       */
00474    }
00475 
00476    /* Init next */
00477    jb->next = jbimpl->next(jbobj);
00478 
00479    /* Init last format for a first time. */
00480    jb->last_format = frr->subclass;
00481 
00482    /* Create a frame log file */
00483    if (ast_test_flag(jbconf, AST_JB_LOG)) {
00484       char safe_logfile[30] = "/tmp/logfile-XXXXXX";
00485       int safe_fd;
00486       snprintf(name2, sizeof(name2), "%s", chan->name);
00487       if ((tmp = strchr(name2, '/'))) {
00488          *tmp = '#';
00489       }
00490 
00491       bridged = ast_bridged_channel(chan);
00492       /* We should always have bridged chan if a jitterbuffer is in use */
00493       ast_assert(bridged != NULL);
00494 
00495       snprintf(name1, sizeof(name1), "%s", bridged->name);
00496       if ((tmp = strchr(name1, '/'))) {
00497          *tmp = '#';
00498       }
00499 
00500       snprintf(logfile_pathname, sizeof(logfile_pathname),
00501          "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2);
00502       if (!(safe_fd = mkstemp(safe_logfile)) > -1 || unlink(logfile_pathname) || link(safe_logfile, logfile_pathname) || unlink(safe_logfile) || !(jb->logfile = fdopen(safe_fd, "w+b"))) {
00503          jb->logfile = NULL;
00504          if (safe_fd > -1) {
00505             close(safe_fd);
00506          }
00507          ast_log(LOG_ERROR, "Failed to create frame log file with pathname '%s': %s\n", logfile_pathname, strerror(errno));
00508       }
00509 
00510       if (res == JB_IMPL_OK) {
00511          jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
00512             now, frr->ts, frr->len);
00513       } else {
00514          jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
00515             now, frr->ts, frr->len);
00516       }
00517    }
00518 
00519    ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name);
00520 
00521    /* Free the frame if it has not been queued in the jb */
00522    if (res != JB_IMPL_OK) {
00523       ast_frfree(frr);
00524    }
00525 
00526    return 0;
00527 }

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

Definition at line 558 of file abstract_jb.c.

References ast_tvdiff_ms(), and ast_jb::timebase.

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

00559 {
00560    struct timeval now;
00561 
00562    if (!when) {
00563       when = &now;
00564       gettimeofday(when, NULL);
00565    }
00566 
00567    return ast_tvdiff_ms(*when, jb->timebase);
00568 }

static void jb_choose_impl ( struct ast_channel chan  )  [static]

Definition at line 180 of file abstract_jb.c.

References ARRAY_LEN, ast_strlen_zero(), ast_jb::conf, ast_jb_conf::impl, ast_jb::impl, ast_channel::jb, and ast_jb_impl::name.

Referenced by ast_jb_do_usecheck().

00181 {
00182    struct ast_jb *jb = &chan->jb;
00183    struct ast_jb_conf *jbconf = &jb->conf;
00184    struct ast_jb_impl *test_impl;
00185    int i, avail_impl_count = ARRAY_LEN(avail_impl);
00186 
00187    jb->impl = &avail_impl[default_impl];
00188 
00189    if (ast_strlen_zero(jbconf->impl)) {
00190       return;
00191    }
00192 
00193    for (i = 0; i < avail_impl_count; i++) {
00194       test_impl = &avail_impl[i];
00195       if (!strcasecmp(jbconf->impl, test_impl->name)) {
00196          jb->impl = test_impl;
00197          return;
00198       }
00199    }
00200 }

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

Definition at line 736 of file abstract_jb.c.

References jb_new(), jb_setconf(), jb_conf::max_contig_interp, jb_conf::max_jitterbuf, ast_jb_conf::max_size, ast_jb_conf::resync_threshold, jb_conf::resync_threshold, ast_jb_conf::target_extra, and jb_conf::target_extra.

00737 {
00738    jb_conf jbconf;
00739    jitterbuf *adaptivejb;
00740 
00741    adaptivejb = jb_new();
00742    if (adaptivejb) {
00743       jbconf.max_jitterbuf = general_config->max_size;
00744       jbconf.resync_threshold = general_config->resync_threshold;
00745       jbconf.max_contig_interp = 10;
00746       jbconf.target_extra = general_config->target_extra;
00747       jb_setconf(adaptivejb, &jbconf);
00748    }
00749 
00750    return adaptivejb;
00751 }

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

Definition at line 642 of file abstract_jb.c.

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

00643 {
00644    struct fixed_jb_conf conf;
00645 
00646    conf.jbsize = general_config->max_size;
00647    conf.resync_threshold = resynch_threshold;
00648 
00649    return fixed_jb_new(&conf);
00650 }

static void jb_destroy_adaptive ( void *  jb  )  [static]

Definition at line 754 of file abstract_jb.c.

References jb_destroy().

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

static void jb_destroy_fixed ( void *  jb  )  [static]

Definition at line 652 of file abstract_jb.c.

References fixed_jb_destroy().

00653 {
00654    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00655 
00656    /* destroy the jb */
00657    fixed_jb_destroy(fixedjb);
00658 }

static void jb_empty_and_reset_adaptive ( void *  jb  )  [static]

Definition at line 817 of file abstract_jb.c.

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

00818 {
00819    jitterbuf *adaptivejb = jb;
00820    jb_frame f;
00821 
00822    while (jb_getall(adaptivejb, &f) == JB_OK) {
00823       ast_frfree(f.data);
00824    }
00825 
00826    jb_reset(adaptivejb);
00827 }

static void jb_empty_and_reset_fixed ( void *  jb  )  [static]

Definition at line 724 of file abstract_jb.c.

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

00725 {
00726    struct fixed_jb *fixedjb = jb;
00727    struct fixed_jb_frame f;
00728 
00729    while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) {
00730       ast_frfree(f.data);
00731    }
00732 }

static void jb_force_resynch_adaptive ( void *  jb  )  [static]

Definition at line 813 of file abstract_jb.c.

00814 {
00815 }

static void jb_force_resynch_fixed ( void *  jb  )  [static]

Definition at line 717 of file abstract_jb.c.

References fixed_jb_set_force_resynch().

00718 {
00719    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00720 
00721    fixed_jb_set_force_resynch(fixedjb);
00722 }

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

Definition at line 779 of file abstract_jb.c.

References jb_frame::data, and jb_get().

00780 {
00781    jitterbuf *adaptivejb = (jitterbuf *) jb;
00782    jb_frame frame;
00783    int res;
00784 
00785    res = jb_get(adaptivejb, &frame, now, interpl);
00786    *fout = frame.data;
00787 
00788    return adaptive_to_abstract_code[res];
00789 }

static void jb_get_and_deliver ( struct ast_channel chan  )  [static]

Definition at line 385 of file abstract_jb.c.

References ast_assert, ast_codec_interp_len(), AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), ast_samp2tv(), ast_tvadd(), ast_write(), ast_frame::delivery, f, ast_jb_impl::get, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME, JB_IMPL_OK, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb_impl::name, ast_frame::next, ast_jb_impl::next, ast_jb::next, ast_frame::offset, ast_frame::samples, ast_frame::src, ast_frame::subclass, ast_jb::timebase, and ast_frame::ts.

Referenced by ast_jb_get_and_deliver().

00386 {
00387    struct ast_jb *jb = &chan->jb;
00388    struct ast_jb_impl *jbimpl = jb->impl;
00389    void *jbobj = jb->jbobj;
00390    struct ast_frame *f, finterp = { .frametype = AST_FRAME_VOICE, };
00391    long now;
00392    int interpolation_len, res;
00393 
00394    now = get_now(jb, NULL);
00395    jb->next = jbimpl->next(jbobj);
00396    if (now < jb->next) {
00397       jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next);
00398       return;
00399    }
00400 
00401    while (now >= jb->next) {
00402       interpolation_len = ast_codec_interp_len(jb->last_format);
00403 
00404       res = jbimpl->get(jbobj, &f, now, interpolation_len);
00405 
00406       switch (res) {
00407       case JB_IMPL_OK:
00408          /* deliver the frame */
00409          ast_write(chan, f);
00410       case JB_IMPL_DROP:
00411          jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
00412             now, jb_get_actions[res], f->ts, f->len);
00413          jb->last_format = f->subclass;
00414          ast_frfree(f);
00415          break;
00416       case JB_IMPL_INTERP:
00417          /* interpolate a frame */
00418          f = &finterp;
00419          f->subclass = jb->last_format;
00420          f->samples  = interpolation_len * 8;
00421          f->src  = "JB interpolation";
00422          f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000));
00423          f->offset = AST_FRIENDLY_OFFSET;
00424          /* deliver the interpolated frame */
00425          ast_write(chan, f);
00426          jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
00427          break;
00428       case JB_IMPL_NOFRAME:
00429          ast_log(LOG_WARNING,
00430             "JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
00431             jbimpl->name, now, jb->next, jbimpl->next(jbobj));
00432          jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now);
00433          return;
00434       default:
00435          ast_log(LOG_ERROR, "This should never happen!\n");
00436          ast_assert("JB type unknown" == NULL);
00437          break;
00438       }
00439 
00440       jb->next = jbimpl->next(jbobj);
00441    }
00442 }

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

Definition at line 683 of file abstract_jb.c.

References fixed_jb_frame::data, and fixed_jb_get().

00684 {
00685    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00686    struct fixed_jb_frame frame;
00687    int res;
00688 
00689    res = fixed_jb_get(fixedjb, &frame, now, interpl);
00690    *fout = frame.data;
00691 
00692    return fixed_to_abstract_code[res];
00693 }

static long jb_next_adaptive ( void *  jb  )  [static]

Definition at line 792 of file abstract_jb.c.

References jb_next().

00793 {
00794    jitterbuf *adaptivejb = (jitterbuf *) jb;
00795 
00796    return jb_next(adaptivejb);
00797 }

static long jb_next_fixed ( void *  jb  )  [static]

Definition at line 696 of file abstract_jb.c.

References fixed_jb_next().

00697 {
00698    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00699 
00700    return fixed_jb_next(fixedjb);
00701 }

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

Definition at line 768 of file abstract_jb.c.

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

Referenced by jb_put_first_adaptive().

00769 {
00770    jitterbuf *adaptivejb = (jitterbuf *) jb;
00771    int res;
00772 
00773    res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
00774 
00775    return adaptive_to_abstract_code[res];
00776 }

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

Definition at line 762 of file abstract_jb.c.

References jb_put_adaptive().

00763 {
00764    return jb_put_adaptive(jb, fin, now);
00765 }

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

Definition at line 661 of file abstract_jb.c.

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

00662 {
00663    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00664    int res;
00665 
00666    res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now);
00667 
00668    return fixed_to_abstract_code[res];
00669 }

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

Definition at line 672 of file abstract_jb.c.

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

00673 {
00674    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00675    int res;
00676 
00677    res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now);
00678 
00679    return fixed_to_abstract_code[res];
00680 }

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

Definition at line 800 of file abstract_jb.c.

References jb_frame::data, and jb_getall().

00801 {
00802    jitterbuf *adaptivejb = (jitterbuf *) jb;
00803    jb_frame frame;
00804    int res;
00805 
00806    res = jb_getall(adaptivejb, &frame);
00807    *fout = frame.data;
00808 
00809    return adaptive_to_abstract_code[res];
00810 }

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

Definition at line 704 of file abstract_jb.c.

References fixed_jb_frame::data, and fixed_jb_remove().

00705 {
00706    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00707    struct fixed_jb_frame frame;
00708    int res;
00709 
00710    res = fixed_jb_remove(fixedjb, &frame);
00711    *fout = frame.data;
00712 
00713    return fixed_to_abstract_code[res];
00714 }


Variable Documentation

int adaptive_to_abstract_code[] [static]
Initial value:

Definition at line 155 of file abstract_jb.c.

struct ast_jb_impl avail_impl[] [static]

Definition at line 113 of file abstract_jb.c.

int default_impl = 0 [static]

Definition at line 141 of file abstract_jb.c.

int fixed_to_abstract_code[] [static]
Initial value:

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.


Generated by  doxygen 1.6.2