Thu Sep 7 01:03:06 2017

Asterisk developer's documentation


abstract_jb.c File Reference

Common implementation-independent jitterbuffer stuff. More...

#include "asterisk.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/abstract_jb.h"
#include "fixedjitterbuf.h"
#include "jitterbuf.h"

Go to the source code of this file.

Data Structures

struct  ast_jb_impl
 Jitterbuffer implementation private struct. More...

Defines

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

Typedefs

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

Enumerations

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

Functions

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

Variables

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

Detailed Description

Common implementation-independent jitterbuffer stuff.

Author:
Slav Klenov <slav@securax.org>

Definition in file abstract_jb.c.


Define Documentation

#define jb_framelog ( ...   ) 

Macros for the frame log files.

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

typedef void(* jb_destroy_impl)(void *jb)

Destroy.

Definition at line 61 of file abstract_jb.c.

typedef void(* jb_empty_and_reset_impl)(void *jb)

Empty and reset jb.

Definition at line 75 of file abstract_jb.c.

typedef void(* jb_force_resynch_impl)(void *jb)

Force resynch.

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

typedef long(* jb_next_impl)(void *jb)

Get next.

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

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

Put frame.

Definition at line 65 of file abstract_jb.c.

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

Remove first frame.

Definition at line 71 of file abstract_jb.c.


Enumeration Type Documentation

anonymous enum

Internal jb flags

Enumerator:
JB_USE 
JB_TIMEBASE_INITIALIZED 
JB_CREATED 

Definition at line 50 of file abstract_jb.c.

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

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

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

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

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

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

References ast_clear_flag, ast_frfree, ast_test_flag, ast_verb, ast_jb_impl::destroy, f, ast_jb::impl, ast_channel::jb, JB_CREATED, JB_IMPL_OK, ast_jb::jbobj, ast_jb::logfile, ast_jb_impl::name, and ast_jb_impl::remove.

Referenced by ast_channel_destructor().

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

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

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

Referenced by ast_generic_bridge().

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

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

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

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

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

Referenced by ast_generic_bridge().

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

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

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

00623 {
00624    memcpy(conf, &chan->jb.conf, sizeof(*conf));
00625 }

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

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

Referenced by ast_generic_bridge().

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

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 306 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(), ast_jb_impl::force_resync, ast_frame::frametype, get_now(), ast_jb::impl, ast_channel::jb, JB_CREATED, jb_framelog, JB_IMPL_OK, JB_USE, ast_jb::jbobj, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb_impl::next, ast_jb::next, ast_jb_impl::put, ast_frame::src, and ast_frame::ts.

Referenced by ast_generic_bridge().

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

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

References AST_JB_CONF_ENABLE, AST_JB_CONF_FORCE, AST_JB_CONF_IMPL, AST_JB_CONF_LOG, AST_JB_CONF_MAX_SIZE, AST_JB_CONF_PREFIX, AST_JB_CONF_RESYNCH_THRESHOLD, AST_JB_CONF_TARGET_EXTRA, AST_JB_ENABLED, AST_JB_FORCED, AST_JB_LOG, ast_set2_flag, ast_strlen_zero(), ast_true(), ast_jb_conf::impl, ast_jb_conf::max_size, name, ast_jb_conf::resync_threshold, and ast_jb_conf::target_extra.

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

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

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

Definition at line 449 of file abstract_jb.c.

References ast_assert, ast_bridged_channel(), AST_CHANNEL_NAME, ast_frfree, AST_JB_IMPL_NAME_SIZE, AST_JB_LOG, ast_log(), ast_test_flag, ast_verb, ast_frame_subclass::codec, ast_jb::conf, ast_jb_impl::create, errno, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, JB_IMPL_OK, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb::logfile, ast_jb_impl::name, ast_jb_impl::next, ast_jb::next, ast_jb_impl::put_first, ast_jb_conf::resync_threshold, ast_frame::subclass, and ast_frame::ts.

Referenced by ast_jb_put().

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

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

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

00565 {
00566    struct timeval now;
00567 
00568    if (!when) {
00569       when = &now;
00570       gettimeofday(when, NULL);
00571    }
00572 
00573    return ast_tvdiff_ms(*when, jb->timebase);
00574 }

static void jb_choose_impl ( struct ast_channel chan  )  [static]

Definition at line 183 of file abstract_jb.c.

References ARRAY_LEN, ast_strlen_zero(), 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    const struct ast_jb_impl *test_impl;
00188    int i, avail_impl_count = ARRAY_LEN(avail_impl);
00189 
00190    jb->impl = &avail_impl[default_impl];
00191 
00192    if (ast_strlen_zero(jbconf->impl)) {
00193       return;
00194    }
00195 
00196    for (i = 0; i < avail_impl_count; i++) {
00197       test_impl = &avail_impl[i];
00198       if (!strcasecmp(jbconf->impl, test_impl->name)) {
00199          jb->impl = test_impl;
00200          return;
00201       }
00202    }
00203 }

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

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

00743 {
00744    jb_conf jbconf;
00745    jitterbuf *adaptivejb;
00746 
00747    adaptivejb = jb_new();
00748    if (adaptivejb) {
00749       jbconf.max_jitterbuf = general_config->max_size;
00750       jbconf.resync_threshold = general_config->resync_threshold;
00751       jbconf.max_contig_interp = 10;
00752       jbconf.target_extra = general_config->target_extra;
00753       jb_setconf(adaptivejb, &jbconf);
00754    }
00755 
00756    return adaptivejb;
00757 }

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

Definition at line 648 of file abstract_jb.c.

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

00649 {
00650    struct fixed_jb_conf conf;
00651 
00652    conf.jbsize = general_config->max_size;
00653    conf.resync_threshold = resynch_threshold;
00654 
00655    return fixed_jb_new(&conf);
00656 }

static void jb_destroy_adaptive ( void *  jb  )  [static]

Definition at line 760 of file abstract_jb.c.

References jb_destroy().

00761 {
00762    jitterbuf *adaptivejb = (jitterbuf *) jb;
00763 
00764    jb_destroy(adaptivejb);
00765 }

static void jb_destroy_fixed ( void *  jb  )  [static]

Definition at line 658 of file abstract_jb.c.

References fixed_jb_destroy().

00659 {
00660    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00661 
00662    /* destroy the jb */
00663    fixed_jb_destroy(fixedjb);
00664 }

static void jb_empty_and_reset_adaptive ( void *  jb  )  [static]

Definition at line 828 of file abstract_jb.c.

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

00829 {
00830    jitterbuf *adaptivejb = jb;
00831    jb_frame f;
00832 
00833    while (jb_getall(adaptivejb, &f) == JB_OK) {
00834       ast_frfree(f.data);
00835    }
00836 
00837    jb_reset(adaptivejb);
00838 }

static void jb_empty_and_reset_fixed ( void *  jb  )  [static]

Definition at line 730 of file abstract_jb.c.

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

00731 {
00732    struct fixed_jb *fixedjb = jb;
00733    struct fixed_jb_frame f;
00734 
00735    while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) {
00736       ast_frfree(f.data);
00737    }
00738 }

static void jb_force_resynch_adaptive ( void *  jb  )  [static]

Definition at line 824 of file abstract_jb.c.

00825 {
00826 }

static void jb_force_resynch_fixed ( void *  jb  )  [static]

Definition at line 723 of file abstract_jb.c.

References fixed_jb_set_force_resynch().

00724 {
00725    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00726 
00727    fixed_jb_set_force_resynch(fixedjb);
00728 }

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

Definition at line 790 of file abstract_jb.c.

References jb_frame::data, and jb_get().

00791 {
00792    jitterbuf *adaptivejb = (jitterbuf *) jb;
00793    jb_frame frame;
00794    int res;
00795 
00796    res = jb_get(adaptivejb, &frame, now, interpl);
00797    *fout = frame.data;
00798 
00799    return adaptive_to_abstract_code[res];
00800 }

static void jb_get_and_deliver ( struct ast_channel chan  )  [static]

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

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

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

Definition at line 689 of file abstract_jb.c.

References fixed_jb_frame::data, and fixed_jb_get().

00690 {
00691    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00692    struct fixed_jb_frame frame;
00693    int res;
00694 
00695    res = fixed_jb_get(fixedjb, &frame, now, interpl);
00696    *fout = frame.data;
00697 
00698    return fixed_to_abstract_code[res];
00699 }

static long jb_next_adaptive ( void *  jb  )  [static]

Definition at line 803 of file abstract_jb.c.

References jb_next().

00804 {
00805    jitterbuf *adaptivejb = (jitterbuf *) jb;
00806 
00807    return jb_next(adaptivejb);
00808 }

static long jb_next_fixed ( void *  jb  )  [static]

Definition at line 702 of file abstract_jb.c.

References fixed_jb_next().

00703 {
00704    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00705 
00706    return fixed_jb_next(fixedjb);
00707 }

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

Definition at line 779 of file abstract_jb.c.

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

Referenced by jb_put_first_adaptive().

00780 {
00781    jitterbuf *adaptivejb = (jitterbuf *) jb;
00782    int res;
00783 
00784    res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
00785 
00786    return adaptive_to_abstract_code[res];
00787 }

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

Definition at line 768 of file abstract_jb.c.

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

00769 {
00770    jitterbuf *adaptivejb = (jitterbuf *) jb;
00771 
00772    /* Initialize the offset to that of the first frame's timestamp */
00773    adaptivejb->info.resync_offset = fin->ts;
00774 
00775    return jb_put_adaptive(jb, fin, now);
00776 }

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

Definition at line 667 of file abstract_jb.c.

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

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

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

Definition at line 678 of file abstract_jb.c.

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

00679 {
00680    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00681    int res;
00682 
00683    res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now);
00684 
00685    return fixed_to_abstract_code[res];
00686 }

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

Definition at line 811 of file abstract_jb.c.

References jb_frame::data, and jb_getall().

00812 {
00813    jitterbuf *adaptivejb = (jitterbuf *) jb;
00814    jb_frame frame;
00815    int res;
00816 
00817    res = jb_getall(adaptivejb, &frame);
00818    *fout = frame.data;
00819 
00820    return adaptive_to_abstract_code[res];
00821 }

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

Definition at line 710 of file abstract_jb.c.

References fixed_jb_frame::data, and fixed_jb_remove().

00711 {
00712    struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
00713    struct fixed_jb_frame frame;
00714    int res;
00715 
00716    res = fixed_jb_remove(fixedjb, &frame);
00717    *fout = frame.data;
00718 
00719    return fixed_to_abstract_code[res];
00720 }


Variable Documentation

const int adaptive_to_abstract_code[] [static]
Initial value:

Definition at line 158 of file abstract_jb.c.

struct ast_jb_impl avail_impl[] [static]

Definition at line 117 of file abstract_jb.c.

int default_impl = 0 [static]

Definition at line 144 of file abstract_jb.c.

const int fixed_to_abstract_code[] [static]
Initial value:

Definition at line 156 of file abstract_jb.c.

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

Definition at line 162 of file abstract_jb.c.


Generated on 7 Sep 2017 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1