Thu May 14 15:12:56 2009

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>no</defaultenabled>
00030  ***/
00031 
00032 #include "asterisk.h"
00033 
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 110880 $")
00035 
00036 #include <fcntl.h>
00037 #include <stdlib.h>
00038 #include <unistd.h>
00039 #include <netinet/in.h>
00040 #include <string.h>
00041 #include <stdio.h>
00042 
00043 #include "asterisk/lock.h"
00044 #include "asterisk/translate.h"
00045 #include "asterisk/module.h"
00046 #include "asterisk/logger.h"
00047 #include "asterisk/channel.h"
00048 #include "asterisk/utils.h"
00049 
00050 #include "ilbc/iLBC_encode.h"
00051 #include "ilbc/iLBC_decode.h"
00052 
00053 /* Sample frame data */
00054 #include "slin_ilbc_ex.h"
00055 #include "ilbc_slin_ex.h"
00056 
00057 #define USE_ILBC_ENHANCER  0
00058 #define ILBC_MS         30
00059 /* #define ILBC_MS         20 */
00060 
00061 #define  ILBC_FRAME_LEN 50 /* apparently... */
00062 #define  ILBC_SAMPLES   240   /* 30ms at 8000 hz */
00063 #define  BUFFER_SAMPLES 8000
00064 
00065 struct ilbc_coder_pvt {
00066    iLBC_Enc_Inst_t enc;
00067    iLBC_Dec_Inst_t dec;
00068    /* Enough to store a full second */
00069    int16_t buf[BUFFER_SAMPLES];
00070 };
00071 
00072 static int lintoilbc_new(struct ast_trans_pvt *pvt)
00073 {
00074    struct ilbc_coder_pvt *tmp = pvt->pvt;
00075 
00076    initEncode(&tmp->enc, ILBC_MS);
00077 
00078    return 0;
00079 }
00080 
00081 static int ilbctolin_new(struct ast_trans_pvt *pvt)
00082 {
00083    struct ilbc_coder_pvt *tmp = pvt->pvt;
00084 
00085    initDecode(&tmp->dec, ILBC_MS, USE_ILBC_ENHANCER);
00086 
00087    return 0;
00088 }
00089 
00090 static struct ast_frame *lintoilbc_sample(void)
00091 {
00092    static struct ast_frame f;
00093    f.frametype = AST_FRAME_VOICE;
00094    f.subclass = AST_FORMAT_SLINEAR;
00095    f.datalen = sizeof(slin_ilbc_ex);
00096    f.samples = sizeof(slin_ilbc_ex)/2;
00097    f.mallocd = 0;
00098    f.offset = 0;
00099    f.src = __PRETTY_FUNCTION__;
00100    f.data = slin_ilbc_ex;
00101    return &f;
00102 }
00103 
00104 static struct ast_frame *ilbctolin_sample(void)
00105 {
00106    static struct ast_frame f;
00107    f.frametype = AST_FRAME_VOICE;
00108    f.subclass = AST_FORMAT_ILBC;
00109    f.datalen = sizeof(ilbc_slin_ex);
00110    /* All frames are 30 ms long */
00111    f.samples = ILBC_SAMPLES;
00112    f.mallocd = 0;
00113    f.offset = 0;
00114    f.src = __PRETTY_FUNCTION__;
00115    f.data = ilbc_slin_ex;
00116    return &f;
00117 }
00118 
00119 /*! \brief decode a frame and store in outbuf */
00120 static int ilbctolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00121 {
00122    struct ilbc_coder_pvt *tmp = pvt->pvt;
00123    int plc_mode = 1; /* 1 = normal data, 0 = plc */
00124    /* Assuming there's space left, decode into the current buffer at
00125       the tail location.  Read in as many frames as there are */
00126    int x,i;
00127    int16_t *dst = (int16_t *)pvt->outbuf;
00128    float tmpf[ILBC_SAMPLES];
00129 
00130    if (f->datalen == 0) { /* native PLC, set fake f->datalen and clear plc_mode */
00131       f->datalen = ILBC_FRAME_LEN;
00132       f->samples = ILBC_SAMPLES;
00133       plc_mode = 0;  /* do native plc */
00134       pvt->samples += ILBC_SAMPLES;
00135    }
00136 
00137    if (f->datalen % ILBC_FRAME_LEN) {
00138       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);
00139       return -1;
00140    }
00141    
00142    for (x=0; x < f->datalen ; x += ILBC_FRAME_LEN) {
00143       if (pvt->samples + ILBC_SAMPLES > BUFFER_SAMPLES) {   
00144          ast_log(LOG_WARNING, "Out of buffer space\n");
00145          return -1;
00146       }     
00147       iLBC_decode(tmpf, plc_mode ? f->data + x : NULL, &tmp->dec, plc_mode);
00148       for ( i=0; i < ILBC_SAMPLES; i++)
00149          dst[pvt->samples + i] = tmpf[i];
00150       pvt->samples += ILBC_SAMPLES;
00151       pvt->datalen += 2*ILBC_SAMPLES;
00152    }
00153    return 0;
00154 }
00155 
00156 /*! \brief store a frame into a temporary buffer, for later decoding */
00157 static int lintoilbc_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00158 {
00159    struct ilbc_coder_pvt *tmp = pvt->pvt;
00160 
00161    /* Just add the frames to our stream */
00162    /* XXX We should look at how old the rest of our stream is, and if it
00163       is too old, then we should overwrite it entirely, otherwise we can
00164       get artifacts of earlier talk that do not belong */
00165    memcpy(tmp->buf + pvt->samples, f->data, f->datalen);
00166    pvt->samples += f->samples;
00167    return 0;
00168 }
00169 
00170 /*! \brief encode the temporary buffer and generate a frame */
00171 static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt)
00172 {
00173    struct ilbc_coder_pvt *tmp = pvt->pvt;
00174    int datalen = 0;
00175    int samples = 0;
00176 
00177    /* We can't work on anything less than a frame in size */
00178    if (pvt->samples < ILBC_SAMPLES)
00179       return NULL;
00180    while (pvt->samples >= ILBC_SAMPLES) {
00181       float tmpf[ILBC_SAMPLES];
00182       int i;
00183 
00184       /* Encode a frame of data */
00185       for (i = 0 ; i < ILBC_SAMPLES ; i++)
00186          tmpf[i] = tmp->buf[samples + i];
00187       iLBC_encode((unsigned char *) pvt->outbuf + datalen, tmpf, &tmp->enc);
00188 
00189       datalen += ILBC_FRAME_LEN;
00190       samples += ILBC_SAMPLES;
00191       pvt->samples -= ILBC_SAMPLES;
00192    }
00193 
00194    /* Move the data at the end of the buffer to the front */
00195    if (pvt->samples)
00196       memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
00197 
00198    return ast_trans_frameout(pvt, datalen, samples);
00199 }
00200 
00201 static struct ast_translator ilbctolin = {
00202    .name = "ilbctolin", 
00203    .srcfmt = AST_FORMAT_ILBC,
00204    .dstfmt = AST_FORMAT_SLINEAR,
00205    .newpvt = ilbctolin_new,
00206    .framein = ilbctolin_framein,
00207    .sample = ilbctolin_sample,
00208    .desc_size = sizeof(struct ilbc_coder_pvt),
00209    .buf_size = BUFFER_SAMPLES * 2,
00210    .native_plc = 1,
00211 };
00212 
00213 static struct ast_translator lintoilbc = {
00214    .name = "lintoilbc", 
00215    .srcfmt = AST_FORMAT_SLINEAR,
00216    .dstfmt = AST_FORMAT_ILBC,
00217    .newpvt = lintoilbc_new,
00218    .framein = lintoilbc_framein,
00219    .frameout = lintoilbc_frameout,
00220    .sample = lintoilbc_sample,
00221    .desc_size = sizeof(struct ilbc_coder_pvt),
00222    .buf_size = (BUFFER_SAMPLES * ILBC_FRAME_LEN + ILBC_SAMPLES - 1) / ILBC_SAMPLES,
00223 };
00224 
00225 static int unload_module(void)
00226 {
00227    int res;
00228 
00229    res = ast_unregister_translator(&lintoilbc);
00230    res |= ast_unregister_translator(&ilbctolin);
00231 
00232    return res;
00233 }
00234 
00235 static int load_module(void)
00236 {
00237    int res;
00238 
00239    res = ast_register_translator(&ilbctolin);
00240    if (!res) 
00241       res=ast_register_translator(&lintoilbc);
00242    else
00243       ast_unregister_translator(&ilbctolin);
00244 
00245    return res;
00246 }
00247 
00248 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "iLBC Coder/Decoder");

Generated on Thu May 14 15:12:57 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7