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