Remove pthread.h from source. We should be using asterisk/lock.h everywhere instead...
[asterisk/asterisk.git] / codecs / codec_ulaw.c
1 /* codec_ulaw.c - translate between signed linear and ulaw
2  * 
3  * Asterisk -- A telephony toolkit for Linux.
4  *
5  * Copyright (c) 2001 Linux Support Services, Inc.  All rights reserved.
6  *
7  * Mark Spencer <markster@linux-support.net
8  *
9  * This program is free software, distributed under the terms of
10  * the GNU General Public License
11  */
12
13 #include <asterisk/lock.h>
14 #include <asterisk/logger.h>
15 #include <asterisk/module.h>
16 #include <asterisk/translate.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/ulaw.h>
19 #include <fcntl.h>
20 #include <netinet/in.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #define BUFFER_SIZE   8096      /* size for the translation buffers */
27
28 AST_MUTEX_DEFINE_STATIC(localuser_lock);
29 static int localusecnt = 0;
30
31 static char *tdesc = "Mu-law Coder/Decoder";
32
33 /* Sample frame data */
34
35 #include "slin_ulaw_ex.h"
36 #include "ulaw_slin_ex.h"
37
38 /*
39  * Private workspace for translating signed linear signals to ulaw.
40  */
41
42 struct ulaw_encoder_pvt
43 {
44   struct ast_frame f;
45   char offset[AST_FRIENDLY_OFFSET];   /* Space to build offset */
46   unsigned char outbuf[BUFFER_SIZE];  /* Encoded ulaw, two nibbles to a word */
47   int tail;
48 };
49
50 /*
51  * Private workspace for translating ulaw signals to signed linear.
52  */
53
54 struct ulaw_decoder_pvt
55 {
56   struct ast_frame f;
57   char offset[AST_FRIENDLY_OFFSET];     /* Space to build offset */
58   short outbuf[BUFFER_SIZE];    /* Decoded signed linear values */
59   int tail;
60 };
61
62 /*
63  * ulawToLin_New
64  *  Create a new instance of ulaw_decoder_pvt.
65  *
66  * Results:
67  *  Returns a pointer to the new instance.
68  *
69  * Side effects:
70  *  None.
71  */
72
73 static struct ast_translator_pvt *
74 ulawtolin_new (void)
75 {
76   struct ulaw_decoder_pvt *tmp;
77   tmp = malloc (sizeof (struct ulaw_decoder_pvt));
78   if (tmp)
79     {
80           memset(tmp, 0, sizeof(*tmp));
81       tmp->tail = 0;
82       localusecnt++;
83       ast_update_use_count ();
84     }
85   return (struct ast_translator_pvt *) tmp;
86 }
87
88 /*
89  * LinToulaw_New
90  *  Create a new instance of ulaw_encoder_pvt.
91  *
92  * Results:
93  *  Returns a pointer to the new instance.
94  *
95  * Side effects:
96  *  None.
97  */
98
99 static struct ast_translator_pvt *
100 lintoulaw_new (void)
101 {
102   struct ulaw_encoder_pvt *tmp;
103   tmp = malloc (sizeof (struct ulaw_encoder_pvt));
104   if (tmp)
105     {
106           memset(tmp, 0, sizeof(*tmp));
107       localusecnt++;
108       ast_update_use_count ();
109       tmp->tail = 0;
110     }
111   return (struct ast_translator_pvt *) tmp;
112 }
113
114 /*
115  * ulawToLin_FrameIn
116  *  Fill an input buffer with packed 4-bit ulaw values if there is room
117  *  left.
118  *
119  * Results:
120  *  Foo
121  *
122  * Side effects:
123  *  tmp->tail is the number of packed values in the buffer.
124  */
125
126 static int
127 ulawtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
128 {
129   struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *) pvt;
130   int x;
131   unsigned char *b;
132
133   if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
134         ast_log(LOG_WARNING, "Out of buffer space\n");
135         return -1;
136   }
137
138   /* Reset ssindex and signal to frame's specified values */
139   b = f->data;
140   for (x=0;x<f->datalen;x++)
141         tmp->outbuf[tmp->tail + x] = AST_MULAW(b[x]);
142
143   tmp->tail += f->datalen;
144   return 0;
145 }
146
147 /*
148  * ulawToLin_FrameOut
149  *  Convert 4-bit ulaw encoded signals to 16-bit signed linear.
150  *
151  * Results:
152  *  Converted signals are placed in tmp->f.data, tmp->f.datalen
153  *  and tmp->f.samples are calculated.
154  *
155  * Side effects:
156  *  None.
157  */
158
159 static struct ast_frame *
160 ulawtolin_frameout (struct ast_translator_pvt *pvt)
161 {
162   struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *) pvt;
163
164   if (!tmp->tail)
165     return NULL;
166
167   tmp->f.frametype = AST_FRAME_VOICE;
168   tmp->f.subclass = AST_FORMAT_SLINEAR;
169   tmp->f.datalen = tmp->tail *2;
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->outbuf;
175   tmp->tail = 0;
176   return &tmp->f;
177 }
178
179 /*
180  * LinToulaw_FrameIn
181  *  Fill an input buffer with 16-bit signed linear PCM values.
182  *
183  * Results:
184  *  None.
185  *
186  * Side effects:
187  *  tmp->tail is number of signal values in the input buffer.
188  */
189
190 static int
191 lintoulaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
192 {
193   struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
194   int x;
195   short *s;
196   if (tmp->tail + f->datalen/2 >= sizeof(tmp->outbuf))
197     {
198       ast_log (LOG_WARNING, "Out of buffer space\n");
199       return -1;
200     }
201   s = f->data;
202   for (x=0;x<f->datalen/2;x++) 
203         tmp->outbuf[x+tmp->tail] = AST_LIN2MU(s[x]);
204   tmp->tail += f->datalen/2;
205   return 0;
206 }
207
208 /*
209  * LinToulaw_FrameOut
210  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
211  *  of 4-bit ulaw packed two to a byte (Big Endian).
212  *
213  * Results:
214  *  Foo
215  *
216  * Side effects:
217  *  Leftover inbuf data gets packed, tail gets updated.
218  */
219
220 static struct ast_frame *
221 lintoulaw_frameout (struct ast_translator_pvt *pvt)
222 {
223   struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
224   
225   if (tmp->tail) {
226           tmp->f.frametype = AST_FRAME_VOICE;
227           tmp->f.subclass = AST_FORMAT_ULAW;
228           tmp->f.samples = tmp->tail;
229           tmp->f.mallocd = 0;
230           tmp->f.offset = AST_FRIENDLY_OFFSET;
231           tmp->f.src = __PRETTY_FUNCTION__;
232           tmp->f.data = tmp->outbuf;
233           tmp->f.datalen = tmp->tail;
234           tmp->tail = 0;
235           return &tmp->f;
236    } else return NULL;
237 }
238
239
240 /*
241  * ulawToLin_Sample
242  */
243
244 static struct ast_frame *
245 ulawtolin_sample (void)
246 {
247   static struct ast_frame f;
248   f.frametype = AST_FRAME_VOICE;
249   f.subclass = AST_FORMAT_ULAW;
250   f.datalen = sizeof (ulaw_slin_ex);
251   f.samples = sizeof(ulaw_slin_ex);
252   f.mallocd = 0;
253   f.offset = 0;
254   f.src = __PRETTY_FUNCTION__;
255   f.data = ulaw_slin_ex;
256   return &f;
257 }
258
259 /*
260  * LinToulaw_Sample
261  */
262
263 static struct ast_frame *
264 lintoulaw_sample (void)
265 {
266   static struct ast_frame f;
267   f.frametype = AST_FRAME_VOICE;
268   f.subclass = AST_FORMAT_SLINEAR;
269   f.datalen = sizeof (slin_ulaw_ex);
270   /* Assume 8000 Hz */
271   f.samples = sizeof (slin_ulaw_ex) / 2;
272   f.mallocd = 0;
273   f.offset = 0;
274   f.src = __PRETTY_FUNCTION__;
275   f.data = slin_ulaw_ex;
276   return &f;
277 }
278
279 /*
280  * ulaw_Destroy
281  *  Destroys a private workspace.
282  *
283  * Results:
284  *  It's gone!
285  *
286  * Side effects:
287  *  None.
288  */
289
290 static void
291 ulaw_destroy (struct ast_translator_pvt *pvt)
292 {
293   free (pvt);
294   localusecnt--;
295   ast_update_use_count ();
296 }
297
298 /*
299  * The complete translator for ulawToLin.
300  */
301
302 static struct ast_translator ulawtolin = {
303   "ulawtolin",
304   AST_FORMAT_ULAW,
305   AST_FORMAT_SLINEAR,
306   ulawtolin_new,
307   ulawtolin_framein,
308   ulawtolin_frameout,
309   ulaw_destroy,
310   /* NULL */
311   ulawtolin_sample
312 };
313
314 /*
315  * The complete translator for LinToulaw.
316  */
317
318 static struct ast_translator lintoulaw = {
319   "lintoulaw",
320   AST_FORMAT_SLINEAR,
321   AST_FORMAT_ULAW,
322   lintoulaw_new,
323   lintoulaw_framein,
324   lintoulaw_frameout,
325   ulaw_destroy,
326   /* NULL */
327   lintoulaw_sample
328 };
329
330 int
331 unload_module (void)
332 {
333   int res;
334   ast_mutex_lock (&localuser_lock);
335   res = ast_unregister_translator (&lintoulaw);
336   if (!res)
337     res = ast_unregister_translator (&ulawtolin);
338   if (localusecnt)
339     res = -1;
340   ast_mutex_unlock (&localuser_lock);
341   return res;
342 }
343
344 int
345 load_module (void)
346 {
347   int res;
348   res = ast_register_translator (&ulawtolin);
349   if (!res)
350     res = ast_register_translator (&lintoulaw);
351   else
352     ast_unregister_translator (&ulawtolin);
353   return res;
354 }
355
356 /*
357  * Return a description of this module.
358  */
359
360 char *
361 description (void)
362 {
363   return tdesc;
364 }
365
366 int
367 usecount (void)
368 {
369   int res;
370   STANDARD_USECOUNT (res);
371   return res;
372 }
373
374 char *
375 key ()
376 {
377   return ASTERISK_GPL_KEY;
378 }