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