Sat Apr 26 2014 22:01:35

Asterisk developer's documentation


codec_ilbc.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * The iLBC code is from The IETF code base and is copyright The Internet Society (2004)
00005  *
00006  * Copyright (C) 1999 - 2005, Digium, Inc.
00007  *
00008  * Mark Spencer <markster@digium.com>
00009  *
00010  * See http://www.asterisk.org for more information about
00011  * the Asterisk project. Please do not directly contact
00012  * any of the maintainers of this project for assistance;
00013  * the project provides a web site, mailing lists and IRC
00014  * channels for your use.
00015  *
00016  * This program is free software, distributed under the terms of
00017  * the GNU General Public License Version 2. See the LICENSE file
00018  * at the top of the source tree.
00019  */
00020 
00021 /*! \file
00022  *
00023  * \brief Translate between signed linear and Internet Low Bitrate Codec
00024  *
00025  * \ingroup codecs
00026  */
00027 
00028 /*** MODULEINFO
00029    <defaultenabled>yes</defaultenabled>
00030    <use>ilbc</use>
00031    <support_level>core</support_level>
00032  ***/
00033 
00034 #include "asterisk.h"
00035 
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 379719 $")
00037 
00038 #include "asterisk/translate.h"
00039 #include "asterisk/module.h"
00040 #include "asterisk/utils.h"
00041 
00042 #ifdef ILBC_WEBRTC
00043 #include <ilbc.h>
00044 typedef WebRtc_UWord16 ilbc_bytes;
00045 typedef WebRtc_Word16  ilbc_block;
00046 #define BUF_TYPE i16
00047 #else
00048 #include "ilbc/iLBC_encode.h"
00049 #include "ilbc/iLBC_decode.h"
00050 typedef unsigned char ilbc_bytes;
00051 typedef float         ilbc_block;
00052 #define BUF_TYPE uc
00053 #endif
00054 
00055 #define USE_ILBC_ENHANCER  0
00056 #define ILBC_MS         30
00057 /* #define ILBC_MS         20 */
00058 
00059 #define  ILBC_FRAME_LEN 50 /* apparently... */
00060 #define  ILBC_SAMPLES   240   /* 30ms at 8000 hz */
00061 #define  BUFFER_SAMPLES 8000
00062 
00063 /* Sample frame data */
00064 #include "asterisk/slin.h"
00065 #include "ex_ilbc.h"
00066 
00067 struct ilbc_coder_pvt {
00068    iLBC_Enc_Inst_t enc;
00069    iLBC_Dec_Inst_t dec;
00070    /* Enough to store a full second */
00071    int16_t buf[BUFFER_SAMPLES];
00072 };
00073 
00074 static int lintoilbc_new(struct ast_trans_pvt *pvt)
00075 {
00076    struct ilbc_coder_pvt *tmp = pvt->pvt;
00077 
00078    initEncode(&tmp->enc, ILBC_MS);
00079 
00080    return 0;
00081 }
00082 
00083 static int ilbctolin_new(struct ast_trans_pvt *pvt)
00084 {
00085    struct ilbc_coder_pvt *tmp = pvt->pvt;
00086 
00087    initDecode(&tmp->dec, ILBC_MS, USE_ILBC_ENHANCER);
00088 
00089    return 0;
00090 }
00091 
00092 /*! \brief decode a frame and store in outbuf */
00093 static int ilbctolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00094 {
00095    struct ilbc_coder_pvt *tmp = pvt->pvt;
00096    int plc_mode = 1; /* 1 = normal data, 0 = plc */
00097    /* Assuming there's space left, decode into the current buffer at
00098       the tail location.  Read in as many frames as there are */
00099    int x,i;
00100    int datalen = f->datalen;
00101    int16_t *dst = pvt->outbuf.i16;
00102    ilbc_block tmpf[ILBC_SAMPLES];
00103 
00104    if (!f->data.ptr && datalen) {
00105       ast_debug(1, "issue 16070, ILIB ERROR. data = NULL datalen = %d src = %s\n", datalen, f->src ? f->src : "no src set");
00106       f->datalen = 0;
00107       datalen = 0;
00108    }
00109 
00110    if (datalen == 0) { /* native PLC, set fake datalen and clear plc_mode */
00111       datalen = ILBC_FRAME_LEN;
00112       f->samples = ILBC_SAMPLES;
00113       plc_mode = 0;  /* do native plc */
00114       pvt->samples += ILBC_SAMPLES;
00115    }
00116 
00117    if (datalen % ILBC_FRAME_LEN) {
00118       ast_log(LOG_WARNING, "Huh?  An ilbc frame that isn't a multiple of 50 bytes long from %s (%d)?\n", f->src, datalen);
00119       return -1;
00120    }
00121 
00122    for (x=0; x < datalen ; x += ILBC_FRAME_LEN) {
00123       if (pvt->samples + ILBC_SAMPLES > BUFFER_SAMPLES) {
00124          ast_log(LOG_WARNING, "Out of buffer space\n");
00125          return -1;
00126       }
00127       iLBC_decode(tmpf, plc_mode ? f->data.ptr + x : NULL, &tmp->dec, plc_mode);
00128       for ( i=0; i < ILBC_SAMPLES; i++)
00129          dst[pvt->samples + i] = tmpf[i];
00130       pvt->samples += ILBC_SAMPLES;
00131       pvt->datalen += 2*ILBC_SAMPLES;
00132    }
00133    return 0;
00134 }
00135 
00136 /*! \brief store a frame into a temporary buffer, for later decoding */
00137 static int lintoilbc_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00138 {
00139    struct ilbc_coder_pvt *tmp = pvt->pvt;
00140 
00141    /* Just add the frames to our stream */
00142    /* XXX We should look at how old the rest of our stream is, and if it
00143       is too old, then we should overwrite it entirely, otherwise we can
00144       get artifacts of earlier talk that do not belong */
00145    memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
00146    pvt->samples += f->samples;
00147    return 0;
00148 }
00149 
00150 /*! \brief encode the temporary buffer and generate a frame */
00151 static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt)
00152 {
00153    struct ilbc_coder_pvt *tmp = pvt->pvt;
00154    int datalen = 0;
00155    int samples = 0;
00156 
00157    /* We can't work on anything less than a frame in size */
00158    if (pvt->samples < ILBC_SAMPLES)
00159       return NULL;
00160    while (pvt->samples >= ILBC_SAMPLES) {
00161       ilbc_block tmpf[ILBC_SAMPLES];
00162       int i;
00163 
00164       /* Encode a frame of data */
00165       for (i = 0 ; i < ILBC_SAMPLES ; i++)
00166          tmpf[i] = tmp->buf[samples + i];
00167       iLBC_encode( (ilbc_bytes*)pvt->outbuf.BUF_TYPE + datalen, tmpf, &tmp->enc);
00168 
00169       datalen += ILBC_FRAME_LEN;
00170       samples += ILBC_SAMPLES;
00171       pvt->samples -= ILBC_SAMPLES;
00172    }
00173 
00174    /* Move the data at the end of the buffer to the front */
00175    if (pvt->samples)
00176       memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
00177 
00178    return ast_trans_frameout(pvt, datalen, samples);
00179 }
00180 
00181 static struct ast_translator ilbctolin = {
00182    .name = "ilbctolin", 
00183    .newpvt = ilbctolin_new,
00184    .framein = ilbctolin_framein,
00185    .sample = ilbc_sample,
00186    .desc_size = sizeof(struct ilbc_coder_pvt),
00187    .buf_size = BUFFER_SAMPLES * 2,
00188    .native_plc = 1,
00189 };
00190 
00191 static struct ast_translator lintoilbc = {
00192    .name = "lintoilbc", 
00193    .newpvt = lintoilbc_new,
00194    .framein = lintoilbc_framein,
00195    .frameout = lintoilbc_frameout,
00196    .sample = slin8_sample,
00197    .desc_size = sizeof(struct ilbc_coder_pvt),
00198    .buf_size = (BUFFER_SAMPLES * ILBC_FRAME_LEN + ILBC_SAMPLES - 1) / ILBC_SAMPLES,
00199 };
00200 
00201 static int unload_module(void)
00202 {
00203    int res;
00204 
00205    res = ast_unregister_translator(&lintoilbc);
00206    res |= ast_unregister_translator(&ilbctolin);
00207 
00208    return res;
00209 }
00210 
00211 static int load_module(void)
00212 {
00213    int res;
00214 
00215    ast_format_set(&ilbctolin.src_format, AST_FORMAT_ILBC, 0);
00216    ast_format_set(&ilbctolin.dst_format, AST_FORMAT_SLINEAR, 0);
00217 
00218    ast_format_set(&lintoilbc.src_format, AST_FORMAT_SLINEAR, 0);
00219    ast_format_set(&lintoilbc.dst_format, AST_FORMAT_ILBC, 0);
00220 
00221 
00222    res = ast_register_translator(&ilbctolin);
00223    if (!res) 
00224       res=ast_register_translator(&lintoilbc);
00225    else
00226       ast_unregister_translator(&ilbctolin);
00227    if (res)
00228       return AST_MODULE_LOAD_FAILURE;
00229    return AST_MODULE_LOAD_SUCCESS;
00230 }
00231 
00232 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "iLBC Coder/Decoder");