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