Sat Aug 6 00:39:33 2011

Asterisk developer's documentation


abstract_jb.h File Reference

Common implementation-independent jitterbuffer stuff. More...

#include <stdio.h>
#include <sys/time.h>

Go to the source code of this file.

Data Structures

struct  ast_jb
 General jitterbuffer state. More...
struct  ast_jb_conf
 General jitterbuffer configuration. More...

Defines

#define AST_JB_CONF_ENABLE   "enable"
#define AST_JB_CONF_FORCE   "force"
#define AST_JB_CONF_IMPL   "impl"
#define AST_JB_CONF_LOG   "log"
#define AST_JB_CONF_MAX_SIZE   "maxsize"
#define AST_JB_CONF_PREFIX   "jb"
#define AST_JB_CONF_RESYNCH_THRESHOLD   "resyncthreshold"
#define AST_JB_IMPL_NAME_SIZE   12

Enumerations

enum  { AST_JB_ENABLED = (1 << 0), AST_JB_FORCED = (1 << 1), AST_JB_LOG = (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.
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, char *varname, char *value)
 Sets jitterbuffer configuration property.


Detailed Description

Common implementation-independent jitterbuffer stuff.

Author:
Slav Klenov <slav@securax.org>

Definition in file abstract_jb.h.


Define Documentation

#define AST_JB_CONF_ENABLE   "enable"

Definition at line 70 of file abstract_jb.h.

Referenced by ast_jb_read_conf().

#define AST_JB_CONF_FORCE   "force"

Definition at line 71 of file abstract_jb.h.

Referenced by ast_jb_read_conf().

#define AST_JB_CONF_IMPL   "impl"

Definition at line 74 of file abstract_jb.h.

Referenced by ast_jb_read_conf().

#define AST_JB_CONF_LOG   "log"

Definition at line 75 of file abstract_jb.h.

Referenced by ast_jb_read_conf().

#define AST_JB_CONF_MAX_SIZE   "maxsize"

Definition at line 72 of file abstract_jb.h.

Referenced by ast_jb_read_conf().

#define AST_JB_CONF_PREFIX   "jb"

Definition at line 69 of file abstract_jb.h.

Referenced by ast_jb_read_conf().

#define AST_JB_CONF_RESYNCH_THRESHOLD   "resyncthreshold"

Definition at line 73 of file abstract_jb.h.

Referenced by ast_jb_read_conf().

#define AST_JB_IMPL_NAME_SIZE   12

Definition at line 50 of file abstract_jb.h.

Referenced by create_jb().


Enumeration Type Documentation

anonymous enum

Enumerator:
AST_JB_ENABLED 
AST_JB_FORCED 
AST_JB_LOG 

Definition at line 44 of file abstract_jb.h.

00044      {
00045    AST_JB_ENABLED = (1 << 0),
00046    AST_JB_FORCED =  (1 << 1),
00047    AST_JB_LOG =     (1 << 2)
00048 };


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

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

Referenced by __oh323_rtp_create(), __oh323_update_info(), alsa_new(), dahdi_new(), gtalk_new(), mgcp_new(), misdn_new(), oss_new(), sip_new(), and skinny_new().

00603 {
00604    memcpy(&chan->jb.conf, conf, sizeof(*conf));
00605 }

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

References ast_clear_flag, ast_frfree, ast_test_flag, ast_verbose(), 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, option_verbose, ast_jb_impl::remove, and VERBOSE_PREFIX_3.

Referenced by ast_channel_free().

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

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.

Returns:
zero if there are no jitter buffers in use, non-zero if there are

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

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

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 613 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().

00614 {
00615    struct ast_jb *jb0 = &c0->jb;
00616    struct ast_jb *jb1 = &c1->jb;
00617    int c0_use_jb = ast_test_flag(jb0, JB_USE);
00618    int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00619    int c1_use_jb = ast_test_flag(jb1, JB_USE);
00620    int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00621 
00622    if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) {
00623       jb0->impl->empty_and_reset(jb0->jbobj);
00624    }
00625 
00626    if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) {
00627       jb1->impl->empty_and_reset(jb1->jbobj);
00628    }
00629 }

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

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

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

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

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

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

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

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

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

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.

Returns:
zero if the frame was queued, -1 if not.

Definition at line 305 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(), f, ast_jb_impl::force_resync, 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, and ast_frame::ts.

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

int ast_jb_read_conf ( struct ast_jb_conf conf,
char *  varname,
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 tipically when reading a configuration file. It is not neccessary 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 568 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_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, and ast_jb_conf::resync_threshold.

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

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


Generated on Sat Aug 6 00:39:33 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7