Merged revisions 305131 via svnmerge from
[asterisk/asterisk.git] / codecs / codec_g722.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2008, Digium, Inc.
5  *
6  * Matthew Fredrickson <creslin@digium.com>
7  * Russell Bryant <russell@digium.com>
8  *
9  * Special thanks to Steve Underwood for the implementation
10  * and for doing the 8khz<->g.722 direct translation code.
11  *
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.
17  *
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.
21  */
22
23 /*! \file
24  *
25  * \brief codec_g722.c - translate between signed linear and ITU G.722-64kbps
26  *
27  * \author Matthew Fredrickson <creslin@digium.com>
28  * \author Russell Bryant <russell@digium.com>
29  *
30  * \arg http://soft-switch.org/downloads/non-gpl-bits.tgz
31  * \arg http://lists.digium.com/pipermail/asterisk-dev/2006-September/022866.html
32  *
33  * \ingroup codecs
34  */
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
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"
45
46 #define BUFFER_SAMPLES   8096   /* size for the translation buffers */
47 #define BUF_SHIFT       5
48
49 #include "g722/g722.h"
50
51 /* Sample frame data */
52 #include "asterisk/slin.h"
53 #include "ex_g722.h"
54
55 struct g722_encoder_pvt {
56         g722_encode_state_t g722;
57 };
58
59 struct g722_decoder_pvt {
60         g722_decode_state_t g722;
61 };
62
63 /*! \brief init a new instance of g722_encoder_pvt. */
64 static int lintog722_new(struct ast_trans_pvt *pvt)
65 {
66         struct g722_encoder_pvt *tmp = pvt->pvt;
67
68         g722_encode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
69
70         return 0;
71 }
72
73 static int lin16tog722_new(struct ast_trans_pvt *pvt)
74 {
75         struct g722_encoder_pvt *tmp = pvt->pvt;
76
77         g722_encode_init(&tmp->g722, 64000, 0);
78
79         return 0;
80 }
81
82 /*! \brief init a new instance of g722_encoder_pvt. */
83 static int g722tolin_new(struct ast_trans_pvt *pvt)
84 {
85         struct g722_decoder_pvt *tmp = pvt->pvt;
86
87         g722_decode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
88
89         return 0;
90 }
91
92 static int g722tolin16_new(struct ast_trans_pvt *pvt)
93 {
94         struct g722_decoder_pvt *tmp = pvt->pvt;
95
96         g722_decode_init(&tmp->g722, 64000, 0);
97
98         return 0;
99 }
100
101 static int g722tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
102 {
103         struct g722_decoder_pvt *tmp = pvt->pvt;
104         int out_samples;
105         int in_samples;
106
107         /* g722_decode expects the samples to be in the invalid samples / 2 format */
108         in_samples = f->samples / 2;
109
110         out_samples = g722_decode(&tmp->g722, &pvt->outbuf.i16[pvt->samples * sizeof(int16_t)], 
111                 (uint8_t *) f->data.ptr, in_samples);
112
113         pvt->samples += out_samples;
114
115         pvt->datalen += (out_samples * sizeof(int16_t));
116
117         return 0;
118 }
119
120 static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
121 {
122         struct g722_encoder_pvt *tmp = pvt->pvt;
123         int outlen;
124
125         outlen = g722_encode(&tmp->g722, (&pvt->outbuf.ui8[pvt->datalen]), 
126                 (int16_t *) f->data.ptr, f->samples);
127
128         pvt->samples += outlen * 2;
129
130         pvt->datalen += outlen;
131
132         return 0;
133 }
134
135 static struct ast_translator g722tolin = {
136         .name = "g722tolin",
137         .srcfmt = AST_FORMAT_G722,
138         .dstfmt = AST_FORMAT_SLINEAR,
139         .newpvt = g722tolin_new,        /* same for both directions */
140         .framein = g722tolin_framein,
141         .sample = g722_sample,
142         .desc_size = sizeof(struct g722_decoder_pvt),
143         .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t),
144         .buf_size = BUFFER_SAMPLES,
145 };
146
147 static struct ast_translator lintog722 = {
148         .name = "lintog722",
149         .srcfmt = AST_FORMAT_SLINEAR,
150         .dstfmt = AST_FORMAT_G722,
151         .newpvt = lintog722_new,        /* same for both directions */
152         .framein = lintog722_framein,
153         .sample = slin8_sample,
154         .desc_size = sizeof(struct g722_encoder_pvt),
155         .buffer_samples = BUFFER_SAMPLES * 2,
156         .buf_size = BUFFER_SAMPLES,
157 };
158
159 static struct ast_translator g722tolin16 = {
160         .name = "g722tolin16",
161         .srcfmt = AST_FORMAT_G722,
162         .dstfmt = AST_FORMAT_SLINEAR16,
163         .newpvt = g722tolin16_new,      /* same for both directions */
164         .framein = g722tolin_framein,
165         .sample = g722_sample,
166         .desc_size = sizeof(struct g722_decoder_pvt),
167         .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t),
168         .buf_size = BUFFER_SAMPLES,
169 };
170
171 static struct ast_translator lin16tog722 = {
172         .name = "lin16tog722",
173         .srcfmt = AST_FORMAT_SLINEAR16,
174         .dstfmt = AST_FORMAT_G722,
175         .newpvt = lin16tog722_new,      /* same for both directions */
176         .framein = lintog722_framein,
177         .sample = slin16_sample,
178         .desc_size = sizeof(struct g722_encoder_pvt),
179         .buffer_samples = BUFFER_SAMPLES * 2,
180         .buf_size = BUFFER_SAMPLES,
181 };
182
183 static int reload(void)
184 {
185         return AST_MODULE_LOAD_SUCCESS;
186 }
187
188 static int unload_module(void)
189 {
190         int res = 0;
191
192         res |= ast_unregister_translator(&g722tolin);
193         res |= ast_unregister_translator(&lintog722);
194         res |= ast_unregister_translator(&g722tolin16);
195         res |= ast_unregister_translator(&lin16tog722);
196
197         return res;
198 }
199
200 static int load_module(void)
201 {
202         int res = 0;
203
204         res |= ast_register_translator(&g722tolin);
205         res |= ast_register_translator(&lintog722);
206         res |= ast_register_translator(&g722tolin16);
207         res |= ast_register_translator(&lin16tog722);
208
209         if (res) {
210                 unload_module();
211                 return AST_MODULE_LOAD_FAILURE;
212         }       
213
214         return AST_MODULE_LOAD_SUCCESS;
215 }
216
217 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder",
218                 .load = load_module,
219                 .unload = unload_module,
220                 .reload = reload,
221                );