Sat Mar 10 01:54:29 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"

Go to the source code of this file.

Data Structures

struct  ast_jb_impl
 Jitterbuffer implementation private struct. More...

Defines

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

Typedefs

typedef void *(*) jb_create_impl (struct ast_jb_conf *general_config, long resynch_threshold)
 Create.
typedef void(*) jb_destroy_impl (void *jb)
 Destroy.
typedef void(*) jb_empty_and_reset_impl (void *jb)
 Empty and reset jb.
typedef void(*) jb_force_resynch_impl (void *jb)
 Force resynch.
typedef int(*) jb_get_impl (void *jb, struct ast_frame **fout, long now, long interpl)
 Get frame for now.
typedef long(*) jb_next_impl (void *jb)
 Get next.
typedef int(*) jb_put_first_impl (void *jb, struct ast_frame *fin, long now)
 Put first frame.
typedef int(*) jb_put_impl (void *jb, struct ast_frame *fin, long now)
 Put frame.
typedef int(*) jb_remove_impl (void *jb, struct ast_frame **fout)
 Remove first frame.

Enumerations

enum  { JB_USE = (1 << 0), JB_TIMEBASE_INITIALIZED = (1 << 1), JB_CREATED = (1 << 2) }
enum  { JB_IMPL_OK, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME }

Functions

void ast_jb_configure (struct ast_channel *chan, const struct ast_jb_conf *conf)
 Configures a jitterbuffer on a channel.
void ast_jb_destroy (struct ast_channel *chan)
 Destroys jitterbuffer on a channel.
int ast_jb_do_usecheck (struct ast_channel *c0, struct ast_channel *c1)
 Checks the need of a jb use in a generic bridge.
void ast_jb_empty_and_reset (struct ast_channel *c0, struct ast_channel *c1)
 drops all frames from a jitterbuffer and resets it
void ast_jb_get_and_deliver (struct ast_channel *c0, struct ast_channel *c1)
 Deliver the queued frames that should be delivered now for both channels.
void ast_jb_get_config (const struct ast_channel *chan, struct ast_jb_conf *conf)
 Copies a channel's jitterbuffer configuration.
int ast_jb_get_when_to_wakeup (struct ast_channel *c0, struct ast_channel *c1, int time_left)
 Calculates the time, left to the closest delivery moment in a bridge.
int ast_jb_put (struct ast_channel *chan, struct ast_frame *f)
 Puts a frame into a channel jitterbuffer.
int ast_jb_read_conf (struct ast_jb_conf *conf, const char *varname, const char *value)
 Sets jitterbuffer configuration property.
static int create_jb (struct ast_channel *chan, struct ast_frame *first_frame)
static long get_now (struct ast_jb *jb, struct timeval *tv)
static void jb_choose_impl (struct ast_channel *chan)
static void * jb_create_adaptive (struct ast_jb_conf *general_config, long resynch_threshold)
static void * jb_create_fixed (struct ast_jb_conf *general_config, long resynch_threshold)
static void jb_destroy_adaptive (void *jb)
static void jb_destroy_fixed (void *jb)
static void jb_empty_and_reset_adaptive (void *jb)
static void jb_empty_and_reset_fixed (void *jb)
static void jb_force_resynch_adaptive (void *jb)
static void jb_force_resynch_fixed (void *jb)
static int jb_get_adaptive (void *jb, struct ast_frame **fout, long now, long interpl)
static void jb_get_and_deliver (struct ast_channel *chan)
static int jb_get_fixed (void *jb, struct ast_frame **fout, long now, long interpl)
static long jb_next_adaptive (void *jb)
static long jb_next_fixed (void *jb)
static int jb_put_adaptive (void *jb, struct ast_frame *fin, long now)
static int jb_put_first_adaptive (void *jb, struct ast_frame *fin, long now)
static int jb_put_first_fixed (void *jb, struct ast_frame *fin, long now)
static int jb_put_fixed (void *jb, struct ast_frame *fin, long now)
static int jb_remove_adaptive (void *jb, struct ast_frame **fout)
static int jb_remove_fixed (void *jb, struct ast_frame **fout)

Variables

static const int adaptive_to_abstract_code []
static struct ast_jb_impl avail_impl []
static int default_impl = 0
static const int fixed_to_abstract_code []
static const char *const jb_get_actions [] = {"Delivered", "Dropped", "Interpolated", "No"}


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

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


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

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

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 531 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_destructor().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 302 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.

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

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

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

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

Definition at line 444 of file abstract_jb.c.

References ast_assert, ast_bridged_channel(), AST_CHANNEL_NAME, ast_frfree, AST_JB_IMPL_NAME_SIZE, AST_JB_LOG, ast_log(), ast_test_flag, ast_verb, ast_frame_subclass::codec, ast_jb::conf, ast_jb_impl::create, errno, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, JB_IMPL_OK, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb::logfile, ast_jb_impl::name, ast_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().

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

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

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

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

static void jb_choose_impl ( struct ast_channel chan  )  [static]

Definition at line 179 of file abstract_jb.c.

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

Referenced by ast_jb_do_usecheck().

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

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

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

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

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

Definition at line 643 of file abstract_jb.c.

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

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

static void jb_destroy_adaptive ( void *  jb  )  [static]

Definition at line 755 of file abstract_jb.c.

References jb_destroy().

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

static void jb_destroy_fixed ( void *  jb  )  [static]

Definition at line 653 of file abstract_jb.c.

References fixed_jb_destroy().

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

static void jb_empty_and_reset_adaptive ( void *  jb  )  [static]

Definition at line 823 of file abstract_jb.c.

References ast_frfree, f, jb_getall(), JB_OK, and jb_reset().

00824 {
00825    jitterbuf *adaptivejb = jb;
00826    jb_frame f;
00827 
00828    while (jb_getall(adaptivejb, &f) == JB_OK) {
00829       ast_frfree(f.data);
00830    }
00831 
00832    jb_reset(adaptivejb);
00833 }

static void jb_empty_and_reset_fixed ( void *  jb  )  [static]

Definition at line 725 of file abstract_jb.c.

References ast_frfree, f, FIXED_JB_OK, and fixed_jb_remove().

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

static void jb_force_resynch_adaptive ( void *  jb  )  [static]

Definition at line 819 of file abstract_jb.c.

00820 {
00821 }

static void jb_force_resynch_fixed ( void *  jb  )  [static]

Definition at line 718 of file abstract_jb.c.

References fixed_jb_set_force_resynch().

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

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

Definition at line 785 of file abstract_jb.c.

References adaptive_to_abstract_code, jb_frame::data, and jb_get().

00786 {
00787    jitterbuf *adaptivejb = (jitterbuf *) jb;
00788    jb_frame frame;
00789    int res;
00790 
00791    res = jb_get(adaptivejb, &frame, now, interpl);
00792    *fout = frame.data;
00793 
00794    return adaptive_to_abstract_code[res];
00795 }

static void jb_get_and_deliver ( struct ast_channel chan  )  [static]

Definition at line 384 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(), f, ast_jb_impl::get, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, jb_get_actions, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME, JB_IMPL_OK, ast_jb::jbobj, ast_jb::last_format, LOG_ERROR, LOG_WARNING, ast_jb_impl::name, ast_frame::next, ast_jb_impl::next, ast_jb::next, and ast_jb::timebase.

Referenced by ast_jb_get_and_deliver().

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

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

Definition at line 684 of file abstract_jb.c.

References fixed_jb_frame::data, fixed_jb_get(), and fixed_to_abstract_code.

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

static long jb_next_adaptive ( void *  jb  )  [static]

Definition at line 798 of file abstract_jb.c.

References jb_next().

00799 {
00800    jitterbuf *adaptivejb = (jitterbuf *) jb;
00801 
00802    return jb_next(adaptivejb);
00803 }

static long jb_next_fixed ( void *  jb  )  [static]

Definition at line 697 of file abstract_jb.c.

References fixed_jb_next().

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

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

Definition at line 774 of file abstract_jb.c.

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

Referenced by jb_put_first_adaptive().

00775 {
00776    jitterbuf *adaptivejb = (jitterbuf *) jb;
00777    int res;
00778 
00779    res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
00780 
00781    return adaptive_to_abstract_code[res];
00782 }

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

Definition at line 763 of file abstract_jb.c.

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

00764 {
00765    jitterbuf *adaptivejb = (jitterbuf *) jb;
00766 
00767    /* Initialize the offset to that of the first frame's timestamp */
00768    adaptivejb->info.resync_offset = fin->ts;
00769 
00770    return jb_put_adaptive(jb, fin, now);
00771 }

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

Definition at line 662 of file abstract_jb.c.

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

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

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

Definition at line 673 of file abstract_jb.c.

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

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

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

Definition at line 806 of file abstract_jb.c.

References adaptive_to_abstract_code, jb_frame::data, and jb_getall().

00807 {
00808    jitterbuf *adaptivejb = (jitterbuf *) jb;
00809    jb_frame frame;
00810    int res;
00811 
00812    res = jb_getall(adaptivejb, &frame);
00813    *fout = frame.data;
00814 
00815    return adaptive_to_abstract_code[res];
00816 }

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

Definition at line 705 of file abstract_jb.c.

References fixed_jb_frame::data, fixed_jb_remove(), and fixed_to_abstract_code.

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


Variable Documentation

const int adaptive_to_abstract_code[] [static]

Initial value:

Definition at line 154 of file abstract_jb.c.

Referenced by jb_get_adaptive(), jb_put_adaptive(), and jb_remove_adaptive().

struct ast_jb_impl avail_impl[] [static]

Definition at line 113 of file abstract_jb.c.

Referenced by jb_choose_impl().

int default_impl = 0 [static]

Definition at line 140 of file abstract_jb.c.

const int fixed_to_abstract_code[] [static]

Initial value:

Definition at line 152 of file abstract_jb.c.

Referenced by jb_get_fixed(), jb_put_first_fixed(), jb_put_fixed(), and jb_remove_fixed().

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

Definition at line 158 of file abstract_jb.c.

Referenced by jb_get_and_deliver().


Generated on Sat Mar 10 01:54:29 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7