ad747abdaf1d43eff6c62f3335a7df4674466ea3
[asterisk/asterisk.git] / main / 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 and codec manipulation routines
22  *
23  * \author Mark Spencer <markster@digium.com> 
24  */
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <stdio.h>
35
36 #include "asterisk/lock.h"
37 #include "asterisk/frame.h"
38 #include "asterisk/logger.h"
39 #include "asterisk/options.h"
40 #include "asterisk/channel.h"
41 #include "asterisk/cli.h"
42 #include "asterisk/term.h"
43 #include "asterisk/utils.h"
44 #include "asterisk/threadstorage.h"
45 #include "asterisk/linkedlists.h"
46
47 #ifdef TRACE_FRAMES
48 static int headers = 0;
49 static AST_LIST_HEAD_STATIC(headerlist, ast_frame);
50 #endif
51
52 static void frame_cache_cleanup(void *data);
53
54 /*! \brief A per-thread cache of frame headers */
55 AST_THREADSTORAGE_CUSTOM(frame_cache, frame_cache_init, frame_cache_cleanup);
56
57 /*! 
58  * \brief Maximum ast_frame cache size
59  *
60  * In most cases where the frame header cache will be useful, the size
61  * of the cache will stay very small.  However, it is not always the case that
62  * the same thread that allocates the frame will be the one freeing them, so
63  * sometimes a thread will never have any frames in its cache, or the cache
64  * will never be pulled from.  For the latter case, we limit the maximum size. 
65  */ 
66 #define FRAME_CACHE_MAX_SIZE    10
67
68 /*! \brief This is just so ast_frames, a list head struct for holding a list of
69  *  ast_frame structures, is defined. */
70 AST_LIST_HEAD_NOLOCK(ast_frames, ast_frame);
71
72 struct ast_frame_cache {
73         struct ast_frames list;
74         size_t size;
75 };
76
77 #define SMOOTHER_SIZE 8000
78
79 enum frame_type {
80         TYPE_HIGH,     /* 0x0 */
81         TYPE_LOW,      /* 0x1 */
82         TYPE_SILENCE,  /* 0x2 */
83         TYPE_DONTSEND  /* 0x3 */
84 };
85
86 #define TYPE_MASK 0x3
87
88 struct ast_smoother {
89         int size;
90         int format;
91         int readdata;
92         int optimizablestream;
93         int flags;
94         float samplesperbyte;
95         struct ast_frame f;
96         struct timeval delivery;
97         char data[SMOOTHER_SIZE];
98         char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
99         struct ast_frame *opt;
100         int len;
101 };
102
103 /*! \brief Definition of supported media formats (codecs) */
104 static struct ast_format_list AST_FORMAT_LIST[] = {                                     /*!< Bit number: comment  - Bit numbers are hard coded in show_codec() */
105         { 1, AST_FORMAT_G723_1 , "g723" , "G.723.1", 24, 30, 300, 30, 30 },     /*!<  1 */
106         { 1, AST_FORMAT_GSM, "gsm" , "GSM", 33, 20, 60, 20, 20 },               /*!<  2: codec_gsm.c */
107         { 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law", 80, 10, 30, 10, 20 },      /*!<  3: codec_ulaw.c */
108         { 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law", 80, 10, 30, 10, 20 },      /*!<  4: codec_alaw.c */
109         { 1, AST_FORMAT_G726, "g726", "G.726 RFC3551", 40, 10, 50, 10, 20 },/*!<  5: codec_g726.c */
110         { 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM", 40, 10, 30, 10, 20 }, /*!<  6: codec_adpcm.c */
111         { 1, AST_FORMAT_SLINEAR, "slin", "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE },       /*!< 7 */
112         { 1, AST_FORMAT_LPC10, "lpc10", "LPC10", 7, 20, 20, 20, 20 },   /*!<  8: codec_lpc10.c */ 
113         { 1, AST_FORMAT_G729A, "g729", "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 }, /*!<  9: Binary commercial distribution */
114         { 1, AST_FORMAT_SPEEX, "speex", "SpeeX", 10, 10, 60, 10, 20 },  /*!< 10: codec_speex.c */
115         { 1, AST_FORMAT_ILBC, "ilbc", "iLBC", 50, 30, 30, 30, 30 },             /*!< 11: codec_ilbc.c */ /* inc=30ms - workaround */
116         { 1, AST_FORMAT_G726_AAL2, "g726aal2", "G.726 AAL2", 40, 10, 50, 10, 20 },      /*!<  12: codec_g726.c */
117         { 0, 0, "nothing", "undefined" },
118         { 0, 0, "nothing", "undefined" },
119         { 0, 0, "nothing", "undefined" },
120         { 0, 0, "nothing", "undefined" },
121         { 0, AST_FORMAT_MAX_AUDIO, "maxaudio", "Maximum audio format" },        
122         { 1, AST_FORMAT_JPEG, "jpeg", "JPEG image"},    /*!< 17: See format_jpeg.c */
123         { 1, AST_FORMAT_PNG, "png", "PNG image"},       /*!< 18: Image format */
124         { 1, AST_FORMAT_H261, "h261", "H.261 Video" },  /*!< 19: Video Passthrough */
125         { 1, AST_FORMAT_H263, "h263", "H.263 Video" },  /*!< 20: Passthrough support, see format_h263.c */
126         { 1, AST_FORMAT_H263_PLUS, "h263p", "H.263+ Video" },   /*!< 21: See format_h263.c */
127         { 1, AST_FORMAT_H264, "h264", "H.264 Video" },  /*!< 22: Passthrough support, see format_h263.c */
128         { 0, 0, "nothing", "undefined" },
129         { 0, 0, "nothing", "undefined" },
130         { 0, 0, "nothing", "undefined" },
131         { 0, AST_FORMAT_MAX_VIDEO, "maxvideo", "Maximum video format" },
132 };
133
134 struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
135
136 void ast_smoother_reset(struct ast_smoother *s, int size)
137 {
138         memset(s, 0, sizeof(*s));
139         s->size = size;
140 }
141
142 struct ast_smoother *ast_smoother_new(int size)
143 {
144         struct ast_smoother *s;
145         if (size < 1)
146                 return NULL;
147         if ((s = ast_malloc(sizeof(*s))))
148                 ast_smoother_reset(s, size);
149         return s;
150 }
151
152 int ast_smoother_get_flags(struct ast_smoother *s)
153 {
154         return s->flags;
155 }
156
157 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
158 {
159         s->flags = flags;
160 }
161
162 int ast_smoother_test_flag(struct ast_smoother *s, int flag)
163 {
164         return (s->flags & flag);
165 }
166
167 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
168 {
169         if (f->frametype != AST_FRAME_VOICE) {
170                 ast_log(LOG_WARNING, "Huh?  Can't smooth a non-voice frame!\n");
171                 return -1;
172         }
173         if (!s->format) {
174                 s->format = f->subclass;
175                 s->samplesperbyte = (float)f->samples / (float)f->datalen;
176         } else if (s->format != f->subclass) {
177                 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
178                 return -1;
179         }
180         if (s->len + f->datalen > SMOOTHER_SIZE) {
181                 ast_log(LOG_WARNING, "Out of smoother space\n");
182                 return -1;
183         }
184         if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
185                                  && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
186                 if (!s->len) {
187                         /* Optimize by sending the frame we just got
188                            on the next read, thus eliminating the douple
189                            copy */
190                         s->opt = f;
191                         return 0;
192                 } else {
193                         s->optimizablestream++;
194                         if (s->optimizablestream > 10) {
195                                 /* For the past 10 rounds, we have input and output
196                                    frames of the correct size for this smoother, yet
197                                    we were unable to optimize because there was still
198                                    some cruft left over.  Lets just drop the cruft so
199                                    we can move to a fully optimized path */
200                                 s->len = 0;
201                                 s->opt = f;
202                                 return 0;
203                         }
204                 }
205         } else 
206                 s->optimizablestream = 0;
207         if (s->flags & AST_SMOOTHER_FLAG_G729) {
208                 if (s->len % 10) {
209                         ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
210                         return 0;
211                 }
212         }
213         if (swap)
214                 ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
215         else
216                 memcpy(s->data + s->len, f->data, f->datalen);
217         /* If either side is empty, reset the delivery time */
218         if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery))      /* XXX really ? */
219                 s->delivery = f->delivery;
220         s->len += f->datalen;
221         return 0;
222 }
223
224 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
225 {
226         struct ast_frame *opt;
227         int len;
228
229         /* IF we have an optimization frame, send it */
230         if (s->opt) {
231                 if (s->opt->offset < AST_FRIENDLY_OFFSET)
232                         ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).",
233                                                         s->opt->offset);
234                 opt = s->opt;
235                 s->opt = NULL;
236                 return opt;
237         }
238
239         /* Make sure we have enough data */
240         if (s->len < s->size) {
241                 /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
242                 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
243                         return NULL;
244         }
245         len = s->size;
246         if (len > s->len)
247                 len = s->len;
248         /* Make frame */
249         s->f.frametype = AST_FRAME_VOICE;
250         s->f.subclass = s->format;
251         s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
252         s->f.offset = AST_FRIENDLY_OFFSET;
253         s->f.datalen = len;
254         /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
255         s->f.samples = len * s->samplesperbyte; /* XXX rounding */
256         s->f.delivery = s->delivery;
257         /* Fill Data */
258         memcpy(s->f.data, s->data, len);
259         s->len -= len;
260         /* Move remaining data to the front if applicable */
261         if (s->len) {
262                 /* In principle this should all be fine because if we are sending
263                    G.729 VAD, the next timestamp will take over anyawy */
264                 memmove(s->data, s->data + len, s->len);
265                 if (!ast_tvzero(s->delivery)) {
266                         /* If we have delivery time, increment it, otherwise, leave it at 0 */
267                         s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
268                 }
269         }
270         /* Return frame */
271         return &s->f;
272 }
273
274 void ast_smoother_free(struct ast_smoother *s)
275 {
276         free(s);
277 }
278
279 static struct ast_frame *ast_frame_header_new(void)
280 {
281         struct ast_frame *f;
282         struct ast_frame_cache *frames;
283
284         if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
285                 if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
286                         size_t mallocd_len = f->mallocd_hdr_len;
287                         memset(f, 0, sizeof(*f));
288                         f->mallocd_hdr_len = mallocd_len;
289                         f->mallocd = AST_MALLOCD_HDR;
290                         frames->size--;
291                         return f;
292                 }
293         }
294
295         if (!(f = ast_calloc(1, sizeof(*f))))
296                 return NULL;
297
298         f->mallocd_hdr_len = sizeof(*f);
299 #ifdef TRACE_FRAMES
300         AST_LIST_LOCK(&headerlist);
301         headers++;
302         AST_LIST_INSERT_HEAD(&headerlist, f, frame_list);
303         AST_LIST_UNLOCK(&headerlist);
304 #endif  
305         
306         return f;
307 }
308
309 static void frame_cache_cleanup(void *data)
310 {
311         struct ast_frame_cache *frames = data;
312         struct ast_frame *f;
313
314         while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
315                 free(f);
316         
317         free(frames);
318 }
319
320 void ast_frame_free(struct ast_frame *fr, int cache)
321 {
322         if (!fr->mallocd)
323                 return;
324
325         if (cache && fr->mallocd == AST_MALLOCD_HDR) {
326                 /* Cool, only the header is malloc'd, let's just cache those for now 
327                  * to keep things simple... */
328                 struct ast_frame_cache *frames;
329
330                 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) 
331                     && frames->size < FRAME_CACHE_MAX_SIZE) {
332                         AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
333                         frames->size++;
334                         return;
335                 }
336         }
337         
338         if (fr->mallocd & AST_MALLOCD_DATA) {
339                 if (fr->data) 
340                         free(fr->data - fr->offset);
341         }
342         if (fr->mallocd & AST_MALLOCD_SRC) {
343                 if (fr->src)
344                         free((char *)fr->src);
345         }
346         if (fr->mallocd & AST_MALLOCD_HDR) {
347 #ifdef TRACE_FRAMES
348                 AST_LIST_LOCK(&headerlist);
349                 headers--;
350                 AST_LIST_REMOVE(&headerlist, fr, frame_list);
351                 AST_LIST_UNLOCK(&headerlist);
352 #endif                  
353                 free(fr);
354         }
355 }
356
357 /*!
358  * \brief 'isolates' a frame by duplicating non-malloc'ed components
359  * (header, src, data).
360  * On return all components are malloc'ed
361  */
362 struct ast_frame *ast_frisolate(struct ast_frame *fr)
363 {
364         struct ast_frame *out;
365         void *newdata;
366         
367         if (!(fr->mallocd & AST_MALLOCD_HDR)) {
368                 /* Allocate a new header if needed */
369                 if (!(out = ast_frame_header_new()))
370                         return NULL;
371                 out->frametype = fr->frametype;
372                 out->subclass = fr->subclass;
373                 out->datalen = fr->datalen;
374                 out->samples = fr->samples;
375                 out->offset = fr->offset;
376                 out->data = fr->data;
377                 /* Copy the timing data */
378                 out->has_timing_info = fr->has_timing_info;
379                 if (fr->has_timing_info) {
380                         out->ts = fr->ts;
381                         out->len = fr->len;
382                         out->seqno = fr->seqno;
383                 }
384         } else
385                 out = fr;
386         
387         if (!(fr->mallocd & AST_MALLOCD_SRC)) {
388                 if (fr->src) {
389                         if (!(out->src = ast_strdup(fr->src))) {
390                                 if (out != fr)
391                                         free(out);
392                                 return NULL;
393                         }
394                 }
395         } else
396                 out->src = fr->src;
397         
398         if (!(fr->mallocd & AST_MALLOCD_DATA))  {
399                 if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
400                         if (out->src != fr->src)
401                                 free((void *) out->src);
402                         if (out != fr)
403                                 free(out);
404                         return NULL;
405                 }
406                 newdata += AST_FRIENDLY_OFFSET;
407                 out->offset = AST_FRIENDLY_OFFSET;
408                 out->datalen = fr->datalen;
409                 memcpy(newdata, fr->data, fr->datalen);
410                 out->data = newdata;
411         }
412
413         out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
414         
415         return out;
416 }
417
418 struct ast_frame *ast_frdup(const struct ast_frame *f)
419 {
420         struct ast_frame_cache *frames;
421         struct ast_frame *out;
422         int len, srclen = 0;
423         void *buf = NULL;
424
425         /* Start with standard stuff */
426         len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
427         /* If we have a source, add space for it */
428         /*
429          * XXX Watch out here - if we receive a src which is not terminated
430          * properly, we can be easily attacked. Should limit the size we deal with.
431          */
432         if (f->src)
433                 srclen = strlen(f->src);
434         if (srclen > 0)
435                 len += srclen + 1;
436         
437         if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
438                 AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
439                         if (out->mallocd_hdr_len >= len) {
440                                 size_t mallocd_len = out->mallocd_hdr_len;
441                                 AST_LIST_REMOVE_CURRENT(&frames->list, frame_list);
442                                 memset(out, 0, sizeof(*out));
443                                 out->mallocd_hdr_len = mallocd_len;
444                                 buf = out;
445                                 frames->size--;
446                                 break;
447                         }
448                 }
449                 AST_LIST_TRAVERSE_SAFE_END
450         }
451         if (!buf) {
452                 if (!(buf = ast_calloc(1, len)))
453                         return NULL;
454                 out = buf;
455                 out->mallocd_hdr_len = len;
456         }
457
458         out->frametype = f->frametype;
459         out->subclass = f->subclass;
460         out->datalen = f->datalen;
461         out->samples = f->samples;
462         out->delivery = f->delivery;
463         /* Set us as having malloc'd header only, so it will eventually
464            get freed. */
465         out->mallocd = AST_MALLOCD_HDR;
466         out->offset = AST_FRIENDLY_OFFSET;
467         if (out->datalen) {
468                 out->data = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
469                 memcpy(out->data, f->data, out->datalen);       
470         }
471         if (srclen > 0) {
472                 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
473                 /* Must have space since we allocated for it */
474                 strcpy((char *)out->src, f->src);
475         }
476         out->has_timing_info = f->has_timing_info;
477         if (f->has_timing_info) {
478                 out->ts = f->ts;
479                 out->len = f->len;
480                 out->seqno = f->seqno;
481         }
482         return out;
483 }
484
485 void ast_swapcopy_samples(void *dst, const void *src, int samples)
486 {
487         int i;
488         unsigned short *dst_s = dst;
489         const unsigned short *src_s = src;
490
491         for (i = 0; i < samples; i++)
492                 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
493 }
494
495
496 struct ast_format_list *ast_get_format_list_index(int index) 
497 {
498         return &AST_FORMAT_LIST[index];
499 }
500
501 struct ast_format_list *ast_get_format_list(size_t *size) 
502 {
503         *size = (sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]));
504         return AST_FORMAT_LIST;
505 }
506
507 char* ast_getformatname(int format)
508 {
509         int x;
510         char *ret = "unknown";
511         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
512                 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
513                         ret = AST_FORMAT_LIST[x].name;
514                         break;
515                 }
516         }
517         return ret;
518 }
519
520 char *ast_getformatname_multiple(char *buf, size_t size, int format)
521 {
522         int x;
523         unsigned len;
524         char *start, *end = buf;
525
526         if (!size)
527                 return buf;
528         snprintf(end, size, "0x%x (", format);
529         len = strlen(end);
530         end += len;
531         size -= len;
532         start = end;
533         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
534                 if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
535                         snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
536                         len = strlen(end);
537                         end += len;
538                         size -= len;
539                 }
540         }
541         if (start == end)
542                 snprintf(start, size, "nothing)");
543         else if (size > 1)
544                 *(end -1) = ')';
545         return buf;
546 }
547
548 static struct ast_codec_alias_table {
549         char *alias;
550         char *realname;
551 } ast_codec_alias_table[] = {
552         { "slinear", "slin"},
553         { "g723.1", "g723"},
554 };
555
556 static const char *ast_expand_codec_alias(const char *in)
557 {
558         int x;
559
560         for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(ast_codec_alias_table[0]); x++) {
561                 if(!strcmp(in,ast_codec_alias_table[x].alias))
562                         return ast_codec_alias_table[x].realname;
563         }
564         return in;
565 }
566
567 int ast_getformatbyname(const char *name)
568 {
569         int x, all, format = 0;
570
571         all = strcasecmp(name, "all") ? 0 : 1;
572         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
573                 if(AST_FORMAT_LIST[x].visible && (all || 
574                           !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
575                           !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
576                         format |= AST_FORMAT_LIST[x].bits;
577                         if(!all)
578                                 break;
579                 }
580         }
581
582         return format;
583 }
584
585 char *ast_codec2str(int codec)
586 {
587         int x;
588         char *ret = "unknown";
589         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
590                 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
591                         ret = AST_FORMAT_LIST[x].desc;
592                         break;
593                 }
594         }
595         return ret;
596 }
597
598 static int show_codecs_deprecated(int fd, int argc, char *argv[])
599 {
600         int i, found=0;
601         char hex[25];
602         
603         if ((argc < 2) || (argc > 3))
604                 return RESULT_SHOWUSAGE;
605
606         if (!ast_opt_dont_warn)
607                 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
608                                 "\tIt does not indicate anything about your configuration.\n");
609
610         ast_cli(fd, "%11s %9s %10s   TYPE   %8s   %s\n","INT","BINARY","HEX","NAME","DESC");
611         ast_cli(fd, "--------------------------------------------------------------------------------\n");
612         if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
613                 found = 1;
614                 for (i=0;i<12;i++) {
615                         snprintf(hex,25,"(0x%x)",1<<i);
616                         ast_cli(fd, "%11u (1 << %2d) %10s  audio   %8s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
617                 }
618         }
619
620         if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
621                 found = 1;
622                 for (i=16;i<18;i++) {
623                         snprintf(hex,25,"(0x%x)",1<<i);
624                         ast_cli(fd, "%11u (1 << %2d) %10s  image   %8s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
625                 }
626         }
627
628         if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
629                 found = 1;
630                 for (i=18;i<22;i++) {
631                         snprintf(hex,25,"(0x%x)",1<<i);
632                         ast_cli(fd, "%11u (1 << %2d) %10s  video   %8s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
633                 }
634         }
635
636         if (! found)
637                 return RESULT_SHOWUSAGE;
638         else
639                 return RESULT_SUCCESS;
640 }
641
642 static int show_codecs(int fd, int argc, char *argv[])
643 {
644         int i, found=0;
645         char hex[25];
646         
647         if ((argc < 3) || (argc > 4))
648                 return RESULT_SHOWUSAGE;
649
650         if (!ast_opt_dont_warn)
651                 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
652                                 "\tIt does not indicate anything about your configuration.\n");
653
654         ast_cli(fd, "%11s %9s %10s   TYPE   %8s   %s\n","INT","BINARY","HEX","NAME","DESC");
655         ast_cli(fd, "--------------------------------------------------------------------------------\n");
656         if ((argc == 3) || (!strcasecmp(argv[3],"audio"))) {
657                 found = 1;
658                 for (i=0;i<12;i++) {
659                         snprintf(hex,25,"(0x%x)",1<<i);
660                         ast_cli(fd, "%11u (1 << %2d) %10s  audio   %8s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
661                 }
662         }
663
664         if ((argc == 3) || (!strcasecmp(argv[3],"image"))) {
665                 found = 1;
666                 for (i=16;i<18;i++) {
667                         snprintf(hex,25,"(0x%x)",1<<i);
668                         ast_cli(fd, "%11u (1 << %2d) %10s  image   %8s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
669                 }
670         }
671
672         if ((argc == 3) || (!strcasecmp(argv[3],"video"))) {
673                 found = 1;
674                 for (i=18;i<22;i++) {
675                         snprintf(hex,25,"(0x%x)",1<<i);
676                         ast_cli(fd, "%11u (1 << %2d) %10s  video   %8s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
677                 }
678         }
679
680         if (! found)
681                 return RESULT_SHOWUSAGE;
682         else
683                 return RESULT_SUCCESS;
684 }
685
686 static char frame_show_codecs_usage[] =
687 "Usage: core list codecs [audio|video|image]\n"
688 "       Displays codec mapping\n";
689
690 static int show_codec_n_deprecated(int fd, int argc, char *argv[])
691 {
692         int codec, i, found=0;
693
694         if (argc != 3)
695                 return RESULT_SHOWUSAGE;
696
697         if (sscanf(argv[2],"%d",&codec) != 1)
698                 return RESULT_SHOWUSAGE;
699
700         for (i = 0; i < 32; i++)
701                 if (codec & (1 << i)) {
702                         found = 1;
703                         ast_cli(fd, "%11u (1 << %2d)  %s\n",1 << i,i,ast_codec2str(1<<i));
704                 }
705
706         if (!found)
707                 ast_cli(fd, "Codec %d not found\n", codec);
708
709         return RESULT_SUCCESS;
710 }
711
712 static int show_codec_n(int fd, int argc, char *argv[])
713 {
714         int codec, i, found=0;
715
716         if (argc != 4)
717                 return RESULT_SHOWUSAGE;
718
719         if (sscanf(argv[3],"%d",&codec) != 1)
720                 return RESULT_SHOWUSAGE;
721
722         for (i = 0; i < 32; i++)
723                 if (codec & (1 << i)) {
724                         found = 1;
725                         ast_cli(fd, "%11u (1 << %2d)  %s\n",1 << i,i,ast_codec2str(1<<i));
726                 }
727
728         if (!found)
729                 ast_cli(fd, "Codec %d not found\n", codec);
730
731         return RESULT_SUCCESS;
732 }
733
734 static char frame_show_codec_n_usage[] =
735 "Usage: core show codec <number>\n"
736 "       Displays codec mapping\n";
737
738 /*! Dump a frame for debugging purposes */
739 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
740 {
741         const char noname[] = "unknown";
742         char ftype[40] = "Unknown Frametype";
743         char cft[80];
744         char subclass[40] = "Unknown Subclass";
745         char csub[80];
746         char moreinfo[40] = "";
747         char cn[60];
748         char cp[40];
749         char cmn[40];
750
751         if (!name)
752                 name = noname;
753
754
755         if (!f) {
756                 ast_verbose("%s [ %s (NULL) ] [%s]\n", 
757                         term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
758                         term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)), 
759                         term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
760                 return;
761         }
762         /* XXX We should probably print one each of voice and video when the format changes XXX */
763         if (f->frametype == AST_FRAME_VOICE)
764                 return;
765         if (f->frametype == AST_FRAME_VIDEO)
766                 return;
767         switch(f->frametype) {
768         case AST_FRAME_DTMF_BEGIN:
769                 strcpy(ftype, "DTMF Begin");
770                 subclass[0] = f->subclass;
771                 subclass[1] = '\0';
772                 break;
773         case AST_FRAME_DTMF_END:
774                 strcpy(ftype, "DTMF End");
775                 subclass[0] = f->subclass;
776                 subclass[1] = '\0';
777                 break;
778         case AST_FRAME_CONTROL:
779                 strcpy(ftype, "Control");
780                 switch(f->subclass) {
781                 case AST_CONTROL_HANGUP:
782                         strcpy(subclass, "Hangup");
783                         break;
784                 case AST_CONTROL_RING:
785                         strcpy(subclass, "Ring");
786                         break;
787                 case AST_CONTROL_RINGING:
788                         strcpy(subclass, "Ringing");
789                         break;
790                 case AST_CONTROL_ANSWER:
791                         strcpy(subclass, "Answer");
792                         break;
793                 case AST_CONTROL_BUSY:
794                         strcpy(subclass, "Busy");
795                         break;
796                 case AST_CONTROL_TAKEOFFHOOK:
797                         strcpy(subclass, "Take Off Hook");
798                         break;
799                 case AST_CONTROL_OFFHOOK:
800                         strcpy(subclass, "Line Off Hook");
801                         break;
802                 case AST_CONTROL_CONGESTION:
803                         strcpy(subclass, "Congestion");
804                         break;
805                 case AST_CONTROL_FLASH:
806                         strcpy(subclass, "Flash");
807                         break;
808                 case AST_CONTROL_WINK:
809                         strcpy(subclass, "Wink");
810                         break;
811                 case AST_CONTROL_OPTION:
812                         strcpy(subclass, "Option");
813                         break;
814                 case AST_CONTROL_RADIO_KEY:
815                         strcpy(subclass, "Key Radio");
816                         break;
817                 case AST_CONTROL_RADIO_UNKEY:
818                         strcpy(subclass, "Unkey Radio");
819                         break;
820                 case -1:
821                         strcpy(subclass, "Stop generators");
822                         break;
823                 default:
824                         snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
825                 }
826                 break;
827         case AST_FRAME_NULL:
828                 strcpy(ftype, "Null Frame");
829                 strcpy(subclass, "N/A");
830                 break;
831         case AST_FRAME_IAX:
832                 /* Should never happen */
833                 strcpy(ftype, "IAX Specific");
834                 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
835                 break;
836         case AST_FRAME_TEXT:
837                 strcpy(ftype, "Text");
838                 strcpy(subclass, "N/A");
839                 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
840                 break;
841         case AST_FRAME_IMAGE:
842                 strcpy(ftype, "Image");
843                 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
844                 break;
845         case AST_FRAME_HTML:
846                 strcpy(ftype, "HTML");
847                 switch(f->subclass) {
848                 case AST_HTML_URL:
849                         strcpy(subclass, "URL");
850                         ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
851                         break;
852                 case AST_HTML_DATA:
853                         strcpy(subclass, "Data");
854                         break;
855                 case AST_HTML_BEGIN:
856                         strcpy(subclass, "Begin");
857                         break;
858                 case AST_HTML_END:
859                         strcpy(subclass, "End");
860                         break;
861                 case AST_HTML_LDCOMPLETE:
862                         strcpy(subclass, "Load Complete");
863                         break;
864                 case AST_HTML_NOSUPPORT:
865                         strcpy(subclass, "No Support");
866                         break;
867                 case AST_HTML_LINKURL:
868                         strcpy(subclass, "Link URL");
869                         ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
870                         break;
871                 case AST_HTML_UNLINK:
872                         strcpy(subclass, "Unlink");
873                         break;
874                 case AST_HTML_LINKREJECT:
875                         strcpy(subclass, "Link Reject");
876                         break;
877                 default:
878                         snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
879                         break;
880                 }
881                 break;
882         case AST_FRAME_MODEM:
883                 strcpy(ftype, "Modem");
884                 switch (f->subclass) {
885                 case AST_MODEM_T38:
886                         strcpy(subclass, "T.38");
887                         break;
888                 case AST_MODEM_V150:
889                         strcpy(subclass, "V.150");
890                         break;
891                 default:
892                         snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
893                         break;
894                 }
895                 break;
896         default:
897                 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
898         }
899         if (!ast_strlen_zero(moreinfo))
900                 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",  
901                             term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
902                             term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
903                             f->frametype, 
904                             term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
905                             f->subclass, 
906                             term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
907                             term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
908         else
909                 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",  
910                             term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
911                             term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
912                             f->frametype, 
913                             term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
914                             f->subclass, 
915                             term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
916 }
917
918
919 #ifdef TRACE_FRAMES
920 static int show_frame_stats_deprecated(int fd, int argc, char *argv[])
921 {
922         struct ast_frame *f;
923         int x=1;
924         if (argc != 3)
925                 return RESULT_SHOWUSAGE;
926         AST_LIST_LOCK(&headerlist);
927         ast_cli(fd, "     Framer Statistics     \n");
928         ast_cli(fd, "---------------------------\n");
929         ast_cli(fd, "Total allocated headers: %d\n", headers);
930         ast_cli(fd, "Queue Dump:\n");
931         AST_LIST_TRAVERSE(&headerlist, f, frame_list)
932                 ast_cli(fd, "%d.  Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
933         AST_LIST_UNLOCK(&headerlist);
934         return RESULT_SUCCESS;
935 }
936
937 static int show_frame_stats(int fd, int argc, char *argv[])
938 {
939         struct ast_frame *f;
940         int x=1;
941         if (argc != 4)
942                 return RESULT_SHOWUSAGE;
943         AST_LIST_LOCK(&headerlist);
944         ast_cli(fd, "     Framer Statistics     \n");
945         ast_cli(fd, "---------------------------\n");
946         ast_cli(fd, "Total allocated headers: %d\n", headers);
947         ast_cli(fd, "Queue Dump:\n");
948         AST_LIST_TRAVERSE(&headerlist, f, frame_list)
949                 ast_cli(fd, "%d.  Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
950         AST_LIST_UNLOCK(&headerlist);
951         return RESULT_SUCCESS;
952 }
953
954 static char frame_stats_usage[] =
955 "Usage: core show frame stats\n"
956 "       Displays debugging statistics from framer\n";
957 #endif
958
959 /* Builtin Asterisk CLI-commands for debugging */
960 static struct ast_cli_entry cli_show_codecs = {
961         { "show", "codecs", NULL },
962         show_codecs_deprecated, NULL,
963         NULL };
964
965 static struct ast_cli_entry cli_show_audio_codecs = {
966         { "show", "audio", "codecs", NULL },
967         show_codecs_deprecated, NULL,
968         NULL };
969
970 static struct ast_cli_entry cli_show_video_codecs = {
971         { "show", "video", "codecs", NULL },
972         show_codecs_deprecated, NULL,
973         NULL };
974
975 static struct ast_cli_entry cli_show_image_codecs = {
976         { "show", "image", "codecs", NULL },
977         show_codecs_deprecated, NULL,
978         NULL };
979
980 static struct ast_cli_entry cli_show_codec = {
981         { "show", "codec", NULL },
982         show_codec_n_deprecated, NULL,
983         NULL };
984
985 #ifdef TRACE_FRAMES
986 static struct ast_cli_entry cli_show_frame_stats = {
987         { "show", "frame", "stats", NULL },
988         show_frame_stats, NULL,
989         NULL };
990 #endif
991
992 static struct ast_cli_entry my_clis[] = {
993         { { "core", "list", "codecs", NULL },
994         show_codecs, "Displays a list of codecs",
995         frame_show_codecs_usage, NULL, &cli_show_codecs },
996
997         { { "core", "list", "codecs", "audio", NULL },
998         show_codecs, "Displays a list of audio codecs",
999         frame_show_codecs_usage, NULL, &cli_show_audio_codecs },
1000
1001         { { "core", "list", "codecs", "video", NULL },
1002         show_codecs, "Displays a list of video codecs",
1003         frame_show_codecs_usage, NULL, &cli_show_video_codecs },
1004
1005         { { "core", "list", "codecs", "image", NULL },
1006         show_codecs, "Displays a list of image codecs",
1007         frame_show_codecs_usage, NULL, &cli_show_image_codecs },
1008
1009         { { "core", "show", "codec", NULL },
1010         show_codec_n, "Shows a specific codec",
1011         frame_show_codec_n_usage, NULL, &cli_show_codec },
1012
1013 #ifdef TRACE_FRAMES
1014         { { "core", "show", "frame", "stats", NULL },
1015         show_frame_stats, "Shows frame statistics",
1016         frame_stats_usage, NULL, &cli_show_frame_stats },
1017 #endif
1018 };
1019
1020 int init_framer(void)
1021 {
1022         ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
1023         return 0;       
1024 }
1025
1026 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right) 
1027 {
1028         int x, differential = (int) 'A', mem;
1029         char *from, *to;
1030
1031         if(right) {
1032                 from = pref->order;
1033                 to = buf;
1034                 mem = size;
1035         } else {
1036                 to = pref->order;
1037                 from = buf;
1038                 mem = 32;
1039         }
1040
1041         memset(to, 0, mem);
1042         for (x = 0; x < 32 ; x++) {
1043                 if(!from[x])
1044                         break;
1045                 to[x] = right ? (from[x] + differential) : (from[x] - differential);
1046         }
1047 }
1048
1049 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size) 
1050 {
1051         int x, codec; 
1052         size_t total_len, slen;
1053         char *formatname;
1054         
1055         memset(buf,0,size);
1056         total_len = size;
1057         buf[0] = '(';
1058         total_len--;
1059         for(x = 0; x < 32 ; x++) {
1060                 if(total_len <= 0)
1061                         break;
1062                 if(!(codec = ast_codec_pref_index(pref,x)))
1063                         break;
1064                 if((formatname = ast_getformatname(codec))) {
1065                         slen = strlen(formatname);
1066                         if(slen > total_len)
1067                                 break;
1068                         strncat(buf,formatname,total_len);
1069                         total_len -= slen;
1070                 }
1071                 if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
1072                         strncat(buf,"|",total_len);
1073                         total_len--;
1074                 }
1075         }
1076         if(total_len) {
1077                 strncat(buf,")",total_len);
1078                 total_len--;
1079         }
1080
1081         return size - total_len;
1082 }
1083
1084 int ast_codec_pref_index(struct ast_codec_pref *pref, int index) 
1085 {
1086         int slot = 0;
1087
1088         
1089         if((index >= 0) && (index < sizeof(pref->order))) {
1090                 slot = pref->order[index];
1091         }
1092
1093         return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
1094 }
1095
1096 /*! \brief Remove codec from pref list */
1097 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
1098 {
1099         struct ast_codec_pref oldorder;
1100         int x, y = 0;
1101         int slot;
1102         int size;
1103
1104         if(!pref->order[0])
1105                 return;
1106
1107         memcpy(&oldorder, pref, sizeof(oldorder));
1108         memset(pref, 0, sizeof(*pref));
1109
1110         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1111                 slot = oldorder.order[x];
1112                 size = oldorder.framing[x];
1113                 if(! slot)
1114                         break;
1115                 if(AST_FORMAT_LIST[slot-1].bits != format) {
1116                         pref->order[y] = slot;
1117                         pref->framing[y++] = size;
1118                 }
1119         }
1120         
1121 }
1122
1123 /*! \brief Append codec to list */
1124 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
1125 {
1126         int x, newindex = -1;
1127
1128         ast_codec_pref_remove(pref, format);
1129
1130         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1131                 if(AST_FORMAT_LIST[x].bits == format) {
1132                         newindex = x + 1;
1133                         break;
1134                 }
1135         }
1136
1137         if(newindex) {
1138                 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1139                         if(!pref->order[x]) {
1140                                 pref->order[x] = newindex;
1141                                 break;
1142                         }
1143                 }
1144         }
1145
1146         return x;
1147 }
1148
1149
1150 /*! \brief Set packet size for codec */
1151 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
1152 {
1153         int x, index = -1;
1154
1155         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1156                 if(AST_FORMAT_LIST[x].bits == format) {
1157                         index = x;
1158                         break;
1159                 }
1160         }
1161
1162         if(index < 0)
1163                 return -1;
1164
1165         /* size validation */
1166         if(!framems)
1167                 framems = AST_FORMAT_LIST[index].def_ms;
1168
1169         if(AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1170                 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1171
1172         if(framems < AST_FORMAT_LIST[index].min_ms)
1173                 framems = AST_FORMAT_LIST[index].min_ms;
1174
1175         if(framems > AST_FORMAT_LIST[index].max_ms)
1176                 framems = AST_FORMAT_LIST[index].max_ms;
1177
1178
1179         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1180                 if(pref->order[x] == (index + 1)) {
1181                         pref->framing[x] = framems;
1182                         break;
1183                 }
1184         }
1185
1186         return x;
1187 }
1188
1189 /*! \brief Get packet size for codec */
1190 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
1191 {
1192         int x, index = -1, framems = 0;
1193         struct ast_format_list fmt;
1194
1195         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1196                 if(AST_FORMAT_LIST[x].bits == format) {
1197                         fmt = AST_FORMAT_LIST[x];
1198                         index = x;
1199                         break;
1200                 }
1201         }
1202
1203         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1204                 if(pref->order[x] == (index + 1)) {
1205                         framems = pref->framing[x];
1206                         break;
1207                 }
1208         }
1209
1210         /* size validation */
1211         if(!framems)
1212                 framems = AST_FORMAT_LIST[index].def_ms;
1213
1214         if(AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1215                 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1216
1217         if(framems < AST_FORMAT_LIST[index].min_ms)
1218                 framems = AST_FORMAT_LIST[index].min_ms;
1219
1220         if(framems > AST_FORMAT_LIST[index].max_ms)
1221                 framems = AST_FORMAT_LIST[index].max_ms;
1222
1223         fmt.cur_ms = framems;
1224
1225         return fmt;
1226 }
1227
1228 /*! \brief Pick a codec */
1229 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
1230 {
1231         int x, ret = 0, slot;
1232
1233         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1234                 slot = pref->order[x];
1235
1236                 if (!slot)
1237                         break;
1238                 if (formats & AST_FORMAT_LIST[slot-1].bits) {
1239                         ret = AST_FORMAT_LIST[slot-1].bits;
1240                         break;
1241                 }
1242         }
1243         if(ret & AST_FORMAT_AUDIO_MASK)
1244                 return ret;
1245
1246         if (option_debug > 3)
1247                 ast_log(LOG_DEBUG, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1248
1249         return find_best ? ast_best_codec(formats) : 0;
1250 }
1251
1252 void ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing) 
1253 {
1254         char *parse = NULL, *this = NULL, *psize = NULL;
1255         int format = 0, framems = 0;
1256
1257         parse = ast_strdupa(list);
1258         while ((this = strsep(&parse, ","))) {
1259                 framems = 0;
1260                 if ((psize = strrchr(this, ':'))) {
1261                         *psize++ = '\0';
1262                         if (option_debug)
1263                                 ast_log(LOG_DEBUG,"Packetization for codec: %s is %s\n", this, psize);
1264                         framems = atoi(psize);
1265                         if (framems < 0)
1266                                 framems = 0;
1267                 }
1268                 if (!(format = ast_getformatbyname(this))) {
1269                         ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1270                         continue;
1271                 }
1272
1273                 if (mask) {
1274                         if (allowing)
1275                                 *mask |= format;
1276                         else
1277                                 *mask &= ~format;
1278                 }
1279
1280                 /* Set up a preference list for audio. Do not include video in preferences 
1281                    since we can not transcode video and have to use whatever is offered
1282                  */
1283                 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1284                         if (strcasecmp(this, "all")) {
1285                                 if (allowing) {
1286                                         ast_codec_pref_append(pref, format);
1287                                         ast_codec_pref_setsize(pref, format, framems);
1288                                 }
1289                                 else
1290                                         ast_codec_pref_remove(pref, format);
1291                         } else if (!allowing) {
1292                                 memset(pref, 0, sizeof(*pref));
1293                         }
1294                 }
1295         }
1296 }
1297
1298 static int g723_len(unsigned char buf)
1299 {
1300         enum frame_type type = buf & TYPE_MASK;
1301
1302         switch(type) {
1303         case TYPE_DONTSEND:
1304                 return 0;
1305                 break;
1306         case TYPE_SILENCE:
1307                 return 4;
1308                 break;
1309         case TYPE_HIGH:
1310                 return 24;
1311                 break;
1312         case TYPE_LOW:
1313                 return 20;
1314                 break;
1315         default:
1316                 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
1317         }
1318         return -1;
1319 }
1320
1321 static int g723_samples(unsigned char *buf, int maxlen)
1322 {
1323         int pos = 0;
1324         int samples = 0;
1325         int res;
1326         while(pos < maxlen) {
1327                 res = g723_len(buf[pos]);
1328                 if (res <= 0)
1329                         break;
1330                 samples += 240;
1331                 pos += res;
1332         }
1333         return samples;
1334 }
1335
1336 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1337 {
1338         int byte = bit / 8;       /* byte containing first bit */
1339         int rem = 8 - (bit % 8);  /* remaining bits in first byte */
1340         unsigned char ret = 0;
1341         
1342         if (n <= 0 || n > 8)
1343                 return 0;
1344
1345         if (rem < n) {
1346                 ret = (data[byte] << (n - rem));
1347                 ret |= (data[byte + 1] >> (8 - n + rem));
1348         } else {
1349                 ret = (data[byte] >> (rem - n));
1350         }
1351
1352         return (ret & (0xff >> (8 - n)));
1353 }
1354
1355 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1356 {
1357         static int SpeexWBSubModeSz[] = {
1358                 0, 36, 112, 192,
1359                 352, 0, 0, 0 };
1360         int off = bit;
1361         unsigned char c;
1362
1363         /* skip up to two wideband frames */
1364         if (((len * 8 - off) >= 5) && 
1365                 get_n_bits_at(data, 1, off)) {
1366                 c = get_n_bits_at(data, 3, off + 1);
1367                 off += SpeexWBSubModeSz[c];
1368
1369                 if (((len * 8 - off) >= 5) && 
1370                         get_n_bits_at(data, 1, off)) {
1371                         c = get_n_bits_at(data, 3, off + 1);
1372                         off += SpeexWBSubModeSz[c];
1373
1374                         if (((len * 8 - off) >= 5) && 
1375                                 get_n_bits_at(data, 1, off)) {
1376                                 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1377                                 return -1;
1378                         }
1379                 }
1380
1381         }
1382         return off - bit;
1383 }
1384
1385 static int speex_samples(unsigned char *data, int len)
1386 {
1387         static int SpeexSubModeSz[] = {
1388                5, 43, 119, 160,
1389                 220, 300, 364, 492, 
1390                 79, 0, 0, 0,
1391                 0, 0, 0, 0 };
1392         static int SpeexInBandSz[] = { 
1393                 1, 1, 4, 4,
1394                 4, 4, 4, 4,
1395                 8, 8, 16, 16,
1396                 32, 32, 64, 64 };
1397         int bit = 0;
1398         int cnt = 0;
1399         int off;
1400         unsigned char c;
1401
1402         while ((len * 8 - bit) >= 5) {
1403                 /* skip wideband frames */
1404                 off = speex_get_wb_sz_at(data, len, bit);
1405                 if (off < 0)  {
1406                         ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1407                         break;
1408                 }
1409                 bit += off;
1410
1411                 if ((len * 8 - bit) < 5) {
1412                         ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1413                         break;
1414                 }
1415
1416                 /* get control bits */
1417                 c = get_n_bits_at(data, 5, bit);
1418                 bit += 5;
1419
1420                 if (c == 15) { 
1421                         /* terminator */
1422                         break; 
1423                 } else if (c == 14) {
1424                         /* in-band signal; next 4 bits contain signal id */
1425                         c = get_n_bits_at(data, 4, bit);
1426                         bit += 4;
1427                         bit += SpeexInBandSz[c];
1428                 } else if (c == 13) {
1429                         /* user in-band; next 5 bits contain msg len */
1430                         c = get_n_bits_at(data, 5, bit);
1431                         bit += 5;
1432                         bit += c * 8;
1433                 } else if (c > 8) {
1434                         /* unknown */
1435                         break;
1436                 } else {
1437                         /* skip number bits for submode (less the 5 control bits) */
1438                         bit += SpeexSubModeSz[c] - 5;
1439                         cnt += 160; /* new frame */
1440                 }
1441         }
1442         return cnt;
1443 }
1444
1445 int ast_codec_get_samples(struct ast_frame *f)
1446 {
1447         int samples=0;
1448         switch(f->subclass) {
1449         case AST_FORMAT_SPEEX:
1450                 samples = speex_samples(f->data, f->datalen);
1451                 break;
1452         case AST_FORMAT_G723_1:
1453                 samples = g723_samples(f->data, f->datalen);
1454                 break;
1455         case AST_FORMAT_ILBC:
1456                 samples = 240 * (f->datalen / 50);
1457                 break;
1458         case AST_FORMAT_GSM:
1459                 samples = 160 * (f->datalen / 33);
1460                 break;
1461         case AST_FORMAT_G729A:
1462                 samples = f->datalen * 8;
1463                 break;
1464         case AST_FORMAT_SLINEAR:
1465                 samples = f->datalen / 2;
1466                 break;
1467         case AST_FORMAT_LPC10:
1468                 /* assumes that the RTP packet contains one LPC10 frame */
1469                 samples = 22 * 8;
1470                 samples += (((char *)(f->data))[7] & 0x1) * 8;
1471                 break;
1472         case AST_FORMAT_ULAW:
1473         case AST_FORMAT_ALAW:
1474                 samples = f->datalen;
1475                 break;
1476         case AST_FORMAT_ADPCM:
1477         case AST_FORMAT_G726:
1478         case AST_FORMAT_G726_AAL2:
1479                 samples = f->datalen * 2;
1480                 break;
1481         default:
1482                 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1483         }
1484         return samples;
1485 }
1486
1487 int ast_codec_get_len(int format, int samples)
1488 {
1489         int len = 0;
1490
1491         /* XXX Still need speex, g723, and lpc10 XXX */ 
1492         switch(format) {
1493         case AST_FORMAT_ILBC:
1494                 len = (samples / 240) * 50;
1495                 break;
1496         case AST_FORMAT_GSM:
1497                 len = (samples / 160) * 33;
1498                 break;
1499         case AST_FORMAT_G729A:
1500                 len = samples / 8;
1501                 break;
1502         case AST_FORMAT_SLINEAR:
1503                 len = samples * 2;
1504                 break;
1505         case AST_FORMAT_ULAW:
1506         case AST_FORMAT_ALAW:
1507                 len = samples;
1508                 break;
1509         case AST_FORMAT_ADPCM:
1510         case AST_FORMAT_G726:
1511         case AST_FORMAT_G726_AAL2:
1512                 len = samples / 2;
1513                 break;
1514         default:
1515                 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1516         }
1517
1518         return len;
1519 }
1520
1521 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1522 {
1523         int count;
1524         short *fdata = f->data;
1525         short adjust_value = abs(adjustment);
1526
1527         if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
1528                 return -1;
1529
1530         if (!adjustment)
1531                 return 0;
1532
1533         for (count = 0; count < f->samples; count++) {
1534                 if (adjustment > 0) {
1535                         ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1536                 } else if (adjustment < 0) {
1537                         ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1538                 }
1539         }
1540
1541         return 0;
1542 }
1543
1544 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1545 {
1546         int count;
1547         short *data1, *data2;
1548
1549         if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
1550                 return -1;
1551
1552         if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
1553                 return -1;
1554
1555         if (f1->samples != f2->samples)
1556                 return -1;
1557
1558         for (count = 0, data1 = f1->data, data2 = f2->data;
1559              count < f1->samples;
1560              count++, data1++, data2++)
1561                 ast_slinear_saturated_add(data1, data2);
1562
1563         return 0;
1564 }