use the proper variable type for these unixODBC API calls, eliminating warnings on...
[asterisk-bristuff.git] / main / frame.c
blobbeb141d523d44c636377586f4cddf4acf5567e16
1 /*
2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
19 /*! \file
21 * \brief Frame and codec manipulation routines
23 * \author Mark Spencer <markster@digium.com>
26 #include "asterisk.h"
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <stdio.h>
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"
47 #ifdef TRACE_FRAMES
48 static int headers = 0;
49 static AST_LIST_HEAD_STATIC(headerlist, ast_frame);
50 #endif
52 static void frame_cache_cleanup(void *data);
54 /*! \brief A per-thread cache of frame headers */
55 AST_THREADSTORAGE_CUSTOM(frame_cache, frame_cache_init, frame_cache_cleanup);
57 /*!
58 * \brief Maximum ast_frame cache size
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
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);
72 struct ast_frame_cache {
73 struct ast_frames list;
74 size_t size;
77 #define SMOOTHER_SIZE 8000
79 enum frame_type {
80 TYPE_HIGH, /* 0x0 */
81 TYPE_LOW, /* 0x1 */
82 TYPE_SILENCE, /* 0x2 */
83 TYPE_DONTSEND /* 0x3 */
86 #define TYPE_MASK 0x3
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;
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, 300, 20, 20 }, /*!< 2: codec_gsm.c */
107 { 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law", 80, 10, 150, 10, 20 }, /*!< 3: codec_ulaw.c */
108 { 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law", 80, 10, 150, 10, 20 }, /*!< 4: codec_alaw.c */
109 { 1, AST_FORMAT_G726, "g726", "G.726 RFC3551", 40, 10, 300, 10, 20 }, /*!< 5: codec_g726.c */
110 { 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM", 40, 10, 300, 10, 20 }, /*!< 6: codec_adpcm.c */
111 { 1, AST_FORMAT_SLINEAR, "slin", "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE }, /*!< 7 */
112 { 1, AST_FORMAT_LPC10, "lpc10", "LPC10", 7, 20, 20, 20, 20 }, /*!< 8: codec_lpc10.c */
113 { 1, AST_FORMAT_G729A, "g729", "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 }, /*!< 9: Binary commercial distribution */
114 { 1, AST_FORMAT_SPEEX, "speex", "SpeeX", 10, 10, 60, 10, 20 }, /*!< 10: codec_speex.c */
115 { 1, AST_FORMAT_ILBC, "ilbc", "iLBC", 50, 30, 30, 30, 30 }, /*!< 11: codec_ilbc.c */ /* inc=30ms - workaround */
116 { 1, AST_FORMAT_G726_AAL2, "g726aal2", "G.726 AAL2", 40, 10, 300, 10, 20 }, /*!< 12: codec_g726.c */
117 { 1, AST_FORMAT_G722, "g722", "G722"}, /*!< 13 */
118 { 0, 0, "nothing", "undefined" },
119 { 0, 0, "nothing", "undefined" },
120 { 0, 0, "nothing", "undefined" },
121 { 0, 0, "nothing", "undefined" },
122 { 0, AST_FORMAT_MAX_AUDIO, "maxaudio", "Maximum audio format" },
123 { 1, AST_FORMAT_JPEG, "jpeg", "JPEG image"}, /*!< 17: See format_jpeg.c */
124 { 1, AST_FORMAT_PNG, "png", "PNG image"}, /*!< 18: Image format */
125 { 1, AST_FORMAT_H261, "h261", "H.261 Video" }, /*!< 19: Video Passthrough */
126 { 1, AST_FORMAT_H263, "h263", "H.263 Video" }, /*!< 20: Passthrough support, see format_h263.c */
127 { 1, AST_FORMAT_H263_PLUS, "h263p", "H.263+ Video" }, /*!< 21: See format_h263.c */
128 { 1, AST_FORMAT_H264, "h264", "H.264 Video" }, /*!< 22: Passthrough support, see format_h263.c */
129 { 0, 0, "nothing", "undefined" },
130 { 0, 0, "nothing", "undefined" },
131 { 0, 0, "nothing", "undefined" },
132 { 0, AST_FORMAT_MAX_VIDEO, "maxvideo", "Maximum video format" },
135 struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
137 void ast_smoother_reset(struct ast_smoother *s, int size)
139 memset(s, 0, sizeof(*s));
140 s->size = size;
143 struct ast_smoother *ast_smoother_new(int size)
145 struct ast_smoother *s;
146 if (size < 1)
147 return NULL;
148 if ((s = ast_malloc(sizeof(*s))))
149 ast_smoother_reset(s, size);
150 return s;
153 int ast_smoother_get_flags(struct ast_smoother *s)
155 return s->flags;
158 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
160 s->flags = flags;
163 int ast_smoother_test_flag(struct ast_smoother *s, int flag)
165 return (s->flags & flag);
168 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
170 if (f->frametype != AST_FRAME_VOICE) {
171 ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
172 return -1;
174 if (!s->format) {
175 s->format = f->subclass;
176 s->samplesperbyte = (float)f->samples / (float)f->datalen;
177 } else if (s->format != f->subclass) {
178 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
179 return -1;
181 if (s->len + f->datalen > SMOOTHER_SIZE) {
182 ast_log(LOG_WARNING, "Out of smoother space\n");
183 return -1;
185 if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
186 && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
187 if (!s->len) {
188 /* Optimize by sending the frame we just got
189 on the next read, thus eliminating the douple
190 copy */
191 if (swap)
192 ast_swapcopy_samples(f->data, f->data, f->samples);
193 s->opt = f;
194 return 0;
195 } else {
196 s->optimizablestream++;
197 if (s->optimizablestream > 10) {
198 /* For the past 10 rounds, we have input and output
199 frames of the correct size for this smoother, yet
200 we were unable to optimize because there was still
201 some cruft left over. Lets just drop the cruft so
202 we can move to a fully optimized path */
203 if (swap)
204 ast_swapcopy_samples(f->data, f->data, f->samples);
205 s->len = 0;
206 s->opt = f;
207 return 0;
210 } else
211 s->optimizablestream = 0;
212 if (s->flags & AST_SMOOTHER_FLAG_G729) {
213 if (s->len % 10) {
214 ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
215 return 0;
218 if (swap)
219 ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
220 else
221 memcpy(s->data + s->len, f->data, f->datalen);
222 /* If either side is empty, reset the delivery time */
223 if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) /* XXX really ? */
224 s->delivery = f->delivery;
225 s->len += f->datalen;
226 return 0;
229 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
231 struct ast_frame *opt;
232 int len;
234 /* IF we have an optimization frame, send it */
235 if (s->opt) {
236 if (s->opt->offset < AST_FRIENDLY_OFFSET)
237 ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
238 s->opt->offset);
239 opt = s->opt;
240 s->opt = NULL;
241 return opt;
244 /* Make sure we have enough data */
245 if (s->len < s->size) {
246 /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
247 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
248 return NULL;
250 len = s->size;
251 if (len > s->len)
252 len = s->len;
253 /* Make frame */
254 s->f.frametype = AST_FRAME_VOICE;
255 s->f.subclass = s->format;
256 s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
257 s->f.offset = AST_FRIENDLY_OFFSET;
258 s->f.datalen = len;
259 /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
260 s->f.samples = len * s->samplesperbyte; /* XXX rounding */
261 s->f.delivery = s->delivery;
262 /* Fill Data */
263 memcpy(s->f.data, s->data, len);
264 s->len -= len;
265 /* Move remaining data to the front if applicable */
266 if (s->len) {
267 /* In principle this should all be fine because if we are sending
268 G.729 VAD, the next timestamp will take over anyawy */
269 memmove(s->data, s->data + len, s->len);
270 if (!ast_tvzero(s->delivery)) {
271 /* If we have delivery time, increment it, otherwise, leave it at 0 */
272 s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
275 /* Return frame */
276 return &s->f;
279 void ast_smoother_free(struct ast_smoother *s)
281 free(s);
284 static struct ast_frame *ast_frame_header_new(void)
286 struct ast_frame *f;
287 struct ast_frame_cache *frames;
289 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
290 if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
291 size_t mallocd_len = f->mallocd_hdr_len;
292 memset(f, 0, sizeof(*f));
293 f->mallocd_hdr_len = mallocd_len;
294 f->mallocd = AST_MALLOCD_HDR;
295 frames->size--;
296 return f;
300 if (!(f = ast_calloc(1, sizeof(*f))))
301 return NULL;
303 f->mallocd_hdr_len = sizeof(*f);
304 #ifdef TRACE_FRAMES
305 AST_LIST_LOCK(&headerlist);
306 headers++;
307 AST_LIST_INSERT_HEAD(&headerlist, f, frame_list);
308 AST_LIST_UNLOCK(&headerlist);
309 #endif
311 return f;
314 static void frame_cache_cleanup(void *data)
316 struct ast_frame_cache *frames = data;
317 struct ast_frame *f;
319 while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
320 free(f);
322 free(frames);
325 void ast_frame_free(struct ast_frame *fr, int cache)
327 if (!fr->mallocd)
328 return;
330 if (cache && fr->mallocd == AST_MALLOCD_HDR) {
331 /* Cool, only the header is malloc'd, let's just cache those for now
332 * to keep things simple... */
333 struct ast_frame_cache *frames;
335 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))
336 && frames->size < FRAME_CACHE_MAX_SIZE) {
337 AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
338 frames->size++;
339 return;
343 if (fr->mallocd & AST_MALLOCD_DATA) {
344 if (fr->data)
345 free(fr->data - fr->offset);
347 if (fr->mallocd & AST_MALLOCD_SRC) {
348 if (fr->src)
349 free((char *)fr->src);
351 if (fr->mallocd & AST_MALLOCD_HDR) {
352 #ifdef TRACE_FRAMES
353 AST_LIST_LOCK(&headerlist);
354 headers--;
355 AST_LIST_REMOVE(&headerlist, fr, frame_list);
356 AST_LIST_UNLOCK(&headerlist);
357 #endif
358 free(fr);
363 * \brief 'isolates' a frame by duplicating non-malloc'ed components
364 * (header, src, data).
365 * On return all components are malloc'ed
367 struct ast_frame *ast_frisolate(struct ast_frame *fr)
369 struct ast_frame *out;
370 void *newdata;
372 if (!(fr->mallocd & AST_MALLOCD_HDR)) {
373 /* Allocate a new header if needed */
374 if (!(out = ast_frame_header_new()))
375 return NULL;
376 out->frametype = fr->frametype;
377 out->subclass = fr->subclass;
378 out->datalen = fr->datalen;
379 out->samples = fr->samples;
380 out->offset = fr->offset;
381 out->data = fr->data;
382 /* Copy the timing data */
383 out->has_timing_info = fr->has_timing_info;
384 if (fr->has_timing_info) {
385 out->ts = fr->ts;
386 out->len = fr->len;
387 out->seqno = fr->seqno;
389 } else
390 out = fr;
392 if (!(fr->mallocd & AST_MALLOCD_SRC)) {
393 if (fr->src) {
394 if (!(out->src = ast_strdup(fr->src))) {
395 if (out != fr)
396 free(out);
397 return NULL;
400 } else
401 out->src = fr->src;
403 if (!(fr->mallocd & AST_MALLOCD_DATA)) {
404 if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
405 if (out->src != fr->src)
406 free((void *) out->src);
407 if (out != fr)
408 free(out);
409 return NULL;
411 newdata += AST_FRIENDLY_OFFSET;
412 out->offset = AST_FRIENDLY_OFFSET;
413 out->datalen = fr->datalen;
414 memcpy(newdata, fr->data, fr->datalen);
415 out->data = newdata;
418 out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
420 return out;
423 struct ast_frame *ast_frdup(const struct ast_frame *f)
425 struct ast_frame_cache *frames;
426 struct ast_frame *out = NULL;
427 int len, srclen = 0;
428 void *buf = NULL;
430 /* Start with standard stuff */
431 len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
432 /* If we have a source, add space for it */
434 * XXX Watch out here - if we receive a src which is not terminated
435 * properly, we can be easily attacked. Should limit the size we deal with.
437 if (f->src)
438 srclen = strlen(f->src);
439 if (srclen > 0)
440 len += srclen + 1;
442 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
443 AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
444 if (out->mallocd_hdr_len >= len) {
445 size_t mallocd_len = out->mallocd_hdr_len;
446 AST_LIST_REMOVE_CURRENT(&frames->list, frame_list);
447 memset(out, 0, sizeof(*out));
448 out->mallocd_hdr_len = mallocd_len;
449 buf = out;
450 frames->size--;
451 break;
454 AST_LIST_TRAVERSE_SAFE_END
456 if (!buf) {
457 if (!(buf = ast_calloc(1, len)))
458 return NULL;
459 out = buf;
460 out->mallocd_hdr_len = len;
463 out->frametype = f->frametype;
464 out->subclass = f->subclass;
465 out->datalen = f->datalen;
466 out->samples = f->samples;
467 out->delivery = f->delivery;
468 /* Set us as having malloc'd header only, so it will eventually
469 get freed. */
470 out->mallocd = AST_MALLOCD_HDR;
471 out->offset = AST_FRIENDLY_OFFSET;
472 if (out->datalen) {
473 out->data = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
474 memcpy(out->data, f->data, out->datalen);
476 if (srclen > 0) {
477 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
478 /* Must have space since we allocated for it */
479 strcpy((char *)out->src, f->src);
481 out->has_timing_info = f->has_timing_info;
482 if (f->has_timing_info) {
483 out->ts = f->ts;
484 out->len = f->len;
485 out->seqno = f->seqno;
487 return out;
490 void ast_swapcopy_samples(void *dst, const void *src, int samples)
492 int i;
493 unsigned short *dst_s = dst;
494 const unsigned short *src_s = src;
496 for (i = 0; i < samples; i++)
497 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
501 struct ast_format_list *ast_get_format_list_index(int index)
503 return &AST_FORMAT_LIST[index];
506 struct ast_format_list *ast_get_format_list(size_t *size)
508 *size = (sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]));
509 return AST_FORMAT_LIST;
512 char* ast_getformatname(int format)
514 int x;
515 char *ret = "unknown";
516 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
517 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
518 ret = AST_FORMAT_LIST[x].name;
519 break;
522 return ret;
525 char *ast_getformatname_multiple(char *buf, size_t size, int format)
527 int x;
528 unsigned len;
529 char *start, *end = buf;
531 if (!size)
532 return buf;
533 snprintf(end, size, "0x%x (", format);
534 len = strlen(end);
535 end += len;
536 size -= len;
537 start = end;
538 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
539 if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
540 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
541 len = strlen(end);
542 end += len;
543 size -= len;
546 if (start == end)
547 snprintf(start, size, "nothing)");
548 else if (size > 1)
549 *(end -1) = ')';
550 return buf;
553 static struct ast_codec_alias_table {
554 char *alias;
555 char *realname;
556 } ast_codec_alias_table[] = {
557 { "slinear", "slin"},
558 { "g723.1", "g723"},
561 static const char *ast_expand_codec_alias(const char *in)
563 int x;
565 for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(ast_codec_alias_table[0]); x++) {
566 if(!strcmp(in,ast_codec_alias_table[x].alias))
567 return ast_codec_alias_table[x].realname;
569 return in;
572 int ast_getformatbyname(const char *name)
574 int x, all, format = 0;
576 all = strcasecmp(name, "all") ? 0 : 1;
577 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
578 if(AST_FORMAT_LIST[x].visible && (all ||
579 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
580 !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
581 format |= AST_FORMAT_LIST[x].bits;
582 if(!all)
583 break;
587 return format;
590 char *ast_codec2str(int codec)
592 int x;
593 char *ret = "unknown";
594 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
595 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
596 ret = AST_FORMAT_LIST[x].desc;
597 break;
600 return ret;
603 static int show_codecs_deprecated(int fd, int argc, char *argv[])
605 int i, found=0;
606 char hex[25];
608 if ((argc < 2) || (argc > 3))
609 return RESULT_SHOWUSAGE;
611 if (!ast_opt_dont_warn)
612 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
613 "\tIt does not indicate anything about your configuration.\n");
615 ast_cli(fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
616 ast_cli(fd, "--------------------------------------------------------------------------------\n");
617 if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
618 found = 1;
619 for (i=0;i<13;i++) {
620 snprintf(hex,25,"(0x%x)",1<<i);
621 ast_cli(fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
625 if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
626 found = 1;
627 for (i=16;i<18;i++) {
628 snprintf(hex,25,"(0x%x)",1<<i);
629 ast_cli(fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
633 if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
634 found = 1;
635 for (i=18;i<22;i++) {
636 snprintf(hex,25,"(0x%x)",1<<i);
637 ast_cli(fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
641 if (! found)
642 return RESULT_SHOWUSAGE;
643 else
644 return RESULT_SUCCESS;
647 static int show_codecs(int fd, int argc, char *argv[])
649 int i, found=0;
650 char hex[25];
652 if ((argc < 3) || (argc > 4))
653 return RESULT_SHOWUSAGE;
655 if (!ast_opt_dont_warn)
656 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
657 "\tIt does not indicate anything about your configuration.\n");
659 ast_cli(fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
660 ast_cli(fd, "--------------------------------------------------------------------------------\n");
661 if ((argc == 3) || (!strcasecmp(argv[3],"audio"))) {
662 found = 1;
663 for (i=0;i<13;i++) {
664 snprintf(hex,25,"(0x%x)",1<<i);
665 ast_cli(fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
669 if ((argc == 3) || (!strcasecmp(argv[3],"image"))) {
670 found = 1;
671 for (i=16;i<18;i++) {
672 snprintf(hex,25,"(0x%x)",1<<i);
673 ast_cli(fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
677 if ((argc == 3) || (!strcasecmp(argv[3],"video"))) {
678 found = 1;
679 for (i=18;i<22;i++) {
680 snprintf(hex,25,"(0x%x)",1<<i);
681 ast_cli(fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
685 if (! found)
686 return RESULT_SHOWUSAGE;
687 else
688 return RESULT_SUCCESS;
691 static char frame_show_codecs_usage[] =
692 "Usage: core show codecs [audio|video|image]\n"
693 " Displays codec mapping\n";
695 static int show_codec_n_deprecated(int fd, int argc, char *argv[])
697 int codec, i, found=0;
699 if (argc != 3)
700 return RESULT_SHOWUSAGE;
702 if (sscanf(argv[2],"%d",&codec) != 1)
703 return RESULT_SHOWUSAGE;
705 for (i = 0; i < 32; i++)
706 if (codec & (1 << i)) {
707 found = 1;
708 ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
711 if (!found)
712 ast_cli(fd, "Codec %d not found\n", codec);
714 return RESULT_SUCCESS;
717 static int show_codec_n(int fd, int argc, char *argv[])
719 int codec, i, found=0;
721 if (argc != 4)
722 return RESULT_SHOWUSAGE;
724 if (sscanf(argv[3],"%d",&codec) != 1)
725 return RESULT_SHOWUSAGE;
727 for (i = 0; i < 32; i++)
728 if (codec & (1 << i)) {
729 found = 1;
730 ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
733 if (!found)
734 ast_cli(fd, "Codec %d not found\n", codec);
736 return RESULT_SUCCESS;
739 static char frame_show_codec_n_usage[] =
740 "Usage: core show codec <number>\n"
741 " Displays codec mapping\n";
743 /*! Dump a frame for debugging purposes */
744 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
746 const char noname[] = "unknown";
747 char ftype[40] = "Unknown Frametype";
748 char cft[80];
749 char subclass[40] = "Unknown Subclass";
750 char csub[80];
751 char moreinfo[40] = "";
752 char cn[60];
753 char cp[40];
754 char cmn[40];
756 if (!name)
757 name = noname;
760 if (!f) {
761 ast_verbose("%s [ %s (NULL) ] [%s]\n",
762 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
763 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
764 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
765 return;
767 /* XXX We should probably print one each of voice and video when the format changes XXX */
768 if (f->frametype == AST_FRAME_VOICE)
769 return;
770 if (f->frametype == AST_FRAME_VIDEO)
771 return;
772 switch(f->frametype) {
773 case AST_FRAME_DTMF_BEGIN:
774 strcpy(ftype, "DTMF Begin");
775 subclass[0] = f->subclass;
776 subclass[1] = '\0';
777 break;
778 case AST_FRAME_DTMF_END:
779 strcpy(ftype, "DTMF End");
780 subclass[0] = f->subclass;
781 subclass[1] = '\0';
782 break;
783 case AST_FRAME_CONTROL:
784 strcpy(ftype, "Control");
785 switch(f->subclass) {
786 case AST_CONTROL_HANGUP:
787 strcpy(subclass, "Hangup");
788 break;
789 case AST_CONTROL_RING:
790 strcpy(subclass, "Ring");
791 break;
792 case AST_CONTROL_RINGING:
793 strcpy(subclass, "Ringing");
794 break;
795 case AST_CONTROL_ANSWER:
796 strcpy(subclass, "Answer");
797 break;
798 case AST_CONTROL_BUSY:
799 strcpy(subclass, "Busy");
800 break;
801 case AST_CONTROL_TAKEOFFHOOK:
802 strcpy(subclass, "Take Off Hook");
803 break;
804 case AST_CONTROL_OFFHOOK:
805 strcpy(subclass, "Line Off Hook");
806 break;
807 case AST_CONTROL_CONGESTION:
808 strcpy(subclass, "Congestion");
809 break;
810 case AST_CONTROL_FLASH:
811 strcpy(subclass, "Flash");
812 break;
813 case AST_CONTROL_WINK:
814 strcpy(subclass, "Wink");
815 break;
816 case AST_CONTROL_OPTION:
817 strcpy(subclass, "Option");
818 break;
819 case AST_CONTROL_RADIO_KEY:
820 strcpy(subclass, "Key Radio");
821 break;
822 case AST_CONTROL_RADIO_UNKEY:
823 strcpy(subclass, "Unkey Radio");
824 break;
825 case -1:
826 strcpy(subclass, "Stop generators");
827 break;
828 default:
829 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
831 break;
832 case AST_FRAME_NULL:
833 strcpy(ftype, "Null Frame");
834 strcpy(subclass, "N/A");
835 break;
836 case AST_FRAME_IAX:
837 /* Should never happen */
838 strcpy(ftype, "IAX Specific");
839 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
840 break;
841 case AST_FRAME_TEXT:
842 strcpy(ftype, "Text");
843 strcpy(subclass, "N/A");
844 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
845 break;
846 case AST_FRAME_IMAGE:
847 strcpy(ftype, "Image");
848 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
849 break;
850 case AST_FRAME_HTML:
851 strcpy(ftype, "HTML");
852 switch(f->subclass) {
853 case AST_HTML_URL:
854 strcpy(subclass, "URL");
855 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
856 break;
857 case AST_HTML_DATA:
858 strcpy(subclass, "Data");
859 break;
860 case AST_HTML_BEGIN:
861 strcpy(subclass, "Begin");
862 break;
863 case AST_HTML_END:
864 strcpy(subclass, "End");
865 break;
866 case AST_HTML_LDCOMPLETE:
867 strcpy(subclass, "Load Complete");
868 break;
869 case AST_HTML_NOSUPPORT:
870 strcpy(subclass, "No Support");
871 break;
872 case AST_HTML_LINKURL:
873 strcpy(subclass, "Link URL");
874 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
875 break;
876 case AST_HTML_UNLINK:
877 strcpy(subclass, "Unlink");
878 break;
879 case AST_HTML_LINKREJECT:
880 strcpy(subclass, "Link Reject");
881 break;
882 default:
883 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
884 break;
886 break;
887 case AST_FRAME_MODEM:
888 strcpy(ftype, "Modem");
889 switch (f->subclass) {
890 case AST_MODEM_T38:
891 strcpy(subclass, "T.38");
892 break;
893 case AST_MODEM_V150:
894 strcpy(subclass, "V.150");
895 break;
896 default:
897 snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
898 break;
900 break;
901 default:
902 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
904 if (!ast_strlen_zero(moreinfo))
905 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
906 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
907 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
908 f->frametype,
909 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
910 f->subclass,
911 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
912 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
913 else
914 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
915 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
916 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
917 f->frametype,
918 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
919 f->subclass,
920 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
924 #ifdef TRACE_FRAMES
925 static int show_frame_stats_deprecated(int fd, int argc, char *argv[])
927 struct ast_frame *f;
928 int x=1;
929 if (argc != 3)
930 return RESULT_SHOWUSAGE;
931 AST_LIST_LOCK(&headerlist);
932 ast_cli(fd, " Framer Statistics \n");
933 ast_cli(fd, "---------------------------\n");
934 ast_cli(fd, "Total allocated headers: %d\n", headers);
935 ast_cli(fd, "Queue Dump:\n");
936 AST_LIST_TRAVERSE(&headerlist, f, frame_list)
937 ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
938 AST_LIST_UNLOCK(&headerlist);
939 return RESULT_SUCCESS;
942 static int show_frame_stats(int fd, int argc, char *argv[])
944 struct ast_frame *f;
945 int x=1;
946 if (argc != 4)
947 return RESULT_SHOWUSAGE;
948 AST_LIST_LOCK(&headerlist);
949 ast_cli(fd, " Framer Statistics \n");
950 ast_cli(fd, "---------------------------\n");
951 ast_cli(fd, "Total allocated headers: %d\n", headers);
952 ast_cli(fd, "Queue Dump:\n");
953 AST_LIST_TRAVERSE(&headerlist, f, frame_list)
954 ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
955 AST_LIST_UNLOCK(&headerlist);
956 return RESULT_SUCCESS;
959 static char frame_stats_usage[] =
960 "Usage: core show frame stats\n"
961 " Displays debugging statistics from framer\n";
962 #endif
964 /* Builtin Asterisk CLI-commands for debugging */
965 static struct ast_cli_entry cli_show_codecs = {
966 { "show", "codecs", NULL },
967 show_codecs_deprecated, NULL,
968 NULL };
970 static struct ast_cli_entry cli_show_audio_codecs = {
971 { "show", "audio", "codecs", NULL },
972 show_codecs_deprecated, NULL,
973 NULL };
975 static struct ast_cli_entry cli_show_video_codecs = {
976 { "show", "video", "codecs", NULL },
977 show_codecs_deprecated, NULL,
978 NULL };
980 static struct ast_cli_entry cli_show_image_codecs = {
981 { "show", "image", "codecs", NULL },
982 show_codecs_deprecated, NULL,
983 NULL };
985 static struct ast_cli_entry cli_show_codec = {
986 { "show", "codec", NULL },
987 show_codec_n_deprecated, NULL,
988 NULL };
990 #ifdef TRACE_FRAMES
991 static struct ast_cli_entry cli_show_frame_stats = {
992 { "show", "frame", "stats", NULL },
993 show_frame_stats, NULL,
994 NULL };
995 #endif
997 static struct ast_cli_entry my_clis[] = {
998 { { "core", "show", "codecs", NULL },
999 show_codecs, "Displays a list of codecs",
1000 frame_show_codecs_usage, NULL, &cli_show_codecs },
1002 { { "core", "show", "audio", "codecs", NULL },
1003 show_codecs, "Displays a list of audio codecs",
1004 frame_show_codecs_usage, NULL, &cli_show_audio_codecs },
1006 { { "core", "show", "video", "codecs", NULL },
1007 show_codecs, "Displays a list of video codecs",
1008 frame_show_codecs_usage, NULL, &cli_show_video_codecs },
1010 { { "core", "show", "image", "codecs", NULL },
1011 show_codecs, "Displays a list of image codecs",
1012 frame_show_codecs_usage, NULL, &cli_show_image_codecs },
1014 { { "core", "show", "codec", NULL },
1015 show_codec_n, "Shows a specific codec",
1016 frame_show_codec_n_usage, NULL, &cli_show_codec },
1018 #ifdef TRACE_FRAMES
1019 { { "core", "show", "frame", "stats", NULL },
1020 show_frame_stats, "Shows frame statistics",
1021 frame_stats_usage, NULL, &cli_show_frame_stats },
1022 #endif
1025 int init_framer(void)
1027 ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
1028 return 0;
1031 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
1033 int x, differential = (int) 'A', mem;
1034 char *from, *to;
1036 if(right) {
1037 from = pref->order;
1038 to = buf;
1039 mem = size;
1040 } else {
1041 to = pref->order;
1042 from = buf;
1043 mem = 32;
1046 memset(to, 0, mem);
1047 for (x = 0; x < 32 ; x++) {
1048 if(!from[x])
1049 break;
1050 to[x] = right ? (from[x] + differential) : (from[x] - differential);
1054 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
1056 int x, codec;
1057 size_t total_len, slen;
1058 char *formatname;
1060 memset(buf,0,size);
1061 total_len = size;
1062 buf[0] = '(';
1063 total_len--;
1064 for(x = 0; x < 32 ; x++) {
1065 if(total_len <= 0)
1066 break;
1067 if(!(codec = ast_codec_pref_index(pref,x)))
1068 break;
1069 if((formatname = ast_getformatname(codec))) {
1070 slen = strlen(formatname);
1071 if(slen > total_len)
1072 break;
1073 strncat(buf,formatname,total_len);
1074 total_len -= slen;
1076 if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
1077 strncat(buf,"|",total_len);
1078 total_len--;
1081 if(total_len) {
1082 strncat(buf,")",total_len);
1083 total_len--;
1086 return size - total_len;
1089 int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
1091 int slot = 0;
1094 if((index >= 0) && (index < sizeof(pref->order))) {
1095 slot = pref->order[index];
1098 return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
1101 /*! \brief Remove codec from pref list */
1102 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
1104 struct ast_codec_pref oldorder;
1105 int x, y = 0;
1106 int slot;
1107 int size;
1109 if(!pref->order[0])
1110 return;
1112 memcpy(&oldorder, pref, sizeof(oldorder));
1113 memset(pref, 0, sizeof(*pref));
1115 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1116 slot = oldorder.order[x];
1117 size = oldorder.framing[x];
1118 if(! slot)
1119 break;
1120 if(AST_FORMAT_LIST[slot-1].bits != format) {
1121 pref->order[y] = slot;
1122 pref->framing[y++] = size;
1128 /*! \brief Append codec to list */
1129 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
1131 int x, newindex = -1;
1133 ast_codec_pref_remove(pref, format);
1135 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1136 if(AST_FORMAT_LIST[x].bits == format) {
1137 newindex = x + 1;
1138 break;
1142 if(newindex) {
1143 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1144 if(!pref->order[x]) {
1145 pref->order[x] = newindex;
1146 break;
1151 return x;
1155 /*! \brief Set packet size for codec */
1156 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
1158 int x, index = -1;
1160 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1161 if(AST_FORMAT_LIST[x].bits == format) {
1162 index = x;
1163 break;
1167 if(index < 0)
1168 return -1;
1170 /* size validation */
1171 if(!framems)
1172 framems = AST_FORMAT_LIST[index].def_ms;
1174 if(AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1175 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1177 if(framems < AST_FORMAT_LIST[index].min_ms)
1178 framems = AST_FORMAT_LIST[index].min_ms;
1180 if(framems > AST_FORMAT_LIST[index].max_ms)
1181 framems = AST_FORMAT_LIST[index].max_ms;
1184 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1185 if(pref->order[x] == (index + 1)) {
1186 pref->framing[x] = framems;
1187 break;
1191 return x;
1194 /*! \brief Get packet size for codec */
1195 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
1197 int x, index = -1, framems = 0;
1198 struct ast_format_list fmt;
1200 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1201 if(AST_FORMAT_LIST[x].bits == format) {
1202 fmt = AST_FORMAT_LIST[x];
1203 index = x;
1204 break;
1208 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1209 if(pref->order[x] == (index + 1)) {
1210 framems = pref->framing[x];
1211 break;
1215 /* size validation */
1216 if(!framems)
1217 framems = AST_FORMAT_LIST[index].def_ms;
1219 if(AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1220 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1222 if(framems < AST_FORMAT_LIST[index].min_ms)
1223 framems = AST_FORMAT_LIST[index].min_ms;
1225 if(framems > AST_FORMAT_LIST[index].max_ms)
1226 framems = AST_FORMAT_LIST[index].max_ms;
1228 fmt.cur_ms = framems;
1230 return fmt;
1233 /*! \brief Pick a codec */
1234 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
1236 int x, ret = 0, slot;
1238 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1239 slot = pref->order[x];
1241 if (!slot)
1242 break;
1243 if (formats & AST_FORMAT_LIST[slot-1].bits) {
1244 ret = AST_FORMAT_LIST[slot-1].bits;
1245 break;
1248 if(ret & AST_FORMAT_AUDIO_MASK)
1249 return ret;
1251 if (option_debug > 3)
1252 ast_log(LOG_DEBUG, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1254 return find_best ? ast_best_codec(formats) : 0;
1257 void ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
1259 char *parse = NULL, *this = NULL, *psize = NULL;
1260 int format = 0, framems = 0;
1262 parse = ast_strdupa(list);
1263 while ((this = strsep(&parse, ","))) {
1264 framems = 0;
1265 if ((psize = strrchr(this, ':'))) {
1266 *psize++ = '\0';
1267 if (option_debug)
1268 ast_log(LOG_DEBUG,"Packetization for codec: %s is %s\n", this, psize);
1269 framems = atoi(psize);
1270 if (framems < 0)
1271 framems = 0;
1273 if (!(format = ast_getformatbyname(this))) {
1274 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1275 continue;
1278 if (mask) {
1279 if (allowing)
1280 *mask |= format;
1281 else
1282 *mask &= ~format;
1285 /* Set up a preference list for audio. Do not include video in preferences
1286 since we can not transcode video and have to use whatever is offered
1288 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1289 if (strcasecmp(this, "all")) {
1290 if (allowing) {
1291 ast_codec_pref_append(pref, format);
1292 ast_codec_pref_setsize(pref, format, framems);
1294 else
1295 ast_codec_pref_remove(pref, format);
1296 } else if (!allowing) {
1297 memset(pref, 0, sizeof(*pref));
1303 static int g723_len(unsigned char buf)
1305 enum frame_type type = buf & TYPE_MASK;
1307 switch(type) {
1308 case TYPE_DONTSEND:
1309 return 0;
1310 break;
1311 case TYPE_SILENCE:
1312 return 4;
1313 break;
1314 case TYPE_HIGH:
1315 return 24;
1316 break;
1317 case TYPE_LOW:
1318 return 20;
1319 break;
1320 default:
1321 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
1323 return -1;
1326 static int g723_samples(unsigned char *buf, int maxlen)
1328 int pos = 0;
1329 int samples = 0;
1330 int res;
1331 while(pos < maxlen) {
1332 res = g723_len(buf[pos]);
1333 if (res <= 0)
1334 break;
1335 samples += 240;
1336 pos += res;
1338 return samples;
1341 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1343 int byte = bit / 8; /* byte containing first bit */
1344 int rem = 8 - (bit % 8); /* remaining bits in first byte */
1345 unsigned char ret = 0;
1347 if (n <= 0 || n > 8)
1348 return 0;
1350 if (rem < n) {
1351 ret = (data[byte] << (n - rem));
1352 ret |= (data[byte + 1] >> (8 - n + rem));
1353 } else {
1354 ret = (data[byte] >> (rem - n));
1357 return (ret & (0xff >> (8 - n)));
1360 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1362 static int SpeexWBSubModeSz[] = {
1363 0, 36, 112, 192,
1364 352, 0, 0, 0 };
1365 int off = bit;
1366 unsigned char c;
1368 /* skip up to two wideband frames */
1369 if (((len * 8 - off) >= 5) &&
1370 get_n_bits_at(data, 1, off)) {
1371 c = get_n_bits_at(data, 3, off + 1);
1372 off += SpeexWBSubModeSz[c];
1374 if (((len * 8 - off) >= 5) &&
1375 get_n_bits_at(data, 1, off)) {
1376 c = get_n_bits_at(data, 3, off + 1);
1377 off += SpeexWBSubModeSz[c];
1379 if (((len * 8 - off) >= 5) &&
1380 get_n_bits_at(data, 1, off)) {
1381 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1382 return -1;
1387 return off - bit;
1390 static int speex_samples(unsigned char *data, int len)
1392 static int SpeexSubModeSz[] = {
1393 5, 43, 119, 160,
1394 220, 300, 364, 492,
1395 79, 0, 0, 0,
1396 0, 0, 0, 0 };
1397 static int SpeexInBandSz[] = {
1398 1, 1, 4, 4,
1399 4, 4, 4, 4,
1400 8, 8, 16, 16,
1401 32, 32, 64, 64 };
1402 int bit = 0;
1403 int cnt = 0;
1404 int off;
1405 unsigned char c;
1407 while ((len * 8 - bit) >= 5) {
1408 /* skip wideband frames */
1409 off = speex_get_wb_sz_at(data, len, bit);
1410 if (off < 0) {
1411 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1412 break;
1414 bit += off;
1416 if ((len * 8 - bit) < 5) {
1417 ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1418 break;
1421 /* get control bits */
1422 c = get_n_bits_at(data, 5, bit);
1423 bit += 5;
1425 if (c == 15) {
1426 /* terminator */
1427 break;
1428 } else if (c == 14) {
1429 /* in-band signal; next 4 bits contain signal id */
1430 c = get_n_bits_at(data, 4, bit);
1431 bit += 4;
1432 bit += SpeexInBandSz[c];
1433 } else if (c == 13) {
1434 /* user in-band; next 5 bits contain msg len */
1435 c = get_n_bits_at(data, 5, bit);
1436 bit += 5;
1437 bit += c * 8;
1438 } else if (c > 8) {
1439 /* unknown */
1440 break;
1441 } else {
1442 /* skip number bits for submode (less the 5 control bits) */
1443 bit += SpeexSubModeSz[c] - 5;
1444 cnt += 160; /* new frame */
1447 return cnt;
1450 int ast_codec_get_samples(struct ast_frame *f)
1452 int samples=0;
1453 switch(f->subclass) {
1454 case AST_FORMAT_SPEEX:
1455 samples = speex_samples(f->data, f->datalen);
1456 break;
1457 case AST_FORMAT_G723_1:
1458 samples = g723_samples(f->data, f->datalen);
1459 break;
1460 case AST_FORMAT_ILBC:
1461 samples = 240 * (f->datalen / 50);
1462 break;
1463 case AST_FORMAT_GSM:
1464 samples = 160 * (f->datalen / 33);
1465 break;
1466 case AST_FORMAT_G729A:
1467 samples = f->datalen * 8;
1468 break;
1469 case AST_FORMAT_SLINEAR:
1470 samples = f->datalen / 2;
1471 break;
1472 case AST_FORMAT_LPC10:
1473 /* assumes that the RTP packet contains one LPC10 frame */
1474 samples = 22 * 8;
1475 samples += (((char *)(f->data))[7] & 0x1) * 8;
1476 break;
1477 case AST_FORMAT_ULAW:
1478 case AST_FORMAT_ALAW:
1479 case AST_FORMAT_G722:
1480 samples = f->datalen;
1481 break;
1482 case AST_FORMAT_ADPCM:
1483 case AST_FORMAT_G726:
1484 case AST_FORMAT_G726_AAL2:
1485 samples = f->datalen * 2;
1486 break;
1487 default:
1488 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1490 return samples;
1493 int ast_codec_get_len(int format, int samples)
1495 int len = 0;
1497 /* XXX Still need speex, g723, and lpc10 XXX */
1498 switch(format) {
1499 case AST_FORMAT_ILBC:
1500 len = (samples / 240) * 50;
1501 break;
1502 case AST_FORMAT_GSM:
1503 len = (samples / 160) * 33;
1504 break;
1505 case AST_FORMAT_G729A:
1506 len = samples / 8;
1507 break;
1508 case AST_FORMAT_SLINEAR:
1509 len = samples * 2;
1510 break;
1511 case AST_FORMAT_ULAW:
1512 case AST_FORMAT_ALAW:
1513 len = samples;
1514 break;
1515 case AST_FORMAT_ADPCM:
1516 case AST_FORMAT_G726:
1517 case AST_FORMAT_G726_AAL2:
1518 len = samples / 2;
1519 break;
1520 default:
1521 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1524 return len;
1527 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1529 int count;
1530 short *fdata = f->data;
1531 short adjust_value = abs(adjustment);
1533 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
1534 return -1;
1536 if (!adjustment)
1537 return 0;
1539 for (count = 0; count < f->samples; count++) {
1540 if (adjustment > 0) {
1541 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1542 } else if (adjustment < 0) {
1543 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1547 return 0;
1550 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1552 int count;
1553 short *data1, *data2;
1555 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
1556 return -1;
1558 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
1559 return -1;
1561 if (f1->samples != f2->samples)
1562 return -1;
1564 for (count = 0, data1 = f1->data, data2 = f2->data;
1565 count < f1->samples;
1566 count++, data1++, data2++)
1567 ast_slinear_saturated_add(data1, data2);
1569 return 0;