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