f2ceabf16e13a0e081e2517821de1492c96245b4
[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 (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR))
325                 ast_translate_frame_freed(fr);
326
327         if (!fr->mallocd)
328                 return;
329
330 #if !defined(LOW_MEMORY)
331         if (cache && fr->mallocd == AST_MALLOCD_HDR) {
332                 /* Cool, only the header is malloc'd, let's just cache those for now 
333                  * to keep things simple... */
334                 struct ast_frame_cache *frames;
335
336                 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) 
337                     && frames->size < FRAME_CACHE_MAX_SIZE) {
338                         AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
339                         frames->size++;
340                         return;
341                 }
342         }
343 #endif
344         
345         if (fr->mallocd & AST_MALLOCD_DATA) {
346                 if (fr->data) 
347                         ast_free(fr->data - fr->offset);
348         }
349         if (fr->mallocd & AST_MALLOCD_SRC) {
350                 if (fr->src)
351                         ast_free((char *)fr->src);
352         }
353         if (fr->mallocd & AST_MALLOCD_HDR) {
354 #ifdef TRACE_FRAMES
355                 AST_LIST_LOCK(&headerlist);
356                 headers--;
357                 AST_LIST_REMOVE(&headerlist, fr, frame_list);
358                 AST_LIST_UNLOCK(&headerlist);
359 #endif                  
360                 ast_free(fr);
361         }
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         const char *message = "Unknown";
714
715         if (!name)
716                 name = noname;
717
718
719         if (!f) {
720                 ast_verbose("%s [ %s (NULL) ] [%s]\n", 
721                         term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
722                         term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)), 
723                         term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
724                 return;
725         }
726         /* XXX We should probably print one each of voice and video when the format changes XXX */
727         if (f->frametype == AST_FRAME_VOICE)
728                 return;
729         if (f->frametype == AST_FRAME_VIDEO)
730                 return;
731         switch(f->frametype) {
732         case AST_FRAME_DTMF_BEGIN:
733                 strcpy(ftype, "DTMF Begin");
734                 subclass[0] = f->subclass;
735                 subclass[1] = '\0';
736                 break;
737         case AST_FRAME_DTMF_END:
738                 strcpy(ftype, "DTMF End");
739                 subclass[0] = f->subclass;
740                 subclass[1] = '\0';
741                 break;
742         case AST_FRAME_CONTROL:
743                 strcpy(ftype, "Control");
744                 switch(f->subclass) {
745                 case AST_CONTROL_HANGUP:
746                         strcpy(subclass, "Hangup");
747                         break;
748                 case AST_CONTROL_RING:
749                         strcpy(subclass, "Ring");
750                         break;
751                 case AST_CONTROL_RINGING:
752                         strcpy(subclass, "Ringing");
753                         break;
754                 case AST_CONTROL_ANSWER:
755                         strcpy(subclass, "Answer");
756                         break;
757                 case AST_CONTROL_BUSY:
758                         strcpy(subclass, "Busy");
759                         break;
760                 case AST_CONTROL_TAKEOFFHOOK:
761                         strcpy(subclass, "Take Off Hook");
762                         break;
763                 case AST_CONTROL_OFFHOOK:
764                         strcpy(subclass, "Line Off Hook");
765                         break;
766                 case AST_CONTROL_CONGESTION:
767                         strcpy(subclass, "Congestion");
768                         break;
769                 case AST_CONTROL_FLASH:
770                         strcpy(subclass, "Flash");
771                         break;
772                 case AST_CONTROL_WINK:
773                         strcpy(subclass, "Wink");
774                         break;
775                 case AST_CONTROL_OPTION:
776                         strcpy(subclass, "Option");
777                         break;
778                 case AST_CONTROL_RADIO_KEY:
779                         strcpy(subclass, "Key Radio");
780                         break;
781                 case AST_CONTROL_RADIO_UNKEY:
782                         strcpy(subclass, "Unkey Radio");
783                         break;
784                 case AST_CONTROL_HOLD:
785                         strcpy(subclass, "Hold");
786                         break;
787                 case AST_CONTROL_UNHOLD:
788                         strcpy(subclass, "Unhold");
789                         break;
790                 case AST_CONTROL_T38:
791                         if (f->datalen != sizeof(enum ast_control_t38)) {
792                                 message = "Invalid";
793                         } else {
794                                 enum ast_control_t38 state = *((enum ast_control_t38 *) f->data);
795                                 if (state == AST_T38_REQUEST_NEGOTIATE)
796                                         message = "Negotiation Requested";
797                                 else if (state == AST_T38_REQUEST_TERMINATE)
798                                         message = "Negotiation Request Terminated";
799                                 else if (state == AST_T38_NEGOTIATED)
800                                         message = "Negotiated";
801                                 else if (state == AST_T38_TERMINATED)
802                                         message = "Terminated";
803                                 else if (state == AST_T38_REFUSED)
804                                         message = "Refused";
805                         }
806                         snprintf(subclass, sizeof(subclass), "T38/%s", message);
807                         break;
808                 case -1:
809                         strcpy(subclass, "Stop generators");
810                         break;
811                 default:
812                         snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
813                 }
814                 break;
815         case AST_FRAME_NULL:
816                 strcpy(ftype, "Null Frame");
817                 strcpy(subclass, "N/A");
818                 break;
819         case AST_FRAME_IAX:
820                 /* Should never happen */
821                 strcpy(ftype, "IAX Specific");
822                 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
823                 break;
824         case AST_FRAME_TEXT:
825                 strcpy(ftype, "Text");
826                 strcpy(subclass, "N/A");
827                 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
828                 break;
829         case AST_FRAME_IMAGE:
830                 strcpy(ftype, "Image");
831                 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
832                 break;
833         case AST_FRAME_HTML:
834                 strcpy(ftype, "HTML");
835                 switch(f->subclass) {
836                 case AST_HTML_URL:
837                         strcpy(subclass, "URL");
838                         ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
839                         break;
840                 case AST_HTML_DATA:
841                         strcpy(subclass, "Data");
842                         break;
843                 case AST_HTML_BEGIN:
844                         strcpy(subclass, "Begin");
845                         break;
846                 case AST_HTML_END:
847                         strcpy(subclass, "End");
848                         break;
849                 case AST_HTML_LDCOMPLETE:
850                         strcpy(subclass, "Load Complete");
851                         break;
852                 case AST_HTML_NOSUPPORT:
853                         strcpy(subclass, "No Support");
854                         break;
855                 case AST_HTML_LINKURL:
856                         strcpy(subclass, "Link URL");
857                         ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
858                         break;
859                 case AST_HTML_UNLINK:
860                         strcpy(subclass, "Unlink");
861                         break;
862                 case AST_HTML_LINKREJECT:
863                         strcpy(subclass, "Link Reject");
864                         break;
865                 default:
866                         snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
867                         break;
868                 }
869                 break;
870         case AST_FRAME_MODEM:
871                 strcpy(ftype, "Modem");
872                 switch (f->subclass) {
873                 case AST_MODEM_T38:
874                         strcpy(subclass, "T.38");
875                         break;
876                 case AST_MODEM_V150:
877                         strcpy(subclass, "V.150");
878                         break;
879                 default:
880                         snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
881                         break;
882                 }
883                 break;
884         default:
885                 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
886         }
887         if (!ast_strlen_zero(moreinfo))
888                 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",  
889                             term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
890                             term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
891                             f->frametype, 
892                             term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
893                             f->subclass, 
894                             term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
895                             term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
896         else
897                 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",  
898                             term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
899                             term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
900                             f->frametype, 
901                             term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
902                             f->subclass, 
903                             term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
904 }
905
906
907 #ifdef TRACE_FRAMES
908 static char *show_frame_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
909 {
910         struct ast_frame *f;
911         int x=1;
912
913         switch (cmd) {
914         case CLI_INIT:
915                 e->command = "core show frame stats";
916                 e->usage = 
917                         "Usage: core show frame stats\n"
918                         "       Displays debugging statistics from framer\n";
919                 return NULL;
920         case CLI_GENERATE:
921                 return NULL;    
922         }
923
924         if (a->argc != 4)
925                 return CLI_SHOWUSAGE;
926         AST_LIST_LOCK(&headerlist);
927         ast_cli(a->fd, "     Framer Statistics     \n");
928         ast_cli(a->fd, "---------------------------\n");
929         ast_cli(a->fd, "Total allocated headers: %d\n", headers);
930         ast_cli(a->fd, "Queue Dump:\n");
931         AST_LIST_TRAVERSE(&headerlist, f, frame_list)
932                 ast_cli(a->fd, "%d.  Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
933         AST_LIST_UNLOCK(&headerlist);
934         return CLI_SUCCESS;
935 }
936 #endif
937
938 /* Builtin Asterisk CLI-commands for debugging */
939 static struct ast_cli_entry my_clis[] = {
940         AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
941         AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
942 #ifdef TRACE_FRAMES
943         AST_CLI_DEFINE(show_frame_stats, "Shows frame statistics"),
944 #endif
945 };
946
947 int init_framer(void)
948 {
949         ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
950         return 0;       
951 }
952
953 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right) 
954 {
955         int x, differential = (int) 'A', mem;
956         char *from, *to;
957
958         if (right) {
959                 from = pref->order;
960                 to = buf;
961                 mem = size;
962         } else {
963                 to = pref->order;
964                 from = buf;
965                 mem = 32;
966         }
967
968         memset(to, 0, mem);
969         for (x = 0; x < 32 ; x++) {
970                 if (!from[x])
971                         break;
972                 to[x] = right ? (from[x] + differential) : (from[x] - differential);
973         }
974 }
975
976 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size) 
977 {
978         int x, codec; 
979         size_t total_len, slen;
980         char *formatname;
981         
982         memset(buf,0,size);
983         total_len = size;
984         buf[0] = '(';
985         total_len--;
986         for(x = 0; x < 32 ; x++) {
987                 if (total_len <= 0)
988                         break;
989                 if (!(codec = ast_codec_pref_index(pref,x)))
990                         break;
991                 if ((formatname = ast_getformatname(codec))) {
992                         slen = strlen(formatname);
993                         if (slen > total_len)
994                                 break;
995                         strncat(buf, formatname, total_len - 1); /* safe */
996                         total_len -= slen;
997                 }
998                 if (total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
999                         strncat(buf, "|", total_len - 1); /* safe */
1000                         total_len--;
1001                 }
1002         }
1003         if (total_len) {
1004                 strncat(buf, ")", total_len - 1); /* safe */
1005                 total_len--;
1006         }
1007
1008         return size - total_len;
1009 }
1010
1011 int ast_codec_pref_index(struct ast_codec_pref *pref, int index) 
1012 {
1013         int slot = 0;
1014
1015         
1016         if ((index >= 0) && (index < sizeof(pref->order))) {
1017                 slot = pref->order[index];
1018         }
1019
1020         return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
1021 }
1022
1023 /*! \brief Remove codec from pref list */
1024 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
1025 {
1026         struct ast_codec_pref oldorder;
1027         int x, y = 0;
1028         int slot;
1029         int size;
1030
1031         if (!pref->order[0])
1032                 return;
1033
1034         memcpy(&oldorder, pref, sizeof(oldorder));
1035         memset(pref, 0, sizeof(*pref));
1036
1037         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1038                 slot = oldorder.order[x];
1039                 size = oldorder.framing[x];
1040                 if (! slot)
1041                         break;
1042                 if (AST_FORMAT_LIST[slot-1].bits != format) {
1043                         pref->order[y] = slot;
1044                         pref->framing[y++] = size;
1045                 }
1046         }
1047         
1048 }
1049
1050 /*! \brief Append codec to list */
1051 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
1052 {
1053         int x, newindex = 0;
1054
1055         ast_codec_pref_remove(pref, format);
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                         newindex = x + 1;
1060                         break;
1061                 }
1062         }
1063
1064         if (newindex) {
1065                 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1066                         if (!pref->order[x]) {
1067                                 pref->order[x] = newindex;
1068                                 break;
1069                         }
1070                 }
1071         }
1072
1073         return x;
1074 }
1075
1076 /*! \brief Prepend codec to list */
1077 void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing)
1078 {
1079         int x, newindex = 0;
1080
1081         /* First step is to get the codecs "index number" */
1082         for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1083                 if (AST_FORMAT_LIST[x].bits == format) {
1084                         newindex = x + 1;
1085                         break;
1086                 }
1087         }
1088         /* Done if its unknown */
1089         if (!newindex)
1090                 return;
1091
1092         /* Now find any existing occurrence, or the end */
1093         for (x = 0; x < 32; x++) {
1094                 if (!pref->order[x] || pref->order[x] == newindex)
1095                         break;
1096         }
1097
1098         if (only_if_existing && !pref->order[x])
1099                 return;
1100
1101         /* Move down to make space to insert - either all the way to the end,
1102            or as far as the existing location (which will be overwritten) */
1103         for (; x > 0; x--) {
1104                 pref->order[x] = pref->order[x - 1];
1105                 pref->framing[x] = pref->framing[x - 1];
1106         }
1107
1108         /* And insert the new entry */
1109         pref->order[0] = newindex;
1110         pref->framing[0] = 0; /* ? */
1111 }
1112
1113 /*! \brief Set packet size for codec */
1114 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
1115 {
1116         int x, index = -1;
1117
1118         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1119                 if (AST_FORMAT_LIST[x].bits == format) {
1120                         index = x;
1121                         break;
1122                 }
1123         }
1124
1125         if (index < 0)
1126                 return -1;
1127
1128         /* size validation */
1129         if (!framems)
1130                 framems = AST_FORMAT_LIST[index].def_ms;
1131
1132         if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1133                 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1134
1135         if (framems < AST_FORMAT_LIST[index].min_ms)
1136                 framems = AST_FORMAT_LIST[index].min_ms;
1137
1138         if (framems > AST_FORMAT_LIST[index].max_ms)
1139                 framems = AST_FORMAT_LIST[index].max_ms;
1140
1141
1142         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1143                 if (pref->order[x] == (index + 1)) {
1144                         pref->framing[x] = framems;
1145                         break;
1146                 }
1147         }
1148
1149         return x;
1150 }
1151
1152 /*! \brief Get packet size for codec */
1153 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
1154 {
1155         int x, index = -1, framems = 0;
1156         struct ast_format_list fmt = { 0, };
1157
1158         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1159                 if (AST_FORMAT_LIST[x].bits == format) {
1160                         fmt = AST_FORMAT_LIST[x];
1161                         index = x;
1162                         break;
1163                 }
1164         }
1165
1166         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1167                 if (pref->order[x] == (index + 1)) {
1168                         framems = pref->framing[x];
1169                         break;
1170                 }
1171         }
1172
1173         /* size validation */
1174         if (!framems)
1175                 framems = AST_FORMAT_LIST[index].def_ms;
1176
1177         if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1178                 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1179
1180         if (framems < AST_FORMAT_LIST[index].min_ms)
1181                 framems = AST_FORMAT_LIST[index].min_ms;
1182
1183         if (framems > AST_FORMAT_LIST[index].max_ms)
1184                 framems = AST_FORMAT_LIST[index].max_ms;
1185
1186         fmt.cur_ms = framems;
1187
1188         return fmt;
1189 }
1190
1191 /*! \brief Pick a codec */
1192 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
1193 {
1194         int x, ret = 0, slot;
1195
1196         for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1197                 slot = pref->order[x];
1198
1199                 if (!slot)
1200                         break;
1201                 if (formats & AST_FORMAT_LIST[slot-1].bits) {
1202                         ret = AST_FORMAT_LIST[slot-1].bits;
1203                         break;
1204                 }
1205         }
1206         if (ret & AST_FORMAT_AUDIO_MASK)
1207                 return ret;
1208
1209         ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1210
1211         return find_best ? ast_best_codec(formats) : 0;
1212 }
1213
1214 int ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing) 
1215 {
1216         int errors = 0;
1217         char *parse = NULL, *this = NULL, *psize = NULL;
1218         int format = 0, framems = 0;
1219
1220         parse = ast_strdupa(list);
1221         while ((this = strsep(&parse, ","))) {
1222                 framems = 0;
1223                 if ((psize = strrchr(this, ':'))) {
1224                         *psize++ = '\0';
1225                         ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
1226                         framems = atoi(psize);
1227                         if (framems < 0) {
1228                                 framems = 0;
1229                                 errors++;
1230                                 ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
1231                         }
1232                 }
1233                 if (!(format = ast_getformatbyname(this))) {
1234                         ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1235                         errors++;
1236                         continue;
1237                 }
1238
1239                 if (mask) {
1240                         if (allowing)
1241                                 *mask |= format;
1242                         else
1243                                 *mask &= ~format;
1244                 }
1245
1246                 /* Set up a preference list for audio. Do not include video in preferences 
1247                    since we can not transcode video and have to use whatever is offered
1248                  */
1249                 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1250                         if (strcasecmp(this, "all")) {
1251                                 if (allowing) {
1252                                         ast_codec_pref_append(pref, format);
1253                                         ast_codec_pref_setsize(pref, format, framems);
1254                                 }
1255                                 else
1256                                         ast_codec_pref_remove(pref, format);
1257                         } else if (!allowing) {
1258                                 memset(pref, 0, sizeof(*pref));
1259                         }
1260                 }
1261         }
1262         return errors;
1263 }
1264
1265 static int g723_len(unsigned char buf)
1266 {
1267         enum frame_type type = buf & TYPE_MASK;
1268
1269         switch(type) {
1270         case TYPE_DONTSEND:
1271                 return 0;
1272                 break;
1273         case TYPE_SILENCE:
1274                 return 4;
1275                 break;
1276         case TYPE_HIGH:
1277                 return 24;
1278                 break;
1279         case TYPE_LOW:
1280                 return 20;
1281                 break;
1282         default:
1283                 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
1284         }
1285         return -1;
1286 }
1287
1288 static int g723_samples(unsigned char *buf, int maxlen)
1289 {
1290         int pos = 0;
1291         int samples = 0;
1292         int res;
1293         while(pos < maxlen) {
1294                 res = g723_len(buf[pos]);
1295                 if (res <= 0)
1296                         break;
1297                 samples += 240;
1298                 pos += res;
1299         }
1300         return samples;
1301 }
1302
1303 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1304 {
1305         int byte = bit / 8;       /* byte containing first bit */
1306         int rem = 8 - (bit % 8);  /* remaining bits in first byte */
1307         unsigned char ret = 0;
1308         
1309         if (n <= 0 || n > 8)
1310                 return 0;
1311
1312         if (rem < n) {
1313                 ret = (data[byte] << (n - rem));
1314                 ret |= (data[byte + 1] >> (8 - n + rem));
1315         } else {
1316                 ret = (data[byte] >> (rem - n));
1317         }
1318
1319         return (ret & (0xff >> (8 - n)));
1320 }
1321
1322 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1323 {
1324         static int SpeexWBSubModeSz[] = {
1325                 0, 36, 112, 192,
1326                 352, 0, 0, 0 };
1327         int off = bit;
1328         unsigned char c;
1329
1330         /* skip up to two wideband frames */
1331         if (((len * 8 - off) >= 5) && 
1332                 get_n_bits_at(data, 1, off)) {
1333                 c = get_n_bits_at(data, 3, off + 1);
1334                 off += SpeexWBSubModeSz[c];
1335
1336                 if (((len * 8 - off) >= 5) && 
1337                         get_n_bits_at(data, 1, off)) {
1338                         c = get_n_bits_at(data, 3, off + 1);
1339                         off += SpeexWBSubModeSz[c];
1340
1341                         if (((len * 8 - off) >= 5) && 
1342                                 get_n_bits_at(data, 1, off)) {
1343                                 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1344                                 return -1;
1345                         }
1346                 }
1347
1348         }
1349         return off - bit;
1350 }
1351
1352 static int speex_samples(unsigned char *data, int len)
1353 {
1354         static int SpeexSubModeSz[] = {
1355                 5, 43, 119, 160,
1356                 220, 300, 364, 492, 
1357                 79, 0, 0, 0,
1358                 0, 0, 0, 0 };
1359         static int SpeexInBandSz[] = { 
1360                 1, 1, 4, 4,
1361                 4, 4, 4, 4,
1362                 8, 8, 16, 16,
1363                 32, 32, 64, 64 };
1364         int bit = 0;
1365         int cnt = 0;
1366         int off;
1367         unsigned char c;
1368
1369         while ((len * 8 - bit) >= 5) {
1370                 /* skip wideband frames */
1371                 off = speex_get_wb_sz_at(data, len, bit);
1372                 if (off < 0)  {
1373                         ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1374                         break;
1375                 }
1376                 bit += off;
1377
1378                 if ((len * 8 - bit) < 5) {
1379                         ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1380                         break;
1381                 }
1382
1383                 /* get control bits */
1384                 c = get_n_bits_at(data, 5, bit);
1385                 bit += 5;
1386
1387                 if (c == 15) { 
1388                         /* terminator */
1389                         break; 
1390                 } else if (c == 14) {
1391                         /* in-band signal; next 4 bits contain signal id */
1392                         c = get_n_bits_at(data, 4, bit);
1393                         bit += 4;
1394                         bit += SpeexInBandSz[c];
1395                 } else if (c == 13) {
1396                         /* user in-band; next 5 bits contain msg len */
1397                         c = get_n_bits_at(data, 5, bit);
1398                         bit += 5;
1399                         bit += c * 8;
1400                 } else if (c > 8) {
1401                         /* unknown */
1402                         break;
1403                 } else {
1404                         /* skip number bits for submode (less the 5 control bits) */
1405                         bit += SpeexSubModeSz[c] - 5;
1406                         cnt += 160; /* new frame */
1407                 }
1408         }
1409         return cnt;
1410 }
1411
1412 int ast_codec_get_samples(struct ast_frame *f)
1413 {
1414         int samples=0;
1415         switch(f->subclass) {
1416         case AST_FORMAT_SPEEX:
1417                 samples = speex_samples(f->data, f->datalen);
1418                 break;
1419         case AST_FORMAT_G723_1:
1420                 samples = g723_samples(f->data, f->datalen);
1421                 break;
1422         case AST_FORMAT_ILBC:
1423                 samples = 240 * (f->datalen / 50);
1424                 break;
1425         case AST_FORMAT_GSM:
1426                 samples = 160 * (f->datalen / 33);
1427                 break;
1428         case AST_FORMAT_G729A:
1429                 samples = f->datalen * 8;
1430                 break;
1431         case AST_FORMAT_SLINEAR:
1432         case AST_FORMAT_SLINEAR16:
1433                 samples = f->datalen / 2;
1434                 break;
1435         case AST_FORMAT_LPC10:
1436                 /* assumes that the RTP packet contains one LPC10 frame */
1437                 samples = 22 * 8;
1438                 samples += (((char *)(f->data))[7] & 0x1) * 8;
1439                 break;
1440         case AST_FORMAT_ULAW:
1441         case AST_FORMAT_ALAW:
1442                 samples = f->datalen;
1443                 break;
1444         case AST_FORMAT_G722:
1445         case AST_FORMAT_ADPCM:
1446         case AST_FORMAT_G726:
1447         case AST_FORMAT_G726_AAL2:
1448                 samples = f->datalen * 2;
1449                 break;
1450         default:
1451                 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1452         }
1453         return samples;
1454 }
1455
1456 int ast_codec_get_len(int format, int samples)
1457 {
1458         int len = 0;
1459
1460         /* XXX Still need speex, g723, and lpc10 XXX */ 
1461         switch(format) {
1462         case AST_FORMAT_G723_1:
1463                 len = (samples / 240) * 20;
1464                 break;
1465         case AST_FORMAT_ILBC:
1466                 len = (samples / 240) * 50;
1467                 break;
1468         case AST_FORMAT_GSM:
1469                 len = (samples / 160) * 33;
1470                 break;
1471         case AST_FORMAT_G729A:
1472                 len = samples / 8;
1473                 break;
1474         case AST_FORMAT_SLINEAR:
1475         case AST_FORMAT_SLINEAR16:
1476                 len = samples * 2;
1477                 break;
1478         case AST_FORMAT_ULAW:
1479         case AST_FORMAT_ALAW:
1480                 len = samples;
1481                 break;
1482         case AST_FORMAT_G722:
1483         case AST_FORMAT_ADPCM:
1484         case AST_FORMAT_G726:
1485         case AST_FORMAT_G726_AAL2:
1486                 len = samples / 2;
1487                 break;
1488         default:
1489                 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1490         }
1491
1492         return len;
1493 }
1494
1495 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1496 {
1497         int count;
1498         short *fdata = f->data;
1499         short adjust_value = abs(adjustment);
1500
1501         if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
1502                 return -1;
1503
1504         if (!adjustment)
1505                 return 0;
1506
1507         for (count = 0; count < f->samples; count++) {
1508                 if (adjustment > 0) {
1509                         ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1510                 } else if (adjustment < 0) {
1511                         ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1512                 }
1513         }
1514
1515         return 0;
1516 }
1517
1518 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1519 {
1520         int count;
1521         short *data1, *data2;
1522
1523         if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
1524                 return -1;
1525
1526         if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
1527                 return -1;
1528
1529         if (f1->samples != f2->samples)
1530                 return -1;
1531
1532         for (count = 0, data1 = f1->data, data2 = f2->data;
1533              count < f1->samples;
1534              count++, data1++, data2++)
1535                 ast_slinear_saturated_add(data1, data2);
1536
1537         return 0;
1538 }