40 #include "asterisk/frame.h"
59 typedef void * (*jb_create_impl)(
struct ast_jb_conf *general_config,
long resynch_threshold);
162 static const char *
const jb_get_actions[] = {
"Delivered",
"Dropped",
"Interpolated",
"No"};
165 #define jb_framelog(...) do { \
167 fprintf(jb->logfile, __VA_ARGS__); \
168 fflush(jb->logfile); \
188 int i, avail_impl_count =
ARRAY_LEN(avail_impl);
196 for (i = 0; i < avail_impl_count; i++) {
197 test_impl = &avail_impl[i];
198 if (!strcasecmp(jbconf->
impl, test_impl->
name)) {
199 jb->
impl = test_impl;
226 if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) {
228 if (!c0_jb_timebase_initialized) {
229 if (c1_jb_timebase_initialized) {
237 if (!c0_jb_created) {
245 if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) {
247 if (!c1_jb_timebase_initialized) {
248 if (c0_jb_timebase_initialized) {
256 if (!c1_jb_created) {
274 int wait, wait0, wait1;
275 struct timeval tv_now;
277 if (time_left == 0) {
287 gettimeofday(&tv_now, NULL);
289 wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->
next -
get_now(jb0, &tv_now) : time_left;
290 wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->
next -
get_now(jb1, &tv_now) : time_left;
292 wait = wait0 < wait1 ? wait0 : wait1;
293 wait = wait < time_left ? wait : time_left;
295 if (wait == INT_MAX) {
297 }
else if (wait < 1) {
310 void *jbobj = jb->
jbobj;
319 jb_framelog(
"JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now);
329 "has_timing_info=%u, len=%ld, ts=%ld, src=%s\n",
337 ast_log(
LOG_ERROR,
"Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan->
name);
354 jb_framelog(
"JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->
ts, frr->
len);
364 jb_framelog(
"JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->
ts, frr->
len);
380 if (c0_use_jb && c0_jb_is_created)
383 if (c1_use_jb && c1_jb_is_created)
392 void *jbobj = jb->
jbobj;
395 int interpolation_len, res;
399 if (now < jb->
next) {
404 while (now >= jb->
next) {
407 res = jbimpl->
get(jbobj, &f, now, interpolation_len);
415 jb_framelog(
"\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
416 now, jb_get_actions[res], f->
ts, f->
len);
424 f->
samples = interpolation_len * 8;
425 f->
src =
"JB interpolation";
430 jb_framelog(
"\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
434 "JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
436 jb_framelog(
"\tJB_GET {now=%ld}: No frame for now!?\n", now);
468 res = jbimpl->
put_first(jbobj, frr, now);
488 char safe_logfile[30] =
"/tmp/logfile-XXXXXX";
490 snprintf(name2,
sizeof(name2),
"%s", chan->
name);
491 while ((tmp = strchr(name2,
'/'))) {
499 snprintf(name1,
sizeof(name1),
"%s", bridged->
name);
500 while ((tmp = strchr(name1,
'/'))) {
504 snprintf(logfile_pathname,
sizeof(logfile_pathname),
505 "/tmp/ast_%s_jb_%s--%s.log", jbimpl->
name, name1, name2);
506 unlink(logfile_pathname);
507 safe_fd = mkstemp(safe_logfile);
508 if (safe_fd < 0 || link(safe_logfile, logfile_pathname) || unlink(safe_logfile) || !(jb->
logfile = fdopen(safe_fd,
"w+b"))) {
509 ast_log(
LOG_ERROR,
"Failed to create frame log file with pathname '%s': %s\n", logfile_pathname, strerror(
errno));
517 jb_framelog(
"JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
518 now, frr->
ts, frr->
len);
520 jb_framelog(
"JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
521 now, frr->
ts, frr->
len);
525 ast_verb(3,
"%s jitterbuffer created on channel %s\n", jbimpl->
name, chan->
name);
540 void *jbobj = jb->
jbobj;
559 ast_verb(3,
"%s jitterbuffer destroyed on channel %s\n", jbimpl->
name, chan->
name);
570 gettimeofday(when, NULL);
587 name = varname + prefixlen;
594 if ((tmp = atoi(value)) > 0)
597 if ((tmp = atoi(value)) > 0)
601 snprintf(conf->
impl,
sizeof(conf->
impl),
"%s", value);
603 if (sscanf(value,
"%30d", &tmp) == 1) {
618 memcpy(&chan->
jb.
conf, conf,
sizeof(*conf));
624 memcpy(conf, &chan->
jb.
conf,
sizeof(*conf));
674 return fixed_to_abstract_code[res];
685 return fixed_to_abstract_code[res];
698 return fixed_to_abstract_code[res];
719 return fixed_to_abstract_code[res];
786 return adaptive_to_abstract_code[res];
796 res =
jb_get(adaptivejb, &frame, now, interpl);
799 return adaptive_to_abstract_code[res];
820 return adaptive_to_abstract_code[res];
union ast_frame_subclass subclass
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
static void * jb_create_adaptive(struct ast_jb_conf *general_config, long resynch_threshold)
private fixed_jb structure
int ast_jb_put(struct ast_channel *chan, struct ast_frame *f)
Puts a frame into a channel jitterbuffer.
#define ast_set2_flag(p, value, flag)
#define ast_test_flag(p, flag)
static int ast_codec_interp_len(format_t format)
Gets duration in ms of interpolation frame for a format.
void ast_jb_empty_and_reset(struct ast_channel *c0, struct ast_channel *c1)
drops all frames from a jitterbuffer and resets it
#define AST_JB_CONF_ENABLE
int fixed_jb_remove(struct fixed_jb *jb, struct fixed_jb_frame *frameout)
static void jb_force_resynch_fixed(void *jb)
int(* jb_get_impl)(void *jb, struct ast_frame **fout, long now, long interpl)
Get frame for now.
#define ast_set_flag(p, flag)
void(* jb_force_resynch_impl)(void *jb)
Force resynch.
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
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.
enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now)
queue a frame
static int create_jb(struct ast_channel *chan, struct ast_frame *first_frame)
static void jb_destroy_fixed(void *jb)
static const char *const jb_get_actions[]
void(* jb_destroy_impl)(void *jb)
Destroy.
static int jb_remove_adaptive(void *jb, struct ast_frame **fout)
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
static long get_now(struct ast_jb *jb, struct timeval *tv)
struct ast_jb_conf conf
Jitterbuffer configuration.
void *(* jb_create_impl)(struct ast_jb_conf *general_config, long resynch_threshold)
Create.
#define AST_JB_IMPL_NAME_SIZE
enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frame, long now, long interpl)
get a frame for time now (receiver's time) return value is one of JB_OK: You've got frame! JB_DROP: H...
static long jb_next_fixed(void *jb)
Common implementation-independent jitterbuffer stuff.
static struct ast_jb_impl avail_impl[]
#define ast_verb(level,...)
static void jb_choose_impl(struct ast_channel *chan)
static int jb_put_fixed(void *jb, struct ast_frame *fin, long now)
jitterbuf * jb_new(void)
new jitterbuf
long resync_threshold
Resynchronization threshold of the jitterbuffer implementation.
static void jb_force_resynch_adaptive(void *jb)
#define jb_framelog(...)
Macros for the frame log files.
long jb_next(jitterbuf *jb)
when is the next frame due out, in receiver's time (0=EMPTY) This value may change as frames are adde...
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
static void jb_destroy_adaptive(void *jb)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define AST_JB_CONF_PREFIX
jb_force_resynch_impl force_resync
void ast_jb_destroy(struct ast_channel *chan)
Destroys jitterbuffer on a channel.
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
static int jb_get_adaptive(void *jb, struct ast_frame **fout, long now, long interpl)
void * jbobj
Jitterbuffer object, passed to the implementation.
long target_extra
amount of additional jitterbuffer adjustment
int fixed_jb_get(struct fixed_jb *jb, struct fixed_jb_frame *frame, long now, long interpl)
#define AST_JB_CONF_TARGET_EXTRA
char impl[AST_JB_IMPL_NAME_SIZE]
Name of the jitterbuffer implementation to be used.
int(* jb_put_first_impl)(void *jb, struct ast_frame *fin, long now)
Put first frame.
jitterbuf: an application-independent jitterbuffer jitterbuf.c
static void jb_empty_and_reset_fixed(void *jb)
static const int fixed_to_abstract_code[]
void fixed_jb_destroy(struct fixed_jb *jb)
static int jb_put_first_fixed(void *jb, struct ast_frame *fin, long now)
void ast_jb_get_config(const struct ast_channel *chan, struct ast_jb_conf *conf)
Copies a channel's jitterbuffer configuration.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
set jitterbuf conf
int fixed_jb_put_first(struct fixed_jb *jb, void *data, long ms, long ts, long now)
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
static const int adaptive_to_abstract_code[]
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
const ast_string_field name
static long jb_next_adaptive(void *jb)
#define AST_JB_CONF_FORCE
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
jb_put_first_impl put_first
long(* jb_next_impl)(void *jb)
Get next.
struct ast_jb_impl * impl
Jitterbuffer implementation to be used.
General jitterbuffer state.
static int jb_remove_fixed(void *jb, struct ast_frame **fout)
long fixed_jb_next(struct fixed_jb *jb)
FILE * logfile
File for frame timestamp tracing.
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
format_t last_format
Voice format of the last frame in.
int(* jb_put_impl)(void *jb, struct ast_frame *fin, long now)
Put frame.
Jitterbuffering algorithm.
#define ast_clear_flag(p, flag)
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
char name[AST_JB_IMPL_NAME_SIZE]
void fixed_jb_set_force_resynch(struct fixed_jb *jb)
jb_empty_and_reset_impl empty_and_reset
Channels have this property if they can create jitter; i.e. most VoIP channels.
struct fixed_jb * fixed_jb_new(struct fixed_jb_conf *conf)
int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
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.
static void * jb_create_fixed(struct ast_jb_conf *general_config, long resynch_threshold)
Data structure associated with a single frame of data.
static int jb_put_adaptive(void *jb, struct ast_frame *fin, long now)
Handy terminal functions for vt* terms.
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
enum ast_frame_type frametype
void jb_destroy(jitterbuf *jb)
destroy jitterbuf
int(* jb_remove_impl)(void *jb, struct ast_frame **fout)
Remove first frame.
#define AST_JB_CONF_MAX_SIZE
struct timeval timebase
The time the jitterbuffer was created.
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
unconditionally get frames from jitterbuf until empty
int ast_jb_do_usecheck(struct ast_channel *c0, struct ast_channel *c1)
Checks the need of a jb use in a generic bridge.
#define AST_JB_CONF_RESYNCH_THRESHOLD
struct ast_channel_tech * tech
long max_size
Max size of the jitterbuffer implementation.
void(* jb_empty_and_reset_impl)(void *jb)
Empty and reset jb.
static void jb_get_and_deliver(struct ast_channel *chan)
Jitterbuffer implementation private struct.
General jitterbuffer configuration.
static void jb_empty_and_reset_adaptive(void *jb)
struct ast_frame * ast_frdup(const struct ast_frame *fr)
Copies a frame.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
static int jb_put_first_adaptive(void *jb, struct ast_frame *fin, long now)
long next
The time the next frame should be played.
void jb_reset(jitterbuf *jb)
reset jitterbuf
static int jb_get_fixed(void *jb, struct ast_frame **fout, long now, long interpl)