I went looking for where we downloaded the g722 implementation and came across
[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  * \arg http://soft-switch.org/downloads/non-gpl-bits.tgz
27  * \arg http://lists.digium.com/pipermail/asterisk-dev/2006-September/022866.html
28  *
29  * \ingroup codecs
30  */
31
32 #include "asterisk.h"
33
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include "asterisk/linkedlists.h"
37 #include "asterisk/module.h"
38 #include "asterisk/config.h"
39 #include "asterisk/translate.h"
40 #include "asterisk/utils.h"
41
42 #define BUFFER_SAMPLES   8096   /* size for the translation buffers */
43 #define BUF_SHIFT       5
44
45 /* Sample frame data */
46
47 #include "g722/g722.h"
48 #include "slin_g722_ex.h"
49 #include "g722_slin_ex.h"
50
51 struct g722_encoder_pvt {
52         g722_encode_state_t g722;
53 };
54
55 struct g722_decoder_pvt {
56         g722_decode_state_t g722;
57 };
58
59 /*! \brief init a new instance of g722_encoder_pvt. */
60 static int lintog722_new(struct ast_trans_pvt *pvt)
61 {
62         struct g722_encoder_pvt *tmp = pvt->pvt;
63
64         g722_encode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
65
66         return 0;
67 }
68
69 static int lin16tog722_new(struct ast_trans_pvt *pvt)
70 {
71         struct g722_encoder_pvt *tmp = pvt->pvt;
72
73         g722_encode_init(&tmp->g722, 64000, 0);
74
75         return 0;
76 }
77
78 /*! \brief init a new instance of g722_encoder_pvt. */
79 static int g722tolin_new(struct ast_trans_pvt *pvt)
80 {
81         struct g722_decoder_pvt *tmp = pvt->pvt;
82
83         g722_decode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
84
85         return 0;
86 }
87
88 static int g722tolin16_new(struct ast_trans_pvt *pvt)
89 {
90         struct g722_decoder_pvt *tmp = pvt->pvt;
91
92         g722_decode_init(&tmp->g722, 64000, 0);
93
94         return 0;
95 }
96
97 static int g722tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
98 {
99         struct g722_decoder_pvt *tmp = pvt->pvt;
100         unsigned char *src = f->data;
101         int16_t *dst = (int16_t *) pvt->outbuf + pvt->samples;
102
103         g722_decode(&tmp->g722, dst, src, f->samples);
104         pvt->samples += f->samples;
105         pvt->datalen += 2 * f->samples;
106
107         return 0;
108 }
109
110 static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
111 {
112         struct g722_encoder_pvt *tmp = pvt->pvt;
113         int16_t *src = f->data;
114
115         g722_encode(&tmp->g722, (uint8_t*)(&pvt->outbuf[pvt->datalen]), src, f->samples);
116         /* Since G.722 64kbps per second is one bye per sample, all of these
117            calculations are easy */
118         pvt->samples += f->samples;
119         pvt->datalen += f->samples;
120
121         return 0;
122 }
123
124 static struct ast_frame *g722tolin_sample(void)
125 {
126         static struct ast_frame f = {
127                 .frametype = AST_FRAME_VOICE,
128                 .subclass = AST_FORMAT_G722,
129                 .datalen = sizeof(g722_slin_ex),
130                 .samples = sizeof(g722_slin_ex) / sizeof(g722_slin_ex[0]),
131                 .src = __PRETTY_FUNCTION__,
132                 .data = g722_slin_ex,
133         };
134
135         return &f;
136 }
137
138 static struct ast_frame *g722tolin16_sample(void)
139 {
140         static struct ast_frame f = {
141                 .frametype = AST_FRAME_VOICE,
142                 .subclass = AST_FORMAT_G722,
143                 .datalen = sizeof(slin_g722_ex),
144                 .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]),
145                 .src = __PRETTY_FUNCTION__,
146                 .data = slin_g722_ex,
147         };
148
149         return &f;
150 }
151
152 static struct ast_frame *lintog722_sample (void)
153 {
154         static struct ast_frame f = {
155                 .frametype = AST_FRAME_VOICE,
156                 .subclass = AST_FORMAT_SLINEAR,
157                 .datalen = sizeof(slin_g722_ex),
158                 .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]),
159                 .src = __PRETTY_FUNCTION__,
160                 .data = slin_g722_ex,
161         };
162
163         return &f;
164 }
165
166 static struct ast_frame *lin16tog722_sample (void)
167 {
168         static struct ast_frame f = {
169                 .frametype = AST_FRAME_VOICE,
170                 .subclass = AST_FORMAT_SLINEAR16,
171                 .datalen = sizeof(slin_g722_ex),
172                 .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]),
173                 .src = __PRETTY_FUNCTION__,
174                 .data = slin_g722_ex,
175         };
176
177         return &f;
178 }
179
180 static struct ast_translator g722tolin = {
181         .name = "g722tolin",
182         .srcfmt = AST_FORMAT_G722,
183         .dstfmt = AST_FORMAT_SLINEAR,
184         .newpvt = g722tolin_new,        /* same for both directions */
185         .framein = g722tolin_framein,
186         .sample = g722tolin_sample,
187         .desc_size = sizeof(struct g722_decoder_pvt),
188         .buffer_samples = BUFFER_SAMPLES,
189         .buf_size = BUFFER_SAMPLES,
190         .plc_samples = 160,
191 };
192
193 static struct ast_translator lintog722 = {
194         .name = "lintog722",
195         .srcfmt = AST_FORMAT_SLINEAR,
196         .dstfmt = AST_FORMAT_G722,
197         .newpvt = lintog722_new,        /* same for both directions */
198         .framein = lintog722_framein,
199         .sample = lintog722_sample,
200         .desc_size = sizeof(struct g722_encoder_pvt),
201         .buffer_samples = BUFFER_SAMPLES,
202         .buf_size = BUFFER_SAMPLES,
203 };
204
205 static struct ast_translator g722tolin16 = {
206         .name = "g722tolin16",
207         .srcfmt = AST_FORMAT_G722,
208         .dstfmt = AST_FORMAT_SLINEAR16,
209         .newpvt = g722tolin16_new,      /* same for both directions */
210         .framein = g722tolin_framein,
211         .sample = g722tolin16_sample,
212         .desc_size = sizeof(struct g722_decoder_pvt),
213         .buffer_samples = BUFFER_SAMPLES,
214         .buf_size = BUFFER_SAMPLES,
215         .plc_samples = 160,
216 };
217
218 static struct ast_translator lin16tog722 = {
219         .name = "lin16tog722",
220         .srcfmt = AST_FORMAT_SLINEAR16,
221         .dstfmt = AST_FORMAT_G722,
222         .newpvt = lin16tog722_new,      /* same for both directions */
223         .framein = lintog722_framein,
224         .sample = lin16tog722_sample,
225         .desc_size = sizeof(struct g722_encoder_pvt),
226         .buffer_samples = BUFFER_SAMPLES,
227         .buf_size = BUFFER_SAMPLES,
228 };
229
230 static int parse_config(int reload)
231 {
232         struct ast_variable *var;
233         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
234         struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
235
236         if (cfg == NULL)
237                 return 0;
238         if (cfg == CONFIG_STATUS_FILEUNCHANGED)
239                 return 0;
240         for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
241                 if (!strcasecmp(var->name, "genericplc")) {
242                         g722tolin.useplc = ast_true(var->value) ? 1 : 0;
243                         ast_verb(3, "codec_g722: %susing generic PLC\n",
244                                         g722tolin.useplc ? "" : "not ");
245                 }
246         }
247         ast_config_destroy(cfg);
248         return 0;
249 }
250
251 static int reload(void)
252 {
253         if (parse_config(1))
254                 return AST_MODULE_LOAD_DECLINE;
255         return AST_MODULE_LOAD_SUCCESS;
256 }
257
258 static int unload_module(void)
259 {
260         int res = 0;
261
262         res |= ast_unregister_translator(&g722tolin);
263         res |= ast_unregister_translator(&lintog722);
264         res |= ast_unregister_translator(&g722tolin16);
265         res |= ast_unregister_translator(&lin16tog722);
266
267         return res;
268 }
269
270 static int load_module(void)
271 {
272         int res = 0;
273
274         if (parse_config(0))
275                 return AST_MODULE_LOAD_DECLINE;
276
277         res |= ast_register_translator(&g722tolin);
278         res |= ast_register_translator(&lintog722);
279         res |= ast_register_translator(&g722tolin16);
280         res |= ast_register_translator(&lin16tog722);
281
282         if (res) {
283                 unload_module();
284                 return AST_MODULE_LOAD_FAILURE;
285         }       
286
287         return AST_MODULE_LOAD_SUCCESS;
288 }
289
290 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder",
291                 .load = load_module,
292                 .unload = unload_module,
293                 .reload = reload,
294                );