Bring in the new loader code as described in mantis #4377
[asterisk/asterisk.git] / codecs / codec_alaw.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief codec_alaw.c - translate between signed linear and alaw
22  * 
23  * \ingroup codecs
24  */
25
26 #include <fcntl.h>
27 #include <netinet/in.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 #include "asterisk.h"
34
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36
37 #include "asterisk/lock.h"
38 #include "asterisk/logger.h"
39 #include "asterisk/module.h"
40 #include "asterisk/config.h"
41 #include "asterisk/options.h"
42 #include "asterisk/translate.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/alaw.h"
45 #include "asterisk/utils.h"
46
47 #define BUFFER_SIZE   8096      /* size for the translation buffers */
48
49 AST_MUTEX_DEFINE_STATIC(localuser_lock);
50 static int localusecnt = 0;
51
52 static char *tdesc = "A-law Coder/Decoder";
53
54 static int useplc = 0;
55
56 /* Sample frame data (Mu data is okay) */
57
58 #include "slin_ulaw_ex.h"
59 #include "ulaw_slin_ex.h"
60
61 /*!
62  * \brief Private workspace for translating signed linear signals to alaw.
63  */
64 struct alaw_encoder_pvt
65 {
66         struct ast_frame f;
67         char offset[AST_FRIENDLY_OFFSET];   /*!< Space to build offset */
68         unsigned char outbuf[BUFFER_SIZE];  /*!< Encoded alaw, two nibbles to a word */
69         int tail;
70 };
71
72 /*!
73  * \brief Private workspace for translating alaw signals to signed linear.
74  */
75 struct alaw_decoder_pvt
76 {
77         struct ast_frame f;
78         char offset[AST_FRIENDLY_OFFSET];       /* Space to build offset */
79         short outbuf[BUFFER_SIZE];              /* Decoded signed linear values */
80         int tail;
81         plc_state_t plc;
82 };
83
84 /*!
85  * \brief alawToLin_New
86  *  Create a new instance of alaw_decoder_pvt.
87  *
88  * Results:
89  *  Returns a pointer to the new instance.
90  *
91  * Side effects:
92  *  None.
93  */
94
95 static struct ast_translator_pvt *alawtolin_new(void)
96 {
97         struct alaw_decoder_pvt *tmp;
98         
99         if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
100                 tmp->tail = 0;
101                 plc_init(&tmp->plc);
102                 localusecnt++;
103                 ast_update_use_count();
104         }
105
106         return (struct ast_translator_pvt *)tmp;
107 }
108
109 /*!
110  * \brief LinToalaw_New
111  *  Create a new instance of alaw_encoder_pvt.
112  *
113  * Results:
114  *  Returns a pointer to the new instance.
115  *
116  * Side effects:
117  *  None.
118  */
119
120 static struct ast_translator_pvt *lintoalaw_new(void)
121 {
122         struct alaw_encoder_pvt *tmp;
123
124         if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
125                 localusecnt++;
126                 ast_update_use_count();
127                 tmp->tail = 0;
128         }
129
130         return (struct ast_translator_pvt *)tmp;
131 }
132
133 /*!
134  * \brief alawToLin_FrameIn
135  *  Fill an input buffer with packed 4-bit alaw values if there is room
136  *  left.
137  *
138  * Results:
139  *  Foo
140  *
141  * Side effects:
142  *  tmp->tail is the number of packed values in the buffer.
143  */
144
145 static int alawtolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
146 {
147         struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *)pvt;
148         int x;
149         unsigned char *b;
150
151         if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
152                 if((tmp->tail + 160) * 2 > sizeof(tmp->outbuf)) {
153                         ast_log(LOG_WARNING, "Out of buffer space\n");
154                         return -1;
155                 }
156                 if(useplc) {
157                         plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
158                         tmp->tail += 160;
159                 }
160                 return 0;
161         }
162
163         if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
164                 ast_log(LOG_WARNING, "Out of buffer space\n");
165                 return -1;
166         }
167
168         /* Reset ssindex and signal to frame's specified values */
169         b = f->data;
170         for (x=0;x<f->datalen;x++)
171                 tmp->outbuf[tmp->tail + x] = AST_ALAW(b[x]);
172
173         if(useplc)
174                 plc_rx(&tmp->plc, tmp->outbuf+tmp->tail, f->datalen);
175
176         tmp->tail += f->datalen;
177         return 0;
178 }
179
180 /*!
181  * \brief alawToLin_FrameOut
182  *  Convert 4-bit alaw encoded signals to 16-bit signed linear.
183  *
184  * Results:
185  *  Converted signals are placed in tmp->f.data, tmp->f.datalen
186  *  and tmp->f.samples are calculated.
187  *
188  * Side effects:
189  *  None.
190  */
191
192 static struct ast_frame *alawtolin_frameout(struct ast_translator_pvt *pvt)
193 {
194         struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *)pvt;
195
196         if (!tmp->tail)
197                 return NULL;
198
199         tmp->f.frametype = AST_FRAME_VOICE;
200         tmp->f.subclass = AST_FORMAT_SLINEAR;
201         tmp->f.datalen = tmp->tail * 2;
202         tmp->f.samples = tmp->tail;
203         tmp->f.mallocd = 0;
204         tmp->f.offset = AST_FRIENDLY_OFFSET;
205         tmp->f.src = __PRETTY_FUNCTION__;
206         tmp->f.data = tmp->outbuf;
207         tmp->tail = 0;
208         return &tmp->f;
209 }
210
211 /*!
212  * \brief LinToalaw_FrameIn
213  *  Fill an input buffer with 16-bit signed linear PCM values.
214  *
215  * Results:
216  *  None.
217  *
218  * Side effects:
219  *  tmp->tail is number of signal values in the input buffer.
220  */
221
222 static int lintoalaw_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
223 {
224         struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *)pvt;
225         int x;
226         short *s;
227         if (tmp->tail + f->datalen / 2 >= sizeof(tmp->outbuf)) {
228                 ast_log(LOG_WARNING, "Out of buffer space\n");
229                 return -1;
230         }
231         s = f->data;
232         for (x=0;x<f->datalen/2;x++) 
233                 tmp->outbuf[x+tmp->tail] = AST_LIN2A(s[x]);
234         tmp->tail += f->datalen/2;
235         return 0;
236 }
237
238 /*!
239  * \brief LinToalaw_FrameOut
240  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
241  *  of 4-bit alaw packed two to a byte (Big Endian).
242  *
243  * Results:
244  *  Foo
245  *
246  * Side effects:
247  *  Leftover inbuf data gets packed, tail gets updated.
248  */
249
250 static struct ast_frame *lintoalaw_frameout(struct ast_translator_pvt *pvt)
251 {
252         struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *)pvt;
253   
254         if (tmp->tail) {
255                 tmp->f.frametype = AST_FRAME_VOICE;
256                 tmp->f.subclass = AST_FORMAT_ALAW;
257                 tmp->f.samples = tmp->tail;
258                 tmp->f.mallocd = 0;
259                 tmp->f.offset = AST_FRIENDLY_OFFSET;
260                 tmp->f.src = __PRETTY_FUNCTION__;
261                 tmp->f.data = tmp->outbuf;
262                 tmp->f.datalen = tmp->tail;
263                 tmp->tail = 0;
264                 return &tmp->f;
265         } else
266                 return NULL;
267 }
268
269 /*!
270  * \brief alawToLin_Sample
271  */
272
273 static struct ast_frame *alawtolin_sample(void)
274 {
275         static struct ast_frame f;
276         f.frametype = AST_FRAME_VOICE;
277         f.subclass = AST_FORMAT_ALAW;
278         f.datalen = sizeof(ulaw_slin_ex);
279         f.samples = sizeof(ulaw_slin_ex);
280         f.mallocd = 0;
281         f.offset = 0;
282         f.src = __PRETTY_FUNCTION__;
283         f.data = ulaw_slin_ex;
284         return &f;
285 }
286
287 /*!
288  * \brief LinToalaw_Sample
289  */
290
291 static struct ast_frame *lintoalaw_sample(void)
292 {
293         static struct ast_frame f;
294         f.frametype = AST_FRAME_VOICE;
295         f.subclass = AST_FORMAT_SLINEAR;
296         f.datalen = sizeof(slin_ulaw_ex);
297         /* Assume 8000 Hz */
298         f.samples = sizeof(slin_ulaw_ex) / 2;
299         f.mallocd = 0;
300         f.offset = 0;
301         f.src = __PRETTY_FUNCTION__;
302         f.data = slin_ulaw_ex;
303         return &f;
304 }
305
306 /*!
307  * \brief alaw_Destroy
308  *  Destroys a private workspace.
309  *
310  * Results:
311  *  It's gone!
312  *
313  * Side effects:
314  *  None.
315  */
316
317 static void alaw_destroy(struct ast_translator_pvt *pvt)
318 {
319         free(pvt);
320         localusecnt--;
321         ast_update_use_count();
322 }
323
324 /*!
325  * \brief The complete translator for alawToLin.
326  */
327
328 static struct ast_translator alawtolin = {
329         "alawtolin",
330         AST_FORMAT_ALAW,
331         AST_FORMAT_SLINEAR,
332         alawtolin_new,
333         alawtolin_framein,
334         alawtolin_frameout,
335         alaw_destroy,
336         /* NULL */
337         alawtolin_sample
338 };
339
340 /*!
341  * \brief The complete translator for LinToalaw.
342  */
343
344 static struct ast_translator lintoalaw = {
345         "lintoalaw",
346         AST_FORMAT_SLINEAR,
347         AST_FORMAT_ALAW,
348         lintoalaw_new,
349         lintoalaw_framein,
350         lintoalaw_frameout,
351         alaw_destroy,
352         /* NULL */
353         lintoalaw_sample
354 };
355
356 static void parse_config(void)
357 {
358         struct ast_config *cfg;
359         struct ast_variable *var;
360
361         if ((cfg = ast_config_load("codecs.conf"))) {
362                 if ((var = ast_variable_browse(cfg, "plc"))) {
363                         while (var) {
364                                 if (!strcasecmp(var->name, "genericplc")) {
365                                         useplc = ast_true(var->value) ? 1 : 0;
366                                         if (option_verbose > 2)
367                                                 ast_verbose(VERBOSE_PREFIX_3 "codec_alaw: %susing generic PLC\n", useplc ? "" : "not ");
368                                 }
369                                 var = var->next;
370                         }
371                 }
372                 ast_config_destroy(cfg);
373         }
374 }
375
376 int reload(void)
377 {
378         parse_config();
379         return 0;
380 }
381
382 int unload_module(void)
383 {
384         int res;
385         ast_mutex_lock(&localuser_lock);
386         res = ast_unregister_translator(&lintoalaw);
387         if (!res)
388                 res = ast_unregister_translator(&alawtolin);
389         if (localusecnt)
390                 res = -1;
391         ast_mutex_unlock(&localuser_lock);
392         return res;
393 }
394
395 int load_module(void)
396 {
397         int res;
398         parse_config();
399         res = ast_register_translator(&alawtolin);
400         if (!res)
401                 res = ast_register_translator(&lintoalaw);
402         else
403                 ast_unregister_translator(&alawtolin);
404         return res;
405 }
406
407 /*
408  * Return a description of this module.
409  */
410
411 char *description(void)
412 {
413         return tdesc;
414 }
415
416 int usecount(void)
417 {
418         int res;
419         OLD_STANDARD_USECOUNT(res);
420         return res;
421 }
422
423 char *key()
424 {
425         return ASTERISK_GPL_KEY;
426 }