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