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/pbx.h"
#include "asterisk/timing.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  jb_framedata

Defines

#define DEFAULT_RESYNC   1000
#define DEFAULT_SIZE   200
#define DEFAULT_TARGET_EXTRA   40
#define DEFAULT_TIMER_INTERVAL   20
#define DEFAULT_TYPE   AST_JB_FIXED
#define jb_framelog(...)
 Macros for the frame log files.

Enumerations

enum  { JB_USE = (1 << 0), JB_TIMEBASE_INITIALIZED = (1 << 1), JB_CREATED = (1 << 2) }

Functions

void ast_jb_conf_default (struct ast_jb_conf *conf)
 Sets the contents of an ast_jb_conf struct to the default jitterbuffer settings.
void ast_jb_configure (struct ast_channel *chan, const struct ast_jb_conf *conf)
 Configures a jitterbuffer on a channel.
void ast_jb_create_framehook (struct ast_channel *chan, struct ast_jb_conf *jb_conf, int prefer_existing)
 Applies a jitterbuffer framehook to a channel based on a provided jitterbuffer config.
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_enable_for_channel (struct ast_channel *chan)
 Sets a jitterbuffer frame hook on the channel based on the channel's stored jitterbuffer configuration.
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.
struct ast_jb_implast_jb_get_impl (enum ast_jb_type type)
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 void datastore_destroy_cb (void *data)
static long get_now (struct ast_jb *jb, struct timeval *tv)
static void hook_destroy_cb (void *framedata)
static struct ast_framehook_event_cb (struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
static void jb_choose_impl (struct ast_channel *chan)
static void * jb_create_adaptive (struct ast_jb_conf *general_config)
static void * jb_create_fixed (struct ast_jb_conf *general_config)
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 void jb_framedata_destroy (struct jb_framedata *framedata)
static int jb_framedata_init (struct jb_framedata *framedata, struct ast_jb_conf *jb_conf)
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 struct ast_datastore_info jb_datastore
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 DEFAULT_RESYNC   1000

Definition at line 818 of file abstract_jb.c.

Referenced by ast_jb_conf_default().

#define DEFAULT_SIZE   200

Definition at line 816 of file abstract_jb.c.

Referenced by ast_jb_conf_default().

#define DEFAULT_TARGET_EXTRA   40

Definition at line 817 of file abstract_jb.c.

Referenced by ast_jb_conf_default().

#define DEFAULT_TIMER_INTERVAL   20

Definition at line 815 of file abstract_jb.c.

Referenced by jb_framedata_init().

#define DEFAULT_TYPE   AST_JB_FIXED

Definition at line 819 of file abstract_jb.c.

Referenced by jb_framedata_init().

#define jb_framelog ( ...   ) 

Macros for the frame log files.

Definition at line 123 of file abstract_jb.c.

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


Enumeration Type Documentation

anonymous enum

Internal jb flags

Enumerator:
JB_USE 
JB_TIMEBASE_INITIALIZED 
JB_CREATED 

Definition at line 52 of file abstract_jb.c.

00052      {
00053    JB_USE =                  (1 << 0),
00054    JB_TIMEBASE_INITIALIZED = (1 << 1),
00055    JB_CREATED =              (1 << 2)
00056 };


Function Documentation

void ast_jb_conf_default ( struct ast_jb_conf conf  ) 

Sets the contents of an ast_jb_conf struct to the default jitterbuffer settings.

Since:
12
Parameters:
conf Which jitterbuffer is being set

Definition at line 851 of file abstract_jb.c.

References ast_copy_string(), DEFAULT_RESYNC, DEFAULT_SIZE, DEFAULT_TARGET_EXTRA, ast_jb_conf::impl, ast_jb_conf::max_size, ast_jb_conf::resync_threshold, and ast_jb_conf::target_extra.

Referenced by jb_helper().

00852 {
00853    conf->max_size = DEFAULT_SIZE;
00854    conf->resync_threshold = DEFAULT_RESYNC;
00855    ast_copy_string(conf->impl, "fixed", sizeof(conf->impl));
00856    conf->target_extra = DEFAULT_TARGET_EXTRA;
00857 }

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

References ast_channel_jb().

Referenced by alsa_new(), ast_unreal_new_channels(), console_new(), dahdi_new(), mgcp_new(), misdn_new(), ooh323_new(), oss_new(), sip_new(), skinny_new(), and unistim_new().

00583 {
00584    memcpy(&ast_channel_jb(chan)->conf, conf, sizeof(*conf));
00585 }

void ast_jb_create_framehook ( struct ast_channel chan,
struct ast_jb_conf jb_conf,
int  prefer_existing 
)

Applies a jitterbuffer framehook to a channel based on a provided jitterbuffer config.

Since:
12
Parameters:
chan Which channel the jitterbuffer is being set on
jb_conf Configuration to use for the jitterbuffer
prefer_existing If this is true and a jitterbuffer already exists for the channel, use the existing jitterbuffer

Definition at line 1050 of file abstract_jb.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_set_fd(), ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_framehook_attach(), ast_framehook_detach(), AST_FRAMEHOOK_INTERFACE_VERSION, AST_JITTERBUFFER_FD, ast_framehook_interface::data, ast_datastore::data, hook_destroy_cb(), hook_event_cb(), id, ast_jb_conf::impl, jb_framedata_destroy(), jb_framedata_init(), NULL, jb_framedata::timer_fd, and ast_framehook_interface::version.

Referenced by ast_jb_enable_for_channel(), and jb_helper().

01051 {
01052    struct jb_framedata *framedata;
01053    struct ast_datastore *datastore = NULL;
01054    struct ast_framehook_interface interface = {
01055       .version = AST_FRAMEHOOK_INTERFACE_VERSION,
01056       .event_cb = hook_event_cb,
01057       .destroy_cb = hook_destroy_cb,
01058    };
01059    int i = 0;
01060 
01061    /* If disabled, strip any existing jitterbuffer and don't replace it. */
01062    if (!strcasecmp(jb_conf->impl, "disabled")) {
01063       int *id;
01064       ast_channel_lock(chan);
01065       if ((datastore = ast_channel_datastore_find(chan, &jb_datastore, NULL))) {
01066          id = datastore->data;
01067          ast_framehook_detach(chan, *id);
01068          ast_channel_datastore_remove(chan, datastore);
01069          ast_datastore_free(datastore);
01070       }
01071       ast_channel_unlock(chan);
01072       return;
01073    }
01074 
01075    if (!(framedata = ast_calloc(1, sizeof(*framedata)))) {
01076       return;
01077    }
01078 
01079    if (jb_framedata_init(framedata, jb_conf)) {
01080       jb_framedata_destroy(framedata);
01081       return;
01082    }
01083 
01084    interface.data = framedata;
01085 
01086    ast_channel_lock(chan);
01087    i = ast_framehook_attach(chan, &interface);
01088    if (i >= 0) {
01089       int *id;
01090       if ((datastore = ast_channel_datastore_find(chan, &jb_datastore, NULL))) {
01091          /* There is already a jitterbuffer on the channel. */
01092          if (prefer_existing) {
01093             /* We prefer the existing jitterbuffer, so remove the new one and keep the old one. */
01094             ast_framehook_detach(chan, i);
01095             ast_channel_unlock(chan);
01096             return;
01097          }
01098          /* We prefer the new jitterbuffer, so strip the old one. */
01099          id = datastore->data;
01100          ast_framehook_detach(chan, *id);
01101          ast_channel_datastore_remove(chan, datastore);
01102          ast_datastore_free(datastore);
01103       }
01104 
01105       if (!(datastore = ast_datastore_alloc(&jb_datastore, NULL))) {
01106          ast_framehook_detach(chan, i);
01107          ast_channel_unlock(chan);
01108          return;
01109       }
01110 
01111       if (!(id = ast_calloc(1, sizeof(int)))) {
01112          ast_datastore_free(datastore);
01113          ast_framehook_detach(chan, i);
01114          ast_channel_unlock(chan);
01115          return;
01116       }
01117 
01118       *id = i; /* Store off the id. The channel is still locked so it is safe to access this ptr. */
01119       datastore->data = id;
01120       ast_channel_datastore_add(chan, datastore);
01121 
01122       ast_channel_set_fd(chan, AST_JITTERBUFFER_FD, framedata->timer_fd);
01123    } else {
01124       jb_framedata_destroy(framedata);
01125       framedata = NULL;
01126    }
01127    ast_channel_unlock(chan);
01128 }

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

References ao2_cleanup, ast_channel_jb(), ast_channel_name(), ast_clear_flag, ast_frfree, AST_JB_IMPL_OK, ast_test_flag, ast_verb, ast_jb_impl::destroy, f, ast_jb::impl, JB_CREATED, ast_jb::jbobj, ast_jb::last_format, ast_jb::logfile, ast_jb_impl::name, NULL, and ast_jb_impl::remove.

Referenced by ast_channel_destructor().

00494 {
00495    struct ast_jb *jb = ast_channel_jb(chan);
00496    const struct ast_jb_impl *jbimpl = jb->impl;
00497    void *jbobj = jb->jbobj;
00498    struct ast_frame *f;
00499 
00500    if (jb->logfile) {
00501       fclose(jb->logfile);
00502       jb->logfile = NULL;
00503    }
00504 
00505    ao2_cleanup(jb->last_format);
00506 
00507    if (ast_test_flag(jb, JB_CREATED)) {
00508       /* Remove and free all frames still queued in jb */
00509       while (jbimpl->remove(jbobj, &f) == AST_JB_IMPL_OK) {
00510          ast_frfree(f);
00511       }
00512 
00513       jbimpl->destroy(jbobj);
00514       jb->jbobj = NULL;
00515 
00516       ast_clear_flag(jb, JB_CREATED);
00517 
00518       ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, ast_channel_name(chan));
00519    }
00520 }

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

References AST_CHAN_TP_CREATESJITTER, AST_CHAN_TP_WANTSJITTER, ast_channel_jb(), ast_channel_tech(), AST_JB_ENABLED, AST_JB_FORCED, ast_set_flag, ast_test_flag, ast_jb::conf, jb_choose_impl(), JB_CREATED, JB_TIMEBASE_INITIALIZED, JB_USE, NULL, ast_channel_tech::properties, and ast_jb::timebase.

00164 {
00165    struct ast_jb *jb0 = ast_channel_jb(c0);
00166    struct ast_jb *jb1 = ast_channel_jb(c1);
00167    struct ast_jb_conf *conf0 = &jb0->conf;
00168    struct ast_jb_conf *conf1 = &jb1->conf;
00169    int c0_wants_jitter = ast_channel_tech(c0)->properties & AST_CHAN_TP_WANTSJITTER;
00170    int c0_creates_jitter = ast_channel_tech(c0)->properties & AST_CHAN_TP_CREATESJITTER;
00171    int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED);
00172    int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED);
00173    int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED);
00174    int c0_jb_created = ast_test_flag(jb0, JB_CREATED);
00175    int c1_wants_jitter = ast_channel_tech(c1)->properties & AST_CHAN_TP_WANTSJITTER;
00176    int c1_creates_jitter = ast_channel_tech(c1)->properties & AST_CHAN_TP_CREATESJITTER;
00177    int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED);
00178    int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED);
00179    int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED);
00180    int c1_jb_created = ast_test_flag(jb1, JB_CREATED);
00181    int inuse = 0;
00182 
00183    /* Determine whether audio going to c0 needs a jitter buffer */
00184    if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) {
00185       ast_set_flag(jb0, JB_USE);
00186       if (!c0_jb_timebase_initialized) {
00187          if (c1_jb_timebase_initialized) {
00188             memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval));
00189          } else {
00190             gettimeofday(&jb0->timebase, NULL);
00191          }
00192          ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED);
00193       }
00194 
00195       if (!c0_jb_created) {
00196          jb_choose_impl(c0);
00197       }
00198 
00199       inuse = 1;
00200    }
00201 
00202    /* Determine whether audio going to c1 needs a jitter buffer */
00203    if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) {
00204       ast_set_flag(jb1, JB_USE);
00205       if (!c1_jb_timebase_initialized) {
00206          if (c0_jb_timebase_initialized) {
00207             memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval));
00208          } else {
00209             gettimeofday(&jb1->timebase, NULL);
00210          }
00211          ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED);
00212       }
00213 
00214       if (!c1_jb_created) {
00215          jb_choose_impl(c1);
00216       }
00217 
00218       inuse = 1;
00219    }
00220 
00221    return inuse;
00222 }

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

References ast_channel_jb(), ast_test_flag, ast_jb_impl::empty_and_reset, ast_jb::impl, JB_CREATED, JB_USE, and ast_jb::jbobj.

00594 {
00595    struct ast_jb *jb0 = ast_channel_jb(c0);
00596    struct ast_jb *jb1 = ast_channel_jb(c1);
00597    int c0_use_jb = ast_test_flag(jb0, JB_USE);
00598    int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00599    int c1_use_jb = ast_test_flag(jb1, JB_USE);
00600    int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00601 
00602    if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) {
00603       jb0->impl->empty_and_reset(jb0->jbobj);
00604    }
00605 
00606    if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) {
00607       jb1->impl->empty_and_reset(jb1->jbobj);
00608    }
00609 }

void ast_jb_enable_for_channel ( struct ast_channel chan  ) 

Sets a jitterbuffer frame hook on the channel based on the channel's stored jitterbuffer configuration.

Since:
12.0
Parameters:
chan Which channel is being set up

Definition at line 574 of file abstract_jb.c.

References ast_channel_jb(), ast_jb_create_framehook(), AST_JB_ENABLED, ast_test_flag, and ast_jb::conf.

Referenced by bridge_channel_internal_join().

00575 {
00576    struct ast_jb_conf conf = ast_channel_jb(chan)->conf;
00577    if (ast_test_flag(&conf, AST_JB_ENABLED)) {
00578       ast_jb_create_framehook(chan, &conf, 1);
00579    }
00580 }

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

References ast_channel_jb(), ast_test_flag, JB_CREATED, jb_get_and_deliver(), and JB_USE.

00330 {
00331    struct ast_jb *jb0 = ast_channel_jb(c0);
00332    struct ast_jb *jb1 = ast_channel_jb(c1);
00333    int c0_use_jb = ast_test_flag(jb0, JB_USE);
00334    int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00335    int c1_use_jb = ast_test_flag(jb1, JB_USE);
00336    int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00337 
00338    if (c0_use_jb && c0_jb_is_created)
00339       jb_get_and_deliver(c0);
00340 
00341    if (c1_use_jb && c1_jb_is_created)
00342       jb_get_and_deliver(c1);
00343 }

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

References ast_channel_jb().

00589 {
00590    memcpy(conf, &ast_channel_jb((struct ast_channel *) chan)->conf, sizeof(*conf));
00591 }

struct ast_jb_impl* ast_jb_get_impl ( enum ast_jb_type  type  )  [read]

Definition at line 804 of file abstract_jb.c.

References ARRAY_LEN, and NULL.

Referenced by jb_framedata_init().

00805 {
00806    int i;
00807    for (i = 0; i < ARRAY_LEN(avail_impl); i++) {
00808       if (avail_impl[i].type == type) {
00809          return &avail_impl[i];
00810       }
00811    }
00812    return NULL;
00813 }

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

References ast_channel_jb(), ast_test_flag, get_now(), JB_CREATED, JB_USE, ast_jb::next, and NULL.

00225 {
00226    struct ast_jb *jb0 = ast_channel_jb(c0);
00227    struct ast_jb *jb1 = ast_channel_jb(c1);
00228    int c0_use_jb = ast_test_flag(jb0, JB_USE);
00229    int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
00230    int c1_use_jb = ast_test_flag(jb1, JB_USE);
00231    int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
00232    int wait, wait0, wait1;
00233    struct timeval tv_now;
00234 
00235    if (time_left == 0) {
00236       /* No time left - the bridge will be retried */
00237       /* TODO: Test disable this */
00238       /*return 0;*/
00239    }
00240 
00241    if (time_left < 0) {
00242       time_left = INT_MAX;
00243    }
00244 
00245    gettimeofday(&tv_now, NULL);
00246 
00247    wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left;
00248    wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left;
00249 
00250    wait = wait0 < wait1 ? wait0 : wait1;
00251    wait = wait < time_left ? wait : time_left;
00252 
00253    if (wait == INT_MAX) {
00254       wait = -1;
00255    } else if (wait < 1) {
00256       /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */
00257       wait = 1;
00258    }
00259 
00260    return wait;
00261 }

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

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

00265 {
00266    struct ast_jb *jb = ast_channel_jb(chan);
00267    const struct ast_jb_impl *jbimpl = jb->impl;
00268    void *jbobj = jb->jbobj;
00269    struct ast_frame *frr;
00270    long now = 0;
00271 
00272    if (!ast_test_flag(jb, JB_USE))
00273       return -1;
00274 
00275    if (f->frametype != AST_FRAME_VOICE) {
00276       if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) {
00277          jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now);
00278          jbimpl->force_resync(jbobj);
00279       }
00280 
00281       return -1;
00282    }
00283 
00284    /* We consider an enabled jitterbuffer should receive frames with valid timing info. */
00285    if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) {
00286       ast_log(LOG_WARNING, "%s received frame with invalid timing info: "
00287          "has_timing_info=%u, len=%ld, ts=%ld, src=%s\n",
00288          ast_channel_name(chan), ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO), f->len, f->ts, f->src);
00289       return -1;
00290    }
00291 
00292    frr = ast_frdup(f);
00293 
00294    if (!frr) {
00295       ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", ast_channel_name(chan));
00296       return -1;
00297    }
00298 
00299    if (!ast_test_flag(jb, JB_CREATED)) {
00300       if (create_jb(chan, frr)) {
00301          ast_frfree(frr);
00302          /* Disable the jitterbuffer */
00303          ast_clear_flag(jb, JB_USE);
00304          return -1;
00305       }
00306 
00307       ast_set_flag(jb, JB_CREATED);
00308       return 0;
00309    } else {
00310       now = get_now(jb, NULL);
00311       if (jbimpl->put(jbobj, frr, now) != AST_JB_IMPL_OK) {
00312          jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
00313          ast_frfree(frr);
00314          /*return -1;*/
00315          /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't
00316             be delivered at all */
00317          return 0;
00318       }
00319 
00320       jb->next = jbimpl->next(jbobj);
00321 
00322       jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
00323 
00324       return 0;
00325    }
00326 }

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 536 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, ast_jb_conf::target_extra, and tmp().

Referenced by _build_general_config(), config_parse_variables(), jb_helper(), load_module(), process_dahdi(), reload_config(), and store_config_core().

00537 {
00538    int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1;
00539    const char *name;
00540    int tmp;
00541 
00542    if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) {
00543       return -1;
00544    }
00545 
00546    name = varname + prefixlen;
00547 
00548    if (!strcasecmp(name, AST_JB_CONF_ENABLE)) {
00549       ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED);
00550    } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) {
00551       ast_set2_flag(conf, ast_true(value), AST_JB_FORCED);
00552    } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) {
00553       if ((tmp = atoi(value)) > 0)
00554          conf->max_size = tmp;
00555    } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) {
00556       if ((tmp = atoi(value)) > 0)
00557          conf->resync_threshold = tmp;
00558    } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) {
00559       if (!ast_strlen_zero(value))
00560          snprintf(conf->impl, sizeof(conf->impl), "%s", value);
00561    } else if (!strcasecmp(name, AST_JB_CONF_TARGET_EXTRA)) {
00562       if (sscanf(value, "%30d", &tmp) == 1) {
00563          conf->target_extra = tmp;
00564       }
00565    } else if (!strcasecmp(name, AST_JB_CONF_LOG)) {
00566       ast_set2_flag(conf, ast_true(value), AST_JB_LOG);
00567    } else {
00568       return -1;
00569    }
00570 
00571    return 0;
00572 }

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

Definition at line 406 of file abstract_jb.c.

References ao2_bump, ast_assert, ast_channel_bridge_peer(), ast_channel_cleanup, ast_channel_jb(), ast_channel_name(), AST_CHANNEL_NAME, ast_frfree, AST_JB_IMPL_NAME_SIZE, AST_JB_IMPL_OK, AST_JB_LOG, ast_log, ast_test_flag, ast_verb, ast_jb::conf, ast_jb_impl::create, errno, ast_frame_subclass::format, get_now(), ast_jb::impl, jb_framelog, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb::logfile, ast_jb_impl::name, ast_jb_impl::next, ast_jb::next, NULL, ast_jb_impl::put_first, RAII_VAR, ast_frame::subclass, tmp(), and ast_frame::ts.

Referenced by ast_jb_put().

00407 {
00408    struct ast_jb *jb = ast_channel_jb(chan);
00409    struct ast_jb_conf *jbconf = &jb->conf;
00410    const struct ast_jb_impl *jbimpl = jb->impl;
00411    void *jbobj;
00412    long now;
00413    char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1];
00414    char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp;
00415    int res;
00416 
00417    jbobj = jb->jbobj = jbimpl->create(jbconf);
00418    if (!jbobj) {
00419       ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", ast_channel_name(chan));
00420       return -1;
00421    }
00422 
00423    now = get_now(jb, NULL);
00424    res = jbimpl->put_first(jbobj, frr, now);
00425 
00426    /* The result of putting the first frame should not differ from OK. However, its possible
00427       some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */
00428    if (res != AST_JB_IMPL_OK) {
00429       ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", ast_channel_name(chan));
00430       /*
00431       jbimpl->destroy(jbobj);
00432       return -1;
00433       */
00434    }
00435 
00436    /* Init next */
00437    jb->next = jbimpl->next(jbobj);
00438 
00439    /* Init last format for a first time. */
00440    jb->last_format = ao2_bump(frr->subclass.format);
00441 
00442    /* Create a frame log file */
00443    if (ast_test_flag(jbconf, AST_JB_LOG)) {
00444       RAII_VAR(struct ast_channel *, bridged, ast_channel_bridge_peer(chan), ast_channel_cleanup);
00445       char safe_logfile[30] = "/tmp/logfile-XXXXXX";
00446       int safe_fd;
00447 
00448       snprintf(name2, sizeof(name2), "%s", ast_channel_name(chan));
00449       while ((tmp = strchr(name2, '/'))) {
00450          *tmp = '#';
00451       }
00452 
00453       /* We should always have bridged chan if a jitterbuffer is in use */
00454       ast_assert(bridged != NULL);
00455 
00456       snprintf(name1, sizeof(name1), "%s", ast_channel_name(bridged));
00457       while ((tmp = strchr(name1, '/'))) {
00458          *tmp = '#';
00459       }
00460 
00461       snprintf(logfile_pathname, sizeof(logfile_pathname),
00462          "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2);
00463       unlink(logfile_pathname);
00464       safe_fd = mkstemp(safe_logfile);
00465       if (safe_fd < 0 || link(safe_logfile, logfile_pathname) || unlink(safe_logfile) || !(jb->logfile = fdopen(safe_fd, "w+b"))) {
00466          ast_log(LOG_ERROR, "Failed to create frame log file with pathname '%s': %s\n", logfile_pathname, strerror(errno));
00467          jb->logfile = NULL;
00468          if (safe_fd > -1) {
00469             close(safe_fd);
00470          }
00471       }
00472 
00473       if (res == AST_JB_IMPL_OK) {
00474          jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
00475             now, frr->ts, frr->len);
00476       } else {
00477          jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
00478             now, frr->ts, frr->len);
00479       }
00480    }
00481 
00482    ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, ast_channel_name(chan));
00483 
00484    /* Free the frame if it has not been queued in the jb */
00485    if (res != AST_JB_IMPL_OK) {
00486       ast_frfree(frr);
00487    }
00488 
00489    return 0;
00490 }

static void datastore_destroy_cb ( void *  data  )  [static]

Definition at line 859 of file abstract_jb.c.

References ast_debug, and ast_free.

00859                                              {
00860    ast_free(data);
00861    ast_debug(1, "JITTERBUFFER datastore destroyed\n");
00862 }

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

Definition at line 523 of file abstract_jb.c.

References ast_tvdiff_ms(), NULL, and ast_jb::timebase.

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

00524 {
00525    struct timeval now;
00526 
00527    if (!when) {
00528       when = &now;
00529       gettimeofday(when, NULL);
00530    }
00531 
00532    return ast_tvdiff_ms(*when, jb->timebase);
00533 }

static void hook_destroy_cb ( void *  framedata  )  [static]

Definition at line 869 of file abstract_jb.c.

References ast_debug, and jb_framedata_destroy().

00870 {
00871    ast_debug(1, "JITTERBUFFER hook destroyed\n");
00872    jb_framedata_destroy((struct jb_framedata *) framedata);
00873 }

static struct ast_frame* hook_event_cb ( struct ast_channel chan,
struct ast_frame frame,
enum ast_framehook_event  event,
void *  data 
) [static, read]

Definition at line 875 of file abstract_jb.c.

References ao2_replace, ast_channel_fdno(), AST_CONTROL_HOLD, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_UNHOLD, ast_format_get_sample_rate(), AST_FRAME_CONTROL, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRAMEHOOK_EVENT_ATTACHED, AST_FRAMEHOOK_EVENT_DETACHED, AST_FRAMEHOOK_EVENT_READ, AST_FRAMEHOOK_EVENT_WRITE, ast_frdup(), AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, AST_FRIENDLY_OFFSET, ast_frisolate(), AST_JB_IMPL_DROP, AST_JB_IMPL_INTERP, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_OK, AST_JITTERBUFFER_FD, ast_log, ast_null_frame, ast_samp2tv(), ast_test_flag, ast_timer_ack(), ast_timer_set_rate(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_frame::delivery, jb_framedata::first, ast_jb_impl::force_resync, ast_frame_subclass::format, ast_frame::frametype, ast_jb_impl::get, ast_frame_subclass::integer, jb_framedata::jb_impl, jb_framedata::jb_obj, jb_framedata::last_format, ast_frame::len, LOG_ERROR, ast_jb_impl::next, ast_frame::next, ast_frame::offset, ast_jb_impl::put, ast_jb_impl::put_first, ast_frame::samples, ast_frame::src, jb_framedata::start_tv, ast_frame::subclass, jb_framedata::timer, jb_framedata::timer_interval, and ast_frame::ts.

00876 {
00877    struct jb_framedata *framedata = data;
00878    struct timeval now_tv;
00879    unsigned long now;
00880    int putframe = 0; /* signifies if audio frame was placed into the buffer or not */
00881 
00882    switch (event) {
00883    case AST_FRAMEHOOK_EVENT_READ:
00884       break;
00885    case AST_FRAMEHOOK_EVENT_ATTACHED:
00886    case AST_FRAMEHOOK_EVENT_DETACHED:
00887    case AST_FRAMEHOOK_EVENT_WRITE:
00888       return frame;
00889    }
00890 
00891    if (ast_channel_fdno(chan) == AST_JITTERBUFFER_FD && framedata->timer) {
00892       if (ast_timer_ack(framedata->timer, 1) < 0) {
00893          ast_log(LOG_ERROR, "Failed to acknowledge timer in jitter buffer\n");
00894          return frame;
00895       }
00896    }
00897 
00898    if (!frame) {
00899       return frame;
00900    }
00901 
00902    now_tv = ast_tvnow();
00903    now = ast_tvdiff_ms(now_tv, framedata->start_tv);
00904 
00905    if (frame->frametype == AST_FRAME_VOICE) {
00906       int res;
00907       struct ast_frame *jbframe;
00908 
00909       if (!ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO) || frame->len < 2 || frame->ts < 0) {
00910          /* only frames with timing info can enter the jitterbuffer */
00911          return frame;
00912       }
00913 
00914       jbframe = ast_frisolate(frame);
00915       ao2_replace(framedata->last_format, frame->subclass.format);
00916 
00917       if (frame->len && (frame->len != framedata->timer_interval)) {
00918          framedata->timer_interval = frame->len;
00919          ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
00920       }
00921       if (!framedata->first) {
00922          framedata->first = 1;
00923          res = framedata->jb_impl->put_first(framedata->jb_obj, jbframe, now);
00924       } else {
00925          res = framedata->jb_impl->put(framedata->jb_obj, jbframe, now);
00926       }
00927 
00928       if (res == AST_JB_IMPL_OK) {
00929          if (jbframe != frame) {
00930             ast_frfree(frame);
00931          }
00932          frame = &ast_null_frame;
00933       } else if (jbframe != frame) {
00934          ast_frfree(jbframe);
00935       }
00936       putframe = 1;
00937    }
00938 
00939    if (frame->frametype == AST_FRAME_NULL) {
00940       int res;
00941       long next = framedata->jb_impl->next(framedata->jb_obj);
00942 
00943       /* If now is earlier than the next expected output frame
00944        * from the jitterbuffer we may choose to pass on retrieving
00945        * a frame during this read iteration.  The only exception
00946        * to this rule is when an audio frame is placed into the buffer
00947        * and the time for the next frame to come out of the buffer is
00948        * at least within the timer_interval of the next output frame. By
00949        * doing this we are able to feed off the timing of the input frames
00950        * and only rely on our jitterbuffer timer when frames are dropped.
00951        * During testing, this hybrid form of timing gave more reliable results. */
00952       if (now < next) {
00953          long int diff = next - now;
00954          if (!putframe) {
00955             return frame;
00956          } else if (diff >= framedata->timer_interval) {
00957             return frame;
00958          }
00959       }
00960 
00961       ast_frfree(frame);
00962       frame = &ast_null_frame;
00963       res = framedata->jb_impl->get(framedata->jb_obj, &frame, now, framedata->timer_interval);
00964       switch (res) {
00965       case AST_JB_IMPL_OK:
00966          /* got it, and pass it through */
00967          break;
00968       case AST_JB_IMPL_DROP:
00969          ast_frfree(frame);
00970          frame = &ast_null_frame;
00971          break;
00972       case AST_JB_IMPL_INTERP:
00973          if (framedata->last_format) {
00974             struct ast_frame tmp = { 0, };
00975 
00976             tmp.frametype = AST_FRAME_VOICE;
00977             tmp.subclass.format = framedata->last_format;
00978             /* example: 8000hz / (1000 / 20ms) = 160 samples */
00979             tmp.samples = ast_format_get_sample_rate(framedata->last_format) / (1000 / framedata->timer_interval);
00980             tmp.delivery = ast_tvadd(framedata->start_tv, ast_samp2tv(next, 1000));
00981             tmp.offset = AST_FRIENDLY_OFFSET;
00982             tmp.src  = "func_jitterbuffer interpolation";
00983             ast_frfree(frame);
00984             frame = ast_frdup(&tmp);
00985             break;
00986          }
00987          /* else fall through */
00988       case AST_JB_IMPL_NOFRAME:
00989          ast_frfree(frame);
00990          frame = &ast_null_frame;
00991          break;
00992       }
00993    }
00994 
00995    if (frame->frametype == AST_FRAME_CONTROL) {
00996       switch(frame->subclass.integer) {
00997       case AST_CONTROL_HOLD:
00998       case AST_CONTROL_UNHOLD:
00999       case AST_CONTROL_T38_PARAMETERS:
01000       case AST_CONTROL_SRCUPDATE:
01001       case AST_CONTROL_SRCCHANGE:
01002          framedata->jb_impl->force_resync(framedata->jb_obj);
01003          break;
01004       default:
01005          break;
01006       }
01007    }
01008 
01009    return frame;
01010 }

static void jb_choose_impl ( struct ast_channel chan  )  [static]

Definition at line 141 of file abstract_jb.c.

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

Referenced by ast_jb_do_usecheck().

00142 {
00143    struct ast_jb *jb = ast_channel_jb(chan);
00144    struct ast_jb_conf *jbconf = &jb->conf;
00145    const struct ast_jb_impl *test_impl;
00146    int i, avail_impl_count = ARRAY_LEN(avail_impl);
00147 
00148    jb->impl = &avail_impl[default_impl];
00149 
00150    if (ast_strlen_zero(jbconf->impl)) {
00151       return;
00152    }
00153 
00154    for (i = 0; i < avail_impl_count; i++) {
00155       test_impl = &avail_impl[i];
00156       if (!strcasecmp(jbconf->impl, test_impl->name)) {
00157          jb->impl = test_impl;
00158          return;
00159       }
00160    }
00161 }

static void * jb_create_adaptive ( struct ast_jb_conf general_config  )  [static]

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

00712 {
00713    jb_conf jbconf;
00714    jitterbuf *adaptivejb;
00715 
00716    adaptivejb = jb_new();
00717    if (adaptivejb) {
00718       jbconf.max_jitterbuf = general_config->max_size;
00719       jbconf.resync_threshold = general_config->resync_threshold;
00720       jbconf.max_contig_interp = 10;
00721       jbconf.target_extra = general_config->target_extra;
00722       jb_setconf(adaptivejb, &jbconf);
00723    }
00724 
00725    return adaptivejb;
00726 }

static void * jb_create_fixed ( struct ast_jb_conf general_config  )  [static]

Definition at line 614 of file abstract_jb.c.

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

00615 {
00616    struct fixed_jb_conf conf;
00617 
00618    conf.jbsize = general_config->max_size;
00619    conf.resync_threshold = general_config->resync_threshold;
00620 
00621    return fixed_jb_new(&conf);
00622 }

static void jb_destroy_adaptive ( void *  jb  )  [static]

Definition at line 729 of file abstract_jb.c.

References jb_destroy().

00730 {
00731    jitterbuf *adaptivejb = (jitterbuf *) jb;
00732 
00733    jb_destroy(adaptivejb);
00734 }

static void jb_destroy_fixed ( void *  jb  )  [static]

Definition at line 624 of file abstract_jb.c.

References fixed_jb_destroy(), and jb_empty_and_reset_fixed().

00625 {
00626    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00627 
00628    /* Ensure the fixed jb is empty - otherwise it will raise an ASSERT */
00629    jb_empty_and_reset_fixed(jb);
00630 
00631    /* destroy the jb */
00632    fixed_jb_destroy(fixedjb);
00633 }

static void jb_empty_and_reset_adaptive ( void *  jb  )  [static]

Definition at line 792 of file abstract_jb.c.

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

00793 {
00794    jitterbuf *adaptivejb = jb;
00795    jb_frame f;
00796 
00797    while (jb_getall(adaptivejb, &f) == JB_OK) {
00798       ast_frfree(f.data);
00799    }
00800 
00801    jb_reset(adaptivejb);
00802 }

static void jb_empty_and_reset_fixed ( void *  jb  )  [static]

Definition at line 699 of file abstract_jb.c.

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

Referenced by jb_destroy_fixed().

00700 {
00701    struct fixed_jb *fixedjb = jb;
00702    struct fixed_jb_frame f;
00703 
00704    while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) {
00705       ast_frfree(f.data);
00706    }
00707 }

static void jb_force_resynch_adaptive ( void *  jb  )  [static]

Definition at line 788 of file abstract_jb.c.

00789 {
00790 }

static void jb_force_resynch_fixed ( void *  jb  )  [static]

Definition at line 692 of file abstract_jb.c.

References fixed_jb_set_force_resynch().

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

static void jb_framedata_destroy ( struct jb_framedata framedata  )  [static]

Definition at line 833 of file abstract_jb.c.

References ao2_cleanup, ast_free, ast_frfree, AST_JB_IMPL_OK, ast_timer_close(), ast_jb_impl::destroy, f, jb_framedata::jb_impl, jb_framedata::jb_obj, jb_framedata::last_format, NULL, ast_jb_impl::remove, and jb_framedata::timer.

Referenced by ast_jb_create_framehook(), and hook_destroy_cb().

00834 {
00835    if (framedata->timer) {
00836       ast_timer_close(framedata->timer);
00837       framedata->timer = NULL;
00838    }
00839    if (framedata->jb_impl && framedata->jb_obj) {
00840       struct ast_frame *f;
00841       while (framedata->jb_impl->remove(framedata->jb_obj, &f) == AST_JB_IMPL_OK) {
00842          ast_frfree(f);
00843       }
00844       framedata->jb_impl->destroy(framedata->jb_obj);
00845       framedata->jb_obj = NULL;
00846    }
00847    ao2_cleanup(framedata->last_format);
00848    ast_free(framedata);
00849 }

static int jb_framedata_init ( struct jb_framedata framedata,
struct ast_jb_conf jb_conf 
) [static]

Definition at line 1013 of file abstract_jb.c.

References AST_JB_ADAPTIVE, AST_JB_FIXED, ast_jb_get_impl(), ast_log, ast_strlen_zero, ast_timer_fd(), ast_timer_open(), ast_timer_set_rate(), ast_tvnow(), ast_jb_impl::create, DEFAULT_TIMER_INTERVAL, DEFAULT_TYPE, ast_jb_conf::impl, jb_framedata::jb_conf, jb_framedata::jb_impl, jb_framedata::jb_obj, LOG_WARNING, jb_framedata::start_tv, jb_framedata::timer, jb_framedata::timer_fd, and jb_framedata::timer_interval.

Referenced by ast_jb_create_framehook().

01014 {
01015    int jb_impl_type = DEFAULT_TYPE;
01016    /* Initialize defaults */
01017    framedata->timer_fd = -1;
01018    memcpy(&framedata->jb_conf, jb_conf, sizeof(*jb_conf));
01019 
01020    /* Figure out implementation type from the configuration implementation string */
01021    if (!ast_strlen_zero(jb_conf->impl)) {
01022       if (!strcasecmp(jb_conf->impl, "fixed")) {
01023          jb_impl_type = AST_JB_FIXED;
01024       } else if (!strcasecmp(jb_conf->impl, "adaptive")) {
01025          jb_impl_type = AST_JB_ADAPTIVE;
01026       } else {
01027          ast_log(LOG_WARNING, "Unknown Jitterbuffer type %s. Failed to create jitterbuffer.\n", jb_conf->impl);
01028          return -1;
01029       }
01030    }
01031 
01032    if (!(framedata->jb_impl = ast_jb_get_impl(jb_impl_type))) {
01033       return -1;
01034    }
01035 
01036    if (!(framedata->timer = ast_timer_open())) {
01037       return -1;
01038    }
01039 
01040    framedata->timer_fd = ast_timer_fd(framedata->timer);
01041    framedata->timer_interval = DEFAULT_TIMER_INTERVAL;
01042    ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
01043    framedata->start_tv = ast_tvnow();
01044 
01045    framedata->jb_obj = framedata->jb_impl->create(&framedata->jb_conf);
01046    return 0;
01047 }

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

Definition at line 754 of file abstract_jb.c.

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

00755 {
00756    jitterbuf *adaptivejb = (jitterbuf *) jb;
00757    jb_frame frame = { .data = &ast_null_frame };
00758    int res;
00759 
00760    res = jb_get(adaptivejb, &frame, now, interpl);
00761    *fout = frame.data;
00762 
00763    return adaptive_to_abstract_code[res];
00764 }

static void jb_get_and_deliver ( struct ast_channel chan  )  [static]

Definition at line 346 of file abstract_jb.c.

References ao2_replace, ast_assert, ast_channel_jb(), ast_format_get_default_ms(), AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, AST_JB_IMPL_DROP, AST_JB_IMPL_INTERP, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_OK, ast_log, ast_samp2tv(), ast_tvadd(), ast_write(), ast_frame::delivery, f, ast_frame_subclass::format, ast_jb_impl::get, get_now(), ast_jb::impl, jb_framelog, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb_impl::name, ast_frame::next, ast_jb_impl::next, ast_jb::next, NULL, ast_frame::offset, ast_frame::samples, ast_frame::src, ast_frame::subclass, ast_jb::timebase, and ast_frame::ts.

Referenced by ast_jb_get_and_deliver().

00347 {
00348    struct ast_jb *jb = ast_channel_jb(chan);
00349    const struct ast_jb_impl *jbimpl = jb->impl;
00350    void *jbobj = jb->jbobj;
00351    struct ast_frame *f, finterp = { .frametype = AST_FRAME_VOICE, };
00352    long now;
00353    int interpolation_len, res;
00354 
00355    now = get_now(jb, NULL);
00356    jb->next = jbimpl->next(jbobj);
00357    if (now < jb->next) {
00358       jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next);
00359       return;
00360    }
00361 
00362    while (now >= jb->next) {
00363       interpolation_len = ast_format_get_default_ms(jb->last_format);
00364 
00365       res = jbimpl->get(jbobj, &f, now, interpolation_len);
00366 
00367       switch (res) {
00368       case AST_JB_IMPL_OK:
00369          /* deliver the frame */
00370          ast_write(chan, f);
00371       case AST_JB_IMPL_DROP:
00372          jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
00373             now, jb_get_actions[res], f->ts, f->len);
00374          ao2_replace(jb->last_format, f->subclass.format);
00375          ast_frfree(f);
00376          break;
00377       case AST_JB_IMPL_INTERP:
00378          /* interpolate a frame */
00379          f = &finterp;
00380          f->subclass.format = jb->last_format;
00381          f->samples  = interpolation_len * 8;
00382          f->src  = "JB interpolation";
00383          f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000));
00384          f->offset = AST_FRIENDLY_OFFSET;
00385          /* deliver the interpolated frame */
00386          ast_write(chan, f);
00387          jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
00388          break;
00389       case AST_JB_IMPL_NOFRAME:
00390          ast_log(LOG_WARNING,
00391             "AST_JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
00392             jbimpl->name, now, jb->next, jbimpl->next(jbobj));
00393          jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now);
00394          return;
00395       default:
00396          ast_log(LOG_ERROR, "This should never happen!\n");
00397          ast_assert("JB type unknown" == NULL);
00398          break;
00399       }
00400 
00401       jb->next = jbimpl->next(jbobj);
00402    }
00403 }

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

Definition at line 658 of file abstract_jb.c.

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

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

static long jb_next_adaptive ( void *  jb  )  [static]

Definition at line 767 of file abstract_jb.c.

References jb_next().

00768 {
00769    jitterbuf *adaptivejb = (jitterbuf *) jb;
00770 
00771    return jb_next(adaptivejb);
00772 }

static long jb_next_fixed ( void *  jb  )  [static]

Definition at line 671 of file abstract_jb.c.

References fixed_jb_next().

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

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

Definition at line 743 of file abstract_jb.c.

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

Referenced by jb_put_first_adaptive().

00744 {
00745    jitterbuf *adaptivejb = (jitterbuf *) jb;
00746    int res;
00747 
00748    res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
00749 
00750    return adaptive_to_abstract_code[res];
00751 }

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

Definition at line 737 of file abstract_jb.c.

References jb_put_adaptive().

00738 {
00739    return jb_put_adaptive(jb, fin, now);
00740 }

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

Definition at line 636 of file abstract_jb.c.

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

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

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

Definition at line 647 of file abstract_jb.c.

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

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

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

Definition at line 775 of file abstract_jb.c.

References jb_frame::data, and jb_getall().

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

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

Definition at line 679 of file abstract_jb.c.

References fixed_jb_frame::data, and fixed_jb_remove().

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


Variable Documentation

const int adaptive_to_abstract_code[] [static]

Initial value:

Definition at line 116 of file abstract_jb.c.

struct ast_jb_impl avail_impl[] [static]

Definition at line 82 of file abstract_jb.c.

int default_impl = 0 [static]

Definition at line 111 of file abstract_jb.c.

const int fixed_to_abstract_code[] [static]

Initial value:

 {
   .type = "jitterbuffer",
   .destroy = datastore_destroy_cb
}

Definition at line 864 of file abstract_jb.c.

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

Definition at line 120 of file abstract_jb.c.


Generated on Thu Apr 16 06:28:07 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6