add missing break (issue #5154)
[asterisk/asterisk.git] / frame.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Frame manipulation routines
5  * 
6  * Copyright (C) 1999 - 2005, Digium, Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <errno.h>
18 #include <stdio.h>
19
20 #include "asterisk.h"
21
22 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
23
24 #include "asterisk/lock.h"
25 #include "asterisk/frame.h"
26 #include "asterisk/logger.h"
27 #include "asterisk/options.h"
28 #include "asterisk/channel.h"
29 #include "asterisk/cli.h"
30 #include "asterisk/term.h"
31 #include "asterisk/utils.h"
32
33 #ifdef TRACE_FRAMES
34 static int headers = 0;
35 static struct ast_frame *headerlist = NULL;
36 AST_MUTEX_DEFINE_STATIC(framelock);
37 #endif
38
39 #define SMOOTHER_SIZE 8000
40
41 #define TYPE_HIGH        0x0
42 #define TYPE_LOW         0x1
43 #define TYPE_SILENCE     0x2
44 #define TYPE_DONTSEND    0x3
45 #define TYPE_MASK        0x3
46
47 struct ast_format_list {
48         int visible; /* Can we see this entry */
49         int bits; /* bitmask value */
50         char *name; /* short name */
51         char *desc; /* Description */
52 };
53
54 struct ast_smoother {
55         int size;
56         int format;
57         int readdata;
58         int optimizablestream;
59         int flags;
60         float samplesperbyte;
61         struct ast_frame f;
62         struct timeval delivery;
63         char data[SMOOTHER_SIZE];
64         char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
65         struct ast_frame *opt;
66         int len;
67 };
68
69 void ast_smoother_reset(struct ast_smoother *s, int size)
70 {
71         memset(s, 0, sizeof(struct ast_smoother));
72         s->size = size;
73 }
74
75 struct ast_smoother *ast_smoother_new(int size)
76 {
77         struct ast_smoother *s;
78         if (size < 1)
79                 return NULL;
80         s = malloc(sizeof(struct ast_smoother));
81         if (s)
82                 ast_smoother_reset(s, size);
83         return s;
84 }
85
86 int ast_smoother_get_flags(struct ast_smoother *s)
87 {
88         return s->flags;
89 }
90
91 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
92 {
93         s->flags = flags;
94 }
95
96 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
97 {
98         if (f->frametype != AST_FRAME_VOICE) {
99                 ast_log(LOG_WARNING, "Huh?  Can't smooth a non-voice frame!\n");
100                 return -1;
101         }
102         if (!s->format) {
103                 s->format = f->subclass;
104                 s->samplesperbyte = (float)f->samples / (float)f->datalen;
105         } else if (s->format != f->subclass) {
106                 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
107                 return -1;
108         }
109         if (s->len + f->datalen > SMOOTHER_SIZE) {
110                 ast_log(LOG_WARNING, "Out of smoother space\n");
111                 return -1;
112         }
113         if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
114                                  && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
115                 if (!s->len) {
116                         /* Optimize by sending the frame we just got
117                            on the next read, thus eliminating the douple
118                            copy */
119                         s->opt = f;
120                         return 0;
121                 } else {
122                         s->optimizablestream++;
123                         if (s->optimizablestream > 10) {
124                                 /* For the past 10 rounds, we have input and output
125                                    frames of the correct size for this smoother, yet
126                                    we were unable to optimize because there was still
127                                    some cruft left over.  Lets just drop the cruft so
128                                    we can move to a fully optimized path */
129                                 s->len = 0;
130                                 s->opt = f;
131                                 return 0;
132                         }
133                 }
134         } else 
135                 s->optimizablestream = 0;
136         if (s->flags & AST_SMOOTHER_FLAG_G729) {
137                 if (s->len % 10) {
138                         ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
139                         return 0;
140                 }
141         }
142         if (swap)
143                 ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
144         else
145                 memcpy(s->data + s->len, f->data, f->datalen);
146         /* If either side is empty, reset the delivery time */
147         if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery))      /* XXX really ? */
148                 s->delivery = f->delivery;
149         s->len += f->datalen;
150         return 0;
151 }
152
153 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
154 {
155         struct ast_frame *opt;
156         int len;
157         /* IF we have an optimization frame, send it */
158         if (s->opt) {
159                 if (s->opt->offset < AST_FRIENDLY_OFFSET)
160                         ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).",
161                                                         s->opt->offset);
162                 opt = s->opt;
163                 s->opt = NULL;
164                 return opt;
165         }
166
167         /* Make sure we have enough data */
168         if (s->len < s->size) {
169                 /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
170                 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
171                         return NULL;
172         }
173         len = s->size;
174         if (len > s->len)
175                 len = s->len;
176         /* Make frame */
177         s->f.frametype = AST_FRAME_VOICE;
178         s->f.subclass = s->format;
179         s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
180         s->f.offset = AST_FRIENDLY_OFFSET;
181         s->f.datalen = len;
182         /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
183         s->f.samples = len * s->samplesperbyte; /* XXX rounding */
184         s->f.delivery = s->delivery;
185         /* Fill Data */
186         memcpy(s->f.data, s->data, len);
187         s->len -= len;
188         /* Move remaining data to the front if applicable */
189         if (s->len) {
190                 /* In principle this should all be fine because if we are sending
191                    G.729 VAD, the next timestamp will take over anyawy */
192                 memmove(s->data, s->data + len, s->len);
193                 if (!ast_tvzero(s->delivery)) {
194                         /* If we have delivery time, increment it, otherwise, leave it at 0 */
195                         s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
196                 }
197         }
198         /* Return frame */
199         return &s->f;
200 }
201
202 void ast_smoother_free(struct ast_smoother *s)
203 {
204         free(s);
205 }
206
207 static struct ast_frame *ast_frame_header_new(void)
208 {
209         struct ast_frame *f;
210         f = malloc(sizeof(struct ast_frame));
211         if (f)
212                 memset(f, 0, sizeof(struct ast_frame));
213 #ifdef TRACE_FRAMES
214         if (f) {
215                 headers++;
216                 f->prev = NULL;
217                 ast_mutex_lock(&framelock);
218                 f->next = headerlist;
219                 if (headerlist)
220                         headerlist->prev = f;
221                 headerlist = f;
222                 ast_mutex_unlock(&framelock);
223         }
224 #endif  
225         return f;
226 }
227
228 /*
229  * Important: I should be made more efficient.  Frame headers should
230  * most definitely be cached
231  */
232
233 void ast_frfree(struct ast_frame *fr)
234 {
235         if (fr->mallocd & AST_MALLOCD_DATA) {
236                 if (fr->data) 
237                         free(fr->data - fr->offset);
238         }
239         if (fr->mallocd & AST_MALLOCD_SRC) {
240                 if (fr->src)
241                         free((char *)fr->src);
242         }
243         if (fr->mallocd & AST_MALLOCD_HDR) {
244 #ifdef TRACE_FRAMES
245                 headers--;
246                 ast_mutex_lock(&framelock);
247                 if (fr->next)
248                         fr->next->prev = fr->prev;
249                 if (fr->prev)
250                         fr->prev->next = fr->next;
251                 else
252                         headerlist = fr->next;
253                 ast_mutex_unlock(&framelock);
254 #endif                  
255                 free(fr);
256         }
257 }
258
259 /*
260  * 'isolates' a frame by duplicating non-malloc'ed components
261  * (header, src, data).
262  * On return all components are malloc'ed
263  */
264 struct ast_frame *ast_frisolate(struct ast_frame *fr)
265 {
266         struct ast_frame *out;
267         if (!(fr->mallocd & AST_MALLOCD_HDR)) {
268                 /* Allocate a new header if needed */
269                 out = ast_frame_header_new();
270                 if (!out) {
271                         ast_log(LOG_WARNING, "Out of memory\n");
272                         return NULL;
273                 }
274                 out->frametype = fr->frametype;
275                 out->subclass = fr->subclass;
276                 out->datalen = fr->datalen;
277                 out->samples = fr->samples;
278                 out->offset = fr->offset;
279                 out->src = NULL;
280                 out->data = fr->data;
281         } else {
282                 out = fr;
283         }
284         if (!(fr->mallocd & AST_MALLOCD_SRC)) {
285                 if (fr->src)
286                         out->src = strdup(fr->src);
287         } else
288                 out->src = fr->src;
289         if (!(fr->mallocd & AST_MALLOCD_DATA))  {
290                 out->data = malloc(fr->datalen + AST_FRIENDLY_OFFSET);
291                 if (!out->data) {
292                         free(out);
293                         ast_log(LOG_WARNING, "Out of memory\n");
294                         return NULL;
295                 }
296                 out->data += AST_FRIENDLY_OFFSET;
297                 out->offset = AST_FRIENDLY_OFFSET;
298                 out->datalen = fr->datalen;
299                 memcpy(out->data, fr->data, fr->datalen);
300         }
301         out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
302         return out;
303 }
304
305 struct ast_frame *ast_frdup(struct ast_frame *f)
306 {
307         struct ast_frame *out;
308         int len, srclen = 0;
309         void *buf;
310         /* Start with standard stuff */
311         len = sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET + f->datalen;
312         /* If we have a source, add space for it */
313         /*
314          * XXX Watch out here - if we receive a src which is not terminated
315          * properly, we can be easily attacked. Should limit the size we deal with.
316          */
317         if (f->src)
318                 srclen = strlen(f->src);
319         if (srclen > 0)
320                 len += srclen + 1;
321         buf = malloc(len);
322         if (!buf)
323                 return NULL;
324         out = buf;
325         /* Set us as having malloc'd header only, so it will eventually
326            get freed. */
327         out->frametype = f->frametype;
328         out->subclass = f->subclass;
329         out->datalen = f->datalen;
330         out->samples = f->samples;
331         out->delivery = f->delivery;
332         out->mallocd = AST_MALLOCD_HDR;
333         out->offset = AST_FRIENDLY_OFFSET;
334         out->data = buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
335         if (srclen > 0) {
336                 out->src = out->data + f->datalen;
337                 /* Must have space since we allocated for it */
338                 strcpy((char *)out->src, f->src);
339         } else
340                 out->src = NULL;
341         out->prev = NULL;
342         out->next = NULL;
343         memcpy(out->data, f->data, out->datalen);       
344         return out;
345 }
346
347 #if 0
348 /*
349  * XXX
350  * This function is badly broken - it does not handle correctly
351  * partial reads on either header or body.
352  * However is it never used anywhere so we leave it commented out
353  */
354 struct ast_frame *ast_fr_fdread(int fd)
355 {
356         char buf[65536];
357         int res;
358         int ttl = sizeof(struct ast_frame);
359         struct ast_frame *f = (struct ast_frame *)buf;
360         /* Read a frame directly from there.  They're always in the
361            right format. */
362         
363         while(ttl) {
364                 res = read(fd, buf, ttl);
365                 if (res < 0) {
366                         ast_log(LOG_WARNING, "Bad read on %d: %s\n", fd, strerror(errno));
367                         return NULL;
368                 }
369                 ttl -= res;
370         }
371         
372         /* read the frame header */
373         f->mallocd = 0;
374         /* Re-write data position */
375         f->data = buf + sizeof(struct ast_frame);
376         f->offset = 0;
377         /* Forget about being mallocd */
378         f->mallocd = 0;
379         /* Re-write the source */
380         f->src = (char *)__FUNCTION__;
381         if (f->datalen > sizeof(buf) - sizeof(struct ast_frame)) {
382                 /* Really bad read */
383                 ast_log(LOG_WARNING, "Strange read (%d bytes)\n", f->datalen);
384                 return NULL;
385         }
386         if (f->datalen) {
387                 if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
388                         /* Bad read */
389                         ast_log(LOG_WARNING, "How very strange, expected %d, got %d\n", f->datalen, res);
390                         return NULL;
391                 }
392         }
393         if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
394                 return NULL;
395         }
396         return ast_frisolate(f);
397 }
398
399 /* Some convenient routines for sending frames to/from stream or datagram
400    sockets, pipes, etc (maybe even files) */
401
402 /*
403  * XXX this function is also partly broken because it does not handle
404  * partial writes. We comment it out too, and also the unique
405  * client it has, ast_fr_fdhangup()
406  */
407 int ast_fr_fdwrite(int fd, struct ast_frame *frame)
408 {
409         /* Write the frame exactly */
410         if (write(fd, frame, sizeof(struct ast_frame)) != sizeof(struct ast_frame)) {
411                 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
412                 return -1;
413         }
414         if (write(fd, frame->data, frame->datalen) != frame->datalen) {
415                 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
416                 return -1;
417         }
418         return 0;
419 }
420
421 int ast_fr_fdhangup(int fd)
422 {
423         struct ast_frame hangup = {
424                 AST_FRAME_CONTROL,
425                 AST_CONTROL_HANGUP
426         };
427         return ast_fr_fdwrite(fd, &hangup);
428 }
429
430 #endif /* unused functions */
431 void ast_swapcopy_samples(void *dst, const void *src, int samples)
432 {
433         int i;
434         unsigned short *dst_s = dst;
435         const unsigned short *src_s = src;
436
437         for (i=0; i<samples; i++)
438                 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
439 }
440
441 static struct ast_format_list AST_FORMAT_LIST[] = {
442         { 1, AST_FORMAT_G723_1 , "g723" , "G.723.1"},
443         { 1, AST_FORMAT_GSM, "gsm" , "GSM"},
444         { 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law" },
445         { 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law" },
446         { 1, AST_FORMAT_G726, "g726", "G.726" },
447         { 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM"},
448         { 1, AST_FORMAT_SLINEAR, "slin",  "16 bit Signed Linear PCM"},
449         { 1, AST_FORMAT_LPC10, "lpc10", "LPC10" },
450         { 1, AST_FORMAT_G729A, "g729", "G.729A" },
451         { 1, AST_FORMAT_SPEEX, "speex", "SpeeX" },
452         { 1, AST_FORMAT_ILBC, "ilbc", "iLBC"},
453         { 0, 0, "nothing", "undefined" },
454         { 0, 0, "nothing", "undefined" },
455         { 0, 0, "nothing", "undefined" },
456         { 0, 0, "nothing", "undefined" },
457         { 0, AST_FORMAT_MAX_AUDIO, "maxaudio", "Maximum audio format" },
458         { 1, AST_FORMAT_JPEG, "jpeg", "JPEG image"},
459         { 1, AST_FORMAT_PNG, "png", "PNG image"},
460         { 1, AST_FORMAT_H261, "h261", "H.261 Video" },
461         { 1, AST_FORMAT_H263, "h263", "H.263 Video" },
462         { 1, AST_FORMAT_H263_PLUS, "h263p", "H.263+ Video" },
463         { 0, 0, "nothing", "undefined" },
464         { 0, 0, "nothing", "undefined" },
465         { 0, 0, "nothing", "undefined" },
466         { 0, 0, "nothing", "undefined" },
467         { 0, AST_FORMAT_MAX_VIDEO, "maxvideo", "Maximum video format" },
468 };
469
470 struct ast_format_list *ast_get_format_list_index(int index) 
471 {
472         return &AST_FORMAT_LIST[index];
473 }
474
475 struct ast_format_list *ast_get_format_list(size_t *size) 
476 {
477         *size = (sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list));
478         return AST_FORMAT_LIST;
479 }
480
481 char* ast_getformatname(int format)
482 {
483         int x = 0;
484         char *ret = "unknown";
485         for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
486                 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
487                         ret = AST_FORMAT_LIST[x].name;
488                         break;
489                 }
490         }
491         return ret;
492 }
493
494 char *ast_getformatname_multiple(char *buf, size_t size, int format) {
495
496         int x = 0;
497         unsigned len;
498         char *end = buf;
499         char *start = buf;
500         if (!size) return buf;
501         snprintf(end, size, "0x%x (", format);
502         len = strlen(end);
503         end += len;
504         size -= len;
505         start = end;
506         for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
507                 if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
508                         snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
509                         len = strlen(end);
510                         end += len;
511                         size -= len;
512                 }
513         }
514         if (start == end)
515                 snprintf(start, size, "nothing)");
516         else if (size > 1)
517                 *(end -1) = ')';
518         return buf;
519 }
520
521 static struct ast_codec_alias_table {
522         char *alias;
523         char *realname;
524
525 } ast_codec_alias_table[] = {
526         {"slinear","slin"},
527         {"g723.1","g723"},
528 };
529
530 static char *ast_expand_codec_alias(char *in) {
531         int x = 0;
532
533         for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(struct ast_codec_alias_table) ; x++) {
534                 if(!strcmp(in,ast_codec_alias_table[x].alias))
535                         return ast_codec_alias_table[x].realname;
536         }
537         return in;
538 }
539
540 int ast_getformatbyname(char *name)
541 {
542         int x = 0, all = 0, format = 0;
543
544         all = strcasecmp(name, "all") ? 0 : 1;
545         for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
546                 if(AST_FORMAT_LIST[x].visible && (all || 
547                                                                                   !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
548                                                                                   !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
549                         format |= AST_FORMAT_LIST[x].bits;
550                         if(!all)
551                                 break;
552                 }
553         }
554
555         return format;
556 }
557
558 char *ast_codec2str(int codec) {
559         int x = 0;
560         char *ret = "unknown";
561         for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
562                 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
563                         ret = AST_FORMAT_LIST[x].desc;
564                         break;
565                 }
566         }
567         return ret;
568 }
569
570 static int show_codecs(int fd, int argc, char *argv[])
571 {
572         int i, found=0;
573         char hex[25];
574         
575         if ((argc < 2) || (argc > 3))
576                 return RESULT_SHOWUSAGE;
577
578         if (!option_dontwarn)
579                 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
580                                 "\tIt does not indicate anything about your configuration.\n");
581
582         ast_cli(fd, "%11s %9s %10s   TYPE   %5s   %s\n","INT","BINARY","HEX","NAME","DESC");
583         ast_cli(fd, "--------------------------------------------------------------------------------\n");
584         if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
585                 found = 1;
586                 for (i=0;i<11;i++) {
587                         snprintf(hex,25,"(0x%x)",1<<i);
588                         ast_cli(fd, "%11u (1 << %2d) %10s  audio   %5s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
589                 }
590         }
591
592         if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
593                 found = 1;
594                 for (i=16;i<18;i++) {
595                         snprintf(hex,25,"(0x%x)",1<<i);
596                         ast_cli(fd, "%11u (1 << %2d) %10s  image   %5s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
597                 }
598         }
599
600         if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
601                 found = 1;
602                 for (i=18;i<21;i++) {
603                         snprintf(hex,25,"(0x%x)",1<<i);
604                         ast_cli(fd, "%11u (1 << %2d) %10s  video   %5s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
605                 }
606         }
607
608         if (! found)
609                 return RESULT_SHOWUSAGE;
610         else
611                 return RESULT_SUCCESS;
612 }
613
614 static char frame_show_codecs_usage[] =
615 "Usage: show [audio|video|image] codecs\n"
616 "       Displays codec mapping\n";
617
618 static int show_codec_n(int fd, int argc, char *argv[])
619 {
620         int codec, i, found=0;
621
622         if (argc != 3)
623                 return RESULT_SHOWUSAGE;
624
625         if (sscanf(argv[2],"%d",&codec) != 1)
626                 return RESULT_SHOWUSAGE;
627
628         for (i=0;i<32;i++)
629                 if (codec & (1 << i)) {
630                         found = 1;
631                         ast_cli(fd, "%11u (1 << %2d)  %s\n",1 << i,i,ast_codec2str(1<<i));
632                 }
633
634         if (! found)
635                 ast_cli(fd, "Codec %d not found\n", codec);
636
637         return RESULT_SUCCESS;
638 }
639
640 static char frame_show_codec_n_usage[] =
641 "Usage: show codec <number>\n"
642 "       Displays codec mapping\n";
643
644 void ast_frame_dump(char *name, struct ast_frame *f, char *prefix)
645 {
646         char *n = "unknown";
647         char ftype[40] = "Unknown Frametype";
648         char cft[80];
649         char subclass[40] = "Unknown Subclass";
650         char csub[80];
651         char moreinfo[40] = "";
652         char cn[60];
653         char cp[40];
654         char cmn[40];
655         if (name)
656                 n = name;
657         if (!f) {
658                 ast_verbose("%s [ %s (NULL) ] [%s]\n", 
659                         term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
660                         term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)), 
661                         term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
662                 return;
663         }
664         /* XXX We should probably print one each of voice and video when the format changes XXX */
665         if (f->frametype == AST_FRAME_VOICE)
666                 return;
667         if (f->frametype == AST_FRAME_VIDEO)
668                 return;
669         switch(f->frametype) {
670         case AST_FRAME_DTMF:
671                 strcpy(ftype, "DTMF");
672                 subclass[0] = f->subclass;
673                 subclass[1] = '\0';
674                 break;
675         case AST_FRAME_CONTROL:
676                 strcpy(ftype, "Control");
677                 switch(f->subclass) {
678                 case AST_CONTROL_HANGUP:
679                         strcpy(subclass, "Hangup");
680                         break;
681                 case AST_CONTROL_RING:
682                         strcpy(subclass, "Ring");
683                         break;
684                 case AST_CONTROL_RINGING:
685                         strcpy(subclass, "Ringing");
686                         break;
687                 case AST_CONTROL_ANSWER:
688                         strcpy(subclass, "Answer");
689                         break;
690                 case AST_CONTROL_BUSY:
691                         strcpy(subclass, "Busy");
692                         break;
693                 case AST_CONTROL_TAKEOFFHOOK:
694                         strcpy(subclass, "Take Off Hook");
695                         break;
696                 case AST_CONTROL_OFFHOOK:
697                         strcpy(subclass, "Line Off Hook");
698                         break;
699                 case AST_CONTROL_CONGESTION:
700                         strcpy(subclass, "Congestion");
701                         break;
702                 case AST_CONTROL_FLASH:
703                         strcpy(subclass, "Flash");
704                         break;
705                 case AST_CONTROL_WINK:
706                         strcpy(subclass, "Wink");
707                         break;
708                 case AST_CONTROL_OPTION:
709                         strcpy(subclass, "Option");
710                         break;
711                 case AST_CONTROL_RADIO_KEY:
712                         strcpy(subclass, "Key Radio");
713                         break;
714                 case AST_CONTROL_RADIO_UNKEY:
715                         strcpy(subclass, "Unkey Radio");
716                         break;
717                 case -1:
718                         strcpy(subclass, "Stop generators");
719                         break;
720                 default:
721                         snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
722                 }
723                 break;
724         case AST_FRAME_NULL:
725                 strcpy(ftype, "Null Frame");
726                 strcpy(subclass, "N/A");
727                 break;
728         case AST_FRAME_IAX:
729                 /* Should never happen */
730                 strcpy(ftype, "IAX Specific");
731                 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
732                 break;
733         case AST_FRAME_TEXT:
734                 strcpy(ftype, "Text");
735                 strcpy(subclass, "N/A");
736                 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
737                 break;
738         case AST_FRAME_IMAGE:
739                 strcpy(ftype, "Image");
740                 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
741                 break;
742         case AST_FRAME_HTML:
743                 strcpy(ftype, "HTML");
744                 switch(f->subclass) {
745                 case AST_HTML_URL:
746                         strcpy(subclass, "URL");
747                         ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
748                         break;
749                 case AST_HTML_DATA:
750                         strcpy(subclass, "Data");
751                         break;
752                 case AST_HTML_BEGIN:
753                         strcpy(subclass, "Begin");
754                         break;
755                 case AST_HTML_END:
756                         strcpy(subclass, "End");
757                         break;
758                 case AST_HTML_LDCOMPLETE:
759                         strcpy(subclass, "Load Complete");
760                         break;
761                 case AST_HTML_NOSUPPORT:
762                         strcpy(subclass, "No Support");
763                         break;
764                 case AST_HTML_LINKURL:
765                         strcpy(subclass, "Link URL");
766                         ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
767                         break;
768                 case AST_HTML_UNLINK:
769                         strcpy(subclass, "Unlink");
770                         break;
771                 case AST_HTML_LINKREJECT:
772                         strcpy(subclass, "Link Reject");
773                         break;
774                 default:
775                         snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
776                         break;
777                 }
778                 break;
779         default:
780                 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
781         }
782         if (!ast_strlen_zero(moreinfo))
783                 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",  
784                         term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
785                         term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
786                         f->frametype, 
787                         term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
788                         f->subclass, 
789                         term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
790                         term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
791         else
792                 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",  
793                         term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
794                         term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
795                         f->frametype, 
796                         term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
797                         f->subclass, 
798                         term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
799
800 }
801
802
803 #ifdef TRACE_FRAMES
804 static int show_frame_stats(int fd, int argc, char *argv[])
805 {
806         struct ast_frame *f;
807         int x=1;
808         if (argc != 3)
809                 return RESULT_SHOWUSAGE;
810         ast_cli(fd, "     Framer Statistics     \n");
811         ast_cli(fd, "---------------------------\n");
812         ast_cli(fd, "Total allocated headers: %d\n", headers);
813         ast_cli(fd, "Queue Dump:\n");
814         ast_mutex_lock(&framelock);
815         for (f=headerlist; f; f = f->next) {
816                 ast_cli(fd, "%d.  Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
817         }
818         ast_mutex_unlock(&framelock);
819         return RESULT_SUCCESS;
820 }
821
822 static char frame_stats_usage[] =
823 "Usage: show frame stats\n"
824 "       Displays debugging statistics from framer\n";
825 #endif
826
827 /* XXX no unregister function here ??? */
828 static struct ast_cli_entry my_clis[] = {
829 { { "show", "codecs", NULL }, show_codecs, "Shows codecs", frame_show_codecs_usage },
830 { { "show", "audio", "codecs", NULL }, show_codecs, "Shows audio codecs", frame_show_codecs_usage },
831 { { "show", "video", "codecs", NULL }, show_codecs, "Shows video codecs", frame_show_codecs_usage },
832 { { "show", "image", "codecs", NULL }, show_codecs, "Shows image codecs", frame_show_codecs_usage },
833 { { "show", "codec", NULL }, show_codec_n, "Shows a specific codec", frame_show_codec_n_usage },
834 #ifdef TRACE_FRAMES
835 { { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage },
836 #endif
837 };
838
839 int init_framer(void)
840 {
841         ast_cli_register_multiple(my_clis, sizeof(my_clis)/sizeof(my_clis[0]) );
842         return 0;       
843 }
844
845 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right) 
846 {
847         int x = 0, differential = (int) 'A', mem = 0;
848         char *from = NULL, *to = NULL;
849
850         if(right) {
851                 from = pref->order;
852                 to = buf;
853                 mem = size;
854         } else {
855                 to = pref->order;
856                 from = buf;
857                 mem = 32;
858         }
859
860         memset(to, 0, mem);
861         for (x = 0; x < 32 ; x++) {
862                 if(!from[x])
863                         break;
864                 to[x] = right ? (from[x] + differential) : (from[x] - differential);
865         }
866 }
867
868 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size) 
869 {
870         int x = 0, codec = 0; 
871         size_t total_len = 0, slen = 0;
872         char *formatname = 0;
873         
874         memset(buf,0,size);
875         total_len = size;
876         buf[0] = '(';
877         total_len--;
878         for(x = 0; x < 32 ; x++) {
879                 if(total_len <= 0)
880                         break;
881                 if(!(codec = ast_codec_pref_index(pref,x)))
882                         break;
883                 if((formatname = ast_getformatname(codec))) {
884                         slen = strlen(formatname);
885                         if(slen > total_len)
886                                 break;
887                         strncat(buf,formatname,total_len);
888                         total_len -= slen;
889                 }
890                 if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
891                         strncat(buf,"|",total_len);
892                         total_len--;
893                 }
894         }
895         if(total_len) {
896                 strncat(buf,")",total_len);
897                 total_len--;
898         }
899
900         return size - total_len;
901 }
902
903 int ast_codec_pref_index(struct ast_codec_pref *pref, int index) 
904 {
905         int slot = 0;
906
907         
908         if((index >= 0) && (index < sizeof(pref->order))) {
909                 slot = pref->order[index];
910         }
911
912         return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
913 }
914
915 /*--- ast_codec_pref_remove: Remove codec from pref list ---*/
916 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
917 {
918         struct ast_codec_pref oldorder;
919         int x=0, y=0;
920         size_t size = 0;
921         int slot = 0;
922
923         if(!pref->order[0])
924                 return;
925
926         size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
927
928         memcpy(&oldorder,pref,sizeof(struct ast_codec_pref));
929         memset(pref,0,sizeof(struct ast_codec_pref));
930
931         for (x = 0; x < size; x++) {
932                 slot = oldorder.order[x];
933                 if(! slot)
934                         break;
935                 if(AST_FORMAT_LIST[slot-1].bits != format)
936                         pref->order[y++] = slot;
937         }
938         
939 }
940
941 /*--- ast_codec_pref_append: Append codec to list ---*/
942 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
943 {
944         size_t size = 0;
945         int x = 0, newindex = -1;
946
947         ast_codec_pref_remove(pref, format);
948         size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
949
950         for (x = 0; x < size; x++) {
951                 if(AST_FORMAT_LIST[x].bits == format) {
952                         newindex = x + 1;
953                         break;
954                 }
955         }
956
957         if(newindex) {
958                 for (x = 0; x < size; x++) {
959                         if(!pref->order[x]) {
960                                 pref->order[x] = newindex;
961                                 break;
962                         }
963                 }
964         }
965
966         return x;
967 }
968
969
970 /*--- sip_codec_choose: Pick a codec ---*/
971 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
972 {
973         size_t size = 0;
974         int x = 0, ret = 0, slot = 0;
975
976         size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
977         for (x = 0; x < size; x++) {
978                 slot = pref->order[x];
979
980                 if(!slot)
981                         break;
982                 if ( formats & AST_FORMAT_LIST[slot-1].bits ) {
983                         ret = AST_FORMAT_LIST[slot-1].bits;
984                         break;
985                 }
986         }
987         if(ret)
988                 return ret;
989
990         return find_best ? ast_best_codec(formats) : 0;
991 }
992
993 void ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, char *list, int allowing) 
994 {
995         int format_i = 0;
996         char *next_format = NULL, *last_format = NULL;
997
998         last_format = ast_strdupa(list);
999         while(last_format) {
1000                 if((next_format = strchr(last_format, ','))) {
1001                         *next_format = '\0';
1002                         next_format++;
1003                 }
1004                 if ((format_i = ast_getformatbyname(last_format)) > 0) {
1005                         if (mask) {
1006                                 if (allowing)
1007                                         (*mask) |= format_i;
1008                                 else
1009                                         (*mask) &= ~format_i;
1010                         }
1011                         /* can't consider 'all' a prefered codec*/
1012                         if(pref && strcasecmp(last_format, "all")) {
1013                                 if(allowing)
1014                                         ast_codec_pref_append(pref, format_i);
1015                                 else
1016                                         ast_codec_pref_remove(pref, format_i);
1017                         } else if(!allowing) /* disallow all must clear your prefs or it makes no sense */
1018                                 memset(pref, 0, sizeof(struct ast_codec_pref));
1019                 } else
1020                         ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", last_format);
1021
1022                 last_format = next_format;
1023         }
1024 }
1025
1026 static int g723_len(unsigned char buf)
1027 {
1028         switch(buf & TYPE_MASK) {
1029         case TYPE_DONTSEND:
1030                 return 0;
1031                 break;
1032         case TYPE_SILENCE:
1033                 return 4;
1034                 break;
1035         case TYPE_HIGH:
1036                 return 24;
1037                 break;
1038         case TYPE_LOW:
1039                 return 20;
1040                 break;
1041         default:
1042                 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
1043         }
1044         return -1;
1045 }
1046
1047 static int g723_samples(unsigned char *buf, int maxlen)
1048 {
1049         int pos = 0;
1050         int samples = 0;
1051         int res;
1052         while(pos < maxlen) {
1053                 res = g723_len(buf[pos]);
1054                 if (res <= 0)
1055                         break;
1056                 samples += 240;
1057                 pos += res;
1058         }
1059         return samples;
1060 }
1061
1062 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1063 {
1064         int byte = bit / 8;       /* byte containing first bit */
1065         int rem = 8 - (bit % 8);  /* remaining bits in first byte */
1066         unsigned char ret = 0;
1067         
1068         if (n <= 0 || n > 8)
1069                 return 0;
1070
1071         if (rem < n) {
1072                 ret = (data[byte] << (n - rem));
1073                 ret |= (data[byte + 1] >> (8 - n + rem));
1074         } else {
1075                 ret = (data[byte] >> (rem - n));
1076         }
1077
1078         return (ret & (0xff >> (8 - n)));
1079 }
1080
1081 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1082 {
1083         static int SpeexWBSubModeSz[] = {
1084                 0, 36, 112, 192,
1085                 352, 0, 0, 0 };
1086         int off = bit;
1087         unsigned char c;
1088
1089         /* skip up to two wideband frames */
1090         if (((len * 8 - off) >= 5) && 
1091                 get_n_bits_at(data, 1, off)) {
1092                 c = get_n_bits_at(data, 3, off + 1);
1093                 off += SpeexWBSubModeSz[c];
1094
1095                 if (((len * 8 - off) >= 5) && 
1096                         get_n_bits_at(data, 1, off)) {
1097                         c = get_n_bits_at(data, 3, off + 1);
1098                         off += SpeexWBSubModeSz[c];
1099
1100                         if (((len * 8 - off) >= 5) && 
1101                                 get_n_bits_at(data, 1, off)) {
1102                                 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1103                                 return -1;
1104                         }
1105                 }
1106
1107         }
1108         return off - bit;
1109 }
1110
1111 static int speex_samples(unsigned char *data, int len)
1112 {
1113         static int SpeexSubModeSz[] = {
1114                5, 43, 119, 160,
1115                 220, 300, 364, 492, 
1116                 79, 0, 0, 0,
1117                 0, 0, 0, 0 };
1118         static int SpeexInBandSz[] = { 
1119                 1, 1, 4, 4,
1120                 4, 4, 4, 4,
1121                 8, 8, 16, 16,
1122                 32, 32, 64, 64 };
1123         int bit = 0;
1124         int cnt = 0;
1125         int off = 0;
1126         unsigned char c;
1127
1128         while ((len * 8 - bit) >= 5) {
1129                 /* skip wideband frames */
1130                 off = speex_get_wb_sz_at(data, len, bit);
1131                 if (off < 0)  {
1132                         ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1133                         break;
1134                 }
1135                 bit += off;
1136
1137                 if ((len * 8 - bit) < 5) {
1138                         ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1139                         break;
1140                 }
1141
1142                 /* get control bits */
1143                 c = get_n_bits_at(data, 5, bit);
1144                 bit += 5;
1145
1146                 if (c == 15) { 
1147                         /* terminator */
1148                         break; 
1149                 } else if (c == 14) {
1150                         /* in-band signal; next 4 bits contain signal id */
1151                         c = get_n_bits_at(data, 4, bit);
1152                         bit += 4;
1153                         bit += SpeexInBandSz[c];
1154                 } else if (c == 13) {
1155                         /* user in-band; next 5 bits contain msg len */
1156                         c = get_n_bits_at(data, 5, bit);
1157                         bit += 5;
1158                         bit += c * 8;
1159                 } else if (c > 8) {
1160                         /* unknown */
1161                         break;
1162                 } else {
1163                         /* skip number bits for submode (less the 5 control bits) */
1164                         bit += SpeexSubModeSz[c] - 5;
1165                         cnt += 160; /* new frame */
1166                 }
1167         }
1168         return cnt;
1169 }
1170
1171 int ast_codec_get_samples(struct ast_frame *f)
1172 {
1173         int samples=0;
1174         switch(f->subclass) {
1175         case AST_FORMAT_SPEEX:
1176                 samples = speex_samples(f->data, f->datalen);
1177                 break;
1178         case AST_FORMAT_G723_1:
1179                 samples = g723_samples(f->data, f->datalen);
1180                 break;
1181         case AST_FORMAT_ILBC:
1182                 samples = 240 * (f->datalen / 50);
1183                 break;
1184         case AST_FORMAT_GSM:
1185                 samples = 160 * (f->datalen / 33);
1186                 break;
1187         case AST_FORMAT_G729A:
1188                 samples = f->datalen * 8;
1189                 break;
1190         case AST_FORMAT_SLINEAR:
1191                 samples = f->datalen / 2;
1192                 break;
1193         case AST_FORMAT_LPC10:
1194                 /* assumes that the RTP packet contains one LPC10 frame */
1195                 samples = 22 * 8;
1196                 samples += (((char *)(f->data))[7] & 0x1) * 8;
1197                 break;
1198         case AST_FORMAT_ULAW:
1199         case AST_FORMAT_ALAW:
1200                 samples = f->datalen;
1201                 break;
1202         case AST_FORMAT_ADPCM:
1203         case AST_FORMAT_G726:
1204                 samples = f->datalen * 2;
1205                 break;
1206         default:
1207                 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1208         }
1209         return samples;
1210 }
1211
1212 int ast_codec_get_len(int format, int samples)
1213 {
1214         int len = 0;
1215
1216         /* XXX Still need speex, g723, and lpc10 XXX */ 
1217         switch(format) {
1218         case AST_FORMAT_ILBC:
1219                 len = (samples / 240) * 50;
1220                 break;
1221         case AST_FORMAT_GSM:
1222                 len = (samples / 160) * 33;
1223                 break;
1224         case AST_FORMAT_G729A:
1225                 len = samples / 8;
1226                 break;
1227         case AST_FORMAT_SLINEAR:
1228                 len = samples * 2;
1229                 break;
1230         case AST_FORMAT_ULAW:
1231         case AST_FORMAT_ALAW:
1232                 len = samples;
1233                 break;
1234         case AST_FORMAT_ADPCM:
1235         case AST_FORMAT_G726:
1236                 len = samples / 2;
1237                 break;
1238         default:
1239                 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1240         }
1241
1242         return len;
1243 }