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