Issue 9869 - replace malloc and memset with ast_calloc, and other coding guidelines...
[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", "audio", "codecs", NULL },
908         show_codecs, "Displays a list of audio codecs",
909         frame_show_codecs_usage },
910
911         { { "core", "show", "video", "codecs", NULL },
912         show_codecs, "Displays a list of video codecs",
913         frame_show_codecs_usage },
914
915         { { "core", "show", "image", "codecs", 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         if (option_debug > 3)
1157                 ast_log(LOG_DEBUG, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1158
1159         return find_best ? ast_best_codec(formats) : 0;
1160 }
1161
1162 int ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing) 
1163 {
1164         int errors = 0;
1165         char *parse = NULL, *this = NULL, *psize = NULL;
1166         int format = 0, framems = 0;
1167
1168         parse = ast_strdupa(list);
1169         while ((this = strsep(&parse, ","))) {
1170                 framems = 0;
1171                 if ((psize = strrchr(this, ':'))) {
1172                         *psize++ = '\0';
1173                         if (option_debug)
1174                                 ast_log(LOG_DEBUG,"Packetization for codec: %s is %s\n", this, psize);
1175                         framems = atoi(psize);
1176                         if (framems < 0) {
1177                                 framems = 0;
1178                                 errors++;
1179                                 ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
1180                         }
1181                 }
1182                 if (!(format = ast_getformatbyname(this))) {
1183                         ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1184                         errors++;
1185                         continue;
1186                 }
1187
1188                 if (mask) {
1189                         if (allowing)
1190                                 *mask |= format;
1191                         else
1192                                 *mask &= ~format;
1193                 }
1194
1195                 /* Set up a preference list for audio. Do not include video in preferences 
1196                    since we can not transcode video and have to use whatever is offered
1197                  */
1198                 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1199                         if (strcasecmp(this, "all")) {
1200                                 if (allowing) {
1201                                         ast_codec_pref_append(pref, format);
1202                                         ast_codec_pref_setsize(pref, format, framems);
1203                                 }
1204                                 else
1205                                         ast_codec_pref_remove(pref, format);
1206                         } else if (!allowing) {
1207                                 memset(pref, 0, sizeof(*pref));
1208                         }
1209                 }
1210         }
1211         return errors;
1212 }
1213
1214 static int g723_len(unsigned char buf)
1215 {
1216         enum frame_type type = buf & TYPE_MASK;
1217
1218         switch(type) {
1219         case TYPE_DONTSEND:
1220                 return 0;
1221                 break;
1222         case TYPE_SILENCE:
1223                 return 4;
1224                 break;
1225         case TYPE_HIGH:
1226                 return 24;
1227                 break;
1228         case TYPE_LOW:
1229                 return 20;
1230                 break;
1231         default:
1232                 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
1233         }
1234         return -1;
1235 }
1236
1237 static int g723_samples(unsigned char *buf, int maxlen)
1238 {
1239         int pos = 0;
1240         int samples = 0;
1241         int res;
1242         while(pos < maxlen) {
1243                 res = g723_len(buf[pos]);
1244                 if (res <= 0)
1245                         break;
1246                 samples += 240;
1247                 pos += res;
1248         }
1249         return samples;
1250 }
1251
1252 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1253 {
1254         int byte = bit / 8;       /* byte containing first bit */
1255         int rem = 8 - (bit % 8);  /* remaining bits in first byte */
1256         unsigned char ret = 0;
1257         
1258         if (n <= 0 || n > 8)
1259                 return 0;
1260
1261         if (rem < n) {
1262                 ret = (data[byte] << (n - rem));
1263                 ret |= (data[byte + 1] >> (8 - n + rem));
1264         } else {
1265                 ret = (data[byte] >> (rem - n));
1266         }
1267
1268         return (ret & (0xff >> (8 - n)));
1269 }
1270
1271 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1272 {
1273         static int SpeexWBSubModeSz[] = {
1274                 0, 36, 112, 192,
1275                 352, 0, 0, 0 };
1276         int off = bit;
1277         unsigned char c;
1278
1279         /* skip up to two wideband frames */
1280         if (((len * 8 - off) >= 5) && 
1281                 get_n_bits_at(data, 1, off)) {
1282                 c = get_n_bits_at(data, 3, off + 1);
1283                 off += SpeexWBSubModeSz[c];
1284
1285                 if (((len * 8 - off) >= 5) && 
1286                         get_n_bits_at(data, 1, off)) {
1287                         c = get_n_bits_at(data, 3, off + 1);
1288                         off += SpeexWBSubModeSz[c];
1289
1290                         if (((len * 8 - off) >= 5) && 
1291                                 get_n_bits_at(data, 1, off)) {
1292                                 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1293                                 return -1;
1294                         }
1295                 }
1296
1297         }
1298         return off - bit;
1299 }
1300
1301 static int speex_samples(unsigned char *data, int len)
1302 {
1303         static int SpeexSubModeSz[] = {
1304                5, 43, 119, 160,
1305                 220, 300, 364, 492, 
1306                 79, 0, 0, 0,
1307                 0, 0, 0, 0 };
1308         static int SpeexInBandSz[] = { 
1309                 1, 1, 4, 4,
1310                 4, 4, 4, 4,
1311                 8, 8, 16, 16,
1312                 32, 32, 64, 64 };
1313         int bit = 0;
1314         int cnt = 0;
1315         int off;
1316         unsigned char c;
1317
1318         while ((len * 8 - bit) >= 5) {
1319                 /* skip wideband frames */
1320                 off = speex_get_wb_sz_at(data, len, bit);
1321                 if (off < 0)  {
1322                         ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1323                         break;
1324                 }
1325                 bit += off;
1326
1327                 if ((len * 8 - bit) < 5) {
1328                         ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1329                         break;
1330                 }
1331
1332                 /* get control bits */
1333                 c = get_n_bits_at(data, 5, bit);
1334                 bit += 5;
1335
1336                 if (c == 15) { 
1337                         /* terminator */
1338                         break; 
1339                 } else if (c == 14) {
1340                         /* in-band signal; next 4 bits contain signal id */
1341                         c = get_n_bits_at(data, 4, bit);
1342                         bit += 4;
1343                         bit += SpeexInBandSz[c];
1344                 } else if (c == 13) {
1345                         /* user in-band; next 5 bits contain msg len */
1346                         c = get_n_bits_at(data, 5, bit);
1347                         bit += 5;
1348                         bit += c * 8;
1349                 } else if (c > 8) {
1350                         /* unknown */
1351                         break;
1352                 } else {
1353                         /* skip number bits for submode (less the 5 control bits) */
1354                         bit += SpeexSubModeSz[c] - 5;
1355                         cnt += 160; /* new frame */
1356                 }
1357         }
1358         return cnt;
1359 }
1360
1361 int ast_codec_get_samples(struct ast_frame *f)
1362 {
1363         int samples=0;
1364         switch(f->subclass) {
1365         case AST_FORMAT_SPEEX:
1366                 samples = speex_samples(f->data, f->datalen);
1367                 break;
1368         case AST_FORMAT_G723_1:
1369                 samples = g723_samples(f->data, f->datalen);
1370                 break;
1371         case AST_FORMAT_ILBC:
1372                 samples = 240 * (f->datalen / 50);
1373                 break;
1374         case AST_FORMAT_GSM:
1375                 samples = 160 * (f->datalen / 33);
1376                 break;
1377         case AST_FORMAT_G729A:
1378                 samples = f->datalen * 8;
1379                 break;
1380         case AST_FORMAT_SLINEAR:
1381                 samples = f->datalen / 2;
1382                 break;
1383         case AST_FORMAT_LPC10:
1384                 /* assumes that the RTP packet contains one LPC10 frame */
1385                 samples = 22 * 8;
1386                 samples += (((char *)(f->data))[7] & 0x1) * 8;
1387                 break;
1388         case AST_FORMAT_ULAW:
1389         case AST_FORMAT_ALAW:
1390         case AST_FORMAT_G722:
1391                 samples = f->datalen;
1392                 break;
1393         case AST_FORMAT_ADPCM:
1394         case AST_FORMAT_G726:
1395         case AST_FORMAT_G726_AAL2:
1396                 samples = f->datalen * 2;
1397                 break;
1398         default:
1399                 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1400         }
1401         return samples;
1402 }
1403
1404 int ast_codec_get_len(int format, int samples)
1405 {
1406         int len = 0;
1407
1408         /* XXX Still need speex, g723, and lpc10 XXX */ 
1409         switch(format) {
1410         case AST_FORMAT_G723_1:
1411                 len = (samples / 240) * 20;
1412                 break;
1413         case AST_FORMAT_ILBC:
1414                 len = (samples / 240) * 50;
1415                 break;
1416         case AST_FORMAT_GSM:
1417                 len = (samples / 160) * 33;
1418                 break;
1419         case AST_FORMAT_G729A:
1420                 len = samples / 8;
1421                 break;
1422         case AST_FORMAT_SLINEAR:
1423                 len = samples * 2;
1424                 break;
1425         case AST_FORMAT_ULAW:
1426         case AST_FORMAT_ALAW:
1427                 len = samples;
1428                 break;
1429         case AST_FORMAT_ADPCM:
1430         case AST_FORMAT_G726:
1431         case AST_FORMAT_G726_AAL2:
1432                 len = samples / 2;
1433                 break;
1434         default:
1435                 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1436         }
1437
1438         return len;
1439 }
1440
1441 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1442 {
1443         int count;
1444         short *fdata = f->data;
1445         short adjust_value = abs(adjustment);
1446
1447         if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
1448                 return -1;
1449
1450         if (!adjustment)
1451                 return 0;
1452
1453         for (count = 0; count < f->samples; count++) {
1454                 if (adjustment > 0) {
1455                         ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1456                 } else if (adjustment < 0) {
1457                         ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1458                 }
1459         }
1460
1461         return 0;
1462 }
1463
1464 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1465 {
1466         int count;
1467         short *data1, *data2;
1468
1469         if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
1470                 return -1;
1471
1472         if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
1473                 return -1;
1474
1475         if (f1->samples != f2->samples)
1476                 return -1;
1477
1478         for (count = 0, data1 = f1->data, data2 = f2->data;
1479              count < f1->samples;
1480              count++, data1++, data2++)
1481                 ast_slinear_saturated_add(data1, data2);
1482
1483         return 0;
1484 }