Merge FreeBSD locking fixes (bug #1411)
[asterisk/asterisk.git] / codecs / codec_a_mu.c
1 /* codec_a_mu.c - translate between alaw and ulaw directly
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/alaw.h>
19 #include <asterisk/ulaw.h>
20 #include <fcntl.h>
21 #include <netinet/in.h>
22 #include <pthread.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #define BUFFER_SIZE   8096      /* size for the translation buffers */
29
30 AST_MUTEX_DEFINE_STATIC(localuser_lock);
31 static int localusecnt = 0;
32
33 static char *tdesc = "A-law and Mulaw direct Coder/Decoder";
34
35 static unsigned char mu2a[256];
36 static unsigned char a2mu[256];
37
38 /* Sample frame data (Mu data is okay) */
39
40 #include "ulaw_slin_ex.h"
41
42 /*
43  * Private workspace for translating signed linear signals to alaw.
44  */
45
46 struct alaw_encoder_pvt
47 {
48   struct ast_frame f;
49   char offset[AST_FRIENDLY_OFFSET];   /* Space to build offset */
50   unsigned char outbuf[BUFFER_SIZE];  /* Encoded alaw, two nibbles to a word */
51   int tail;
52 };
53
54 /*
55  * Private workspace for translating laws.
56  */
57
58 struct ulaw_encoder_pvt
59 {
60   struct ast_frame f;
61   char offset[AST_FRIENDLY_OFFSET];     /* Space to build offset */
62   unsigned char outbuf[BUFFER_SIZE];    /* Encoded ulaw values */
63   int tail;
64 };
65
66 static struct ast_translator_pvt *
67 alawtoulaw_new (void)
68 {
69   struct ulaw_encoder_pvt *tmp;
70   tmp = malloc (sizeof (struct ulaw_encoder_pvt));
71   if (tmp)
72     {
73           memset(tmp, 0, sizeof(*tmp));
74       tmp->tail = 0;
75       localusecnt++;
76       ast_update_use_count ();
77     }
78   return (struct ast_translator_pvt *) tmp;
79 }
80
81 static struct ast_translator_pvt *
82 ulawtoalaw_new (void)
83 {
84   struct alaw_encoder_pvt *tmp;
85   tmp = malloc (sizeof (struct alaw_encoder_pvt));
86   if (tmp)
87     {
88           memset(tmp, 0, sizeof(*tmp));
89       localusecnt++;
90       ast_update_use_count ();
91       tmp->tail = 0;
92     }
93   return (struct ast_translator_pvt *) tmp;
94 }
95
96 static int
97 alawtoulaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
98 {
99   struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
100   int x;
101   unsigned char *b;
102
103   if ((tmp->tail + f->datalen)> sizeof(tmp->outbuf)) {
104         ast_log(LOG_WARNING, "Out of buffer space\n");
105         return -1;
106   }
107
108   /* Reset ssindex and signal to frame's specified values */
109   b = f->data;
110   for (x=0;x<f->datalen;x++)
111         tmp->outbuf[tmp->tail + x] = a2mu[b[x]];
112
113   tmp->tail += f->datalen;
114   return 0;
115 }
116
117 static struct ast_frame *
118 alawtoulaw_frameout (struct ast_translator_pvt *pvt)
119 {
120   struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
121
122   if (!tmp->tail)
123     return NULL;
124
125   tmp->f.frametype = AST_FRAME_VOICE;
126   tmp->f.subclass = AST_FORMAT_ULAW;
127   tmp->f.datalen = tmp->tail;
128   tmp->f.samples = tmp->tail;
129   tmp->f.mallocd = 0;
130   tmp->f.offset = AST_FRIENDLY_OFFSET;
131   tmp->f.src = __PRETTY_FUNCTION__;
132   tmp->f.data = tmp->outbuf;
133   tmp->tail = 0;
134   return &tmp->f;
135 }
136
137 static int
138 ulawtoalaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
139 {
140   struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
141   int x;
142   unsigned char *s;
143   if (tmp->tail + f->datalen >= sizeof(tmp->outbuf))
144     {
145       ast_log (LOG_WARNING, "Out of buffer space\n");
146       return -1;
147     }
148   s = f->data;
149   for (x=0;x<f->datalen;x++) 
150         tmp->outbuf[x+tmp->tail] = mu2a[s[x]];
151   tmp->tail += f->datalen;
152   return 0;
153 }
154
155 /*
156  * LinToalaw_FrameOut
157  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
158  *  of 4-bit alaw packed two to a byte (Big Endian).
159  *
160  * Results:
161  *  Foo
162  *
163  * Side effects:
164  *  Leftover inbuf data gets packed, tail gets updated.
165  */
166
167 static struct ast_frame *
168 ulawtoalaw_frameout (struct ast_translator_pvt *pvt)
169 {
170   struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
171   
172   if (tmp->tail) {
173           tmp->f.frametype = AST_FRAME_VOICE;
174           tmp->f.subclass = AST_FORMAT_ALAW;
175           tmp->f.samples = tmp->tail;
176           tmp->f.mallocd = 0;
177           tmp->f.offset = AST_FRIENDLY_OFFSET;
178           tmp->f.src = __PRETTY_FUNCTION__;
179           tmp->f.data = tmp->outbuf;
180           tmp->f.datalen = tmp->tail;
181           tmp->tail = 0;
182           return &tmp->f;
183    } else return NULL;
184 }
185
186
187 /*
188  * alawToLin_Sample
189  */
190
191 static struct ast_frame *
192 alawtoulaw_sample (void)
193 {
194   static struct ast_frame f;
195   f.frametype = AST_FRAME_VOICE;
196   f.subclass = AST_FORMAT_ALAW;
197   f.datalen = sizeof (ulaw_slin_ex);
198   f.samples = sizeof(ulaw_slin_ex);
199   f.mallocd = 0;
200   f.offset = 0;
201   f.src = __PRETTY_FUNCTION__;
202   f.data = ulaw_slin_ex;
203   return &f;
204 }
205
206 static struct ast_frame *
207 ulawtoalaw_sample (void)
208 {
209   static struct ast_frame f;
210   f.frametype = AST_FRAME_VOICE;
211   f.subclass = AST_FORMAT_ULAW;
212   f.datalen = sizeof (ulaw_slin_ex);
213   f.samples = sizeof(ulaw_slin_ex);
214   f.mallocd = 0;
215   f.offset = 0;
216   f.src = __PRETTY_FUNCTION__;
217   f.data = ulaw_slin_ex;
218   return &f;
219 }
220
221
222 /*
223  * alaw_Destroy
224  *  Destroys a private workspace.
225  *
226  * Results:
227  *  It's gone!
228  *
229  * Side effects:
230  *  None.
231  */
232
233 static void
234 alaw_destroy (struct ast_translator_pvt *pvt)
235 {
236   free (pvt);
237   localusecnt--;
238   ast_update_use_count ();
239 }
240
241 /*
242  * The complete translator for alawToLin.
243  */
244
245 static struct ast_translator alawtoulaw = {
246   "alawtoulaw",
247   AST_FORMAT_ALAW,
248   AST_FORMAT_ULAW,
249   alawtoulaw_new,
250   alawtoulaw_framein,
251   alawtoulaw_frameout,
252   alaw_destroy,
253   /* NULL */
254   alawtoulaw_sample
255 };
256
257 /*
258  * The complete translator for LinToalaw.
259  */
260
261 static struct ast_translator ulawtoalaw = {
262   "ulawtoalaw",
263   AST_FORMAT_ULAW,
264   AST_FORMAT_ALAW,
265   ulawtoalaw_new,
266   ulawtoalaw_framein,
267   ulawtoalaw_frameout,
268   alaw_destroy,
269   /* NULL */
270   ulawtoalaw_sample
271 };
272
273 int
274 unload_module (void)
275 {
276   int res;
277   ast_mutex_lock (&localuser_lock);
278   res = ast_unregister_translator (&ulawtoalaw);
279   if (!res)
280     res = ast_unregister_translator (&alawtoulaw);
281   if (localusecnt)
282     res = -1;
283   ast_mutex_unlock (&localuser_lock);
284   return res;
285 }
286
287 int
288 load_module (void)
289 {
290   int res;
291   int x;
292   for (x=0;x<256;x++) {
293         mu2a[x] = AST_LIN2A(AST_MULAW(x));
294         a2mu[x] = AST_LIN2MU(AST_ALAW(x));
295   }
296   res = ast_register_translator (&alawtoulaw);
297   if (!res)
298     res = ast_register_translator (&ulawtoalaw);
299   else
300     ast_unregister_translator (&alawtoulaw);
301   return res;
302 }
303
304 /*
305  * Return a description of this module.
306  */
307
308 char *
309 description (void)
310 {
311   return tdesc;
312 }
313
314 int
315 usecount (void)
316 {
317   int res;
318   STANDARD_USECOUNT (res);
319   return res;
320 }
321
322 char *
323 key ()
324 {
325   return ASTERISK_GPL_KEY;
326 }