#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"} |
Definition in file abstract_jb.c.
#define jb_framelog | ( | ) |
Macros for the frame log files.
Definition at line 161 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) |
typedef void(*) jb_destroy_impl(void *jb) |
typedef void(*) jb_empty_and_reset_impl(void *jb) |
typedef void(*) jb_force_resynch_impl(void *jb) |
typedef int(*) jb_get_impl(void *jb, struct ast_frame **fout, long now, long interpl) |
typedef long(*) jb_next_impl(void *jb) |
typedef int(*) jb_put_first_impl(void *jb, struct ast_frame *fin, long now) |
typedef int(*) jb_put_impl(void *jb, struct ast_frame *fin, long now) |
typedef int(*) jb_remove_impl(void *jb, struct ast_frame **fout) |
anonymous enum |
Internal jb flags
Definition at line 46 of file abstract_jb.c.
00046 { 00047 JB_USE = (1 << 0), 00048 JB_TIMEBASE_INITIALIZED = (1 << 1), 00049 JB_CREATED = (1 << 2) 00050 };
anonymous enum |
Abstract return codes
Definition at line 144 of file abstract_jb.c.
00144 { 00145 JB_IMPL_OK, 00146 JB_IMPL_DROP, 00147 JB_IMPL_INTERP, 00148 JB_IMPL_NOFRAME 00149 };
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. |
Definition at line 611 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(), unistim_new(), and usbradio_new().
void ast_jb_destroy | ( | struct ast_channel * | chan | ) |
Destroys jitterbuffer on a channel.
chan | channel. |
Definition at line 531 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_channel::name, ast_jb_impl::name, and ast_jb_impl::remove.
Referenced by ast_channel_destructor().
00532 { 00533 struct ast_jb *jb = &chan->jb; 00534 const struct ast_jb_impl *jbimpl = jb->impl; 00535 void *jbobj = jb->jbobj; 00536 struct ast_frame *f; 00537 00538 if (jb->logfile) { 00539 fclose(jb->logfile); 00540 jb->logfile = NULL; 00541 } 00542 00543 if (ast_test_flag(jb, JB_CREATED)) { 00544 /* Remove and free all frames still queued in jb */ 00545 while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) { 00546 ast_frfree(f); 00547 } 00548 00549 jbimpl->destroy(jbobj); 00550 jb->jbobj = NULL; 00551 00552 ast_clear_flag(jb, JB_CREATED); 00553 00554 ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name); 00555 } 00556 }
int ast_jb_do_usecheck | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) |
Checks the need of a jb use in a generic bridge.
c0 | first bridged channel. | |
c1 | second bridged channel. |
zero | if there are no jitter buffers in use | |
non-zero | if there are |
Definition at line 201 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().
00202 { 00203 struct ast_jb *jb0 = &c0->jb; 00204 struct ast_jb *jb1 = &c1->jb; 00205 struct ast_jb_conf *conf0 = &jb0->conf; 00206 struct ast_jb_conf *conf1 = &jb1->conf; 00207 int c0_wants_jitter = c0->tech->properties & AST_CHAN_TP_WANTSJITTER; 00208 int c0_creates_jitter = c0->tech->properties & AST_CHAN_TP_CREATESJITTER; 00209 int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED); 00210 int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED); 00211 int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED); 00212 int c0_jb_created = ast_test_flag(jb0, JB_CREATED); 00213 int c1_wants_jitter = c1->tech->properties & AST_CHAN_TP_WANTSJITTER; 00214 int c1_creates_jitter = c1->tech->properties & AST_CHAN_TP_CREATESJITTER; 00215 int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED); 00216 int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED); 00217 int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED); 00218 int c1_jb_created = ast_test_flag(jb1, JB_CREATED); 00219 int inuse = 0; 00220 00221 /* Determine whether audio going to c0 needs a jitter buffer */ 00222 if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) { 00223 ast_set_flag(jb0, JB_USE); 00224 if (!c0_jb_timebase_initialized) { 00225 if (c1_jb_timebase_initialized) { 00226 memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval)); 00227 } else { 00228 gettimeofday(&jb0->timebase, NULL); 00229 } 00230 ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED); 00231 } 00232 00233 if (!c0_jb_created) { 00234 jb_choose_impl(c0); 00235 } 00236 00237 inuse = 1; 00238 } 00239 00240 /* Determine whether audio going to c1 needs a jitter buffer */ 00241 if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) { 00242 ast_set_flag(jb1, JB_USE); 00243 if (!c1_jb_timebase_initialized) { 00244 if (c0_jb_timebase_initialized) { 00245 memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval)); 00246 } else { 00247 gettimeofday(&jb1->timebase, NULL); 00248 } 00249 ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED); 00250 } 00251 00252 if (!c1_jb_created) { 00253 jb_choose_impl(c1); 00254 } 00255 00256 inuse = 1; 00257 } 00258 00259 return inuse; 00260 }
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 622 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().
00623 { 00624 struct ast_jb *jb0 = &c0->jb; 00625 struct ast_jb *jb1 = &c1->jb; 00626 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00627 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00628 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00629 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00630 00631 if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) { 00632 jb0->impl->empty_and_reset(jb0->jbobj); 00633 } 00634 00635 if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) { 00636 jb1->impl->empty_and_reset(jb1->jbobj); 00637 } 00638 }
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. |
Definition at line 367 of file abstract_jb.c.
References ast_test_flag, ast_channel::jb, JB_CREATED, jb_get_and_deliver(), and JB_USE.
00368 { 00369 struct ast_jb *jb0 = &c0->jb; 00370 struct ast_jb *jb1 = &c1->jb; 00371 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00372 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00373 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00374 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00375 00376 if (c0_use_jb && c0_jb_is_created) 00377 jb_get_and_deliver(c0); 00378 00379 if (c1_use_jb && c1_jb_is_created) 00380 jb_get_and_deliver(c1); 00381 }
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 617 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. |
Definition at line 262 of file abstract_jb.c.
References ast_test_flag, get_now(), ast_channel::jb, JB_CREATED, JB_USE, and ast_jb::next.
00263 { 00264 struct ast_jb *jb0 = &c0->jb; 00265 struct ast_jb *jb1 = &c1->jb; 00266 int c0_use_jb = ast_test_flag(jb0, JB_USE); 00267 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED); 00268 int c1_use_jb = ast_test_flag(jb1, JB_USE); 00269 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED); 00270 int wait, wait0, wait1; 00271 struct timeval tv_now; 00272 00273 if (time_left == 0) { 00274 /* No time left - the bridge will be retried */ 00275 /* TODO: Test disable this */ 00276 /*return 0;*/ 00277 } 00278 00279 if (time_left < 0) { 00280 time_left = INT_MAX; 00281 } 00282 00283 gettimeofday(&tv_now, NULL); 00284 00285 wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left; 00286 wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left; 00287 00288 wait = wait0 < wait1 ? wait0 : wait1; 00289 wait = wait < time_left ? wait : time_left; 00290 00291 if (wait == INT_MAX) { 00292 wait = -1; 00293 } else if (wait < 1) { 00294 /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */ 00295 wait = 1; 00296 } 00297 00298 return wait; 00299 }
int ast_jb_put | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) |
Puts a frame into a channel jitterbuffer.
chan | channel. | |
f | frame. |
0 | if the frame was queued | |
-1 | if not |
Definition at line 302 of file abstract_jb.c.
References ast_clear_flag, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frdup(), AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_log(), ast_set_flag, ast_test_flag, create_jb(), f, ast_jb_impl::force_resync, get_now(), ast_jb::impl, ast_channel::jb, JB_CREATED, jb_framelog, JB_IMPL_OK, JB_USE, ast_jb::jbobj, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_channel::name, ast_jb_impl::next, ast_jb::next, ast_jb_impl::put, and ast_frame::ts.
00303 { 00304 struct ast_jb *jb = &chan->jb; 00305 const struct ast_jb_impl *jbimpl = jb->impl; 00306 void *jbobj = jb->jbobj; 00307 struct ast_frame *frr; 00308 long now = 0; 00309 00310 if (!ast_test_flag(jb, JB_USE)) 00311 return -1; 00312 00313 if (f->frametype != AST_FRAME_VOICE) { 00314 if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) { 00315 jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now); 00316 jbimpl->force_resync(jbobj); 00317 } 00318 00319 return -1; 00320 } 00321 00322 /* We consider an enabled jitterbuffer should receive frames with valid timing info. */ 00323 if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) { 00324 ast_log(LOG_WARNING, "%s received frame with invalid timing info: " 00325 "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n", 00326 chan->name, ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO), f->len, f->ts, f->src); 00327 return -1; 00328 } 00329 00330 frr = ast_frdup(f); 00331 00332 if (!frr) { 00333 ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan->name); 00334 return -1; 00335 } 00336 00337 if (!ast_test_flag(jb, JB_CREATED)) { 00338 if (create_jb(chan, frr)) { 00339 ast_frfree(frr); 00340 /* Disable the jitterbuffer */ 00341 ast_clear_flag(jb, JB_USE); 00342 return -1; 00343 } 00344 00345 ast_set_flag(jb, JB_CREATED); 00346 return 0; 00347 } else { 00348 now = get_now(jb, NULL); 00349 if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) { 00350 jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); 00351 ast_frfree(frr); 00352 /*return -1;*/ 00353 /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't 00354 be delivered at all */ 00355 return 0; 00356 } 00357 00358 jb->next = jbimpl->next(jbobj); 00359 00360 jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len); 00361 00362 return 0; 00363 } 00364 }
int ast_jb_read_conf | ( | struct ast_jb_conf * | conf, | |
const char * | varname, | |||
const char * | value | |||
) |
Sets jitterbuffer configuration property.
conf | configuration to store the property in. | |
varname | property name. | |
value | property value. |
Definition at line 572 of file abstract_jb.c.
References AST_JB_CONF_ENABLE, AST_JB_CONF_FORCE, AST_JB_CONF_IMPL, AST_JB_CONF_LOG, AST_JB_CONF_MAX_SIZE, AST_JB_CONF_PREFIX, AST_JB_CONF_RESYNCH_THRESHOLD, AST_JB_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(), store_config(), and store_config_core().
00573 { 00574 int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1; 00575 const char *name; 00576 int tmp; 00577 00578 if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) { 00579 return -1; 00580 } 00581 00582 name = varname + prefixlen; 00583 00584 if (!strcasecmp(name, AST_JB_CONF_ENABLE)) { 00585 ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED); 00586 } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) { 00587 ast_set2_flag(conf, ast_true(value), AST_JB_FORCED); 00588 } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) { 00589 if ((tmp = atoi(value)) > 0) 00590 conf->max_size = tmp; 00591 } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) { 00592 if ((tmp = atoi(value)) > 0) 00593 conf->resync_threshold = tmp; 00594 } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) { 00595 if (!ast_strlen_zero(value)) 00596 snprintf(conf->impl, sizeof(conf->impl), "%s", value); 00597 } else if (!strcasecmp(name, AST_JB_CONF_TARGET_EXTRA)) { 00598 if (sscanf(value, "%30d", &tmp) == 1) { 00599 conf->target_extra = tmp; 00600 } 00601 } else if (!strcasecmp(name, AST_JB_CONF_LOG)) { 00602 ast_set2_flag(conf, ast_true(value), AST_JB_LOG); 00603 } else { 00604 return -1; 00605 } 00606 00607 return 0; 00608 }
static int create_jb | ( | struct ast_channel * | chan, | |
struct ast_frame * | first_frame | |||
) | [static] |
Definition at line 444 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_channel::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().
00445 { 00446 struct ast_jb *jb = &chan->jb; 00447 struct ast_jb_conf *jbconf = &jb->conf; 00448 const struct ast_jb_impl *jbimpl = jb->impl; 00449 void *jbobj; 00450 struct ast_channel *bridged; 00451 long now; 00452 char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1]; 00453 char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp; 00454 int res; 00455 00456 jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold); 00457 if (!jbobj) { 00458 ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name); 00459 return -1; 00460 } 00461 00462 now = get_now(jb, NULL); 00463 res = jbimpl->put_first(jbobj, frr, now); 00464 00465 /* The result of putting the first frame should not differ from OK. However, its possible 00466 some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */ 00467 if (res != JB_IMPL_OK) { 00468 ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name); 00469 /* 00470 jbimpl->destroy(jbobj); 00471 return -1; 00472 */ 00473 } 00474 00475 /* Init next */ 00476 jb->next = jbimpl->next(jbobj); 00477 00478 /* Init last format for a first time. */ 00479 jb->last_format = frr->subclass.codec; 00480 00481 /* Create a frame log file */ 00482 if (ast_test_flag(jbconf, AST_JB_LOG)) { 00483 char safe_logfile[30] = "/tmp/logfile-XXXXXX"; 00484 int safe_fd; 00485 snprintf(name2, sizeof(name2), "%s", chan->name); 00486 if ((tmp = strchr(name2, '/'))) { 00487 *tmp = '#'; 00488 } 00489 00490 bridged = ast_bridged_channel(chan); 00491 /* We should always have bridged chan if a jitterbuffer is in use */ 00492 ast_assert(bridged != NULL); 00493 00494 snprintf(name1, sizeof(name1), "%s", bridged->name); 00495 if ((tmp = strchr(name1, '/'))) { 00496 *tmp = '#'; 00497 } 00498 00499 snprintf(logfile_pathname, sizeof(logfile_pathname), 00500 "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2); 00501 unlink(logfile_pathname); 00502 safe_fd = mkstemp(safe_logfile); 00503 if (safe_fd < 0 || link(safe_logfile, logfile_pathname) || unlink(safe_logfile) || !(jb->logfile = fdopen(safe_fd, "w+b"))) { 00504 ast_log(LOG_ERROR, "Failed to create frame log file with pathname '%s': %s\n", logfile_pathname, strerror(errno)); 00505 jb->logfile = NULL; 00506 if (safe_fd > -1) { 00507 close(safe_fd); 00508 } 00509 } 00510 00511 if (res == JB_IMPL_OK) { 00512 jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n", 00513 now, frr->ts, frr->len); 00514 } else { 00515 jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", 00516 now, frr->ts, frr->len); 00517 } 00518 } 00519 00520 ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name); 00521 00522 /* Free the frame if it has not been queued in the jb */ 00523 if (res != JB_IMPL_OK) { 00524 ast_frfree(frr); 00525 } 00526 00527 return 0; 00528 }
static long get_now | ( | struct ast_jb * | jb, | |
struct timeval * | tv | |||
) | [static] |
Definition at line 559 of file abstract_jb.c.
References ast_tvdiff_ms(), and ast_jb::timebase.
Referenced by ast_jb_get_when_to_wakeup(), ast_jb_put(), create_jb(), and jb_get_and_deliver().
00560 { 00561 struct timeval now; 00562 00563 if (!when) { 00564 when = &now; 00565 gettimeofday(when, NULL); 00566 } 00567 00568 return ast_tvdiff_ms(*when, jb->timebase); 00569 }
static void jb_choose_impl | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 179 of file abstract_jb.c.
References ARRAY_LEN, ast_strlen_zero(), avail_impl, ast_jb::conf, ast_jb_conf::impl, ast_jb::impl, ast_channel::jb, and ast_jb_impl::name.
Referenced by ast_jb_do_usecheck().
00180 { 00181 struct ast_jb *jb = &chan->jb; 00182 struct ast_jb_conf *jbconf = &jb->conf; 00183 const struct ast_jb_impl *test_impl; 00184 int i, avail_impl_count = ARRAY_LEN(avail_impl); 00185 00186 jb->impl = &avail_impl[default_impl]; 00187 00188 if (ast_strlen_zero(jbconf->impl)) { 00189 return; 00190 } 00191 00192 for (i = 0; i < avail_impl_count; i++) { 00193 test_impl = &avail_impl[i]; 00194 if (!strcasecmp(jbconf->impl, test_impl->name)) { 00195 jb->impl = test_impl; 00196 return; 00197 } 00198 } 00199 }
static void * jb_create_adaptive | ( | struct ast_jb_conf * | general_config, | |
long | resynch_threshold | |||
) | [static] |
Definition at line 737 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.
00738 { 00739 jb_conf jbconf; 00740 jitterbuf *adaptivejb; 00741 00742 adaptivejb = jb_new(); 00743 if (adaptivejb) { 00744 jbconf.max_jitterbuf = general_config->max_size; 00745 jbconf.resync_threshold = general_config->resync_threshold; 00746 jbconf.max_contig_interp = 10; 00747 jbconf.target_extra = general_config->target_extra; 00748 jb_setconf(adaptivejb, &jbconf); 00749 } 00750 00751 return adaptivejb; 00752 }
static void * jb_create_fixed | ( | struct ast_jb_conf * | general_config, | |
long | resynch_threshold | |||
) | [static] |
Definition at line 643 of file abstract_jb.c.
References fixed_jb_new(), fixed_jb_conf::jbsize, ast_jb_conf::max_size, and fixed_jb_conf::resync_threshold.
00644 { 00645 struct fixed_jb_conf conf; 00646 00647 conf.jbsize = general_config->max_size; 00648 conf.resync_threshold = resynch_threshold; 00649 00650 return fixed_jb_new(&conf); 00651 }
static void jb_destroy_adaptive | ( | void * | jb | ) | [static] |
Definition at line 755 of file abstract_jb.c.
References jb_destroy().
00756 { 00757 jitterbuf *adaptivejb = (jitterbuf *) jb; 00758 00759 jb_destroy(adaptivejb); 00760 }
static void jb_destroy_fixed | ( | void * | jb | ) | [static] |
Definition at line 653 of file abstract_jb.c.
References fixed_jb_destroy().
00654 { 00655 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00656 00657 /* destroy the jb */ 00658 fixed_jb_destroy(fixedjb); 00659 }
static void jb_empty_and_reset_adaptive | ( | void * | jb | ) | [static] |
Definition at line 823 of file abstract_jb.c.
References ast_frfree, f, jb_getall(), JB_OK, and jb_reset().
00824 { 00825 jitterbuf *adaptivejb = jb; 00826 jb_frame f; 00827 00828 while (jb_getall(adaptivejb, &f) == JB_OK) { 00829 ast_frfree(f.data); 00830 } 00831 00832 jb_reset(adaptivejb); 00833 }
static void jb_empty_and_reset_fixed | ( | void * | jb | ) | [static] |
Definition at line 725 of file abstract_jb.c.
References ast_frfree, f, FIXED_JB_OK, and fixed_jb_remove().
00726 { 00727 struct fixed_jb *fixedjb = jb; 00728 struct fixed_jb_frame f; 00729 00730 while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) { 00731 ast_frfree(f.data); 00732 } 00733 }
static void jb_force_resynch_adaptive | ( | void * | jb | ) | [static] |
static void jb_force_resynch_fixed | ( | void * | jb | ) | [static] |
Definition at line 718 of file abstract_jb.c.
References fixed_jb_set_force_resynch().
00719 { 00720 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00721 00722 fixed_jb_set_force_resynch(fixedjb); 00723 }
static int jb_get_adaptive | ( | void * | jb, | |
struct ast_frame ** | fout, | |||
long | now, | |||
long | interpl | |||
) | [static] |
Definition at line 785 of file abstract_jb.c.
References adaptive_to_abstract_code, jb_frame::data, and jb_get().
00786 { 00787 jitterbuf *adaptivejb = (jitterbuf *) jb; 00788 jb_frame frame; 00789 int res; 00790 00791 res = jb_get(adaptivejb, &frame, now, interpl); 00792 *fout = frame.data; 00793 00794 return adaptive_to_abstract_code[res]; 00795 }
static void jb_get_and_deliver | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 384 of file abstract_jb.c.
References ast_assert, ast_codec_interp_len(), AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), ast_samp2tv(), ast_tvadd(), ast_write(), f, ast_jb_impl::get, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, jb_get_actions, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME, JB_IMPL_OK, ast_jb::jbobj, ast_jb::last_format, LOG_ERROR, LOG_WARNING, ast_jb_impl::name, ast_frame::next, ast_jb_impl::next, ast_jb::next, and ast_jb::timebase.
Referenced by ast_jb_get_and_deliver().
00385 { 00386 struct ast_jb *jb = &chan->jb; 00387 const struct ast_jb_impl *jbimpl = jb->impl; 00388 void *jbobj = jb->jbobj; 00389 struct ast_frame *f, finterp = { .frametype = AST_FRAME_VOICE, }; 00390 long now; 00391 int interpolation_len, res; 00392 00393 now = get_now(jb, NULL); 00394 jb->next = jbimpl->next(jbobj); 00395 if (now < jb->next) { 00396 jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next); 00397 return; 00398 } 00399 00400 while (now >= jb->next) { 00401 interpolation_len = ast_codec_interp_len(jb->last_format); 00402 00403 res = jbimpl->get(jbobj, &f, now, interpolation_len); 00404 00405 switch (res) { 00406 case JB_IMPL_OK: 00407 /* deliver the frame */ 00408 ast_write(chan, f); 00409 case JB_IMPL_DROP: 00410 jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n", 00411 now, jb_get_actions[res], f->ts, f->len); 00412 jb->last_format = f->subclass.codec; 00413 ast_frfree(f); 00414 break; 00415 case JB_IMPL_INTERP: 00416 /* interpolate a frame */ 00417 f = &finterp; 00418 f->subclass.codec = jb->last_format; 00419 f->samples = interpolation_len * 8; 00420 f->src = "JB interpolation"; 00421 f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000)); 00422 f->offset = AST_FRIENDLY_OFFSET; 00423 /* deliver the interpolated frame */ 00424 ast_write(chan, f); 00425 jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len); 00426 break; 00427 case JB_IMPL_NOFRAME: 00428 ast_log(LOG_WARNING, 00429 "JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n", 00430 jbimpl->name, now, jb->next, jbimpl->next(jbobj)); 00431 jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now); 00432 return; 00433 default: 00434 ast_log(LOG_ERROR, "This should never happen!\n"); 00435 ast_assert("JB type unknown" == NULL); 00436 break; 00437 } 00438 00439 jb->next = jbimpl->next(jbobj); 00440 } 00441 }
static int jb_get_fixed | ( | void * | jb, | |
struct ast_frame ** | fout, | |||
long | now, | |||
long | interpl | |||
) | [static] |
Definition at line 684 of file abstract_jb.c.
References fixed_jb_frame::data, fixed_jb_get(), and fixed_to_abstract_code.
00685 { 00686 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00687 struct fixed_jb_frame frame; 00688 int res; 00689 00690 res = fixed_jb_get(fixedjb, &frame, now, interpl); 00691 *fout = frame.data; 00692 00693 return fixed_to_abstract_code[res]; 00694 }
static long jb_next_adaptive | ( | void * | jb | ) | [static] |
static long jb_next_fixed | ( | void * | jb | ) | [static] |
Definition at line 697 of file abstract_jb.c.
References fixed_jb_next().
00698 { 00699 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00700 00701 return fixed_jb_next(fixedjb); 00702 }
static int jb_put_adaptive | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 774 of file abstract_jb.c.
References adaptive_to_abstract_code, jb_put(), JB_TYPE_VOICE, ast_frame::len, and ast_frame::ts.
Referenced by jb_put_first_adaptive().
00775 { 00776 jitterbuf *adaptivejb = (jitterbuf *) jb; 00777 int res; 00778 00779 res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now); 00780 00781 return adaptive_to_abstract_code[res]; 00782 }
static int jb_put_first_adaptive | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 763 of file abstract_jb.c.
References jitterbuf::info, jb_put_adaptive(), jb_info::resync_offset, and ast_frame::ts.
00764 { 00765 jitterbuf *adaptivejb = (jitterbuf *) jb; 00766 00767 /* Initialize the offset to that of the first frame's timestamp */ 00768 adaptivejb->info.resync_offset = fin->ts; 00769 00770 return jb_put_adaptive(jb, fin, now); 00771 }
static int jb_put_first_fixed | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 662 of file abstract_jb.c.
References fixed_jb_put_first(), fixed_to_abstract_code, ast_frame::len, and ast_frame::ts.
00663 { 00664 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00665 int res; 00666 00667 res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now); 00668 00669 return fixed_to_abstract_code[res]; 00670 }
static int jb_put_fixed | ( | void * | jb, | |
struct ast_frame * | fin, | |||
long | now | |||
) | [static] |
Definition at line 673 of file abstract_jb.c.
References fixed_jb_put(), fixed_to_abstract_code, ast_frame::len, and ast_frame::ts.
00674 { 00675 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00676 int res; 00677 00678 res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now); 00679 00680 return fixed_to_abstract_code[res]; 00681 }
static int jb_remove_adaptive | ( | void * | jb, | |
struct ast_frame ** | fout | |||
) | [static] |
Definition at line 806 of file abstract_jb.c.
References adaptive_to_abstract_code, jb_frame::data, and jb_getall().
00807 { 00808 jitterbuf *adaptivejb = (jitterbuf *) jb; 00809 jb_frame frame; 00810 int res; 00811 00812 res = jb_getall(adaptivejb, &frame); 00813 *fout = frame.data; 00814 00815 return adaptive_to_abstract_code[res]; 00816 }
static int jb_remove_fixed | ( | void * | jb, | |
struct ast_frame ** | fout | |||
) | [static] |
Definition at line 705 of file abstract_jb.c.
References fixed_jb_frame::data, fixed_jb_remove(), and fixed_to_abstract_code.
00706 { 00707 struct fixed_jb *fixedjb = (struct fixed_jb *) jb; 00708 struct fixed_jb_frame frame; 00709 int res; 00710 00711 res = fixed_jb_remove(fixedjb, &frame); 00712 *fout = frame.data; 00713 00714 return fixed_to_abstract_code[res]; 00715 }
const int adaptive_to_abstract_code[] [static] |
Initial value:
{JB_IMPL_OK, JB_IMPL_NOFRAME, JB_IMPL_NOFRAME, JB_IMPL_INTERP, JB_IMPL_DROP, JB_IMPL_OK}
Definition at line 154 of file abstract_jb.c.
Referenced by jb_get_adaptive(), jb_put_adaptive(), and jb_remove_adaptive().
struct ast_jb_impl avail_impl[] [static] |
int default_impl = 0 [static] |
Definition at line 140 of file abstract_jb.c.
const int fixed_to_abstract_code[] [static] |
Initial value:
Definition at line 152 of file abstract_jb.c.
Referenced by jb_get_fixed(), jb_put_first_fixed(), jb_put_fixed(), and jb_remove_fixed().
const char* const jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"} [static] |