1 #include <pthread.h>
2 #include <fcntl.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <netinet/in.h>
6 #include <string.h>
7 #include <stdio.h>
8 #include <time.h>
9
10 /* single file implements both G.729 and G.723.1, both IPP and Bcg729 based codecs,
11 Asterisk 1.4 to 14 */
12 /* quite a lot of preprocessor abuse, but still better than maintaining multiple
13 similar files */
14
15 #if G72X_ASTERISK
16 #if G72X_ASTERISK >= 140
17 #define AST_MODULE_SELF_SYM __internal_g72x_self
18 #endif
19
20 #ifdef ASTERISK_ASTERISK_H
21 /* Ubuntu */
22 #include <asterisk/asterisk.h>
23 #else
24 #include <asterisk.h>
25 #endif
26 #include <asterisk/lock.h>
27 #include <asterisk/translate.h>
28 #include <asterisk/module.h>
29 #if G72X_ASTERISK >= 110 && G72X_ASTERISK < 150
30 ASTERISK_REGISTER_FILE()
31 #endif
32 #include <asterisk/logger.h>
33 #include <asterisk/channel.h>
34 #include <asterisk/utils.h>
35 #include <asterisk/options.h>
36 #include <asterisk/cli.h>
37
38 #if G72X_ASTERISK < 14
39 #error not supported
40 #endif
41
42 #elif G72X_CALLWEAVER
43 #error not supported yet
44
45 #include "confdefs.h"
46 #include <callweaver/lock.h>
47 #include <callweaver/translate.h>
48 #include <callweaver/module.h>
49 #include <callweaver/logger.h>
50 #include <callweaver/channel.h>
51 #include <callweaver/utils.h>
52 #include <callweaver/options.h>
53 #include <callweaver/cli.h>
54
55 #define ast_frame opbx_frame
56 #define ast_log opbx_log
57 #define ast_translator opbx_translator
58 #define ast_mutex_lock opbx_mutex_lock
59 #define ast_verbose opbx_verbose
60 #define ast_trans_frameout opbx_trans_frameout
61 #define ast_register_translator opbx_register_translator
62 #define ast_unregister_translator opbx_unregister_translator
63 #define AST_FRAME_VOICE OPBX_FRAME_VOICE
64 #define AST_FORMAT_SLINEAR OPBX_FORMAT_SLINEAR
65 #define AST_FORMAT_G729A OPBX_FORMAT_G729A
66 #define AST_FORMAT_G723_1 OPBX_FORMAT_G723_1
67 #define AST_FRIENDLY_OFFSET OPBX_FRIENDLY_OFFSET
68
69 #else
70 #error either G72X_ASTERISK or G72X_CALLWEAVER must be defined
71 #endif
72
73 #if !G72X_BCG729
74 #include <ippcore.h>
75 #include <ipps.h>
76 #endif
77
78 #if G72X_9
79 #define G72X_CODEC "g729"
80
81 #if G72X_BCG729
82 #include "bcg729/decoder.h"
83 #include "bcg729/encoder.h"
84
85 #else
86 #if !G72X_9_NOFP
87 #include "g729fpapi.h"
88
89 #define apiG729Encoder_InitBuff apiG729FPEncoder_InitBuff
90 #define apiG729Decoder_InitBuff apiG729FPDecoder_InitBuff
91 #define apiG729Encoder_Init apiG729FPEncoder_Init
92 #define apiG729Decoder_Init apiG729FPDecoder_Init
93 #define apiG729Encode apiG729FPEncode
94 #define apiG729Decode apiG729FPDecode
95 #define apiG729Encoder_Alloc apiG729FPEncoder_Alloc
96 #define apiG729Decoder_Alloc apiG729FPDecoder_Alloc
97 #define apiG729Codec_ScratchMemoryAlloc apiG729FPCodec_ScratchMemoryAlloc
98
99 #else
100 #include "g729api.h"
101 #endif
102 #endif
103
104 #include "slin_g72x_ex.h"
105 #include "g729_slin_ex.h"
106
107 #define SLIN_FRAME_LEN 160
108 #define G729_FRAME_LEN 10
109 #define G729_SAMPLES 80 /* 10ms at 8000 hz, 160 bytes signed linear */
110 #define BUFFER_SAMPLES 8000
111
112 #define G72X_FRAME_LEN G729_FRAME_LEN
113 #define G72X_SAMPLES G729_SAMPLES
114 #define G72X_AST_FORMAT AST_FORMAT_G729A
115 #define G72X_AST_FORMAT13 ast_format_g729
116
117 #elif G72X_3
118 #define G72X_CODEC "g723"
119
120 #if G72X_BCG729
121 #error no portable code for G.723.1, ITU-T ref impl is too slow
122 #else
123 #include "g723api.h"
124 #endif
125
126 #include "slin_g72x_ex.h"
127 #include "g723_slin_ex.h"
128
129 #define SLIN_FRAME_LEN 480
130 #define G723_FRAME_LEN 24 /* maximum frame length */
131 #define G723_SAMPLES 240 /* 30ms at 8000 hz, 480 bytes signed linear */
132 #define BUFFER_SAMPLES 8000
133
134 #define G72X_FRAME_LEN G723_FRAME_LEN
135 #define G72X_SAMPLES G723_SAMPLES
136 #define G72X_AST_FORMAT AST_FORMAT_G723_1
137 #define G72X_AST_FORMAT13 ast_format_g723
138
139 #define G723_RATE_63 0 /* G723_Rate63 in owng723.h */
140 #define G723_RATE_53 1 /* G723_Rate53 */
141 #define G723_DEFAULT_SEND_RATE G723_RATE_63
142
143 static int g723_sendrate = G723_DEFAULT_SEND_RATE;
144
145 #else
146 #error either G72X_9 or G72X_3 must be defined
147 #endif
148
149 #if G72X_ASTERISK > 16
150 #define FRAME_SUBCLASS subclass.codec
151 #else
152 #define FRAME_SUBCLASS subclass
153 #endif
154
155 #if G72X_ASTERISK >= 16
156 #define FRAME_DATA data.ptr
157 #define OUTBUF_SLIN outbuf.i16
158 #define OUTBUF_G72X outbuf.uc
159 #else
160 #define FRAME_DATA data
161 #define OUTBUF_SLIN outbuf
162 #define OUTBUF_G72X outbuf
163 #endif
164
165 #define AST_MODULE "codec_" G72X_CODEC
166 #if !G72X_BCG729
167 #define G72X_DESC G72X_CODEC " Coder/Decoder, based on Intel IPP"
168 #else
169 #define G72X_DESC G72X_CODEC " Coder/Decoder, based on Bcg729"
170 #endif
171
172 struct g72x_coder_pvt {
173 void *coder;
174 #if !G72X_BCG729
175 void *scratch_mem;
176 #endif
177 int16_t buf[BUFFER_SAMPLES]; /* 1 second */
178 };
179
180 #if !G72X_BCG729
181 static int encoder_size;
182 static int decoder_size;
183 static int coder_size_scratch;
184 #endif
185
186 /* debug array to collect information about incoming frame sizes */
187 /* the code is not aiming at correctness so there are no locking and no atomic operations */
188 static int *frame_sizes = NULL;
189 #define DEBUG_MAX_FRAME_SIZE 2000
190 #define DEBUG_FRAME_SIZE_INC \
191 do { \
192 if (frame_sizes != NULL) { \
193 if (f->datalen >= DEBUG_MAX_FRAME_SIZE) \
194 ++frame_sizes[DEBUG_MAX_FRAME_SIZE]; \
195 else \
196 ++frame_sizes[f->datalen]; \
197 } \
198 } while (0)
199
lintog72x_new(struct ast_trans_pvt * pvt)200 static int lintog72x_new(struct ast_trans_pvt *pvt)
201 {
202 struct g72x_coder_pvt *state = pvt->pvt;
203
204 #if !G72X_BCG729
205 #ifndef IPPCORE_NO_SSE
206 ippSetFlushToZero(1, NULL); /* is FZM flag per-thread or not? does it matter at all? */
207 #endif
208 state->coder = ippsMalloc_8u(encoder_size);
209 state->scratch_mem = ippsMalloc_8u(coder_size_scratch);
210 #if G72X_9
211 apiG729Encoder_InitBuff(state->coder, state->scratch_mem);
212 apiG729Encoder_Init(state->coder, G729A_CODEC, G729Encode_VAD_Disabled);
213 #else
214 apiG723Encoder_InitBuff(state->coder, state->scratch_mem);
215 apiG723Encoder_Init(state->coder, G723Encode_DefaultMode);
216 #endif
217 #else
218 state->coder = initBcg729EncoderChannel(0);
219 #endif
220 return 0;
221 }
222
g72xtolin_new(struct ast_trans_pvt * pvt)223 static int g72xtolin_new(struct ast_trans_pvt *pvt)
224 {
225 struct g72x_coder_pvt *state = pvt->pvt;
226
227 #if !G72X_BCG729
228 #ifndef IPPCORE_NO_SSE
229 ippSetFlushToZero(1, NULL);
230 #endif
231 state->coder = ippsMalloc_8u(decoder_size);
232 state->scratch_mem = ippsMalloc_8u(coder_size_scratch);
233 #if G72X_9
234 apiG729Decoder_InitBuff(state->coder, state->scratch_mem);
235 apiG729Decoder_Init(state->coder, G729A_CODEC);
236 #else
237 apiG723Decoder_InitBuff(state->coder, state->scratch_mem);
238 apiG723Decoder_Init(state->coder, G723Decode_DefaultMode);
239 #endif
240 #else
241 state->coder = initBcg729DecoderChannel();
242 #endif
243 return 0;
244 }
245
lintog72x_sample(void)246 static struct ast_frame *lintog72x_sample(void)
247 {
248 static struct ast_frame f;
249 f.frametype = AST_FRAME_VOICE;
250 #if G72X_ASTERISK < 100
251 f.FRAME_SUBCLASS = AST_FORMAT_SLINEAR;
252 #elif G72X_ASTERISK == 100
253 ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0);
254 #else /* 13.0+ */
255 f.subclass.format = ast_format_slin;
256 #endif
257 f.datalen = sizeof(slin_g72x_ex);
258 f.samples = sizeof(slin_g72x_ex)/2;
259 f.mallocd = 0;
260 f.offset = 0;
261 f.src = __PRETTY_FUNCTION__;
262 f.FRAME_DATA = slin_g72x_ex;
263 return &f;
264 }
265
g72xtolin_sample(void)266 static struct ast_frame *g72xtolin_sample(void)
267 {
268 static struct ast_frame f;
269 f.frametype = AST_FRAME_VOICE;
270 #if G72X_ASTERISK < 100
271 f.FRAME_SUBCLASS = G72X_AST_FORMAT;
272 #elif G72X_ASTERISK == 100
273 ast_format_set(&f.subclass.format, G72X_AST_FORMAT, 0);
274 #else /* 13.0+ */
275 f.subclass.format = G72X_AST_FORMAT13;
276 #endif
277 f.datalen = sizeof(g72x_slin_ex);
278 f.samples = G72X_SAMPLES;
279 f.mallocd = 0;
280 f.offset = 0;
281 f.src = __PRETTY_FUNCTION__;
282 f.FRAME_DATA = g72x_slin_ex;
283 return &f;
284 }
285
286 static unsigned char lost_frame[G72X_FRAME_LEN] = { 0 };
287
288 #if G72X_9
289 #if !G72X_BCG729
g729_frame_type(int datalen)290 static int g729_frame_type(int datalen)
291 {
292 switch (datalen) {
293 case 0: return -1; /* erased */
294 /* case 0: return 0; maybe it should be 0 - untransmitted silence? */
295 case 2: return 1; /* SID */
296 case 8: return 2; /* 729d */
297 case 10: return 3; /* 729, 729a */
298 case 15: return 4; /* 729e */
299 }
300 return 0;
301 }
302 #endif
303
g72xtolin_framein(struct ast_trans_pvt * pvt,struct ast_frame * f)304 static int g72xtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
305 {
306 struct g72x_coder_pvt *state = pvt->pvt;
307 int16_t *dst = (int16_t *)pvt->OUTBUF_SLIN;
308 int framesize;
309 int x;
310
311 DEBUG_FRAME_SIZE_INC;
312
313 if (f->datalen == 0) { /* Native PLC interpolation */
314 if (option_verbose > 2)
315 ast_verbose(VERBOSE_PREFIX_3 "G.729 PLC\n");
316 if (pvt->samples + G729_SAMPLES > BUFFER_SAMPLES) {
317 ast_log(LOG_WARNING, "Out of buffer space\n");
318 return -1;
319 }
320 #if !G72X_BCG729
321 apiG729Decode(state->coder, (unsigned char *)lost_frame, g729_frame_type(0), dst + pvt->samples);
322 #else
323 bcg729Decoder(state->coder, (unsigned char *)lost_frame, 0, 1, 0, 0, dst + pvt->samples);
324 #endif
325 pvt->samples += G729_SAMPLES;
326 pvt->datalen += 2 * G729_SAMPLES; /* 2 bytes/sample */
327 return 0;
328 }
329
330 for(x = 0; x < f->datalen; x += framesize) {
331 if (pvt->samples + G729_SAMPLES > BUFFER_SAMPLES) { /* XXX how the hell this BUFFER_SAMPLES check is supposed to catch memory overruns? use buf_size */
332 ast_log(LOG_WARNING, "Out of buffer space\n");
333 return -1;
334 }
335 if(f->datalen - x < 8)
336 framesize = 2; /* SID */
337 else
338 framesize = 10; /* regular 729a frame */
339 #if !G72X_BCG729
340 apiG729Decode(state->coder, (unsigned char *)f->FRAME_DATA + x, g729_frame_type(framesize), dst + pvt->samples);
341 #elif G72X_9
342 bcg729Decoder(state->coder, (unsigned char *)f->FRAME_DATA + x, 0, 0, framesize == 2 ? 1 : 0, 0, dst + pvt->samples);
343 #endif
344 pvt->samples += G729_SAMPLES;
345 pvt->datalen += 2*G729_SAMPLES;
346 }
347 return 0;
348 }
349
350 #else /* G72X_3 */
g723_frame_length(int frametype)351 static int g723_frame_length(int frametype)
352 {
353 switch(frametype) {
354 case 0: return 24; /* 6.3kbps */
355 case 1: return 20; /* 5.3kbps */
356 case 2: return 4; /* SID */
357 }
358 return 1; /* XXX untransmitted */
359 }
360
g72xtolin_framein(struct ast_trans_pvt * pvt,struct ast_frame * f)361 static int g72xtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
362 {
363 struct g72x_coder_pvt *state = pvt->pvt;
364 int16_t *dst = (int16_t *)pvt->OUTBUF_SLIN;
365 int badframe;
366 int frametype;
367 int framesize;
368 int x;
369
370 DEBUG_FRAME_SIZE_INC;
371
372 if (f->datalen == 0) { /* Native PLC interpolation */
373 if (option_verbose > 2)
374 ast_verbose(VERBOSE_PREFIX_3 "G.723.1 PLC\n");
375 if (pvt->samples + G723_SAMPLES > BUFFER_SAMPLES) {
376 ast_log(LOG_WARNING, "Out of buffer space\n");
377 return -1;
378 }
379 badframe = 1; /* the frame is lost */
380 apiG723Decode(state->coder, (void *)lost_frame, badframe, dst + pvt->samples);
381 pvt->samples += G723_SAMPLES;
382 pvt->datalen += 2 * G723_SAMPLES; /* 2 bytes/sample */
383 return 0;
384 }
385
386 badframe = 0;
387 for(x = 0; x < f->datalen; x += framesize) {
388 if (pvt->samples + G723_SAMPLES > BUFFER_SAMPLES) {
389 ast_log(LOG_WARNING, "Out of buffer space\n");
390 return -1;
391 }
392 frametype = *((unsigned char *)f->FRAME_DATA + x) & (short)0x0003;
393 framesize = g723_frame_length(frametype);
394 apiG723Decode(state->coder, (void *)f->FRAME_DATA + x, badframe, dst + pvt->samples);
395 pvt->samples += G723_SAMPLES;
396 pvt->datalen += 2*G723_SAMPLES;
397 }
398 return 0;
399 }
400
401 #endif
402
lintog72x_framein(struct ast_trans_pvt * pvt,struct ast_frame * f)403 static int lintog72x_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
404 {
405 struct g72x_coder_pvt *state = pvt->pvt;
406
407 memcpy(state->buf + pvt->samples, f->FRAME_DATA, f->datalen);
408 pvt->samples += f->samples;
409 return 0;
410 }
411
412 #if G72X_9 && !G72X_BCG729
413 /* length != 10 can't happen but let it be here for reference */
g729_frame_length(int frametype)414 static int g729_frame_length(int frametype)
415 {
416 switch (frametype) {
417 case 0: return 0; /* not transmited */
418 case 1: return 2; /* SID */
419 case 2: return 8; /* 729d */
420 case 3: return G729_FRAME_LEN; /* 729, 729a */
421 case 4: return 15; /* 729e */
422 }
423 return 0;
424 }
425 #endif
426
lintog72x_frameout(struct ast_trans_pvt * pvt)427 static struct ast_frame *lintog72x_frameout(struct ast_trans_pvt *pvt)
428 {
429 struct g72x_coder_pvt *state = pvt->pvt;
430 int datalen = 0;
431 int samples = 0;
432 #if G72X_9 && !G72X_BCG729
433 int frametype;
434 #endif
435
436 /* We can't work on anything less than a frame in size */
437 if (pvt->samples < G72X_SAMPLES)
438 return NULL;
439 while (pvt->samples >= G72X_SAMPLES) {
440 #if !G72X_BCG729
441 #if G72X_9
442 apiG729Encode(state->coder, state->buf + samples, (unsigned char *)(pvt->OUTBUF_G72X) + datalen, G729A_CODEC, &frametype);
443 datalen += g729_frame_length(frametype);
444 /* if (frametype == 1) break; if encoding with VAD enabled then terminate the frame */
445 #else
446 apiG723Encode(state->coder, state->buf + samples, g723_sendrate, (void *)(pvt->OUTBUF_G72X + datalen));
447 datalen += (g723_sendrate == G723_RATE_63) ? 24 : 20;
448 #endif
449 #else
450 uint8_t framesize;
451 bcg729Encoder(state->coder, state->buf + samples, (unsigned char *)(pvt->OUTBUF_G72X) + datalen, &framesize);
452 datalen += framesize; // VAD is disabled, it's G729_FRAME_LEN
453 #endif
454 samples += G72X_SAMPLES;
455 pvt->samples -= G72X_SAMPLES;
456 }
457
458 /* Move the data at the end of the buffer to the front */
459 if (pvt->samples)
460 memmove(state->buf, state->buf + samples, pvt->samples * 2);
461
462 return ast_trans_frameout(pvt, datalen, samples);
463 }
464
g72x_destroy(struct ast_trans_pvt * pvt)465 static void g72x_destroy(struct ast_trans_pvt *pvt)
466 {
467 int i;
468 struct g72x_coder_pvt *state = pvt->pvt;
469 #if !G72X_BCG729
470 ippsFree(state->coder);
471 ippsFree(state->scratch_mem);
472 #else
473 #if G72X_ASTERISK >= 160
474 ast_std_free(state->coder);
475 #else
476 free(state->coder);
477 #endif
478 #endif
479 /* output the sizes of frames passed to decoder */
480 if (option_verbose > 2 && frame_sizes != NULL) {
481 ast_verbose(VERBOSE_PREFIX_3 G72X_CODEC " frames\n");
482 ast_verbose(VERBOSE_PREFIX_3 "length: count\n");
483 for (i = 0; i <= DEBUG_MAX_FRAME_SIZE; ++i) {
484 if (frame_sizes[i] > 0)
485 ast_verbose(VERBOSE_PREFIX_3 "%6d: %d\n", i, frame_sizes[i]);
486 }
487 }
488 }
489
490 static struct ast_translator g72xtolin = {
491 .name = G72X_CODEC "tolin",
492 #if G72X_CALLWEAVER
493 .src_format = G72X_AST_FORMAT,
494 .dst_format = AST_FORMAT_SLINEAR,
495 #elif G72X_ASTERISK < 100
496 .srcfmt = G72X_AST_FORMAT,
497 .dstfmt = AST_FORMAT_SLINEAR,
498 #elif G72X_ASTERISK >= 130
499 .src_codec = { .name = G72X_CODEC, .type = AST_MEDIA_TYPE_AUDIO, .sample_rate = 8000 },
500 .dst_codec = { .name = "slin", .type = AST_MEDIA_TYPE_AUDIO, .sample_rate = 8000 },
501 #endif
502 .newpvt = g72xtolin_new,
503 .framein = g72xtolin_framein,
504 .destroy = g72x_destroy,
505 .sample = g72xtolin_sample,
506 #if G72X_CALLWEAVER
507 .src_rate = 8000,
508 .dst_rate = 8000
509 #elif G72X_ASTERISK >= 14
510 .desc_size = sizeof(struct g72x_coder_pvt) - BUFFER_SAMPLES*2, /* buffer is not needed for g723/9 -> slin */
511 .buf_size = SLIN_FRAME_LEN*100, /* 1 second */
512 .native_plc = 1
513 #endif
514 };
515
516 static struct ast_translator lintog72x = {
517 .name = "linto" G72X_CODEC,
518 #if G72X_CALLWEAVER
519 .src_format = AST_FORMAT_SLINEAR,
520 .dst_format = G72X_AST_FORMAT,
521 #elif G72X_ASTERISK < 100
522 .srcfmt = AST_FORMAT_SLINEAR,
523 .dstfmt = G72X_AST_FORMAT,
524 #elif G72X_ASTERISK >= 130
525 .src_codec = { .name = "slin", .type = AST_MEDIA_TYPE_AUDIO, .sample_rate = 8000 },
526 .dst_codec = { .name = G72X_CODEC, .type = AST_MEDIA_TYPE_AUDIO, .sample_rate = 8000 },
527 #endif
528 .newpvt = lintog72x_new,
529 .framein = lintog72x_framein,
530 .frameout = lintog72x_frameout,
531 .destroy = g72x_destroy,
532 .sample = lintog72x_sample,
533 #if G72X_CALLWEAVER
534 .src_rate = 8000,
535 .dst_rate = 8000
536 #elif G72X_ASTERISK >= 14
537 .desc_size = sizeof(struct g72x_coder_pvt), /* buffer up-to 1 second of speech */
538 #if G72X_9
539 .buf_size = G729_FRAME_LEN*100 /* 1 sec of g729 */
540 #else
541 .buf_size = G723_FRAME_LEN*33 /* almost 1 sec of g723 at 6.3kbps */
542 #endif
543 #endif
544 };
545
546 #if G72X_3
parse_config(void)547 static void parse_config(void)
548 {
549 #if G72X_ASTERISK >= 15
550 /* XXX struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; */
551 struct ast_flags config_flags = { 0 };
552 struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
553 #else
554 struct ast_config *cfg = ast_config_load("codecs.conf");
555 #endif
556 struct ast_variable *var;
557 int rate;
558
559 if (cfg == NULL)
560 return;
561 for (var = ast_variable_browse(cfg, "g723"); var; var = var->next) {
562 if (!strcasecmp(var->name, "sendrate")) {
563 rate = atoi(var->value);
564 if (rate == 53 || rate == 63) {
565 if (option_verbose > 2)
566 ast_verbose(VERBOSE_PREFIX_3 "G.723.1 setting sendrate to %d\n", rate);
567 g723_sendrate = (rate == 63) ? G723_RATE_63 : G723_RATE_53;
568 } else {
569 ast_log(LOG_ERROR, "G.723.1 sendrate must be 53 or 63\n");
570 }
571 } else {
572 ast_log(LOG_ERROR, "G.723.1 has only one option \"sendrate=<53|63>\" for 5.3 and 6.3Kbps respectivelly\n");
573 }
574 }
575 ast_config_destroy(cfg);
576 }
577 #endif
578
579 #if G72X_ASTERISK >= 16
g72x_toggle_debug(int fd)580 static char* g72x_toggle_debug(int fd)
581 #else
582 static int g72x_toggle_debug(int fd)
583 #define CLI_SUCCESS RESULT_SUCCESS
584 #define CLI_FAILURE RESULT_FAILURE
585 #endif
586 {
587 struct timespec delay = { 0, 100000000 }; /* 100ms */
588 void *tmp;
589
590 /* no locking intentionally */
591 if (frame_sizes != NULL) {
592 tmp = frame_sizes;
593 frame_sizes = NULL;
594 nanosleep(&delay, NULL); /* hope all users are gone */
595 ast_free(tmp);
596 ast_cli(fd, G72X_CODEC " debug disabled\n");
597 } else {
598 frame_sizes = (int*)ast_malloc((DEBUG_MAX_FRAME_SIZE+1)*sizeof(int));
599 if (frame_sizes == NULL)
600 return CLI_FAILURE;
601 memset(frame_sizes, 0, (DEBUG_MAX_FRAME_SIZE+1)*sizeof(int));
602 ast_cli(fd, G72X_CODEC " debug enabled\n");
603 }
604 return CLI_SUCCESS;
605 }
606
607 static char g72x_toggle_debug_desc[] = "Toggle " G72X_CODEC " codec frame size statistics";
608 static char g72x_usage[] =
609 "Usage: " G72X_CODEC " debug\n"
610 " Toggle " G72X_CODEC " codec frame size statistics\n";
611
612 #if G72X_ASTERISK >= 16
handle_cli_g72x_toggle_debug(struct ast_cli_entry * e,int cmd,struct ast_cli_args * a)613 static char *handle_cli_g72x_toggle_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
614 {
615 switch (cmd) {
616 case CLI_INIT:
617 e->command = G72X_CODEC " debug";
618 e->usage = g72x_usage;
619 return NULL;
620 case CLI_GENERATE:
621 return NULL;
622 }
623 if (a->argc != 2)
624 return CLI_SHOWUSAGE;
625 g72x_toggle_debug(a->fd);
626 return CLI_SUCCESS;
627 }
628
629 static struct ast_cli_entry cli_g72x = AST_CLI_DEFINE(handle_cli_g72x_toggle_debug, g72x_toggle_debug_desc);
630
631 #else /* 1.4 or Callweaver */
handle_cli_g72x_toggle_debug(int fd,int argc,char ** argv)632 static int handle_cli_g72x_toggle_debug(int fd, int argc, char **argv)
633 {
634 if (argc != 2)
635 return RESULT_SHOWUSAGE;
636 return g72x_toggle_debug(fd);
637 }
638
639 static struct ast_cli_entry cli_g72x = {
640 { G72X_CODEC, "debug", NULL }, handle_cli_g72x_toggle_debug,
641 g72x_toggle_debug_desc, g72x_usage, NULL
642 };
643
644 #endif
645
load_module(void)646 static int load_module(void)
647 {
648 int res;
649
650 #if G72X_ASTERISK == 100
651 ast_format_set(&lintog72x.src_format, AST_FORMAT_SLINEAR, 0);
652 ast_format_set(&lintog72x.dst_format, G72X_AST_FORMAT, 0);
653
654 ast_format_set(&g72xtolin.src_format, G72X_AST_FORMAT, 0);
655 ast_format_set(&g72xtolin.dst_format, AST_FORMAT_SLINEAR, 0);
656 #endif
657
658 #if !G72X_BCG729 && IPPCORE_STATIC_INIT
659 ippStaticInit();
660 #endif
661
662 #if G72X_3
663 parse_config();
664 #endif
665
666 #if !G72X_BCG729
667 #if G72X_9
668 apiG729Decoder_Alloc(G729A_CODEC, &decoder_size);
669 apiG729Encoder_Alloc(G729A_CODEC, &encoder_size);
670 apiG729Codec_ScratchMemoryAlloc(&coder_size_scratch);
671 #else
672 apiG723Decoder_Alloc(&decoder_size);
673 apiG723Encoder_Alloc(&encoder_size);
674 apiG723Codec_ScratchMemoryAlloc(&coder_size_scratch);
675 #endif
676 #endif
677
678 res = ast_register_translator(&g72xtolin);
679 if (!res)
680 res = ast_register_translator(&lintog72x);
681 else
682 ast_unregister_translator(&g72xtolin);
683
684 ast_cli_register(&cli_g72x);
685
686 return res;
687 }
688
unload_module(void)689 static int unload_module(void)
690 {
691 int res;
692
693 res = ast_unregister_translator(&lintog72x);
694 res |= ast_unregister_translator(&g72xtolin);
695
696 ast_cli_unregister(&cli_g72x);
697
698 return res;
699 }
700
701 #if G72X_ASTERISK < 110
702 ASTERISK_FILE_VERSION(__FILE__, "1.0")
703 #endif
704
705 #if G72X_ASTERISK >= 14
706 /* AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, G72X_CODEC " Coder/Decoder"); */
707 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, G72X_DESC, .load = load_module, .unload = unload_module, .buildopt_sum = "");
708
709 #else /* Asterisk 1.2 or Callweaver */
710
711 static int localusecnt = 0;
712 static char *tdesc = G72X_DESC;
713
714 char *description(void) {
715 return tdesc;
716 }
717 int usecount(void) {
718 int res;
719 STANDARD_USECOUNT(res);
720 return res;
721 }
722 #if G72X_ASTERISK
723 char *key() {
724 return ASTERISK_GPL_KEY;
725 }
726 #endif
727 #endif
728