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