00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 356042 $")
00035
00036 #include "asterisk/module.h"
00037 #include "asterisk/channel.h"
00038 #include "asterisk/framehook.h"
00039 #include "asterisk/pbx.h"
00040 #include "asterisk/abstract_jb.h"
00041 #include "asterisk/timing.h"
00042 #include "asterisk/app.h"
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #define DEFAULT_TIMER_INTERVAL 20
00078 #define DEFAULT_SIZE 200
00079 #define DEFAULT_TARGET_EXTRA 40
00080 #define DEFAULT_RESYNC 1000
00081 #define DEFAULT_TYPE AST_JB_FIXED
00082
00083 struct jb_framedata {
00084 const struct ast_jb_impl *jb_impl;
00085 struct ast_jb_conf jb_conf;
00086 struct timeval start_tv;
00087 struct ast_format last_format;
00088 struct ast_timer *timer;
00089 int timer_interval;
00090 int timer_fd;
00091 int first;
00092 void *jb_obj;
00093 };
00094
00095 static void jb_framedata_destroy(struct jb_framedata *framedata)
00096 {
00097 if (framedata->timer) {
00098 ast_timer_close(framedata->timer);
00099 framedata->timer = NULL;
00100 }
00101 if (framedata->jb_impl && framedata->jb_obj) {
00102 struct ast_frame *f;
00103 while (framedata->jb_impl->remove(framedata->jb_obj, &f) == AST_JB_IMPL_OK) {
00104 ast_frfree(f);
00105 }
00106 framedata->jb_impl->destroy(framedata->jb_obj);
00107 framedata->jb_obj = NULL;
00108 }
00109 ast_free(framedata);
00110 }
00111
00112 static void jb_conf_default(struct ast_jb_conf *conf)
00113 {
00114 conf->max_size = DEFAULT_SIZE;
00115 conf->resync_threshold = DEFAULT_RESYNC;
00116 ast_copy_string(conf->impl, "fixed", sizeof(conf->impl));
00117 conf->target_extra = DEFAULT_TARGET_EXTRA;
00118 }
00119
00120
00121 static int jb_framedata_init(struct jb_framedata *framedata, const char *data, const char *value)
00122 {
00123 int jb_impl_type = DEFAULT_TYPE;
00124
00125
00126 framedata->timer_fd = -1;
00127 jb_conf_default(&framedata->jb_conf);
00128 if (!(framedata->jb_impl = ast_jb_get_impl(jb_impl_type))) {
00129 return -1;
00130 }
00131 if (!(framedata->timer = ast_timer_open())) {
00132 return -1;
00133 }
00134 framedata->timer_fd = ast_timer_fd(framedata->timer);
00135 framedata->timer_interval = DEFAULT_TIMER_INTERVAL;
00136 ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
00137 framedata->start_tv = ast_tvnow();
00138
00139
00140
00141
00142 if (!ast_strlen_zero(data)) {
00143 if (!strcasecmp(data, "fixed")) {
00144 jb_impl_type = AST_JB_FIXED;
00145 } else if (!strcasecmp(data, "adaptive")) {
00146 jb_impl_type = AST_JB_ADAPTIVE;
00147 } else {
00148 ast_log(LOG_WARNING, "Unknown Jitterbuffer type %s. Failed to create jitterbuffer.\n", data);
00149 return -1;
00150 }
00151 ast_copy_string(framedata->jb_conf.impl, data, sizeof(framedata->jb_conf.impl));
00152 }
00153
00154 if (!ast_strlen_zero(value) && strcasecmp(value, "default")) {
00155 char *parse = ast_strdupa(value);
00156 int res = 0;
00157 AST_DECLARE_APP_ARGS(args,
00158 AST_APP_ARG(max_size);
00159 AST_APP_ARG(resync_threshold);
00160 AST_APP_ARG(target_extra);
00161 );
00162
00163 AST_STANDARD_APP_ARGS(args, parse);
00164 if (!ast_strlen_zero(args.max_size)) {
00165 res |= ast_jb_read_conf(&framedata->jb_conf,
00166 "jbmaxsize",
00167 args.max_size);
00168 }
00169 if (!ast_strlen_zero(args.resync_threshold)) {
00170 res |= ast_jb_read_conf(&framedata->jb_conf,
00171 "jbresyncthreshold",
00172 args.resync_threshold);
00173 }
00174 if (!ast_strlen_zero(args.target_extra)) {
00175 res |= ast_jb_read_conf(&framedata->jb_conf,
00176 "jbtargetextra",
00177 args.target_extra);
00178 }
00179 if (res) {
00180 ast_log(LOG_WARNING, "Invalid jitterbuffer parameters %s\n", value);
00181 }
00182 }
00183
00184
00185 framedata->jb_obj = framedata->jb_impl->create(&framedata->jb_conf, framedata->jb_conf.resync_threshold);
00186 return 0;
00187 }
00188
00189 static void datastore_destroy_cb(void *data) {
00190 ast_free(data);
00191 ast_debug(1, "JITTERBUFFER datastore destroyed\n");
00192 }
00193
00194 static const struct ast_datastore_info jb_datastore = {
00195 .type = "jitterbuffer",
00196 .destroy = datastore_destroy_cb
00197 };
00198
00199 static void hook_destroy_cb(void *framedata)
00200 {
00201 ast_debug(1, "JITTERBUFFER hook destroyed\n");
00202 jb_framedata_destroy((struct jb_framedata *) framedata);
00203 }
00204
00205 static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
00206 {
00207 struct jb_framedata *framedata = data;
00208 struct timeval now_tv;
00209 unsigned long now;
00210 int putframe = 0;
00211
00212 switch (event) {
00213 case AST_FRAMEHOOK_EVENT_READ:
00214 break;
00215 case AST_FRAMEHOOK_EVENT_ATTACHED:
00216 case AST_FRAMEHOOK_EVENT_DETACHED:
00217 case AST_FRAMEHOOK_EVENT_WRITE:
00218 return frame;
00219 }
00220
00221 if (ast_channel_fdno(chan) == AST_JITTERBUFFER_FD && framedata->timer) {
00222 ast_timer_ack(framedata->timer, 1);
00223 }
00224
00225 if (!frame) {
00226 return frame;
00227 }
00228
00229 now_tv = ast_tvnow();
00230 now = ast_tvdiff_ms(now_tv, framedata->start_tv);
00231
00232 if (frame->frametype == AST_FRAME_VOICE) {
00233 int res;
00234 struct ast_frame *jbframe;
00235
00236 if (!ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO) || frame->len < 2 || frame->ts < 0) {
00237
00238 return frame;
00239 }
00240
00241 jbframe = ast_frisolate(frame);
00242 ast_format_copy(&framedata->last_format, &frame->subclass.format);
00243
00244 if (frame->len && (frame->len != framedata->timer_interval)) {
00245 framedata->timer_interval = frame->len;
00246 ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
00247 }
00248 if (!framedata->first) {
00249 framedata->first = 1;
00250 res = framedata->jb_impl->put_first(framedata->jb_obj, jbframe, now);
00251 } else {
00252 res = framedata->jb_impl->put(framedata->jb_obj, jbframe, now);
00253 }
00254 if (res == AST_JB_IMPL_OK) {
00255 frame = &ast_null_frame;
00256 }
00257 putframe = 1;
00258 }
00259
00260 if (frame->frametype == AST_FRAME_NULL) {
00261 int res;
00262 long next = framedata->jb_impl->next(framedata->jb_obj);
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 if (now < next) {
00274 long int diff = next - now;
00275 if (!putframe) {
00276 return frame;
00277 } else if (diff >= framedata->timer_interval) {
00278 return frame;
00279 }
00280 }
00281
00282 res = framedata->jb_impl->get(framedata->jb_obj, &frame, now, framedata->timer_interval);
00283 switch (res) {
00284 case AST_JB_IMPL_OK:
00285
00286 break;
00287 case AST_JB_IMPL_DROP:
00288 ast_frfree(frame);
00289 frame = &ast_null_frame;
00290 break;
00291 case AST_JB_IMPL_INTERP:
00292 if (framedata->last_format.id) {
00293 struct ast_frame tmp = { 0, };
00294 tmp.frametype = AST_FRAME_VOICE;
00295 ast_format_copy(&tmp.subclass.format, &framedata->last_format);
00296
00297 tmp.samples = ast_format_rate(&framedata->last_format) / (1000 / framedata->timer_interval);
00298 tmp.delivery = ast_tvadd(framedata->start_tv, ast_samp2tv(next, 1000));
00299 tmp.offset = AST_FRIENDLY_OFFSET;
00300 tmp.src = "func_jitterbuffer interpolation";
00301 frame = ast_frdup(&tmp);
00302 break;
00303 }
00304
00305 case AST_JB_IMPL_NOFRAME:
00306 frame = &ast_null_frame;
00307 break;
00308 }
00309 }
00310
00311 return frame;
00312 }
00313
00314 static int jb_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00315 {
00316 struct jb_framedata *framedata;
00317 struct ast_datastore *datastore = NULL;
00318 struct ast_framehook_interface interface = {
00319 .version = AST_FRAMEHOOK_INTERFACE_VERSION,
00320 .event_cb = hook_event_cb,
00321 .destroy_cb = hook_destroy_cb,
00322 };
00323 int i = 0;
00324
00325 if (!(framedata = ast_calloc(1, sizeof(*framedata)))) {
00326 return 0;
00327 }
00328
00329 if (jb_framedata_init(framedata, data, value)) {
00330 jb_framedata_destroy(framedata);
00331 return 0;
00332 }
00333
00334 interface.data = framedata;
00335
00336 ast_channel_lock(chan);
00337 i = ast_framehook_attach(chan, &interface);
00338 if (i >= 0) {
00339 int *id;
00340 if ((datastore = ast_channel_datastore_find(chan, &jb_datastore, NULL))) {
00341 id = datastore->data;
00342 ast_framehook_detach(chan, *id);
00343 ast_channel_datastore_remove(chan, datastore);
00344 }
00345
00346 if (!(datastore = ast_datastore_alloc(&jb_datastore, NULL))) {
00347 ast_framehook_detach(chan, i);
00348 ast_channel_unlock(chan);
00349 return 0;
00350 }
00351
00352 if (!(id = ast_calloc(1, sizeof(int)))) {
00353 ast_datastore_free(datastore);
00354 ast_framehook_detach(chan, i);
00355 ast_channel_unlock(chan);
00356 return 0;
00357 }
00358
00359 *id = i;
00360 datastore->data = id;
00361 ast_channel_datastore_add(chan, datastore);
00362
00363 ast_channel_set_fd(chan, AST_JITTERBUFFER_FD, framedata->timer_fd);
00364 } else {
00365 jb_framedata_destroy(framedata);
00366 framedata = NULL;
00367 }
00368 ast_channel_unlock(chan);
00369
00370 return 0;
00371 }
00372
00373 static struct ast_custom_function jb_function = {
00374 .name = "JITTERBUFFER",
00375 .write = jb_helper,
00376 };
00377
00378 static int unload_module(void)
00379 {
00380 return ast_custom_function_unregister(&jb_function);
00381 }
00382
00383 static int load_module(void)
00384 {
00385 int res = ast_custom_function_register(&jb_function);
00386 return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
00387 }
00388
00389 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Jitter buffer for read side of channel.");
00390