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