include "logger.h" and errno.h from asterisk.h - usage shows that they
[asterisk/asterisk.git] / codecs / codec_g722.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Matthew Fredrickson <creslin@digium.com>
7  *
8  * Special thanks to Steve Underwood for the implementation
9  * and for doing the 8khz<->g.722 direct translation code.
10  *
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2. See the LICENSE file
19  * at the top of the source tree.
20  */
21
22 /*! \file
23  *
24  * \brief codec_g722.c - translate between signed linear and ITU G.722-64kbps
25  *
26  * \ingroup codecs
27  */
28
29 #include "asterisk.h"
30
31 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
32
33 #include <fcntl.h>
34 #include <netinet/in.h>
35
36 #include "asterisk/lock.h"
37 #include "asterisk/linkedlists.h"
38 #include "asterisk/module.h"
39 #include "asterisk/config.h"
40 #include "asterisk/options.h"
41 #include "asterisk/translate.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/utils.h"
44
45 #define BUFFER_SAMPLES   8096   /* size for the translation buffers */
46 #define BUF_SHIFT       5
47
48 /* Sample frame data */
49
50 #include "g722/g722.h"
51 #include "slin_g722_ex.h"
52 #include "g722_slin_ex.h"
53
54 struct g722_encoder_pvt {
55         g722_encode_state_t g722;
56 };
57
58 struct g722_decoder_pvt {
59         g722_decode_state_t g722;
60 };
61
62 /*! \brief init a new instance of g722_encoder_pvt. */
63 static int lintog722_new(struct ast_trans_pvt *pvt)
64 {
65         struct g722_encoder_pvt *tmp = pvt->pvt;
66
67         g722_encode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
68
69         return 0;
70 }
71
72 static int lin16tog722_new(struct ast_trans_pvt *pvt)
73 {
74         struct g722_encoder_pvt *tmp = pvt->pvt;
75
76         g722_encode_init(&tmp->g722, 64000, 0);
77
78         return 0;
79 }
80
81 /*! \brief init a new instance of g722_encoder_pvt. */
82 static int g722tolin_new(struct ast_trans_pvt *pvt)
83 {
84         struct g722_decoder_pvt *tmp = pvt->pvt;
85
86         g722_decode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
87
88         return 0;
89 }
90
91 static int g722tolin16_new(struct ast_trans_pvt *pvt)
92 {
93         struct g722_decoder_pvt *tmp = pvt->pvt;
94
95         g722_decode_init(&tmp->g722, 64000, 0);
96
97         return 0;
98 }
99
100 static int g722tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
101 {
102         struct g722_decoder_pvt *tmp = pvt->pvt;
103         unsigned char *src = f->data;
104         int16_t *dst = (int16_t *) pvt->outbuf + pvt->samples;
105
106         g722_decode(&tmp->g722, dst, src, f->samples);
107         pvt->samples += f->samples;
108         pvt->datalen += 2 * f->samples;
109
110         return 0;
111 }
112
113 static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
114 {
115         struct g722_encoder_pvt *tmp = pvt->pvt;
116         int16_t *src = f->data;
117
118         g722_encode(&tmp->g722, (uint8_t*)(&pvt->outbuf[pvt->datalen]), src, f->samples);
119         /* Since G.722 64kbps per second is one bye per sample, all of these
120            calculations are easy */
121         pvt->samples += f->samples;
122         pvt->datalen += f->samples;
123
124         return 0;
125 }
126
127 static struct ast_frame *g722tolin_sample(void)
128 {
129         static struct ast_frame f = {
130                 .frametype = AST_FRAME_VOICE,
131                 .subclass = AST_FORMAT_G722,
132                 .datalen = sizeof(g722_slin_ex),
133                 .samples = sizeof(g722_slin_ex) / sizeof(g722_slin_ex[0]),
134                 .src = __PRETTY_FUNCTION__,
135                 .data = g722_slin_ex,
136         };
137
138         return &f;
139 }
140
141 static struct ast_frame *g722tolin16_sample(void)
142 {
143         static struct ast_frame f = {
144                 .frametype = AST_FRAME_VOICE,
145                 .subclass = AST_FORMAT_G722,
146                 .datalen = sizeof(slin_g722_ex),
147                 .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]),
148                 .src = __PRETTY_FUNCTION__,
149                 .data = slin_g722_ex,
150         };
151
152         return &f;
153 }
154
155 static struct ast_frame *lintog722_sample (void)
156 {
157         static struct ast_frame f = {
158                 .frametype = AST_FRAME_VOICE,
159                 .subclass = AST_FORMAT_SLINEAR,
160                 .datalen = sizeof(slin_g722_ex),
161                 .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]),
162                 .src = __PRETTY_FUNCTION__,
163                 .data = slin_g722_ex,
164         };
165
166         return &f;
167 }
168
169 static struct ast_frame *lin16tog722_sample (void)
170 {
171         static struct ast_frame f = {
172                 .frametype = AST_FRAME_VOICE,
173                 .subclass = AST_FORMAT_SLINEAR16,
174                 .datalen = sizeof(slin_g722_ex),
175                 .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]),
176                 .src = __PRETTY_FUNCTION__,
177                 .data = slin_g722_ex,
178         };
179
180         return &f;
181 }
182
183 static struct ast_translator g722tolin = {
184         .name = "g722tolin",
185         .srcfmt = AST_FORMAT_G722,
186         .dstfmt = AST_FORMAT_SLINEAR,
187         .newpvt = g722tolin_new,        /* same for both directions */
188         .framein = g722tolin_framein,
189         .sample = g722tolin_sample,
190         .desc_size = sizeof(struct g722_decoder_pvt),
191         .buffer_samples = BUFFER_SAMPLES,
192         .buf_size = BUFFER_SAMPLES,
193         .plc_samples = 160,
194 };
195
196 static struct ast_translator lintog722 = {
197         .name = "lintog722",
198         .srcfmt = AST_FORMAT_SLINEAR,
199         .dstfmt = AST_FORMAT_G722,
200         .newpvt = lintog722_new,        /* same for both directions */
201         .framein = lintog722_framein,
202         .sample = lintog722_sample,
203         .desc_size = sizeof(struct g722_encoder_pvt),
204         .buffer_samples = BUFFER_SAMPLES,
205         .buf_size = BUFFER_SAMPLES,
206 };
207
208 static struct ast_translator g722tolin16 = {
209         .name = "g722tolin16",
210         .srcfmt = AST_FORMAT_G722,
211         .dstfmt = AST_FORMAT_SLINEAR16,
212         .newpvt = g722tolin16_new,      /* same for both directions */
213         .framein = g722tolin_framein,
214         .sample = g722tolin16_sample,
215         .desc_size = sizeof(struct g722_decoder_pvt),
216         .buffer_samples = BUFFER_SAMPLES,
217         .buf_size = BUFFER_SAMPLES,
218         .plc_samples = 160,
219 };
220
221 static struct ast_translator lin16tog722 = {
222         .name = "lin16tog722",
223         .srcfmt = AST_FORMAT_SLINEAR16,
224         .dstfmt = AST_FORMAT_G722,
225         .newpvt = lin16tog722_new,      /* same for both directions */
226         .framein = lintog722_framein,
227         .sample = lin16tog722_sample,
228         .desc_size = sizeof(struct g722_encoder_pvt),
229         .buffer_samples = BUFFER_SAMPLES,
230         .buf_size = BUFFER_SAMPLES,
231 };
232
233 static int parse_config(int reload)
234 {
235         struct ast_variable *var;
236         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
237         struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
238
239         if (cfg == NULL)
240                 return -1;
241         if (cfg == CONFIG_STATUS_FILEUNCHANGED)
242                 return 0;
243         for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
244                 if (!strcasecmp(var->name, "genericplc")) {
245                         g722tolin.useplc = ast_true(var->value) ? 1 : 0;
246                         ast_verb(3, "codec_g722: %susing generic PLC\n",
247                                         g722tolin.useplc ? "" : "not ");
248                 }
249         }
250         ast_config_destroy(cfg);
251         return 0;
252 }
253
254 static int reload(void)
255 {
256         if (parse_config(1))
257                 return AST_MODULE_LOAD_DECLINE;
258         return AST_MODULE_LOAD_SUCCESS;
259 }
260
261 static int unload_module(void)
262 {
263         int res = 0;
264
265         res |= ast_unregister_translator(&g722tolin);
266         res |= ast_unregister_translator(&lintog722);
267         res |= ast_unregister_translator(&g722tolin16);
268         res |= ast_unregister_translator(&lin16tog722);
269
270         return res;
271 }
272
273 static int load_module(void)
274 {
275         int res = 0;
276
277         if (parse_config(0))
278                 return AST_MODULE_LOAD_DECLINE;
279
280         res |= ast_register_translator(&g722tolin);
281         res |= ast_register_translator(&lintog722);
282         res |= ast_register_translator(&g722tolin16);
283         res |= ast_register_translator(&lin16tog722);
284
285         if (res) {
286                 unload_module();
287                 return AST_MODULE_LOAD_FAILURE;
288         }       
289
290         return AST_MODULE_LOAD_SUCCESS;
291 }
292
293 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder",
294                 .load = load_module,
295                 .unload = unload_module,
296                 .reload = reload,
297                );