Common implementation-independent jitterbuffer stuff. More...
#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/term.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/abstract_jb.h"
#include "fixedjitterbuf.h"
#include "jitterbuf.h"
Go to the source code of this file.
Data Structures | |
struct | ast_jb_impl |
Jitterbuffer implementation private struct. More... | |
Defines | |
#define | jb_framelog(...) |
Macros for the frame log files. | |
Typedefs | |
typedef void *(* | jb_create_impl )(struct ast_jb_conf *general_config, long resynch_threshold) |
Create. | |
typedef void(* | jb_destroy_impl )(void *jb) |
Destroy. | |
typedef void(* | jb_empty_and_reset_impl )(void *jb) |
Empty and reset jb. | |
typedef void(* | jb_force_resynch_impl )(void *jb) |
Force resynch. | |
typedef int(* | jb_get_impl )(void *jb, struct ast_frame **fout, long now, long interpl) |
Get frame for now. | |
typedef long(* | jb_next_impl )(void *jb) |
Get next. | |
typedef int(* | jb_put_first_impl )(void *jb, struct ast_frame *fin, long now) |
Put first frame. | |
typedef int(* | jb_put_impl )(void *jb, struct ast_frame *fin, long now) |
Put frame. | |
typedef int(* | jb_remove_impl )(void *jb, struct ast_frame **fout) |
Remove first frame. | |
Enumerations | |
enum | { JB_USE = (1 << 0), JB_TIMEBASE_INITIALIZED = (1 << 1), JB_CREATED = (1 << 2) } |
enum | { JB_IMPL_OK, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME } |
Functions | |
void | ast_jb_configure (struct ast_channel *chan, const struct ast_jb_conf *conf) |
Configures a jitterbuffer on a channel. | |
void | ast_jb_destroy (struct ast_channel *chan) |
Destroys jitterbuffer on a channel. | |
int | ast_jb_do_usecheck (struct ast_channel *c0, struct ast_channel *c1) |
Checks the need of a jb use in a generic bridge. | |
void | ast_jb_empty_and_reset (struct ast_channel *c0, struct ast_channel *c1) |
drops all frames from a jitterbuffer and resets it | |
void | ast_jb_get_and_deliver (struct ast_channel *c0, struct ast_channel *c1) |
Deliver the queued frames that should be delivered now for both channels. | |
void | ast_jb_get_config (const struct ast_channel *chan, struct ast_jb_conf *conf) |
Copies a channel's jitterbuffer configuration. | |
int | ast_jb_get_when_to_wakeup (struct ast_channel *c0, struct ast_channel *c1, int time_left) |
Calculates the time, left to the closest delivery moment in a bridge. | |
int | ast_jb_put (struct ast_channel *chan, struct ast_frame *f) |
Puts a frame into a channel jitterbuffer. | |
int | ast_jb_read_conf (struct ast_jb_conf *conf, char *varname, char *value) |
Sets jitterbuffer configuration property. | |
static int | create_jb (struct ast_channel *chan, struct ast_frame *first_frame) |
static long | get_now (struct ast_jb *jb, struct timeval *tv) |
static void | jb_choose_impl (struct ast_channel *chan) |
static void * | jb_create_adaptive (struct ast_jb_conf *general_config, long resynch_threshold) |
static void * | jb_create_fixed (struct ast_jb_conf *general_config, long resynch_threshold) |
static void | jb_destroy_adaptive (void *jb) |
static void | jb_destroy_fixed (void *jb) |
static void | jb_empty_and_reset_adaptive (void *jb) |
static void | jb_empty_and_reset_fixed (void *jb) |
static void | jb_force_resynch_adaptive (void *jb) |
static void | jb_force_resynch_fixed (void *jb) |
static int | jb_get_adaptive (void *jb, struct ast_frame **fout, long now, long interpl) |
static void | jb_get_and_deliver (struct ast_channel *chan) |
static int | jb_get_fixed (void *jb, struct ast_frame **fout, long now, long interpl) |
static long | jb_next_adaptive (void *jb) |
static long | jb_next_fixed (void *jb) |
static int | jb_put_adaptive (void *jb, struct ast_frame *fin, long now) |
static int | jb_put_first_adaptive (void *jb, struct ast_frame *fin, long now) |
static int | jb_put_first_fixed (void *jb, struct ast_frame *fin, long now) |
static int | jb_put_fixed (void *jb, struct ast_frame *fin, long now) |
static int | jb_remove_adaptive (void *jb, struct ast_frame **fout) |
static int | jb_remove_fixed (void *jb, struct ast_frame **fout) |
Variables | |
static int | adaptive_to_abstract_code [] |
static struct ast_jb_impl | avail_impl [] |
static int | default_impl = 0 |
static int | fixed_to_abstract_code [] |
static char * | jb_get_actions [] = {"Delivered", "Dropped", "Interpolated", "No"} |
Common implementation-independent jitterbuffer stuff.
Definition in file abstract_jb.c.
#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 void*(* jb_create_impl)(struct ast_jb_conf *general_config, long resynch_threshold) |
Create.
Definition at line 58 of file abstract_jb.c.
typedef void(* jb_destroy_impl)(void *jb) |
Destroy.
Definition at line 60 of file abstract_jb.c.
typedef void(* jb_empty_and_reset_impl)(void *jb) |
Empty and reset jb.
Definition at line 74 of file abstract_jb.c.
typedef void(* jb_force_resynch_impl)(void *jb) |
Force resynch.
Definition at line 72 of file abstract_jb.c.
typedef int(* jb_get_impl)(void *jb, struct ast_frame **fout, long now, long interpl) |
Get frame for now.
Definition at line 66 of file abstract_jb.c.
typedef long(* jb_next_impl)(void *jb) |
Get next.
Definition at line 68 of file abstract_jb.c.
typedef int(* jb_put_first_impl)(void *jb, struct ast_frame *fin, long now) |
Put first frame.
Definition at line 62 of file abstract_jb.c.
typedef int(* jb_put_impl)(void *jb, struct ast_frame *fin, long now) |
Put frame.
Definition at line 64 of file abstract_jb.c.
typedef int(* jb_remove_impl)(void *jb, struct ast_frame **fout) |
Remove first frame.
Definition at line 70 of file abstract_jb.c.
anonymous enum |
Internal jb flags
Definition at line 49 of file abstract_jb.c.
00049 { 00050 JB_USE = (1 << 0), 00051 JB_TIMEBASE_INITIALIZED = (1 << 1), 00052 JB_CREATED = (1 << 2) 00053 };
anonymous enum |
Abstract return codes
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 };
void ast_jb_configure | ( | struct ast_channel * | chan, | |
const struct ast_jb_conf * | conf | |||
) |
Configures a jitterbuffer on a channel.
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 602 of file abstract_jb.c.
References ast_jb::conf, and ast_channel::jb.
Referenced by __oh323_rtp_create(), __oh323_update_info(), alsa_new(), dahdi_new(), gtalk_new(), mgcp_new(), misdn_new(), oss_new(), sip_new(), and skinny_new().
void ast_jb_destroy | ( | struct ast_channel * | chan | ) |
Destroys jitterbuffer on a channel.
chan | channel. |
Called from ast_channel_free() when a channel is destroyed.
Definition at line 526 of file abstract_jb.c.
References ast_clear_flag, ast_frfree, ast_test_flag, ast_verbose(), ast_jb_impl::destroy, f, ast_jb::impl, ast_channel::jb, JB_CREATED, JB_IMPL_OK, ast_jb::jbobj, ast_jb::logfile, ast_jb_impl::name, option_verbose, ast_jb_impl::remove, and VERBOSE_PREFIX_3.
Referenced by ast_channel_free().
00527 { 00528 struct ast_jb *jb = &chan->jb; 00529 struct ast_jb_impl *jbimpl = jb->impl; 00530 void *jbobj = jb->jbobj; 00531 struct ast_frame *f; 00532 00533 if (jb->logfile) { 00534 fclose(jb->logfile); 00535 jb->logfile = NULL; 00536 } 00537 00538 if (ast_test_flag(jb, JB_CREATED)) { 00539 /* Remove and free all frames still queued in jb */ 00540 while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) { 00541 ast_frfree(f); 00542 } 00543 00544 jbimpl->destroy(jbobj); 00545 jb->jbobj = NULL; 00546 00547 ast_clear_flag(jb, JB_CREATED); 00548 00549 if (option_verbose > 2) 00550 ast_verbose(VERBOSE_PREFIX_3 "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name); 00551 } 00552 }
int ast_jb_do_usecheck | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) |
Checks the need of a jb use in a generic bridge.
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.
Definition at line 204 of file abstract_jb.c.
References AST_CHAN_TP_CREATESJITTER, AST_CHAN_TP_WANTSJITTER, AST_JB_ENABLED, AST_JB_FORCED, ast_set_flag, ast_test_flag, ast_jb::conf, inuse, ast_channel::jb, jb_choose_impl(), JB_CREATED, JB_TIMEBASE_INITIALIZED, JB_USE, ast_channel_tech::properties, ast_channel::tech, and ast_jb::timebase.
Referenced by ast_generic_bridge().
00205 { 00206 struct ast_jb *jb0 = &c0->jb; 00207 struct ast_jb *jb1 = &c1->jb; 00208 struct ast_jb_conf *conf0 = &jb0->conf; 00209 struct ast_jb_conf *conf1 = &jb1->conf; 00210 int c0_wants_jitter = c0->tech->properties & AST_CHAN_TP_WANTSJITTER; 00211 int c0_creates_jitter = c0->tech->properties & AST_CHAN_TP_CREATESJITTER; 00212 int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED); 00213 int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED); 00214 int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED); 00215 int c0_jb_created = ast_test_flag(jb0, JB_CREATED); 00216 int c1_wants_jitter = c1->tech->properties & AST_CHAN_TP_WANTSJITTER; 00217 int c1_creates_jitter = c1->tech->properties & AST_CHAN_TP_CREATESJITTER; 00218 int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED); 00219 int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED); 00220 int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED); 00221 int c1_jb_created = ast_test_flag(jb1, JB_CREATED); 00222 int inuse = 0; 00223 00224 /* Determine whether audio going to c0 needs a jitter buffer */ 00225 if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) { 00226 ast_set_flag(jb0, JB_USE); 00227 if (!c0_jb_timebase_initialized) { 00228 if (c1_jb_timebase_initialized) { 00229 memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval)); 00230 } else { 00231 gettimeofday(&jb0->timebase, NULL); 00232 } 00233 ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED); 00234 } 00235 00236 if (!c0_jb_created) { 00237 jb_choose_impl(c0); 00238 } 00239 00240 inuse = 1; 00241 } 00242 00243 /* Determine whether audio going to c1 needs a jitter buffer */ 00244 if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) { 00245 ast_set_flag(jb1, JB_USE); 00246 if (!c1_jb_timebase_initialized) { 00247 if (c0_jb_timebase_initialized) { 00248 memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval)); 00249 } else { 00250 gettimeofday(&jb1->timebase, NULL); 00251 } 00252 ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED); 00253 } 00254 00255 if (!c1_jb_created) { 00256 jb_choose_impl(c1); 00257 } 00258 00259 inuse = 1; 00260 } 00261 00262 return inuse; 00263 }
void ast_jb_empty_and_reset | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) |
drops all frames from a jitterbuffer and resets it
c0 | one channel of a bridge | |
c1 | the other channel of the bridge |
Definition at line 613 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().
00614 { 00615 struct ast_jb *jb0 = &c0->jb; 00616 struct ast_jb *jb1 = &c1->jb; 00617 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00618 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00619 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00620 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00621 00622 if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) { 00623 jb0->impl->empty_and_reset(jb0->jbobj); 00624 } 00625 00626 if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) { 00627 jb1->impl->empty_and_reset(jb1->jbobj); 00628 } 00629 }
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.
c0 | first bridged channel. | |
c1 | second bridged channel. |
Called from ast_generic_bridge() to deliver any frames, that should be delivered for the moment of invocation. Does nothing if neihter of the channels is using jb or has any frames currently queued in. The function delivers frames usig ast_write() each of the channels.
Definition at line 370 of file abstract_jb.c.
References ast_test_flag, ast_channel::jb, JB_CREATED, jb_get_and_deliver(), and JB_USE.
Referenced by ast_generic_bridge().
00371 { 00372 struct ast_jb *jb0 = &c0->jb; 00373 struct ast_jb *jb1 = &c1->jb; 00374 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00375 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00376 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00377 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00378 00379 if (c0_use_jb && c0_jb_is_created) 00380 jb_get_and_deliver(c0); 00381 00382 if (c1_use_jb && c1_jb_is_created) 00383 jb_get_and_deliver(c1); 00384 }
void ast_jb_get_config | ( | const struct ast_channel * | chan, | |
struct ast_jb_conf * | conf | |||
) |
Copies a channel's jitterbuffer configuration.
chan | channel. | |
conf | destination. |
Definition at line 608 of file abstract_jb.c.
References ast_jb::conf, and ast_channel::jb.
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.
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.
Definition at line 265 of file abstract_jb.c.
References ast_test_flag, get_now(), ast_channel::jb, JB_CREATED, JB_USE, and ast_jb::next.
Referenced by ast_generic_bridge().
00266 { 00267 struct ast_jb *jb0 = &c0->jb; 00268 struct ast_jb *jb1 = &c1->jb; 00269 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00270 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00271 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00272 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00273 int wait, wait0, wait1; 00274 struct timeval tv_now; 00275 00276 if (time_left == 0) { 00277 /* No time left - the bridge will be retried */ 00278 /* TODO: Test disable this */ 00279 /*return 0;*/ 00280 } 00281 00282 if (time_left < 0) { 00283 time_left = INT_MAX; 00284 } 00285 00286 gettimeofday(&tv_now, NULL); 00287 00288 wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left; 00289 wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left; 00290 00291 wait = wait0 < wait1 ? wait0 : wait1; 00292 wait = wait < time_left ? wait : time_left; 00293 00294 if (wait == INT_MAX) { 00295 wait = -1; 00296 } else if (wait < 1) { 00297 /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */ 00298 wait = 1; 00299 } 00300 00301 return wait; 00302 }
int ast_jb_put | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) |
Puts a frame into a channel jitterbuffer.
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.
Definition at line 305 of file abstract_jb.c.
References ast_clear_flag, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frdup(), AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_log(), ast_set_flag, ast_test_flag, create_jb(), 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().
00306 { 00307 struct ast_jb *jb = &chan->jb; 00308 struct ast_jb_impl *jbimpl = jb->impl; 00309 void *jbobj = jb->jbobj; 00310 struct ast_frame *frr; 00311 long now = 0; 00312 00313 if (!ast_test_flag(jb, JB_USE)) 00314 return -1; 00315 00316 if (f->frametype != AST_FRAME_VOICE) { 00317 if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) { 00318 jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now); 00319 jbimpl->force_resync(jbobj); 00320 } 00321 00322 return -1; 00323 } 00324 00325 /* We consider an enabled jitterbuffer should receive frames with valid timing info. */ 00326 if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) { 00327 ast_log(LOG_WARNING, "%s received frame with invalid timing info: " 00328 "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n", 00329 chan->name, ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO), f->len, f->ts, f->src); 00330 return -1; 00331 } 00332 00333 frr = ast_frdup(f); 00334 00335 if (!frr) { 00336 ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan->name); 00337 return -1; 00338 } 00339 00340 if (!ast_test_flag(jb, JB_CREATED)) { 00341 if (create_jb(chan, frr)) { 00342 ast_frfree(frr); 00343 /* Disable the jitterbuffer */ 00344 ast_clear_flag(jb, JB_USE); 00345 return -1; 00346 } 00347 00348 ast_set_flag(jb, JB_CREATED); 00349 return 0; 00350 } else { 00351 now = get_now(jb, NULL); 00352 if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) { 00353 jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); 00354 ast_frfree(frr); 00355 /*return -1;*/ 00356 /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't 00357 be delivered at all */ 00358 return 0; 00359 } 00360 00361 jb->next = jbimpl->next(jbobj); 00362 00363 jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); 00364 00365 return 0; 00366 } 00367 }
int ast_jb_read_conf | ( | struct ast_jb_conf * | conf, | |
char * | varname, | |||
char * | value | |||
) |
Sets jitterbuffer configuration property.
conf | configuration to store the property in. | |
varname | property name. | |
value | property value. |
Called from a channel driver to build a jitterbuffer configuration tipically when reading a configuration file. It is not neccessary for a channel driver to know each of the jb configuration property names. The jitterbuffer itself knows them. The channel driver can pass each config var it reads through this function. It will return 0 if the variable was consumed from the jb conf.
Definition at line 568 of file abstract_jb.c.
References AST_JB_CONF_ENABLE, AST_JB_CONF_FORCE, AST_JB_CONF_IMPL, AST_JB_CONF_LOG, AST_JB_CONF_MAX_SIZE, AST_JB_CONF_PREFIX, AST_JB_CONF_RESYNCH_THRESHOLD, AST_JB_ENABLED, AST_JB_FORCED, AST_JB_LOG, ast_set2_flag, ast_strlen_zero(), ast_true(), ast_jb_conf::impl, ast_jb_conf::max_size, name, and ast_jb_conf::resync_threshold.
Referenced by _build_general_config(), gtalk_load_config(), load_module(), process_dahdi(), reload_config(), and store_config().
00569 { 00570 int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1; 00571 char *name; 00572 int tmp; 00573 00574 if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) 00575 return -1; 00576 00577 name = varname + prefixlen; 00578 00579 if (!strcasecmp(name, AST_JB_CONF_ENABLE)) { 00580 ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED); 00581 } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) { 00582 ast_set2_flag(conf, ast_true(value), AST_JB_FORCED); 00583 } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) { 00584 if ((tmp = atoi(value)) > 0) 00585 conf->max_size = tmp; 00586 } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) { 00587 if ((tmp = atoi(value)) > 0) 00588 conf->resync_threshold = tmp; 00589 } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) { 00590 if (!ast_strlen_zero(value)) 00591 snprintf(conf->impl, sizeof(conf->impl), "%s", value); 00592 } else if (!strcasecmp(name, AST_JB_CONF_LOG)) { 00593 ast_set2_flag(conf, ast_true(value), AST_JB_LOG); 00594 } else { 00595 return -1; 00596 } 00597 00598 return 0; 00599 }
static int create_jb | ( | struct ast_channel * | chan, | |
struct ast_frame * | first_frame | |||
) | [static] |
Definition at line 447 of file abstract_jb.c.
References ast_assert, ast_bridged_channel(), AST_CHANNEL_NAME, ast_frfree, AST_JB_IMPL_NAME_SIZE, AST_JB_LOG, ast_log(), ast_test_flag, ast_verbose(), ast_jb::conf, ast_jb_impl::create, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, JB_IMPL_OK, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_WARNING, ast_jb::logfile, ast_jb_impl::name, ast_jb_impl::next, ast_jb::next, option_verbose, ast_jb_impl::put_first, ast_jb_conf::resync_threshold, ast_frame::subclass, ast_frame::ts, and VERBOSE_PREFIX_3.
Referenced by ast_jb_put().
00448 { 00449 struct ast_jb *jb = &chan->jb; 00450 struct ast_jb_conf *jbconf = &jb->conf; 00451 struct ast_jb_impl *jbimpl = jb->impl; 00452 void *jbobj; 00453 struct ast_channel *bridged; 00454 long now; 00455 char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1]; 00456 char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp; 00457 int res; 00458 00459 jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold); 00460 if (!jbobj) { 00461 ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name); 00462 return -1; 00463 } 00464 00465 now = get_now(jb, NULL); 00466 res = jbimpl->put_first(jbobj, frr, now); 00467 00468 /* The result of putting the first frame should not differ from OK. However, its possible 00469 some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */ 00470 if (res != JB_IMPL_OK) { 00471 ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name); 00472 /* 00473 jbimpl->destroy(jbobj); 00474 return -1; 00475 */ 00476 } 00477 00478 /* Init next */ 00479 jb->next = jbimpl->next(jbobj); 00480 00481 /* Init last format for a first time. */ 00482 jb->last_format = frr->subclass; 00483 00484 /* Create a frame log file */ 00485 if (ast_test_flag(jbconf, AST_JB_LOG)) { 00486 snprintf(name2, sizeof(name2), "%s", chan->name); 00487 tmp = strchr(name2, '/'); 00488 if (tmp) 00489 *tmp = '#'; 00490 00491 bridged = ast_bridged_channel(chan); 00492 /* We should always have bridged chan if a jitterbuffer is in use */ 00493 ast_assert(bridged != NULL); 00494 00495 snprintf(name1, sizeof(name1), "%s", bridged->name); 00496 tmp = strchr(name1, '/'); 00497 if (tmp) 00498 *tmp = '#'; 00499 00500 snprintf(logfile_pathname, sizeof(logfile_pathname), 00501 "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2); 00502 jb->logfile = fopen(logfile_pathname, "w+b"); 00503 00504 if (!jb->logfile) 00505 ast_log(LOG_WARNING, "Failed to create frame log file with pathname '%s'\n", logfile_pathname); 00506 00507 if (res == JB_IMPL_OK) 00508 jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n", 00509 now, frr->ts, frr->len); 00510 else 00511 jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", 00512 now, frr->ts, frr->len); 00513 } 00514 00515 if (option_verbose > 2) 00516 ast_verbose(VERBOSE_PREFIX_3 "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name); 00517 00518 /* Free the frame if it has not been queued in the jb */ 00519 if (res != JB_IMPL_OK) 00520 ast_frfree(frr); 00521 00522 return 0; 00523 }
static long get_now | ( | struct ast_jb * | jb, | |
struct timeval * | tv | |||
) | [static] |
Definition at line 555 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().
00556 { 00557 struct timeval now; 00558 00559 if (!tv) { 00560 tv = &now; 00561 gettimeofday(tv, NULL); 00562 } 00563 00564 return ast_tvdiff_ms(*tv, jb->timebase); 00565 }
static void jb_choose_impl | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 183 of file abstract_jb.c.
References 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 struct ast_jb_impl *test_impl; 00188 int i, avail_impl_count = sizeof(avail_impl) / sizeof(avail_impl[0]); 00189 00190 jb->impl = &avail_impl[default_impl]; 00191 00192 if (ast_strlen_zero(jbconf->impl)) 00193 return; 00194 00195 for (i = 0; i < avail_impl_count; i++) { 00196 test_impl = &avail_impl[i]; 00197 if (!strcasecmp(jbconf->impl, test_impl->name)) { 00198 jb->impl = test_impl; 00199 return; 00200 } 00201 } 00202 }
static void * jb_create_adaptive | ( | struct ast_jb_conf * | general_config, | |
long | resynch_threshold | |||
) | [static] |
Definition at line 728 of file abstract_jb.c.
References jb_new(), jb_setconf(), jb_conf::max_contig_interp, jb_conf::max_jitterbuf, ast_jb_conf::max_size, ast_jb_conf::resync_threshold, and jb_conf::resync_threshold.
00729 { 00730 jb_conf jbconf; 00731 jitterbuf *adaptivejb; 00732 00733 adaptivejb = jb_new(); 00734 if (adaptivejb) { 00735 jbconf.max_jitterbuf = general_config->max_size; 00736 jbconf.resync_threshold = general_config->resync_threshold; 00737 jbconf.max_contig_interp = 10; 00738 jb_setconf(adaptivejb, &jbconf); 00739 } 00740 00741 return adaptivejb; 00742 }
static void * jb_create_fixed | ( | struct ast_jb_conf * | general_config, | |
long | resynch_threshold | |||
) | [static] |
Definition at line 634 of file abstract_jb.c.
References fixed_jb_new(), fixed_jb_conf::jbsize, ast_jb_conf::max_size, and fixed_jb_conf::resync_threshold.
00635 { 00636 struct fixed_jb_conf conf; 00637 00638 conf.jbsize = general_config->max_size; 00639 conf.resync_threshold = resynch_threshold; 00640 00641 return fixed_jb_new(&conf); 00642 }
static void jb_destroy_adaptive | ( | void * | jb | ) | [static] |
Definition at line 745 of file abstract_jb.c.
References jb_destroy().
00746 { 00747 jitterbuf *adaptivejb = (jitterbuf *) jb; 00748 00749 jb_destroy(adaptivejb); 00750 }
static void jb_destroy_fixed | ( | void * | jb | ) | [static] |
Definition at line 644 of file abstract_jb.c.
References fixed_jb_destroy().
00645 { 00646 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00647 00648 /* destroy the jb */ 00649 fixed_jb_destroy(fixedjb); 00650 }
static void jb_empty_and_reset_adaptive | ( | void * | jb | ) | [static] |
Definition at line 813 of file abstract_jb.c.
References ast_frfree, jb_frame::data, f, jb_getall(), JB_OK, and jb_reset().
static void jb_empty_and_reset_fixed | ( | void * | jb | ) | [static] |
Definition at line 716 of file abstract_jb.c.
References ast_frfree, fixed_jb_frame::data, FIXED_JB_OK, and fixed_jb_remove().
00717 { 00718 struct fixed_jb *fixedjb = jb; 00719 struct fixed_jb_frame f; 00720 00721 while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) { 00722 ast_frfree(f.data); 00723 } 00724 }
static void jb_force_resynch_adaptive | ( | void * | jb | ) | [static] |
Definition at line 809 of file abstract_jb.c.
static void jb_force_resynch_fixed | ( | void * | jb | ) | [static] |
Definition at line 709 of file abstract_jb.c.
References fixed_jb_set_force_resynch().
00710 { 00711 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00712 00713 fixed_jb_set_force_resynch(fixedjb); 00714 }
static int jb_get_adaptive | ( | void * | jb, | |
struct ast_frame ** | fout, | |||
long | now, | |||
long | interpl | |||
) | [static] |
Definition at line 775 of file abstract_jb.c.
References jb_frame::data, and jb_get().
static void jb_get_and_deliver | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 387 of file abstract_jb.c.
References ast_assert, ast_codec_interp_len(), AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), ast_samp2tv(), ast_tvadd(), ast_write(), 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().
00388 { 00389 struct ast_jb *jb = &chan->jb; 00390 struct ast_jb_impl *jbimpl = jb->impl; 00391 void *jbobj = jb->jbobj; 00392 struct ast_frame *f, finterp = { .frametype = AST_FRAME_VOICE, }; 00393 long now; 00394 int interpolation_len, res; 00395 00396 now = get_now(jb, NULL); 00397 jb->next = jbimpl->next(jbobj); 00398 if (now < jb->next) { 00399 jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next); 00400 return; 00401 } 00402 00403 while (now >= jb->next) { 00404 interpolation_len = ast_codec_interp_len(jb->last_format); 00405 00406 res = jbimpl->get(jbobj, &f, now, interpolation_len); 00407 00408 switch(res) { 00409 case JB_IMPL_OK: 00410 /* deliver the frame */ 00411 ast_write(chan, f); 00412 case JB_IMPL_DROP: 00413 jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n", 00414 now, jb_get_actions[res], f->ts, f->len); 00415 jb->last_format = f->subclass; 00416 ast_frfree(f); 00417 break; 00418 case JB_IMPL_INTERP: 00419 /* interpolate a frame */ 00420 f = &finterp; 00421 f->subclass = jb->last_format; 00422 f->samples = interpolation_len * 8; 00423 f->src = "JB interpolation"; 00424 f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000)); 00425 f->offset = AST_FRIENDLY_OFFSET; 00426 /* deliver the interpolated frame */ 00427 ast_write(chan, f); 00428 jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len); 00429 break; 00430 case JB_IMPL_NOFRAME: 00431 ast_log(LOG_WARNING, 00432 "JB_IMPL_NOFRAME is retuned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n", 00433 jbimpl->name, now, jb->next, jbimpl->next(jbobj)); 00434 jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now); 00435 return; 00436 default: 00437 ast_log(LOG_ERROR, "This should never happen!\n"); 00438 ast_assert("JB type unknown" == NULL); 00439 break; 00440 } 00441 00442 jb->next = jbimpl->next(jbobj); 00443 } 00444 }
static int jb_get_fixed | ( | void * | jb, | |
struct ast_frame ** | fout, | |||
long | now, | |||
long | interpl | |||
) | [static] |
Definition at line 675 of file abstract_jb.c.
References fixed_jb_frame::data, and fixed_jb_get().
00676 { 00677 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00678 struct fixed_jb_frame frame; 00679 int res; 00680 00681 res = fixed_jb_get(fixedjb, &frame, now, interpl); 00682 *fout = frame.data; 00683 00684 return fixed_to_abstract_code[res]; 00685 }
static long jb_next_adaptive | ( | void * | jb | ) | [static] |
static long jb_next_fixed | ( | void * | jb | ) | [static] |
Definition at line 688 of file abstract_jb.c.
References fixed_jb_next().
00689 { 00690 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00691 00692 return fixed_jb_next(fixedjb); 00693 }
static int jb_put_adaptive | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 764 of file abstract_jb.c.
References jb_put(), JB_TYPE_VOICE, ast_frame::len, and ast_frame::ts.
Referenced by jb_put_first_adaptive().
00765 { 00766 jitterbuf *adaptivejb = (jitterbuf *) jb; 00767 int res; 00768 00769 res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now); 00770 00771 return adaptive_to_abstract_code[res]; 00772 }
static int jb_put_first_adaptive | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 753 of file abstract_jb.c.
References jitterbuf::info, jb_put_adaptive(), jb_info::resync_offset, and ast_frame::ts.
00754 { 00755 jitterbuf *adaptivejb = (jitterbuf *) jb; 00756 00757 /* Initialize the offset to that of the first frame's timestamp */ 00758 adaptivejb->info.resync_offset = fin->ts; 00759 00760 return jb_put_adaptive(jb, fin, now); 00761 }
static int jb_put_first_fixed | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 653 of file abstract_jb.c.
References fixed_jb_put_first(), ast_frame::len, and ast_frame::ts.
00654 { 00655 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00656 int res; 00657 00658 res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now); 00659 00660 return fixed_to_abstract_code[res]; 00661 }
static int jb_put_fixed | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 664 of file abstract_jb.c.
References fixed_jb_put(), ast_frame::len, and ast_frame::ts.
00665 { 00666 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00667 int res; 00668 00669 res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now); 00670 00671 return fixed_to_abstract_code[res]; 00672 }
static int jb_remove_adaptive | ( | void * | jb, | |
struct ast_frame ** | fout | |||
) | [static] |
Definition at line 796 of file abstract_jb.c.
References jb_frame::data, and jb_getall().
static int jb_remove_fixed | ( | void * | jb, | |
struct ast_frame ** | fout | |||
) | [static] |
Definition at line 696 of file abstract_jb.c.
References fixed_jb_frame::data, and fixed_jb_remove().
00697 { 00698 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00699 struct fixed_jb_frame frame; 00700 int res; 00701 00702 res = fixed_jb_remove(fixedjb, &frame); 00703 *fout = frame.data; 00704 00705 return fixed_to_abstract_code[res]; 00706 }
int adaptive_to_abstract_code[] [static] |
{JB_IMPL_OK, JB_IMPL_NOFRAME, JB_IMPL_NOFRAME, JB_IMPL_INTERP, JB_IMPL_DROP, JB_IMPL_OK}
Definition at line 158 of file abstract_jb.c.
struct ast_jb_impl avail_impl[] [static] |
Definition at line 116 of file abstract_jb.c.
int default_impl = 0 [static] |
Definition at line 144 of file abstract_jb.c.
int fixed_to_abstract_code[] [static] |
Definition at line 156 of file abstract_jb.c.
char* jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"} [static] |
Definition at line 162 of file abstract_jb.c.