Fri Apr 24 16:26:03 2009

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"

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, 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_empty_and_reset_adaptive (void *jb)
static void jb_empty_and_reset_fixed (void *jb)
static void jb_force_resynch_adaptive (void *jb)
static void jb_force_resynch_fixed (void *jb)
static int jb_get_adaptive (void *jb, struct ast_frame **fout, long now, long interpl)
static void jb_get_and_deliver (struct ast_channel *chan)
static int jb_get_fixed (void *jb, struct ast_frame **fout, long now, long interpl)
static long jb_next_adaptive (void *jb)
static long jb_next_fixed (void *jb)
static int jb_put_adaptive (void *jb, struct ast_frame *fin, long now)
static int jb_put_first_adaptive (void *jb, struct ast_frame *fin, long now)
static int jb_put_first_fixed (void *jb, struct ast_frame *fin, long now)
static int jb_put_fixed (void *jb, struct ast_frame *fin, long now)
static int jb_remove_adaptive (void *jb, struct ast_frame **fout)
static int jb_remove_fixed (void *jb, struct ast_frame **fout)

Variables

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


Detailed Description

Common implementation-independent jitterbuffer stuff.

Author:
Slav Klenov <slav@securax.org>

Definition in file abstract_jb.c.


Define Documentation

 
#define jb_framelog (  ) 

Macros for the frame log files.

Definition at line 165 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_empty_and_reset_impl(void *jb)

Empty and reset jb.

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

00148      {
00149    JB_IMPL_OK,
00150    JB_IMPL_DROP,
00151    JB_IMPL_INTERP,
00152    JB_IMPL_NOFRAME
00153 };


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

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

void ast_jb_destroy ( struct ast_channel chan  ) 

Destroys jitterbuffer on a channel.

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

Definition at line 530 of file abstract_jb.c.

References ast_clear_flag, ast_frfree, ast_test_flag, ast_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, ast_channel::name, option_verbose, ast_jb_impl::remove, and VERBOSE_PREFIX_3.

Referenced by ast_channel_free().

00531 {
00532    struct ast_jb *jb = &chan->jb;
00533    struct ast_jb_impl *jbimpl = jb->impl;
00534    void *jbobj = jb->jbobj;
00535    struct ast_frame *f;
00536 
00537    if (jb->logfile) {
00538       fclose(jb->logfile);
00539       jb->logfile = NULL;
00540    }
00541    
00542    if (ast_test_flag(jb, JB_CREATED)) {
00543       /* Remove and free all frames still queued in jb */
00544       while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) {
00545          ast_frfree(f);
00546       }
00547       
00548       jbimpl->destroy(jbobj);
00549       jb->jbobj = NULL;
00550       
00551       ast_clear_flag(jb, JB_CREATED);
00552 
00553       if (option_verbose > 2)
00554          ast_verbose(VERBOSE_PREFIX_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.

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

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

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

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

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

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::next, ast_jb_impl::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 recieved 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 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_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().

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

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

Definition at line 451 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_verbose(), ast_jb::conf, 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_channel::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().

00452 {
00453    struct ast_jb *jb = &chan->jb;
00454    struct ast_jb_conf *jbconf = &jb->conf;
00455    struct ast_jb_impl *jbimpl = jb->impl;
00456    void *jbobj;
00457    struct ast_channel *bridged;
00458    long now;
00459    char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1];
00460    char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp;
00461    int res;
00462 
00463    jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold);
00464    if (!jbobj) {
00465       ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name);
00466       return -1;
00467    }
00468    
00469    now = get_now(jb, NULL);
00470    res = jbimpl->put_first(jbobj, frr, now);
00471    
00472    /* The result of putting the first frame should not differ from OK. However, its possible
00473       some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */
00474    if (res != JB_IMPL_OK) {
00475       ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name);
00476       /*
00477       jbimpl->destroy(jbobj);
00478       return -1;
00479       */
00480    }
00481    
00482    /* Init next */
00483    jb->next = jbimpl->next(jbobj);
00484    
00485    /* Init last format for a first time. */
00486    jb->last_format = frr->subclass;
00487    
00488    /* Create a frame log file */
00489    if (ast_test_flag(jbconf, AST_JB_LOG)) {
00490       snprintf(name2, sizeof(name2), "%s", chan->name);
00491       tmp = strchr(name2, '/');
00492       if (tmp)
00493          *tmp = '#';
00494       
00495       bridged = ast_bridged_channel(chan);
00496       /* We should always have bridged chan if a jitterbuffer is in use */
00497       ast_assert(bridged != NULL);
00498 
00499       snprintf(name1, sizeof(name1), "%s", bridged->name);
00500       tmp = strchr(name1, '/');
00501       if (tmp)
00502          *tmp = '#';
00503       
00504       snprintf(logfile_pathname, sizeof(logfile_pathname),
00505          "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2);
00506       jb->logfile = fopen(logfile_pathname, "w+b");
00507       
00508       if (!jb->logfile)
00509          ast_log(LOG_WARNING, "Failed to create frame log file with pathname '%s'\n", logfile_pathname);
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    if (option_verbose > 2) 
00520       ast_verbose(VERBOSE_PREFIX_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    return 0;
00527 }

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 (!tv) {
00564       tv = &now;
00565       gettimeofday(tv, NULL);
00566    }
00567 
00568    return ast_tvdiff_ms(*tv, jb->timebase);
00569 }

static void jb_choose_impl ( struct ast_channel chan  )  [static]

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

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

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

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

00733 {
00734    jb_conf jbconf;
00735    jitterbuf *adaptivejb;
00736 
00737    adaptivejb = jb_new();
00738    if (adaptivejb) {
00739       jbconf.max_jitterbuf = general_config->max_size;
00740       jbconf.resync_threshold = general_config->resync_threshold;
00741       jbconf.max_contig_interp = 10;
00742       jb_setconf(adaptivejb, &jbconf);
00743    }
00744    
00745    return adaptivejb;
00746 }

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

Definition at line 638 of file abstract_jb.c.

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

00639 {
00640    struct fixed_jb_conf conf;
00641 
00642    conf.jbsize = general_config->max_size;
00643    conf.resync_threshold = resynch_threshold;
00644 
00645    return fixed_jb_new(&conf);
00646 }

static void jb_destroy_adaptive ( void *  jb  )  [static]

Definition at line 749 of file abstract_jb.c.

References jb_destroy().

00750 {
00751    jitterbuf *adaptivejb = (jitterbuf *) jb;
00752    
00753    jb_destroy(adaptivejb);
00754 }

static void jb_destroy_fixed ( void *  jb  )  [static]

Definition at line 648 of file abstract_jb.c.

References fixed_jb_destroy().

00649 {
00650    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00651    
00652    /* destroy the jb */
00653    fixed_jb_destroy(fixedjb);
00654 }

static void jb_empty_and_reset_adaptive ( void *  jb  )  [static]

Definition at line 812 of file abstract_jb.c.

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

00813 {
00814    jitterbuf *adaptivejb = jb;
00815    jb_frame f;
00816 
00817    while (jb_getall(adaptivejb, &f) == JB_OK) {
00818       ast_frfree(f.data);
00819    }
00820 
00821    jb_reset(adaptivejb);
00822 }

static void jb_empty_and_reset_fixed ( void *  jb  )  [static]

Definition at line 720 of file abstract_jb.c.

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

00721 {
00722    struct fixed_jb *fixedjb = jb;
00723    struct fixed_jb_frame f;
00724 
00725    while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) {
00726       ast_frfree(f.data);
00727    }
00728 }

static void jb_force_resynch_adaptive ( void *  jb  )  [static]

Definition at line 808 of file abstract_jb.c.

00809 {
00810 }

static void jb_force_resynch_fixed ( void *  jb  )  [static]

Definition at line 713 of file abstract_jb.c.

References fixed_jb_set_force_resynch().

00714 {
00715    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00716    
00717    fixed_jb_set_force_resynch(fixedjb);
00718 }

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

Definition at line 774 of file abstract_jb.c.

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

00775 {
00776    jitterbuf *adaptivejb = (jitterbuf *) jb;
00777    jb_frame frame;
00778    int res;
00779    
00780    res = jb_get(adaptivejb, &frame, now, interpl);
00781    *fout = frame.data;
00782    
00783    return adaptive_to_abstract_code[res];
00784 }

static void jb_get_and_deliver ( struct ast_channel chan  )  [static]

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

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

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

Definition at line 679 of file abstract_jb.c.

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

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

static long jb_next_adaptive ( void *  jb  )  [static]

Definition at line 787 of file abstract_jb.c.

References jb_next().

00788 {
00789    jitterbuf *adaptivejb = (jitterbuf *) jb;
00790    
00791    return jb_next(adaptivejb);
00792 }

static long jb_next_fixed ( void *  jb  )  [static]

Definition at line 692 of file abstract_jb.c.

References fixed_jb_next().

00693 {
00694    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00695    
00696    return fixed_jb_next(fixedjb);
00697 }

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

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

00764 {
00765    jitterbuf *adaptivejb = (jitterbuf *) jb;
00766    int res;
00767    
00768    res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
00769    
00770    return adaptive_to_abstract_code[res];
00771 }

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

Definition at line 757 of file abstract_jb.c.

References jb_put_adaptive().

00758 {
00759    return jb_put_adaptive(jb, fin, now);
00760 }

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

Definition at line 657 of file abstract_jb.c.

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

00658 {
00659    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00660    int res;
00661    
00662    res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now);
00663    
00664    return fixed_to_abstract_code[res];
00665 }

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

Definition at line 668 of file abstract_jb.c.

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

00669 {
00670    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00671    int res;
00672    
00673    res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now);
00674    
00675    return fixed_to_abstract_code[res];
00676 }

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

Definition at line 795 of file abstract_jb.c.

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

00796 {
00797    jitterbuf *adaptivejb = (jitterbuf *) jb;
00798    jb_frame frame;
00799    int res;
00800    
00801    res = jb_getall(adaptivejb, &frame);
00802    *fout = frame.data;
00803    
00804    return adaptive_to_abstract_code[res];
00805 }

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

Definition at line 700 of file abstract_jb.c.

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

00701 {
00702    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00703    struct fixed_jb_frame frame;
00704    int res;
00705    
00706    res = fixed_jb_remove(fixedjb, &frame);
00707    *fout = frame.data;
00708    
00709    return fixed_to_abstract_code[res];
00710 }


Variable Documentation

int adaptive_to_abstract_code[] [static]

Initial value:

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

Referenced by jb_choose_impl().

int default_impl = 0 [static]

Definition at line 144 of file abstract_jb.c.

int fixed_to_abstract_code[] [static]

Initial value:

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

Referenced by jb_get_and_deliver().


Generated on Fri Apr 24 16:26:04 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7