54 JB_TIMEBASE_INITIALIZED = (1 << 1),
59 #define MAXIMUM_EARLY_FRAME_COUNT 200
64 static void *jb_create_fixed(
struct ast_jb_conf *general_config);
65 static void jb_destroy_fixed(
void *jb);
66 static int jb_put_first_fixed(
void *jb,
struct ast_frame *fin,
long now);
67 static int jb_put_fixed(
void *jb,
struct ast_frame *fin,
long now);
68 static int jb_get_fixed(
void *jb,
struct ast_frame **fout,
long now,
long interpl);
69 static long jb_next_fixed(
void *jb);
70 static int jb_remove_fixed(
void *jb,
struct ast_frame **fout);
71 static void jb_force_resynch_fixed(
void *jb);
72 static void jb_empty_and_reset_fixed(
void *jb);
73 static int jb_is_late_fixed(
void *jb,
long ts);
75 static void * jb_create_adaptive(
struct ast_jb_conf *general_config);
76 static void jb_destroy_adaptive(
void *jb);
77 static int jb_put_first_adaptive(
void *jb,
struct ast_frame *fin,
long now);
78 static int jb_put_adaptive(
void *jb,
struct ast_frame *fin,
long now);
79 static int jb_get_adaptive(
void *jb,
struct ast_frame **fout,
long now,
long interpl);
80 static long jb_next_adaptive(
void *jb);
81 static int jb_remove_adaptive(
void *jb,
struct ast_frame **fout);
82 static void jb_force_resynch_adaptive(
void *jb);
83 static void jb_empty_and_reset_adaptive(
void *jb);
84 static int jb_is_late_adaptive(
void *jb,
long ts);
91 .create = jb_create_fixed,
92 .destroy = jb_destroy_fixed,
93 .put_first = jb_put_first_fixed,
96 .next = jb_next_fixed,
97 .remove = jb_remove_fixed,
98 .force_resync = jb_force_resynch_fixed,
99 .empty_and_reset = jb_empty_and_reset_fixed,
100 .is_late = jb_is_late_fixed,
104 .type = AST_JB_ADAPTIVE,
105 .create = jb_create_adaptive,
106 .destroy = jb_destroy_adaptive,
107 .put_first = jb_put_first_adaptive,
108 .put = jb_put_adaptive,
109 .get = jb_get_adaptive,
110 .next = jb_next_adaptive,
111 .remove = jb_remove_adaptive,
112 .force_resync = jb_force_resynch_adaptive,
113 .empty_and_reset = jb_empty_and_reset_adaptive,
114 .is_late = jb_is_late_adaptive,
118 static int default_impl = 0;
121 static const int fixed_to_abstract_code[] =
122 {AST_JB_IMPL_OK, AST_JB_IMPL_DROP, AST_JB_IMPL_INTERP, AST_JB_IMPL_NOFRAME};
123 static const int adaptive_to_abstract_code[] =
124 {AST_JB_IMPL_OK, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_NOFRAME, AST_JB_IMPL_INTERP, AST_JB_IMPL_DROP, AST_JB_IMPL_OK};
127 static 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); \
139 static void jb_choose_impl(
struct ast_channel *chan);
140 static void jb_get_and_deliver(
struct ast_channel *chan);
142 static long get_now(
struct ast_jb *jb,
struct timeval *tv);
148 static void jb_choose_impl(
struct ast_channel *chan)
150 struct ast_jb *jb = ast_channel_jb(chan);
153 int i, avail_impl_count = ARRAY_LEN(avail_impl);
155 jb->
impl = &avail_impl[default_impl];
157 if (ast_strlen_zero(jbconf->
impl)) {
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;
172 struct ast_jb *jb0 = ast_channel_jb(c0);
173 struct ast_jb *jb1 = ast_channel_jb(c1);
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);
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);
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) {
199 ast_set_flag(jb0, 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) {
211 ast_set_flag(jb1, JB_USE);
212 if (!c1_jb_timebase_initialized) {
213 if (c0_jb_timebase_initialized) {
218 ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED);
221 if (!c1_jb_created) {
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;
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) {
273 struct ast_jb *jb = ast_channel_jb(chan);
275 void *jbobj = jb->
jbobj;
279 if (!ast_test_flag(jb, JB_USE))
283 if (f->
frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) {
284 jb_framelog(
"JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now);
285 jbimpl->force_resync(jbobj);
293 ast_log(LOG_WARNING,
"%s received frame with invalid timing info: "
294 "has_timing_info=%u, len=%ld, ts=%ld, src=%s\n",
302 ast_log(LOG_ERROR,
"Failed to isolate frame for the jitterbuffer on channel '%s'\n", ast_channel_name(chan));
306 if (!ast_test_flag(jb, JB_CREATED)) {
307 if (create_jb(chan, frr)) {
310 ast_clear_flag(jb, JB_USE);
314 ast_set_flag(jb, JB_CREATED);
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);
327 jb->
next = jbimpl->next(jbobj);
329 jb_framelog(
"JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->
ts, frr->
len);
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);
345 if (c0_use_jb && c0_jb_is_created)
346 jb_get_and_deliver(c0);
348 if (c1_use_jb && c1_jb_is_created)
349 jb_get_and_deliver(c1);
353 static void jb_get_and_deliver(
struct ast_channel *chan)
355 struct ast_jb *jb = ast_channel_jb(chan);
357 void *jbobj = jb->
jbobj;
360 int interpolation_len, res;
362 now = get_now(jb, NULL);
363 jb->
next = jbimpl->next(jbobj);
364 if (now < jb->next) {
369 while (now >= jb->
next) {
372 res = jbimpl->get(jbobj, &f, now, interpolation_len);
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);
384 case AST_JB_IMPL_INTERP:
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);
396 case AST_JB_IMPL_NOFRAME:
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);
403 ast_log(LOG_ERROR,
"This should never happen!\n");
404 ast_assert(
"JB type unknown" == NULL);
408 jb->
next = jbimpl->next(jbobj);
415 struct ast_jb *jb = ast_channel_jb(chan);
424 jbobj = jb->
jbobj = jbimpl->create(jbconf);
426 ast_log(LOG_WARNING,
"Failed to create jitterbuffer on channel '%s'\n", ast_channel_name(chan));
430 now = get_now(jb, NULL);
431 res = jbimpl->put_first(jbobj, frr, now);
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));
444 jb->
next = jbimpl->next(jbobj);
450 if (ast_test_flag(jbconf, AST_JB_LOG)) {
452 char safe_logfile[30] =
"/tmp/logfile-XXXXXX";
455 snprintf(name2,
sizeof(name2),
"%s", ast_channel_name(chan));
456 while ((tmp = strchr(name2,
'/'))) {
461 ast_assert(bridged != NULL);
463 snprintf(name1,
sizeof(name1),
"%s", ast_channel_name(bridged));
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));
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);
484 jb_framelog(
"JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
485 now, frr->
ts, frr->
len);
491 ast_verb(3,
"%s jitterbuffer created on channel %s\n", jbimpl->name, ast_channel_name(chan));
494 if (res != AST_JB_IMPL_OK) {
504 struct ast_jb *jb = ast_channel_jb(chan);
506 void *jbobj = jb->
jbobj;
516 if (ast_test_flag(jb, JB_CREATED)) {
518 while (jbimpl->remove(jbobj, &f) == AST_JB_IMPL_OK) {
522 jbimpl->destroy(jbobj);
525 ast_clear_flag(jb, JB_CREATED);
527 ast_verb(3,
"%s jitterbuffer destroyed on channel %s\n", jbimpl->name, ast_channel_name(chan));
532 static long get_now(
struct ast_jb *jb,
struct timeval *when)
538 gettimeofday(when, NULL);
547 int prefixlen =
sizeof(AST_JB_CONF_PREFIX) - 1;
551 if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen)) {
555 name = varname + prefixlen;
557 if (!strcasecmp(name, AST_JB_CONF_ENABLE)) {
558 ast_set2_flag(conf,
ast_true(value), AST_JB_ENABLED);
559 }
else if (!strcasecmp(name, AST_JB_CONF_FORCE)) {
560 ast_set2_flag(conf,
ast_true(value), AST_JB_FORCED);
561 }
else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) {
562 if ((tmp = atoi(value)) > 0)
564 }
else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) {
565 if ((tmp = atoi(value)) > 0)
567 }
else if (!strcasecmp(name, AST_JB_CONF_IMPL)) {
568 if (!ast_strlen_zero(value))
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) {
574 }
else if (!strcasecmp(name, AST_JB_CONF_LOG)) {
575 ast_set2_flag(conf,
ast_true(value), AST_JB_LOG);
576 }
else if (!strcasecmp(name, AST_JB_CONF_SYNC_VIDEO)) {
577 ast_set2_flag(conf,
ast_true(value), AST_JB_SYNC_VIDEO);
588 if (ast_test_flag(&conf, AST_JB_ENABLED)) {
595 memcpy(&ast_channel_jb(chan)->conf, conf,
sizeof(*conf));
601 memcpy(conf, &ast_channel_jb((
struct ast_channel *) chan)->conf,
sizeof(*conf));
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);
613 if (c0_use_jb && c0_jb_is_created && jb0->
impl->empty_and_reset) {
617 if (c1_use_jb && c1_jb_is_created && jb1->
impl->empty_and_reset) {
625 static void * jb_create_fixed(
struct ast_jb_conf *general_config)
632 return fixed_jb_new(&
conf);
635 static void jb_destroy_fixed(
void *jb)
640 jb_empty_and_reset_fixed(jb);
643 fixed_jb_destroy(fixedjb);
647 static int jb_put_first_fixed(
void *jb,
struct ast_frame *fin,
long now)
652 res = fixed_jb_put_first(fixedjb, fin, fin->
len, fin->
ts, now);
654 return fixed_to_abstract_code[res];
658 static int jb_put_fixed(
void *jb,
struct ast_frame *fin,
long now)
663 res = fixed_jb_put(fixedjb, fin, fin->
len, fin->
ts, now);
665 return fixed_to_abstract_code[res];
669 static int jb_get_fixed(
void *jb,
struct ast_frame **fout,
long now,
long interpl)
675 res = fixed_jb_get(fixedjb, &frame, now, interpl);
678 return fixed_to_abstract_code[res];
682 static long jb_next_fixed(
void *jb)
686 return fixed_jb_next(fixedjb);
690 static int jb_remove_fixed(
void *jb,
struct ast_frame **fout)
696 res = fixed_jb_remove(fixedjb, &frame);
699 return fixed_to_abstract_code[res];
703 static void jb_force_resynch_fixed(
void *jb)
707 fixed_jb_set_force_resynch(fixedjb);
710 static void jb_empty_and_reset_fixed(
void *jb)
715 while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) {
720 static int jb_is_late_fixed(
void *jb,
long ts)
727 static void *jb_create_adaptive(
struct ast_jb_conf *general_config)
745 static void jb_destroy_adaptive(
void *jb)
753 static int jb_put_first_adaptive(
void *jb,
struct ast_frame *fin,
long now)
755 return jb_put_adaptive(jb, fin, now);
759 static int jb_put_adaptive(
void *jb,
struct ast_frame *fin,
long now)
766 return adaptive_to_abstract_code[res];
770 static int jb_get_adaptive(
void *jb,
struct ast_frame **fout,
long now,
long interpl)
776 res =
jb_get(adaptivejb, &frame, now, interpl);
779 return adaptive_to_abstract_code[res];
783 static long jb_next_adaptive(
void *jb)
791 static int jb_remove_adaptive(
void *jb,
struct ast_frame **fout)
800 return adaptive_to_abstract_code[res];
804 static void jb_force_resynch_adaptive(
void *jb)
808 static void jb_empty_and_reset_adaptive(
void *jb)
813 while (
jb_getall(adaptivejb, &f) == JB_OK) {
820 const struct ast_jb_impl *ast_jb_get_impl(
enum ast_jb_type type)
823 for (i = 0; i < ARRAY_LEN(avail_impl); i++) {
824 if (avail_impl[i].type == type) {
825 return &avail_impl[i];
831 static int jb_is_late_adaptive(
void *jb,
long ts)
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
843 unsigned int timestamp;
850 struct timeval start_tv;
861 unsigned int early_frame_count;
862 struct timeval last_audio_ntp_timestamp;
867 static void jb_framedata_destroy(
struct jb_framedata *framedata)
871 if (framedata->timer) {
873 framedata->timer = NULL;
875 if (framedata->jb_impl && framedata->jb_obj) {
877 while (framedata->jb_impl->remove(framedata->jb_obj, &f) == AST_JB_IMPL_OK) {
880 framedata->jb_impl->destroy(framedata->jb_obj);
881 framedata->jb_obj = NULL;
883 ao2_cleanup(framedata->last_format);
892 ast_clear_flag(conf, AST_FLAGS_ALL);
899 static void datastore_destroy_cb(
void *
data) {
901 ast_debug(1,
"JITTERBUFFER datastore destroyed\n");
905 .
type =
"jitterbuffer",
906 .destroy = datastore_destroy_cb
909 static void hook_destroy_cb(
void *framedata)
911 ast_debug(1,
"JITTERBUFFER hook destroyed\n");
912 jb_framedata_destroy((
struct jb_framedata *) framedata);
915 static struct timeval jitterbuffer_frame_get_ntp_timestamp(const struct
jb_stream_sync *stream_sync,
const struct ast_frame *frame)
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;
971 ast_log(LOG_ERROR,
"Failed to acknowledge timer in jitter buffer\n");
991 framedata->jb_impl->is_late(framedata->jb_obj, frame->
ts))) {
995 if (ast_test_flag(&framedata->jb_conf, AST_JB_SYNC_VIDEO)) {
1000 framedata->audio_stream_id = frame->
stream_num;
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;
1014 stream_sync->timestamp = rtcp_report->sender_information.rtp_timestamp;
1015 stream_sync->ntp = rtcp_report->sender_information.ntp_timestamp;
1023 framedata->video_stream_id = frame->
stream_num;
1033 if (framedata->audio_flowing) {
1034 struct timeval video_timestamp;
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) {
1048 framedata->early_frame_count--;
1049 ast_frfree(jbframe);
1061 framedata->early_frame_count++;
1067 relative_frame_start =
ast_tvdiff_ms(now_tv, framedata->start_tv);
1068 if (relative_frame_start < 0) {
1091 if (frame->
len && (frame->
len != framedata->timer_interval)) {
1092 framedata->timer_interval = frame->
len;
1095 if (!framedata->first) {
1096 framedata->first = 1;
1097 res = framedata->jb_impl->put_first(framedata->jb_obj, jbframe, relative_frame_start);
1099 res = framedata->jb_impl->put(framedata->jb_obj, jbframe, relative_frame_start);
1102 if (res == AST_JB_IMPL_OK) {
1103 if (jbframe != frame) {
1107 }
else if (jbframe != frame) {
1108 ast_frfree(jbframe);
1115 long next = framedata->jb_impl->next(framedata->jb_obj);
1126 if (relative_frame_start < next) {
1127 long int diff = next - relative_frame_start;
1130 }
else if (diff >= framedata->timer_interval) {
1137 res = framedata->jb_impl->get(framedata->jb_obj, &frame, relative_frame_start, framedata->timer_interval);
1139 case AST_JB_IMPL_OK:
1142 case AST_JB_IMPL_DROP:
1146 case AST_JB_IMPL_INTERP:
1147 if (framedata->last_format) {
1156 tmp.
src =
"func_jitterbuffer interpolation";
1162 case AST_JB_IMPL_NOFRAME:
1178 framedata->jb_impl->force_resync(framedata->jb_obj);
1181 ast_frfree(early_frame);
1183 framedata->audio_flowing = 0;
1184 framedata->early_frame_count = 0;
1199 framedata->last_audio_ntp_timestamp = jitterbuffer_frame_get_ntp_timestamp(&framedata->audio_stream_sync, frame);
1200 framedata->audio_flowing = 1;
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);
1213 framedata->early_frame_count--;
1229 int jb_impl_type = DEFAULT_TYPE;
1231 framedata->timer_fd = -1;
1232 memcpy(&framedata->jb_conf, jb_conf,
sizeof(*jb_conf));
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;
1241 ast_log(LOG_WARNING,
"Unknown Jitterbuffer type %s. Failed to create jitterbuffer.\n", jb_conf->
impl);
1246 if (!(framedata->jb_impl = ast_jb_get_impl(jb_impl_type))) {
1254 framedata->audio_stream_id = -1;
1255 framedata->video_stream_id = -1;
1258 framedata->timer_interval = DEFAULT_TIMER_INTERVAL;
1262 framedata->jb_obj = framedata->jb_impl->create(&framedata->jb_conf);
1272 .
version = AST_FRAMEHOOK_INTERFACE_VERSION,
1273 .event_cb = hook_event_cb,
1274 .destroy_cb = hook_destroy_cb,
1279 if (!strcasecmp(jb_conf->
impl,
"disabled")) {
1281 ast_channel_lock(chan);
1283 id = datastore->
data;
1288 ast_channel_unlock(chan);
1292 if (!(framedata =
ast_calloc(1,
sizeof(*framedata)))) {
1296 if (jb_framedata_init(framedata, jb_conf)) {
1297 jb_framedata_destroy(framedata);
1301 interface.
data = framedata;
1303 ast_channel_lock(chan);
1309 if (prefer_existing) {
1312 ast_channel_unlock(chan);
1316 id = datastore->
data;
1322 if (!(datastore = ast_datastore_alloc(&jb_datastore, NULL))) {
1324 ast_channel_unlock(chan);
1331 ast_channel_unlock(chan);
1336 datastore->
data = id;
1341 jb_framedata_destroy(framedata);
1344 ast_channel_unlock(chan);
An object that represents data sent during a SR/RR RTCP report.
Main Channel structure associated with a channel.
#define ast_frdup(fr)
Copies a frame.
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
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.
#define MAXIMUM_EARLY_FRAME_COUNT
private fixed_jb structure
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
const struct ast_jb_impl * impl
Jitterbuffer implementation to be used.
void ast_jb_destroy(struct ast_channel *chan)
Destroys jitterbuffer on a channel.
ast_framehook_event
These are the types of events that the framehook's event callback can receive.
void ast_jb_empty_and_reset(struct ast_channel *c0, struct ast_channel *c1)
drops all frames from a jitterbuffer and resets it
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
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
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
Structure for a data store type.
struct ast_timer * ast_timer_open(void)
Open a timer.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Structure for a data store object.
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.
struct ast_jb_conf conf
Jitterbuffer configuration.
enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frame, long now, long interpl)
get a frame for time now (receiver's time) return value is one of JB_OK: You've got frame! JB_DROP: H...
Common implementation-independent jitterbuffer stuff.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
struct ast_frame_subclass subclass
All configuration options for http media cache.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
jitterbuf * jb_new(void)
new jitterbuf
long resync_threshold
Resynchronization threshold of the jitterbuffer implementation.
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
#define jb_framelog(...)
Macros for the frame log files.
long jb_next(jitterbuf *jb)
when is the next frame due out, in receiver's time (0=EMPTY) This value may change as frames are adde...
void ast_jb_conf_default(struct ast_jb_conf *conf)
Sets the contents of an ast_jb_conf struct to the default jitterbuffer settings.
int ast_jb_do_usecheck(struct ast_channel *c0, struct ast_channel *c1)
Checks the need of a jb use in a generic bridge.
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
int jb_is_late(jitterbuf *jb, long ts)
Checks if the given time stamp is late.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Asterisk internal frame definitions.
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 ...
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...
void * jbobj
Jitterbuffer object, passed to the implementation.
long target_extra
amount of additional jitterbuffer adjustment
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
char impl[AST_JB_IMPL_NAME_SIZE]
Name of the jitterbuffer implementation to be used.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
jitterbuf: an application-independent jitterbuffer jitterbuf.c
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.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
set jitterbuf conf
int ast_jb_put(struct ast_channel *chan, struct ast_frame *f)
Puts a frame into a channel jitterbuffer.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
void ast_jb_get_config(const struct ast_channel *chan, struct ast_jb_conf *conf)
Copies a channel's jitterbuffer configuration.
General jitterbuffer state.
union ast_frame::@224 data
#define ast_calloc(num, len)
A wrapper for calloc()
FILE * logfile
File for frame timestamp tracing.
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
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.
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
Jitterbuffering algorithm.
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
int ast_rtp_get_rate(const struct ast_format *format)
Retrieve the sample rate of a format according to RTP specifications.
struct ast_frame ast_null_frame
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.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
Data structure associated with a single frame of data.
int fixed_jb_is_late(struct fixed_jb *jb, long ts)
Checks if the given time stamp is late.
struct ast_format * last_format
Voice format of the last frame in.
#define AST_JITTERBUFFER_FD
Handy terminal functions for vt* terms.
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
enum ast_frame_type frametype
Channels have this property if they can create jitter; i.e. most VoIP channels.
void jb_destroy(jitterbuf *jb)
destroy jitterbuf
struct ast_format * format
struct timeval timebase
The time the jitterbuffer was created.
Pluggable RTP Architecture.
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
unconditionally get frames from jitterbuf until empty
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
long max_size
Max size of the jitterbuffer implementation.
Jitterbuffer implementation struct.
General jitterbuffer configuration.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Timing source management.
long next
The time the next frame should be played.
void jb_reset(jitterbuf *jb)
reset jitterbuf