include "logger.h" and errno.h from asterisk.h - usage shows that they
[asterisk/asterisk.git] / codecs / codec_gsm.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * The GSM code is from TOAST.  Copyright information for that package is available
5  * in the GSM directory.
6  *
7  * Copyright (C) 1999 - 2005, Digium, Inc.
8  *
9  * Mark Spencer <markster@digium.com>
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 Translate between signed linear and Global System for Mobile Communications (GSM)
25  *
26  * \ingroup codecs
27  */
28
29 /*** MODULEINFO
30         <depend>gsm</depend>
31  ***/
32
33 #include "asterisk.h"
34
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36
37 #include <fcntl.h>
38 #include <netinet/in.h>
39
40 #include "asterisk/lock.h"
41 #include "asterisk/translate.h"
42 #include "asterisk/config.h"
43 #include "asterisk/options.h"
44 #include "asterisk/module.h"
45 #include "asterisk/channel.h"
46 #include "asterisk/utils.h"
47
48 #ifdef HAVE_GSM_HEADER
49 #include "gsm.h"
50 #elif defined(HAVE_GSM_GSM_HEADER)
51 #include <gsm/gsm.h>
52 #endif
53
54 #include "../formats/msgsm.h"
55
56 /* Sample frame data */
57 #include "slin_gsm_ex.h"
58 #include "gsm_slin_ex.h"
59
60 #define BUFFER_SAMPLES  8000
61 #define GSM_SAMPLES     160
62 #define GSM_FRAME_LEN   33
63 #define MSGSM_FRAME_LEN 65
64
65 struct gsm_translator_pvt {     /* both gsm2lin and lin2gsm */
66         gsm gsm;
67         int16_t buf[BUFFER_SAMPLES];    /* lin2gsm, temporary storage */
68 };
69
70 static int gsm_new(struct ast_trans_pvt *pvt)
71 {
72         struct gsm_translator_pvt *tmp = pvt->pvt;
73         
74         return (tmp->gsm = gsm_create()) ? 0 : -1;
75 }
76
77 static struct ast_frame *lintogsm_sample(void)
78 {
79         static struct ast_frame f;
80         f.frametype = AST_FRAME_VOICE;
81         f.subclass = AST_FORMAT_SLINEAR;
82         f.datalen = sizeof(slin_gsm_ex);
83         /* Assume 8000 Hz */
84         f.samples = sizeof(slin_gsm_ex)/2;
85         f.mallocd = 0;
86         f.offset = 0;
87         f.src = __PRETTY_FUNCTION__;
88         f.data = slin_gsm_ex;
89         return &f;
90 }
91
92 static struct ast_frame *gsmtolin_sample(void)
93 {
94         static struct ast_frame f;
95         f.frametype = AST_FRAME_VOICE;
96         f.subclass = AST_FORMAT_GSM;
97         f.datalen = sizeof(gsm_slin_ex);
98         /* All frames are 20 ms long */
99         f.samples = GSM_SAMPLES;
100         f.mallocd = 0;
101         f.offset = 0;
102         f.src = __PRETTY_FUNCTION__;
103         f.data = gsm_slin_ex;
104         return &f;
105 }
106
107 /*! \brief decode and store in outbuf. */
108 static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
109 {
110         struct gsm_translator_pvt *tmp = pvt->pvt;
111         int x;
112         int16_t *dst = (int16_t *)pvt->outbuf;
113         /* guess format from frame len. 65 for MSGSM, 33 for regular GSM */
114         int flen = (f->datalen % MSGSM_FRAME_LEN == 0) ?
115                 MSGSM_FRAME_LEN : GSM_FRAME_LEN;
116
117         for (x=0; x < f->datalen; x += flen) {
118                 unsigned char data[2 * GSM_FRAME_LEN];
119                 unsigned char *src;
120                 int len;
121                 if (flen == MSGSM_FRAME_LEN) {
122                         len = 2*GSM_SAMPLES;
123                         src = data;
124                         /* Translate MSGSM format to Real GSM format before feeding in */
125                         /* XXX what's the point here! we should just work
126                          * on the full format.
127                          */
128                         conv65(f->data + x, data);
129                 } else {
130                         len = GSM_SAMPLES;
131                         src = f->data + x;
132                 }
133                 /* XXX maybe we don't need to check */
134                 if (pvt->samples + len > BUFFER_SAMPLES) {      
135                         ast_log(LOG_WARNING, "Out of buffer space\n");
136                         return -1;
137                 }
138                 if (gsm_decode(tmp->gsm, src, dst + pvt->samples)) {
139                         ast_log(LOG_WARNING, "Invalid GSM data (1)\n");
140                         return -1;
141                 }
142                 pvt->samples += GSM_SAMPLES;
143                 pvt->datalen += 2 * GSM_SAMPLES;
144                 if (flen == MSGSM_FRAME_LEN) {
145                         if (gsm_decode(tmp->gsm, data + GSM_FRAME_LEN, dst + pvt->samples)) {
146                                 ast_log(LOG_WARNING, "Invalid GSM data (2)\n");
147                                 return -1;
148                         }
149                         pvt->samples += GSM_SAMPLES;
150                         pvt->datalen += 2 * GSM_SAMPLES;
151                 }
152         }
153         return 0;
154 }
155
156 /*! \brief store samples into working buffer for later decode */
157 static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
158 {
159         struct gsm_translator_pvt *tmp = pvt->pvt;
160
161         /* XXX We should look at how old the rest of our stream is, and if it
162            is too old, then we should overwrite it entirely, otherwise we can
163            get artifacts of earlier talk that do not belong */
164         if (pvt->samples + f->samples > BUFFER_SAMPLES) {
165                 ast_log(LOG_WARNING, "Out of buffer space\n");
166                 return -1;
167         }
168         memcpy(tmp->buf + pvt->samples, f->data, f->datalen);
169         pvt->samples += f->samples;
170         return 0;
171 }
172
173 /*! \brief encode and produce a frame */
174 static struct ast_frame *lintogsm_frameout(struct ast_trans_pvt *pvt)
175 {
176         struct gsm_translator_pvt *tmp = pvt->pvt;
177         int datalen = 0;
178         int samples = 0;
179
180         /* We can't work on anything less than a frame in size */
181         if (pvt->samples < GSM_SAMPLES)
182                 return NULL;
183         while (pvt->samples >= GSM_SAMPLES) {
184                 /* Encode a frame of data */
185                 gsm_encode(tmp->gsm, tmp->buf + samples, (gsm_byte *) pvt->outbuf + datalen);
186                 datalen += GSM_FRAME_LEN;
187                 samples += GSM_SAMPLES;
188                 pvt->samples -= GSM_SAMPLES;
189         }
190
191         /* Move the data at the end of the buffer to the front */
192         if (pvt->samples)
193                 memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
194
195         return ast_trans_frameout(pvt, datalen, samples);
196 }
197
198 static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
199 {
200         struct gsm_translator_pvt *tmp = pvt->pvt;
201         if (tmp->gsm)
202                 gsm_destroy(tmp->gsm);
203 }
204
205 static struct ast_translator gsmtolin = {
206         .name = "gsmtolin", 
207         .srcfmt = AST_FORMAT_GSM,
208         .dstfmt = AST_FORMAT_SLINEAR,
209         .newpvt = gsm_new,
210         .framein = gsmtolin_framein,
211         .destroy = gsm_destroy_stuff,
212         .sample = gsmtolin_sample,
213         .buffer_samples = BUFFER_SAMPLES,
214         .buf_size = BUFFER_SAMPLES * 2,
215         .desc_size = sizeof (struct gsm_translator_pvt ),
216         .plc_samples = GSM_SAMPLES,
217 };
218
219 static struct ast_translator lintogsm = {
220         .name = "lintogsm", 
221         .srcfmt = AST_FORMAT_SLINEAR,
222         .dstfmt = AST_FORMAT_GSM,
223         .newpvt = gsm_new,
224         .framein = lintogsm_framein,
225         .frameout = lintogsm_frameout,
226         .destroy = gsm_destroy_stuff,
227         .sample = lintogsm_sample,
228         .desc_size = sizeof (struct gsm_translator_pvt ),
229         .buf_size = (BUFFER_SAMPLES * GSM_FRAME_LEN + GSM_SAMPLES - 1)/GSM_SAMPLES,
230 };
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         if (!cfg)
239                 return -1;
240         if (cfg == CONFIG_STATUS_FILEUNCHANGED) 
241                 return 0;
242         for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
243                if (!strcasecmp(var->name, "genericplc")) {
244                        gsmtolin.useplc = ast_true(var->value) ? 1 : 0;
245                            ast_verb(3, "codec_gsm: %susing generic PLC\n", gsmtolin.useplc ? "" : "not ");
246                }
247         }
248         ast_config_destroy(cfg);
249         return 0;
250 }
251
252 /*! \brief standard module glue */
253 static int reload(void)
254 {
255         if (parse_config(1)) {
256                 return AST_MODULE_LOAD_DECLINE;
257         }
258         return AST_MODULE_LOAD_SUCCESS;
259 }
260
261 static int unload_module(void)
262 {
263         int res;
264
265         res = ast_unregister_translator(&lintogsm);
266         if (!res)
267                 res = ast_unregister_translator(&gsmtolin);
268
269         return res;
270 }
271
272 static int load_module(void)
273 {
274         int res;
275
276         if (parse_config(0))
277                 return AST_MODULE_LOAD_DECLINE;
278         res = ast_register_translator(&gsmtolin);
279         if (!res) 
280                 res=ast_register_translator(&lintogsm);
281         else
282                 ast_unregister_translator(&gsmtolin);
283         if (res) 
284                 return AST_MODULE_LOAD_FAILURE;
285         return AST_MODULE_LOAD_SUCCESS;
286 }
287
288 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "GSM Coder/Decoder",
289                 .load = load_module,
290                 .unload = unload_module,
291                 .reload = reload,
292                );