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