00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
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
00066 char offset[AST_FRIENDLY_OFFSET];
00067
00068 short outbuf[8000];
00069
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
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
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
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
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
00139
00140 tmp->f.frametype = AST_FRAME_VOICE;
00141 tmp->f.subclass = AST_FORMAT_SLINEAR;
00142 tmp->f.datalen = tmp->tail * 2;
00143
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
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
00158
00159 int x,i;
00160 float tmpf[240];
00161
00162 if (f->datalen == 0) {
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
00196
00197
00198
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
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
00230 iLBC_encode(((unsigned char *)(tmp->outbuf)) + (x * 50), tmpf, &tmp->enc);
00231
00232 tmp->tail -= 240;
00233
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 }