Sun May 20 06:33:53 2012

Asterisk developer's documentation


func_jitterbuffer.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2011, Digium, Inc.
00005  *
00006  * David Vossel <dvossel@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Put a jitterbuffer on the read side of a channel
00022  *
00023  * \author David Vossel <dvossel@digium.com>
00024  *
00025  * \ingroup functions
00026  */
00027 
00028 /*** MODULEINFO
00029    <support_level>core</support_level>
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 /*** DOCUMENTATION
00045    <function name="JITTERBUFFER" language="en_US">
00046       <synopsis>
00047          Add a Jitterbuffer to the Read side of the channel.  This dejitters the audio stream before it reaches the Asterisk core. This is a write only function.
00048       </synopsis>
00049       <syntax>
00050          <parameter name="jitterbuffer type" required="true">
00051             <para>Jitterbuffer type can be either <literal>fixed</literal> or <literal>adaptive</literal>.</para>
00052             <para>Used as follows. </para>
00053             <para>Set(JITTERBUFFER(type)=max_size[,resync_threshold[,target_extra]])</para>
00054             <para>Set(JITTERBUFFER(type)=default) </para>
00055          </parameter>
00056       </syntax>
00057       <description>
00058          <para>max_size: Defaults to 200 ms</para>
00059          <para>Length in milliseconds of buffer.</para>
00060          <para> </para>
00061          <para>resync_threshold: Defaults to 1000ms </para>
00062          <para>The length in milliseconds over which a timestamp difference will result in resyncing the jitterbuffer. </para>
00063          <para> </para>
00064          <para>target_extra: Defaults to 40ms</para>
00065          <para>This option only affects the adaptive jitterbuffer. It represents the amount time in milliseconds by which the new jitter buffer will pad its size.</para>
00066          <para> </para>
00067          <para>Examples:</para>
00068          <para>exten => 1,1,Set(JITTERBUFFER(fixed)=default);Fixed with defaults. </para>
00069          <para>exten => 1,1,Set(JITTERBUFFER(fixed)=200);Fixed with max size 200ms, default resync threshold and target extra. </para>
00070          <para>exten => 1,1,Set(JITTERBUFFER(fixed)=200,1500);Fixed with max size 200ms resync threshold 1500. </para>
00071          <para>exten => 1,1,Set(JITTERBUFFER(adaptive)=default);Adaptive with defaults. </para>
00072          <para>exten => 1,1,Set(JITTERBUFFER(adaptive)=200,,60);Adaptive with max size 200ms, default resync threshold and 40ms target extra. </para>
00073       </description>
00074    </function>
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; /* ms between deliveries */
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 /* set defaults */
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    /* Initialize defaults */
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    /* Now check user options to see if any of the defaults need to change. */
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    /* now that all the user parsing is done and nothing will change, create the jb obj */
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; /* signifies if audio frame was placed into the buffer or not */
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          /* only frames with timing info can enter the jitterbuffer */
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       /* If now is earlier than the next expected output frame
00265        * from the jitterbuffer we may choose to pass on retrieving
00266        * a frame during this read iteration.  The only exception
00267        * to this rule is when an audio frame is placed into the buffer
00268        * and the time for the next frame to come out of the buffer is
00269        * at least within the timer_interval of the next output frame. By
00270        * doing this we are able to feed off the timing of the input frames
00271        * and only rely on our jitterbuffer timer when frames are dropped.
00272        * During testing, this hybrid form of timing gave more reliable results. */
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          /* got it, and pass it through */
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             /* example: 8000hz / (1000 / 20ms) = 160 samples */
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          /* else fall through */
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; /* Store off the id. The channel is still locked so it is safe to access this ptr. */
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 

Generated on Sun May 20 06:33:53 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6