Fri May 26 01:45:33 2006

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 #include <fcntl.h>
00029 #include <stdlib.h>
00030 #include <unistd.h>
00031 #include <netinet/in.h>
00032 #include <string.h>
00033 #include <stdio.h>
00034 
00035 #include "asterisk.h"
00036 
00037 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00038 
00039 #include "asterisk/lock.h"
00040 #include "asterisk/translate.h"
00041 #include "asterisk/module.h"
00042 #include "asterisk/logger.h"
00043 #include "asterisk/channel.h"
00044 
00045 #include "ilbc/iLBC_encode.h"
00046 #include "ilbc/iLBC_decode.h"
00047 
00048 /* Sample frame data */
00049 #include "slin_ilbc_ex.h"
00050 #include "ilbc_slin_ex.h"
00051 
00052 #define USE_ILBC_ENHANCER  0
00053 #define ILBC_MS         30
00054 /* #define ILBC_MS         20 */
00055 
00056 AST_MUTEX_DEFINE_STATIC(localuser_lock);
00057 static int localusecnt=0;
00058 
00059 static char *tdesc = "iLBC/PCM16 (signed linear) Codec Translator";
00060 
00061 struct ast_translator_pvt {
00062    iLBC_Enc_Inst_t enc;
00063    iLBC_Dec_Inst_t dec;
00064    struct ast_frame f;
00065    /* Space to build offset */
00066    char offset[AST_FRIENDLY_OFFSET];
00067    /* Buffer for our outgoing frame */
00068    short outbuf[8000];
00069    /* Enough to store a full second */
00070    short buf[8000];
00071    int tail;
00072 };
00073 
00074 #define ilbc_coder_pvt ast_translator_pvt
00075 
00076 static struct ast_translator_pvt *lintoilbc_new(void)
00077 {
00078    struct ilbc_coder_pvt *tmp;
00079    tmp = malloc(sizeof(struct ilbc_coder_pvt));
00080    if (tmp) {
00081       /* Shut valgrind up */
00082       memset(&tmp->enc, 0, sizeof(tmp->enc));
00083       initEncode(&tmp->enc, ILBC_MS);
00084       tmp->tail = 0;
00085       localusecnt++;
00086    }
00087    return tmp;
00088 }
00089 
00090 static struct ast_translator_pvt *ilbctolin_new(void)
00091 {
00092    struct ilbc_coder_pvt *tmp;
00093    tmp = malloc(sizeof(struct ilbc_coder_pvt));
00094    if (tmp) {
00095       /* Shut valgrind up */
00096       memset(&tmp->dec, 0, sizeof(tmp->dec));
00097       initDecode(&tmp->dec, ILBC_MS, USE_ILBC_ENHANCER);
00098       tmp->tail = 0;
00099       localusecnt++;
00100    }
00101    return tmp;
00102 }
00103 
00104 static struct ast_frame *lintoilbc_sample(void)
00105 {
00106    static struct ast_frame f;
00107    f.frametype = AST_FRAME_VOICE;
00108    f.subclass = AST_FORMAT_SLINEAR;
00109    f.datalen = sizeof(slin_ilbc_ex);
00110    /* Assume 8000 Hz */
00111    f.samples = sizeof(slin_ilbc_ex)/2;
00112    f.mallocd = 0;
00113    f.offset = 0;
00114    f.src = __PRETTY_FUNCTION__;
00115    f.data = slin_ilbc_ex;
00116    return &f;
00117 }
00118 
00119 static struct ast_frame *ilbctolin_sample(void)
00120 {
00121    static struct ast_frame f;
00122    f.frametype = AST_FRAME_VOICE;
00123    f.subclass = AST_FORMAT_ILBC;
00124    f.datalen = sizeof(ilbc_slin_ex);
00125    /* All frames are 30 ms long */
00126    f.samples = 240;
00127    f.mallocd = 0;
00128    f.offset = 0;
00129    f.src = __PRETTY_FUNCTION__;
00130    f.data = ilbc_slin_ex;
00131    return &f;
00132 }
00133 
00134 static struct ast_frame *ilbctolin_frameout(struct ast_translator_pvt *tmp)
00135 {
00136    if (!tmp->tail)
00137       return NULL;
00138    /* Signed linear is no particular frame size, so just send whatever
00139       we have in the buffer in one lump sum */
00140    tmp->f.frametype = AST_FRAME_VOICE;
00141    tmp->f.subclass = AST_FORMAT_SLINEAR;
00142    tmp->f.datalen = tmp->tail * 2;
00143    /* Assume 8000 Hz */
00144    tmp->f.samples = tmp->tail;
00145    tmp->f.mallocd = 0;
00146    tmp->f.offset = AST_FRIENDLY_OFFSET;
00147    tmp->f.src = __PRETTY_FUNCTION__;
00148    tmp->f.data = tmp->buf;
00149    /* Reset tail pointer */
00150    tmp->tail = 0;
00151 
00152    return &tmp->f;   
00153 }
00154 
00155 static int ilbctolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
00156 {
00157    /* Assuming there's space left, decode into the current buffer at
00158       the tail location.  Read in as many frames as there are */
00159    int x,i;
00160    float tmpf[240];
00161 
00162    if (f->datalen == 0) { /* native PLC */
00163       if (tmp->tail + 240 < sizeof(tmp->buf)/2) {  
00164          iLBC_decode(tmpf, NULL, &tmp->dec, 0);
00165          for (i=0;i<240;i++)
00166             tmp->buf[tmp->tail + i] = tmpf[i];
00167          tmp->tail+=240;
00168       } else {
00169          ast_log(LOG_WARNING, "Out of buffer space\n");
00170          return -1;
00171       }     
00172    }
00173 
00174    if (f->datalen % 50) {
00175       ast_log(LOG_WARNING, "Huh?  An ilbc frame that isn't a multiple of 50 bytes long from %s (%d)?\n", f->src, f->datalen);
00176       return -1;
00177    }
00178    
00179    for (x=0;x<f->datalen;x+=50) {
00180       if (tmp->tail + 240 < sizeof(tmp->buf)/2) {  
00181          iLBC_decode(tmpf, f->data + x, &tmp->dec, 1);
00182          for (i=0;i<240;i++)
00183             tmp->buf[tmp->tail + i] = tmpf[i];
00184          tmp->tail+=240;
00185       } else {
00186          ast_log(LOG_WARNING, "Out of buffer space\n");
00187          return -1;
00188       }     
00189    }
00190    return 0;
00191 }
00192 
00193 static int lintoilbc_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
00194 {
00195    /* Just add the frames to our stream */
00196    /* XXX We should look at how old the rest of our stream is, and if it
00197       is too old, then we should overwrite it entirely, otherwise we can
00198       get artifacts of earlier talk that do not belong */
00199    if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
00200       memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
00201       tmp->tail += f->datalen/2;
00202    } else {
00203       ast_log(LOG_WARNING, "Out of buffer space\n");
00204       return -1;
00205    }
00206    return 0;
00207 }
00208 
00209 static struct ast_frame *lintoilbc_frameout(struct ast_translator_pvt *tmp)
00210 {
00211    int x=0,i;
00212    float tmpf[240];
00213    /* We can't work on anything less than a frame in size */
00214    if (tmp->tail < 240)
00215       return NULL;
00216    tmp->f.frametype = AST_FRAME_VOICE;
00217    tmp->f.subclass = AST_FORMAT_ILBC;
00218    tmp->f.mallocd = 0;
00219    tmp->f.offset = AST_FRIENDLY_OFFSET;
00220    tmp->f.src = __PRETTY_FUNCTION__;
00221    tmp->f.data = tmp->outbuf;
00222    while(tmp->tail >= 240) {
00223       if ((x+1) * 50 >= sizeof(tmp->outbuf)) {
00224          ast_log(LOG_WARNING, "Out of buffer space\n");
00225          break;
00226       }
00227       for (i=0;i<240;i++)
00228          tmpf[i] = tmp->buf[i];
00229       /* Encode a frame of data */
00230       iLBC_encode(((unsigned char *)(tmp->outbuf)) + (x * 50), tmpf, &tmp->enc);
00231       /* Assume 8000 Hz -- 20 ms */
00232       tmp->tail -= 240;
00233       /* Move the data at the end of the buffer to the front */
00234       if (tmp->tail)
00235          memmove(tmp->buf, tmp->buf + 240, tmp->tail * 2);
00236       x++;
00237    }
00238    tmp->f.datalen = x * 50;
00239    tmp->f.samples = x * 240;
00240 #if 0
00241    {
00242       static int fd = -1;
00243       if (fd == -1) {
00244          fd = open("ilbc.out", O_CREAT|O_TRUNC|O_WRONLY, 0666);
00245          write(fd, tmp->f.data, tmp->f.datalen);
00246          close(fd);
00247       }
00248    }
00249 #endif   
00250    return &tmp->f;   
00251 }
00252 
00253 static void ilbc_destroy_stuff(struct ast_translator_pvt *pvt)
00254 {
00255    free(pvt);
00256    localusecnt--;
00257 }
00258 
00259 static struct ast_translator ilbctolin =
00260    { "ilbctolin", 
00261       AST_FORMAT_ILBC, AST_FORMAT_SLINEAR,
00262       ilbctolin_new,
00263       ilbctolin_framein,
00264       ilbctolin_frameout,
00265       ilbc_destroy_stuff,
00266       ilbctolin_sample
00267       };
00268 
00269 static struct ast_translator lintoilbc =
00270    { "lintoilbc", 
00271       AST_FORMAT_SLINEAR, AST_FORMAT_ILBC,
00272       lintoilbc_new,
00273       lintoilbc_framein,
00274       lintoilbc_frameout,
00275       ilbc_destroy_stuff,
00276       lintoilbc_sample
00277       };
00278 
00279 int unload_module(void)
00280 {
00281    int res;
00282    ast_mutex_lock(&localuser_lock);
00283    res = ast_unregister_translator(&lintoilbc);
00284    if (!res)
00285       res = ast_unregister_translator(&ilbctolin);
00286    if (localusecnt)
00287       res = -1;
00288    ast_mutex_unlock(&localuser_lock);
00289    return res;
00290 }
00291 
00292 int load_module(void)
00293 {
00294    int res;
00295    res=ast_register_translator(&ilbctolin);
00296    if (!res) 
00297       res=ast_register_translator(&lintoilbc);
00298    else
00299       ast_unregister_translator(&ilbctolin);
00300    return res;
00301 }
00302 
00303 char *description(void)
00304 {
00305    return tdesc;
00306 }
00307 
00308 int usecount(void)
00309 {
00310    int res;
00311    STANDARD_USECOUNT(res);
00312    return res;
00313 }
00314 
00315 char *key()
00316 {
00317    return ASTERISK_GPL_KEY;
00318 }

Generated on Fri May 26 01:45:33 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6