|
1 Index: cdr/cdr_sqlite.c |
|
2 diff -Nau cdr/cdr_sqlite.c.orig cdr/cdr_sqlite.c |
|
3 --- cdr/cdr_sqlite.c.orig 2007-06-14 23:50:40.000000000 +0200 |
|
4 +++ cdr/cdr_sqlite.c 2009-04-24 00:30:33.000000000 +0200 |
|
5 @@ -58,7 +58,7 @@ |
|
6 #define DATE_FORMAT "%Y-%m-%d %T" |
|
7 |
|
8 static char *name = "sqlite"; |
|
9 -static sqlite* db = NULL; |
|
10 +static sqlite3 *db = NULL; |
|
11 |
|
12 AST_MUTEX_DEFINE_STATIC(sqlite_lock); |
|
13 |
|
14 @@ -92,10 +92,10 @@ |
|
15 static int sqlite_log(struct ast_cdr *cdr) |
|
16 { |
|
17 int res = 0; |
|
18 - char *zErr = 0; |
|
19 struct tm tm; |
|
20 time_t t; |
|
21 char startstr[80], answerstr[80], endstr[80]; |
|
22 + char *cdrsql = 0; |
|
23 int count; |
|
24 |
|
25 ast_mutex_lock(&sqlite_lock); |
|
26 @@ -113,7 +113,7 @@ |
|
27 strftime(endstr, sizeof(endstr), DATE_FORMAT, &tm); |
|
28 |
|
29 for(count=0; count<5; count++) { |
|
30 - res = sqlite_exec_printf(db, |
|
31 + cdrsql = sqlite3_mprintf( |
|
32 "INSERT INTO cdr (" |
|
33 "clid,src,dst,dcontext," |
|
34 "channel,dstchannel,lastapp,lastdata, " |
|
35 @@ -138,8 +138,7 @@ |
|
36 # if LOG_USERFIELD |
|
37 ",'%q'" |
|
38 # endif |
|
39 - ")", NULL, NULL, &zErr, |
|
40 - cdr->clid, cdr->src, cdr->dst, cdr->dcontext, |
|
41 + ")", cdr->clid, cdr->src, cdr->dst, cdr->dcontext, |
|
42 cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata, |
|
43 startstr, answerstr, endstr, |
|
44 cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags, |
|
45 @@ -151,16 +150,13 @@ |
|
46 ,cdr->userfield |
|
47 # endif |
|
48 ); |
|
49 + res = sqlite3_exec(db, cdrsql, 0, 0, 0); |
|
50 + sqlite3_free(cdrsql); |
|
51 if (res != SQLITE_BUSY && res != SQLITE_LOCKED) |
|
52 break; |
|
53 usleep(200); |
|
54 } |
|
55 |
|
56 - if (zErr) { |
|
57 - ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr); |
|
58 - free(zErr); |
|
59 - } |
|
60 - |
|
61 ast_mutex_unlock(&sqlite_lock); |
|
62 return res; |
|
63 } |
|
64 @@ -168,7 +164,7 @@ |
|
65 static int unload_module(void) |
|
66 { |
|
67 if (db) |
|
68 - sqlite_close(db); |
|
69 + sqlite3_close(db); |
|
70 ast_cdr_unregister(name); |
|
71 return 0; |
|
72 } |
|
73 @@ -181,17 +177,16 @@ |
|
74 |
|
75 /* is the database there? */ |
|
76 snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR); |
|
77 - db = sqlite_open(fn, 0660, &zErr); |
|
78 + sqlite3_open(fn, &db); |
|
79 if (!db) { |
|
80 - ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr); |
|
81 - free(zErr); |
|
82 + ast_log(LOG_ERROR, "cdr_sqlite: %s\n", sqlite3_errmsg(db)); |
|
83 return -1; |
|
84 } |
|
85 |
|
86 /* is the table there? */ |
|
87 - res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL); |
|
88 + res = sqlite3_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL); |
|
89 if (res) { |
|
90 - res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr); |
|
91 + res = sqlite3_exec(db, sql_create_table, NULL, NULL, &zErr); |
|
92 if (res) { |
|
93 ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr); |
|
94 free(zErr); |
|
95 @@ -210,7 +205,7 @@ |
|
96 |
|
97 err: |
|
98 if (db) |
|
99 - sqlite_close(db); |
|
100 + sqlite3_close(db); |
|
101 return -1; |
|
102 } |
|
103 |
|
104 Index: channels/chan_sip.c |
|
105 diff -Nau channels/chan_sip.c.orig channels/chan_sip.c |
|
106 --- channels/chan_sip.c.orig 2009-04-02 19:20:22.000000000 +0200 |
|
107 +++ channels/chan_sip.c 2009-04-24 00:30:33.000000000 +0200 |
|
108 @@ -7469,7 +7469,7 @@ |
|
109 |
|
110 ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from)); |
|
111 c = get_in_brackets(from); |
|
112 - if (strncasecmp(c, "sip:", 4)) { |
|
113 + if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { |
|
114 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); |
|
115 return -1; |
|
116 } |
|
117 @@ -7477,7 +7477,7 @@ |
|
118 |
|
119 ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to)); |
|
120 c = get_in_brackets(to); |
|
121 - if (strncasecmp(c, "sip:", 4)) { |
|
122 + if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { |
|
123 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); |
|
124 return -1; |
|
125 } |
|
126 @@ -8004,7 +8004,10 @@ |
|
127 of = get_in_brackets(from); |
|
128 ast_string_field_set(p, from, of); |
|
129 if (strncasecmp(of, "sip:", 4)) |
|
130 - ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); |
|
131 + if (strncasecmp(of, "sips:", 5)) |
|
132 + ast_log(LOG_NOTICE, "From address missing 'sip:' or 'sips:', using it anyway\n"); |
|
133 + else |
|
134 + of += 5; |
|
135 else |
|
136 of += 4; |
|
137 /* Get just the username part */ |
|
138 @@ -8280,7 +8283,10 @@ |
|
139 |
|
140 /* Make sure it's a SIP URL */ |
|
141 if (strncasecmp(contact, "sip:", 4)) { |
|
142 - ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact); |
|
143 + if (strncasecmp(contact, "sips:", 5)) |
|
144 + ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip: or sips:) trying to use anyway\n", contact); |
|
145 + else |
|
146 + contact += 5; |
|
147 } else |
|
148 contact += 4; |
|
149 |
|
150 @@ -8409,7 +8415,10 @@ |
|
151 |
|
152 /* Make sure it's a SIP URL */ |
|
153 if (strncasecmp(curi, "sip:", 4)) { |
|
154 - ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", curi); |
|
155 + if (strncasecmp(curi, "sips:", 5)) |
|
156 + ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip: or sips:) trying to use anyway\n", curi); |
|
157 + else |
|
158 + curi += 5; |
|
159 } else |
|
160 curi += 4; |
|
161 /* Ditch q */ |
|
162 @@ -9000,9 +9009,12 @@ |
|
163 |
|
164 if (!strncasecmp(c, "sip:", 4)) { |
|
165 name = c + 4; |
|
166 + } |
|
167 + else if (!strncasecmp(c, "sips:", 5)) { |
|
168 + name = c + 5; |
|
169 } else { |
|
170 name = c; |
|
171 - ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr)); |
|
172 + ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip: or sips:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr)); |
|
173 } |
|
174 |
|
175 /* Strip off the domain name */ |
|
176 @@ -9162,10 +9174,15 @@ |
|
177 return 0; |
|
178 c = get_in_brackets(tmp); |
|
179 if (strncasecmp(c, "sip:", 4)) { |
|
180 - ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", c); |
|
181 - return -1; |
|
182 + if (strncasecmp(c, "sips:", 5)) { |
|
183 + ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", c); |
|
184 + return -1; |
|
185 + } |
|
186 + else |
|
187 + c += 5; |
|
188 } |
|
189 - c += 4; |
|
190 + else |
|
191 + c += 4; |
|
192 a = c; |
|
193 strsep(&a, "@;"); /* trim anything after @ or ; */ |
|
194 if (sip_debug_test_pvt(p)) |
|
195 @@ -9200,10 +9217,15 @@ |
|
196 uri = get_in_brackets(tmp); |
|
197 |
|
198 if (strncasecmp(uri, "sip:", 4)) { |
|
199 - ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", uri); |
|
200 - return -1; |
|
201 + if (strncasecmp(uri, "sips:", 5)) { |
|
202 + ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", uri); |
|
203 + return -1; |
|
204 + } |
|
205 + else |
|
206 + uri += 5; |
|
207 } |
|
208 - uri += 4; |
|
209 + else |
|
210 + uri += 4; |
|
211 |
|
212 /* Now find the From: caller ID and name */ |
|
213 ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf)); |
|
214 @@ -9217,10 +9239,15 @@ |
|
215 |
|
216 if (!ast_strlen_zero(from)) { |
|
217 if (strncasecmp(from, "sip:", 4)) { |
|
218 - ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); |
|
219 - return -1; |
|
220 + if (strncasecmp(from, "sips:", 5)) { |
|
221 + ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); |
|
222 + return -1; |
|
223 + } |
|
224 + else |
|
225 + from += 5; |
|
226 } |
|
227 - from += 4; |
|
228 + else |
|
229 + from += 4; |
|
230 if ((a = strchr(from, '@'))) |
|
231 *a++ = '\0'; |
|
232 else |
|
233 @@ -9397,10 +9424,15 @@ |
|
234 ast_uri_decode(refer_to); |
|
235 |
|
236 if (strncasecmp(refer_to, "sip:", 4)) { |
|
237 - ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); |
|
238 - return -3; |
|
239 + if (strncasecmp(refer_to, "sips:", 5)) { |
|
240 + ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); |
|
241 + return -3; |
|
242 + } |
|
243 + else |
|
244 + refer_to += 5; /* Skip sips: */ |
|
245 } |
|
246 - refer_to += 4; /* Skip sip: */ |
|
247 + else |
|
248 + refer_to += 4; /* Skip sip: */ |
|
249 |
|
250 /* Get referred by header if it exists */ |
|
251 p_referred_by = get_header(req, "Referred-By"); |
|
252 @@ -9417,9 +9449,13 @@ |
|
253 } |
|
254 |
|
255 referred_by_uri = get_in_brackets(h_referred_by); |
|
256 - if(strncasecmp(referred_by_uri, "sip:", 4)) { |
|
257 - ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); |
|
258 - referred_by_uri = (char *) NULL; |
|
259 + if (strncasecmp(referred_by_uri, "sip:", 4)) { |
|
260 + if (strncasecmp(referred_by_uri, "sips:", 5)) { |
|
261 + ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); |
|
262 + referred_by_uri = (char *) NULL; |
|
263 + } |
|
264 + else |
|
265 + referred_by_uri += 5; /* Skip sips: */ |
|
266 } else { |
|
267 referred_by_uri += 4; /* Skip sip: */ |
|
268 } |
|
269 @@ -9547,10 +9583,15 @@ |
|
270 ast_uri_decode(c); |
|
271 |
|
272 if (strncasecmp(c, "sip:", 4)) { |
|
273 - ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); |
|
274 - return -1; |
|
275 + if (strncasecmp(c, "sips:", 5)) { |
|
276 + ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); |
|
277 + return -1; |
|
278 + } |
|
279 + else |
|
280 + c += 5; |
|
281 } |
|
282 - c += 4; |
|
283 + else |
|
284 + c += 4; |
|
285 if ((a = strchr(c, ';'))) /* Remove arguments */ |
|
286 *a = '\0'; |
|
287 |
|
288 @@ -9761,6 +9802,8 @@ |
|
289 t = uri2; |
|
290 if (!strncasecmp(t, "sip:", 4)) |
|
291 t+= 4; |
|
292 + else if (!strncasecmp(t, "sips:", 5)) |
|
293 + t+= 5; |
|
294 ast_string_field_set(p, exten, t); |
|
295 t = strchr(p->exten, '@'); |
|
296 if (t) |
|
297 @@ -9771,7 +9814,10 @@ |
|
298 /* save the URI part of the From header */ |
|
299 ast_string_field_set(p, from, of); |
|
300 if (strncasecmp(of, "sip:", 4)) { |
|
301 - ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); |
|
302 + if (strncasecmp(of, "sips:", 5)) |
|
303 + ast_log(LOG_NOTICE, "From address missing 'sip:' or 'sips:', using it anyway\n"); |
|
304 + else |
|
305 + of += 5; |
|
306 } else |
|
307 of += 4; |
|
308 /* Get just the username part */ |
|
309 @@ -12379,6 +12425,8 @@ |
|
310 if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { |
|
311 if (!strncasecmp(s, "sip:", 4)) |
|
312 s += 4; |
|
313 + else if (!strncasecmp(s, "sips:", 5)) |
|
314 + s += 5; |
|
315 e = strchr(s, ';'); |
|
316 if (e) |
|
317 *e = '\0'; |
|
318 @@ -12404,6 +12452,8 @@ |
|
319 |
|
320 if (!strncasecmp(s, "sip:", 4)) |
|
321 s += 4; |
|
322 + else if (!strncasecmp(s, "sips:", 5)) |
|
323 + s += 5; |
|
324 if (option_debug > 1) |
|
325 ast_log(LOG_DEBUG, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain); |
|
326 if (p->owner) { |
|
327 Index: codecs/codec_g722.c |
|
328 diff -Nau codecs/codec_g722.c.orig codecs/codec_g722.c |
|
329 --- codecs/codec_g722.c.orig 1970-01-01 01:00:00.000000000 +0100 |
|
330 +++ codecs/codec_g722.c 2009-04-24 00:30:33.000000000 +0200 |
|
331 @@ -0,0 +1,306 @@ |
|
332 +/* |
|
333 + * Asterisk -- An open source telephony toolkit. |
|
334 + * |
|
335 + * Copyright (C) 1999 - 2008, Digium, Inc. |
|
336 + * |
|
337 + * Matthew Fredrickson <creslin@digium.com> |
|
338 + * Russell Bryant <russell@digium.com> |
|
339 + * |
|
340 + * Special thanks to Steve Underwood for the implementation |
|
341 + * and for doing the 8khz<->g.722 direct translation code. |
|
342 + * |
|
343 + * See http://www.asterisk.org for more information about |
|
344 + * the Asterisk project. Please do not directly contact |
|
345 + * any of the maintainers of this project for assistance; |
|
346 + * the project provides a web site, mailing lists and IRC |
|
347 + * channels for your use. |
|
348 + * |
|
349 + * This program is free software, distributed under the terms of |
|
350 + * the GNU General Public License Version 2. See the LICENSE file |
|
351 + * at the top of the source tree. |
|
352 + */ |
|
353 + |
|
354 +/*! \file |
|
355 + * |
|
356 + * \brief codec_g722.c - translate between signed linear and ITU G.722-64kbps |
|
357 + * |
|
358 + * \author Matthew Fredrickson <creslin@digium.com> |
|
359 + * \author Russell Bryant <russell@digium.com> |
|
360 + * |
|
361 + * \arg http://soft-switch.org/downloads/non-gpl-bits.tgz |
|
362 + * \arg http://lists.digium.com/pipermail/asterisk-dev/2006-September/022866.html |
|
363 + * |
|
364 + * \ingroup codecs |
|
365 + */ |
|
366 + |
|
367 +#include "asterisk.h" |
|
368 + |
|
369 +ASTERISK_FILE_VERSION(__FILE__, "$Revision: 106501 $") |
|
370 + |
|
371 +#include "asterisk/linkedlists.h" |
|
372 +#include "asterisk/module.h" |
|
373 +#include "asterisk/config.h" |
|
374 +#include "asterisk/options.h" |
|
375 +#include "asterisk/translate.h" |
|
376 +#include "asterisk/utils.h" |
|
377 + |
|
378 +#define BUFFER_SAMPLES 8096 /* size for the translation buffers */ |
|
379 +#define BUF_SHIFT 5 |
|
380 + |
|
381 +/* Sample frame data */ |
|
382 + |
|
383 +#include "g722/g722.h" |
|
384 +#include "slin_g722_ex.h" |
|
385 +#include "g722_slin_ex.h" |
|
386 + |
|
387 +struct g722_encoder_pvt { |
|
388 + g722_encode_state_t g722; |
|
389 +}; |
|
390 + |
|
391 +struct g722_decoder_pvt { |
|
392 + g722_decode_state_t g722; |
|
393 +}; |
|
394 + |
|
395 +/*! \brief init a new instance of g722_encoder_pvt. */ |
|
396 +static int lintog722_new(struct ast_trans_pvt *pvt) |
|
397 +{ |
|
398 + struct g722_encoder_pvt *tmp = pvt->pvt; |
|
399 + |
|
400 + g722_encode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000); |
|
401 + |
|
402 + return 0; |
|
403 +} |
|
404 + |
|
405 +static int lin16tog722_new(struct ast_trans_pvt *pvt) |
|
406 +{ |
|
407 + struct g722_encoder_pvt *tmp = pvt->pvt; |
|
408 + |
|
409 + g722_encode_init(&tmp->g722, 64000, 0); |
|
410 + |
|
411 + return 0; |
|
412 +} |
|
413 + |
|
414 +/*! \brief init a new instance of g722_encoder_pvt. */ |
|
415 +static int g722tolin_new(struct ast_trans_pvt *pvt) |
|
416 +{ |
|
417 + struct g722_decoder_pvt *tmp = pvt->pvt; |
|
418 + |
|
419 + g722_decode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000); |
|
420 + |
|
421 + return 0; |
|
422 +} |
|
423 + |
|
424 +static int g722tolin16_new(struct ast_trans_pvt *pvt) |
|
425 +{ |
|
426 + struct g722_decoder_pvt *tmp = pvt->pvt; |
|
427 + |
|
428 + g722_decode_init(&tmp->g722, 64000, 0); |
|
429 + |
|
430 + return 0; |
|
431 +} |
|
432 + |
|
433 +static int g722tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) |
|
434 +{ |
|
435 + struct g722_decoder_pvt *tmp = pvt->pvt; |
|
436 + int out_samples; |
|
437 + int in_samples; |
|
438 + |
|
439 + /* g722_decode expects the samples to be in the invalid samples / 2 format */ |
|
440 + in_samples = f->samples / 2; |
|
441 + |
|
442 + out_samples = g722_decode(&tmp->g722, (int16_t *) &pvt->outbuf[pvt->samples * sizeof(int16_t)], |
|
443 + (uint8_t *) f->data, in_samples); |
|
444 + |
|
445 + pvt->samples += out_samples; |
|
446 + |
|
447 + pvt->datalen += (out_samples * sizeof(int16_t)); |
|
448 + |
|
449 + return 0; |
|
450 +} |
|
451 + |
|
452 +static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) |
|
453 +{ |
|
454 + struct g722_encoder_pvt *tmp = pvt->pvt; |
|
455 + int outlen; |
|
456 + |
|
457 + outlen = g722_encode(&tmp->g722, (uint8_t *) (&pvt->outbuf[pvt->datalen]), |
|
458 + (int16_t *) f->data, f->samples); |
|
459 + |
|
460 + pvt->samples += outlen * 2; |
|
461 + |
|
462 + pvt->datalen += outlen; |
|
463 + |
|
464 + return 0; |
|
465 +} |
|
466 + |
|
467 +static struct ast_frame *g722tolin_sample(void) |
|
468 +{ |
|
469 + static struct ast_frame f = { |
|
470 + .frametype = AST_FRAME_VOICE, |
|
471 + .subclass = AST_FORMAT_G722, |
|
472 + .datalen = sizeof(g722_slin_ex), |
|
473 + .samples = sizeof(g722_slin_ex) * 2, |
|
474 + .src = __PRETTY_FUNCTION__, |
|
475 + .data = g722_slin_ex, |
|
476 + }; |
|
477 + |
|
478 + return &f; |
|
479 +} |
|
480 + |
|
481 +static struct ast_frame *g722tolin16_sample(void) |
|
482 +{ |
|
483 + static struct ast_frame f = { |
|
484 + .frametype = AST_FRAME_VOICE, |
|
485 + .subclass = AST_FORMAT_G722, |
|
486 + .datalen = sizeof(slin_g722_ex), |
|
487 + .samples = sizeof(slin_g722_ex) * 2, |
|
488 + .src = __PRETTY_FUNCTION__, |
|
489 + .data = slin_g722_ex, |
|
490 + }; |
|
491 + |
|
492 + return &f; |
|
493 +} |
|
494 + |
|
495 +static struct ast_frame *lintog722_sample (void) |
|
496 +{ |
|
497 + static struct ast_frame f = { |
|
498 + .frametype = AST_FRAME_VOICE, |
|
499 + .subclass = AST_FORMAT_SLINEAR, |
|
500 + .datalen = sizeof(slin_g722_ex), |
|
501 + .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]), |
|
502 + .src = __PRETTY_FUNCTION__, |
|
503 + .data = slin_g722_ex, |
|
504 + }; |
|
505 + |
|
506 + return &f; |
|
507 +} |
|
508 + |
|
509 +static struct ast_frame *lin16tog722_sample (void) |
|
510 +{ |
|
511 + static struct ast_frame f = { |
|
512 + .frametype = AST_FRAME_VOICE, |
|
513 + .subclass = AST_FORMAT_SLINEAR16, |
|
514 + .datalen = sizeof(slin_g722_ex), |
|
515 + .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]), |
|
516 + .src = __PRETTY_FUNCTION__, |
|
517 + .data = slin_g722_ex, |
|
518 + }; |
|
519 + |
|
520 + return &f; |
|
521 +} |
|
522 + |
|
523 +static struct ast_translator g722tolin = { |
|
524 + .name = "g722tolin", |
|
525 + .srcfmt = AST_FORMAT_G722, |
|
526 + .dstfmt = AST_FORMAT_SLINEAR, |
|
527 + .newpvt = g722tolin_new, /* same for both directions */ |
|
528 + .framein = g722tolin_framein, |
|
529 + .sample = g722tolin_sample, |
|
530 + .desc_size = sizeof(struct g722_decoder_pvt), |
|
531 + .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t), |
|
532 + .buf_size = BUFFER_SAMPLES, |
|
533 + .plc_samples = 160, |
|
534 +}; |
|
535 + |
|
536 +static struct ast_translator lintog722 = { |
|
537 + .name = "lintog722", |
|
538 + .srcfmt = AST_FORMAT_SLINEAR, |
|
539 + .dstfmt = AST_FORMAT_G722, |
|
540 + .newpvt = lintog722_new, /* same for both directions */ |
|
541 + .framein = lintog722_framein, |
|
542 + .sample = lintog722_sample, |
|
543 + .desc_size = sizeof(struct g722_encoder_pvt), |
|
544 + .buffer_samples = BUFFER_SAMPLES * 2, |
|
545 + .buf_size = BUFFER_SAMPLES, |
|
546 +}; |
|
547 + |
|
548 +static struct ast_translator g722tolin16 = { |
|
549 + .name = "g722tolin16", |
|
550 + .srcfmt = AST_FORMAT_G722, |
|
551 + .dstfmt = AST_FORMAT_SLINEAR16, |
|
552 + .newpvt = g722tolin16_new, /* same for both directions */ |
|
553 + .framein = g722tolin_framein, |
|
554 + .sample = g722tolin16_sample, |
|
555 + .desc_size = sizeof(struct g722_decoder_pvt), |
|
556 + .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t), |
|
557 + .buf_size = BUFFER_SAMPLES, |
|
558 + .plc_samples = 160, |
|
559 +}; |
|
560 + |
|
561 +static struct ast_translator lin16tog722 = { |
|
562 + .name = "lin16tog722", |
|
563 + .srcfmt = AST_FORMAT_SLINEAR16, |
|
564 + .dstfmt = AST_FORMAT_G722, |
|
565 + .newpvt = lin16tog722_new, /* same for both directions */ |
|
566 + .framein = lintog722_framein, |
|
567 + .sample = lin16tog722_sample, |
|
568 + .desc_size = sizeof(struct g722_encoder_pvt), |
|
569 + .buffer_samples = BUFFER_SAMPLES * 2, |
|
570 + .buf_size = BUFFER_SAMPLES, |
|
571 +}; |
|
572 + |
|
573 +static int parse_config(int reload) |
|
574 +{ |
|
575 + struct ast_variable *var; |
|
576 + struct ast_config *cfg = ast_config_load("codecs.conf"); |
|
577 + |
|
578 + if (cfg == NULL) |
|
579 + return 0; |
|
580 + if (cfg == CONFIG_STATUS_FILEUNCHANGED) |
|
581 + return 0; |
|
582 + for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { |
|
583 + if (!strcasecmp(var->name, "genericplc")) { |
|
584 + g722tolin.useplc = ast_true(var->value) ? 1 : 0; |
|
585 + if (option_verbose > 2) |
|
586 + ast_verbose(VERBOSE_PREFIX_3 "codec_g722: %susing generic PLC\n", |
|
587 + g722tolin.useplc ? "" : "not "); |
|
588 + } |
|
589 + } |
|
590 + ast_config_destroy(cfg); |
|
591 + return 0; |
|
592 +} |
|
593 + |
|
594 +static int reload(void) |
|
595 +{ |
|
596 + if (parse_config(1)) |
|
597 + return AST_MODULE_LOAD_DECLINE; |
|
598 + return AST_MODULE_LOAD_SUCCESS; |
|
599 +} |
|
600 + |
|
601 +static int unload_module(void) |
|
602 +{ |
|
603 + int res = 0; |
|
604 + |
|
605 + res |= ast_unregister_translator(&g722tolin); |
|
606 + res |= ast_unregister_translator(&lintog722); |
|
607 + res |= ast_unregister_translator(&g722tolin16); |
|
608 + res |= ast_unregister_translator(&lin16tog722); |
|
609 + |
|
610 + return res; |
|
611 +} |
|
612 + |
|
613 +static int load_module(void) |
|
614 +{ |
|
615 + int res = 0; |
|
616 + |
|
617 + if (parse_config(0)) |
|
618 + return AST_MODULE_LOAD_DECLINE; |
|
619 + |
|
620 + res |= ast_register_translator(&g722tolin); |
|
621 + res |= ast_register_translator(&lintog722); |
|
622 + res |= ast_register_translator(&g722tolin16); |
|
623 + res |= ast_register_translator(&lin16tog722); |
|
624 + |
|
625 + if (res) { |
|
626 + unload_module(); |
|
627 + return AST_MODULE_LOAD_FAILURE; |
|
628 + } |
|
629 + |
|
630 + return AST_MODULE_LOAD_SUCCESS; |
|
631 +} |
|
632 + |
|
633 +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder", |
|
634 + .load = load_module, |
|
635 + .unload = unload_module, |
|
636 + .reload = reload, |
|
637 + ); |
|
638 Index: codecs/g722/g722_decode.c |
|
639 diff -Nau codecs/g722/g722_decode.c.orig codecs/g722/g722_decode.c |
|
640 --- codecs/g722/g722_decode.c.orig 1970-01-01 01:00:00.000000000 +0100 |
|
641 +++ codecs/g722/g722_decode.c 2009-04-24 00:30:33.000000000 +0200 |
|
642 @@ -0,0 +1,398 @@ |
|
643 +/* |
|
644 + * SpanDSP - a series of DSP components for telephony |
|
645 + * |
|
646 + * g722_decode.c - The ITU G.722 codec, decode part. |
|
647 + * |
|
648 + * Written by Steve Underwood <steveu@coppice.org> |
|
649 + * |
|
650 + * Copyright (C) 2005 Steve Underwood |
|
651 + * |
|
652 + * Despite my general liking of the GPL, I place my own contributions |
|
653 + * to this code in the public domain for the benefit of all mankind - |
|
654 + * even the slimy ones who might try to proprietize my work and use it |
|
655 + * to my detriment. |
|
656 + * |
|
657 + * Based in part on a single channel G.722 codec which is: |
|
658 + * |
|
659 + * Copyright (c) CMU 1993 |
|
660 + * Computer Science, Speech Group |
|
661 + * Chengxiang Lu and Alex Hauptmann |
|
662 + * |
|
663 + * $Id: g722_decode.c 48661 2006-12-21 00:08:21Z mattf $ |
|
664 + */ |
|
665 + |
|
666 +/*! \file */ |
|
667 + |
|
668 +#ifdef HAVE_CONFIG_H |
|
669 +#include <config.h> |
|
670 +#endif |
|
671 + |
|
672 +#include <stdio.h> |
|
673 +#include <inttypes.h> |
|
674 +#include <memory.h> |
|
675 +#include <stdlib.h> |
|
676 +#if 0 |
|
677 +#include <tgmath.h> |
|
678 +#endif |
|
679 + |
|
680 +#include "g722.h" |
|
681 + |
|
682 +#if !defined(FALSE) |
|
683 +#define FALSE 0 |
|
684 +#endif |
|
685 +#if !defined(TRUE) |
|
686 +#define TRUE (!FALSE) |
|
687 +#endif |
|
688 + |
|
689 +static __inline__ int16_t saturate(int32_t amp) |
|
690 +{ |
|
691 + int16_t amp16; |
|
692 + |
|
693 + /* Hopefully this is optimised for the common case - not clipping */ |
|
694 + amp16 = (int16_t) amp; |
|
695 + if (amp == amp16) |
|
696 + return amp16; |
|
697 + if (amp > INT16_MAX) |
|
698 + return INT16_MAX; |
|
699 + return INT16_MIN; |
|
700 +} |
|
701 +/*- End of function --------------------------------------------------------*/ |
|
702 + |
|
703 +static void block4(g722_decode_state_t *s, int band, int d); |
|
704 + |
|
705 +static void block4(g722_decode_state_t *s, int band, int d) |
|
706 +{ |
|
707 + int wd1; |
|
708 + int wd2; |
|
709 + int wd3; |
|
710 + int i; |
|
711 + |
|
712 + /* Block 4, RECONS */ |
|
713 + s->band[band].d[0] = d; |
|
714 + s->band[band].r[0] = saturate(s->band[band].s + d); |
|
715 + |
|
716 + /* Block 4, PARREC */ |
|
717 + s->band[band].p[0] = saturate(s->band[band].sz + d); |
|
718 + |
|
719 + /* Block 4, UPPOL2 */ |
|
720 + for (i = 0; i < 3; i++) |
|
721 + s->band[band].sg[i] = s->band[band].p[i] >> 15; |
|
722 + wd1 = saturate(s->band[band].a[1] << 2); |
|
723 + |
|
724 + wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1; |
|
725 + if (wd2 > 32767) |
|
726 + wd2 = 32767; |
|
727 + wd3 = (s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128; |
|
728 + wd3 += (wd2 >> 7); |
|
729 + wd3 += (s->band[band].a[2]*32512) >> 15; |
|
730 + if (wd3 > 12288) |
|
731 + wd3 = 12288; |
|
732 + else if (wd3 < -12288) |
|
733 + wd3 = -12288; |
|
734 + s->band[band].ap[2] = wd3; |
|
735 + |
|
736 + /* Block 4, UPPOL1 */ |
|
737 + s->band[band].sg[0] = s->band[band].p[0] >> 15; |
|
738 + s->band[band].sg[1] = s->band[band].p[1] >> 15; |
|
739 + wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192; |
|
740 + wd2 = (s->band[band].a[1]*32640) >> 15; |
|
741 + |
|
742 + s->band[band].ap[1] = saturate(wd1 + wd2); |
|
743 + wd3 = saturate(15360 - s->band[band].ap[2]); |
|
744 + if (s->band[band].ap[1] > wd3) |
|
745 + s->band[band].ap[1] = wd3; |
|
746 + else if (s->band[band].ap[1] < -wd3) |
|
747 + s->band[band].ap[1] = -wd3; |
|
748 + |
|
749 + /* Block 4, UPZERO */ |
|
750 + wd1 = (d == 0) ? 0 : 128; |
|
751 + s->band[band].sg[0] = d >> 15; |
|
752 + for (i = 1; i < 7; i++) |
|
753 + { |
|
754 + s->band[band].sg[i] = s->band[band].d[i] >> 15; |
|
755 + wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1; |
|
756 + wd3 = (s->band[band].b[i]*32640) >> 15; |
|
757 + s->band[band].bp[i] = saturate(wd2 + wd3); |
|
758 + } |
|
759 + |
|
760 + /* Block 4, DELAYA */ |
|
761 + for (i = 6; i > 0; i--) |
|
762 + { |
|
763 + s->band[band].d[i] = s->band[band].d[i - 1]; |
|
764 + s->band[band].b[i] = s->band[band].bp[i]; |
|
765 + } |
|
766 + |
|
767 + for (i = 2; i > 0; i--) |
|
768 + { |
|
769 + s->band[band].r[i] = s->band[band].r[i - 1]; |
|
770 + s->band[band].p[i] = s->band[band].p[i - 1]; |
|
771 + s->band[band].a[i] = s->band[band].ap[i]; |
|
772 + } |
|
773 + |
|
774 + /* Block 4, FILTEP */ |
|
775 + wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]); |
|
776 + wd1 = (s->band[band].a[1]*wd1) >> 15; |
|
777 + wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]); |
|
778 + wd2 = (s->band[band].a[2]*wd2) >> 15; |
|
779 + s->band[band].sp = saturate(wd1 + wd2); |
|
780 + |
|
781 + /* Block 4, FILTEZ */ |
|
782 + s->band[band].sz = 0; |
|
783 + for (i = 6; i > 0; i--) |
|
784 + { |
|
785 + wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]); |
|
786 + s->band[band].sz += (s->band[band].b[i]*wd1) >> 15; |
|
787 + } |
|
788 + s->band[band].sz = saturate(s->band[band].sz); |
|
789 + |
|
790 + /* Block 4, PREDIC */ |
|
791 + s->band[band].s = saturate(s->band[band].sp + s->band[band].sz); |
|
792 +} |
|
793 +/*- End of function --------------------------------------------------------*/ |
|
794 + |
|
795 +g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options) |
|
796 +{ |
|
797 + if (s == NULL) |
|
798 + { |
|
799 + if ((s = (g722_decode_state_t *) malloc(sizeof(*s))) == NULL) |
|
800 + return NULL; |
|
801 + } |
|
802 + memset(s, 0, sizeof(*s)); |
|
803 + if (rate == 48000) |
|
804 + s->bits_per_sample = 6; |
|
805 + else if (rate == 56000) |
|
806 + s->bits_per_sample = 7; |
|
807 + else |
|
808 + s->bits_per_sample = 8; |
|
809 + if ((options & G722_SAMPLE_RATE_8000)) |
|
810 + s->eight_k = TRUE; |
|
811 + if ((options & G722_PACKED) && s->bits_per_sample != 8) |
|
812 + s->packed = TRUE; |
|
813 + else |
|
814 + s->packed = FALSE; |
|
815 + s->band[0].det = 32; |
|
816 + s->band[1].det = 8; |
|
817 + return s; |
|
818 +} |
|
819 +/*- End of function --------------------------------------------------------*/ |
|
820 + |
|
821 +int g722_decode_release(g722_decode_state_t *s) |
|
822 +{ |
|
823 + free(s); |
|
824 + return 0; |
|
825 +} |
|
826 +/*- End of function --------------------------------------------------------*/ |
|
827 + |
|
828 +int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len) |
|
829 +{ |
|
830 + static const int wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042 }; |
|
831 + static const int rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 }; |
|
832 + static const int ilb[32] = |
|
833 + { |
|
834 + 2048, 2093, 2139, 2186, 2233, 2282, 2332, |
|
835 + 2383, 2435, 2489, 2543, 2599, 2656, 2714, |
|
836 + 2774, 2834, 2896, 2960, 3025, 3091, 3158, |
|
837 + 3228, 3298, 3371, 3444, 3520, 3597, 3676, |
|
838 + 3756, 3838, 3922, 4008 |
|
839 + }; |
|
840 + static const int wh[3] = {0, -214, 798}; |
|
841 + static const int rh2[4] = {2, 1, 2, 1}; |
|
842 + static const int qm2[4] = {-7408, -1616, 7408, 1616}; |
|
843 + static const int qm4[16] = |
|
844 + { |
|
845 + 0, -20456, -12896, -8968, |
|
846 + -6288, -4240, -2584, -1200, |
|
847 + 20456, 12896, 8968, 6288, |
|
848 + 4240, 2584, 1200, 0 |
|
849 + }; |
|
850 + static const int qm5[32] = |
|
851 + { |
|
852 + -280, -280, -23352, -17560, |
|
853 + -14120, -11664, -9752, -8184, |
|
854 + -6864, -5712, -4696, -3784, |
|
855 + -2960, -2208, -1520, -880, |
|
856 + 23352, 17560, 14120, 11664, |
|
857 + 9752, 8184, 6864, 5712, |
|
858 + 4696, 3784, 2960, 2208, |
|
859 + 1520, 880, 280, -280 |
|
860 + }; |
|
861 + static const int qm6[64] = |
|
862 + { |
|
863 + -136, -136, -136, -136, |
|
864 + -24808, -21904, -19008, -16704, |
|
865 + -14984, -13512, -12280, -11192, |
|
866 + -10232, -9360, -8576, -7856, |
|
867 + -7192, -6576, -6000, -5456, |
|
868 + -4944, -4464, -4008, -3576, |
|
869 + -3168, -2776, -2400, -2032, |
|
870 + -1688, -1360, -1040, -728, |
|
871 + 24808, 21904, 19008, 16704, |
|
872 + 14984, 13512, 12280, 11192, |
|
873 + 10232, 9360, 8576, 7856, |
|
874 + 7192, 6576, 6000, 5456, |
|
875 + 4944, 4464, 4008, 3576, |
|
876 + 3168, 2776, 2400, 2032, |
|
877 + 1688, 1360, 1040, 728, |
|
878 + 432, 136, -432, -136 |
|
879 + }; |
|
880 + static const int qmf_coeffs[12] = |
|
881 + { |
|
882 + 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, |
|
883 + }; |
|
884 + |
|
885 + int dlowt; |
|
886 + int rlow; |
|
887 + int ihigh; |
|
888 + int dhigh; |
|
889 + int rhigh; |
|
890 + int xout1; |
|
891 + int xout2; |
|
892 + int wd1; |
|
893 + int wd2; |
|
894 + int wd3; |
|
895 + int code; |
|
896 + int outlen; |
|
897 + int i; |
|
898 + int j; |
|
899 + |
|
900 + outlen = 0; |
|
901 + rhigh = 0; |
|
902 + for (j = 0; j < len; ) |
|
903 + { |
|
904 + if (s->packed) |
|
905 + { |
|
906 + /* Unpack the code bits */ |
|
907 + if (s->in_bits < s->bits_per_sample) |
|
908 + { |
|
909 + s->in_buffer |= (g722_data[j++] << s->in_bits); |
|
910 + s->in_bits += 8; |
|
911 + } |
|
912 + code = s->in_buffer & ((1 << s->bits_per_sample) - 1); |
|
913 + s->in_buffer >>= s->bits_per_sample; |
|
914 + s->in_bits -= s->bits_per_sample; |
|
915 + } |
|
916 + else |
|
917 + { |
|
918 + code = g722_data[j++]; |
|
919 + } |
|
920 + |
|
921 + switch (s->bits_per_sample) |
|
922 + { |
|
923 + default: |
|
924 + case 8: |
|
925 + wd1 = code & 0x3F; |
|
926 + ihigh = (code >> 6) & 0x03; |
|
927 + wd2 = qm6[wd1]; |
|
928 + wd1 >>= 2; |
|
929 + break; |
|
930 + case 7: |
|
931 + wd1 = code & 0x1F; |
|
932 + ihigh = (code >> 5) & 0x03; |
|
933 + wd2 = qm5[wd1]; |
|
934 + wd1 >>= 1; |
|
935 + break; |
|
936 + case 6: |
|
937 + wd1 = code & 0x0F; |
|
938 + ihigh = (code >> 4) & 0x03; |
|
939 + wd2 = qm4[wd1]; |
|
940 + break; |
|
941 + } |
|
942 + /* Block 5L, LOW BAND INVQBL */ |
|
943 + wd2 = (s->band[0].det*wd2) >> 15; |
|
944 + /* Block 5L, RECONS */ |
|
945 + rlow = s->band[0].s + wd2; |
|
946 + /* Block 6L, LIMIT */ |
|
947 + if (rlow > 16383) |
|
948 + rlow = 16383; |
|
949 + else if (rlow < -16384) |
|
950 + rlow = -16384; |
|
951 + |
|
952 + /* Block 2L, INVQAL */ |
|
953 + wd2 = qm4[wd1]; |
|
954 + dlowt = (s->band[0].det*wd2) >> 15; |
|
955 + |
|
956 + /* Block 3L, LOGSCL */ |
|
957 + wd2 = rl42[wd1]; |
|
958 + wd1 = (s->band[0].nb*127) >> 7; |
|
959 + wd1 += wl[wd2]; |
|
960 + if (wd1 < 0) |
|
961 + wd1 = 0; |
|
962 + else if (wd1 > 18432) |
|
963 + wd1 = 18432; |
|
964 + s->band[0].nb = wd1; |
|
965 + |
|
966 + /* Block 3L, SCALEL */ |
|
967 + wd1 = (s->band[0].nb >> 6) & 31; |
|
968 + wd2 = 8 - (s->band[0].nb >> 11); |
|
969 + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
|
970 + s->band[0].det = wd3 << 2; |
|
971 + |
|
972 + block4(s, 0, dlowt); |
|
973 + |
|
974 + if (!s->eight_k) |
|
975 + { |
|
976 + /* Block 2H, INVQAH */ |
|
977 + wd2 = qm2[ihigh]; |
|
978 + dhigh = (s->band[1].det*wd2) >> 15; |
|
979 + /* Block 5H, RECONS */ |
|
980 + rhigh = dhigh + s->band[1].s; |
|
981 + /* Block 6H, LIMIT */ |
|
982 + if (rhigh > 16383) |
|
983 + rhigh = 16383; |
|
984 + else if (rhigh < -16384) |
|
985 + rhigh = -16384; |
|
986 + |
|
987 + /* Block 2H, INVQAH */ |
|
988 + wd2 = rh2[ihigh]; |
|
989 + wd1 = (s->band[1].nb*127) >> 7; |
|
990 + wd1 += wh[wd2]; |
|
991 + if (wd1 < 0) |
|
992 + wd1 = 0; |
|
993 + else if (wd1 > 22528) |
|
994 + wd1 = 22528; |
|
995 + s->band[1].nb = wd1; |
|
996 + |
|
997 + /* Block 3H, SCALEH */ |
|
998 + wd1 = (s->band[1].nb >> 6) & 31; |
|
999 + wd2 = 10 - (s->band[1].nb >> 11); |
|
1000 + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
|
1001 + s->band[1].det = wd3 << 2; |
|
1002 + |
|
1003 + block4(s, 1, dhigh); |
|
1004 + } |
|
1005 + |
|
1006 + if (s->itu_test_mode) |
|
1007 + { |
|
1008 + amp[outlen++] = (int16_t) (rlow << 1); |
|
1009 + amp[outlen++] = (int16_t) (rhigh << 1); |
|
1010 + } |
|
1011 + else |
|
1012 + { |
|
1013 + if (s->eight_k) |
|
1014 + { |
|
1015 + amp[outlen++] = (int16_t) rlow; |
|
1016 + } |
|
1017 + else |
|
1018 + { |
|
1019 + /* Apply the receive QMF */ |
|
1020 + for (i = 0; i < 22; i++) |
|
1021 + s->x[i] = s->x[i + 2]; |
|
1022 + s->x[22] = rlow + rhigh; |
|
1023 + s->x[23] = rlow - rhigh; |
|
1024 + |
|
1025 + xout1 = 0; |
|
1026 + xout2 = 0; |
|
1027 + for (i = 0; i < 12; i++) |
|
1028 + { |
|
1029 + xout2 += s->x[2*i]*qmf_coeffs[i]; |
|
1030 + xout1 += s->x[2*i + 1]*qmf_coeffs[11 - i]; |
|
1031 + } |
|
1032 + amp[outlen++] = (int16_t) (xout1 >> 12); |
|
1033 + amp[outlen++] = (int16_t) (xout2 >> 12); |
|
1034 + } |
|
1035 + } |
|
1036 + } |
|
1037 + return outlen; |
|
1038 +} |
|
1039 +/*- End of function --------------------------------------------------------*/ |
|
1040 +/*- End of file ------------------------------------------------------------*/ |
|
1041 Index: codecs/g722/g722_encode.c |
|
1042 diff -Nau codecs/g722/g722_encode.c.orig codecs/g722/g722_encode.c |
|
1043 --- codecs/g722/g722_encode.c.orig 1970-01-01 01:00:00.000000000 +0100 |
|
1044 +++ codecs/g722/g722_encode.c 2009-04-24 00:30:33.000000000 +0200 |
|
1045 @@ -0,0 +1,400 @@ |
|
1046 +/* |
|
1047 + * SpanDSP - a series of DSP components for telephony |
|
1048 + * |
|
1049 + * g722_encode.c - The ITU G.722 codec, encode part. |
|
1050 + * |
|
1051 + * Written by Steve Underwood <steveu@coppice.org> |
|
1052 + * |
|
1053 + * Copyright (C) 2005 Steve Underwood |
|
1054 + * |
|
1055 + * All rights reserved. |
|
1056 + * |
|
1057 + * Despite my general liking of the GPL, I place my own contributions |
|
1058 + * to this code in the public domain for the benefit of all mankind - |
|
1059 + * even the slimy ones who might try to proprietize my work and use it |
|
1060 + * to my detriment. |
|
1061 + * |
|
1062 + * Based on a single channel 64kbps only G.722 codec which is: |
|
1063 + * |
|
1064 + ***** Copyright (c) CMU 1993 ***** |
|
1065 + * Computer Science, Speech Group |
|
1066 + * Chengxiang Lu and Alex Hauptmann |
|
1067 + * |
|
1068 + * $Id: g722_encode.c 48661 2006-12-21 00:08:21Z mattf $ |
|
1069 + */ |
|
1070 + |
|
1071 +/*! \file */ |
|
1072 + |
|
1073 +#ifdef HAVE_CONFIG_H |
|
1074 +#include <config.h> |
|
1075 +#endif |
|
1076 + |
|
1077 +#include <stdio.h> |
|
1078 +#include <inttypes.h> |
|
1079 +#include <memory.h> |
|
1080 +#include <stdlib.h> |
|
1081 +#if 0 |
|
1082 +#include <tgmath.h> |
|
1083 +#endif |
|
1084 + |
|
1085 +#include "g722.h" |
|
1086 + |
|
1087 +#if !defined(FALSE) |
|
1088 +#define FALSE 0 |
|
1089 +#endif |
|
1090 +#if !defined(TRUE) |
|
1091 +#define TRUE (!FALSE) |
|
1092 +#endif |
|
1093 + |
|
1094 +static __inline__ int16_t saturate(int32_t amp) |
|
1095 +{ |
|
1096 + int16_t amp16; |
|
1097 + |
|
1098 + /* Hopefully this is optimised for the common case - not clipping */ |
|
1099 + amp16 = (int16_t) amp; |
|
1100 + if (amp == amp16) |
|
1101 + return amp16; |
|
1102 + if (amp > INT16_MAX) |
|
1103 + return INT16_MAX; |
|
1104 + return INT16_MIN; |
|
1105 +} |
|
1106 +/*- End of function --------------------------------------------------------*/ |
|
1107 + |
|
1108 +static void block4(g722_encode_state_t *s, int band, int d) |
|
1109 +{ |
|
1110 + int wd1; |
|
1111 + int wd2; |
|
1112 + int wd3; |
|
1113 + int i; |
|
1114 + |
|
1115 + /* Block 4, RECONS */ |
|
1116 + s->band[band].d[0] = d; |
|
1117 + s->band[band].r[0] = saturate(s->band[band].s + d); |
|
1118 + |
|
1119 + /* Block 4, PARREC */ |
|
1120 + s->band[band].p[0] = saturate(s->band[band].sz + d); |
|
1121 + |
|
1122 + /* Block 4, UPPOL2 */ |
|
1123 + for (i = 0; i < 3; i++) |
|
1124 + s->band[band].sg[i] = s->band[band].p[i] >> 15; |
|
1125 + wd1 = saturate(s->band[band].a[1] << 2); |
|
1126 + |
|
1127 + wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1; |
|
1128 + if (wd2 > 32767) |
|
1129 + wd2 = 32767; |
|
1130 + wd3 = (wd2 >> 7) + ((s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128); |
|
1131 + wd3 += (s->band[band].a[2]*32512) >> 15; |
|
1132 + if (wd3 > 12288) |
|
1133 + wd3 = 12288; |
|
1134 + else if (wd3 < -12288) |
|
1135 + wd3 = -12288; |
|
1136 + s->band[band].ap[2] = wd3; |
|
1137 + |
|
1138 + /* Block 4, UPPOL1 */ |
|
1139 + s->band[band].sg[0] = s->band[band].p[0] >> 15; |
|
1140 + s->band[band].sg[1] = s->band[band].p[1] >> 15; |
|
1141 + wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192; |
|
1142 + wd2 = (s->band[band].a[1]*32640) >> 15; |
|
1143 + |
|
1144 + s->band[band].ap[1] = saturate(wd1 + wd2); |
|
1145 + wd3 = saturate(15360 - s->band[band].ap[2]); |
|
1146 + if (s->band[band].ap[1] > wd3) |
|
1147 + s->band[band].ap[1] = wd3; |
|
1148 + else if (s->band[band].ap[1] < -wd3) |
|
1149 + s->band[band].ap[1] = -wd3; |
|
1150 + |
|
1151 + /* Block 4, UPZERO */ |
|
1152 + wd1 = (d == 0) ? 0 : 128; |
|
1153 + s->band[band].sg[0] = d >> 15; |
|
1154 + for (i = 1; i < 7; i++) |
|
1155 + { |
|
1156 + s->band[band].sg[i] = s->band[band].d[i] >> 15; |
|
1157 + wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1; |
|
1158 + wd3 = (s->band[band].b[i]*32640) >> 15; |
|
1159 + s->band[band].bp[i] = saturate(wd2 + wd3); |
|
1160 + } |
|
1161 + |
|
1162 + /* Block 4, DELAYA */ |
|
1163 + for (i = 6; i > 0; i--) |
|
1164 + { |
|
1165 + s->band[band].d[i] = s->band[band].d[i - 1]; |
|
1166 + s->band[band].b[i] = s->band[band].bp[i]; |
|
1167 + } |
|
1168 + |
|
1169 + for (i = 2; i > 0; i--) |
|
1170 + { |
|
1171 + s->band[band].r[i] = s->band[band].r[i - 1]; |
|
1172 + s->band[band].p[i] = s->band[band].p[i - 1]; |
|
1173 + s->band[band].a[i] = s->band[band].ap[i]; |
|
1174 + } |
|
1175 + |
|
1176 + /* Block 4, FILTEP */ |
|
1177 + wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]); |
|
1178 + wd1 = (s->band[band].a[1]*wd1) >> 15; |
|
1179 + wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]); |
|
1180 + wd2 = (s->band[band].a[2]*wd2) >> 15; |
|
1181 + s->band[band].sp = saturate(wd1 + wd2); |
|
1182 + |
|
1183 + /* Block 4, FILTEZ */ |
|
1184 + s->band[band].sz = 0; |
|
1185 + for (i = 6; i > 0; i--) |
|
1186 + { |
|
1187 + wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]); |
|
1188 + s->band[band].sz += (s->band[band].b[i]*wd1) >> 15; |
|
1189 + } |
|
1190 + s->band[band].sz = saturate(s->band[band].sz); |
|
1191 + |
|
1192 + /* Block 4, PREDIC */ |
|
1193 + s->band[band].s = saturate(s->band[band].sp + s->band[band].sz); |
|
1194 +} |
|
1195 +/*- End of function --------------------------------------------------------*/ |
|
1196 + |
|
1197 +g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options) |
|
1198 +{ |
|
1199 + if (s == NULL) |
|
1200 + { |
|
1201 + if ((s = (g722_encode_state_t *) malloc(sizeof(*s))) == NULL) |
|
1202 + return NULL; |
|
1203 + } |
|
1204 + memset(s, 0, sizeof(*s)); |
|
1205 + if (rate == 48000) |
|
1206 + s->bits_per_sample = 6; |
|
1207 + else if (rate == 56000) |
|
1208 + s->bits_per_sample = 7; |
|
1209 + else |
|
1210 + s->bits_per_sample = 8; |
|
1211 + if ((options & G722_SAMPLE_RATE_8000)) |
|
1212 + s->eight_k = TRUE; |
|
1213 + if ((options & G722_PACKED) && s->bits_per_sample != 8) |
|
1214 + s->packed = TRUE; |
|
1215 + else |
|
1216 + s->packed = FALSE; |
|
1217 + s->band[0].det = 32; |
|
1218 + s->band[1].det = 8; |
|
1219 + return s; |
|
1220 +} |
|
1221 +/*- End of function --------------------------------------------------------*/ |
|
1222 + |
|
1223 +int g722_encode_release(g722_encode_state_t *s) |
|
1224 +{ |
|
1225 + free(s); |
|
1226 + return 0; |
|
1227 +} |
|
1228 +/*- End of function --------------------------------------------------------*/ |
|
1229 + |
|
1230 +int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len) |
|
1231 +{ |
|
1232 + static const int q6[32] = |
|
1233 + { |
|
1234 + 0, 35, 72, 110, 150, 190, 233, 276, |
|
1235 + 323, 370, 422, 473, 530, 587, 650, 714, |
|
1236 + 786, 858, 940, 1023, 1121, 1219, 1339, 1458, |
|
1237 + 1612, 1765, 1980, 2195, 2557, 2919, 0, 0 |
|
1238 + }; |
|
1239 + static const int iln[32] = |
|
1240 + { |
|
1241 + 0, 63, 62, 31, 30, 29, 28, 27, |
|
1242 + 26, 25, 24, 23, 22, 21, 20, 19, |
|
1243 + 18, 17, 16, 15, 14, 13, 12, 11, |
|
1244 + 10, 9, 8, 7, 6, 5, 4, 0 |
|
1245 + }; |
|
1246 + static const int ilp[32] = |
|
1247 + { |
|
1248 + 0, 61, 60, 59, 58, 57, 56, 55, |
|
1249 + 54, 53, 52, 51, 50, 49, 48, 47, |
|
1250 + 46, 45, 44, 43, 42, 41, 40, 39, |
|
1251 + 38, 37, 36, 35, 34, 33, 32, 0 |
|
1252 + }; |
|
1253 + static const int wl[8] = |
|
1254 + { |
|
1255 + -60, -30, 58, 172, 334, 538, 1198, 3042 |
|
1256 + }; |
|
1257 + static const int rl42[16] = |
|
1258 + { |
|
1259 + 0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 |
|
1260 + }; |
|
1261 + static const int ilb[32] = |
|
1262 + { |
|
1263 + 2048, 2093, 2139, 2186, 2233, 2282, 2332, |
|
1264 + 2383, 2435, 2489, 2543, 2599, 2656, 2714, |
|
1265 + 2774, 2834, 2896, 2960, 3025, 3091, 3158, |
|
1266 + 3228, 3298, 3371, 3444, 3520, 3597, 3676, |
|
1267 + 3756, 3838, 3922, 4008 |
|
1268 + }; |
|
1269 + static const int qm4[16] = |
|
1270 + { |
|
1271 + 0, -20456, -12896, -8968, |
|
1272 + -6288, -4240, -2584, -1200, |
|
1273 + 20456, 12896, 8968, 6288, |
|
1274 + 4240, 2584, 1200, 0 |
|
1275 + }; |
|
1276 + static const int qm2[4] = |
|
1277 + { |
|
1278 + -7408, -1616, 7408, 1616 |
|
1279 + }; |
|
1280 + static const int qmf_coeffs[12] = |
|
1281 + { |
|
1282 + 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, |
|
1283 + }; |
|
1284 + static const int ihn[3] = {0, 1, 0}; |
|
1285 + static const int ihp[3] = {0, 3, 2}; |
|
1286 + static const int wh[3] = {0, -214, 798}; |
|
1287 + static const int rh2[4] = {2, 1, 2, 1}; |
|
1288 + |
|
1289 + int dlow; |
|
1290 + int dhigh; |
|
1291 + int el; |
|
1292 + int wd; |
|
1293 + int wd1; |
|
1294 + int ril; |
|
1295 + int wd2; |
|
1296 + int il4; |
|
1297 + int ih2; |
|
1298 + int wd3; |
|
1299 + int eh; |
|
1300 + int mih; |
|
1301 + int i; |
|
1302 + int j; |
|
1303 + /* Low and high band PCM from the QMF */ |
|
1304 + int xlow; |
|
1305 + int xhigh; |
|
1306 + int g722_bytes; |
|
1307 + /* Even and odd tap accumulators */ |
|
1308 + int sumeven; |
|
1309 + int sumodd; |
|
1310 + int ihigh; |
|
1311 + int ilow; |
|
1312 + int code; |
|
1313 + |
|
1314 + g722_bytes = 0; |
|
1315 + xhigh = 0; |
|
1316 + for (j = 0; j < len; ) |
|
1317 + { |
|
1318 + if (s->itu_test_mode) |
|
1319 + { |
|
1320 + xlow = |
|
1321 + xhigh = amp[j++] >> 1; |
|
1322 + } |
|
1323 + else |
|
1324 + { |
|
1325 + if (s->eight_k) |
|
1326 + { |
|
1327 + xlow = amp[j++]; |
|
1328 + } |
|
1329 + else |
|
1330 + { |
|
1331 + /* Apply the transmit QMF */ |
|
1332 + /* Shuffle the buffer down */ |
|
1333 + for (i = 0; i < 22; i++) |
|
1334 + s->x[i] = s->x[i + 2]; |
|
1335 + s->x[22] = amp[j++]; |
|
1336 + s->x[23] = amp[j++]; |
|
1337 + |
|
1338 + /* Discard every other QMF output */ |
|
1339 + sumeven = 0; |
|
1340 + sumodd = 0; |
|
1341 + for (i = 0; i < 12; i++) |
|
1342 + { |
|
1343 + sumodd += s->x[2*i]*qmf_coeffs[i]; |
|
1344 + sumeven += s->x[2*i + 1]*qmf_coeffs[11 - i]; |
|
1345 + } |
|
1346 + xlow = (sumeven + sumodd) >> 13; |
|
1347 + xhigh = (sumeven - sumodd) >> 13; |
|
1348 + } |
|
1349 + } |
|
1350 + /* Block 1L, SUBTRA */ |
|
1351 + el = saturate(xlow - s->band[0].s); |
|
1352 + |
|
1353 + /* Block 1L, QUANTL */ |
|
1354 + wd = (el >= 0) ? el : -(el + 1); |
|
1355 + |
|
1356 + for (i = 1; i < 30; i++) |
|
1357 + { |
|
1358 + wd1 = (q6[i]*s->band[0].det) >> 12; |
|
1359 + if (wd < wd1) |
|
1360 + break; |
|
1361 + } |
|
1362 + ilow = (el < 0) ? iln[i] : ilp[i]; |
|
1363 + |
|
1364 + /* Block 2L, INVQAL */ |
|
1365 + ril = ilow >> 2; |
|
1366 + wd2 = qm4[ril]; |
|
1367 + dlow = (s->band[0].det*wd2) >> 15; |
|
1368 + |
|
1369 + /* Block 3L, LOGSCL */ |
|
1370 + il4 = rl42[ril]; |
|
1371 + wd = (s->band[0].nb*127) >> 7; |
|
1372 + s->band[0].nb = wd + wl[il4]; |
|
1373 + if (s->band[0].nb < 0) |
|
1374 + s->band[0].nb = 0; |
|
1375 + else if (s->band[0].nb > 18432) |
|
1376 + s->band[0].nb = 18432; |
|
1377 + |
|
1378 + /* Block 3L, SCALEL */ |
|
1379 + wd1 = (s->band[0].nb >> 6) & 31; |
|
1380 + wd2 = 8 - (s->band[0].nb >> 11); |
|
1381 + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
|
1382 + s->band[0].det = wd3 << 2; |
|
1383 + |
|
1384 + block4(s, 0, dlow); |
|
1385 + |
|
1386 + if (s->eight_k) |
|
1387 + { |
|
1388 + /* Just leave the high bits as zero */ |
|
1389 + code = (0xC0 | ilow) >> (8 - s->bits_per_sample); |
|
1390 + } |
|
1391 + else |
|
1392 + { |
|
1393 + /* Block 1H, SUBTRA */ |
|
1394 + eh = saturate(xhigh - s->band[1].s); |
|
1395 + |
|
1396 + /* Block 1H, QUANTH */ |
|
1397 + wd = (eh >= 0) ? eh : -(eh + 1); |
|
1398 + wd1 = (564*s->band[1].det) >> 12; |
|
1399 + mih = (wd >= wd1) ? 2 : 1; |
|
1400 + ihigh = (eh < 0) ? ihn[mih] : ihp[mih]; |
|
1401 + |
|
1402 + /* Block 2H, INVQAH */ |
|
1403 + wd2 = qm2[ihigh]; |
|
1404 + dhigh = (s->band[1].det*wd2) >> 15; |
|
1405 + |
|
1406 + /* Block 3H, LOGSCH */ |
|
1407 + ih2 = rh2[ihigh]; |
|
1408 + wd = (s->band[1].nb*127) >> 7; |
|
1409 + s->band[1].nb = wd + wh[ih2]; |
|
1410 + if (s->band[1].nb < 0) |
|
1411 + s->band[1].nb = 0; |
|
1412 + else if (s->band[1].nb > 22528) |
|
1413 + s->band[1].nb = 22528; |
|
1414 + |
|
1415 + /* Block 3H, SCALEH */ |
|
1416 + wd1 = (s->band[1].nb >> 6) & 31; |
|
1417 + wd2 = 10 - (s->band[1].nb >> 11); |
|
1418 + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
|
1419 + s->band[1].det = wd3 << 2; |
|
1420 + |
|
1421 + block4(s, 1, dhigh); |
|
1422 + code = ((ihigh << 6) | ilow) >> (8 - s->bits_per_sample); |
|
1423 + } |
|
1424 + |
|
1425 + if (s->packed) |
|
1426 + { |
|
1427 + /* Pack the code bits */ |
|
1428 + s->out_buffer |= (code << s->out_bits); |
|
1429 + s->out_bits += s->bits_per_sample; |
|
1430 + if (s->out_bits >= 8) |
|
1431 + { |
|
1432 + g722_data[g722_bytes++] = (uint8_t) (s->out_buffer & 0xFF); |
|
1433 + s->out_bits -= 8; |
|
1434 + s->out_buffer >>= 8; |
|
1435 + } |
|
1436 + } |
|
1437 + else |
|
1438 + { |
|
1439 + g722_data[g722_bytes++] = (uint8_t) code; |
|
1440 + } |
|
1441 + } |
|
1442 + return g722_bytes; |
|
1443 +} |
|
1444 +/*- End of function --------------------------------------------------------*/ |
|
1445 +/*- End of file ------------------------------------------------------------*/ |
|
1446 Index: codecs/g722/g722.h |
|
1447 diff -Nau codecs/g722/g722.h.orig codecs/g722/g722.h |
|
1448 --- codecs/g722/g722.h.orig 1970-01-01 01:00:00.000000000 +0100 |
|
1449 +++ codecs/g722/g722.h 2009-04-24 00:30:33.000000000 +0200 |
|
1450 @@ -0,0 +1,148 @@ |
|
1451 +/* |
|
1452 + * SpanDSP - a series of DSP components for telephony |
|
1453 + * |
|
1454 + * g722.h - The ITU G.722 codec. |
|
1455 + * |
|
1456 + * Written by Steve Underwood <steveu@coppice.org> |
|
1457 + * |
|
1458 + * Copyright (C) 2005 Steve Underwood |
|
1459 + * |
|
1460 + * Despite my general liking of the GPL, I place my own contributions |
|
1461 + * to this code in the public domain for the benefit of all mankind - |
|
1462 + * even the slimy ones who might try to proprietize my work and use it |
|
1463 + * to my detriment. |
|
1464 + * |
|
1465 + * Based on a single channel G.722 codec which is: |
|
1466 + * |
|
1467 + ***** Copyright (c) CMU 1993 ***** |
|
1468 + * Computer Science, Speech Group |
|
1469 + * Chengxiang Lu and Alex Hauptmann |
|
1470 + * |
|
1471 + * $Id: g722.h 48959 2006-12-25 06:42:15Z rizzo $ |
|
1472 + */ |
|
1473 + |
|
1474 + |
|
1475 +/*! \file */ |
|
1476 + |
|
1477 +#if !defined(_G722_H_) |
|
1478 +#define _G722_H_ |
|
1479 + |
|
1480 +/*! \page g722_page G.722 encoding and decoding |
|
1481 +\section g722_page_sec_1 What does it do? |
|
1482 +The G.722 module is a bit exact implementation of the ITU G.722 specification for all three |
|
1483 +specified bit rates - 64000bps, 56000bps and 48000bps. It passes the ITU tests. |
|
1484 + |
|
1485 +To allow fast and flexible interworking with narrow band telephony, the encoder and decoder |
|
1486 +support an option for the linear audio to be an 8k samples/second stream. In this mode the |
|
1487 +codec is considerably faster, and still fully compatible with wideband terminals using G.722. |
|
1488 + |
|
1489 +\section g722_page_sec_2 How does it work? |
|
1490 +???. |
|
1491 +*/ |
|
1492 + |
|
1493 +enum |
|
1494 +{ |
|
1495 + G722_SAMPLE_RATE_8000 = 0x0001, |
|
1496 + G722_PACKED = 0x0002 |
|
1497 +}; |
|
1498 + |
|
1499 +#ifndef INT16_MAX |
|
1500 +#define INT16_MAX 32767 |
|
1501 +#endif |
|
1502 +#ifndef INT16_MIN |
|
1503 +#define INT16_MIN (-32768) |
|
1504 +#endif |
|
1505 + |
|
1506 +typedef struct |
|
1507 +{ |
|
1508 + /*! TRUE if the operating in the special ITU test mode, with the band split filters |
|
1509 + disabled. */ |
|
1510 + int itu_test_mode; |
|
1511 + /*! TRUE if the G.722 data is packed */ |
|
1512 + int packed; |
|
1513 + /*! TRUE if encode from 8k samples/second */ |
|
1514 + int eight_k; |
|
1515 + /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ |
|
1516 + int bits_per_sample; |
|
1517 + |
|
1518 + /*! Signal history for the QMF */ |
|
1519 + int x[24]; |
|
1520 + |
|
1521 + struct |
|
1522 + { |
|
1523 + int s; |
|
1524 + int sp; |
|
1525 + int sz; |
|
1526 + int r[3]; |
|
1527 + int a[3]; |
|
1528 + int ap[3]; |
|
1529 + int p[3]; |
|
1530 + int d[7]; |
|
1531 + int b[7]; |
|
1532 + int bp[7]; |
|
1533 + int sg[7]; |
|
1534 + int nb; |
|
1535 + int det; |
|
1536 + } band[2]; |
|
1537 + |
|
1538 + unsigned int in_buffer; |
|
1539 + int in_bits; |
|
1540 + unsigned int out_buffer; |
|
1541 + int out_bits; |
|
1542 +} g722_encode_state_t; |
|
1543 + |
|
1544 +typedef struct |
|
1545 +{ |
|
1546 + /*! TRUE if the operating in the special ITU test mode, with the band split filters |
|
1547 + disabled. */ |
|
1548 + int itu_test_mode; |
|
1549 + /*! TRUE if the G.722 data is packed */ |
|
1550 + int packed; |
|
1551 + /*! TRUE if decode to 8k samples/second */ |
|
1552 + int eight_k; |
|
1553 + /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ |
|
1554 + int bits_per_sample; |
|
1555 + |
|
1556 + /*! Signal history for the QMF */ |
|
1557 + int x[24]; |
|
1558 + |
|
1559 + struct |
|
1560 + { |
|
1561 + int s; |
|
1562 + int sp; |
|
1563 + int sz; |
|
1564 + int r[3]; |
|
1565 + int a[3]; |
|
1566 + int ap[3]; |
|
1567 + int p[3]; |
|
1568 + int d[7]; |
|
1569 + int b[7]; |
|
1570 + int bp[7]; |
|
1571 + int sg[7]; |
|
1572 + int nb; |
|
1573 + int det; |
|
1574 + } band[2]; |
|
1575 + |
|
1576 + unsigned int in_buffer; |
|
1577 + int in_bits; |
|
1578 + unsigned int out_buffer; |
|
1579 + int out_bits; |
|
1580 +} g722_decode_state_t; |
|
1581 + |
|
1582 +#ifdef __cplusplus |
|
1583 +extern "C" { |
|
1584 +#endif |
|
1585 + |
|
1586 +g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options); |
|
1587 +int g722_encode_release(g722_encode_state_t *s); |
|
1588 +int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len); |
|
1589 + |
|
1590 +g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options); |
|
1591 +int g722_decode_release(g722_decode_state_t *s); |
|
1592 +int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len); |
|
1593 + |
|
1594 +#ifdef __cplusplus |
|
1595 +} |
|
1596 +#endif |
|
1597 + |
|
1598 +#endif |
|
1599 Index: codecs/g722/Makefile |
|
1600 diff -Nau codecs/g722/Makefile.orig codecs/g722/Makefile |
|
1601 --- codecs/g722/Makefile.orig 1970-01-01 01:00:00.000000000 +0100 |
|
1602 +++ codecs/g722/Makefile 2009-04-24 00:30:33.000000000 +0200 |
|
1603 @@ -0,0 +1,18 @@ |
|
1604 +LIB=libg722.a |
|
1605 +CFLAGS+=-fPIC |
|
1606 + |
|
1607 +include $(ASTTOPDIR)/Makefile.rules |
|
1608 + |
|
1609 +OBJS=g722_encode.o g722_decode.o |
|
1610 + |
|
1611 +all: $(LIB) |
|
1612 + |
|
1613 +$(LIB): $(OBJS) |
|
1614 + $(ECHO_PREFIX) echo " [AR] $^ -> $@" |
|
1615 + $(CMD_PREFIX) $(AR) cr $@ $^ |
|
1616 + $(CMD_PREFIX) $(RANLIB) $@ |
|
1617 + |
|
1618 +clean: |
|
1619 + rm -f $(LIB) *.o |
|
1620 + rm -f .*.o.d |
|
1621 + rm -f *.s *.i |
|
1622 Index: codecs/g722_slin_ex.h |
|
1623 diff -Nau codecs/g722_slin_ex.h.orig codecs/g722_slin_ex.h |
|
1624 --- codecs/g722_slin_ex.h.orig 1970-01-01 01:00:00.000000000 +0100 |
|
1625 +++ codecs/g722_slin_ex.h 2009-04-24 00:30:33.000000000 +0200 |
|
1626 @@ -0,0 +1,25 @@ |
|
1627 +/*! \file |
|
1628 + * \brief g722_slin_ex.h -- |
|
1629 + * |
|
1630 + * 4-bit ADPCM data, 20 milliseconds worth at 8 kHz. |
|
1631 + * |
|
1632 + * Source: g723.example |
|
1633 + * |
|
1634 + * Copyright (C) 2001-2005, Digium Inc. |
|
1635 + * |
|
1636 + * Distributed under the terms of the GNU General Public License |
|
1637 + * |
|
1638 + */ |
|
1639 + |
|
1640 +static unsigned char g722_slin_ex[] = { |
|
1641 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
1642 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
1643 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
1644 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
1645 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
1646 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
1647 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
1648 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
1649 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
1650 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
|
1651 +}; |
|
1652 Index: codecs/Makefile |
|
1653 diff -Nau codecs/Makefile.orig codecs/Makefile |
|
1654 --- codecs/Makefile.orig 2008-03-26 17:42:35.000000000 +0100 |
|
1655 +++ codecs/Makefile 2009-04-24 00:30:33.000000000 +0200 |
|
1656 @@ -31,6 +31,7 @@ |
|
1657 |
|
1658 LIBILBC:=ilbc/libilbc.a |
|
1659 LIBLPC10:=lpc10/liblpc10.a |
|
1660 +LIBG722:=g722/libg722.a |
|
1661 |
|
1662 all: _all |
|
1663 |
|
1664 @@ -45,6 +46,7 @@ |
|
1665 $(MAKE) -C gsm clean |
|
1666 $(MAKE) -C lpc10 clean |
|
1667 $(MAKE) -C ilbc clean |
|
1668 + $(MAKE) -C g722 clean |
|
1669 |
|
1670 gsm/lib/libgsm.a: |
|
1671 @mkdir -p gsm/lib |
|
1672 @@ -59,3 +61,8 @@ |
|
1673 @$(MAKE) -C ilbc all ASTCFLAGS="$(filter-out -Wmissing-prototypes -Wmissing-declarations,$(ASTCFLAGS)) $(AST_NO_STRICT_OVERFLOW)" |
|
1674 |
|
1675 $(if $(filter codec_ilbc,$(EMBEDDED_MODS)),modules.link,codec_ilbc.so): $(LIBILBC) |
|
1676 + |
|
1677 +$(LIBG722): |
|
1678 + @$(MAKE) -C g722 all |
|
1679 + |
|
1680 +$(if $(filter codec_g722,$(EMBEDDED_MODS)),modules.link,codec_g722.so): $(LIBG722) |
|
1681 Index: codecs/slin_g722_ex.h |
|
1682 diff -Nau codecs/slin_g722_ex.h.orig codecs/slin_g722_ex.h |
|
1683 --- codecs/slin_g722_ex.h.orig 1970-01-01 01:00:00.000000000 +0100 |
|
1684 +++ codecs/slin_g722_ex.h 2009-04-24 00:30:33.000000000 +0200 |
|
1685 @@ -0,0 +1,25 @@ |
|
1686 +/*! \file |
|
1687 + * \brief slin_g722_ex.h -- |
|
1688 + * |
|
1689 + * Signed 16-bit audio data, 10 milliseconds worth at 8 kHz. |
|
1690 + * |
|
1691 + * Source: g723.example |
|
1692 + * |
|
1693 + * Copyright (C) 2001-2005, Digium Inc. |
|
1694 + * |
|
1695 + * Distributed under the terms of the GNU General Public License |
|
1696 + * |
|
1697 + */ |
|
1698 + |
|
1699 +static signed short slin_g722_ex[] = { |
|
1700 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
1701 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
1702 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
1703 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
1704 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
1705 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
1706 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
1707 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
1708 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
|
1709 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 |
|
1710 +}; |
|
1711 Index: configure |
|
1712 diff -Nau configure.orig configure |
|
1713 --- configure.orig 2009-02-18 21:06:45.000000000 +0100 |
|
1714 +++ configure 2009-04-24 00:30:33.000000000 +0200 |
|
1715 @@ -11143,6 +11143,61 @@ |
|
1716 |
|
1717 fi |
|
1718 |
|
1719 +{ echo "$as_me:$LINENO: checking for tm_gmtoff in struct tm" >&5 |
|
1720 +echo $ECHO_N "checking for tm_gmtoff in struct tm... $ECHO_C" >&6; } |
|
1721 +if test "${ac_cv_struct_tm_gmtoff+set}" = set; then |
|
1722 + echo $ECHO_N "(cached) $ECHO_C" >&6 |
|
1723 +else |
|
1724 + cat >conftest.$ac_ext <<_ACEOF |
|
1725 +/* confdefs.h. */ |
|
1726 +_ACEOF |
|
1727 +cat confdefs.h >>conftest.$ac_ext |
|
1728 +cat >>conftest.$ac_ext <<_ACEOF |
|
1729 +/* end confdefs.h. */ |
|
1730 +$ac_includes_default |
|
1731 +#include <sys/types.h> |
|
1732 +#include <$ac_cv_struct_tm> |
|
1733 +int main() { |
|
1734 +struct tm tm; tm.tm_gmtoff; |
|
1735 +; return 0; } |
|
1736 +_ACEOF |
|
1737 +rm -f conftest.$ac_objext |
|
1738 +if { (ac_try="$ac_compile" |
|
1739 +case "(($ac_try" in |
|
1740 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; |
|
1741 + *) ac_try_echo=$ac_try;; |
|
1742 +esac |
|
1743 +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 |
|
1744 + (eval "$ac_compile") 2>conftest.er1 |
|
1745 + ac_status=$? |
|
1746 + grep -v '^ *+' conftest.er1 >conftest.err |
|
1747 + rm -f conftest.er1 |
|
1748 + cat conftest.err >&5 |
|
1749 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
|
1750 + (exit $ac_status); } && { |
|
1751 + test -z "$ac_c_werror_flag" || |
|
1752 + test ! -s conftest.err |
|
1753 + } && test -s conftest.$ac_objext; then |
|
1754 + ac_cv_struct_tm_gmtoff=yes |
|
1755 +else |
|
1756 + echo "$as_me: failed program was:" >&5 |
|
1757 +sed 's/^/| /' conftest.$ac_ext >&5 |
|
1758 + |
|
1759 + ac_cv_struct_tm_gmtoff=no |
|
1760 +fi |
|
1761 + |
|
1762 +rm -f conftest* |
|
1763 +fi |
|
1764 +{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm_gmtoff" >&5 |
|
1765 +echo "${ECHO_T}$ac_cv_struct_tm_gmtoff" >&6; } |
|
1766 +if test $ac_cv_struct_tm_gmtoff = yes; then |
|
1767 + |
|
1768 +cat >>confdefs.h <<\_ACEOF |
|
1769 +#define TM_GMTOFF 1 |
|
1770 +_ACEOF |
|
1771 + |
|
1772 +fi |
|
1773 + |
|
1774 { echo "$as_me:$LINENO: checking for working volatile" >&5 |
|
1775 echo $ECHO_N "checking for working volatile... $ECHO_C" >&6; } |
|
1776 if test "${ac_cv_c_volatile+set}" = set; then |
|
1777 Index: include/asterisk/config.h |
|
1778 diff -Nau include/asterisk/config.h.orig include/asterisk/config.h |
|
1779 --- include/asterisk/config.h.orig 2009-02-18 19:30:38.000000000 +0100 |
|
1780 +++ include/asterisk/config.h 2009-04-24 00:30:33.000000000 +0200 |
|
1781 @@ -33,6 +33,8 @@ |
|
1782 |
|
1783 struct ast_category; |
|
1784 |
|
1785 +#define CONFIG_STATUS_FILEUNCHANGED (void *)-1 |
|
1786 + |
|
1787 struct ast_variable { |
|
1788 char *name; |
|
1789 char *value; |
|
1790 Index: include/asterisk/frame.h |
|
1791 diff -Nau include/asterisk/frame.h.orig include/asterisk/frame.h |
|
1792 --- include/asterisk/frame.h.orig 2009-03-05 19:22:16.000000000 +0100 |
|
1793 +++ include/asterisk/frame.h 2009-04-24 00:30:33.000000000 +0200 |
|
1794 @@ -260,6 +260,8 @@ |
|
1795 #define AST_FORMAT_G726 (1 << 11) |
|
1796 /*! G.722 */ |
|
1797 #define AST_FORMAT_G722 (1 << 12) |
|
1798 +/*! Raw 16-bit Signed Linear (16000 Hz) PCM */ |
|
1799 +#define AST_FORMAT_SLINEAR16 (1 << 15) |
|
1800 /*! Unsupported audio bits */ |
|
1801 #define AST_FORMAT_AUDIO_UNDEFINED ((1 << 13) | (1 << 14) | (1 << 15)) |
|
1802 /*! Maximum audio format */ |
|
1803 Index: main/editline/np/vis.h |
|
1804 diff -Nau main/editline/np/vis.h.orig main/editline/np/vis.h |
|
1805 --- main/editline/np/vis.h.orig 2006-08-21 04:11:39.000000000 +0200 |
|
1806 +++ main/editline/np/vis.h 2009-04-24 00:30:33.000000000 +0200 |
|
1807 @@ -76,6 +76,22 @@ |
|
1808 |
|
1809 #include <sys/cdefs.h> |
|
1810 |
|
1811 +/* correct nonportable unsigned type usage */ |
|
1812 +#if !defined(__FreeBSD__) && !defined(__linux__) |
|
1813 +#ifndef u_int64_t |
|
1814 +#define u_int64_t unsigned long long |
|
1815 +#endif |
|
1816 +#ifndef u_int32_t |
|
1817 +#define u_int32_t unsigned int |
|
1818 +#endif |
|
1819 +#ifndef u_int16_t |
|
1820 +#define u_int16_t unsigned short |
|
1821 +#endif |
|
1822 +#ifndef u_int6_t |
|
1823 +#define u_int8_t unsigned char |
|
1824 +#endif |
|
1825 +#endif |
|
1826 + |
|
1827 __BEGIN_DECLS |
|
1828 char *vis __P((char *, int, int, int)); |
|
1829 char *svis __P((char *, int, int, int, const char *)); |
|
1830 Index: main/stdtime/localtime.c |
|
1831 diff -Nau main/stdtime/localtime.c.orig main/stdtime/localtime.c |
|
1832 --- main/stdtime/localtime.c.orig 2008-09-27 17:00:48.000000000 +0200 |
|
1833 +++ main/stdtime/localtime.c 2009-04-24 00:30:33.000000000 +0200 |
|
1834 @@ -1134,9 +1134,9 @@ |
|
1835 */ |
|
1836 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); |
|
1837 tmp->tm_isdst = ttisp->tt_isdst; |
|
1838 -#ifndef SOLARIS /* Solaris doesn't have this element */ |
|
1839 +#ifdef TM_GMTOFF |
|
1840 tmp->tm_gmtoff = ttisp->tt_gmtoff; |
|
1841 -#endif |
|
1842 +#endif /* defined TM_GMTOFF */ |
|
1843 #ifdef TM_ZONE |
|
1844 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; |
|
1845 #endif /* defined TM_ZONE */ |
|
1846 Index: Makefile.moddir_rules |
|
1847 diff -Nau Makefile.moddir_rules.orig Makefile.moddir_rules |
|
1848 --- Makefile.moddir_rules.orig 2008-11-26 19:36:24.000000000 +0100 |
|
1849 +++ Makefile.moddir_rules 2009-04-24 00:30:33.000000000 +0200 |
|
1850 @@ -69,7 +69,9 @@ |
|
1851 rm -f modules.link |
|
1852 |
|
1853 install:: all |
|
1854 +ifneq ($(LOADABLE_MODS),) |
|
1855 for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done |
|
1856 +endif |
|
1857 |
|
1858 uninstall:: |
|
1859 |
|
1860 Index: res/res_features.c |
|
1861 diff -Nau res/res_features.c.orig res/res_features.c |
|
1862 --- res/res_features.c.orig 2009-03-03 19:27:09.000000000 +0100 |
|
1863 +++ res/res_features.c 2009-04-24 00:30:33.000000000 +0200 |
|
1864 @@ -732,6 +732,10 @@ |
|
1865 snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename); |
|
1866 } |
|
1867 |
|
1868 + for( x = 0; x < strlen(touch_filename); x++) { |
|
1869 + if (touch_filename[x] == '/') |
|
1870 + touch_filename[x] = '-'; |
|
1871 + } |
|
1872 for( x = 0; x < strlen(args); x++) { |
|
1873 if (args[x] == '/') |
|
1874 args[x] = '-'; |
|
1875 @@ -2774,6 +2778,293 @@ |
|
1876 } |
|
1877 } |
|
1878 |
|
1879 +static char mandescr_bridge[] = |
|
1880 +"Description: Bridge together two channels already in the PBX\n" |
|
1881 +"Variables: ( Headers marked with * are required )\n" |
|
1882 +" *Channel1: Channel to Bridge to Channel2\n" |
|
1883 +" *Channel2: Channel to Bridge to Channel1\n" |
|
1884 +" Tone: (Yes|No) Play courtesy tone to Channel 2\n" |
|
1885 +"\n"; |
|
1886 + |
|
1887 +/*! |
|
1888 + * \brief Actual bridge |
|
1889 + * \param chan |
|
1890 + * \param tmpchan |
|
1891 + * |
|
1892 + * Stop hold music, lock both channels, masq channels, |
|
1893 + * after bridge return channel to next priority. |
|
1894 +*/ |
|
1895 +static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan) |
|
1896 +{ |
|
1897 + ast_moh_stop(chan); |
|
1898 + ast_channel_lock(chan); |
|
1899 + ast_setstate(tmpchan, chan->_state); |
|
1900 + tmpchan->readformat = chan->readformat; |
|
1901 + tmpchan->writeformat = chan->writeformat; |
|
1902 + ast_channel_masquerade(tmpchan, chan); |
|
1903 + ast_channel_lock(tmpchan); |
|
1904 + ast_do_masquerade(tmpchan); |
|
1905 + /* when returning from bridge, the channel will continue at the next priority */ |
|
1906 + ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1); |
|
1907 + ast_channel_unlock(tmpchan); |
|
1908 + ast_channel_unlock(chan); |
|
1909 +} |
|
1910 + |
|
1911 +/*! |
|
1912 + * \brief Bridge channels together |
|
1913 + * \param s |
|
1914 + * \param m |
|
1915 + * |
|
1916 + * Make sure valid channels were specified, |
|
1917 + * send errors if any of the channels could not be found/locked, answer channels if needed, |
|
1918 + * create the placeholder channels and grab the other channels |
|
1919 + * make the channels compatible, send error if we fail doing so |
|
1920 + * setup the bridge thread object and start the bridge. |
|
1921 + * |
|
1922 + * \retval 0 on success or on incorrect use. |
|
1923 + * \retval 1 on failure to bridge channels. |
|
1924 +*/ |
|
1925 +static int action_bridge(struct mansession *s, const struct message *m) |
|
1926 +{ |
|
1927 + const char *channela = astman_get_header(m, "Channel1"); |
|
1928 + const char *channelb = astman_get_header(m, "Channel2"); |
|
1929 + const char *playtone = astman_get_header(m, "Tone"); |
|
1930 + struct ast_channel *chana = NULL, *chanb = NULL; |
|
1931 + struct ast_channel *tmpchana = NULL, *tmpchanb = NULL; |
|
1932 + struct ast_bridge_thread_obj *tobj = NULL; |
|
1933 + |
|
1934 + /* make sure valid channels were specified */ |
|
1935 + if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) { |
|
1936 + chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela)); |
|
1937 + chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb)); |
|
1938 + if (chana) |
|
1939 + ast_channel_unlock(chana); |
|
1940 + if (chanb) |
|
1941 + ast_channel_unlock(chanb); |
|
1942 + |
|
1943 + /* send errors if any of the channels could not be found/locked */ |
|
1944 + if (!chana) { |
|
1945 + char buf[256]; |
|
1946 + snprintf(buf, sizeof(buf), "Channel1 does not exist: %s", channela); |
|
1947 + astman_send_error(s, m, buf); |
|
1948 + return 0; |
|
1949 + } |
|
1950 + if (!chanb) { |
|
1951 + char buf[256]; |
|
1952 + snprintf(buf, sizeof(buf), "Channel2 does not exist: %s", channelb); |
|
1953 + astman_send_error(s, m, buf); |
|
1954 + return 0; |
|
1955 + } |
|
1956 + } else { |
|
1957 + astman_send_error(s, m, "Missing channel parameter in request"); |
|
1958 + return 0; |
|
1959 + } |
|
1960 + |
|
1961 + /* Answer the channels if needed */ |
|
1962 + if (chana->_state != AST_STATE_UP) |
|
1963 + ast_answer(chana); |
|
1964 + if (chanb->_state != AST_STATE_UP) |
|
1965 + ast_answer(chanb); |
|
1966 + |
|
1967 + /* create the placeholder channels and grab the other channels */ |
|
1968 + if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, |
|
1969 + NULL, NULL, 0, "Bridge/%s", chana->name))) { |
|
1970 + astman_send_error(s, m, "Unable to create temporary channel!"); |
|
1971 + return 1; |
|
1972 + } |
|
1973 + |
|
1974 + if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, |
|
1975 + NULL, NULL, 0, "Bridge/%s", chanb->name))) { |
|
1976 + astman_send_error(s, m, "Unable to create temporary channels!"); |
|
1977 + ast_channel_free(tmpchana); |
|
1978 + return 1; |
|
1979 + } |
|
1980 + |
|
1981 + do_bridge_masquerade(chana, tmpchana); |
|
1982 + do_bridge_masquerade(chanb, tmpchanb); |
|
1983 + |
|
1984 + /* make the channels compatible, send error if we fail doing so */ |
|
1985 + if (ast_channel_make_compatible(tmpchana, tmpchanb)) { |
|
1986 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name); |
|
1987 + astman_send_error(s, m, "Could not make channels compatible for manager bridge"); |
|
1988 + ast_hangup(tmpchana); |
|
1989 + ast_hangup(tmpchanb); |
|
1990 + return 1; |
|
1991 + } |
|
1992 + |
|
1993 + /* setup the bridge thread object and start the bridge */ |
|
1994 + if (!(tobj = ast_calloc(1, sizeof(*tobj)))) { |
|
1995 + ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno)); |
|
1996 + astman_send_error(s, m, "Unable to spawn a new bridge thread"); |
|
1997 + ast_hangup(tmpchana); |
|
1998 + ast_hangup(tmpchanb); |
|
1999 + return 1; |
|
2000 + } |
|
2001 + |
|
2002 + tobj->chan = tmpchana; |
|
2003 + tobj->peer = tmpchanb; |
|
2004 + |
|
2005 + if (ast_true(playtone)) { |
|
2006 + if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) { |
|
2007 + if (ast_waitstream(tmpchanb, "") < 0) |
|
2008 + ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name); |
|
2009 + } |
|
2010 + } |
|
2011 + |
|
2012 + ast_bridge_call_thread_launch(tobj); |
|
2013 + |
|
2014 + astman_send_ack(s, m, "Launched bridge thread with success"); |
|
2015 + |
|
2016 + return 0; |
|
2017 +} |
|
2018 + |
|
2019 +static char *app_bridge = "Bridge"; |
|
2020 +static char *bridge_synopsis = "Bridge two channels"; |
|
2021 +static char *bridge_descrip = |
|
2022 +"Usage: Bridge(channel[,options])\n" |
|
2023 +" Allows the ability to bridge two channels via the dialplan.\n" |
|
2024 +"The current channel is bridged to the specified 'channel'.\n" |
|
2025 +" Options:\n" |
|
2026 +" p - Play a courtesy tone to 'channel'.\n" |
|
2027 +"This application sets the following channel variable upon completion:\n" |
|
2028 +" BRIDGERESULT The result of the bridge attempt as a text string, one of\n" |
|
2029 +" SUCCESS | FAILURE | LOOP | NONEXISTENT | INCOMPATIBLE\n"; |
|
2030 + |
|
2031 +enum { |
|
2032 + BRIDGE_OPT_PLAYTONE = (1 << 0), |
|
2033 +}; |
|
2034 + |
|
2035 +AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS |
|
2036 + AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE) |
|
2037 +END_OPTIONS ); |
|
2038 + |
|
2039 +/*! |
|
2040 + * \brief Bridge channels |
|
2041 + * \param chan |
|
2042 + * \param data channel to bridge with. |
|
2043 + * |
|
2044 + * Split data, check we aren't bridging with ourself, check valid channel, |
|
2045 + * answer call if not already, check compatible channels, setup bridge config |
|
2046 + * now bridge call, if transfered party hangs up return to PBX extension. |
|
2047 +*/ |
|
2048 +static int bridge_exec(struct ast_channel *chan, void *data) |
|
2049 +{ |
|
2050 + struct ast_channel *current_dest_chan, *final_dest_chan; |
|
2051 + char *tmp_data = NULL; |
|
2052 + struct ast_flags opts = { 0, }; |
|
2053 + struct ast_bridge_config bconfig = { { 0, }, }; |
|
2054 + |
|
2055 + AST_DECLARE_APP_ARGS(args, |
|
2056 + AST_APP_ARG(dest_chan); |
|
2057 + AST_APP_ARG(options); |
|
2058 + ); |
|
2059 + |
|
2060 + if (ast_strlen_zero(data)) { |
|
2061 + ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n"); |
|
2062 + return -1; |
|
2063 + } |
|
2064 + |
|
2065 + tmp_data = ast_strdupa(data); |
|
2066 + AST_STANDARD_APP_ARGS(args, tmp_data); |
|
2067 + if (!ast_strlen_zero(args.options)) |
|
2068 + ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options); |
|
2069 + |
|
2070 + /* avoid bridge with ourselves */ |
|
2071 + if (!strncmp(chan->name, args.dest_chan, |
|
2072 + strlen(chan->name) < strlen(args.dest_chan) ? |
|
2073 + strlen(chan->name) : strlen(args.dest_chan))) { |
|
2074 + ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name); |
|
2075 + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
|
2076 + "Response: Failed\r\n" |
|
2077 + "Reason: Unable to bridge channel to itself\r\n" |
|
2078 + "Channel1: %s\r\n" |
|
2079 + "Channel2: %s\r\n", |
|
2080 + chan->name, args.dest_chan); |
|
2081 + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP"); |
|
2082 + return 0; |
|
2083 + } |
|
2084 + |
|
2085 + /* make sure we have a valid end point */ |
|
2086 + if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan, |
|
2087 + strlen(args.dest_chan)))) { |
|
2088 + ast_log(LOG_WARNING, "Bridge failed because channel %s does not exist or we " |
|
2089 + "cannot get its lock\n", args.dest_chan); |
|
2090 + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
|
2091 + "Response: Failed\r\n" |
|
2092 + "Reason: Cannot grab end point\r\n" |
|
2093 + "Channel1: %s\r\n" |
|
2094 + "Channel2: %s\r\n", chan->name, args.dest_chan); |
|
2095 + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT"); |
|
2096 + return 0; |
|
2097 + } |
|
2098 + ast_channel_unlock(current_dest_chan); |
|
2099 + |
|
2100 + /* answer the channel if needed */ |
|
2101 + if (current_dest_chan->_state != AST_STATE_UP) |
|
2102 + ast_answer(current_dest_chan); |
|
2103 + |
|
2104 + /* try to allocate a place holder where current_dest_chan will be placed */ |
|
2105 + if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, |
|
2106 + NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) { |
|
2107 + ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan); |
|
2108 + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
|
2109 + "Response: Failed\r\n" |
|
2110 + "Reason: cannot create placeholder\r\n" |
|
2111 + "Channel1: %s\r\n" |
|
2112 + "Channel2: %s\r\n", chan->name, args.dest_chan); |
|
2113 + } |
|
2114 + do_bridge_masquerade(current_dest_chan, final_dest_chan); |
|
2115 + |
|
2116 + /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */ |
|
2117 + /* try to make compatible, send error if we fail */ |
|
2118 + if (ast_channel_make_compatible(chan, final_dest_chan) < 0) { |
|
2119 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name); |
|
2120 + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
|
2121 + "Response: Failed\r\n" |
|
2122 + "Reason: Could not make channels compatible for bridge\r\n" |
|
2123 + "Channel1: %s\r\n" |
|
2124 + "Channel2: %s\r\n", chan->name, final_dest_chan->name); |
|
2125 + ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */ |
|
2126 + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE"); |
|
2127 + return 0; |
|
2128 + } |
|
2129 + |
|
2130 + /* Report that the bridge will be successfull */ |
|
2131 + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
|
2132 + "Response: Success\r\n" |
|
2133 + "Channel1: %s\r\n" |
|
2134 + "Channel2: %s\r\n", chan->name, final_dest_chan->name); |
|
2135 + |
|
2136 + /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */ |
|
2137 + if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) { |
|
2138 + if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) { |
|
2139 + if (ast_waitstream(final_dest_chan, "") < 0) |
|
2140 + ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name); |
|
2141 + } |
|
2142 + } |
|
2143 + |
|
2144 + /* do the bridge */ |
|
2145 + ast_bridge_call(chan, final_dest_chan, &bconfig); |
|
2146 + |
|
2147 + /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */ |
|
2148 + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS"); |
|
2149 + if (!ast_check_hangup(final_dest_chan)) { |
|
2150 + ast_log(LOG_EVENT, "starting new PBX in %s,%s,%d for chan %s\n", |
|
2151 + final_dest_chan->context, final_dest_chan->exten, |
|
2152 + final_dest_chan->priority, final_dest_chan->name); |
|
2153 + |
|
2154 + if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) { |
|
2155 + ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name); |
|
2156 + ast_hangup(final_dest_chan); |
|
2157 + } else |
|
2158 + ast_log(LOG_EVENT, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name); |
|
2159 + } else { |
|
2160 + ast_log(LOG_EVENT, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name); |
|
2161 + ast_hangup(final_dest_chan); |
|
2162 + } |
|
2163 + |
|
2164 + return 0; |
|
2165 +} |
|
2166 |
|
2167 static int load_config(void) |
|
2168 { |
|
2169 @@ -3034,6 +3325,8 @@ |
|
2170 { |
|
2171 int res; |
|
2172 |
|
2173 + ast_register_application(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip); |
|
2174 + |
|
2175 memset(parking_ext, 0, sizeof(parking_ext)); |
|
2176 memset(parking_con, 0, sizeof(parking_con)); |
|
2177 |
|
2178 @@ -3048,6 +3341,7 @@ |
|
2179 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" ); |
|
2180 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park, |
|
2181 "Park a channel", mandescr_park); |
|
2182 + ast_manager_register2("Bridge", EVENT_FLAG_CALL, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge); |
|
2183 } |
|
2184 |
|
2185 res |= ast_devstate_prov_add("Park", metermaidstate); |
|
2186 Index: apps/app_voicemail.c |
|
2187 diff -Nau apps/app_voicemail.c.orig apps/app_voicemail.c |
|
2188 --- apps/app_voicemail.c.orig 2009-04-25 02:38:20.343758775 +0200 |
|
2189 +++ apps/app_voicemail.c 2009-04-25 19:56:25.287569363 +0200 |
|
2190 @@ -115,6 +115,7 @@ |
|
2191 static char imapport[8]; |
|
2192 static char imapflags[128]; |
|
2193 static char imapfolder[64]; |
|
2194 +static int imapsubfold = 0; |
|
2195 static char authuser[32]; |
|
2196 static char authpassword[42]; |
|
2197 |
|
2198 @@ -4313,6 +4314,7 @@ |
|
2199 /* we must use mbox(x) folder names, and copy the message there */ |
|
2200 /* simple. huh? */ |
|
2201 char sequence[10]; |
|
2202 + char folder[256]; |
|
2203 /* get the real IMAP message number for this message */ |
|
2204 snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]); |
|
2205 if (option_debug > 2) |
|
2206 @@ -4323,11 +4325,21 @@ |
|
2207 } else if (box == 0) { |
|
2208 mail_clearflag(vms->mailstream, sequence, "\\Seen"); |
|
2209 } |
|
2210 - if (!strcasecmp(mbox(0), vms->curbox) && (box == 0 || box == 1)) { |
|
2211 + if ((!strcasecmp(mbox(0), vms->curbox) || \ |
|
2212 + !strcasecmp(mbox(1), vms->curbox)) && \ |
|
2213 + (box == 0 || box == 1)) { /* Don't copy data, just change Seen flag */ |
|
2214 ast_mutex_unlock(&vms->lock); |
|
2215 return 0; |
|
2216 - } else { |
|
2217 - int res = !mail_copy(vms->mailstream,sequence,(char *) mbox(box)); |
|
2218 + } else if (box > 1) { /* Do copy data using INBOX or subfolder */ |
|
2219 + if (imapsubfold == 1) |
|
2220 + snprintf(folder, sizeof(folder), "%s%c%s", imapfolder, delimiter, mbox(box)); |
|
2221 + else |
|
2222 + strncpy(folder, mbox(box), sizeof(folder)); |
|
2223 + int res = !mail_copy(vms->mailstream,sequence,folder); |
|
2224 + ast_mutex_unlock(&vms->lock); |
|
2225 + return res; |
|
2226 + } else { /* Copy data to INBOX delegating new/old status to Seen flag */ |
|
2227 + int res = !mail_copy(vms->mailstream,sequence,imapfolder); |
|
2228 ast_mutex_unlock(&vms->lock); |
|
2229 return res; |
|
2230 } |
|
2231 @@ -7686,6 +7698,10 @@ |
|
2232 #ifndef IMAP_STORAGE |
|
2233 } else if (!cmd) { |
|
2234 vms.deleted[vms.curmsg] = 1; |
|
2235 +#else |
|
2236 + } else if (!cmd && (folder_int(vms.curbox) > 1 || box > 1)) { |
|
2237 + vms.deleted[vms.curmsg] = 1; /* Enforce deletion after */ |
|
2238 + deleted = 1; /* successful copy op */ |
|
2239 #endif |
|
2240 } else { |
|
2241 vms.deleted[vms.curmsg] = 0; |
|
2242 @@ -8198,6 +8214,7 @@ |
|
2243 const char *imap_port; |
|
2244 const char *imap_flags; |
|
2245 const char *imap_folder; |
|
2246 + const char *imap_use_subfold; |
|
2247 const char *auth_user; |
|
2248 const char *auth_password; |
|
2249 const char *expunge_on_hangup; |
|
2250 @@ -8342,6 +8359,15 @@ |
|
2251 } else { |
|
2252 ast_copy_string(imapfolder,"INBOX", sizeof(imapfolder)); |
|
2253 } |
|
2254 + /* IMAP saved (sub)folder location policy */ |
|
2255 + if ((imap_use_subfold = ast_variable_retrieve(cfg, "general", "imapsubfold"))) { |
|
2256 + if (ast_false(imap_use_subfold)) |
|
2257 + imapsubfold = 0; |
|
2258 + else |
|
2259 + imapsubfold = 1; |
|
2260 + } else { |
|
2261 + imapsubfold = 0; |
|
2262 + } |
|
2263 |
|
2264 /* There is some very unorthodox casting done here. This is due |
|
2265 * to the way c-client handles the argument passed in. It expects a |