use LDFLAGS and LIBS properly, and allow dependencies to provide LDFLAGS if needed...
[asterisk-bristuff.git] / frame.c
blob4774f267232aa558e71e175b9f1334af1512a642
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"
45 #ifdef TRACE_FRAMES
46 static int headers = 0;
47 static struct ast_frame *headerlist = NULL;
48 AST_MUTEX_DEFINE_STATIC(framelock);
49 #endif
51 #define SMOOTHER_SIZE 8000
53 enum frame_type {
54 TYPE_HIGH, /* 0x0 */
55 TYPE_LOW, /* 0x1 */
56 TYPE_SILENCE, /* 0x2 */
57 TYPE_DONTSEND /* 0x3 */
60 #define TYPE_MASK 0x3
62 struct ast_smoother {
63 int size;
64 int format;
65 int readdata;
66 int optimizablestream;
67 int flags;
68 float samplesperbyte;
69 struct ast_frame f;
70 struct timeval delivery;
71 char data[SMOOTHER_SIZE];
72 char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
73 struct ast_frame *opt;
74 int len;
77 /*! \brief Definition of supported media formats (codecs) */
78 static struct ast_format_list {
79 int visible; /*!< Can we see this entry */
80 int bits; /*!< bitmask value */
81 char *name; /*!< short name */
82 char *desc; /*!< Description */
83 } AST_FORMAT_LIST[] = { /*!< Bit number: comment - Bit numbers are hard coded in show_codec() */
84 { 1, AST_FORMAT_G723_1 , "g723" , "G.723.1"}, /*!< 1 */
85 { 1, AST_FORMAT_GSM, "gsm" , "GSM"}, /*!< 2: codec_gsm.c */
86 { 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law" }, /*!< 3: codec_ulaw.c */
87 { 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law" }, /*!< 4: codec_alaw.c */
88 { 1, AST_FORMAT_G726, "g726", "G.726 RFC3551" },/*!< 5: codec_g726.c */
89 { 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM"}, /*!< 6: codec_adpcm.c */
90 { 1, AST_FORMAT_SLINEAR, "slin", "16 bit Signed Linear PCM"}, /*!< 7 */
91 { 1, AST_FORMAT_LPC10, "lpc10", "LPC10" }, /*!< 8: codec_lpc10.c */
92 { 1, AST_FORMAT_G729A, "g729", "G.729A" }, /*!< 9: Binary commercial distribution */
93 { 1, AST_FORMAT_SPEEX, "speex", "SpeeX" }, /*!< 10: codec_speex.c */
94 { 1, AST_FORMAT_ILBC, "ilbc", "iLBC"}, /*!< 11: codec_ilbc.c */
95 { 1, AST_FORMAT_G726_AAL2, "g726aal2", "G.726 AAL2" }, /*!< 12: codec_g726.c */
96 { 0, 0, "nothing", "undefined" },
97 { 0, 0, "nothing", "undefined" },
98 { 0, 0, "nothing", "undefined" },
99 { 0, 0, "nothing", "undefined" },
100 { 0, AST_FORMAT_MAX_AUDIO, "maxaudio", "Maximum audio format" },
101 { 1, AST_FORMAT_JPEG, "jpeg", "JPEG image"}, /*!< 17: See format_jpeg.c */
102 { 1, AST_FORMAT_PNG, "png", "PNG image"}, /*!< 18: Image format */
103 { 1, AST_FORMAT_H261, "h261", "H.261 Video" }, /*!< 19: Video Passthrough */
104 { 1, AST_FORMAT_H263, "h263", "H.263 Video" }, /*!< 20: Passthrough support, see format_h263.c */
105 { 1, AST_FORMAT_H263_PLUS, "h263p", "H.263+ Video" }, /*!< 21: See format_h263.c */
106 { 1, AST_FORMAT_H264, "h264", "H.264 Video" }, /*!< 22: Passthrough support, see format_h263.c */
107 { 0, 0, "nothing", "undefined" },
108 { 0, 0, "nothing", "undefined" },
109 { 0, 0, "nothing", "undefined" },
110 { 0, AST_FORMAT_MAX_VIDEO, "maxvideo", "Maximum video format" },
113 struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
115 void ast_smoother_reset(struct ast_smoother *s, int size)
117 memset(s, 0, sizeof(*s));
118 s->size = size;
121 struct ast_smoother *ast_smoother_new(int size)
123 struct ast_smoother *s;
124 if (size < 1)
125 return NULL;
126 if ((s = ast_malloc(sizeof(*s))))
127 ast_smoother_reset(s, size);
128 return s;
131 int ast_smoother_get_flags(struct ast_smoother *s)
133 return s->flags;
136 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
138 s->flags = flags;
141 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
143 if (f->frametype != AST_FRAME_VOICE) {
144 ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
145 return -1;
147 if (!s->format) {
148 s->format = f->subclass;
149 s->samplesperbyte = (float)f->samples / (float)f->datalen;
150 } else if (s->format != f->subclass) {
151 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
152 return -1;
154 if (s->len + f->datalen > SMOOTHER_SIZE) {
155 ast_log(LOG_WARNING, "Out of smoother space\n");
156 return -1;
158 if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
159 && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
160 if (!s->len) {
161 /* Optimize by sending the frame we just got
162 on the next read, thus eliminating the douple
163 copy */
164 s->opt = f;
165 return 0;
166 } else {
167 s->optimizablestream++;
168 if (s->optimizablestream > 10) {
169 /* For the past 10 rounds, we have input and output
170 frames of the correct size for this smoother, yet
171 we were unable to optimize because there was still
172 some cruft left over. Lets just drop the cruft so
173 we can move to a fully optimized path */
174 s->len = 0;
175 s->opt = f;
176 return 0;
179 } else
180 s->optimizablestream = 0;
181 if (s->flags & AST_SMOOTHER_FLAG_G729) {
182 if (s->len % 10) {
183 ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
184 return 0;
187 if (swap)
188 ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
189 else
190 memcpy(s->data + s->len, f->data, f->datalen);
191 /* If either side is empty, reset the delivery time */
192 if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) /* XXX really ? */
193 s->delivery = f->delivery;
194 s->len += f->datalen;
195 return 0;
198 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
200 struct ast_frame *opt;
201 int len;
203 /* IF we have an optimization frame, send it */
204 if (s->opt) {
205 if (s->opt->offset < AST_FRIENDLY_OFFSET)
206 ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).",
207 s->opt->offset);
208 opt = s->opt;
209 s->opt = NULL;
210 return opt;
213 /* Make sure we have enough data */
214 if (s->len < s->size) {
215 /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
216 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
217 return NULL;
219 len = s->size;
220 if (len > s->len)
221 len = s->len;
222 /* Make frame */
223 s->f.frametype = AST_FRAME_VOICE;
224 s->f.subclass = s->format;
225 s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
226 s->f.offset = AST_FRIENDLY_OFFSET;
227 s->f.datalen = len;
228 /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
229 s->f.samples = len * s->samplesperbyte; /* XXX rounding */
230 s->f.delivery = s->delivery;
231 /* Fill Data */
232 memcpy(s->f.data, s->data, len);
233 s->len -= len;
234 /* Move remaining data to the front if applicable */
235 if (s->len) {
236 /* In principle this should all be fine because if we are sending
237 G.729 VAD, the next timestamp will take over anyawy */
238 memmove(s->data, s->data + len, s->len);
239 if (!ast_tvzero(s->delivery)) {
240 /* If we have delivery time, increment it, otherwise, leave it at 0 */
241 s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
244 /* Return frame */
245 return &s->f;
248 void ast_smoother_free(struct ast_smoother *s)
250 free(s);
253 static struct ast_frame *ast_frame_header_new(void)
255 struct ast_frame *f = ast_calloc(1, sizeof(*f));
256 #ifdef TRACE_FRAMES
257 if (f) {
258 headers++;
259 f->prev = NULL;
260 ast_mutex_lock(&framelock);
261 f->next = headerlist;
262 if (headerlist)
263 headerlist->prev = f;
264 headerlist = f;
265 ast_mutex_unlock(&framelock);
267 #endif
268 return f;
272 * \todo Important: I should be made more efficient. Frame headers should
273 * most definitely be cached
275 void ast_frfree(struct ast_frame *fr)
277 if (fr->mallocd & AST_MALLOCD_DATA) {
278 if (fr->data)
279 free(fr->data - fr->offset);
281 if (fr->mallocd & AST_MALLOCD_SRC) {
282 if (fr->src)
283 free((char *)fr->src);
285 if (fr->mallocd & AST_MALLOCD_HDR) {
286 #ifdef TRACE_FRAMES
287 headers--;
288 ast_mutex_lock(&framelock);
289 if (fr->next)
290 fr->next->prev = fr->prev;
291 if (fr->prev)
292 fr->prev->next = fr->next;
293 else
294 headerlist = fr->next;
295 ast_mutex_unlock(&framelock);
296 #endif
297 free(fr);
302 * \brief 'isolates' a frame by duplicating non-malloc'ed components
303 * (header, src, data).
304 * On return all components are malloc'ed
306 struct ast_frame *ast_frisolate(struct ast_frame *fr)
308 struct ast_frame *out;
309 void *newdata;
311 if (!(fr->mallocd & AST_MALLOCD_HDR)) {
312 /* Allocate a new header if needed */
313 if (!(out = ast_frame_header_new()))
314 return NULL;
315 out->frametype = fr->frametype;
316 out->subclass = fr->subclass;
317 out->datalen = fr->datalen;
318 out->samples = fr->samples;
319 out->offset = fr->offset;
320 out->data = fr->data;
321 /* Copy the timing data */
322 out->has_timing_info = fr->has_timing_info;
323 if (fr->has_timing_info) {
324 out->ts = fr->ts;
325 out->len = fr->len;
326 out->seqno = fr->seqno;
328 } else
329 out = fr;
331 if (!(fr->mallocd & AST_MALLOCD_SRC)) {
332 if (fr->src) {
333 if (!(out->src = ast_strdup(fr->src))) {
334 if (out != fr)
335 free(out);
336 return NULL;
339 } else
340 out->src = fr->src;
342 if (!(fr->mallocd & AST_MALLOCD_DATA)) {
343 if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
344 if (out->src != fr->src)
345 free((void *) out->src);
346 if (out != fr)
347 free(out);
348 return NULL;
350 newdata += AST_FRIENDLY_OFFSET;
351 out->offset = AST_FRIENDLY_OFFSET;
352 out->datalen = fr->datalen;
353 memcpy(newdata, fr->data, fr->datalen);
354 out->data = newdata;
357 out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
359 return out;
362 struct ast_frame *ast_frdup(struct ast_frame *f)
364 struct ast_frame *out;
365 int len, srclen = 0;
366 void *buf;
367 /* Start with standard stuff */
368 len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
369 /* If we have a source, add space for it */
371 * XXX Watch out here - if we receive a src which is not terminated
372 * properly, we can be easily attacked. Should limit the size we deal with.
374 if (f->src)
375 srclen = strlen(f->src);
376 if (srclen > 0)
377 len += srclen + 1;
378 if (!(buf = ast_malloc(len)))
379 return NULL;
380 out = buf;
381 /* Set us as having malloc'd header only, so it will eventually
382 get freed. */
383 out->frametype = f->frametype;
384 out->subclass = f->subclass;
385 out->datalen = f->datalen;
386 out->samples = f->samples;
387 out->delivery = f->delivery;
388 out->mallocd = AST_MALLOCD_HDR;
389 out->offset = AST_FRIENDLY_OFFSET;
390 out->data = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
391 if (srclen > 0) {
392 out->src = out->data + f->datalen;
393 /* Must have space since we allocated for it */
394 strcpy((char *)out->src, f->src);
395 } else
396 out->src = NULL;
397 out->prev = NULL;
398 out->next = NULL;
399 memcpy(out->data, f->data, out->datalen);
400 out->has_timing_info = f->has_timing_info;
401 if (f->has_timing_info) {
402 out->ts = f->ts;
403 out->len = f->len;
404 out->seqno = f->seqno;
406 return out;
409 #if 0
411 * XXX
412 * This function is badly broken - it does not handle correctly
413 * partial reads on either header or body.
414 * However is it never used anywhere so we leave it commented out
416 struct ast_frame *ast_fr_fdread(int fd)
418 char buf[65536];
419 int res;
420 struct ast_frame *f = (struct ast_frame *)buf;
421 int ttl = sizeof(*f);
422 /* Read a frame directly from there. They're always in the
423 right format. */
425 while(ttl) {
426 res = read(fd, buf, ttl);
427 if (res < 0) {
428 ast_log(LOG_WARNING, "Bad read on %d: %s\n", fd, strerror(errno));
429 return NULL;
431 ttl -= res;
434 /* read the frame header */
436 /* Re-write data position */
437 f->data = buf + sizeof(*f);
438 f->offset = 0;
439 /* Forget about being mallocd */
440 f->mallocd = 0;
441 /* Re-write the source */
442 f->src = (char *)__FUNCTION__;
443 if (f->datalen > sizeof(buf) - sizeof(*f)) {
444 /* Really bad read */
445 ast_log(LOG_WARNING, "Strange read (%d bytes)\n", f->datalen);
446 return NULL;
448 if (f->datalen) {
449 if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
450 /* Bad read */
451 ast_log(LOG_WARNING, "How very strange, expected %d, got %d\n", f->datalen, res);
452 return NULL;
455 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
456 return NULL;
458 return ast_frisolate(f);
461 /* Some convenient routines for sending frames to/from stream or datagram
462 sockets, pipes, etc (maybe even files) */
465 * XXX this function is also partly broken because it does not handle
466 * partial writes. We comment it out too, and also the unique
467 * client it has, ast_fr_fdhangup()
469 int ast_fr_fdwrite(int fd, struct ast_frame *frame)
471 /* Write the frame exactly */
472 if (write(fd, frame, sizeof(*frame)) != sizeof(*frame)) {
473 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
474 return -1;
476 if (write(fd, frame->data, frame->datalen) != frame->datalen) {
477 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
478 return -1;
480 return 0;
483 int ast_fr_fdhangup(int fd)
485 struct ast_frame hangup = {
486 AST_FRAME_CONTROL,
487 AST_CONTROL_HANGUP
489 return ast_fr_fdwrite(fd, &hangup);
492 #endif /* unused functions */
494 void ast_swapcopy_samples(void *dst, const void *src, int samples)
496 int i;
497 unsigned short *dst_s = dst;
498 const unsigned short *src_s = src;
500 for (i = 0; i < samples; i++)
501 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
505 struct ast_format_list *ast_get_format_list_index(int index)
507 return &AST_FORMAT_LIST[index];
510 struct ast_format_list *ast_get_format_list(size_t *size)
512 *size = (sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]));
513 return AST_FORMAT_LIST;
516 char* ast_getformatname(int format)
518 int x;
519 char *ret = "unknown";
520 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
521 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
522 ret = AST_FORMAT_LIST[x].name;
523 break;
526 return ret;
529 char *ast_getformatname_multiple(char *buf, size_t size, int format)
531 int x;
532 unsigned len;
533 char *start, *end = buf;
535 if (!size)
536 return buf;
537 snprintf(end, size, "0x%x (", format);
538 len = strlen(end);
539 end += len;
540 size -= len;
541 start = end;
542 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
543 if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
544 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
545 len = strlen(end);
546 end += len;
547 size -= len;
550 if (start == end)
551 snprintf(start, size, "nothing)");
552 else if (size > 1)
553 *(end -1) = ')';
554 return buf;
557 static struct ast_codec_alias_table {
558 char *alias;
559 char *realname;
560 } ast_codec_alias_table[] = {
561 { "slinear", "slin"},
562 { "g723.1", "g723"},
565 static const char *ast_expand_codec_alias(const char *in)
567 int x;
569 for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(ast_codec_alias_table[0]); x++) {
570 if(!strcmp(in,ast_codec_alias_table[x].alias))
571 return ast_codec_alias_table[x].realname;
573 return in;
576 int ast_getformatbyname(const char *name)
578 int x, all, format = 0;
580 all = strcasecmp(name, "all") ? 0 : 1;
581 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
582 if(AST_FORMAT_LIST[x].visible && (all ||
583 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
584 !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
585 format |= AST_FORMAT_LIST[x].bits;
586 if(!all)
587 break;
591 return format;
594 char *ast_codec2str(int codec)
596 int x;
597 char *ret = "unknown";
598 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
599 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
600 ret = AST_FORMAT_LIST[x].desc;
601 break;
604 return ret;
607 static int show_codecs(int fd, int argc, char *argv[])
609 int i, found=0;
610 char hex[25];
612 if ((argc < 2) || (argc > 3))
613 return RESULT_SHOWUSAGE;
615 if (!ast_opt_dont_warn)
616 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
617 "\tIt does not indicate anything about your configuration.\n");
619 ast_cli(fd, "%11s %9s %10s TYPE %5s %s\n","INT","BINARY","HEX","NAME","DESC");
620 ast_cli(fd, "--------------------------------------------------------------------------------\n");
621 if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
622 found = 1;
623 for (i=0;i<11;i++) {
624 snprintf(hex,25,"(0x%x)",1<<i);
625 ast_cli(fd, "%11u (1 << %2d) %10s audio %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
629 if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
630 found = 1;
631 for (i=16;i<18;i++) {
632 snprintf(hex,25,"(0x%x)",1<<i);
633 ast_cli(fd, "%11u (1 << %2d) %10s image %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
637 if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
638 found = 1;
639 for (i=18;i<22;i++) {
640 snprintf(hex,25,"(0x%x)",1<<i);
641 ast_cli(fd, "%11u (1 << %2d) %10s video %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
645 if (! found)
646 return RESULT_SHOWUSAGE;
647 else
648 return RESULT_SUCCESS;
651 static char frame_show_codecs_usage[] =
652 "Usage: show [audio|video|image] codecs\n"
653 " Displays codec mapping\n";
655 static int show_codec_n(int fd, int argc, char *argv[])
657 int codec, i, found=0;
659 if (argc != 3)
660 return RESULT_SHOWUSAGE;
662 if (sscanf(argv[2],"%d",&codec) != 1)
663 return RESULT_SHOWUSAGE;
665 for (i = 0; i < 32; i++)
666 if (codec & (1 << i)) {
667 found = 1;
668 ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
671 if (!found)
672 ast_cli(fd, "Codec %d not found\n", codec);
674 return RESULT_SUCCESS;
677 static char frame_show_codec_n_usage[] =
678 "Usage: show codec <number>\n"
679 " Displays codec mapping\n";
681 /*! Dump a frame for debugging purposes */
682 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
684 const char noname[] = "unknown";
685 char ftype[40] = "Unknown Frametype";
686 char cft[80];
687 char subclass[40] = "Unknown Subclass";
688 char csub[80];
689 char moreinfo[40] = "";
690 char cn[60];
691 char cp[40];
692 char cmn[40];
694 if (!name)
695 name = noname;
698 if (!f) {
699 ast_verbose("%s [ %s (NULL) ] [%s]\n",
700 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
701 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
702 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
703 return;
705 /* XXX We should probably print one each of voice and video when the format changes XXX */
706 if (f->frametype == AST_FRAME_VOICE)
707 return;
708 if (f->frametype == AST_FRAME_VIDEO)
709 return;
710 switch(f->frametype) {
711 case AST_FRAME_DTMF:
712 strcpy(ftype, "DTMF");
713 subclass[0] = f->subclass;
714 subclass[1] = '\0';
715 break;
716 case AST_FRAME_CONTROL:
717 strcpy(ftype, "Control");
718 switch(f->subclass) {
719 case AST_CONTROL_HANGUP:
720 strcpy(subclass, "Hangup");
721 break;
722 case AST_CONTROL_RING:
723 strcpy(subclass, "Ring");
724 break;
725 case AST_CONTROL_RINGING:
726 strcpy(subclass, "Ringing");
727 break;
728 case AST_CONTROL_ANSWER:
729 strcpy(subclass, "Answer");
730 break;
731 case AST_CONTROL_BUSY:
732 strcpy(subclass, "Busy");
733 break;
734 case AST_CONTROL_TAKEOFFHOOK:
735 strcpy(subclass, "Take Off Hook");
736 break;
737 case AST_CONTROL_OFFHOOK:
738 strcpy(subclass, "Line Off Hook");
739 break;
740 case AST_CONTROL_CONGESTION:
741 strcpy(subclass, "Congestion");
742 break;
743 case AST_CONTROL_FLASH:
744 strcpy(subclass, "Flash");
745 break;
746 case AST_CONTROL_WINK:
747 strcpy(subclass, "Wink");
748 break;
749 case AST_CONTROL_OPTION:
750 strcpy(subclass, "Option");
751 break;
752 case AST_CONTROL_RADIO_KEY:
753 strcpy(subclass, "Key Radio");
754 break;
755 case AST_CONTROL_RADIO_UNKEY:
756 strcpy(subclass, "Unkey Radio");
757 break;
758 case -1:
759 strcpy(subclass, "Stop generators");
760 break;
761 default:
762 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
764 break;
765 case AST_FRAME_NULL:
766 strcpy(ftype, "Null Frame");
767 strcpy(subclass, "N/A");
768 break;
769 case AST_FRAME_IAX:
770 /* Should never happen */
771 strcpy(ftype, "IAX Specific");
772 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
773 break;
774 case AST_FRAME_TEXT:
775 strcpy(ftype, "Text");
776 strcpy(subclass, "N/A");
777 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
778 break;
779 case AST_FRAME_IMAGE:
780 strcpy(ftype, "Image");
781 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
782 break;
783 case AST_FRAME_HTML:
784 strcpy(ftype, "HTML");
785 switch(f->subclass) {
786 case AST_HTML_URL:
787 strcpy(subclass, "URL");
788 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
789 break;
790 case AST_HTML_DATA:
791 strcpy(subclass, "Data");
792 break;
793 case AST_HTML_BEGIN:
794 strcpy(subclass, "Begin");
795 break;
796 case AST_HTML_END:
797 strcpy(subclass, "End");
798 break;
799 case AST_HTML_LDCOMPLETE:
800 strcpy(subclass, "Load Complete");
801 break;
802 case AST_HTML_NOSUPPORT:
803 strcpy(subclass, "No Support");
804 break;
805 case AST_HTML_LINKURL:
806 strcpy(subclass, "Link URL");
807 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
808 break;
809 case AST_HTML_UNLINK:
810 strcpy(subclass, "Unlink");
811 break;
812 case AST_HTML_LINKREJECT:
813 strcpy(subclass, "Link Reject");
814 break;
815 default:
816 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
817 break;
819 break;
820 case AST_FRAME_MODEM:
821 strcpy(ftype, "Modem");
822 switch (f->subclass) {
823 case AST_MODEM_T38:
824 strcpy(subclass, "T.38");
825 break;
826 case AST_MODEM_V150:
827 strcpy(subclass, "V.150");
828 break;
829 default:
830 snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
831 break;
833 break;
834 default:
835 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
837 if (!ast_strlen_zero(moreinfo))
838 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
839 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
840 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
841 f->frametype,
842 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
843 f->subclass,
844 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
845 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
846 else
847 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
848 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
849 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
850 f->frametype,
851 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
852 f->subclass,
853 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
857 #ifdef TRACE_FRAMES
858 static int show_frame_stats(int fd, int argc, char *argv[])
860 struct ast_frame *f;
861 int x=1;
862 if (argc != 3)
863 return RESULT_SHOWUSAGE;
864 ast_cli(fd, " Framer Statistics \n");
865 ast_cli(fd, "---------------------------\n");
866 ast_cli(fd, "Total allocated headers: %d\n", headers);
867 ast_cli(fd, "Queue Dump:\n");
868 ast_mutex_lock(&framelock);
869 for (f=headerlist; f; f = f->next) {
870 ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
872 ast_mutex_unlock(&framelock);
873 return RESULT_SUCCESS;
876 static char frame_stats_usage[] =
877 "Usage: show frame stats\n"
878 " Displays debugging statistics from framer\n";
879 #endif
881 /* Builtin Asterisk CLI-commands for debugging */
882 static struct ast_cli_entry my_clis[] = {
883 { { "show", "codecs", NULL }, show_codecs, "Shows codecs", frame_show_codecs_usage },
884 { { "show", "audio", "codecs", NULL }, show_codecs, "Shows audio codecs", frame_show_codecs_usage },
885 { { "show", "video", "codecs", NULL }, show_codecs, "Shows video codecs", frame_show_codecs_usage },
886 { { "show", "image", "codecs", NULL }, show_codecs, "Shows image codecs", frame_show_codecs_usage },
887 { { "show", "codec", NULL }, show_codec_n, "Shows a specific codec", frame_show_codec_n_usage },
888 #ifdef TRACE_FRAMES
889 { { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage },
890 #endif
893 int init_framer(void)
895 ast_cli_register_multiple(my_clis, sizeof(my_clis)/sizeof(my_clis[0]) );
896 return 0;
899 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
901 int x, differential = (int) 'A', mem;
902 char *from, *to;
904 if(right) {
905 from = pref->order;
906 to = buf;
907 mem = size;
908 } else {
909 to = pref->order;
910 from = buf;
911 mem = 32;
914 memset(to, 0, mem);
915 for (x = 0; x < 32 ; x++) {
916 if(!from[x])
917 break;
918 to[x] = right ? (from[x] + differential) : (from[x] - differential);
922 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
924 int x, codec;
925 size_t total_len, slen;
926 char *formatname;
928 memset(buf,0,size);
929 total_len = size;
930 buf[0] = '(';
931 total_len--;
932 for(x = 0; x < 32 ; x++) {
933 if(total_len <= 0)
934 break;
935 if(!(codec = ast_codec_pref_index(pref,x)))
936 break;
937 if((formatname = ast_getformatname(codec))) {
938 slen = strlen(formatname);
939 if(slen > total_len)
940 break;
941 strncat(buf,formatname,total_len);
942 total_len -= slen;
944 if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
945 strncat(buf,"|",total_len);
946 total_len--;
949 if(total_len) {
950 strncat(buf,")",total_len);
951 total_len--;
954 return size - total_len;
957 int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
959 int slot = 0;
962 if((index >= 0) && (index < sizeof(pref->order))) {
963 slot = pref->order[index];
966 return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
969 /*! \brief Remove codec from pref list */
970 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
972 struct ast_codec_pref oldorder;
973 int x, y = 0;
974 int slot;
976 if(!pref->order[0])
977 return;
979 memcpy(&oldorder, pref, sizeof(oldorder));
980 memset(pref, 0, sizeof(*pref));
982 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
983 slot = oldorder.order[x];
984 if(! slot)
985 break;
986 if(AST_FORMAT_LIST[slot-1].bits != format)
987 pref->order[y++] = slot;
992 /*! \brief Append codec to list */
993 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
995 int x, newindex = -1;
997 ast_codec_pref_remove(pref, format);
999 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1000 if(AST_FORMAT_LIST[x].bits == format) {
1001 newindex = x + 1;
1002 break;
1006 if(newindex) {
1007 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1008 if(!pref->order[x]) {
1009 pref->order[x] = newindex;
1010 break;
1015 return x;
1019 /*! \brief Pick a codec */
1020 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
1022 int x, ret = 0, slot;
1024 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1025 slot = pref->order[x];
1027 if (!slot)
1028 break;
1029 if (formats & AST_FORMAT_LIST[slot-1].bits) {
1030 ret = AST_FORMAT_LIST[slot-1].bits;
1031 break;
1034 if(ret & AST_FORMAT_AUDIO_MASK)
1035 return ret;
1037 if (option_debug > 3)
1038 ast_log(LOG_DEBUG, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1040 return find_best ? ast_best_codec(formats) : 0;
1043 void ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
1045 char *parse;
1046 char *this;
1047 int format;
1049 parse = ast_strdupa(list);
1050 while ((this = strsep(&parse, ","))) {
1051 if (!(format = ast_getformatbyname(this))) {
1052 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1053 continue;
1056 if (mask) {
1057 if (allowing)
1058 *mask |= format;
1059 else
1060 *mask &= ~format;
1063 /* Set up a preference list for audio. Do not include video in preferences
1064 since we can not transcode video and have to use whatever is offered
1066 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1067 if (strcasecmp(this, "all")) {
1068 if (allowing)
1069 ast_codec_pref_append(pref, format);
1070 else
1071 ast_codec_pref_remove(pref, format);
1072 } else if (!allowing) {
1073 memset(pref, 0, sizeof(*pref));
1079 static int g723_len(unsigned char buf)
1081 enum frame_type type = buf & TYPE_MASK;
1083 switch(type) {
1084 case TYPE_DONTSEND:
1085 return 0;
1086 break;
1087 case TYPE_SILENCE:
1088 return 4;
1089 break;
1090 case TYPE_HIGH:
1091 return 24;
1092 break;
1093 case TYPE_LOW:
1094 return 20;
1095 break;
1096 default:
1097 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
1099 return -1;
1102 static int g723_samples(unsigned char *buf, int maxlen)
1104 int pos = 0;
1105 int samples = 0;
1106 int res;
1107 while(pos < maxlen) {
1108 res = g723_len(buf[pos]);
1109 if (res <= 0)
1110 break;
1111 samples += 240;
1112 pos += res;
1114 return samples;
1117 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1119 int byte = bit / 8; /* byte containing first bit */
1120 int rem = 8 - (bit % 8); /* remaining bits in first byte */
1121 unsigned char ret = 0;
1123 if (n <= 0 || n > 8)
1124 return 0;
1126 if (rem < n) {
1127 ret = (data[byte] << (n - rem));
1128 ret |= (data[byte + 1] >> (8 - n + rem));
1129 } else {
1130 ret = (data[byte] >> (rem - n));
1133 return (ret & (0xff >> (8 - n)));
1136 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1138 static int SpeexWBSubModeSz[] = {
1139 0, 36, 112, 192,
1140 352, 0, 0, 0 };
1141 int off = bit;
1142 unsigned char c;
1144 /* skip up to two wideband frames */
1145 if (((len * 8 - off) >= 5) &&
1146 get_n_bits_at(data, 1, off)) {
1147 c = get_n_bits_at(data, 3, off + 1);
1148 off += SpeexWBSubModeSz[c];
1150 if (((len * 8 - off) >= 5) &&
1151 get_n_bits_at(data, 1, off)) {
1152 c = get_n_bits_at(data, 3, off + 1);
1153 off += SpeexWBSubModeSz[c];
1155 if (((len * 8 - off) >= 5) &&
1156 get_n_bits_at(data, 1, off)) {
1157 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1158 return -1;
1163 return off - bit;
1166 static int speex_samples(unsigned char *data, int len)
1168 static int SpeexSubModeSz[] = {
1169 5, 43, 119, 160,
1170 220, 300, 364, 492,
1171 79, 0, 0, 0,
1172 0, 0, 0, 0 };
1173 static int SpeexInBandSz[] = {
1174 1, 1, 4, 4,
1175 4, 4, 4, 4,
1176 8, 8, 16, 16,
1177 32, 32, 64, 64 };
1178 int bit = 0;
1179 int cnt = 0;
1180 int off;
1181 unsigned char c;
1183 while ((len * 8 - bit) >= 5) {
1184 /* skip wideband frames */
1185 off = speex_get_wb_sz_at(data, len, bit);
1186 if (off < 0) {
1187 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1188 break;
1190 bit += off;
1192 if ((len * 8 - bit) < 5) {
1193 ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1194 break;
1197 /* get control bits */
1198 c = get_n_bits_at(data, 5, bit);
1199 bit += 5;
1201 if (c == 15) {
1202 /* terminator */
1203 break;
1204 } else if (c == 14) {
1205 /* in-band signal; next 4 bits contain signal id */
1206 c = get_n_bits_at(data, 4, bit);
1207 bit += 4;
1208 bit += SpeexInBandSz[c];
1209 } else if (c == 13) {
1210 /* user in-band; next 5 bits contain msg len */
1211 c = get_n_bits_at(data, 5, bit);
1212 bit += 5;
1213 bit += c * 8;
1214 } else if (c > 8) {
1215 /* unknown */
1216 break;
1217 } else {
1218 /* skip number bits for submode (less the 5 control bits) */
1219 bit += SpeexSubModeSz[c] - 5;
1220 cnt += 160; /* new frame */
1223 return cnt;
1226 int ast_codec_get_samples(struct ast_frame *f)
1228 int samples=0;
1229 switch(f->subclass) {
1230 case AST_FORMAT_SPEEX:
1231 samples = speex_samples(f->data, f->datalen);
1232 break;
1233 case AST_FORMAT_G723_1:
1234 samples = g723_samples(f->data, f->datalen);
1235 break;
1236 case AST_FORMAT_ILBC:
1237 samples = 240 * (f->datalen / 50);
1238 break;
1239 case AST_FORMAT_GSM:
1240 samples = 160 * (f->datalen / 33);
1241 break;
1242 case AST_FORMAT_G729A:
1243 samples = f->datalen * 8;
1244 break;
1245 case AST_FORMAT_SLINEAR:
1246 samples = f->datalen / 2;
1247 break;
1248 case AST_FORMAT_LPC10:
1249 /* assumes that the RTP packet contains one LPC10 frame */
1250 samples = 22 * 8;
1251 samples += (((char *)(f->data))[7] & 0x1) * 8;
1252 break;
1253 case AST_FORMAT_ULAW:
1254 case AST_FORMAT_ALAW:
1255 samples = f->datalen;
1256 break;
1257 case AST_FORMAT_ADPCM:
1258 case AST_FORMAT_G726:
1259 case AST_FORMAT_G726_AAL2:
1260 samples = f->datalen * 2;
1261 break;
1262 default:
1263 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1265 return samples;
1268 int ast_codec_get_len(int format, int samples)
1270 int len = 0;
1272 /* XXX Still need speex, g723, and lpc10 XXX */
1273 switch(format) {
1274 case AST_FORMAT_ILBC:
1275 len = (samples / 240) * 50;
1276 break;
1277 case AST_FORMAT_GSM:
1278 len = (samples / 160) * 33;
1279 break;
1280 case AST_FORMAT_G729A:
1281 len = samples / 8;
1282 break;
1283 case AST_FORMAT_SLINEAR:
1284 len = samples * 2;
1285 break;
1286 case AST_FORMAT_ULAW:
1287 case AST_FORMAT_ALAW:
1288 len = samples;
1289 break;
1290 case AST_FORMAT_ADPCM:
1291 case AST_FORMAT_G726:
1292 case AST_FORMAT_G726_AAL2:
1293 len = samples / 2;
1294 break;
1295 default:
1296 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1299 return len;
1302 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1304 int count;
1305 short *fdata = f->data;
1306 short adjust_value = abs(adjustment);
1308 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
1309 return -1;
1311 if (!adjustment)
1312 return 0;
1314 for (count = 0; count < f->samples; count++) {
1315 if (adjustment > 0) {
1316 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1317 } else if (adjustment < 0) {
1318 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1322 return 0;
1325 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1327 int count;
1328 short *data1, *data2;
1330 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
1331 return -1;
1333 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
1334 return -1;
1336 if (f1->samples != f2->samples)
1337 return -1;
1339 for (count = 0, data1 = f1->data, data2 = f2->data;
1340 count < f1->samples;
1341 count++, data1++, data2++)
1342 ast_slinear_saturated_add(data1, data2);
1344 return 0;
1347 struct ast_frame *ast_frame_enqueue(struct ast_frame *head, struct ast_frame *f, int maxlen, int dupe)
1349 struct ast_frame *cur, *oldhead;
1350 int len=0;
1351 if (f && dupe)
1352 f = ast_frdup(f);
1353 if (!f)
1354 return head;
1356 f->next = NULL;
1357 if (!head)
1358 return f;
1359 cur = head;
1360 while(cur->next) {
1361 cur = cur->next;
1362 len++;
1363 if (len >= maxlen) {
1364 oldhead = head;
1365 head = head->next;
1366 ast_frfree(oldhead);
1369 return head;