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