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