Fri Aug 17 00:17:15 2018

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

Generated on 17 Aug 2018 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1