Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Macros | Enumerations | Functions | Variables
abstract_jb.c File Reference

Common implementation-independent jitterbuffer stuff. More...

#include "asterisk.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/pbx.h"
#include "asterisk/timing.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/format_cache.h"
#include "asterisk/abstract_jb.h"
#include "fixedjitterbuf.h"
#include "jitterbuf.h"
Include dependency graph for abstract_jb.c:

Go to the source code of this file.

Data Structures

struct  jb_framedata
 
struct  jb_stream_sync
 

Macros

#define DEFAULT_RESYNC   1000
 
#define DEFAULT_SIZE   200
 
#define DEFAULT_TARGET_EXTRA   40
 
#define DEFAULT_TIMER_INTERVAL   20
 
#define DEFAULT_TYPE   AST_JB_FIXED
 
#define jb_framelog(...)
 Macros for the frame log files. More...
 
#define MAXIMUM_EARLY_FRAME_COUNT   200
 

Enumerations

enum  { JB_USE = (1 << 0) , JB_TIMEBASE_INITIALIZED = (1 << 1) , JB_CREATED = (1 << 2) }
 

Functions

void ast_jb_conf_default (struct ast_jb_conf *conf)
 Sets the contents of an ast_jb_conf struct to the default jitterbuffer settings. More...
 
void ast_jb_configure (struct ast_channel *chan, const struct ast_jb_conf *conf)
 Configures a jitterbuffer on a channel. More...
 
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. More...
 
void ast_jb_destroy (struct ast_channel *chan)
 Destroys jitterbuffer on a channel. More...
 
int ast_jb_do_usecheck (struct ast_channel *c0, struct ast_channel *c1)
 Checks the need of a jb use in a generic bridge. More...
 
void ast_jb_empty_and_reset (struct ast_channel *c0, struct ast_channel *c1)
 drops all frames from a jitterbuffer and resets it More...
 
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 configuration. More...
 
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. More...
 
void ast_jb_get_config (const struct ast_channel *chan, struct ast_jb_conf *conf)
 Copies a channel's jitterbuffer configuration. More...
 
const struct ast_jb_implast_jb_get_impl (enum ast_jb_type type)
 
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. More...
 
int ast_jb_put (struct ast_channel *chan, struct ast_frame *f)
 Puts a frame into a channel jitterbuffer. More...
 
int ast_jb_read_conf (struct ast_jb_conf *conf, const char *varname, const char *value)
 Sets jitterbuffer configuration property. More...
 
static int create_jb (struct ast_channel *chan, struct ast_frame *first_frame)
 
static void datastore_destroy_cb (void *data)
 
static long get_now (struct ast_jb *jb, struct timeval *tv)
 
static void hook_destroy_cb (void *framedata)
 
static struct ast_framehook_event_cb (struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
 
static void jb_choose_impl (struct ast_channel *chan)
 
static void * jb_create_adaptive (struct ast_jb_conf *general_config)
 
static void * jb_create_fixed (struct ast_jb_conf *general_config)
 
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 void jb_framedata_destroy (struct jb_framedata *framedata)
 
static int jb_framedata_init (struct jb_framedata *framedata, struct ast_jb_conf *jb_conf)
 
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 int jb_is_late_adaptive (void *jb, long ts)
 
static int jb_is_late_fixed (void *jb, long ts)
 
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)
 
static struct timeval jitterbuffer_frame_get_ntp_timestamp (const struct jb_stream_sync *stream_sync, const struct ast_frame *frame)
 

Variables

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

Detailed Description

Common implementation-independent jitterbuffer stuff.

Author
Slav Klenov slav@.nosp@m.secu.nosp@m.rax.o.nosp@m.rg

Definition in file abstract_jb.c.

Macro Definition Documentation

◆ DEFAULT_RESYNC

#define DEFAULT_RESYNC   1000

Definition at line 839 of file abstract_jb.c.

◆ DEFAULT_SIZE

#define DEFAULT_SIZE   200

Definition at line 837 of file abstract_jb.c.

◆ DEFAULT_TARGET_EXTRA

#define DEFAULT_TARGET_EXTRA   40

Definition at line 838 of file abstract_jb.c.

◆ DEFAULT_TIMER_INTERVAL

#define DEFAULT_TIMER_INTERVAL   20

Definition at line 836 of file abstract_jb.c.

◆ DEFAULT_TYPE

#define DEFAULT_TYPE   AST_JB_FIXED

Definition at line 840 of file abstract_jb.c.

◆ jb_framelog

#define jb_framelog (   ...)

Macros for the frame log files.

Definition at line 130 of file abstract_jb.c.

◆ MAXIMUM_EARLY_FRAME_COUNT

#define MAXIMUM_EARLY_FRAME_COUNT   200

The maximum size we allow the early frame buffer to get

Definition at line 59 of file abstract_jb.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Internal jb flags

Enumerator
JB_USE 
JB_TIMEBASE_INITIALIZED 
JB_CREATED 

Definition at line 52 of file abstract_jb.c.

52 {
53 JB_USE = (1 << 0),
54 JB_TIMEBASE_INITIALIZED = (1 << 1),
55 JB_CREATED = (1 << 2)
56};
@ JB_CREATED
Definition: abstract_jb.c:55
@ JB_USE
Definition: abstract_jb.c:53
@ JB_TIMEBASE_INITIALIZED
Definition: abstract_jb.c:54

Function Documentation

◆ ast_jb_conf_default()

void ast_jb_conf_default ( struct ast_jb_conf conf)

Sets the contents of an ast_jb_conf struct to the default jitterbuffer settings.

Since
12
Parameters
confWhich jitterbuffer is being set

Definition at line 890 of file abstract_jb.c.

891{
893 conf->max_size = DEFAULT_SIZE;
894 conf->resync_threshold = DEFAULT_RESYNC;
895 ast_copy_string(conf->impl, "fixed", sizeof(conf->impl));
896 conf->target_extra = DEFAULT_TARGET_EXTRA;
897}
#define DEFAULT_TARGET_EXTRA
Definition: abstract_jb.c:838
#define DEFAULT_RESYNC
Definition: abstract_jb.c:839
#define DEFAULT_SIZE
Definition: abstract_jb.c:837
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
All configuration options for http media cache.
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define AST_FLAGS_ALL
Definition: utils.h:196

References ast_clear_flag, ast_copy_string(), AST_FLAGS_ALL, DEFAULT_RESYNC, DEFAULT_SIZE, and DEFAULT_TARGET_EXTRA.

Referenced by jb_helper().

◆ ast_jb_configure()

void ast_jb_configure ( struct ast_channel chan,
const struct ast_jb_conf conf 
)

Configures a jitterbuffer on a channel.

Parameters
chanchannel to configure.
confconfiguration to apply.

Called from a channel driver when a channel is created and its jitterbuffer needs to be configured.

Definition at line 593 of file abstract_jb.c.

594{
595 memcpy(&ast_channel_jb(chan)->conf, conf, sizeof(*conf));
596}
struct ast_jb * ast_channel_jb(struct ast_channel *chan)

References ast_channel_jb().

Referenced by ast_unreal_new_channels(), console_new(), dahdi_new(), ooh323_new(), and unistim_new().

◆ ast_jb_create_framehook()

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.

Since
12
Parameters
chanWhich channel the jitterbuffer is being set on
jb_confConfiguration to use for the jitterbuffer
prefer_existingIf this is true and a jitterbuffer already exists for the channel, use the existing jitterbuffer

Definition at line 1267 of file abstract_jb.c.

1268{
1269 struct jb_framedata *framedata;
1270 struct ast_datastore *datastore = NULL;
1271 struct ast_framehook_interface interface = {
1273 .event_cb = hook_event_cb,
1274 .destroy_cb = hook_destroy_cb,
1275 };
1276 int i = 0;
1277
1278 /* If disabled, strip any existing jitterbuffer and don't replace it. */
1279 if (!strcasecmp(jb_conf->impl, "disabled")) {
1280 int *id;
1281 ast_channel_lock(chan);
1282 if ((datastore = ast_channel_datastore_find(chan, &jb_datastore, NULL))) {
1283 id = datastore->data;
1284 ast_framehook_detach(chan, *id);
1285 ast_channel_datastore_remove(chan, datastore);
1286 ast_datastore_free(datastore);
1287 }
1288 ast_channel_unlock(chan);
1289 return;
1290 }
1291
1292 if (!(framedata = ast_calloc(1, sizeof(*framedata)))) {
1293 return;
1294 }
1295
1296 if (jb_framedata_init(framedata, jb_conf)) {
1297 jb_framedata_destroy(framedata);
1298 return;
1299 }
1300
1301 interface.data = framedata;
1302
1303 ast_channel_lock(chan);
1304 i = ast_framehook_attach(chan, &interface);
1305 if (i >= 0) {
1306 int *id;
1307 if ((datastore = ast_channel_datastore_find(chan, &jb_datastore, NULL))) {
1308 /* There is already a jitterbuffer on the channel. */
1309 if (prefer_existing) {
1310 /* We prefer the existing jitterbuffer, so remove the new one and keep the old one. */
1311 ast_framehook_detach(chan, i);
1312 ast_channel_unlock(chan);
1313 return;
1314 }
1315 /* We prefer the new jitterbuffer, so strip the old one. */
1316 id = datastore->data;
1317 ast_framehook_detach(chan, *id);
1318 ast_channel_datastore_remove(chan, datastore);
1319 ast_datastore_free(datastore);
1320 }
1321
1322 if (!(datastore = ast_datastore_alloc(&jb_datastore, NULL))) {
1323 ast_framehook_detach(chan, i);
1324 ast_channel_unlock(chan);
1325 return;
1326 }
1327
1328 if (!(id = ast_calloc(1, sizeof(int)))) {
1329 ast_datastore_free(datastore);
1330 ast_framehook_detach(chan, i);
1331 ast_channel_unlock(chan);
1332 return;
1333 }
1334
1335 *id = i; /* Store off the id. The channel is still locked so it is safe to access this ptr. */
1336 datastore->data = id;
1337 ast_channel_datastore_add(chan, datastore);
1338
1340 } else {
1341 jb_framedata_destroy(framedata);
1342 framedata = NULL;
1343 }
1344 ast_channel_unlock(chan);
1345}
static void jb_framedata_destroy(struct jb_framedata *framedata)
Definition: abstract_jb.c:867
static const struct ast_datastore_info jb_datastore
Definition: abstract_jb.c:904
static struct ast_frame * hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
Definition: abstract_jb.c:953
static void hook_destroy_cb(void *framedata)
Definition: abstract_jb.c:909
static int jb_framedata_init(struct jb_framedata *framedata, struct ast_jb_conf *jb_conf)
Definition: abstract_jb.c:1227
enum queue_result id
Definition: app_queue.c:1638
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2394
#define ast_channel_lock(chan)
Definition: channel.h:2922
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2426
#define AST_JITTERBUFFER_FD
Definition: channel.h:204
#define ast_channel_unlock(chan)
Definition: channel.h:2923
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.
Definition: channel.c:2399
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
#define NULL
Definition: resample.c:96
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_set_fd(), ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_framehook_attach(), ast_framehook_detach(), AST_FRAMEHOOK_INTERFACE_VERSION, AST_JITTERBUFFER_FD, ast_datastore::data, ast_framehook_interface::data, hook_destroy_cb(), hook_event_cb(), id, jb_datastore, jb_framedata_destroy(), jb_framedata_init(), NULL, jb_framedata::timer_fd, and ast_framehook_interface::version.

Referenced by ast_jb_enable_for_channel(), and jb_helper().

◆ ast_jb_destroy()

void ast_jb_destroy ( struct ast_channel chan)

Destroys jitterbuffer on a channel.

Parameters
chanchannel.

Called from ast_channel_free() when a channel is destroyed.

Definition at line 502 of file abstract_jb.c.

503{
504 struct ast_jb *jb = ast_channel_jb(chan);
505 const struct ast_jb_impl *jbimpl = jb->impl;
506 void *jbobj = jb->jbobj;
507 struct ast_frame *f;
508
509 if (jb->logfile) {
510 fclose(jb->logfile);
511 jb->logfile = NULL;
512 }
513
515
516 if (ast_test_flag(jb, JB_CREATED)) {
517 /* Remove and free all frames still queued in jb */
518 while (jbimpl->remove(jbobj, &f) == AST_JB_IMPL_OK) {
519 ast_frfree(f);
520 }
521
522 jbimpl->destroy(jbobj);
523 jb->jbobj = NULL;
524
526
527 ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, ast_channel_name(chan));
528 }
529}
@ AST_JB_IMPL_OK
Definition: abstract_jb.h:58
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
#define ast_verb(level,...)
Data structure associated with a single frame of data.
Jitterbuffer implementation struct.
Definition: abstract_jb.h:122
jb_destroy_impl destroy
Definition: abstract_jb.h:126
char name[AST_JB_IMPL_NAME_SIZE]
Definition: abstract_jb.h:123
jb_remove_impl remove
Definition: abstract_jb.h:131
General jitterbuffer state.
Definition: abstract_jb.h:141
void * jbobj
Jitterbuffer object, passed to the implementation.
Definition: abstract_jb.h:147
struct ast_format * last_format
Voice format of the last frame in.
Definition: abstract_jb.h:153
FILE * logfile
File for frame timestamp tracing.
Definition: abstract_jb.h:155
const struct ast_jb_impl * impl
Jitterbuffer implementation to be used.
Definition: abstract_jb.h:145
#define ast_test_flag(p, flag)
Definition: utils.h:63

References ao2_cleanup, ast_channel_jb(), ast_channel_name(), ast_clear_flag, ast_frfree, AST_JB_IMPL_OK, ast_test_flag, ast_verb, ast_jb_impl::destroy, ast_jb::impl, JB_CREATED, ast_jb::jbobj, ast_jb::last_format, ast_jb::logfile, ast_jb_impl::name, NULL, and ast_jb_impl::remove.

Referenced by ast_channel_destructor().

◆ ast_jb_do_usecheck()

int ast_jb_do_usecheck ( struct ast_channel c0,
struct ast_channel c1 
)

Checks the need of a jb use in a generic bridge.

Parameters
c0first bridged channel.
c1second bridged channel.

Called from ast_generic_bridge() when two channels are entering in a bridge. The function checks the need of a jitterbuffer, depending on both channel's configuration and technology properties. As a result, this function sets appropriate internal jb flags to the channels, determining further behaviour of the bridged jitterbuffers.

Return values
zeroif there are no jitter buffers in use
non-zeroif there are

Definition at line 170 of file abstract_jb.c.

171{
172 struct ast_jb *jb0 = ast_channel_jb(c0);
173 struct ast_jb *jb1 = ast_channel_jb(c1);
174 struct ast_jb_conf *conf0 = &jb0->conf;
175 struct ast_jb_conf *conf1 = &jb1->conf;
176 int c0_wants_jitter = ast_channel_tech(c0)->properties & AST_CHAN_TP_WANTSJITTER;
177 int c0_creates_jitter = ast_channel_tech(c0)->properties & AST_CHAN_TP_CREATESJITTER;
178 int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED);
179 int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED);
180 int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED);
181 int c0_jb_created = ast_test_flag(jb0, JB_CREATED);
182 int c1_wants_jitter = ast_channel_tech(c1)->properties & AST_CHAN_TP_WANTSJITTER;
183 int c1_creates_jitter = ast_channel_tech(c1)->properties & AST_CHAN_TP_CREATESJITTER;
184 int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED);
185 int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED);
186 int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED);
187 int c1_jb_created = ast_test_flag(jb1, JB_CREATED);
188 int inuse = 0;
189
190 /* Determine whether audio going to c0 needs a jitter buffer */
191 if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) {
192 ast_set_flag(jb0, JB_USE);
193 if (!c0_jb_timebase_initialized) {
194 if (c1_jb_timebase_initialized) {
195 memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval));
196 } else {
197 gettimeofday(&jb0->timebase, NULL);
198 }
200 }
201
202 if (!c0_jb_created) {
203 jb_choose_impl(c0);
204 }
205
206 inuse = 1;
207 }
208
209 /* Determine whether audio going to c1 needs a jitter buffer */
210 if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) {
211 ast_set_flag(jb1, JB_USE);
212 if (!c1_jb_timebase_initialized) {
213 if (c0_jb_timebase_initialized) {
214 memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval));
215 } else {
216 gettimeofday(&jb1->timebase, NULL);
217 }
219 }
220
221 if (!c1_jb_created) {
222 jb_choose_impl(c1);
223 }
224
225 inuse = 1;
226 }
227
228 return inuse;
229}
static void jb_choose_impl(struct ast_channel *chan)
Definition: abstract_jb.c:148
@ AST_JB_FORCED
Definition: abstract_jb.h:46
@ AST_JB_ENABLED
Definition: abstract_jb.h:45
@ AST_CHAN_TP_WANTSJITTER
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
Definition: channel.h:960
@ AST_CHAN_TP_CREATESJITTER
Channels have this property if they can create jitter; i.e. most VoIP channels.
Definition: channel.h:965
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
General jitterbuffer configuration.
Definition: abstract_jb.h:70
struct ast_jb_conf conf
Jitterbuffer configuration.
Definition: abstract_jb.h:143
struct timeval timebase
The time the jitterbuffer was created.
Definition: abstract_jb.h:149
#define ast_set_flag(p, flag)
Definition: utils.h:70

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

◆ ast_jb_empty_and_reset()

void ast_jb_empty_and_reset ( struct ast_channel c0,
struct ast_channel c1 
)

drops all frames from a jitterbuffer and resets it

Parameters
c0one channel of a bridge
c1the other channel of the bridge

Definition at line 604 of file abstract_jb.c.

605{
606 struct ast_jb *jb0 = ast_channel_jb(c0);
607 struct ast_jb *jb1 = ast_channel_jb(c1);
608 int c0_use_jb = ast_test_flag(jb0, JB_USE);
609 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
610 int c1_use_jb = ast_test_flag(jb1, JB_USE);
611 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
612
613 if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) {
614 jb0->impl->empty_and_reset(jb0->jbobj);
615 }
616
617 if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) {
618 jb1->impl->empty_and_reset(jb1->jbobj);
619 }
620}
jb_empty_and_reset_impl empty_and_reset
Definition: abstract_jb.h:133

References ast_channel_jb(), ast_test_flag, ast_jb_impl::empty_and_reset, ast_jb::impl, JB_CREATED, JB_USE, and ast_jb::jbobj.

◆ ast_jb_enable_for_channel()

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 configuration.

Since
12.0
Parameters
chanWhich channel is being set up

Definition at line 585 of file abstract_jb.c.

586{
587 struct ast_jb_conf conf = ast_channel_jb(chan)->conf;
589 ast_jb_create_framehook(chan, &conf, 1);
590 }
591}
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.
Definition: abstract_jb.c:1267

References ast_channel_jb(), ast_jb_create_framehook(), AST_JB_ENABLED, ast_test_flag, and ast_jb::conf.

Referenced by bridge_channel_internal_join().

◆ ast_jb_get_and_deliver()

void ast_jb_get_and_deliver ( struct ast_channel c0,
struct ast_channel c1 
)

Deliver the queued frames that should be delivered now for both channels.

Parameters
c0first bridged channel.
c1second 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 using ast_write() each of the channels.

Definition at line 336 of file abstract_jb.c.

337{
338 struct ast_jb *jb0 = ast_channel_jb(c0);
339 struct ast_jb *jb1 = ast_channel_jb(c1);
340 int c0_use_jb = ast_test_flag(jb0, JB_USE);
341 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
342 int c1_use_jb = ast_test_flag(jb1, JB_USE);
343 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
344
345 if (c0_use_jb && c0_jb_is_created)
347
348 if (c1_use_jb && c1_jb_is_created)
350}
static void jb_get_and_deliver(struct ast_channel *chan)
Definition: abstract_jb.c:353

References ast_channel_jb(), ast_test_flag, JB_CREATED, jb_get_and_deliver(), and JB_USE.

◆ ast_jb_get_config()

void ast_jb_get_config ( const struct ast_channel chan,
struct ast_jb_conf conf 
)

Copies a channel's jitterbuffer configuration.

Parameters
chanchannel.
confdestination.

Definition at line 599 of file abstract_jb.c.

600{
601 memcpy(conf, &ast_channel_jb((struct ast_channel *) chan)->conf, sizeof(*conf));
602}
Main Channel structure associated with a channel.

References ast_channel_jb().

◆ ast_jb_get_impl()

const struct ast_jb_impl * ast_jb_get_impl ( enum ast_jb_type  type)

Definition at line 820 of file abstract_jb.c.

821{
822 int i;
823 for (i = 0; i < ARRAY_LEN(avail_impl); i++) {
824 if (avail_impl[i].type == type) {
825 return &avail_impl[i];
826 }
827 }
828 return NULL;
829}
static const struct ast_jb_impl avail_impl[]
Definition: abstract_jb.c:87
static const char type[]
Definition: chan_ooh323.c:109
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, avail_impl, NULL, and type.

Referenced by jb_framedata_init().

◆ ast_jb_get_when_to_wakeup()

int ast_jb_get_when_to_wakeup ( struct ast_channel c0,
struct ast_channel c1,
int  time_left 
)

Calculates the time, left to the closest delivery moment in a bridge.

Parameters
c0first bridged channel.
c1second bridged channel.
time_leftbridge time limit, or -1 if not set.

Called from ast_generic_bridge() to determine the maximum time to wait for activity in ast_waitfor_n() call. If neihter of the channels is using jb, this function returns the time limit passed.

Returns
maximum time to wait.

Definition at line 231 of file abstract_jb.c.

232{
233 struct ast_jb *jb0 = ast_channel_jb(c0);
234 struct ast_jb *jb1 = ast_channel_jb(c1);
235 int c0_use_jb = ast_test_flag(jb0, JB_USE);
236 int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
237 int c1_use_jb = ast_test_flag(jb1, JB_USE);
238 int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
239 int wait, wait0, wait1;
240 struct timeval tv_now;
241
242 if (time_left == 0) {
243 /* No time left - the bridge will be retried */
244 /* TODO: Test disable this */
245 /*return 0;*/
246 }
247
248 if (time_left < 0) {
249 time_left = INT_MAX;
250 }
251
252 gettimeofday(&tv_now, NULL);
253
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;
256
257 wait = wait0 < wait1 ? wait0 : wait1;
258 wait = wait < time_left ? wait : time_left;
259
260 if (wait == INT_MAX) {
261 wait = -1;
262 } else if (wait < 1) {
263 /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */
264 wait = 1;
265 }
266
267 return wait;
268}
static long get_now(struct ast_jb *jb, struct timeval *tv)
Definition: abstract_jb.c:532
long next
The time the next frame should be played.
Definition: abstract_jb.h:151

References ast_channel_jb(), ast_test_flag, get_now(), JB_CREATED, JB_USE, ast_jb::next, and NULL.

◆ ast_jb_put()

int ast_jb_put ( struct ast_channel chan,
struct ast_frame f 
)

Puts a frame into a channel jitterbuffer.

Parameters
chanchannel.
fframe.

Called from ast_generic_bridge() to put a frame into a channel's jitterbuffer. The function will successfuly enqueue a frame if and only if:

  1. the channel is using a jitterbuffer (as determined by ast_jb_do_usecheck()),
  2. the frame's type is AST_FRAME_VOICE,
  3. the frame has timing info set and has length >= 2 ms,
  4. there is no some internal error happened (like failed memory allocation). Frames, successfuly queued, should be delivered by the channel's jitterbuffer, when their delivery time has came. Frames, not successfuly queued, should be delivered immediately. Dropped by the jb implementation frames are considered successfuly enqueued as far as they should not be delivered at all.
Return values
0if the frame was queued
-1if not

Definition at line 271 of file abstract_jb.c.

272{
273 struct ast_jb *jb = ast_channel_jb(chan);
274 const struct ast_jb_impl *jbimpl = jb->impl;
275 void *jbobj = jb->jbobj;
276 struct ast_frame *frr;
277 long now = 0;
278
279 if (!ast_test_flag(jb, JB_USE))
280 return -1;
281
282 if (f->frametype != AST_FRAME_VOICE) {
284 jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now);
285 jbimpl->force_resync(jbobj);
286 }
287
288 return -1;
289 }
290
291 /* We consider an enabled jitterbuffer should receive frames with valid timing info. */
292 if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) {
293 ast_log(LOG_WARNING, "%s received frame with invalid timing info: "
294 "has_timing_info=%u, len=%ld, ts=%ld, src=%s\n",
296 return -1;
297 }
298
299 frr = ast_frdup(f);
300
301 if (!frr) {
302 ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", ast_channel_name(chan));
303 return -1;
304 }
305
306 if (!ast_test_flag(jb, JB_CREATED)) {
307 if (create_jb(chan, frr)) {
308 ast_frfree(frr);
309 /* Disable the jitterbuffer */
311 return -1;
312 }
313
315 return 0;
316 } else {
317 now = get_now(jb, NULL);
318 if (jbimpl->put(jbobj, frr, now) != AST_JB_IMPL_OK) {
319 jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
320 ast_frfree(frr);
321 /*return -1;*/
322 /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't
323 be delivered at all */
324 return 0;
325 }
326
327 jb->next = jbimpl->next(jbobj);
328
329 jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
330
331 return 0;
332 }
333}
static int create_jb(struct ast_channel *chan, struct ast_frame *first_frame)
Definition: abstract_jb.c:413
#define jb_framelog(...)
Macros for the frame log files.
Definition: abstract_jb.c:130
#define ast_log
Definition: astobj2.c:42
@ AST_FRFLAG_HAS_TIMING_INFO
#define AST_FRAME_DTMF
#define ast_frdup(fr)
Copies a frame.
@ AST_FRAME_VOICE
#define LOG_ERROR
#define LOG_WARNING
enum ast_frame_type frametype
const char * src
jb_next_impl next
Definition: abstract_jb.h:130
jb_put_impl put
Definition: abstract_jb.h:128
jb_force_resynch_impl force_resync
Definition: abstract_jb.h:132

References ast_channel_jb(), ast_channel_name(), ast_clear_flag, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frdup, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, AST_JB_IMPL_OK, ast_log, ast_set_flag, ast_test_flag, create_jb(), ast_jb_impl::force_resync, ast_frame::frametype, get_now(), ast_jb::impl, JB_CREATED, jb_framelog, JB_USE, ast_jb::jbobj, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb_impl::next, ast_jb::next, NULL, ast_jb_impl::put, ast_frame::src, and ast_frame::ts.

◆ ast_jb_read_conf()

int ast_jb_read_conf ( struct ast_jb_conf conf,
const char *  varname,
const char *  value 
)

Sets jitterbuffer configuration property.

Parameters
confconfiguration to store the property in.
varnameproperty name.
valueproperty value.

Called from a channel driver to build a jitterbuffer configuration typically when reading a configuration file. It is not necessary for a channel driver to know each of the jb configuration property names. The jitterbuffer itself knows them. The channel driver can pass each config var it reads through this function. It will return 0 if the variable was consumed from the jb conf.

Returns
zero if the property was set to the configuration, -1 if not.

Definition at line 545 of file abstract_jb.c.

546{
547 int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1;
548 const char *name;
549 int tmp;
550
551 if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) {
552 return -1;
553 }
554
555 name = varname + prefixlen;
556
557 if (!strcasecmp(name, AST_JB_CONF_ENABLE)) {
559 } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) {
561 } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) {
562 if ((tmp = atoi(value)) > 0)
563 conf->max_size = tmp;
564 } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) {
565 if ((tmp = atoi(value)) > 0)
566 conf->resync_threshold = tmp;
567 } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) {
569 snprintf(conf->impl, sizeof(conf->impl), "%s", value);
570 } else if (!strcasecmp(name, AST_JB_CONF_TARGET_EXTRA)) {
571 if (sscanf(value, "%30d", &tmp) == 1) {
572 conf->target_extra = tmp;
573 }
574 } else if (!strcasecmp(name, AST_JB_CONF_LOG)) {
576 } else if (!strcasecmp(name, AST_JB_CONF_SYNC_VIDEO)) {
578 } else {
579 return -1;
580 }
581
582 return 0;
583}
#define AST_JB_CONF_ENABLE
Definition: abstract_jb.h:86
#define AST_JB_CONF_RESYNCH_THRESHOLD
Definition: abstract_jb.h:89
#define AST_JB_CONF_IMPL
Definition: abstract_jb.h:91
#define AST_JB_CONF_LOG
Definition: abstract_jb.h:92
@ AST_JB_SYNC_VIDEO
Definition: abstract_jb.h:48
@ AST_JB_LOG
Definition: abstract_jb.h:47
#define AST_JB_CONF_SYNC_VIDEO
Definition: abstract_jb.h:93
#define AST_JB_CONF_FORCE
Definition: abstract_jb.h:87
#define AST_JB_CONF_MAX_SIZE
Definition: abstract_jb.h:88
#define AST_JB_CONF_TARGET_EXTRA
Definition: abstract_jb.h:90
#define AST_JB_CONF_PREFIX
Definition: abstract_jb.h:85
static int tmp()
Definition: bt_open.c:389
static const char name[]
Definition: format_mp3.c:68
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
int value
Definition: syslog.c:37
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94

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_SYNC_VIDEO, AST_JB_CONF_TARGET_EXTRA, AST_JB_ENABLED, AST_JB_FORCED, AST_JB_LOG, AST_JB_SYNC_VIDEO, ast_set2_flag, ast_strlen_zero(), ast_true(), name, tmp(), and value.

Referenced by jb_helper(), process_dahdi(), reload_config(), and store_config_core().

◆ create_jb()

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

Definition at line 413 of file abstract_jb.c.

414{
415 struct ast_jb *jb = ast_channel_jb(chan);
416 struct ast_jb_conf *jbconf = &jb->conf;
417 const struct ast_jb_impl *jbimpl = jb->impl;
418 void *jbobj;
419 long now;
420 char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1];
421 char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp;
422 int res;
423
424 jbobj = jb->jbobj = jbimpl->create(jbconf);
425 if (!jbobj) {
426 ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", ast_channel_name(chan));
427 return -1;
428 }
429
430 now = get_now(jb, NULL);
431 res = jbimpl->put_first(jbobj, frr, now);
432
433 /* The result of putting the first frame should not differ from OK. However, its possible
434 some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */
435 if (res != AST_JB_IMPL_OK) {
436 ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", ast_channel_name(chan));
437 /*
438 jbimpl->destroy(jbobj);
439 return -1;
440 */
441 }
442
443 /* Init next */
444 jb->next = jbimpl->next(jbobj);
445
446 /* Init last format for a first time. */
447 jb->last_format = ao2_bump(frr->subclass.format);
448
449 /* Create a frame log file */
450 if (ast_test_flag(jbconf, AST_JB_LOG)) {
451 struct ast_channel *bridged = ast_channel_bridge_peer(chan);
452 char safe_logfile[30] = "/tmp/logfile-XXXXXX";
453 int safe_fd;
454
455 snprintf(name2, sizeof(name2), "%s", ast_channel_name(chan));
456 while ((tmp = strchr(name2, '/'))) {
457 *tmp = '#';
458 }
459
460 /* We should always have bridged chan if a jitterbuffer is in use */
461 ast_assert(bridged != NULL);
462
463 snprintf(name1, sizeof(name1), "%s", ast_channel_name(bridged));
464 while ((tmp = strchr(name1, '/'))) {
465 *tmp = '#';
466 }
467
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));
474 jb->logfile = NULL;
475 if (safe_fd > -1) {
476 close(safe_fd);
477 }
478 }
479
480 if (res == AST_JB_IMPL_OK) {
481 jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
482 now, frr->ts, frr->len);
483 } else {
484 jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
485 now, frr->ts, frr->len);
486 }
487
488 ast_channel_cleanup(bridged);
489 }
490
491 ast_verb(3, "%s jitterbuffer created on channel %s\n", jbimpl->name, ast_channel_name(chan));
492
493 /* Free the frame if it has not been queued in the jb */
494 if (res != AST_JB_IMPL_OK) {
495 ast_frfree(frr);
496 }
497
498 return 0;
499}
#define AST_JB_IMPL_NAME_SIZE
Definition: abstract_jb.h:64
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10564
#define AST_CHANNEL_NAME
Definition: channel.h:171
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
int errno
struct ast_jb jb
jb_put_first_impl put_first
Definition: abstract_jb.h:127
jb_create_impl create
Definition: abstract_jb.h:125
#define ast_assert(a)
Definition: utils.h:739

References ao2_bump, ast_assert, ast_channel_bridge_peer(), ast_channel_cleanup, ast_channel_jb(), AST_CHANNEL_NAME, ast_channel_name(), ast_frfree, AST_JB_IMPL_NAME_SIZE, AST_JB_IMPL_OK, AST_JB_LOG, ast_log, ast_test_flag, ast_verb, ast_jb::conf, ast_jb_impl::create, errno, ast_frame_subclass::format, get_now(), ast_jb::impl, ast_channel::jb, jb_framelog, ast_jb::jbobj, ast_jb::last_format, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_jb::logfile, ast_jb_impl::name, ast_jb_impl::next, ast_jb::next, NULL, ast_jb_impl::put_first, ast_frame::subclass, tmp(), and ast_frame::ts.

Referenced by ast_jb_put().

◆ datastore_destroy_cb()

static void datastore_destroy_cb ( void *  data)
static

Definition at line 899 of file abstract_jb.c.

899 {
900 ast_free(data);
901 ast_debug(1, "JITTERBUFFER datastore destroyed\n");
902}
#define ast_free(a)
Definition: astmm.h:180
#define ast_debug(level,...)
Log a DEBUG message.

References ast_debug, ast_free, and ast_frame::data.

◆ get_now()

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

Definition at line 532 of file abstract_jb.c.

533{
534 struct timeval now;
535
536 if (!when) {
537 when = &now;
538 gettimeofday(when, NULL);
539 }
540
541 return ast_tvdiff_ms(*when, jb->timebase);
542}
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107

References ast_tvdiff_ms(), NULL, and ast_jb::timebase.

Referenced by ast_jb_get_when_to_wakeup(), ast_jb_put(), create_jb(), and jb_get_and_deliver().

◆ hook_destroy_cb()

static void hook_destroy_cb ( void *  framedata)
static

Definition at line 909 of file abstract_jb.c.

910{
911 ast_debug(1, "JITTERBUFFER hook destroyed\n");
912 jb_framedata_destroy((struct jb_framedata *) framedata);
913}

References ast_debug, and jb_framedata_destroy().

Referenced by ast_jb_create_framehook().

◆ hook_event_cb()

static struct ast_frame * hook_event_cb ( struct ast_channel chan,
struct ast_frame frame,
enum ast_framehook_event  event,
void *  data 
)
static

Definition at line 953 of file abstract_jb.c.

954{
955 struct jb_framedata *framedata = data;
956 struct timeval now_tv;
957 int64_t relative_frame_start;
958 int putframe = 0; /* signifies if audio frame was placed into the buffer or not */
959
960 switch (event) {
962 break;
966 return frame;
967 }
968
969 if (ast_channel_fdno(chan) == AST_JITTERBUFFER_FD && framedata->timer) {
970 if (ast_timer_ack(framedata->timer, 1) < 0) {
971 ast_log(LOG_ERROR, "Failed to acknowledge timer in jitter buffer\n");
972 return frame;
973 }
974 }
975
976 /*
977 * If the frame has been requeued (for instance when the translate core returns
978 * more than one frame) then if the frame is late we want to immediately return
979 * it. Otherwise attempt to insert it into the jitterbuffer.
980 *
981 * If the frame is requeued and late then in all likely hood it's a frame that
982 * that was previously retrieved from the jitterbuffer, passed to the translate
983 * core, and then put back into the channel read queue. Even if it had not been
984 * in the jitterbuffer prior to now it needs to be the next frame "out".
985 *
986 * However late arriving frames that have not been requeued (i.e. regular frames)
987 * need to be passed to the jitterbuffer so they can be appropriately dropped. As
988 * well any requeued frames that are not late should be put into the jitterbuffer.
989 */
990 if (!frame || (ast_test_flag(frame, AST_FRFLAG_REQUEUED) &&
991 framedata->jb_impl->is_late(framedata->jb_obj, frame->ts))) {
992 return frame;
993 }
994
995 if (ast_test_flag(&framedata->jb_conf, AST_JB_SYNC_VIDEO)) {
996 if (frame->frametype == AST_FRAME_VOICE) {
997 /* Store the stream identifier for the audio stream so we can associate the incoming RTCP SR
998 * with the correct stream sync structure.
999 */
1000 framedata->audio_stream_id = frame->stream_num;
1001 } else if (frame->frametype == AST_FRAME_RTCP && frame->subclass.integer == AST_RTP_RTCP_SR) {
1002 struct ast_rtp_rtcp_report *rtcp_report = frame->data.ptr;
1003 struct jb_stream_sync *stream_sync = NULL;
1004
1005 /* Determine which stream this RTCP is in regards to */
1006 if (framedata->audio_stream_id == frame->stream_num) {
1007 stream_sync = &framedata->audio_stream_sync;
1008 } else if (framedata->video_stream_id == frame->stream_num) {
1009 stream_sync = &framedata->video_stream_sync;
1010 }
1011
1012 if (stream_sync) {
1013 /* Store the RTP and NTP timestamp mapping so we can derive an NTP timestamp for each frame */
1014 stream_sync->timestamp = rtcp_report->sender_information.rtp_timestamp;
1015 stream_sync->ntp = rtcp_report->sender_information.ntp_timestamp;
1016 }
1017 } else if (frame->frametype == AST_FRAME_VIDEO) {
1018 /* If a video frame is late according to the audio timestamp don't stash it away, just return it.
1019 * If however it is ahead then we keep it until such time as the audio catches up.
1020 */
1021 struct ast_frame *jbframe;
1022
1023 framedata->video_stream_id = frame->stream_num;
1024
1025 /* If no timing information is available we can't store this away, so just let it through now */
1027 return frame;
1028 }
1029
1030 /* To ensure that the video starts when the audio starts we only start allowing frames through once
1031 * audio starts flowing.
1032 */
1033 if (framedata->audio_flowing) {
1034 struct timeval video_timestamp;
1035
1036 video_timestamp = jitterbuffer_frame_get_ntp_timestamp(&framedata->video_stream_sync, frame);
1037 if (ast_tvdiff_ms(framedata->last_audio_ntp_timestamp, video_timestamp) >= 0) {
1038 return frame;
1039 }
1040 }
1041
1042 /* To prevent the early frame buffer from growing uncontrolled we impose a maximum count that it can
1043 * get to. If this is reached then we drop a video frame, which should cause the receiver to ask for a
1044 * new key frame.
1045 */
1046 if (framedata->early_frame_count == MAXIMUM_EARLY_FRAME_COUNT) {
1047 jbframe = AST_LIST_REMOVE_HEAD(&framedata->early_frames, frame_list);
1048 framedata->early_frame_count--;
1049 ast_frfree(jbframe);
1050 }
1051
1052 jbframe = ast_frisolate(frame);
1053 if (!jbframe) {
1054 /* If we can't isolate the frame the safest thing we can do is return it, even if the A/V sync
1055 * may be off.
1056 */
1057 return frame;
1058 }
1059
1060 AST_LIST_INSERT_TAIL(&framedata->early_frames, jbframe, frame_list);
1061 framedata->early_frame_count++;
1062 return &ast_null_frame;
1063 }
1064 }
1065
1066 now_tv = ast_tvnow();
1067 relative_frame_start = ast_tvdiff_ms(now_tv, framedata->start_tv);
1068 if (relative_frame_start < 0) {
1069 /*
1070 * The only way for this to happen is if the system time has
1071 * stepped backwards between the time framedata->start_tv was
1072 * set and now. Think an ntpd or systemd-timesyncd adjustment.
1073 *
1074 * Just pass the frame through.
1075 */
1076 return frame;
1077 }
1078
1079 if (frame->frametype == AST_FRAME_VOICE) {
1080 int res;
1081 struct ast_frame *jbframe;
1082
1083 if (!ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO) || frame->len < 2 || frame->ts < 0) {
1084 /* only frames with timing info can enter the jitterbuffer */
1085 return frame;
1086 }
1087
1088 jbframe = ast_frisolate(frame);
1089 ao2_replace(framedata->last_format, frame->subclass.format);
1090
1091 if (frame->len && (frame->len != framedata->timer_interval)) {
1092 framedata->timer_interval = frame->len;
1093 ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
1094 }
1095 if (!framedata->first) {
1096 framedata->first = 1;
1097 res = framedata->jb_impl->put_first(framedata->jb_obj, jbframe, relative_frame_start);
1098 } else {
1099 res = framedata->jb_impl->put(framedata->jb_obj, jbframe, relative_frame_start);
1100 }
1101
1102 if (res == AST_JB_IMPL_OK) {
1103 if (jbframe != frame) {
1104 ast_frfree(frame);
1105 }
1106 frame = &ast_null_frame;
1107 } else if (jbframe != frame) {
1108 ast_frfree(jbframe);
1109 }
1110 putframe = 1;
1111 }
1112
1113 if (frame->frametype == AST_FRAME_NULL) {
1114 int res;
1115 long next = framedata->jb_impl->next(framedata->jb_obj);
1116
1117 /* If relative_frame_start is earlier than the next expected output frame
1118 * from the jitterbuffer we may choose to pass on retrieving
1119 * a frame during this read iteration. The only exception
1120 * to this rule is when an audio frame is placed into the buffer
1121 * and the time for the next frame to come out of the buffer is
1122 * at least within the timer_interval of the next output frame. By
1123 * doing this we are able to feed off the timing of the input frames
1124 * and only rely on our jitterbuffer timer when frames are dropped.
1125 * During testing, this hybrid form of timing gave more reliable results. */
1126 if (relative_frame_start < next) {
1127 long int diff = next - relative_frame_start;
1128 if (!putframe) {
1129 return frame;
1130 } else if (diff >= framedata->timer_interval) {
1131 return frame;
1132 }
1133 }
1134
1135 ast_frfree(frame);
1136 frame = &ast_null_frame;
1137 res = framedata->jb_impl->get(framedata->jb_obj, &frame, relative_frame_start, framedata->timer_interval);
1138 switch (res) {
1139 case AST_JB_IMPL_OK:
1140 /* got it, and pass it through */
1141 break;
1142 case AST_JB_IMPL_DROP:
1143 ast_frfree(frame);
1144 frame = &ast_null_frame;
1145 break;
1146 case AST_JB_IMPL_INTERP:
1147 if (framedata->last_format) {
1148 struct ast_frame tmp = { 0, };
1149
1150 tmp.frametype = AST_FRAME_VOICE;
1151 tmp.subclass.format = framedata->last_format;
1152 /* example: 8000hz / (1000 / 20ms) = 160 samples */
1153 tmp.samples = ast_format_get_sample_rate(framedata->last_format) / (1000 / framedata->timer_interval);
1154 tmp.delivery = ast_tvadd(framedata->start_tv, ast_samp2tv(next, 1000));
1155 tmp.offset = AST_FRIENDLY_OFFSET;
1156 tmp.src = "func_jitterbuffer interpolation";
1157 ast_frfree(frame);
1158 frame = ast_frdup(&tmp);
1159 break;
1160 }
1161 /* else fall through */
1163 ast_frfree(frame);
1164 frame = &ast_null_frame;
1165 break;
1166 }
1167 }
1168
1169 if (frame->frametype == AST_FRAME_CONTROL) {
1170 struct ast_frame *early_frame;
1171
1172 switch(frame->subclass.integer) {
1173 case AST_CONTROL_HOLD:
1174 case AST_CONTROL_UNHOLD:
1178 framedata->jb_impl->force_resync(framedata->jb_obj);
1179 /* Since we are resyncing go ahead and clear out the video frames too */
1180 while ((early_frame = AST_LIST_REMOVE_HEAD(&framedata->early_frames, frame_list))) {
1181 ast_frfree(early_frame);
1182 }
1183 framedata->audio_flowing = 0;
1184 framedata->early_frame_count = 0;
1185 break;
1186 default:
1187 break;
1188 }
1189 }
1190
1191 /* If a voice frame is being passed through see if we need to add any additional frames to it */
1192 if (ast_test_flag(&framedata->jb_conf, AST_JB_SYNC_VIDEO) && frame->frametype == AST_FRAME_VOICE) {
1193 AST_LIST_HEAD_NOLOCK(, ast_frame) additional_frames;
1194 struct ast_frame *early_frame;
1195
1196 /* We store the last NTP timestamp for the audio given to the core so that subsequents frames which
1197 * are late can be passed immediately through (this will occur for video frames which are returned here)
1198 */
1200 framedata->audio_flowing = 1;
1201
1202 AST_LIST_HEAD_INIT_NOLOCK(&additional_frames);
1203
1204 AST_LIST_TRAVERSE_SAFE_BEGIN(&framedata->early_frames, early_frame, frame_list) {
1205 struct timeval early_timestamp = jitterbuffer_frame_get_ntp_timestamp(&framedata->video_stream_sync, early_frame);
1206 int diff = ast_tvdiff_ms(framedata->last_audio_ntp_timestamp, early_timestamp);
1207
1208 /* If this frame is from the past we need to include it with the audio frame that is going
1209 * out.
1210 */
1211 if (diff >= 0) {
1213 framedata->early_frame_count--;
1214 AST_LIST_INSERT_TAIL(&additional_frames, early_frame, frame_list);
1215 }
1216 }
1218
1219 /* Append any additional frames we may want to include (such as video) */
1220 AST_LIST_NEXT(frame, frame_list) = AST_LIST_FIRST(&additional_frames);
1221 }
1222
1223 return frame;
1224}
#define MAXIMUM_EARLY_FRAME_COUNT
Definition: abstract_jb.c:59
static struct timeval jitterbuffer_frame_get_ntp_timestamp(const struct jb_stream_sync *stream_sync, const struct ast_frame *frame)
Definition: abstract_jb.c:915
@ AST_JB_IMPL_INTERP
Definition: abstract_jb.h:60
@ AST_JB_IMPL_NOFRAME
Definition: abstract_jb.h:61
@ AST_JB_IMPL_DROP
Definition: abstract_jb.h:59
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
int ast_channel_fdno(const struct ast_channel *chan)
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
@ AST_FRAMEHOOK_EVENT_ATTACHED
Definition: framehook.h:154
@ AST_FRAMEHOOK_EVENT_DETACHED
Definition: framehook.h:155
@ AST_FRAMEHOOK_EVENT_WRITE
Definition: framehook.h:153
@ AST_FRAMEHOOK_EVENT_READ
Definition: framehook.h:152
@ AST_FRFLAG_REQUEUED
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
@ AST_FRAME_VIDEO
@ AST_FRAME_NULL
@ AST_FRAME_RTCP
@ AST_FRAME_CONTROL
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_T38_PARAMETERS
@ AST_CONTROL_HOLD
@ AST_CONTROL_SRCCHANGE
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:225
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
#define AST_RTP_RTCP_SR
Definition: rtp_engine.h:318
struct ast_format * format
struct ast_frame_subclass subclass
union ast_frame::@226 data
struct ast_frame * next
jb_get_impl get
Definition: abstract_jb.h:129
jb_is_late_impl is_late
Definition: abstract_jb.h:134
An object that represents data sent during a SR/RR RTCP report.
Definition: rtp_engine.h:356
struct ast_rtp_rtcp_report::@273 sender_information
unsigned int rtp_timestamp
Definition: rtp_engine.h:362
struct timeval ntp_timestamp
Definition: rtp_engine.h:361
Definition: astman.c:222
struct ast_jb_conf jb_conf
Definition: abstract_jb.c:849
struct jb_stream_sync audio_stream_sync
Definition: abstract_jb.c:857
void * jb_obj
Definition: abstract_jb.c:864
int audio_stream_id
Definition: abstract_jb.c:856
struct jb_stream_sync video_stream_sync
Definition: abstract_jb.c:859
struct timeval start_tv
Definition: abstract_jb.c:850
struct ast_format * last_format
Definition: abstract_jb.c:851
unsigned int early_frame_count
Definition: abstract_jb.c:861
struct timeval last_audio_ntp_timestamp
Definition: abstract_jb.c:862
struct ast_timer * timer
Definition: abstract_jb.c:852
int video_stream_id
Definition: abstract_jb.c:858
int timer_interval
Definition: abstract_jb.c:853
struct jb_framedata::@292 early_frames
const struct ast_jb_impl * jb_impl
Definition: abstract_jb.c:848
struct timeval ntp
Definition: abstract_jb.c:844
unsigned int timestamp
Definition: abstract_jb.c:843
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 ...
Definition: time.h:282
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
Definition: timing.c:171
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
Definition: timing.c:166

References ao2_replace, ast_channel_fdno(), AST_CONTROL_HOLD, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_UNHOLD, ast_format_get_sample_rate(), AST_FRAME_CONTROL, AST_FRAME_NULL, AST_FRAME_RTCP, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRAMEHOOK_EVENT_ATTACHED, AST_FRAMEHOOK_EVENT_DETACHED, AST_FRAMEHOOK_EVENT_READ, AST_FRAMEHOOK_EVENT_WRITE, ast_frdup, AST_FRFLAG_HAS_TIMING_INFO, AST_FRFLAG_REQUEUED, ast_frfree, AST_FRIENDLY_OFFSET, ast_frisolate, AST_JB_IMPL_DROP, AST_JB_IMPL_INTERP, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_OK, AST_JB_SYNC_VIDEO, AST_JITTERBUFFER_FD, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_HEAD_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_NEXT, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, ast_null_frame, AST_RTP_RTCP_SR, ast_samp2tv(), ast_test_flag, ast_timer_ack(), ast_timer_set_rate(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), jb_framedata::audio_flowing, jb_framedata::audio_stream_id, jb_framedata::audio_stream_sync, ast_frame::data, jb_framedata::early_frame_count, jb_framedata::early_frames, jb_framedata::first, ast_jb_impl::force_resync, ast_frame_subclass::format, ast_frame::frametype, ast_jb_impl::get, ast_frame_subclass::integer, ast_jb_impl::is_late, jb_framedata::jb_conf, jb_framedata::jb_impl, jb_framedata::jb_obj, jitterbuffer_frame_get_ntp_timestamp(), jb_framedata::last_audio_ntp_timestamp, jb_framedata::last_format, ast_frame::len, LOG_ERROR, MAXIMUM_EARLY_FRAME_COUNT, ast_jb_impl::next, ast_frame::next, jb_stream_sync::ntp, ast_rtp_rtcp_report::ntp_timestamp, NULL, ast_frame::ptr, ast_jb_impl::put, ast_jb_impl::put_first, ast_rtp_rtcp_report::rtp_timestamp, ast_rtp_rtcp_report::sender_information, jb_framedata::start_tv, ast_frame::stream_num, ast_frame::subclass, jb_framedata::timer, jb_framedata::timer_interval, jb_stream_sync::timestamp, tmp(), ast_frame::ts, jb_framedata::video_stream_id, and jb_framedata::video_stream_sync.

Referenced by ast_jb_create_framehook().

◆ jb_choose_impl()

static void jb_choose_impl ( struct ast_channel chan)
static

Definition at line 148 of file abstract_jb.c.

149{
150 struct ast_jb *jb = ast_channel_jb(chan);
151 struct ast_jb_conf *jbconf = &jb->conf;
152 const struct ast_jb_impl *test_impl;
153 int i, avail_impl_count = ARRAY_LEN(avail_impl);
154
156
157 if (ast_strlen_zero(jbconf->impl)) {
158 return;
159 }
160
161 for (i = 0; i < avail_impl_count; i++) {
162 test_impl = &avail_impl[i];
163 if (!strcasecmp(jbconf->impl, test_impl->name)) {
164 jb->impl = test_impl;
165 return;
166 }
167 }
168}
static int default_impl
Definition: abstract_jb.c:118
char impl[AST_JB_IMPL_NAME_SIZE]
Name of the jitterbuffer implementation to be used.
Definition: abstract_jb.h:78

References ARRAY_LEN, ast_channel_jb(), ast_strlen_zero(), avail_impl, ast_jb::conf, default_impl, ast_jb_conf::impl, ast_jb::impl, and ast_jb_impl::name.

Referenced by ast_jb_do_usecheck().

◆ jb_create_adaptive()

static void * jb_create_adaptive ( struct ast_jb_conf general_config)
static

Definition at line 727 of file abstract_jb.c.

728{
729 jb_conf jbconf;
730 jitterbuf *adaptivejb;
731
732 adaptivejb = jb_new();
733 if (adaptivejb) {
734 jbconf.max_jitterbuf = general_config->max_size;
735 jbconf.resync_threshold = general_config->resync_threshold;
736 jbconf.max_contig_interp = 10;
737 jbconf.target_extra = general_config->target_extra;
738 jb_setconf(adaptivejb, &jbconf);
739 }
740
741 return adaptivejb;
742}
jitterbuf * jb_new(void)
new jitterbuf
Definition: jitterbuf.c:86
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
set jitterbuf conf
Definition: jitterbuf.c:825
long target_extra
amount of additional jitterbuffer adjustment
Definition: abstract_jb.h:80
long max_size
Max size of the jitterbuffer implementation.
Definition: abstract_jb.h:74
long resync_threshold
Resynchronization threshold of the jitterbuffer implementation.
Definition: abstract_jb.h:76
long target_extra
Definition: jitterbuf.h:72
long max_jitterbuf
Definition: jitterbuf.h:69
long resync_threshold
Definition: jitterbuf.h:70
long max_contig_interp
Definition: jitterbuf.h:71

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.

◆ jb_create_fixed()

static void * jb_create_fixed ( struct ast_jb_conf general_config)
static

Definition at line 625 of file abstract_jb.c.

626{
627 struct fixed_jb_conf conf;
628
629 conf.jbsize = general_config->max_size;
630 conf.resync_threshold = general_config->resync_threshold;
631
632 return fixed_jb_new(&conf);
633}
struct fixed_jb * fixed_jb_new(struct fixed_jb_conf *conf)

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

◆ jb_destroy_adaptive()

static void jb_destroy_adaptive ( void *  jb)
static

Definition at line 745 of file abstract_jb.c.

746{
747 jitterbuf *adaptivejb = (jitterbuf *) jb;
748
749 jb_destroy(adaptivejb);
750}
void jb_destroy(jitterbuf *jb)
destroy jitterbuf
Definition: jitterbuf.c:99

References jb_destroy().

◆ jb_destroy_fixed()

static void jb_destroy_fixed ( void *  jb)
static

Definition at line 635 of file abstract_jb.c.

636{
637 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
638
639 /* Ensure the fixed jb is empty - otherwise it will raise an ASSERT */
641
642 /* destroy the jb */
643 fixed_jb_destroy(fixedjb);
644}
static void jb_empty_and_reset_fixed(void *jb)
Definition: abstract_jb.c:710
void fixed_jb_destroy(struct fixed_jb *jb)
private fixed_jb structure

References fixed_jb_destroy(), and jb_empty_and_reset_fixed().

◆ jb_empty_and_reset_adaptive()

static void jb_empty_and_reset_adaptive ( void *  jb)
static

Definition at line 808 of file abstract_jb.c.

809{
810 jitterbuf *adaptivejb = jb;
811 jb_frame f;
812
813 while (jb_getall(adaptivejb, &f) == JB_OK) {
814 ast_frfree(f.data);
815 }
816
817 jb_reset(adaptivejb);
818}
void jb_reset(jitterbuf *jb)
reset jitterbuf
Definition: jitterbuf.c:72
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
unconditionally get frames from jitterbuf until empty
Definition: jitterbuf.c:801
@ JB_OK
Definition: jitterbuf.h:51
void * data
Definition: jitterbuf.h:102

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

◆ jb_empty_and_reset_fixed()

static void jb_empty_and_reset_fixed ( void *  jb)
static

Definition at line 710 of file abstract_jb.c.

711{
712 struct fixed_jb *fixedjb = jb;
713 struct fixed_jb_frame f;
714
715 while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) {
716 ast_frfree(f.data);
717 }
718}
int fixed_jb_remove(struct fixed_jb *jb, struct fixed_jb_frame *frameout)
@ FIXED_JB_OK

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

Referenced by jb_destroy_fixed().

◆ jb_force_resynch_adaptive()

static void jb_force_resynch_adaptive ( void *  jb)
static

Definition at line 804 of file abstract_jb.c.

805{
806}

◆ jb_force_resynch_fixed()

static void jb_force_resynch_fixed ( void *  jb)
static

Definition at line 703 of file abstract_jb.c.

704{
705 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
706
708}
void fixed_jb_set_force_resynch(struct fixed_jb *jb)

References fixed_jb_set_force_resynch().

◆ jb_framedata_destroy()

static void jb_framedata_destroy ( struct jb_framedata framedata)
static

Definition at line 867 of file abstract_jb.c.

868{
869 struct ast_frame *frame;
870
871 if (framedata->timer) {
872 ast_timer_close(framedata->timer);
873 framedata->timer = NULL;
874 }
875 if (framedata->jb_impl && framedata->jb_obj) {
876 struct ast_frame *f;
877 while (framedata->jb_impl->remove(framedata->jb_obj, &f) == AST_JB_IMPL_OK) {
878 ast_frfree(f);
879 }
880 framedata->jb_impl->destroy(framedata->jb_obj);
881 framedata->jb_obj = NULL;
882 }
883 ao2_cleanup(framedata->last_format);
884 while ((frame = AST_LIST_REMOVE_HEAD(&framedata->early_frames, frame_list))) {
885 ast_frfree(frame);
886 }
887 ast_free(framedata);
888}
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
Definition: timing.c:154

References ao2_cleanup, ast_free, ast_frfree, AST_JB_IMPL_OK, AST_LIST_REMOVE_HEAD, ast_timer_close(), ast_jb_impl::destroy, jb_framedata::early_frames, jb_framedata::jb_impl, jb_framedata::jb_obj, jb_framedata::last_format, NULL, ast_jb_impl::remove, and jb_framedata::timer.

Referenced by ast_jb_create_framehook(), and hook_destroy_cb().

◆ jb_framedata_init()

static int jb_framedata_init ( struct jb_framedata framedata,
struct ast_jb_conf jb_conf 
)
static

Definition at line 1227 of file abstract_jb.c.

1228{
1229 int jb_impl_type = DEFAULT_TYPE;
1230 /* Initialize defaults */
1231 framedata->timer_fd = -1;
1232 memcpy(&framedata->jb_conf, jb_conf, sizeof(*jb_conf));
1233
1234 /* Figure out implementation type from the configuration implementation string */
1235 if (!ast_strlen_zero(jb_conf->impl)) {
1236 if (!strcasecmp(jb_conf->impl, "fixed")) {
1237 jb_impl_type = AST_JB_FIXED;
1238 } else if (!strcasecmp(jb_conf->impl, "adaptive")) {
1239 jb_impl_type = AST_JB_ADAPTIVE;
1240 } else {
1241 ast_log(LOG_WARNING, "Unknown Jitterbuffer type %s. Failed to create jitterbuffer.\n", jb_conf->impl);
1242 return -1;
1243 }
1244 }
1245
1246 if (!(framedata->jb_impl = ast_jb_get_impl(jb_impl_type))) {
1247 return -1;
1248 }
1249
1250 if (!(framedata->timer = ast_timer_open())) {
1251 return -1;
1252 }
1253
1254 framedata->audio_stream_id = -1;
1255 framedata->video_stream_id = -1;
1257 framedata->timer_fd = ast_timer_fd(framedata->timer);
1259 ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
1260 framedata->start_tv = ast_tvnow();
1261
1262 framedata->jb_obj = framedata->jb_impl->create(&framedata->jb_conf);
1263 return 0;
1264}
#define DEFAULT_TIMER_INTERVAL
Definition: abstract_jb.c:836
#define DEFAULT_TYPE
Definition: abstract_jb.c:840
const struct ast_jb_impl * ast_jb_get_impl(enum ast_jb_type type)
Definition: abstract_jb.c:820
@ AST_JB_ADAPTIVE
Definition: abstract_jb.h:53
@ AST_JB_FIXED
Definition: abstract_jb.h:52
struct ast_timer * ast_timer_open(void)
Open a timer.
Definition: timing.c:122
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
Definition: timing.c:161

References AST_JB_ADAPTIVE, AST_JB_FIXED, ast_jb_get_impl(), AST_LIST_HEAD_INIT_NOLOCK, ast_log, ast_strlen_zero(), ast_timer_fd(), ast_timer_open(), ast_timer_set_rate(), ast_tvnow(), jb_framedata::audio_stream_id, ast_jb_impl::create, DEFAULT_TIMER_INTERVAL, DEFAULT_TYPE, jb_framedata::early_frames, jb_framedata::jb_conf, jb_framedata::jb_impl, jb_framedata::jb_obj, LOG_WARNING, jb_framedata::start_tv, jb_framedata::timer, jb_framedata::timer_fd, jb_framedata::timer_interval, and jb_framedata::video_stream_id.

Referenced by ast_jb_create_framehook().

◆ jb_get_adaptive()

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

Definition at line 770 of file abstract_jb.c.

771{
772 jitterbuf *adaptivejb = (jitterbuf *) jb;
773 jb_frame frame = { .data = &ast_null_frame };
774 int res;
775
776 res = jb_get(adaptivejb, &frame, now, interpl);
777 *fout = frame.data;
778
779 return adaptive_to_abstract_code[res];
780}
static const int adaptive_to_abstract_code[]
Definition: abstract_jb.c:123
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!...
Definition: jitterbuf.c:785

References adaptive_to_abstract_code, ast_null_frame, jb_frame::data, and jb_get().

◆ jb_get_and_deliver()

static void jb_get_and_deliver ( struct ast_channel chan)
static

Definition at line 353 of file abstract_jb.c.

354{
355 struct ast_jb *jb = ast_channel_jb(chan);
356 const struct ast_jb_impl *jbimpl = jb->impl;
357 void *jbobj = jb->jbobj;
358 struct ast_frame *f, finterp = { .frametype = AST_FRAME_VOICE, };
359 long now;
360 int interpolation_len, res;
361
362 now = get_now(jb, NULL);
363 jb->next = jbimpl->next(jbobj);
364 if (now < jb->next) {
365 jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next);
366 return;
367 }
368
369 while (now >= jb->next) {
370 interpolation_len = ast_format_get_default_ms(jb->last_format);
371
372 res = jbimpl->get(jbobj, &f, now, interpolation_len);
373
374 switch (res) {
375 case AST_JB_IMPL_OK:
376 /* deliver the frame */
377 ast_write(chan, f);
378 case AST_JB_IMPL_DROP:
379 jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
380 now, jb_get_actions[res], f->ts, f->len);
382 ast_frfree(f);
383 break;
385 /* interpolate a frame */
386 f = &finterp;
387 f->subclass.format = jb->last_format;
388 f->samples = interpolation_len * 8;
389 f->src = "JB interpolation";
390 f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000));
392 /* deliver the interpolated frame */
393 ast_write(chan, f);
394 jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
395 break;
398 "AST_JB_IMPL_NOFRAME is returned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
399 jbimpl->name, now, jb->next, jbimpl->next(jbobj));
400 jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now);
401 return;
402 default:
403 ast_log(LOG_ERROR, "This should never happen!\n");
404 ast_assert("JB type unknown" == NULL);
405 break;
406 }
407
408 jb->next = jbimpl->next(jbobj);
409 }
410}
static const char *const jb_get_actions[]
Definition: abstract_jb.c:127
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.
Definition: channel.c:5144
unsigned int ast_format_get_default_ms(const struct ast_format *format)
Get the default framing size (in milliseconds) for a format.
Definition: format.c:359
struct timeval delivery

References ao2_replace, ast_assert, ast_channel_jb(), ast_format_get_default_ms(), AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, AST_JB_IMPL_DROP, AST_JB_IMPL_INTERP, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_OK, ast_log, ast_samp2tv(), ast_tvadd(), ast_write(), ast_frame::delivery, ast_frame_subclass::format, ast_frame::frametype, ast_jb_impl::get, get_now(), ast_jb::impl, jb_framelog, jb_get_actions, 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::next, NULL, 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().

◆ jb_get_fixed()

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

Definition at line 669 of file abstract_jb.c.

670{
671 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
672 struct fixed_jb_frame frame = { .data = &ast_null_frame };
673 int res;
674
675 res = fixed_jb_get(fixedjb, &frame, now, interpl);
676 *fout = frame.data;
677
678 return fixed_to_abstract_code[res];
679}
static const int fixed_to_abstract_code[]
Definition: abstract_jb.c:121
int fixed_jb_get(struct fixed_jb *jb, struct fixed_jb_frame *frame, long now, long interpl)

References ast_null_frame, fixed_jb_frame::data, fixed_jb_get(), and fixed_to_abstract_code.

◆ jb_is_late_adaptive()

static int jb_is_late_adaptive ( void *  jb,
long  ts 
)
static

Definition at line 831 of file abstract_jb.c.

832{
833 return jb_is_late(jb, ts);
834}
int jb_is_late(jitterbuf *jb, long ts)
Checks if the given time stamp is late.
Definition: jitterbuf.c:846

References jb_is_late().

◆ jb_is_late_fixed()

static int jb_is_late_fixed ( void *  jb,
long  ts 
)
static

Definition at line 720 of file abstract_jb.c.

721{
722 return fixed_jb_is_late(jb, ts);
723}
int fixed_jb_is_late(struct fixed_jb *jb, long ts)
Checks if the given time stamp is late.

References fixed_jb_is_late(), and fixed_jb_frame::ts.

◆ jb_next_adaptive()

static long jb_next_adaptive ( void *  jb)
static

Definition at line 783 of file abstract_jb.c.

784{
785 jitterbuf *adaptivejb = (jitterbuf *) jb;
786
787 return jb_next(adaptivejb);
788}
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...
Definition: jitterbuf.c:767

References jb_next().

◆ jb_next_fixed()

static long jb_next_fixed ( void *  jb)
static

Definition at line 682 of file abstract_jb.c.

683{
684 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
685
686 return fixed_jb_next(fixedjb);
687}
long fixed_jb_next(struct fixed_jb *jb)

References fixed_jb_next().

◆ jb_put_adaptive()

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

Definition at line 759 of file abstract_jb.c.

760{
761 jitterbuf *adaptivejb = (jitterbuf *) jb;
762 int res;
763
764 res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
765
766 return adaptive_to_abstract_code[res];
767}
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
Definition: jitterbuf.c:525
@ JB_TYPE_VOICE
Definition: jitterbuf.h:62

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

Referenced by jb_put_first_adaptive().

◆ jb_put_first_adaptive()

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

Definition at line 753 of file abstract_jb.c.

754{
755 return jb_put_adaptive(jb, fin, now);
756}
static int jb_put_adaptive(void *jb, struct ast_frame *fin, long now)
Definition: abstract_jb.c:759

References jb_put_adaptive().

◆ jb_put_first_fixed()

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

Definition at line 647 of file abstract_jb.c.

648{
649 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
650 int res;
651
652 res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now);
653
654 return fixed_to_abstract_code[res];
655}
int fixed_jb_put_first(struct fixed_jb *jb, void *data, long ms, long ts, long now)

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

◆ jb_put_fixed()

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

Definition at line 658 of file abstract_jb.c.

659{
660 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
661 int res;
662
663 res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now);
664
665 return fixed_to_abstract_code[res];
666}
int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)

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

◆ jb_remove_adaptive()

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

Definition at line 791 of file abstract_jb.c.

792{
793 jitterbuf *adaptivejb = (jitterbuf *) jb;
794 jb_frame frame;
795 int res;
796
797 res = jb_getall(adaptivejb, &frame);
798 *fout = frame.data;
799
800 return adaptive_to_abstract_code[res];
801}

References adaptive_to_abstract_code, jb_frame::data, and jb_getall().

◆ jb_remove_fixed()

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

Definition at line 690 of file abstract_jb.c.

691{
692 struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
693 struct fixed_jb_frame frame;
694 int res;
695
696 res = fixed_jb_remove(fixedjb, &frame);
697 *fout = frame.data;
698
699 return fixed_to_abstract_code[res];
700}

References fixed_jb_frame::data, fixed_jb_remove(), and fixed_to_abstract_code.

◆ jitterbuffer_frame_get_ntp_timestamp()

static struct timeval jitterbuffer_frame_get_ntp_timestamp ( const struct jb_stream_sync stream_sync,
const struct ast_frame frame 
)
static

Definition at line 915 of file abstract_jb.c.

916{
917 int timestamp_diff;
918 unsigned int rate;
919
920 /* It's possible for us to receive frames before we receive the information allowing
921 * us to do NTP/RTP timestamp calculations. Since the information isn't available we
922 * can't generate one and give an empty timestamp.
923 */
924 if (ast_tvzero(stream_sync->ntp)) {
925 return ast_tv(0, 0);
926 }
927
928 /* Convert the Asterisk timestamp into an RTP timestamp, and then based on the difference we can
929 * determine how many samples are in the frame and how long has elapsed since the synchronization
930 * RTP and NTP timestamps were received giving us the NTP timestamp for this frame.
931 */
932 if (frame->frametype == AST_FRAME_VOICE) {
933 rate = ast_rtp_get_rate(frame->subclass.format);
934 timestamp_diff = (frame->ts * (rate / 1000)) - stream_sync->timestamp;
935 } else {
936 /* Video is special - internally we reference it as 1000 to preserve the RTP timestamp but
937 * it is actually 90000, this is why we can just directly subtract the timestamp.
938 */
939 rate = 90000;
940 timestamp_diff = frame->ts - stream_sync->timestamp;
941 }
942
943 if (timestamp_diff < 0) {
944 /* It's possible for us to be asked for an NTP timestamp from before our latest
945 * RTCP SR report. To handle this we subtract so we go back in time.
946 */
947 return ast_tvsub(stream_sync->ntp, ast_samp2tv(abs(timestamp_diff), rate));
948 } else {
949 return ast_tvadd(stream_sync->ntp, ast_samp2tv(timestamp_diff, rate));
950 }
951}
#define abs(x)
Definition: f2c.h:195
int ast_rtp_get_rate(const struct ast_format *format)
Retrieve the sample rate of a format according to RTP specifications.
Definition: rtp_engine.c:4108
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2297
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235

References abs, AST_FRAME_VOICE, ast_rtp_get_rate(), ast_samp2tv(), ast_tv(), ast_tvadd(), ast_tvsub(), and ast_tvzero().

Referenced by hook_event_cb().

Variable Documentation

◆ adaptive_to_abstract_code

const int adaptive_to_abstract_code[]
static

◆ avail_impl

const struct ast_jb_impl avail_impl[]
static

Definition at line 87 of file abstract_jb.c.

Referenced by ast_jb_get_impl(), and jb_choose_impl().

◆ default_impl

int default_impl = 0
static

Definition at line 118 of file abstract_jb.c.

Referenced by jb_choose_impl().

◆ fixed_to_abstract_code

const int fixed_to_abstract_code[]
static

◆ jb_datastore

const struct ast_datastore_info jb_datastore
static
Initial value:
= {
.type = "jitterbuffer",
}
static void datastore_destroy_cb(void *data)
Definition: abstract_jb.c:899

Definition at line 904 of file abstract_jb.c.

Referenced by ast_jb_create_framehook().

◆ jb_get_actions

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

Definition at line 127 of file abstract_jb.c.

Referenced by jb_get_and_deliver().