Fix iLBC with valgrind, add iLBC format from bkw_
[asterisk/asterisk.git] / codecs / codec_ilbc.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Translate between signed linear and Internet Low Bitrate Codec
5  *
6  * The iLBC code is from The IETF code base and is copyright GlobalSound, AB
7  * 
8  * Copyright (C) 1999, Mark Spencer
9  *
10  * Mark Spencer <markster@linux-support.net>
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License
14  */
15
16 #include <asterisk/lock.h>
17 #include <asterisk/translate.h>
18 #include <asterisk/module.h>
19 #include <asterisk/logger.h>
20 #include <asterisk/channel.h>
21 #include <pthread.h>
22 #include <fcntl.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <netinet/in.h>
26 #include <string.h>
27 #include <stdio.h>
28
29 #include "ilbc/iLBC_encode.h"
30 #include "ilbc/iLBC_decode.h"
31
32 /* Sample frame data */
33 #include "slin_ilbc_ex.h"
34 #include "ilbc_slin_ex.h"
35
36 #define USE_ILBC_ENHANCER       0
37
38 static ast_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
39 static int localusecnt=0;
40
41 static char *tdesc = "iLBC/PCM16 (signed linear) Codec Translator";
42
43 struct ast_translator_pvt {
44         iLBC_Enc_Inst_t enc;
45         iLBC_Dec_Inst_t dec;
46         struct ast_frame f;
47         /* Space to build offset */
48         char offset[AST_FRIENDLY_OFFSET];
49         /* Buffer for our outgoing frame */
50         short outbuf[8000];
51         /* Enough to store a full second */
52         short buf[8000];
53         int tail;
54 };
55
56 #define ilbc_coder_pvt ast_translator_pvt
57
58 static struct ast_translator_pvt *lintoilbc_new(void)
59 {
60         struct ilbc_coder_pvt *tmp;
61         tmp = malloc(sizeof(struct ilbc_coder_pvt));
62         if (tmp) {
63                 /* Shut valgrind up */
64                 memset(&tmp->enc, 0, sizeof(tmp->enc));
65                 initEncode(&tmp->enc);
66                 tmp->tail = 0;
67                 localusecnt++;
68         }
69         return tmp;
70 }
71
72 static struct ast_translator_pvt *ilbctolin_new(void)
73 {
74         struct ilbc_coder_pvt *tmp;
75         tmp = malloc(sizeof(struct ilbc_coder_pvt));
76         if (tmp) {
77                 /* Shut valgrind up */
78                 memset(&tmp->dec, 0, sizeof(tmp->dec));
79                 initDecode(&tmp->dec, USE_ILBC_ENHANCER);
80                 tmp->tail = 0;
81                 localusecnt++;
82         }
83         return tmp;
84 }
85
86 static struct ast_frame *lintoilbc_sample(void)
87 {
88         static struct ast_frame f;
89         f.frametype = AST_FRAME_VOICE;
90         f.subclass = AST_FORMAT_SLINEAR;
91         f.datalen = sizeof(slin_ilbc_ex);
92         /* Assume 8000 Hz */
93         f.samples = sizeof(slin_ilbc_ex)/2;
94         f.mallocd = 0;
95         f.offset = 0;
96         f.src = __PRETTY_FUNCTION__;
97         f.data = slin_ilbc_ex;
98         return &f;
99 }
100
101 static struct ast_frame *ilbctolin_sample(void)
102 {
103         static struct ast_frame f;
104         f.frametype = AST_FRAME_VOICE;
105         f.subclass = AST_FORMAT_ILBC;
106         f.datalen = sizeof(ilbc_slin_ex);
107         /* All frames are 30 ms long */
108         f.samples = 240;
109         f.mallocd = 0;
110         f.offset = 0;
111         f.src = __PRETTY_FUNCTION__;
112         f.data = ilbc_slin_ex;
113         return &f;
114 }
115
116 static struct ast_frame *ilbctolin_frameout(struct ast_translator_pvt *tmp)
117 {
118         if (!tmp->tail)
119                 return NULL;
120         /* Signed linear is no particular frame size, so just send whatever
121            we have in the buffer in one lump sum */
122         tmp->f.frametype = AST_FRAME_VOICE;
123         tmp->f.subclass = AST_FORMAT_SLINEAR;
124         tmp->f.datalen = tmp->tail * 2;
125         /* Assume 8000 Hz */
126         tmp->f.samples = tmp->tail;
127         tmp->f.mallocd = 0;
128         tmp->f.offset = AST_FRIENDLY_OFFSET;
129         tmp->f.src = __PRETTY_FUNCTION__;
130         tmp->f.data = tmp->buf;
131         /* Reset tail pointer */
132         tmp->tail = 0;
133
134         return &tmp->f; 
135 }
136
137 static int ilbctolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
138 {
139         /* Assuming there's space left, decode into the current buffer at
140            the tail location.  Read in as many frames as there are */
141         int x,i;
142         float tmpf[240];
143         
144         if (f->datalen % 50) {
145                 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);
146                 return -1;
147         }
148         
149         for (x=0;x<f->datalen;x+=50) {
150                 if (tmp->tail + 240 < sizeof(tmp->buf)/2) {     
151                         iLBC_decode(tmpf, f->data + x, &tmp->dec, 1);
152                         for (i=0;i<240;i++)
153                                 tmp->buf[tmp->tail + i] = tmpf[i];
154                         tmp->tail+=240;
155                 } else {
156                         ast_log(LOG_WARNING, "Out of buffer space\n");
157                         return -1;
158                 }               
159         }
160         return 0;
161 }
162
163 static int lintoilbc_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
164 {
165         /* Just add the frames to our stream */
166         /* XXX We should look at how old the rest of our stream is, and if it
167            is too old, then we should overwrite it entirely, otherwise we can
168            get artifacts of earlier talk that do not belong */
169         if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
170                 memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
171                 tmp->tail += f->datalen/2;
172         } else {
173                 ast_log(LOG_WARNING, "Out of buffer space\n");
174                 return -1;
175         }
176         return 0;
177 }
178
179 static struct ast_frame *lintoilbc_frameout(struct ast_translator_pvt *tmp)
180 {
181         int x=0,i;
182         float tmpf[240];
183         /* We can't work on anything less than a frame in size */
184         if (tmp->tail < 240)
185                 return NULL;
186         tmp->f.frametype = AST_FRAME_VOICE;
187         tmp->f.subclass = AST_FORMAT_ILBC;
188         tmp->f.mallocd = 0;
189         tmp->f.offset = AST_FRIENDLY_OFFSET;
190         tmp->f.src = __PRETTY_FUNCTION__;
191         tmp->f.data = tmp->outbuf;
192         while(tmp->tail >= 240) {
193                 if ((x+1) * 50 >= sizeof(tmp->outbuf)) {
194                         ast_log(LOG_WARNING, "Out of buffer space\n");
195                         break;
196                 }
197                 for (i=0;i<240;i++)
198                         tmpf[i] = tmp->buf[i];
199                 /* Encode a frame of data */
200                 iLBC_encode(((unsigned char *)(tmp->outbuf)) + (x * 50), tmpf, &tmp->enc);
201                 /* Assume 8000 Hz -- 20 ms */
202                 tmp->tail -= 240;
203                 /* Move the data at the end of the buffer to the front */
204                 if (tmp->tail)
205                         memmove(tmp->buf, tmp->buf + 240, tmp->tail * 2);
206                 x++;
207         }
208         tmp->f.datalen = x * 50;
209         tmp->f.samples = x * 240;
210 #if 0
211         {
212                 static int fd = -1;
213                 if (fd == -1) {
214                         fd = open("ilbc.out", O_CREAT|O_TRUNC|O_WRONLY, 0666);
215                         write(fd, tmp->f.data, tmp->f.datalen);
216                         close(fd);
217                 }
218         }
219 #endif  
220         return &tmp->f; 
221 }
222
223 static void ilbc_destroy_stuff(struct ast_translator_pvt *pvt)
224 {
225         free(pvt);
226         localusecnt--;
227 }
228
229 static struct ast_translator ilbctolin =
230         { "ilbctolin", 
231            AST_FORMAT_ILBC, AST_FORMAT_SLINEAR,
232            ilbctolin_new,
233            ilbctolin_framein,
234            ilbctolin_frameout,
235            ilbc_destroy_stuff,
236            ilbctolin_sample
237            };
238
239 static struct ast_translator lintoilbc =
240         { "lintoilbc", 
241            AST_FORMAT_SLINEAR, AST_FORMAT_ILBC,
242            lintoilbc_new,
243            lintoilbc_framein,
244            lintoilbc_frameout,
245            ilbc_destroy_stuff,
246            lintoilbc_sample
247            };
248
249 int unload_module(void)
250 {
251         int res;
252         ast_mutex_lock(&localuser_lock);
253         res = ast_unregister_translator(&lintoilbc);
254         if (!res)
255                 res = ast_unregister_translator(&ilbctolin);
256         if (localusecnt)
257                 res = -1;
258         ast_mutex_unlock(&localuser_lock);
259         return res;
260 }
261
262 int load_module(void)
263 {
264         int res;
265         res=ast_register_translator(&ilbctolin);
266         if (!res) 
267                 res=ast_register_translator(&lintoilbc);
268         else
269                 ast_unregister_translator(&ilbctolin);
270         return res;
271 }
272
273 char *description(void)
274 {
275         return tdesc;
276 }
277
278 int usecount(void)
279 {
280         int res;
281         STANDARD_USECOUNT(res);
282         return res;
283 }
284
285 char *key()
286 {
287         return ASTERISK_GPL_KEY;
288 }