59#define MAXIMUM_EARLY_FRAME_COUNT 200
127static const char *
const jb_get_actions[] = {
"Delivered",
"Dropped",
"Interpolated",
"No"};
130#define jb_framelog(...) do { \
132 fprintf(jb->logfile, __VA_ARGS__); \
133 fflush(jb->logfile); \
161 for (i = 0; i < avail_impl_count; i++) {
163 if (!strcasecmp(jbconf->
impl, test_impl->
name)) {
164 jb->
impl = test_impl;
191 if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) {
193 if (!c0_jb_timebase_initialized) {
194 if (c1_jb_timebase_initialized) {
202 if (!c0_jb_created) {
210 if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) {
212 if (!c1_jb_timebase_initialized) {
213 if (c0_jb_timebase_initialized) {
221 if (!c1_jb_created) {
239 int wait, wait0, wait1;
240 struct timeval tv_now;
242 if (time_left == 0) {
252 gettimeofday(&tv_now,
NULL);
254 wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->
next -
get_now(jb0, &tv_now) : time_left;
255 wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->
next -
get_now(jb1, &tv_now) : time_left;
257 wait = wait0 < wait1 ? wait0 : wait1;
258 wait = wait < time_left ? wait : time_left;
260 if (wait == INT_MAX) {
262 }
else if (wait < 1) {
275 void *jbobj = jb->
jbobj;
284 jb_framelog(
"JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now);
294 "has_timing_info=%u, len=%ld, ts=%ld, src=%s\n",
319 jb_framelog(
"JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->
ts, frr->
len);
329 jb_framelog(
"JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->
ts, frr->
len);
345 if (c0_use_jb && c0_jb_is_created)
348 if (c1_use_jb && c1_jb_is_created)
357 void *jbobj = jb->
jbobj;
360 int interpolation_len, res;
364 if (now < jb->
next) {
369 while (now >= jb->
next) {
372 res = jbimpl->
get(jbobj, &f, now, interpolation_len);
379 jb_framelog(
"\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
388 f->
samples = interpolation_len * 8;
389 f->
src =
"JB interpolation";
394 jb_framelog(
"\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
398 "AST_JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
400 jb_framelog(
"\tJB_GET {now=%ld}: No frame for now!?\n", now);
431 res = jbimpl->
put_first(jbobj, frr, now);
452 char safe_logfile[30] =
"/tmp/logfile-XXXXXX";
456 while ((
tmp = strchr(name2,
'/'))) {
464 while ((
tmp = strchr(name1,
'/'))) {
468 snprintf(logfile_pathname,
sizeof(logfile_pathname),
469 "/tmp/ast_%s_jb_%s--%s.log", jbimpl->
name, name1, name2);
470 unlink(logfile_pathname);
471 safe_fd = mkstemp(safe_logfile);
472 if (safe_fd < 0 || link(safe_logfile, logfile_pathname) || unlink(safe_logfile) || !(
jb->
logfile = fdopen(safe_fd,
"w+b"))) {
473 ast_log(
LOG_ERROR,
"Failed to create frame log file with pathname '%s': %s\n", logfile_pathname, strerror(
errno));
481 jb_framelog(
"JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
482 now, frr->
ts, frr->
len);
484 jb_framelog(
"JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
485 now, frr->
ts, frr->
len);
506 void *jbobj = jb->
jbobj;
538 gettimeofday(when,
NULL);
555 name = varname + prefixlen;
571 if (sscanf(
value,
"%30d", &
tmp) == 1) {
776 res =
jb_get(adaptivejb, &frame, now, interpl);
836#define DEFAULT_TIMER_INTERVAL 20
837#define DEFAULT_SIZE 200
838#define DEFAULT_TARGET_EXTRA 40
839#define DEFAULT_RESYNC 1000
840#define DEFAULT_TYPE AST_JB_FIXED
871 if (framedata->
timer) {
901 ast_debug(1,
"JITTERBUFFER datastore destroyed\n");
905 .
type =
"jitterbuffer",
911 ast_debug(1,
"JITTERBUFFER hook destroyed\n");
934 timestamp_diff = (frame->ts * (rate / 1000)) - stream_sync->timestamp;
940 timestamp_diff = frame->ts - stream_sync->timestamp;
943 if (timestamp_diff < 0) {
956 struct timeval now_tv;
957 int64_t relative_frame_start;
1034 struct timeval video_timestamp;
1068 if (relative_frame_start < 0) {
1095 if (!framedata->
first) {
1096 framedata->
first = 1;
1099 res = framedata->
jb_impl->
put(framedata->
jb_obj, jbframe, relative_frame_start);
1103 if (jbframe != frame) {
1107 }
else if (jbframe != frame) {
1126 if (relative_frame_start <
next) {
1127 long int diff =
next - relative_frame_start;
1156 tmp.src =
"func_jitterbuffer interpolation";
1236 if (!strcasecmp(
jb_conf->impl,
"fixed")) {
1238 }
else if (!strcasecmp(
jb_conf->impl,
"adaptive")) {
1279 if (!strcasecmp(
jb_conf->impl,
"disabled")) {
1283 id = datastore->
data;
1292 if (!(framedata =
ast_calloc(1,
sizeof(*framedata)))) {
1301 interface.
data = framedata;
1309 if (prefer_existing) {
1316 id = datastore->
data;
void ast_jb_create_framehook(struct ast_channel *chan, struct ast_jb_conf *jb_conf, int prefer_existing)
Applies a jitterbuffer framehook to a channel based on a provided jitterbuffer config.
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
static int jb_put_fixed(void *jb, struct ast_frame *fin, long now)
static int jb_remove_fixed(void *jb, struct ast_frame **fout)
#define MAXIMUM_EARLY_FRAME_COUNT
static int create_jb(struct ast_channel *chan, struct ast_frame *first_frame)
static long get_now(struct ast_jb *jb, struct timeval *tv)
void ast_jb_empty_and_reset(struct ast_channel *c0, struct ast_channel *c1)
drops all frames from a jitterbuffer and resets it
#define jb_framelog(...)
Macros for the frame log files.
static struct timeval jitterbuffer_frame_get_ntp_timestamp(const struct jb_stream_sync *stream_sync, const struct ast_frame *frame)
static int jb_is_late_adaptive(void *jb, long ts)
static void jb_framedata_destroy(struct jb_framedata *framedata)
static void jb_force_resynch_fixed(void *jb)
static const int fixed_to_abstract_code[]
static int jb_put_adaptive(void *jb, struct ast_frame *fin, 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 long jb_next_adaptive(void *jb)
static void jb_get_and_deliver(struct ast_channel *chan)
static long jb_next_fixed(void *jb)
#define DEFAULT_TARGET_EXTRA
static int jb_get_adaptive(void *jb, struct ast_frame **fout, long now, long interpl)
void ast_jb_conf_default(struct ast_jb_conf *conf)
Sets the contents of an ast_jb_conf struct to the default jitterbuffer settings.
@ JB_TIMEBASE_INITIALIZED
void ast_jb_enable_for_channel(struct ast_channel *chan)
Sets a jitterbuffer frame hook on the channel based on the channel's stored jitterbuffer configuratio...
#define DEFAULT_TIMER_INTERVAL
static const struct ast_datastore_info jb_datastore
int ast_jb_put(struct ast_channel *chan, struct ast_frame *f)
Puts a frame into a channel jitterbuffer.
static const struct ast_jb_impl avail_impl[]
static const char *const jb_get_actions[]
static void jb_force_resynch_adaptive(void *jb)
static struct ast_frame * hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
static const int adaptive_to_abstract_code[]
void ast_jb_destroy(struct ast_channel *chan)
Destroys jitterbuffer on a channel.
static void jb_empty_and_reset_adaptive(void *jb)
static void hook_destroy_cb(void *framedata)
static void jb_choose_impl(struct ast_channel *chan)
static int jb_put_first_adaptive(void *jb, struct ast_frame *fin, long now)
static void datastore_destroy_cb(void *data)
static void * jb_create_fixed(struct ast_jb_conf *general_config)
static void jb_destroy_fixed(void *jb)
const struct ast_jb_impl * ast_jb_get_impl(enum ast_jb_type type)
static void jb_destroy_adaptive(void *jb)
int ast_jb_do_usecheck(struct ast_channel *c0, struct ast_channel *c1)
Checks the need of a jb use in a generic bridge.
static int jb_remove_adaptive(void *jb, struct ast_frame **fout)
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.
static void jb_empty_and_reset_fixed(void *jb)
static int jb_get_fixed(void *jb, struct ast_frame **fout, long now, long interpl)
void ast_jb_get_config(const struct ast_channel *chan, struct ast_jb_conf *conf)
Copies a channel's jitterbuffer configuration.
static int jb_framedata_init(struct jb_framedata *framedata, struct ast_jb_conf *jb_conf)
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
static int jb_put_first_fixed(void *jb, struct ast_frame *fin, long now)
static void * jb_create_adaptive(struct ast_jb_conf *general_config)
static int jb_is_late_fixed(void *jb, long ts)
Common implementation-independent jitterbuffer stuff.
#define AST_JB_CONF_ENABLE
#define AST_JB_CONF_RESYNCH_THRESHOLD
#define AST_JB_CONF_SYNC_VIDEO
#define AST_JB_CONF_FORCE
#define AST_JB_CONF_MAX_SIZE
#define AST_JB_CONF_TARGET_EXTRA
#define AST_JB_IMPL_NAME_SIZE
#define AST_JB_CONF_PREFIX
Asterisk main include file. File version handling, generic pbx functions.
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
@ AST_CHAN_TP_WANTSJITTER
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
@ AST_CHAN_TP_CREATESJITTER
Channels have this property if they can create jitter; i.e. most VoIP channels.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
int ast_channel_fdno(const struct ast_channel *chan)
#define ast_channel_lock(chan)
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.
struct ast_jb * ast_channel_jb(struct ast_channel *chan)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
#define AST_JITTERBUFFER_FD
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
#define ast_channel_unlock(chan)
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
#define ast_datastore_alloc(info, uid)
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
struct fixed_jb * fixed_jb_new(struct fixed_jb_conf *conf)
int fixed_jb_put_first(struct fixed_jb *jb, void *data, long ms, long ts, long now)
int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
long fixed_jb_next(struct fixed_jb *jb)
int fixed_jb_get(struct fixed_jb *jb, struct fixed_jb_frame *frame, long now, long interpl)
int fixed_jb_is_late(struct fixed_jb *jb, long ts)
Checks if the given time stamp is late.
void fixed_jb_destroy(struct fixed_jb *jb)
int fixed_jb_remove(struct fixed_jb *jb, struct fixed_jb_frame *frameout)
void fixed_jb_set_force_resynch(struct fixed_jb *jb)
Jitterbuffering algorithm.
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
ast_framehook_event
These are the types of events that the framehook's event callback can receive.
@ AST_FRAMEHOOK_EVENT_ATTACHED
@ AST_FRAMEHOOK_EVENT_DETACHED
@ AST_FRAMEHOOK_EVENT_WRITE
@ AST_FRAMEHOOK_EVENT_READ
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
#define AST_FRAMEHOOK_INTERFACE_VERSION
Asterisk internal frame definitions.
@ AST_FRFLAG_HAS_TIMING_INFO
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frdup(fr)
Copies a frame.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
@ AST_CONTROL_T38_PARAMETERS
struct ast_frame ast_null_frame
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
jitterbuf: an application-independent jitterbuffer jitterbuf.c
int jb_is_late(jitterbuf *jb, long ts)
Checks if the given time stamp is late.
void jb_destroy(jitterbuf *jb)
destroy jitterbuf
void jb_reset(jitterbuf *jb)
reset jitterbuf
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!...
jitterbuf * jb_new(void)
new jitterbuf
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
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...
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
set jitterbuf conf
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
unconditionally get frames from jitterbuf until empty
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Core PBX routines and definitions.
Pluggable RTP Architecture.
int ast_rtp_get_rate(const struct ast_format *format)
Retrieve the sample rate of a format according to RTP specifications.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Main Channel structure associated with a channel.
Structure for a data store type.
Structure for a data store object.
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
General jitterbuffer configuration.
long target_extra
amount of additional jitterbuffer adjustment
char impl[AST_JB_IMPL_NAME_SIZE]
Name of the jitterbuffer implementation to be used.
long max_size
Max size of the jitterbuffer implementation.
long resync_threshold
Resynchronization threshold of the jitterbuffer implementation.
Jitterbuffer implementation struct.
jb_put_first_impl put_first
char name[AST_JB_IMPL_NAME_SIZE]
jb_empty_and_reset_impl empty_and_reset
jb_force_resynch_impl force_resync
General jitterbuffer state.
void * jbobj
Jitterbuffer object, passed to the implementation.
struct ast_jb_conf conf
Jitterbuffer configuration.
long next
The time the next frame should be played.
struct ast_format * last_format
Voice format of the last frame in.
struct timeval timebase
The time the jitterbuffer was created.
FILE * logfile
File for frame timestamp tracing.
const struct ast_jb_impl * impl
Jitterbuffer implementation to be used.
An object that represents data sent during a SR/RR RTCP report.
struct ast_rtp_rtcp_report::@273 sender_information
unsigned int rtp_timestamp
struct timeval ntp_timestamp
All configuration options for http media cache.
private fixed_jb structure
struct ast_jb_conf jb_conf
struct jb_stream_sync audio_stream_sync
struct jb_stream_sync video_stream_sync
struct ast_format * last_format
unsigned int early_frame_count
struct timeval last_audio_ntp_timestamp
struct jb_framedata::@292 early_frames
const struct ast_jb_impl * jb_impl
Handy terminal functions for vt* terms.
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 ...
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Timing source management.
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
struct ast_timer * ast_timer_open(void)
Open a timer.
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
#define ast_test_flag(p, flag)
#define ast_set2_flag(p, value, flag)
#define ast_clear_flag(p, flag)
#define ast_set_flag(p, flag)