2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2008, Digium, Inc.
6 * Matthew Fredrickson <creslin@digium.com>
7 * Russell Bryant <russell@digium.com>
9 * Special thanks to Steve Underwood for the implementation
10 * and for doing the 8khz<->g.722 direct translation code.
12 * See http://www.asterisk.org for more information about
13 * the Asterisk project. Please do not directly contact
14 * any of the maintainers of this project for assistance;
15 * the project provides a web site, mailing lists and IRC
16 * channels for your use.
18 * This program is free software, distributed under the terms of
19 * the GNU General Public License Version 2. See the LICENSE file
20 * at the top of the source tree.
25 * \brief codec_g722.c - translate between signed linear and ITU G.722-64kbps
27 * \author Matthew Fredrickson <creslin@digium.com>
28 * \author Russell Bryant <russell@digium.com>
30 * \arg http://soft-switch.org/downloads/non-gpl-bits.tgz
31 * \arg http://lists.digium.com/pipermail/asterisk-dev/2006-September/022866.html
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40 #include "asterisk/linkedlists.h"
41 #include "asterisk/module.h"
42 #include "asterisk/config.h"
43 #include "asterisk/translate.h"
44 #include "asterisk/utils.h"
46 #define BUFFER_SAMPLES 8096 /* size for the translation buffers */
49 /* Sample frame data */
51 #include "g722/g722.h"
52 #include "slin_g722_ex.h"
53 #include "g722_slin_ex.h"
55 struct g722_encoder_pvt {
56 g722_encode_state_t g722;
59 struct g722_decoder_pvt {
60 g722_decode_state_t g722;
63 /*! \brief init a new instance of g722_encoder_pvt. */
64 static int lintog722_new(struct ast_trans_pvt *pvt)
66 struct g722_encoder_pvt *tmp = pvt->pvt;
68 g722_encode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
73 static int lin16tog722_new(struct ast_trans_pvt *pvt)
75 struct g722_encoder_pvt *tmp = pvt->pvt;
77 g722_encode_init(&tmp->g722, 64000, 0);
82 /*! \brief init a new instance of g722_encoder_pvt. */
83 static int g722tolin_new(struct ast_trans_pvt *pvt)
85 struct g722_decoder_pvt *tmp = pvt->pvt;
87 g722_decode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
92 static int g722tolin16_new(struct ast_trans_pvt *pvt)
94 struct g722_decoder_pvt *tmp = pvt->pvt;
96 g722_decode_init(&tmp->g722, 64000, 0);
101 static int g722tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
103 struct g722_decoder_pvt *tmp = pvt->pvt;
107 /* g722_decode expects the samples to be in the invalid samples / 2 format */
108 in_samples = f->samples / 2;
110 out_samples = g722_decode(&tmp->g722, (int16_t *) &pvt->outbuf[pvt->samples * sizeof(int16_t)],
111 (uint8_t *) f->data, in_samples);
113 pvt->samples += out_samples;
115 pvt->datalen += (out_samples * sizeof(int16_t));
120 static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
122 struct g722_encoder_pvt *tmp = pvt->pvt;
125 outlen = g722_encode(&tmp->g722, (uint8_t *) (&pvt->outbuf[pvt->datalen]),
126 (int16_t *) f->data, f->samples);
128 pvt->samples += outlen * 2;
130 pvt->datalen += outlen;
135 static struct ast_frame *g722tolin_sample(void)
137 static struct ast_frame f = {
138 .frametype = AST_FRAME_VOICE,
139 .subclass = AST_FORMAT_G722,
140 .datalen = sizeof(g722_slin_ex),
141 .samples = sizeof(g722_slin_ex) * 2,
142 .src = __PRETTY_FUNCTION__,
143 .data = g722_slin_ex,
149 static struct ast_frame *g722tolin16_sample(void)
151 static struct ast_frame f = {
152 .frametype = AST_FRAME_VOICE,
153 .subclass = AST_FORMAT_G722,
154 .datalen = sizeof(slin_g722_ex),
155 .samples = sizeof(slin_g722_ex) * 2,
156 .src = __PRETTY_FUNCTION__,
157 .data = slin_g722_ex,
163 static struct ast_frame *lintog722_sample (void)
165 static struct ast_frame f = {
166 .frametype = AST_FRAME_VOICE,
167 .subclass = AST_FORMAT_SLINEAR,
168 .datalen = sizeof(slin_g722_ex),
169 .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]),
170 .src = __PRETTY_FUNCTION__,
171 .data = slin_g722_ex,
177 static struct ast_frame *lin16tog722_sample (void)
179 static struct ast_frame f = {
180 .frametype = AST_FRAME_VOICE,
181 .subclass = AST_FORMAT_SLINEAR16,
182 .datalen = sizeof(slin_g722_ex),
183 .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]),
184 .src = __PRETTY_FUNCTION__,
185 .data = slin_g722_ex,
191 static struct ast_translator g722tolin = {
193 .srcfmt = AST_FORMAT_G722,
194 .dstfmt = AST_FORMAT_SLINEAR,
195 .newpvt = g722tolin_new, /* same for both directions */
196 .framein = g722tolin_framein,
197 .sample = g722tolin_sample,
198 .desc_size = sizeof(struct g722_decoder_pvt),
199 .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t),
200 .buf_size = BUFFER_SAMPLES,
204 static struct ast_translator lintog722 = {
206 .srcfmt = AST_FORMAT_SLINEAR,
207 .dstfmt = AST_FORMAT_G722,
208 .newpvt = lintog722_new, /* same for both directions */
209 .framein = lintog722_framein,
210 .sample = lintog722_sample,
211 .desc_size = sizeof(struct g722_encoder_pvt),
212 .buffer_samples = BUFFER_SAMPLES * 2,
213 .buf_size = BUFFER_SAMPLES,
216 static struct ast_translator g722tolin16 = {
217 .name = "g722tolin16",
218 .srcfmt = AST_FORMAT_G722,
219 .dstfmt = AST_FORMAT_SLINEAR16,
220 .newpvt = g722tolin16_new, /* same for both directions */
221 .framein = g722tolin_framein,
222 .sample = g722tolin16_sample,
223 .desc_size = sizeof(struct g722_decoder_pvt),
224 .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t),
225 .buf_size = BUFFER_SAMPLES,
229 static struct ast_translator lin16tog722 = {
230 .name = "lin16tog722",
231 .srcfmt = AST_FORMAT_SLINEAR16,
232 .dstfmt = AST_FORMAT_G722,
233 .newpvt = lin16tog722_new, /* same for both directions */
234 .framein = lintog722_framein,
235 .sample = lin16tog722_sample,
236 .desc_size = sizeof(struct g722_encoder_pvt),
237 .buffer_samples = BUFFER_SAMPLES * 2,
238 .buf_size = BUFFER_SAMPLES,
241 static int parse_config(int reload)
243 struct ast_variable *var;
244 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
245 struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
249 if (cfg == CONFIG_STATUS_FILEUNCHANGED)
251 for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
252 if (!strcasecmp(var->name, "genericplc")) {
253 g722tolin.useplc = ast_true(var->value) ? 1 : 0;
254 ast_verb(3, "codec_g722: %susing generic PLC\n",
255 g722tolin.useplc ? "" : "not ");
258 ast_config_destroy(cfg);
262 static int reload(void)
265 return AST_MODULE_LOAD_DECLINE;
266 return AST_MODULE_LOAD_SUCCESS;
269 static int unload_module(void)
273 res |= ast_unregister_translator(&g722tolin);
274 res |= ast_unregister_translator(&lintog722);
275 res |= ast_unregister_translator(&g722tolin16);
276 res |= ast_unregister_translator(&lin16tog722);
281 static int load_module(void)
286 return AST_MODULE_LOAD_DECLINE;
288 res |= ast_register_translator(&g722tolin);
289 res |= ast_register_translator(&lintog722);
290 res |= ast_register_translator(&g722tolin16);
291 res |= ast_register_translator(&lin16tog722);
295 return AST_MODULE_LOAD_FAILURE;
298 return AST_MODULE_LOAD_SUCCESS;
301 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder",
303 .unload = unload_module,