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