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