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