Mon May 14 04:42:58 2007

Asterisk developer's documentation


abstract_jb.c File Reference

Common implementation-independent jitterbuffer stuff. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/term.h"
#include "asterisk/options.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_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_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.
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_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 159 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 58 of file abstract_jb.c.

typedef void(*) jb_destroy_impl(void *jb)

Destroy.

Definition at line 60 of file abstract_jb.c.

typedef void(*) jb_force_resynch_impl(void *jb)

Force resynch.

Definition at line 72 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 66 of file abstract_jb.c.

typedef long(*) jb_next_impl(void *jb)

Get next.

Definition at line 68 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 62 of file abstract_jb.c.

typedef int(*) jb_put_impl(void *jb, struct ast_frame *fin, long now)

Put frame.

Definition at line 64 of file abstract_jb.c.

typedef int(*) jb_remove_impl(void *jb, struct ast_frame **fout)

Remove first frame.

Definition at line 70 of file abstract_jb.c.


Enumeration Type Documentation

anonymous enum

Internal jb flags

Enumerator:
JB_USE 
JB_TIMEBASE_INITIALIZED 
JB_CREATED 

Definition at line 49 of file abstract_jb.c.

00049      {
00050    JB_USE =                  (1 << 0),
00051    JB_TIMEBASE_INITIALIZED = (1 << 1),
00052    JB_CREATED =              (1 << 2)
00053 };

anonymous enum

Abstract return codes

Enumerator:
JB_IMPL_OK 
JB_IMPL_DROP 
JB_IMPL_INTERP 
JB_IMPL_NOFRAME 

Definition at line 142 of file abstract_jb.c.

00142      {
00143    JB_IMPL_OK,
00144    JB_IMPL_DROP,
00145    JB_IMPL_INTERP,
00146    JB_IMPL_NOFRAME
00147 };


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

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

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

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

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 525 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_jb_impl::name, option_verbose, ast_jb_impl::remove, and VERBOSE_PREFIX_3.

Referenced by ast_channel_free().

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

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

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

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

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

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

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

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

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

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

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

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

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

References ast_clear_flag, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frdup(), 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_jb::next, ast_jb_impl::next, ast_jb_impl::put, and ast_frame::ts.

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

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 567 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 gtalk_load_config(), load_module(), process_zap(), reload_config(), and store_config().

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

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_bridged_channel(), AST_CHANNEL_NAME, ast_frfree(), AST_JB_IMPL_NAME_SIZE, AST_JB_LOG, ast_log(), ast_test_flag, ast_verbose(), ast_jb::conf, CRASH, ast_jb_impl::create, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, JB_IMPL_OK, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_WARNING, ast_jb::logfile, ast_jb_impl::name, ast_jb_impl::next, ast_jb::next, option_verbose, ast_jb_impl::put_first, ast_jb_conf::resync_threshold, ast_frame::subclass, ast_frame::ts, and VERBOSE_PREFIX_3.

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       snprintf(name2, sizeof(name2), "%s", chan->name);
00485       tmp = strchr(name2, '/');
00486       if (tmp)
00487          *tmp = '#';
00488       
00489       bridged = ast_bridged_channel(chan);
00490       if (!bridged) {
00491          /* We should always have bridged chan if a jitterbuffer is in use */
00492          CRASH;
00493       }
00494       snprintf(name1, sizeof(name1), "%s", bridged->name);
00495       tmp = strchr(name1, '/');
00496       if (tmp)
00497          *tmp = '#';
00498       
00499       snprintf(logfile_pathname, sizeof(logfile_pathname),
00500          "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2);
00501       jb->logfile = fopen(logfile_pathname, "w+b");
00502       
00503       if (!jb->logfile)
00504          ast_log(LOG_WARNING, "Failed to create frame log file with pathname '%s'\n", logfile_pathname);
00505       
00506       if (res == JB_IMPL_OK)
00507          jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
00508             now, frr->ts, frr->len);
00509       else
00510          jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
00511             now, frr->ts, frr->len);
00512    }
00513 
00514    if (option_verbose > 2) 
00515       ast_verbose(VERBOSE_PREFIX_3 "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name);
00516    
00517    /* Free the frame if it has not been queued in the jb */
00518    if (res != JB_IMPL_OK)
00519       ast_frfree(frr);
00520    
00521    return 0;
00522 }

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

Definition at line 554 of file abstract_jb.c.

References ast_jb::timebase.

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

00555 {
00556    struct timeval now;
00557 
00558    if (!tv) {
00559       tv = &now;
00560       gettimeofday(tv, NULL);
00561    }
00562 
00563    return ast_tvdiff_ms(*tv, jb->timebase);
00564 }

static void jb_choose_impl ( struct ast_channel chan  )  [static]

Definition at line 177 of file abstract_jb.c.

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

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

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

Definition at line 703 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, and jb_conf::resync_threshold.

00704 {
00705    jb_conf jbconf;
00706    jitterbuf *adaptivejb;
00707 
00708    adaptivejb = jb_new();
00709    if (adaptivejb) {
00710       jbconf.max_jitterbuf = general_config->max_size;
00711       jbconf.resync_threshold = general_config->resync_threshold;
00712       jbconf.max_contig_interp = 10;
00713       jb_setconf(adaptivejb, &jbconf);
00714    }
00715    
00716    return adaptivejb;
00717 }

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

Definition at line 617 of file abstract_jb.c.

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

00618 {
00619    struct fixed_jb_conf conf;
00620    
00621    conf.jbsize = general_config->max_size;
00622    conf.resync_threshold = resynch_threshold;
00623    
00624    return fixed_jb_new(&conf);
00625 }

static void jb_destroy_adaptive ( void *  jb  )  [static]

Definition at line 720 of file abstract_jb.c.

References jb_destroy().

00721 {
00722    jitterbuf *adaptivejb = (jitterbuf *) jb;
00723    
00724    jb_destroy(adaptivejb);
00725 }

static void jb_destroy_fixed ( void *  jb  )  [static]

Definition at line 628 of file abstract_jb.c.

References fixed_jb_destroy().

00629 {
00630    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00631    
00632    /* destroy the jb */
00633    fixed_jb_destroy(fixedjb);
00634 }

static void jb_force_resynch_adaptive ( void *  jb  )  [static]

Definition at line 779 of file abstract_jb.c.

00780 {
00781 }

static void jb_force_resynch_fixed ( void *  jb  )  [static]

Definition at line 693 of file abstract_jb.c.

References fixed_jb_set_force_resynch().

00694 {
00695    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00696    
00697    fixed_jb_set_force_resynch(fixedjb);
00698 }

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

Definition at line 745 of file abstract_jb.c.

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

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

static void jb_get_and_deliver ( struct ast_channel chan  )  [static]

Definition at line 381 of file abstract_jb.c.

References ast_codec_interp_len(), AST_FRAME_VOICE, ast_frfree(), AST_FRIENDLY_OFFSET, ast_log(), ast_tvadd(), ast_write(), CRASH, 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_jb_impl::next, ast_jb::next, and ast_jb::timebase.

Referenced by ast_jb_get_and_deliver().

00382 {
00383    struct ast_jb *jb = &chan->jb;
00384    struct ast_jb_impl *jbimpl = jb->impl;
00385    void *jbobj = jb->jbobj;
00386    struct ast_frame *f, finterp;
00387    long now;
00388    int interpolation_len, res;
00389    
00390    now = get_now(jb, NULL);
00391    jb->next = jbimpl->next(jbobj);
00392    if (now < jb->next) {
00393       jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next);
00394       return;
00395    }
00396    
00397    while (now >= jb->next) {
00398       interpolation_len = ast_codec_interp_len(jb->last_format);
00399       
00400       res = jbimpl->get(jbobj, &f, now, interpolation_len);
00401       
00402       switch(res) {
00403       case JB_IMPL_OK:
00404          /* deliver the frame */
00405          ast_write(chan, f);
00406       case JB_IMPL_DROP:
00407          jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
00408             now, jb_get_actions[res], f->ts, f->len);
00409          jb->last_format = f->subclass;
00410          ast_frfree(f);
00411          break;
00412       case JB_IMPL_INTERP:
00413          /* interpolate a frame */
00414          f = &finterp;
00415          f->frametype = AST_FRAME_VOICE;
00416          f->subclass = jb->last_format;
00417          f->datalen  = 0;
00418          f->samples  = interpolation_len * 8;
00419          f->mallocd  = 0;
00420          f->src  = "JB interpolation";
00421          f->data  = NULL;
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 retuned 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          CRASH;
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 659 of file abstract_jb.c.

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

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

static long jb_next_adaptive ( void *  jb  )  [static]

Definition at line 758 of file abstract_jb.c.

References jb_next().

00759 {
00760    jitterbuf *adaptivejb = (jitterbuf *) jb;
00761    
00762    return jb_next(adaptivejb);
00763 }

static long jb_next_fixed ( void *  jb  )  [static]

Definition at line 672 of file abstract_jb.c.

References fixed_jb_next().

00673 {
00674    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00675    
00676    return fixed_jb_next(fixedjb);
00677 }

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

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

00735 {
00736    jitterbuf *adaptivejb = (jitterbuf *) jb;
00737    int res;
00738    
00739    res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
00740    
00741    return adaptive_to_abstract_code[res];
00742 }

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

Definition at line 728 of file abstract_jb.c.

References jb_put_adaptive().

00729 {
00730    return jb_put_adaptive(jb, fin, now);
00731 }

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

Definition at line 637 of file abstract_jb.c.

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

00638 {
00639    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00640    int res;
00641    
00642    res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now);
00643    
00644    return fixed_to_abstract_code[res];
00645 }

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

Definition at line 648 of file abstract_jb.c.

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

00649 {
00650    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00651    int res;
00652    
00653    res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now);
00654    
00655    return fixed_to_abstract_code[res];
00656 }

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

Definition at line 766 of file abstract_jb.c.

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

00767 {
00768    jitterbuf *adaptivejb = (jitterbuf *) jb;
00769    jb_frame frame;
00770    int res;
00771    
00772    res = jb_getall(adaptivejb, &frame);
00773    *fout = frame.data;
00774    
00775    return adaptive_to_abstract_code[res];
00776 }

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

Definition at line 680 of file abstract_jb.c.

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

00681 {
00682    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00683    struct fixed_jb_frame frame;
00684    int res;
00685    
00686    res = fixed_jb_remove(fixedjb, &frame);
00687    *fout = frame.data;
00688    
00689    return fixed_to_abstract_code[res];
00690 }


Variable Documentation

int adaptive_to_abstract_code[] [static]

Initial value:

Definition at line 152 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 112 of file abstract_jb.c.

Referenced by jb_choose_impl().

int default_impl = 0 [static]

Definition at line 138 of file abstract_jb.c.

int fixed_to_abstract_code[] [static]

Initial value:

Definition at line 150 of file abstract_jb.c.

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

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

Definition at line 156 of file abstract_jb.c.

Referenced by jb_get_and_deliver().


Generated on Mon May 14 04:43:00 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1