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