Fix samples vs. length calculations for g722
[asterisk-bristuff.git] / main / frame.c
blobd6400a9afcd5418f900622e17b6500d435466d9d
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;
49 static AST_LIST_HEAD_STATIC(headerlist, ast_frame);
50 #endif
52 #if !defined(LOW_MEMORY)
53 static void frame_cache_cleanup(void *data);
55 /*! \brief A per-thread cache of frame headers */
56 AST_THREADSTORAGE_CUSTOM(frame_cache, frame_cache_init, frame_cache_cleanup);
58 /*!
59 * \brief Maximum ast_frame cache size
61 * In most cases where the frame header cache will be useful, the size
62 * of the cache will stay very small. However, it is not always the case that
63 * the same thread that allocates the frame will be the one freeing them, so
64 * sometimes a thread will never have any frames in its cache, or the cache
65 * will never be pulled from. For the latter case, we limit the maximum size.
66 */
67 #define FRAME_CACHE_MAX_SIZE 10
69 /*! \brief This is just so ast_frames, a list head struct for holding a list of
70 * ast_frame structures, is defined. */
71 AST_LIST_HEAD_NOLOCK(ast_frames, ast_frame);
73 struct ast_frame_cache {
74 struct ast_frames list;
75 size_t size;
77 #endif
79 #define SMOOTHER_SIZE 8000
81 enum frame_type {
82 TYPE_HIGH, /* 0x0 */
83 TYPE_LOW, /* 0x1 */
84 TYPE_SILENCE, /* 0x2 */
85 TYPE_DONTSEND /* 0x3 */
88 #define TYPE_MASK 0x3
90 struct ast_smoother {
91 int size;
92 int format;
93 int readdata;
94 int optimizablestream;
95 int flags;
96 float samplesperbyte;
97 struct ast_frame f;
98 struct timeval delivery;
99 char data[SMOOTHER_SIZE];
100 char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
101 struct ast_frame *opt;
102 int len;
105 /*! \brief Definition of supported media formats (codecs) */
106 static struct ast_format_list AST_FORMAT_LIST[] = { /*!< Bit number: comment - Bit numbers are hard coded in show_codec() */
107 { 1, AST_FORMAT_G723_1 , "g723" , "G.723.1", 24, 30, 300, 30, 30 }, /*!< 1 */
108 { 1, AST_FORMAT_GSM, "gsm" , "GSM", 33, 20, 300, 20, 20 }, /*!< 2: codec_gsm.c */
109 { 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law", 80, 10, 150, 10, 20 }, /*!< 3: codec_ulaw.c */
110 { 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law", 80, 10, 150, 10, 20 }, /*!< 4: codec_alaw.c */
111 { 1, AST_FORMAT_G726, "g726", "G.726 RFC3551", 40, 10, 300, 10, 20 }, /*!< 5: codec_g726.c */
112 { 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM", 40, 10, 300, 10, 20 }, /*!< 6: codec_adpcm.c */
113 { 1, AST_FORMAT_SLINEAR, "slin", "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE }, /*!< 7 */
114 { 1, AST_FORMAT_LPC10, "lpc10", "LPC10", 7, 20, 20, 20, 20 }, /*!< 8: codec_lpc10.c */
115 { 1, AST_FORMAT_G729A, "g729", "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 }, /*!< 9: Binary commercial distribution */
116 { 1, AST_FORMAT_SPEEX, "speex", "SpeeX", 10, 10, 60, 10, 20 }, /*!< 10: codec_speex.c */
117 { 1, AST_FORMAT_ILBC, "ilbc", "iLBC", 50, 30, 30, 30, 30 }, /*!< 11: codec_ilbc.c */ /* inc=30ms - workaround */
118 { 1, AST_FORMAT_G726_AAL2, "g726aal2", "G.726 AAL2", 40, 10, 300, 10, 20 }, /*!< 12: codec_g726.c */
119 { 1, AST_FORMAT_G722, "g722", "G722"}, /*!< 13 */
120 { 0, 0, "nothing", "undefined" },
121 { 0, 0, "nothing", "undefined" },
122 { 0, 0, "nothing", "undefined" },
123 { 0, 0, "nothing", "undefined" },
124 { 0, AST_FORMAT_MAX_AUDIO, "maxaudio", "Maximum audio format" },
125 { 1, AST_FORMAT_JPEG, "jpeg", "JPEG image"}, /*!< 17: See format_jpeg.c */
126 { 1, AST_FORMAT_PNG, "png", "PNG image"}, /*!< 18: Image format */
127 { 1, AST_FORMAT_H261, "h261", "H.261 Video" }, /*!< 19: Video Passthrough */
128 { 1, AST_FORMAT_H263, "h263", "H.263 Video" }, /*!< 20: Passthrough support, see format_h263.c */
129 { 1, AST_FORMAT_H263_PLUS, "h263p", "H.263+ Video" }, /*!< 21: See format_h263.c */
130 { 1, AST_FORMAT_H264, "h264", "H.264 Video" }, /*!< 22: Passthrough support, see format_h263.c */
131 { 0, 0, "nothing", "undefined" },
132 { 0, 0, "nothing", "undefined" },
133 { 0, 0, "nothing", "undefined" },
134 { 0, AST_FORMAT_MAX_VIDEO, "maxvideo", "Maximum video format" },
137 struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
139 void ast_smoother_reset(struct ast_smoother *s, int size)
141 memset(s, 0, sizeof(*s));
142 s->size = size;
145 struct ast_smoother *ast_smoother_new(int size)
147 struct ast_smoother *s;
148 if (size < 1)
149 return NULL;
150 if ((s = ast_malloc(sizeof(*s))))
151 ast_smoother_reset(s, size);
152 return s;
155 int ast_smoother_get_flags(struct ast_smoother *s)
157 return s->flags;
160 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
162 s->flags = flags;
165 int ast_smoother_test_flag(struct ast_smoother *s, int flag)
167 return (s->flags & flag);
170 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
172 if (f->frametype != AST_FRAME_VOICE) {
173 ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
174 return -1;
176 if (!s->format) {
177 s->format = f->subclass;
178 s->samplesperbyte = (float)f->samples / (float)f->datalen;
179 } else if (s->format != f->subclass) {
180 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
181 return -1;
183 if (s->len + f->datalen > SMOOTHER_SIZE) {
184 ast_log(LOG_WARNING, "Out of smoother space\n");
185 return -1;
187 if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
188 && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
189 if (!s->len) {
190 /* Optimize by sending the frame we just got
191 on the next read, thus eliminating the douple
192 copy */
193 if (swap)
194 ast_swapcopy_samples(f->data, f->data, f->samples);
195 s->opt = f;
196 return 0;
197 } else {
198 s->optimizablestream++;
199 if (s->optimizablestream > 10) {
200 /* For the past 10 rounds, we have input and output
201 frames of the correct size for this smoother, yet
202 we were unable to optimize because there was still
203 some cruft left over. Lets just drop the cruft so
204 we can move to a fully optimized path */
205 if (swap)
206 ast_swapcopy_samples(f->data, f->data, f->samples);
207 s->len = 0;
208 s->opt = f;
209 return 0;
212 } else
213 s->optimizablestream = 0;
214 if (s->flags & AST_SMOOTHER_FLAG_G729) {
215 if (s->len % 10) {
216 ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
217 return 0;
220 if (swap)
221 ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
222 else
223 memcpy(s->data + s->len, f->data, f->datalen);
224 /* If either side is empty, reset the delivery time */
225 if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) /* XXX really ? */
226 s->delivery = f->delivery;
227 s->len += f->datalen;
228 return 0;
231 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
233 struct ast_frame *opt;
234 int len;
236 /* IF we have an optimization frame, send it */
237 if (s->opt) {
238 if (s->opt->offset < AST_FRIENDLY_OFFSET)
239 ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
240 s->opt->offset);
241 opt = s->opt;
242 s->opt = NULL;
243 return opt;
246 /* Make sure we have enough data */
247 if (s->len < s->size) {
248 /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
249 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
250 return NULL;
252 len = s->size;
253 if (len > s->len)
254 len = s->len;
255 /* Make frame */
256 s->f.frametype = AST_FRAME_VOICE;
257 s->f.subclass = s->format;
258 s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
259 s->f.offset = AST_FRIENDLY_OFFSET;
260 s->f.datalen = len;
261 /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
262 s->f.samples = len * s->samplesperbyte; /* XXX rounding */
263 s->f.delivery = s->delivery;
264 /* Fill Data */
265 memcpy(s->f.data, s->data, len);
266 s->len -= len;
267 /* Move remaining data to the front if applicable */
268 if (s->len) {
269 /* In principle this should all be fine because if we are sending
270 G.729 VAD, the next timestamp will take over anyawy */
271 memmove(s->data, s->data + len, s->len);
272 if (!ast_tvzero(s->delivery)) {
273 /* If we have delivery time, increment it, otherwise, leave it at 0 */
274 s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
277 /* Return frame */
278 return &s->f;
281 void ast_smoother_free(struct ast_smoother *s)
283 free(s);
286 static struct ast_frame *ast_frame_header_new(void)
288 struct ast_frame *f;
290 #if !defined(LOW_MEMORY)
291 struct ast_frame_cache *frames;
293 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
294 if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
295 size_t mallocd_len = f->mallocd_hdr_len;
296 memset(f, 0, sizeof(*f));
297 f->mallocd_hdr_len = mallocd_len;
298 f->mallocd = AST_MALLOCD_HDR;
299 frames->size--;
300 return f;
303 if (!(f = ast_calloc_cache(1, sizeof(*f))))
304 return NULL;
305 #else
306 if (!(f = ast_calloc(1, sizeof(*f))))
307 return NULL;
308 #endif
310 f->mallocd_hdr_len = sizeof(*f);
311 #ifdef TRACE_FRAMES
312 AST_LIST_LOCK(&headerlist);
313 headers++;
314 AST_LIST_INSERT_HEAD(&headerlist, f, frame_list);
315 AST_LIST_UNLOCK(&headerlist);
316 #endif
318 return f;
321 #if !defined(LOW_MEMORY)
322 static void frame_cache_cleanup(void *data)
324 struct ast_frame_cache *frames = data;
325 struct ast_frame *f;
327 while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
328 free(f);
330 free(frames);
332 #endif
334 void ast_frame_free(struct ast_frame *fr, int cache)
336 if (!fr->mallocd)
337 return;
339 #if !defined(LOW_MEMORY)
340 if (cache && fr->mallocd == AST_MALLOCD_HDR) {
341 /* Cool, only the header is malloc'd, let's just cache those for now
342 * to keep things simple... */
343 struct ast_frame_cache *frames;
345 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))
346 && frames->size < FRAME_CACHE_MAX_SIZE) {
347 AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
348 frames->size++;
349 return;
352 #endif
354 if (fr->mallocd & AST_MALLOCD_DATA) {
355 if (fr->data)
356 free(fr->data - fr->offset);
358 if (fr->mallocd & AST_MALLOCD_SRC) {
359 if (fr->src)
360 free((char *)fr->src);
362 if (fr->mallocd & AST_MALLOCD_HDR) {
363 #ifdef TRACE_FRAMES
364 AST_LIST_LOCK(&headerlist);
365 headers--;
366 AST_LIST_REMOVE(&headerlist, fr, frame_list);
367 AST_LIST_UNLOCK(&headerlist);
368 #endif
369 free(fr);
374 * \brief 'isolates' a frame by duplicating non-malloc'ed components
375 * (header, src, data).
376 * On return all components are malloc'ed
378 struct ast_frame *ast_frisolate(struct ast_frame *fr)
380 struct ast_frame *out;
381 void *newdata;
383 if (!(fr->mallocd & AST_MALLOCD_HDR)) {
384 /* Allocate a new header if needed */
385 if (!(out = ast_frame_header_new()))
386 return NULL;
387 out->frametype = fr->frametype;
388 out->subclass = fr->subclass;
389 out->datalen = fr->datalen;
390 out->samples = fr->samples;
391 out->offset = fr->offset;
392 out->data = fr->data;
393 /* Copy the timing data */
394 out->has_timing_info = fr->has_timing_info;
395 if (fr->has_timing_info) {
396 out->ts = fr->ts;
397 out->len = fr->len;
398 out->seqno = fr->seqno;
400 } else
401 out = fr;
403 if (!(fr->mallocd & AST_MALLOCD_SRC)) {
404 if (fr->src) {
405 if (!(out->src = ast_strdup(fr->src))) {
406 if (out != fr)
407 free(out);
408 return NULL;
411 } else
412 out->src = fr->src;
414 if (!(fr->mallocd & AST_MALLOCD_DATA)) {
415 if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
416 if (out->src != fr->src)
417 free((void *) out->src);
418 if (out != fr)
419 free(out);
420 return NULL;
422 newdata += AST_FRIENDLY_OFFSET;
423 out->offset = AST_FRIENDLY_OFFSET;
424 out->datalen = fr->datalen;
425 memcpy(newdata, fr->data, fr->datalen);
426 out->data = newdata;
429 out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
431 return out;
434 struct ast_frame *ast_frdup(const struct ast_frame *f)
436 struct ast_frame *out = NULL;
437 int len, srclen = 0;
438 void *buf = NULL;
440 #if !defined(LOW_MEMORY)
441 struct ast_frame_cache *frames;
442 #endif
444 /* Start with standard stuff */
445 len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
446 /* If we have a source, add space for it */
448 * XXX Watch out here - if we receive a src which is not terminated
449 * properly, we can be easily attacked. Should limit the size we deal with.
451 if (f->src)
452 srclen = strlen(f->src);
453 if (srclen > 0)
454 len += srclen + 1;
456 #if !defined(LOW_MEMORY)
457 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
458 AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
459 if (out->mallocd_hdr_len >= len) {
460 size_t mallocd_len = out->mallocd_hdr_len;
461 AST_LIST_REMOVE_CURRENT(&frames->list, frame_list);
462 memset(out, 0, sizeof(*out));
463 out->mallocd_hdr_len = mallocd_len;
464 buf = out;
465 frames->size--;
466 break;
469 AST_LIST_TRAVERSE_SAFE_END
471 #endif
473 if (!buf) {
474 if (!(buf = ast_calloc_cache(1, len)))
475 return NULL;
476 out = buf;
477 out->mallocd_hdr_len = len;
480 out->frametype = f->frametype;
481 out->subclass = f->subclass;
482 out->datalen = f->datalen;
483 out->samples = f->samples;
484 out->delivery = f->delivery;
485 /* Set us as having malloc'd header only, so it will eventually
486 get freed. */
487 out->mallocd = AST_MALLOCD_HDR;
488 out->offset = AST_FRIENDLY_OFFSET;
489 if (out->datalen) {
490 out->data = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
491 memcpy(out->data, f->data, out->datalen);
493 if (srclen > 0) {
494 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
495 /* Must have space since we allocated for it */
496 strcpy((char *)out->src, f->src);
498 out->has_timing_info = f->has_timing_info;
499 out->ts = f->ts;
500 out->len = f->len;
501 out->seqno = f->seqno;
502 return out;
505 void ast_swapcopy_samples(void *dst, const void *src, int samples)
507 int i;
508 unsigned short *dst_s = dst;
509 const unsigned short *src_s = src;
511 for (i = 0; i < samples; i++)
512 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
516 struct ast_format_list *ast_get_format_list_index(int index)
518 return &AST_FORMAT_LIST[index];
521 struct ast_format_list *ast_get_format_list(size_t *size)
523 *size = (sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]));
524 return AST_FORMAT_LIST;
527 char* ast_getformatname(int format)
529 int x;
530 char *ret = "unknown";
531 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
532 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
533 ret = AST_FORMAT_LIST[x].name;
534 break;
537 return ret;
540 char *ast_getformatname_multiple(char *buf, size_t size, int format)
542 int x;
543 unsigned len;
544 char *start, *end = buf;
546 if (!size)
547 return buf;
548 snprintf(end, size, "0x%x (", format);
549 len = strlen(end);
550 end += len;
551 size -= len;
552 start = end;
553 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
554 if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
555 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
556 len = strlen(end);
557 end += len;
558 size -= len;
561 if (start == end)
562 snprintf(start, size, "nothing)");
563 else if (size > 1)
564 *(end -1) = ')';
565 return buf;
568 static struct ast_codec_alias_table {
569 char *alias;
570 char *realname;
571 } ast_codec_alias_table[] = {
572 { "slinear", "slin"},
573 { "g723.1", "g723"},
576 static const char *ast_expand_codec_alias(const char *in)
578 int x;
580 for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(ast_codec_alias_table[0]); x++) {
581 if(!strcmp(in,ast_codec_alias_table[x].alias))
582 return ast_codec_alias_table[x].realname;
584 return in;
587 int ast_getformatbyname(const char *name)
589 int x, all, format = 0;
591 all = strcasecmp(name, "all") ? 0 : 1;
592 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
593 if(AST_FORMAT_LIST[x].visible && (all ||
594 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
595 !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
596 format |= AST_FORMAT_LIST[x].bits;
597 if(!all)
598 break;
602 return format;
605 char *ast_codec2str(int codec)
607 int x;
608 char *ret = "unknown";
609 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
610 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
611 ret = AST_FORMAT_LIST[x].desc;
612 break;
615 return ret;
618 static int show_codecs_deprecated(int fd, int argc, char *argv[])
620 int i, found=0;
621 char hex[25];
623 if ((argc < 2) || (argc > 3))
624 return RESULT_SHOWUSAGE;
626 if (!ast_opt_dont_warn)
627 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
628 "\tIt does not indicate anything about your configuration.\n");
630 ast_cli(fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
631 ast_cli(fd, "--------------------------------------------------------------------------------\n");
632 if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
633 found = 1;
634 for (i=0;i<13;i++) {
635 snprintf(hex,25,"(0x%x)",1<<i);
636 ast_cli(fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
640 if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
641 found = 1;
642 for (i=16;i<18;i++) {
643 snprintf(hex,25,"(0x%x)",1<<i);
644 ast_cli(fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
648 if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
649 found = 1;
650 for (i=18;i<22;i++) {
651 snprintf(hex,25,"(0x%x)",1<<i);
652 ast_cli(fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
656 if (! found)
657 return RESULT_SHOWUSAGE;
658 else
659 return RESULT_SUCCESS;
662 static int show_codecs(int fd, int argc, char *argv[])
664 int i, found=0;
665 char hex[25];
667 if ((argc < 3) || (argc > 4))
668 return RESULT_SHOWUSAGE;
670 if (!ast_opt_dont_warn)
671 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
672 "\tIt does not indicate anything about your configuration.\n");
674 ast_cli(fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
675 ast_cli(fd, "--------------------------------------------------------------------------------\n");
676 if ((argc == 3) || (!strcasecmp(argv[3],"audio"))) {
677 found = 1;
678 for (i=0;i<13;i++) {
679 snprintf(hex,25,"(0x%x)",1<<i);
680 ast_cli(fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
684 if ((argc == 3) || (!strcasecmp(argv[3],"image"))) {
685 found = 1;
686 for (i=16;i<18;i++) {
687 snprintf(hex,25,"(0x%x)",1<<i);
688 ast_cli(fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
692 if ((argc == 3) || (!strcasecmp(argv[3],"video"))) {
693 found = 1;
694 for (i=18;i<22;i++) {
695 snprintf(hex,25,"(0x%x)",1<<i);
696 ast_cli(fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
700 if (! found)
701 return RESULT_SHOWUSAGE;
702 else
703 return RESULT_SUCCESS;
706 static char frame_show_codecs_usage[] =
707 "Usage: core show codecs [audio|video|image]\n"
708 " Displays codec mapping\n";
710 static int show_codec_n_deprecated(int fd, int argc, char *argv[])
712 int codec, i, found=0;
714 if (argc != 3)
715 return RESULT_SHOWUSAGE;
717 if (sscanf(argv[2],"%d",&codec) != 1)
718 return RESULT_SHOWUSAGE;
720 for (i = 0; i < 32; i++)
721 if (codec & (1 << i)) {
722 found = 1;
723 ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
726 if (!found)
727 ast_cli(fd, "Codec %d not found\n", codec);
729 return RESULT_SUCCESS;
732 static int show_codec_n(int fd, int argc, char *argv[])
734 int codec, i, found=0;
736 if (argc != 4)
737 return RESULT_SHOWUSAGE;
739 if (sscanf(argv[3],"%d",&codec) != 1)
740 return RESULT_SHOWUSAGE;
742 for (i = 0; i < 32; i++)
743 if (codec & (1 << i)) {
744 found = 1;
745 ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
748 if (!found)
749 ast_cli(fd, "Codec %d not found\n", codec);
751 return RESULT_SUCCESS;
754 static char frame_show_codec_n_usage[] =
755 "Usage: core show codec <number>\n"
756 " Displays codec mapping\n";
758 /*! Dump a frame for debugging purposes */
759 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
761 const char noname[] = "unknown";
762 char ftype[40] = "Unknown Frametype";
763 char cft[80];
764 char subclass[40] = "Unknown Subclass";
765 char csub[80];
766 char moreinfo[40] = "";
767 char cn[60];
768 char cp[40];
769 char cmn[40];
771 if (!name)
772 name = noname;
775 if (!f) {
776 ast_verbose("%s [ %s (NULL) ] [%s]\n",
777 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
778 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
779 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
780 return;
782 /* XXX We should probably print one each of voice and video when the format changes XXX */
783 if (f->frametype == AST_FRAME_VOICE)
784 return;
785 if (f->frametype == AST_FRAME_VIDEO)
786 return;
787 switch(f->frametype) {
788 case AST_FRAME_DTMF_BEGIN:
789 strcpy(ftype, "DTMF Begin");
790 subclass[0] = f->subclass;
791 subclass[1] = '\0';
792 break;
793 case AST_FRAME_DTMF_END:
794 strcpy(ftype, "DTMF End");
795 subclass[0] = f->subclass;
796 subclass[1] = '\0';
797 break;
798 case AST_FRAME_CONTROL:
799 strcpy(ftype, "Control");
800 switch(f->subclass) {
801 case AST_CONTROL_HANGUP:
802 strcpy(subclass, "Hangup");
803 break;
804 case AST_CONTROL_RING:
805 strcpy(subclass, "Ring");
806 break;
807 case AST_CONTROL_RINGING:
808 strcpy(subclass, "Ringing");
809 break;
810 case AST_CONTROL_ANSWER:
811 strcpy(subclass, "Answer");
812 break;
813 case AST_CONTROL_BUSY:
814 strcpy(subclass, "Busy");
815 break;
816 case AST_CONTROL_TAKEOFFHOOK:
817 strcpy(subclass, "Take Off Hook");
818 break;
819 case AST_CONTROL_OFFHOOK:
820 strcpy(subclass, "Line Off Hook");
821 break;
822 case AST_CONTROL_CONGESTION:
823 strcpy(subclass, "Congestion");
824 break;
825 case AST_CONTROL_FLASH:
826 strcpy(subclass, "Flash");
827 break;
828 case AST_CONTROL_WINK:
829 strcpy(subclass, "Wink");
830 break;
831 case AST_CONTROL_OPTION:
832 strcpy(subclass, "Option");
833 break;
834 case AST_CONTROL_RADIO_KEY:
835 strcpy(subclass, "Key Radio");
836 break;
837 case AST_CONTROL_RADIO_UNKEY:
838 strcpy(subclass, "Unkey Radio");
839 break;
840 case -1:
841 strcpy(subclass, "Stop generators");
842 break;
843 default:
844 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
846 break;
847 case AST_FRAME_NULL:
848 strcpy(ftype, "Null Frame");
849 strcpy(subclass, "N/A");
850 break;
851 case AST_FRAME_IAX:
852 /* Should never happen */
853 strcpy(ftype, "IAX Specific");
854 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
855 break;
856 case AST_FRAME_TEXT:
857 strcpy(ftype, "Text");
858 strcpy(subclass, "N/A");
859 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
860 break;
861 case AST_FRAME_IMAGE:
862 strcpy(ftype, "Image");
863 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
864 break;
865 case AST_FRAME_HTML:
866 strcpy(ftype, "HTML");
867 switch(f->subclass) {
868 case AST_HTML_URL:
869 strcpy(subclass, "URL");
870 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
871 break;
872 case AST_HTML_DATA:
873 strcpy(subclass, "Data");
874 break;
875 case AST_HTML_BEGIN:
876 strcpy(subclass, "Begin");
877 break;
878 case AST_HTML_END:
879 strcpy(subclass, "End");
880 break;
881 case AST_HTML_LDCOMPLETE:
882 strcpy(subclass, "Load Complete");
883 break;
884 case AST_HTML_NOSUPPORT:
885 strcpy(subclass, "No Support");
886 break;
887 case AST_HTML_LINKURL:
888 strcpy(subclass, "Link URL");
889 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
890 break;
891 case AST_HTML_UNLINK:
892 strcpy(subclass, "Unlink");
893 break;
894 case AST_HTML_LINKREJECT:
895 strcpy(subclass, "Link Reject");
896 break;
897 default:
898 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
899 break;
901 break;
902 case AST_FRAME_MODEM:
903 strcpy(ftype, "Modem");
904 switch (f->subclass) {
905 case AST_MODEM_T38:
906 strcpy(subclass, "T.38");
907 break;
908 case AST_MODEM_V150:
909 strcpy(subclass, "V.150");
910 break;
911 default:
912 snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
913 break;
915 break;
916 default:
917 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
919 if (!ast_strlen_zero(moreinfo))
920 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
921 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
922 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
923 f->frametype,
924 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
925 f->subclass,
926 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
927 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
928 else
929 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
930 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
931 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
932 f->frametype,
933 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
934 f->subclass,
935 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
939 #ifdef TRACE_FRAMES
940 static int show_frame_stats_deprecated(int fd, int argc, char *argv[])
942 struct ast_frame *f;
943 int x=1;
944 if (argc != 3)
945 return RESULT_SHOWUSAGE;
946 AST_LIST_LOCK(&headerlist);
947 ast_cli(fd, " Framer Statistics \n");
948 ast_cli(fd, "---------------------------\n");
949 ast_cli(fd, "Total allocated headers: %d\n", headers);
950 ast_cli(fd, "Queue Dump:\n");
951 AST_LIST_TRAVERSE(&headerlist, f, frame_list)
952 ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
953 AST_LIST_UNLOCK(&headerlist);
954 return RESULT_SUCCESS;
957 static int show_frame_stats(int fd, int argc, char *argv[])
959 struct ast_frame *f;
960 int x=1;
961 if (argc != 4)
962 return RESULT_SHOWUSAGE;
963 AST_LIST_LOCK(&headerlist);
964 ast_cli(fd, " Framer Statistics \n");
965 ast_cli(fd, "---------------------------\n");
966 ast_cli(fd, "Total allocated headers: %d\n", headers);
967 ast_cli(fd, "Queue Dump:\n");
968 AST_LIST_TRAVERSE(&headerlist, f, frame_list)
969 ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
970 AST_LIST_UNLOCK(&headerlist);
971 return RESULT_SUCCESS;
974 static char frame_stats_usage[] =
975 "Usage: core show frame stats\n"
976 " Displays debugging statistics from framer\n";
977 #endif
979 /* Builtin Asterisk CLI-commands for debugging */
980 static struct ast_cli_entry cli_show_codecs = {
981 { "show", "codecs", NULL },
982 show_codecs_deprecated, NULL,
983 NULL };
985 static struct ast_cli_entry cli_show_audio_codecs = {
986 { "show", "audio", "codecs", NULL },
987 show_codecs_deprecated, NULL,
988 NULL };
990 static struct ast_cli_entry cli_show_video_codecs = {
991 { "show", "video", "codecs", NULL },
992 show_codecs_deprecated, NULL,
993 NULL };
995 static struct ast_cli_entry cli_show_image_codecs = {
996 { "show", "image", "codecs", NULL },
997 show_codecs_deprecated, NULL,
998 NULL };
1000 static struct ast_cli_entry cli_show_codec = {
1001 { "show", "codec", NULL },
1002 show_codec_n_deprecated, NULL,
1003 NULL };
1005 #ifdef TRACE_FRAMES
1006 static struct ast_cli_entry cli_show_frame_stats = {
1007 { "show", "frame", "stats", NULL },
1008 show_frame_stats, NULL,
1009 NULL };
1010 #endif
1012 static struct ast_cli_entry my_clis[] = {
1013 { { "core", "show", "codecs", NULL },
1014 show_codecs, "Displays a list of codecs",
1015 frame_show_codecs_usage, NULL, &cli_show_codecs },
1017 { { "core", "show", "audio", "codecs", NULL },
1018 show_codecs, "Displays a list of audio codecs",
1019 frame_show_codecs_usage, NULL, &cli_show_audio_codecs },
1021 { { "core", "show", "video", "codecs", NULL },
1022 show_codecs, "Displays a list of video codecs",
1023 frame_show_codecs_usage, NULL, &cli_show_video_codecs },
1025 { { "core", "show", "image", "codecs", NULL },
1026 show_codecs, "Displays a list of image codecs",
1027 frame_show_codecs_usage, NULL, &cli_show_image_codecs },
1029 { { "core", "show", "codec", NULL },
1030 show_codec_n, "Shows a specific codec",
1031 frame_show_codec_n_usage, NULL, &cli_show_codec },
1033 #ifdef TRACE_FRAMES
1034 { { "core", "show", "frame", "stats", NULL },
1035 show_frame_stats, "Shows frame statistics",
1036 frame_stats_usage, NULL, &cli_show_frame_stats },
1037 #endif
1040 int init_framer(void)
1042 ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
1043 return 0;
1046 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
1048 int x, differential = (int) 'A', mem;
1049 char *from, *to;
1051 if(right) {
1052 from = pref->order;
1053 to = buf;
1054 mem = size;
1055 } else {
1056 to = pref->order;
1057 from = buf;
1058 mem = 32;
1061 memset(to, 0, mem);
1062 for (x = 0; x < 32 ; x++) {
1063 if(!from[x])
1064 break;
1065 to[x] = right ? (from[x] + differential) : (from[x] - differential);
1069 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
1071 int x, codec;
1072 size_t total_len, slen;
1073 char *formatname;
1075 memset(buf,0,size);
1076 total_len = size;
1077 buf[0] = '(';
1078 total_len--;
1079 for(x = 0; x < 32 ; x++) {
1080 if(total_len <= 0)
1081 break;
1082 if(!(codec = ast_codec_pref_index(pref,x)))
1083 break;
1084 if((formatname = ast_getformatname(codec))) {
1085 slen = strlen(formatname);
1086 if(slen > total_len)
1087 break;
1088 strncat(buf,formatname,total_len);
1089 total_len -= slen;
1091 if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
1092 strncat(buf,"|",total_len);
1093 total_len--;
1096 if(total_len) {
1097 strncat(buf,")",total_len);
1098 total_len--;
1101 return size - total_len;
1104 int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
1106 int slot = 0;
1109 if((index >= 0) && (index < sizeof(pref->order))) {
1110 slot = pref->order[index];
1113 return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
1116 /*! \brief Remove codec from pref list */
1117 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
1119 struct ast_codec_pref oldorder;
1120 int x, y = 0;
1121 int slot;
1122 int size;
1124 if(!pref->order[0])
1125 return;
1127 memcpy(&oldorder, pref, sizeof(oldorder));
1128 memset(pref, 0, sizeof(*pref));
1130 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1131 slot = oldorder.order[x];
1132 size = oldorder.framing[x];
1133 if(! slot)
1134 break;
1135 if(AST_FORMAT_LIST[slot-1].bits != format) {
1136 pref->order[y] = slot;
1137 pref->framing[y++] = size;
1143 /*! \brief Append codec to list */
1144 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
1146 int x, newindex = -1;
1148 ast_codec_pref_remove(pref, format);
1150 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1151 if(AST_FORMAT_LIST[x].bits == format) {
1152 newindex = x + 1;
1153 break;
1157 if(newindex) {
1158 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1159 if(!pref->order[x]) {
1160 pref->order[x] = newindex;
1161 break;
1166 return x;
1170 /*! \brief Set packet size for codec */
1171 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
1173 int x, index = -1;
1175 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1176 if(AST_FORMAT_LIST[x].bits == format) {
1177 index = x;
1178 break;
1182 if(index < 0)
1183 return -1;
1185 /* size validation */
1186 if(!framems)
1187 framems = AST_FORMAT_LIST[index].def_ms;
1189 if(AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1190 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1192 if(framems < AST_FORMAT_LIST[index].min_ms)
1193 framems = AST_FORMAT_LIST[index].min_ms;
1195 if(framems > AST_FORMAT_LIST[index].max_ms)
1196 framems = AST_FORMAT_LIST[index].max_ms;
1199 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1200 if(pref->order[x] == (index + 1)) {
1201 pref->framing[x] = framems;
1202 break;
1206 return x;
1209 /*! \brief Get packet size for codec */
1210 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
1212 int x, index = -1, framems = 0;
1213 struct ast_format_list fmt = {0};
1215 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1216 if(AST_FORMAT_LIST[x].bits == format) {
1217 fmt = AST_FORMAT_LIST[x];
1218 index = x;
1219 break;
1223 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1224 if(pref->order[x] == (index + 1)) {
1225 framems = pref->framing[x];
1226 break;
1230 /* size validation */
1231 if(!framems)
1232 framems = AST_FORMAT_LIST[index].def_ms;
1234 if(AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1235 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1237 if(framems < AST_FORMAT_LIST[index].min_ms)
1238 framems = AST_FORMAT_LIST[index].min_ms;
1240 if(framems > AST_FORMAT_LIST[index].max_ms)
1241 framems = AST_FORMAT_LIST[index].max_ms;
1243 fmt.cur_ms = framems;
1245 return fmt;
1248 /*! \brief Pick a codec */
1249 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
1251 int x, ret = 0, slot;
1253 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1254 slot = pref->order[x];
1256 if (!slot)
1257 break;
1258 if (formats & AST_FORMAT_LIST[slot-1].bits) {
1259 ret = AST_FORMAT_LIST[slot-1].bits;
1260 break;
1263 if(ret & AST_FORMAT_AUDIO_MASK)
1264 return ret;
1266 if (option_debug > 3)
1267 ast_log(LOG_DEBUG, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1269 return find_best ? ast_best_codec(formats) : 0;
1272 void ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
1274 char *parse = NULL, *this = NULL, *psize = NULL;
1275 int format = 0, framems = 0;
1277 parse = ast_strdupa(list);
1278 while ((this = strsep(&parse, ","))) {
1279 framems = 0;
1280 if ((psize = strrchr(this, ':'))) {
1281 *psize++ = '\0';
1282 if (option_debug)
1283 ast_log(LOG_DEBUG,"Packetization for codec: %s is %s\n", this, psize);
1284 framems = atoi(psize);
1285 if (framems < 0)
1286 framems = 0;
1288 if (!(format = ast_getformatbyname(this))) {
1289 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1290 continue;
1293 if (mask) {
1294 if (allowing)
1295 *mask |= format;
1296 else
1297 *mask &= ~format;
1300 /* Set up a preference list for audio. Do not include video in preferences
1301 since we can not transcode video and have to use whatever is offered
1303 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1304 if (strcasecmp(this, "all")) {
1305 if (allowing) {
1306 ast_codec_pref_append(pref, format);
1307 ast_codec_pref_setsize(pref, format, framems);
1309 else
1310 ast_codec_pref_remove(pref, format);
1311 } else if (!allowing) {
1312 memset(pref, 0, sizeof(*pref));
1318 static int g723_len(unsigned char buf)
1320 enum frame_type type = buf & TYPE_MASK;
1322 switch(type) {
1323 case TYPE_DONTSEND:
1324 return 0;
1325 break;
1326 case TYPE_SILENCE:
1327 return 4;
1328 break;
1329 case TYPE_HIGH:
1330 return 24;
1331 break;
1332 case TYPE_LOW:
1333 return 20;
1334 break;
1335 default:
1336 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
1338 return -1;
1341 static int g723_samples(unsigned char *buf, int maxlen)
1343 int pos = 0;
1344 int samples = 0;
1345 int res;
1346 while(pos < maxlen) {
1347 res = g723_len(buf[pos]);
1348 if (res <= 0)
1349 break;
1350 samples += 240;
1351 pos += res;
1353 return samples;
1356 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1358 int byte = bit / 8; /* byte containing first bit */
1359 int rem = 8 - (bit % 8); /* remaining bits in first byte */
1360 unsigned char ret = 0;
1362 if (n <= 0 || n > 8)
1363 return 0;
1365 if (rem < n) {
1366 ret = (data[byte] << (n - rem));
1367 ret |= (data[byte + 1] >> (8 - n + rem));
1368 } else {
1369 ret = (data[byte] >> (rem - n));
1372 return (ret & (0xff >> (8 - n)));
1375 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1377 static int SpeexWBSubModeSz[] = {
1378 0, 36, 112, 192,
1379 352, 0, 0, 0 };
1380 int off = bit;
1381 unsigned char c;
1383 /* skip up to two wideband frames */
1384 if (((len * 8 - off) >= 5) &&
1385 get_n_bits_at(data, 1, off)) {
1386 c = get_n_bits_at(data, 3, off + 1);
1387 off += SpeexWBSubModeSz[c];
1389 if (((len * 8 - off) >= 5) &&
1390 get_n_bits_at(data, 1, off)) {
1391 c = get_n_bits_at(data, 3, off + 1);
1392 off += SpeexWBSubModeSz[c];
1394 if (((len * 8 - off) >= 5) &&
1395 get_n_bits_at(data, 1, off)) {
1396 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1397 return -1;
1402 return off - bit;
1405 static int speex_samples(unsigned char *data, int len)
1407 static int SpeexSubModeSz[] = {
1408 5, 43, 119, 160,
1409 220, 300, 364, 492,
1410 79, 0, 0, 0,
1411 0, 0, 0, 0 };
1412 static int SpeexInBandSz[] = {
1413 1, 1, 4, 4,
1414 4, 4, 4, 4,
1415 8, 8, 16, 16,
1416 32, 32, 64, 64 };
1417 int bit = 0;
1418 int cnt = 0;
1419 int off;
1420 unsigned char c;
1422 while ((len * 8 - bit) >= 5) {
1423 /* skip wideband frames */
1424 off = speex_get_wb_sz_at(data, len, bit);
1425 if (off < 0) {
1426 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1427 break;
1429 bit += off;
1431 if ((len * 8 - bit) < 5) {
1432 ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1433 break;
1436 /* get control bits */
1437 c = get_n_bits_at(data, 5, bit);
1438 bit += 5;
1440 if (c == 15) {
1441 /* terminator */
1442 break;
1443 } else if (c == 14) {
1444 /* in-band signal; next 4 bits contain signal id */
1445 c = get_n_bits_at(data, 4, bit);
1446 bit += 4;
1447 bit += SpeexInBandSz[c];
1448 } else if (c == 13) {
1449 /* user in-band; next 5 bits contain msg len */
1450 c = get_n_bits_at(data, 5, bit);
1451 bit += 5;
1452 bit += c * 8;
1453 } else if (c > 8) {
1454 /* unknown */
1455 break;
1456 } else {
1457 /* skip number bits for submode (less the 5 control bits) */
1458 bit += SpeexSubModeSz[c] - 5;
1459 cnt += 160; /* new frame */
1462 return cnt;
1465 int ast_codec_get_samples(struct ast_frame *f)
1467 int samples=0;
1468 switch(f->subclass) {
1469 case AST_FORMAT_SPEEX:
1470 samples = speex_samples(f->data, f->datalen);
1471 break;
1472 case AST_FORMAT_G723_1:
1473 samples = g723_samples(f->data, f->datalen);
1474 break;
1475 case AST_FORMAT_ILBC:
1476 samples = 240 * (f->datalen / 50);
1477 break;
1478 case AST_FORMAT_GSM:
1479 samples = 160 * (f->datalen / 33);
1480 break;
1481 case AST_FORMAT_G729A:
1482 samples = f->datalen * 8;
1483 break;
1484 case AST_FORMAT_SLINEAR:
1485 samples = f->datalen / 2;
1486 break;
1487 case AST_FORMAT_LPC10:
1488 /* assumes that the RTP packet contains one LPC10 frame */
1489 samples = 22 * 8;
1490 samples += (((char *)(f->data))[7] & 0x1) * 8;
1491 break;
1492 case AST_FORMAT_ULAW:
1493 case AST_FORMAT_ALAW:
1494 samples = f->datalen;
1495 break;
1496 case AST_FORMAT_G722:
1497 case AST_FORMAT_ADPCM:
1498 case AST_FORMAT_G726:
1499 case AST_FORMAT_G726_AAL2:
1500 samples = f->datalen * 2;
1501 break;
1502 default:
1503 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1505 return samples;
1508 int ast_codec_get_len(int format, int samples)
1510 int len = 0;
1512 /* XXX Still need speex, g723, and lpc10 XXX */
1513 switch(format) {
1514 case AST_FORMAT_ILBC:
1515 len = (samples / 240) * 50;
1516 break;
1517 case AST_FORMAT_GSM:
1518 len = (samples / 160) * 33;
1519 break;
1520 case AST_FORMAT_G729A:
1521 len = samples / 8;
1522 break;
1523 case AST_FORMAT_SLINEAR:
1524 len = samples * 2;
1525 break;
1526 case AST_FORMAT_ULAW:
1527 case AST_FORMAT_ALAW:
1528 len = samples;
1529 break;
1530 case AST_FORMAT_G722:
1531 case AST_FORMAT_ADPCM:
1532 case AST_FORMAT_G726:
1533 case AST_FORMAT_G726_AAL2:
1534 len = samples / 2;
1535 break;
1536 default:
1537 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1540 return len;
1543 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1545 int count;
1546 short *fdata = f->data;
1547 short adjust_value = abs(adjustment);
1549 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
1550 return -1;
1552 if (!adjustment)
1553 return 0;
1555 for (count = 0; count < f->samples; count++) {
1556 if (adjustment > 0) {
1557 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1558 } else if (adjustment < 0) {
1559 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1563 return 0;
1566 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1568 int count;
1569 short *data1, *data2;
1571 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
1572 return -1;
1574 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
1575 return -1;
1577 if (f1->samples != f2->samples)
1578 return -1;
1580 for (count = 0, data1 = f1->data, data2 = f2->data;
1581 count < f1->samples;
1582 count++, data1++, data2++)
1583 ast_slinear_saturated_add(data1, data2);
1585 return 0;