move internal function declarations to include/asterisk/_private.h
[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/options.h"
34 #include "asterisk/channel.h"
35 #include "asterisk/cli.h"
36 #include "asterisk/term.h"
37 #include "asterisk/utils.h"
38 #include "asterisk/threadstorage.h"
39 #include "asterisk/linkedlists.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
361 /*!
362  * \brief 'isolates' a frame by duplicating non-malloc'ed components
363  * (header, src, data).
364  * On return all components are malloc'ed
365  */
366 struct ast_frame *ast_frisolate(struct ast_frame *fr)
367 {
368         struct ast_frame *out;
369         void *newdata;
370         
371         if (!(fr->mallocd & AST_MALLOCD_HDR)) {
372                 /* Allocate a new header if needed */
373                 if (!(out = ast_frame_header_new()))
374                         return NULL;
375                 out->frametype = fr->frametype;
376                 out->subclass = fr->subclass;
377                 out->datalen = fr->datalen;
378                 out->samples = fr->samples;
379                 out->offset = fr->offset;
380                 out->data = fr->data;
381                 /* Copy the timing data */
382                 out->has_timing_info = fr->has_timing_info;
383                 if (fr->has_timing_info) {
384                         out->ts = fr->ts;
385                         out->len = fr->len;
386                         out->seqno = fr->seqno;
387                 }
388         } else
389                 out = fr;
390         
391         if (!(fr->mallocd & AST_MALLOCD_SRC)) {
392                 if (fr->src) {
393                         if (!(out->src = ast_strdup(fr->src))) {
394                                 if (out != fr)
395                                         ast_free(out);
396                                 return NULL;
397                         }
398                 }
399         } else
400                 out->src = fr->src;
401         
402         if (!(fr->mallocd & AST_MALLOCD_DATA))  {
403                 if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
404                         if (out->src != fr->src)
405                                 ast_free((void *) out->src);
406                         if (out != fr)
407                                 ast_free(out);
408                         return NULL;
409                 }
410                 newdata += AST_FRIENDLY_OFFSET;
411                 out->offset = AST_FRIENDLY_OFFSET;
412                 out->datalen = fr->datalen;
413                 memcpy(newdata, fr->data, fr->datalen);
414                 out->data = newdata;
415         }
416
417         out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
418         
419         return out;
420 }
421
422 struct ast_frame *ast_frdup(const struct ast_frame *f)
423 {
424         struct ast_frame *out = NULL;
425         int len, srclen = 0;
426         void *buf = NULL;
427
428 #if !defined(LOW_MEMORY)
429         struct ast_frame_cache *frames;
430 #endif
431
432         /* Start with standard stuff */
433         len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
434         /* If we have a source, add space for it */
435         /*
436          * XXX Watch out here - if we receive a src which is not terminated
437          * properly, we can be easily attacked. Should limit the size we deal with.
438          */
439         if (f->src)
440                 srclen = strlen(f->src);
441         if (srclen > 0)
442                 len += srclen + 1;
443         
444 #if !defined(LOW_MEMORY)
445         if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
446                 AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
447                         if (out->mallocd_hdr_len >= len) {
448                                 size_t mallocd_len = out->mallocd_hdr_len;
449
450                                 AST_LIST_REMOVE_CURRENT(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 #endif
461
462         if (!buf) {
463                 if (!(buf = ast_calloc_cache(1, len)))
464                         return NULL;
465                 out = buf;
466                 out->mallocd_hdr_len = len;
467         }
468
469         out->frametype = f->frametype;
470         out->subclass = f->subclass;
471         out->datalen = f->datalen;
472         out->samples = f->samples;
473         out->delivery = f->delivery;
474         /* Set us as having malloc'd header only, so it will eventually
475            get freed. */
476         out->mallocd = AST_MALLOCD_HDR;
477         out->offset = AST_FRIENDLY_OFFSET;
478         if (out->datalen) {
479                 out->data = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
480                 memcpy(out->data, f->data, out->datalen);       
481         }
482         if (srclen > 0) {
483                 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
484                 /* Must have space since we allocated for it */
485                 strcpy((char *)out->src, f->src);
486         }
487         out->has_timing_info = f->has_timing_info;
488         out->ts = f->ts;
489         out->len = f->len;
490         out->seqno = f->seqno;
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].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].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                 ast_copy_string(start, "nothing)", size);
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         { "slinear16", "slin16"},
563         { "g723.1", "g723"},
564 };
565
566 static const char *ast_expand_codec_alias(const char *in)
567 {
568         int x;
569
570         for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(ast_codec_alias_table[0]); x++) {
571                 if (!strcmp(in,ast_codec_alias_table[x].alias))
572                         return ast_codec_alias_table[x].realname;
573         }
574         return in;
575 }
576
577 int ast_getformatbyname(const char *name)
578 {
579         int x, all, format = 0;
580
581         all = strcasecmp(name, "all") ? 0 : 1;
582         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
583                 if (all || 
584                           !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
585                           !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name))) {
586                         format |= AST_FORMAT_LIST[x].bits;
587                         if (!all)
588                                 break;
589                 }
590         }
591
592         return format;
593 }
594
595 char *ast_codec2str(int codec)
596 {
597         int x;
598         char *ret = "unknown";
599         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
600                 if (AST_FORMAT_LIST[x].bits == codec) {
601                         ret = AST_FORMAT_LIST[x].desc;
602                         break;
603                 }
604         }
605         return ret;
606 }
607
608 static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
609 {
610         int i, found=0;
611         char hex[25];
612
613         switch (cmd) {
614         case CLI_INIT:
615                 e->command = "core show codecs [audio|video|image]";
616                 e->usage = 
617                         "Usage: core show codecs [audio|video|image]\n"
618                         "       Displays codec mapping\n";
619                 return NULL;
620         case CLI_GENERATE:
621                 return NULL;
622         }
623         
624         if ((a->argc < 3) || (a->argc > 4))
625                 return CLI_SHOWUSAGE;
626
627         if (!ast_opt_dont_warn)
628                 ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
629                                 "\tIt does not indicate anything about your configuration.\n");
630
631         ast_cli(a->fd, "%11s %9s %10s   TYPE   %8s   %s\n","INT","BINARY","HEX","NAME","DESC");
632         ast_cli(a->fd, "--------------------------------------------------------------------------------\n");
633         if ((a->argc == 3) || (!strcasecmp(a->argv[3],"audio"))) {
634                 found = 1;
635                 for (i=0;i<13;i++) {
636                         snprintf(hex,25,"(0x%x)",1<<i);
637                         ast_cli(a->fd, "%11u (1 << %2d) %10s  audio   %8s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
638                 }
639         }
640
641         if ((a->argc == 3) || (!strcasecmp(a->argv[3],"image"))) {
642                 found = 1;
643                 for (i=16;i<18;i++) {
644                         snprintf(hex,25,"(0x%x)",1<<i);
645                         ast_cli(a->fd, "%11u (1 << %2d) %10s  image   %8s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
646                 }
647         }
648
649         if ((a->argc == 3) || (!strcasecmp(a->argv[3],"video"))) {
650                 found = 1;
651                 for (i=18;i<22;i++) {
652                         snprintf(hex,25,"(0x%x)",1<<i);
653                         ast_cli(a->fd, "%11u (1 << %2d) %10s  video   %8s   (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
654                 }
655         }
656
657         if (!found)
658                 return CLI_SHOWUSAGE;
659         else
660                 return CLI_SUCCESS;
661 }
662
663 static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
664 {
665         int codec, i, found=0;
666
667         switch (cmd) {
668         case CLI_INIT:
669                 e->command = "core show codec";
670                 e->usage = 
671                         "Usage: core show codec <number>\n"
672                         "       Displays codec mapping\n";
673                 return NULL;
674         case CLI_GENERATE:
675                 return NULL;
676         }
677
678         if (a->argc != 4)
679                 return CLI_SHOWUSAGE;
680
681         if (sscanf(a->argv[3],"%d",&codec) != 1)
682                 return CLI_SHOWUSAGE;
683
684         for (i = 0; i < 32; i++)
685                 if (codec & (1 << i)) {
686                         found = 1;
687                         ast_cli(a->fd, "%11u (1 << %2d)  %s\n",1 << i,i,ast_codec2str(1<<i));
688                 }
689
690         if (!found)
691                 ast_cli(a->fd, "Codec %d not found\n", codec);
692
693         return CLI_SUCCESS;
694 }
695
696 /*! Dump a frame for debugging purposes */
697 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
698 {
699         const char noname[] = "unknown";
700         char ftype[40] = "Unknown Frametype";
701         char cft[80];
702         char subclass[40] = "Unknown Subclass";
703         char csub[80];
704         char moreinfo[40] = "";
705         char cn[60];
706         char cp[40];
707         char cmn[40];
708
709         if (!name)
710                 name = noname;
711
712
713         if (!f) {
714                 ast_verbose("%s [ %s (NULL) ] [%s]\n", 
715                         term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
716                         term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)), 
717                         term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
718                 return;
719         }
720         /* XXX We should probably print one each of voice and video when the format changes XXX */
721         if (f->frametype == AST_FRAME_VOICE)
722                 return;
723         if (f->frametype == AST_FRAME_VIDEO)
724                 return;
725         switch(f->frametype) {
726         case AST_FRAME_DTMF_BEGIN:
727                 strcpy(ftype, "DTMF Begin");
728                 subclass[0] = f->subclass;
729                 subclass[1] = '\0';
730                 break;
731         case AST_FRAME_DTMF_END:
732                 strcpy(ftype, "DTMF End");
733                 subclass[0] = f->subclass;
734                 subclass[1] = '\0';
735                 break;
736         case AST_FRAME_CONTROL:
737                 strcpy(ftype, "Control");
738                 switch(f->subclass) {
739                 case AST_CONTROL_HANGUP:
740                         strcpy(subclass, "Hangup");
741                         break;
742                 case AST_CONTROL_RING:
743                         strcpy(subclass, "Ring");
744                         break;
745                 case AST_CONTROL_RINGING:
746                         strcpy(subclass, "Ringing");
747                         break;
748                 case AST_CONTROL_ANSWER:
749                         strcpy(subclass, "Answer");
750                         break;
751                 case AST_CONTROL_BUSY:
752                         strcpy(subclass, "Busy");
753                         break;
754                 case AST_CONTROL_TAKEOFFHOOK:
755                         strcpy(subclass, "Take Off Hook");
756                         break;
757                 case AST_CONTROL_OFFHOOK:
758                         strcpy(subclass, "Line Off Hook");
759                         break;
760                 case AST_CONTROL_CONGESTION:
761                         strcpy(subclass, "Congestion");
762                         break;
763                 case AST_CONTROL_FLASH:
764                         strcpy(subclass, "Flash");
765                         break;
766                 case AST_CONTROL_WINK:
767                         strcpy(subclass, "Wink");
768                         break;
769                 case AST_CONTROL_OPTION:
770                         strcpy(subclass, "Option");
771                         break;
772                 case AST_CONTROL_RADIO_KEY:
773                         strcpy(subclass, "Key Radio");
774                         break;
775                 case AST_CONTROL_RADIO_UNKEY:
776                         strcpy(subclass, "Unkey Radio");
777                         break;
778                 case -1:
779                         strcpy(subclass, "Stop generators");
780                         break;
781                 default:
782                         snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
783                 }
784                 break;
785         case AST_FRAME_NULL:
786                 strcpy(ftype, "Null Frame");
787                 strcpy(subclass, "N/A");
788                 break;
789         case AST_FRAME_IAX:
790                 /* Should never happen */
791                 strcpy(ftype, "IAX Specific");
792                 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
793                 break;
794         case AST_FRAME_TEXT:
795                 strcpy(ftype, "Text");
796                 strcpy(subclass, "N/A");
797                 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
798                 break;
799         case AST_FRAME_IMAGE:
800                 strcpy(ftype, "Image");
801                 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
802                 break;
803         case AST_FRAME_HTML:
804                 strcpy(ftype, "HTML");
805                 switch(f->subclass) {
806                 case AST_HTML_URL:
807                         strcpy(subclass, "URL");
808                         ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
809                         break;
810                 case AST_HTML_DATA:
811                         strcpy(subclass, "Data");
812                         break;
813                 case AST_HTML_BEGIN:
814                         strcpy(subclass, "Begin");
815                         break;
816                 case AST_HTML_END:
817                         strcpy(subclass, "End");
818                         break;
819                 case AST_HTML_LDCOMPLETE:
820                         strcpy(subclass, "Load Complete");
821                         break;
822                 case AST_HTML_NOSUPPORT:
823                         strcpy(subclass, "No Support");
824                         break;
825                 case AST_HTML_LINKURL:
826                         strcpy(subclass, "Link URL");
827                         ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
828                         break;
829                 case AST_HTML_UNLINK:
830                         strcpy(subclass, "Unlink");
831                         break;
832                 case AST_HTML_LINKREJECT:
833                         strcpy(subclass, "Link Reject");
834                         break;
835                 default:
836                         snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
837                         break;
838                 }
839                 break;
840         case AST_FRAME_MODEM:
841                 strcpy(ftype, "Modem");
842                 switch (f->subclass) {
843                 case AST_MODEM_T38:
844                         strcpy(subclass, "T.38");
845                         break;
846                 case AST_MODEM_V150:
847                         strcpy(subclass, "V.150");
848                         break;
849                 default:
850                         snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
851                         break;
852                 }
853                 break;
854         default:
855                 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
856         }
857         if (!ast_strlen_zero(moreinfo))
858                 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",  
859                             term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
860                             term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
861                             f->frametype, 
862                             term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
863                             f->subclass, 
864                             term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
865                             term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
866         else
867                 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",  
868                             term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
869                             term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
870                             f->frametype, 
871                             term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
872                             f->subclass, 
873                             term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
874 }
875
876
877 #ifdef TRACE_FRAMES
878 static char *show_frame_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
879 {
880         struct ast_frame *f;
881         int x=1;
882
883         switch (cmd) {
884         case CLI_INIT:
885                 e->command = "core show frame stats";
886                 e->usage = 
887                         "Usage: core show frame stats\n"
888                         "       Displays debugging statistics from framer\n";
889                 return NULL;
890         case CLI_GENERATE:
891                 return NULL;    
892         }
893
894         if (a->argc != 4)
895                 return CLI_SHOWUSAGE;
896         AST_LIST_LOCK(&headerlist);
897         ast_cli(a->fd, "     Framer Statistics     \n");
898         ast_cli(a->fd, "---------------------------\n");
899         ast_cli(a->fd, "Total allocated headers: %d\n", headers);
900         ast_cli(a->fd, "Queue Dump:\n");
901         AST_LIST_TRAVERSE(&headerlist, f, frame_list)
902                 ast_cli(a->fd, "%d.  Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
903         AST_LIST_UNLOCK(&headerlist);
904         return CLI_SUCCESS;
905 }
906 #endif
907
908 /* Builtin Asterisk CLI-commands for debugging */
909 static struct ast_cli_entry my_clis[] = {
910         AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
911         AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
912 #ifdef TRACE_FRAMES
913         AST_CLI_DEFINE(show_frame_stats, "Shows frame statistics"),
914 #endif
915 };
916
917 int init_framer(void)
918 {
919         ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
920         return 0;       
921 }
922
923 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right) 
924 {
925         int x, differential = (int) 'A', mem;
926         char *from, *to;
927
928         if (right) {
929                 from = pref->order;
930                 to = buf;
931                 mem = size;
932         } else {
933                 to = pref->order;
934                 from = buf;
935                 mem = 32;
936         }
937
938         memset(to, 0, mem);
939         for (x = 0; x < 32 ; x++) {
940                 if (!from[x])
941                         break;
942                 to[x] = right ? (from[x] + differential) : (from[x] - differential);
943         }
944 }
945
946 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size) 
947 {
948         int x, codec; 
949         size_t total_len, slen;
950         char *formatname;
951         
952         memset(buf,0,size);
953         total_len = size;
954         buf[0] = '(';
955         total_len--;
956         for(x = 0; x < 32 ; x++) {
957                 if (total_len <= 0)
958                         break;
959                 if (!(codec = ast_codec_pref_index(pref,x)))
960                         break;
961                 if ((formatname = ast_getformatname(codec))) {
962                         slen = strlen(formatname);
963                         if (slen > total_len)
964                                 break;
965                         strncat(buf,formatname,total_len);
966                         total_len -= slen;
967                 }
968                 if (total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
969                         strncat(buf,"|",total_len);
970                         total_len--;
971                 }
972         }
973         if (total_len) {
974                 strncat(buf,")",total_len);
975                 total_len--;
976         }
977
978         return size - total_len;
979 }
980
981 int ast_codec_pref_index(struct ast_codec_pref *pref, int index) 
982 {
983         int slot = 0;
984
985         
986         if ((index >= 0) && (index < sizeof(pref->order))) {
987                 slot = pref->order[index];
988         }
989
990         return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
991 }
992
993 /*! \brief Remove codec from pref list */
994 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
995 {
996         struct ast_codec_pref oldorder;
997         int x, y = 0;
998         int slot;
999         int size;
1000
1001         if (!pref->order[0])
1002                 return;
1003
1004         memcpy(&oldorder, pref, sizeof(oldorder));
1005         memset(pref, 0, sizeof(*pref));
1006
1007         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1008                 slot = oldorder.order[x];
1009                 size = oldorder.framing[x];
1010                 if (! slot)
1011                         break;
1012                 if (AST_FORMAT_LIST[slot-1].bits != format) {
1013                         pref->order[y] = slot;
1014                         pref->framing[y++] = size;
1015                 }
1016         }
1017         
1018 }
1019
1020 /*! \brief Append codec to list */
1021 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
1022 {
1023         int x, newindex = -1;
1024
1025         ast_codec_pref_remove(pref, format);
1026
1027         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1028                 if (AST_FORMAT_LIST[x].bits == format) {
1029                         newindex = x + 1;
1030                         break;
1031                 }
1032         }
1033
1034         if (newindex) {
1035                 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1036                         if (!pref->order[x]) {
1037                                 pref->order[x] = newindex;
1038                                 break;
1039                         }
1040                 }
1041         }
1042
1043         return x;
1044 }
1045
1046
1047 /*! \brief Set packet size for codec */
1048 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
1049 {
1050         int x, index = -1;
1051
1052         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1053                 if (AST_FORMAT_LIST[x].bits == format) {
1054                         index = x;
1055                         break;
1056                 }
1057         }
1058
1059         if (index < 0)
1060                 return -1;
1061
1062         /* size validation */
1063         if (!framems)
1064                 framems = AST_FORMAT_LIST[index].def_ms;
1065
1066         if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1067                 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1068
1069         if (framems < AST_FORMAT_LIST[index].min_ms)
1070                 framems = AST_FORMAT_LIST[index].min_ms;
1071
1072         if (framems > AST_FORMAT_LIST[index].max_ms)
1073                 framems = AST_FORMAT_LIST[index].max_ms;
1074
1075
1076         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1077                 if (pref->order[x] == (index + 1)) {
1078                         pref->framing[x] = framems;
1079                         break;
1080                 }
1081         }
1082
1083         return x;
1084 }
1085
1086 /*! \brief Get packet size for codec */
1087 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
1088 {
1089         int x, index = -1, framems = 0;
1090         struct ast_format_list fmt = { 0, };
1091
1092         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1093                 if (AST_FORMAT_LIST[x].bits == format) {
1094                         fmt = AST_FORMAT_LIST[x];
1095                         index = x;
1096                         break;
1097                 }
1098         }
1099
1100         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1101                 if (pref->order[x] == (index + 1)) {
1102                         framems = pref->framing[x];
1103                         break;
1104                 }
1105         }
1106
1107         /* size validation */
1108         if (!framems)
1109                 framems = AST_FORMAT_LIST[index].def_ms;
1110
1111         if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1112                 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1113
1114         if (framems < AST_FORMAT_LIST[index].min_ms)
1115                 framems = AST_FORMAT_LIST[index].min_ms;
1116
1117         if (framems > AST_FORMAT_LIST[index].max_ms)
1118                 framems = AST_FORMAT_LIST[index].max_ms;
1119
1120         fmt.cur_ms = framems;
1121
1122         return fmt;
1123 }
1124
1125 /*! \brief Pick a codec */
1126 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
1127 {
1128         int x, ret = 0, slot;
1129
1130         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1131                 slot = pref->order[x];
1132
1133                 if (!slot)
1134                         break;
1135                 if (formats & AST_FORMAT_LIST[slot-1].bits) {
1136                         ret = AST_FORMAT_LIST[slot-1].bits;
1137                         break;
1138                 }
1139         }
1140         if (ret & AST_FORMAT_AUDIO_MASK)
1141                 return ret;
1142
1143         ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1144
1145         return find_best ? ast_best_codec(formats) : 0;
1146 }
1147
1148 int ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing) 
1149 {
1150         int errors = 0;
1151         char *parse = NULL, *this = NULL, *psize = NULL;
1152         int format = 0, framems = 0;
1153
1154         parse = ast_strdupa(list);
1155         while ((this = strsep(&parse, ","))) {
1156                 framems = 0;
1157                 if ((psize = strrchr(this, ':'))) {
1158                         *psize++ = '\0';
1159                         ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
1160                         framems = atoi(psize);
1161                         if (framems < 0) {
1162                                 framems = 0;
1163                                 errors++;
1164                                 ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
1165                         }
1166                 }
1167                 if (!(format = ast_getformatbyname(this))) {
1168                         ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1169                         errors++;
1170                         continue;
1171                 }
1172
1173                 if (mask) {
1174                         if (allowing)
1175                                 *mask |= format;
1176                         else
1177                                 *mask &= ~format;
1178                 }
1179
1180                 /* Set up a preference list for audio. Do not include video in preferences 
1181                    since we can not transcode video and have to use whatever is offered
1182                  */
1183                 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1184                         if (strcasecmp(this, "all")) {
1185                                 if (allowing) {
1186                                         ast_codec_pref_append(pref, format);
1187                                         ast_codec_pref_setsize(pref, format, framems);
1188                                 }
1189                                 else
1190                                         ast_codec_pref_remove(pref, format);
1191                         } else if (!allowing) {
1192                                 memset(pref, 0, sizeof(*pref));
1193                         }
1194                 }
1195         }
1196         return errors;
1197 }
1198
1199 static int g723_len(unsigned char buf)
1200 {
1201         enum frame_type type = buf & TYPE_MASK;
1202
1203         switch(type) {
1204         case TYPE_DONTSEND:
1205                 return 0;
1206                 break;
1207         case TYPE_SILENCE:
1208                 return 4;
1209                 break;
1210         case TYPE_HIGH:
1211                 return 24;
1212                 break;
1213         case TYPE_LOW:
1214                 return 20;
1215                 break;
1216         default:
1217                 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
1218         }
1219         return -1;
1220 }
1221
1222 static int g723_samples(unsigned char *buf, int maxlen)
1223 {
1224         int pos = 0;
1225         int samples = 0;
1226         int res;
1227         while(pos < maxlen) {
1228                 res = g723_len(buf[pos]);
1229                 if (res <= 0)
1230                         break;
1231                 samples += 240;
1232                 pos += res;
1233         }
1234         return samples;
1235 }
1236
1237 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1238 {
1239         int byte = bit / 8;       /* byte containing first bit */
1240         int rem = 8 - (bit % 8);  /* remaining bits in first byte */
1241         unsigned char ret = 0;
1242         
1243         if (n <= 0 || n > 8)
1244                 return 0;
1245
1246         if (rem < n) {
1247                 ret = (data[byte] << (n - rem));
1248                 ret |= (data[byte + 1] >> (8 - n + rem));
1249         } else {
1250                 ret = (data[byte] >> (rem - n));
1251         }
1252
1253         return (ret & (0xff >> (8 - n)));
1254 }
1255
1256 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1257 {
1258         static int SpeexWBSubModeSz[] = {
1259                 0, 36, 112, 192,
1260                 352, 0, 0, 0 };
1261         int off = bit;
1262         unsigned char c;
1263
1264         /* skip up to two wideband frames */
1265         if (((len * 8 - off) >= 5) && 
1266                 get_n_bits_at(data, 1, off)) {
1267                 c = get_n_bits_at(data, 3, off + 1);
1268                 off += SpeexWBSubModeSz[c];
1269
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                                 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1278                                 return -1;
1279                         }
1280                 }
1281
1282         }
1283         return off - bit;
1284 }
1285
1286 static int speex_samples(unsigned char *data, int len)
1287 {
1288         static int SpeexSubModeSz[] = {
1289                5, 43, 119, 160,
1290                 220, 300, 364, 492, 
1291                 79, 0, 0, 0,
1292                 0, 0, 0, 0 };
1293         static int SpeexInBandSz[] = { 
1294                 1, 1, 4, 4,
1295                 4, 4, 4, 4,
1296                 8, 8, 16, 16,
1297                 32, 32, 64, 64 };
1298         int bit = 0;
1299         int cnt = 0;
1300         int off;
1301         unsigned char c;
1302
1303         while ((len * 8 - bit) >= 5) {
1304                 /* skip wideband frames */
1305                 off = speex_get_wb_sz_at(data, len, bit);
1306                 if (off < 0)  {
1307                         ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1308                         break;
1309                 }
1310                 bit += off;
1311
1312                 if ((len * 8 - bit) < 5) {
1313                         ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1314                         break;
1315                 }
1316
1317                 /* get control bits */
1318                 c = get_n_bits_at(data, 5, bit);
1319                 bit += 5;
1320
1321                 if (c == 15) { 
1322                         /* terminator */
1323                         break; 
1324                 } else if (c == 14) {
1325                         /* in-band signal; next 4 bits contain signal id */
1326                         c = get_n_bits_at(data, 4, bit);
1327                         bit += 4;
1328                         bit += SpeexInBandSz[c];
1329                 } else if (c == 13) {
1330                         /* user in-band; next 5 bits contain msg len */
1331                         c = get_n_bits_at(data, 5, bit);
1332                         bit += 5;
1333                         bit += c * 8;
1334                 } else if (c > 8) {
1335                         /* unknown */
1336                         break;
1337                 } else {
1338                         /* skip number bits for submode (less the 5 control bits) */
1339                         bit += SpeexSubModeSz[c] - 5;
1340                         cnt += 160; /* new frame */
1341                 }
1342         }
1343         return cnt;
1344 }
1345
1346 int ast_codec_get_samples(struct ast_frame *f)
1347 {
1348         int samples=0;
1349         switch(f->subclass) {
1350         case AST_FORMAT_SPEEX:
1351                 samples = speex_samples(f->data, f->datalen);
1352                 break;
1353         case AST_FORMAT_G723_1:
1354                 samples = g723_samples(f->data, f->datalen);
1355                 break;
1356         case AST_FORMAT_ILBC:
1357                 samples = 240 * (f->datalen / 50);
1358                 break;
1359         case AST_FORMAT_GSM:
1360                 samples = 160 * (f->datalen / 33);
1361                 break;
1362         case AST_FORMAT_G729A:
1363                 samples = f->datalen * 8;
1364                 break;
1365         case AST_FORMAT_SLINEAR:
1366         case AST_FORMAT_SLINEAR16:
1367                 samples = f->datalen / 2;
1368                 break;
1369         case AST_FORMAT_LPC10:
1370                 /* assumes that the RTP packet contains one LPC10 frame */
1371                 samples = 22 * 8;
1372                 samples += (((char *)(f->data))[7] & 0x1) * 8;
1373                 break;
1374         case AST_FORMAT_ULAW:
1375         case AST_FORMAT_ALAW:
1376         case AST_FORMAT_G722:
1377                 samples = f->datalen;
1378                 break;
1379         case AST_FORMAT_ADPCM:
1380         case AST_FORMAT_G726:
1381         case AST_FORMAT_G726_AAL2:
1382                 samples = f->datalen * 2;
1383                 break;
1384         default:
1385                 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1386         }
1387         return samples;
1388 }
1389
1390 int ast_codec_get_len(int format, int samples)
1391 {
1392         int len = 0;
1393
1394         /* XXX Still need speex, g723, and lpc10 XXX */ 
1395         switch(format) {
1396         case AST_FORMAT_G723_1:
1397                 len = (samples / 240) * 20;
1398                 break;
1399         case AST_FORMAT_ILBC:
1400                 len = (samples / 240) * 50;
1401                 break;
1402         case AST_FORMAT_GSM:
1403                 len = (samples / 160) * 33;
1404                 break;
1405         case AST_FORMAT_G729A:
1406                 len = samples / 8;
1407                 break;
1408         case AST_FORMAT_SLINEAR:
1409         case AST_FORMAT_SLINEAR16:
1410                 len = samples * 2;
1411                 break;
1412         case AST_FORMAT_ULAW:
1413         case AST_FORMAT_ALAW:
1414         case AST_FORMAT_G722:
1415                 len = samples;
1416                 break;
1417         case AST_FORMAT_ADPCM:
1418         case AST_FORMAT_G726:
1419         case AST_FORMAT_G726_AAL2:
1420                 len = samples / 2;
1421                 break;
1422         default:
1423                 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1424         }
1425
1426         return len;
1427 }
1428
1429 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1430 {
1431         int count;
1432         short *fdata = f->data;
1433         short adjust_value = abs(adjustment);
1434
1435         if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
1436                 return -1;
1437
1438         if (!adjustment)
1439                 return 0;
1440
1441         for (count = 0; count < f->samples; count++) {
1442                 if (adjustment > 0) {
1443                         ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1444                 } else if (adjustment < 0) {
1445                         ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1446                 }
1447         }
1448
1449         return 0;
1450 }
1451
1452 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1453 {
1454         int count;
1455         short *data1, *data2;
1456
1457         if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
1458                 return -1;
1459
1460         if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
1461                 return -1;
1462
1463         if (f1->samples != f2->samples)
1464                 return -1;
1465
1466         for (count = 0, data1 = f1->data, data2 = f2->data;
1467              count < f1->samples;
1468              count++, data1++, data2++)
1469                 ast_slinear_saturated_add(data1, data2);
1470
1471         return 0;
1472 }