Remove pthread.h from source. We should be using asterisk/lock.h everywhere instead...
[asterisk/asterisk.git] / codecs / codec_g723_1.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Translate between signed linear and G.723.1
5  *
6  * The G.723.1 code is not included in the Asterisk distribution because
7  * it is covered with patents, and in spite of statements to the contrary,
8  * the "technology" is extremely expensive to license.
9  * 
10  * Copyright (C) 1999, Mark Spencer
11  *
12  * Mark Spencer <markster@linux-support.net>
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License
16  */
17
18 #define TYPE_HIGH        0x0
19 #define TYPE_LOW         0x1
20 #define TYPE_SILENCE     0x2
21 #define TYPE_DONTSEND    0x3
22 #define TYPE_MASK        0x3
23
24 #include <sys/types.h>
25 #include <asterisk/lock.h>
26 #include <asterisk/translate.h>
27 #include <asterisk/module.h>
28 #include <asterisk/logger.h>
29 #include <asterisk/channel.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <netinet/in.h>
34 #include <string.h>
35 #include <stdio.h>
36
37 #ifdef ANNEX_B
38 #include "g723.1b/typedef2.h"
39 #include "g723.1b/cst2.h"
40 #include "g723.1b/coder2.h"
41 #include "g723.1b/decod2.h"
42 #include "g723.1b/deccng2.h"
43 #include "g723.1b/codcng2.h"
44 #include "g723.1b/vad2.h"
45 #else
46 #include "g723.1/typedef.h"
47 #include "g723.1/cst_lbc.h"
48 #include "g723.1/coder.h"
49 #include "g723.1/decod.h"
50 #include "g723.1/dec_cng.h"
51 #include "g723.1/cod_cng.h"
52 #include "g723.1/vad.h"
53 #endif
54
55 /* Sample frame data */
56 #include "slin_g723_ex.h"
57 #include "g723_slin_ex.h"
58
59 AST_MUTEX_DEFINE_STATIC(localuser_lock);
60 static int localusecnt=0;
61
62 #ifdef ANNEX_B
63 static char *tdesc = "Annex B (floating point) G.723.1/PCM16 Codec Translator";
64 #else
65 static char *tdesc = "Annex A (fixed point) G.723.1/PCM16 Codec Translator";
66 #endif
67
68 /* Globals */
69 Flag UsePf = True;
70 Flag UseHp = True;
71 Flag UseVx = True;
72
73 enum Crate WrkRate = Rate63;
74
75 struct g723_encoder_pvt {
76         struct cod_state cod;
77         struct ast_frame f;
78         /* Space to build offset */
79         char offset[AST_FRIENDLY_OFFSET];
80         /* Buffer for our outgoing frame */
81         char outbuf[8000];
82         /* Enough to store a full second */
83         short buf[8000];
84         int tail;
85 };
86
87 struct g723_decoder_pvt {
88         struct dec_state dec;
89         struct ast_frame f;
90         /* Space to build offset */
91         char offset[AST_FRIENDLY_OFFSET];
92         /* Enough to store a full second */
93         short buf[8000];
94         int tail;
95 };
96
97 static struct ast_translator_pvt *g723tolin_new(void)
98 {
99         struct g723_decoder_pvt *tmp;
100         tmp = malloc(sizeof(struct g723_decoder_pvt));
101         if (tmp) {
102                 Init_Decod(&tmp->dec);
103             Init_Dec_Cng(&tmp->dec);
104                 tmp->tail = 0;
105                 localusecnt++;
106                 ast_update_use_count();
107         }
108         return (struct ast_translator_pvt *)tmp;
109 }
110
111 static struct ast_frame *lintog723_sample(void)
112 {
113         static struct ast_frame f;
114         f.frametype = AST_FRAME_VOICE;
115         f.subclass = AST_FORMAT_SLINEAR;
116         f.datalen = sizeof(slin_g723_ex);
117         /* Assume 8000 Hz */
118         f.samples = sizeof(slin_g723_ex)/2;
119         f.mallocd = 0;
120         f.offset = 0;
121         f.src = __PRETTY_FUNCTION__;
122         f.data = slin_g723_ex;
123         return &f;
124 }
125
126 static struct ast_frame *g723tolin_sample(void)
127 {
128         static struct ast_frame f;
129         f.frametype = AST_FRAME_VOICE;
130         f.subclass = AST_FORMAT_G723_1;
131         f.datalen = sizeof(g723_slin_ex);
132         /* All frames are 30 ms long */
133         f.samples = 240;
134         f.mallocd = 0;
135         f.offset = 0;
136         f.src = __PRETTY_FUNCTION__;
137         f.data = g723_slin_ex;
138         return &f;
139 }
140
141 static struct ast_translator_pvt *lintog723_new(void)
142 {
143         struct g723_encoder_pvt *tmp;
144         tmp = malloc(sizeof(struct g723_encoder_pvt));
145         if (tmp) {
146                 Init_Coder(&tmp->cod);
147             /* Init Comfort Noise Functions */
148                  if( UseVx ) {
149                         Init_Vad(&tmp->cod);
150                 Init_Cod_Cng(&tmp->cod);
151          }
152                 localusecnt++;
153                 ast_update_use_count();
154                 tmp->tail = 0;
155         }
156         return (struct ast_translator_pvt *)tmp;
157 }
158
159 static struct ast_frame *g723tolin_frameout(struct ast_translator_pvt *pvt)
160 {
161         struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
162         if (!tmp->tail)
163                 return NULL;
164         /* Signed linear is no particular frame size, so just send whatever
165            we have in the buffer in one lump sum */
166         tmp->f.frametype = AST_FRAME_VOICE;
167         tmp->f.subclass = AST_FORMAT_SLINEAR;
168         tmp->f.datalen = tmp->tail * 2;
169         /* Assume 8000 Hz */
170         tmp->f.samples = tmp->tail;
171         tmp->f.mallocd = 0;
172         tmp->f.offset = AST_FRIENDLY_OFFSET;
173         tmp->f.src = __PRETTY_FUNCTION__;
174         tmp->f.data = tmp->buf;
175         /* Reset tail pointer */
176         tmp->tail = 0;
177
178 #if 0
179         /* Save the frames */
180         { 
181                 static int fd2 = -1;
182                 if (fd2 == -1) {
183                         fd2 = open("g723.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
184                 }
185                 write(fd2, tmp->f.data, tmp->f.datalen);
186         }               
187 #endif
188         return &tmp->f; 
189 }
190
191 static int g723_len(unsigned char buf)
192 {
193         switch(buf & TYPE_MASK) {
194         case TYPE_DONTSEND:
195                 return 0;
196                 break;
197         case TYPE_SILENCE:
198                 return 4;
199                 break;
200         case TYPE_HIGH:
201                 return 24;
202                 break;
203         case TYPE_LOW:
204                 return 20;
205                 break;
206         default:
207                 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
208         }
209         return -1;
210 }
211
212 static int g723tolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
213 {
214         struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
215         int len = 0;
216         int res;
217 #ifdef  ANNEX_B
218         FLOAT tmpdata[Frame];
219         int x;
220 #endif
221         while(len < f->datalen) {
222                 /* Assuming there's space left, decode into the current buffer at
223                    the tail location */
224                 res = g723_len(((unsigned char *)f->data + len)[0]);
225                 if (res < 0) {
226                         ast_log(LOG_WARNING, "Invalid data\n");
227                         return -1;
228                 }
229                 if (res + len > f->datalen) {
230                         ast_log(LOG_WARNING, "Measured length exceeds frame length\n");
231                         return -1;
232                 }
233                 if (tmp->tail + Frame < sizeof(tmp->buf)/2) {   
234 #ifdef ANNEX_B
235                         Decod(&tmp->dec, tmpdata, f->data + len, 0);
236                         for (x=0;x<Frame;x++)
237                                 (tmp->buf + tmp->tail)[x] = (short)(tmpdata[x]); 
238 #else
239                         Decod(&tmp->dec, tmp->buf + tmp->tail, f->data + len, 0);
240 #endif
241                         tmp->tail+=Frame;
242                 } else {
243                         ast_log(LOG_WARNING, "Out of buffer space\n");
244                         return -1;
245                 }
246                 len += res;
247         }
248         return 0;
249 }
250
251 static int lintog723_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
252 {
253         /* Just add the frames to our stream */
254         /* XXX We should look at how old the rest of our stream is, and if it
255            is too old, then we should overwrite it entirely, otherwise we can
256            get artifacts of earlier talk that do not belong */
257         struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
258         if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
259                 memcpy(&tmp->buf[tmp->tail], f->data, f->datalen);
260                 tmp->tail += f->datalen/2;
261         } else {
262                 ast_log(LOG_WARNING, "Out of buffer space\n");
263                 return -1;
264         }
265         return 0;
266 }
267
268 static struct ast_frame *lintog723_frameout(struct ast_translator_pvt *pvt)
269 {
270         struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
271 #ifdef ANNEX_B
272         int x;
273         FLOAT tmpdata[Frame];
274 #endif
275         int cnt=0;
276         /* We can't work on anything less than a frame in size */
277         if (tmp->tail < Frame)
278                 return NULL;
279         tmp->f.frametype = AST_FRAME_VOICE;
280         tmp->f.subclass = AST_FORMAT_G723_1;
281         tmp->f.offset = AST_FRIENDLY_OFFSET;
282         tmp->f.src = __PRETTY_FUNCTION__;
283         tmp->f.samples = 0;
284         tmp->f.mallocd = 0;
285         while(tmp->tail >= Frame) {
286                 /* Encode a frame of data */
287                 if (cnt + 24 >= sizeof(tmp->outbuf)) {
288                         ast_log(LOG_WARNING, "Out of buffer space\n");
289                         return NULL;
290                 }
291 #ifdef ANNEX_B
292                 for (x=0;x<Frame;x++)
293                         tmpdata[x] = tmp->buf[x];
294                 Coder(&tmp->cod, tmpdata, tmp->outbuf + cnt);
295 #else
296                 Coder(&tmp->cod, tmp->buf, tmp->outbuf + cnt);
297 #endif
298                 /* Assume 8000 Hz */
299                 tmp->f.samples += 240;
300                 cnt += g723_len(tmp->outbuf[cnt]);
301                 tmp->tail -= Frame;
302                 /* Move the data at the end of the buffer to the front */
303                 if (tmp->tail)
304                         memmove(tmp->buf, tmp->buf + Frame, tmp->tail * 2);
305         }
306         tmp->f.datalen = cnt;
307         tmp->f.data = tmp->outbuf;
308 #if 0
309         /* Save to a g723 sample output file... */
310         { 
311                 static int fd = -1;
312                 int delay = htonl(30);
313                 short size;
314                 if (fd < 0)
315                         fd = open("trans.g723", O_WRONLY | O_CREAT | O_TRUNC, 0644);
316                 if (fd < 0)
317                         ast_log(LOG_WARNING, "Unable to create demo\n");
318                 write(fd, &delay, 4);
319                 size = htons(tmp->f.datalen);
320                 write(fd, &size, 2);
321                 write(fd, tmp->f.data, tmp->f.datalen);
322         }
323 #endif
324         return &tmp->f; 
325 }
326
327 static void g723_destroy(struct ast_translator_pvt *pvt)
328 {
329         free(pvt);
330         localusecnt--;
331         ast_update_use_count();
332 }
333
334 static struct ast_translator g723tolin =
335 #ifdef ANNEX_B
336         { "g723tolinb", 
337 #else
338         { "g723tolin", 
339 #endif
340            AST_FORMAT_G723_1, AST_FORMAT_SLINEAR,
341            g723tolin_new,
342            g723tolin_framein,
343            g723tolin_frameout,
344            g723_destroy,
345            g723tolin_sample
346            };
347
348 static struct ast_translator lintog723 =
349 #ifdef ANNEX_B
350         { "lintog723b", 
351 #else
352         { "lintog723", 
353 #endif
354            AST_FORMAT_SLINEAR, AST_FORMAT_G723_1,
355            lintog723_new,
356            lintog723_framein,
357            lintog723_frameout,
358            g723_destroy,
359            lintog723_sample
360            };
361
362 int unload_module(void)
363 {
364         int res;
365         ast_mutex_lock(&localuser_lock);
366         res = ast_unregister_translator(&lintog723);
367         if (!res)
368                 res = ast_unregister_translator(&g723tolin);
369         if (localusecnt)
370                 res = -1;
371         ast_mutex_unlock(&localuser_lock);
372         return res;
373 }
374
375 int load_module(void)
376 {
377         int res;
378         res=ast_register_translator(&g723tolin);
379         if (!res) 
380                 res=ast_register_translator(&lintog723);
381         else
382                 ast_unregister_translator(&g723tolin);
383         return res;
384 }
385
386 char *description(void)
387 {
388         return tdesc;
389 }
390
391 int usecount(void)
392 {
393         int res;
394         STANDARD_USECOUNT(res);
395         return res;
396 }
397
398 char *key(void)
399 {
400         return ASTERISK_GPL_KEY;
401 }