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.
21 * \brief Frame and codec manipulation routines
23 * \author Mark Spencer <markster@digium.com>
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30 #include "asterisk/_private.h"
31 #include "asterisk/lock.h"
32 #include "asterisk/frame.h"
33 #include "asterisk/channel.h"
34 #include "asterisk/cli.h"
35 #include "asterisk/term.h"
36 #include "asterisk/utils.h"
37 #include "asterisk/threadstorage.h"
38 #include "asterisk/linkedlists.h"
39 #include "asterisk/translate.h"
43 static AST_LIST_HEAD_STATIC(headerlist, ast_frame);
46 #if !defined(LOW_MEMORY)
47 static void frame_cache_cleanup(void *data);
49 /*! \brief A per-thread cache of frame headers */
50 AST_THREADSTORAGE_CUSTOM(frame_cache, NULL, frame_cache_cleanup);
53 * \brief Maximum ast_frame cache size
55 * In most cases where the frame header cache will be useful, the size
56 * of the cache will stay very small. However, it is not always the case that
57 * the same thread that allocates the frame will be the one freeing them, so
58 * sometimes a thread will never have any frames in its cache, or the cache
59 * will never be pulled from. For the latter case, we limit the maximum size.
61 #define FRAME_CACHE_MAX_SIZE 10
63 /*! \brief This is just so ast_frames, a list head struct for holding a list of
64 * ast_frame structures, is defined. */
65 AST_LIST_HEAD_NOLOCK(ast_frames, ast_frame);
67 struct ast_frame_cache {
68 struct ast_frames list;
73 #define SMOOTHER_SIZE 8000
78 TYPE_SILENCE, /* 0x2 */
79 TYPE_DONTSEND /* 0x3 */
88 int optimizablestream;
92 struct timeval delivery;
93 char data[SMOOTHER_SIZE];
94 char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
95 struct ast_frame *opt;
99 /*! \brief Definition of supported media formats (codecs) */
100 static struct ast_format_list AST_FORMAT_LIST[] = {
101 { AST_FORMAT_G723_1 , "g723", 8000, "G.723.1", 20, 30, 300, 30, 30 }, /*!< G723.1 */
102 { AST_FORMAT_GSM, "gsm", 8000, "GSM", 33, 20, 300, 20, 20 }, /*!< codec_gsm.c */
103 { AST_FORMAT_ULAW, "ulaw", 8000, "G.711 u-law", 80, 10, 150, 10, 20 }, /*!< codec_ulaw.c */
104 { AST_FORMAT_ALAW, "alaw", 8000, "G.711 A-law", 80, 10, 150, 10, 20 }, /*!< codec_alaw.c */
105 { AST_FORMAT_G726, "g726", 8000, "G.726 RFC3551", 40, 10, 300, 10, 20 }, /*!< codec_g726.c */
106 { AST_FORMAT_ADPCM, "adpcm" , 8000, "ADPCM", 40, 10, 300, 10, 20 }, /*!< codec_adpcm.c */
107 { AST_FORMAT_SLINEAR, "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE }, /*!< Signed linear */
108 { AST_FORMAT_LPC10, "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20 }, /*!< codec_lpc10.c */
109 { AST_FORMAT_G729A, "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 }, /*!< Binary commercial distribution */
110 { AST_FORMAT_SPEEX, "speex", 8000, "SpeeX", 10, 10, 60, 10, 20 }, /*!< codec_speex.c */
111 { AST_FORMAT_ILBC, "ilbc", 8000, "iLBC", 50, 30, 30, 30, 30 }, /*!< codec_ilbc.c */ /* inc=30ms - workaround */
112 { AST_FORMAT_G726_AAL2, "g726aal2", 8000, "G.726 AAL2", 40, 10, 300, 10, 20 }, /*!< codec_g726.c */
113 { AST_FORMAT_G722, "g722", 16000, "G722", 80, 10, 150, 10, 20 }, /*!< codec_g722.c */
114 { AST_FORMAT_SLINEAR16, "slin16", 16000, "16 bit Signed Linear PCM (16kHz)", 320, 10, 70, 10, 20 }, /*!< Signed linear (16kHz) */
115 { AST_FORMAT_JPEG, "jpeg", 0, "JPEG image"}, /*!< See format_jpeg.c */
116 { AST_FORMAT_PNG, "png", 0, "PNG image"}, /*!< PNG Image format */
117 { AST_FORMAT_H261, "h261", 0, "H.261 Video" }, /*!< H.261 Video Passthrough */
118 { AST_FORMAT_H263, "h263", 0, "H.263 Video" }, /*!< H.263 Passthrough support, see format_h263.c */
119 { AST_FORMAT_H263_PLUS, "h263p", 0, "H.263+ Video" }, /*!< H.263plus passthrough support See format_h263.c */
120 { AST_FORMAT_H264, "h264", 0, "H.264 Video" }, /*!< Passthrough support, see format_h263.c */
121 { AST_FORMAT_MP4_VIDEO, "mpeg4", 0, "MPEG4 Video" }, /*!< Passthrough support for MPEG4 */
122 { AST_FORMAT_T140, "t140", 0, "Passthrough T.140 Realtime Text" }, /*!< Passthrough support for T.140 Realtime Text */
125 struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
127 void ast_smoother_reset(struct ast_smoother *s, int size)
129 memset(s, 0, sizeof(*s));
133 struct ast_smoother *ast_smoother_new(int size)
135 struct ast_smoother *s;
138 if ((s = ast_malloc(sizeof(*s))))
139 ast_smoother_reset(s, size);
143 int ast_smoother_get_flags(struct ast_smoother *s)
148 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
153 int ast_smoother_test_flag(struct ast_smoother *s, int flag)
155 return (s->flags & flag);
158 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
160 if (f->frametype != AST_FRAME_VOICE) {
161 ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
165 s->format = f->subclass;
166 s->samplesperbyte = (float)f->samples / (float)f->datalen;
167 } else if (s->format != f->subclass) {
168 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
171 if (s->len + f->datalen > SMOOTHER_SIZE) {
172 ast_log(LOG_WARNING, "Out of smoother space\n");
175 if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
176 && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
178 /* Optimize by sending the frame we just got
179 on the next read, thus eliminating the douple
182 ast_swapcopy_samples(f->data, f->data, f->samples);
186 s->optimizablestream++;
187 if (s->optimizablestream > 10) {
188 /* For the past 10 rounds, we have input and output
189 frames of the correct size for this smoother, yet
190 we were unable to optimize because there was still
191 some cruft left over. Lets just drop the cruft so
192 we can move to a fully optimized path */
194 ast_swapcopy_samples(f->data, f->data, f->samples);
201 s->optimizablestream = 0;
202 if (s->flags & AST_SMOOTHER_FLAG_G729) {
204 ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
209 ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
211 memcpy(s->data + s->len, f->data, f->datalen);
212 /* If either side is empty, reset the delivery time */
213 if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) /* XXX really ? */
214 s->delivery = f->delivery;
215 s->len += f->datalen;
219 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
221 struct ast_frame *opt;
224 /* IF we have an optimization frame, send it */
226 if (s->opt->offset < AST_FRIENDLY_OFFSET)
227 ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
234 /* Make sure we have enough data */
235 if (s->len < s->size) {
236 /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
237 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
244 s->f.frametype = AST_FRAME_VOICE;
245 s->f.subclass = s->format;
246 s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
247 s->f.offset = AST_FRIENDLY_OFFSET;
249 /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
250 s->f.samples = len * s->samplesperbyte; /* XXX rounding */
251 s->f.delivery = s->delivery;
253 memcpy(s->f.data, s->data, len);
255 /* Move remaining data to the front if applicable */
257 /* In principle this should all be fine because if we are sending
258 G.729 VAD, the next timestamp will take over anyawy */
259 memmove(s->data, s->data + len, s->len);
260 if (!ast_tvzero(s->delivery)) {
261 /* If we have delivery time, increment it, otherwise, leave it at 0 */
262 s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
269 void ast_smoother_free(struct ast_smoother *s)
274 static struct ast_frame *ast_frame_header_new(void)
278 #if !defined(LOW_MEMORY)
279 struct ast_frame_cache *frames;
281 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
282 if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
283 size_t mallocd_len = f->mallocd_hdr_len;
284 memset(f, 0, sizeof(*f));
285 f->mallocd_hdr_len = mallocd_len;
286 f->mallocd = AST_MALLOCD_HDR;
291 if (!(f = ast_calloc_cache(1, sizeof(*f))))
294 if (!(f = ast_calloc(1, sizeof(*f))))
298 f->mallocd_hdr_len = sizeof(*f);
300 AST_LIST_LOCK(&headerlist);
302 AST_LIST_INSERT_HEAD(&headerlist, f, frame_list);
303 AST_LIST_UNLOCK(&headerlist);
309 #if !defined(LOW_MEMORY)
310 static void frame_cache_cleanup(void *data)
312 struct ast_frame_cache *frames = data;
315 while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
322 void ast_frame_free(struct ast_frame *fr, int cache)
324 if (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR))
325 ast_translate_frame_freed(fr);
330 #if !defined(LOW_MEMORY)
331 if (cache && fr->mallocd == AST_MALLOCD_HDR) {
332 /* Cool, only the header is malloc'd, let's just cache those for now
333 * to keep things simple... */
334 struct ast_frame_cache *frames;
336 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))
337 && frames->size < FRAME_CACHE_MAX_SIZE) {
338 AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
345 if (fr->mallocd & AST_MALLOCD_DATA) {
347 ast_free(fr->data - fr->offset);
349 if (fr->mallocd & AST_MALLOCD_SRC) {
351 ast_free((char *)fr->src);
353 if (fr->mallocd & AST_MALLOCD_HDR) {
355 AST_LIST_LOCK(&headerlist);
357 AST_LIST_REMOVE(&headerlist, fr, frame_list);
358 AST_LIST_UNLOCK(&headerlist);
365 * \brief 'isolates' a frame by duplicating non-malloc'ed components
366 * (header, src, data).
367 * On return all components are malloc'ed
369 struct ast_frame *ast_frisolate(struct ast_frame *fr)
371 struct ast_frame *out;
374 ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
376 if (!(fr->mallocd & AST_MALLOCD_HDR)) {
377 /* Allocate a new header if needed */
378 if (!(out = ast_frame_header_new()))
380 out->frametype = fr->frametype;
381 out->subclass = fr->subclass;
382 out->datalen = fr->datalen;
383 out->samples = fr->samples;
384 out->offset = fr->offset;
385 out->data = fr->data;
386 /* Copy the timing data */
387 ast_copy_flags(out, fr, AST_FRFLAG_HAS_TIMING_INFO);
388 if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
391 out->seqno = fr->seqno;
396 if (!(fr->mallocd & AST_MALLOCD_SRC)) {
398 if (!(out->src = ast_strdup(fr->src))) {
407 if (!(fr->mallocd & AST_MALLOCD_DATA)) {
408 if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
409 if (out->src != fr->src)
410 ast_free((void *) out->src);
415 newdata += AST_FRIENDLY_OFFSET;
416 out->offset = AST_FRIENDLY_OFFSET;
417 out->datalen = fr->datalen;
418 memcpy(newdata, fr->data, fr->datalen);
422 out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
427 struct ast_frame *ast_frdup(const struct ast_frame *f)
429 struct ast_frame *out = NULL;
433 #if !defined(LOW_MEMORY)
434 struct ast_frame_cache *frames;
437 /* Start with standard stuff */
438 len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
439 /* If we have a source, add space for it */
441 * XXX Watch out here - if we receive a src which is not terminated
442 * properly, we can be easily attacked. Should limit the size we deal with.
445 srclen = strlen(f->src);
449 #if !defined(LOW_MEMORY)
450 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
451 AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
452 if (out->mallocd_hdr_len >= len) {
453 size_t mallocd_len = out->mallocd_hdr_len;
455 AST_LIST_REMOVE_CURRENT(frame_list);
456 memset(out, 0, sizeof(*out));
457 out->mallocd_hdr_len = mallocd_len;
463 AST_LIST_TRAVERSE_SAFE_END;
468 if (!(buf = ast_calloc_cache(1, len)))
471 out->mallocd_hdr_len = len;
474 out->frametype = f->frametype;
475 out->subclass = f->subclass;
476 out->datalen = f->datalen;
477 out->samples = f->samples;
478 out->delivery = f->delivery;
479 /* Set us as having malloc'd header only, so it will eventually
481 out->mallocd = AST_MALLOCD_HDR;
482 out->offset = AST_FRIENDLY_OFFSET;
484 out->data = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
485 memcpy(out->data, f->data, out->datalen);
488 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
489 /* Must have space since we allocated for it */
490 strcpy((char *)out->src, f->src);
492 ast_copy_flags(out, f, AST_FRFLAG_HAS_TIMING_INFO);
495 out->seqno = f->seqno;
499 void ast_swapcopy_samples(void *dst, const void *src, int samples)
502 unsigned short *dst_s = dst;
503 const unsigned short *src_s = src;
505 for (i = 0; i < samples; i++)
506 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
510 struct ast_format_list *ast_get_format_list_index(int index)
512 return &AST_FORMAT_LIST[index];
515 struct ast_format_list *ast_get_format_list(size_t *size)
517 *size = (sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]));
518 return AST_FORMAT_LIST;
521 char* ast_getformatname(int format)
524 char *ret = "unknown";
525 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
526 if (AST_FORMAT_LIST[x].bits == format) {
527 ret = AST_FORMAT_LIST[x].name;
534 char *ast_getformatname_multiple(char *buf, size_t size, int format)
538 char *start, *end = buf;
542 snprintf(end, size, "0x%x (", format);
547 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
548 if (AST_FORMAT_LIST[x].bits & format) {
549 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
556 ast_copy_string(start, "nothing)", size);
562 static struct ast_codec_alias_table {
565 } ast_codec_alias_table[] = {
566 { "slinear", "slin"},
567 { "slinear16", "slin16"},
571 static const char *ast_expand_codec_alias(const char *in)
575 for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(ast_codec_alias_table[0]); x++) {
576 if (!strcmp(in,ast_codec_alias_table[x].alias))
577 return ast_codec_alias_table[x].realname;
582 int ast_getformatbyname(const char *name)
584 int x, all, format = 0;
586 all = strcasecmp(name, "all") ? 0 : 1;
587 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
589 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
590 !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name))) {
591 format |= AST_FORMAT_LIST[x].bits;
600 char *ast_codec2str(int codec)
603 char *ret = "unknown";
604 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
605 if (AST_FORMAT_LIST[x].bits == codec) {
606 ret = AST_FORMAT_LIST[x].desc;
613 static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
620 e->command = "core show codecs [audio|video|image]";
622 "Usage: core show codecs [audio|video|image]\n"
623 " Displays codec mapping\n";
629 if ((a->argc < 3) || (a->argc > 4))
630 return CLI_SHOWUSAGE;
632 if (!ast_opt_dont_warn)
633 ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
634 "\tIt does not indicate anything about your configuration.\n");
636 ast_cli(a->fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
637 ast_cli(a->fd, "--------------------------------------------------------------------------------\n");
638 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"audio"))) {
641 snprintf(hex,25,"(0x%x)",1<<i);
642 ast_cli(a->fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
646 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"image"))) {
648 for (i=16;i<18;i++) {
649 snprintf(hex,25,"(0x%x)",1<<i);
650 ast_cli(a->fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
654 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"video"))) {
656 for (i=18;i<22;i++) {
657 snprintf(hex,25,"(0x%x)",1<<i);
658 ast_cli(a->fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
663 return CLI_SHOWUSAGE;
668 static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
670 int codec, i, found=0;
674 e->command = "core show codec";
676 "Usage: core show codec <number>\n"
677 " Displays codec mapping\n";
684 return CLI_SHOWUSAGE;
686 if (sscanf(a->argv[3],"%d",&codec) != 1)
687 return CLI_SHOWUSAGE;
689 for (i = 0; i < 32; i++)
690 if (codec & (1 << i)) {
692 ast_cli(a->fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
696 ast_cli(a->fd, "Codec %d not found\n", codec);
701 /*! Dump a frame for debugging purposes */
702 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
704 const char noname[] = "unknown";
705 char ftype[40] = "Unknown Frametype";
707 char subclass[40] = "Unknown Subclass";
709 char moreinfo[40] = "";
719 ast_verbose("%s [ %s (NULL) ] [%s]\n",
720 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
721 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
722 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
725 /* XXX We should probably print one each of voice and video when the format changes XXX */
726 if (f->frametype == AST_FRAME_VOICE)
728 if (f->frametype == AST_FRAME_VIDEO)
730 switch(f->frametype) {
731 case AST_FRAME_DTMF_BEGIN:
732 strcpy(ftype, "DTMF Begin");
733 subclass[0] = f->subclass;
736 case AST_FRAME_DTMF_END:
737 strcpy(ftype, "DTMF End");
738 subclass[0] = f->subclass;
741 case AST_FRAME_CONTROL:
742 strcpy(ftype, "Control");
743 switch(f->subclass) {
744 case AST_CONTROL_HANGUP:
745 strcpy(subclass, "Hangup");
747 case AST_CONTROL_RING:
748 strcpy(subclass, "Ring");
750 case AST_CONTROL_RINGING:
751 strcpy(subclass, "Ringing");
753 case AST_CONTROL_ANSWER:
754 strcpy(subclass, "Answer");
756 case AST_CONTROL_BUSY:
757 strcpy(subclass, "Busy");
759 case AST_CONTROL_TAKEOFFHOOK:
760 strcpy(subclass, "Take Off Hook");
762 case AST_CONTROL_OFFHOOK:
763 strcpy(subclass, "Line Off Hook");
765 case AST_CONTROL_CONGESTION:
766 strcpy(subclass, "Congestion");
768 case AST_CONTROL_FLASH:
769 strcpy(subclass, "Flash");
771 case AST_CONTROL_WINK:
772 strcpy(subclass, "Wink");
774 case AST_CONTROL_OPTION:
775 strcpy(subclass, "Option");
777 case AST_CONTROL_RADIO_KEY:
778 strcpy(subclass, "Key Radio");
780 case AST_CONTROL_RADIO_UNKEY:
781 strcpy(subclass, "Unkey Radio");
783 case AST_CONTROL_HOLD:
784 strcpy(subclass, "Hold");
786 case AST_CONTROL_UNHOLD:
787 strcpy(subclass, "Unhold");
790 strcpy(subclass, "Stop generators");
793 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
797 strcpy(ftype, "Null Frame");
798 strcpy(subclass, "N/A");
801 /* Should never happen */
802 strcpy(ftype, "IAX Specific");
803 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
806 strcpy(ftype, "Text");
807 strcpy(subclass, "N/A");
808 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
810 case AST_FRAME_IMAGE:
811 strcpy(ftype, "Image");
812 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
815 strcpy(ftype, "HTML");
816 switch(f->subclass) {
818 strcpy(subclass, "URL");
819 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
822 strcpy(subclass, "Data");
825 strcpy(subclass, "Begin");
828 strcpy(subclass, "End");
830 case AST_HTML_LDCOMPLETE:
831 strcpy(subclass, "Load Complete");
833 case AST_HTML_NOSUPPORT:
834 strcpy(subclass, "No Support");
836 case AST_HTML_LINKURL:
837 strcpy(subclass, "Link URL");
838 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
840 case AST_HTML_UNLINK:
841 strcpy(subclass, "Unlink");
843 case AST_HTML_LINKREJECT:
844 strcpy(subclass, "Link Reject");
847 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
851 case AST_FRAME_MODEM:
852 strcpy(ftype, "Modem");
853 switch (f->subclass) {
855 strcpy(subclass, "T.38");
858 strcpy(subclass, "V.150");
861 snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
866 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
868 if (!ast_strlen_zero(moreinfo))
869 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
870 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
871 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
873 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
875 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
876 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
878 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
879 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
880 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
882 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
884 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
889 static char *show_frame_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
896 e->command = "core show frame stats";
898 "Usage: core show frame stats\n"
899 " Displays debugging statistics from framer\n";
906 return CLI_SHOWUSAGE;
907 AST_LIST_LOCK(&headerlist);
908 ast_cli(a->fd, " Framer Statistics \n");
909 ast_cli(a->fd, "---------------------------\n");
910 ast_cli(a->fd, "Total allocated headers: %d\n", headers);
911 ast_cli(a->fd, "Queue Dump:\n");
912 AST_LIST_TRAVERSE(&headerlist, f, frame_list)
913 ast_cli(a->fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
914 AST_LIST_UNLOCK(&headerlist);
919 /* Builtin Asterisk CLI-commands for debugging */
920 static struct ast_cli_entry my_clis[] = {
921 AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
922 AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
924 AST_CLI_DEFINE(show_frame_stats, "Shows frame statistics"),
928 int init_framer(void)
930 ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
934 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
936 int x, differential = (int) 'A', mem;
950 for (x = 0; x < 32 ; x++) {
953 to[x] = right ? (from[x] + differential) : (from[x] - differential);
957 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
960 size_t total_len, slen;
967 for(x = 0; x < 32 ; x++) {
970 if (!(codec = ast_codec_pref_index(pref,x)))
972 if ((formatname = ast_getformatname(codec))) {
973 slen = strlen(formatname);
974 if (slen > total_len)
976 strncat(buf,formatname,total_len);
979 if (total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
980 strncat(buf,"|",total_len);
985 strncat(buf,")",total_len);
989 return size - total_len;
992 int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
997 if ((index >= 0) && (index < sizeof(pref->order))) {
998 slot = pref->order[index];
1001 return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
1004 /*! \brief Remove codec from pref list */
1005 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
1007 struct ast_codec_pref oldorder;
1012 if (!pref->order[0])
1015 memcpy(&oldorder, pref, sizeof(oldorder));
1016 memset(pref, 0, sizeof(*pref));
1018 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1019 slot = oldorder.order[x];
1020 size = oldorder.framing[x];
1023 if (AST_FORMAT_LIST[slot-1].bits != format) {
1024 pref->order[y] = slot;
1025 pref->framing[y++] = size;
1031 /*! \brief Append codec to list */
1032 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
1034 int x, newindex = 0;
1036 ast_codec_pref_remove(pref, format);
1038 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1039 if (AST_FORMAT_LIST[x].bits == format) {
1046 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1047 if (!pref->order[x]) {
1048 pref->order[x] = newindex;
1057 /*! \brief Prepend codec to list */
1058 void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing)
1060 int x, newindex = 0;
1062 /* First step is to get the codecs "index number" */
1063 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1064 if (AST_FORMAT_LIST[x].bits == format) {
1069 /* Done if its unknown */
1073 /* Now find any existing occurrence, or the end */
1074 for (x = 0; x < 32; x++) {
1075 if (!pref->order[x] || pref->order[x] == newindex)
1079 if (only_if_existing && !pref->order[x])
1082 /* Move down to make space to insert - either all the way to the end,
1083 or as far as the existing location (which will be overwritten) */
1084 for (; x > 0; x--) {
1085 pref->order[x] = pref->order[x - 1];
1086 pref->framing[x] = pref->framing[x - 1];
1089 /* And insert the new entry */
1090 pref->order[0] = newindex;
1091 pref->framing[0] = 0; /* ? */
1094 /*! \brief Set packet size for codec */
1095 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
1099 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1100 if (AST_FORMAT_LIST[x].bits == format) {
1109 /* size validation */
1111 framems = AST_FORMAT_LIST[index].def_ms;
1113 if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1114 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1116 if (framems < AST_FORMAT_LIST[index].min_ms)
1117 framems = AST_FORMAT_LIST[index].min_ms;
1119 if (framems > AST_FORMAT_LIST[index].max_ms)
1120 framems = AST_FORMAT_LIST[index].max_ms;
1123 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1124 if (pref->order[x] == (index + 1)) {
1125 pref->framing[x] = framems;
1133 /*! \brief Get packet size for codec */
1134 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
1136 int x, index = -1, framems = 0;
1137 struct ast_format_list fmt = { 0, };
1139 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1140 if (AST_FORMAT_LIST[x].bits == format) {
1141 fmt = AST_FORMAT_LIST[x];
1147 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1148 if (pref->order[x] == (index + 1)) {
1149 framems = pref->framing[x];
1154 /* size validation */
1156 framems = AST_FORMAT_LIST[index].def_ms;
1158 if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1159 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1161 if (framems < AST_FORMAT_LIST[index].min_ms)
1162 framems = AST_FORMAT_LIST[index].min_ms;
1164 if (framems > AST_FORMAT_LIST[index].max_ms)
1165 framems = AST_FORMAT_LIST[index].max_ms;
1167 fmt.cur_ms = framems;
1172 /*! \brief Pick a codec */
1173 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
1175 int x, ret = 0, slot;
1177 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1178 slot = pref->order[x];
1182 if (formats & AST_FORMAT_LIST[slot-1].bits) {
1183 ret = AST_FORMAT_LIST[slot-1].bits;
1187 if (ret & AST_FORMAT_AUDIO_MASK)
1190 ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1192 return find_best ? ast_best_codec(formats) : 0;
1195 int ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
1198 char *parse = NULL, *this = NULL, *psize = NULL;
1199 int format = 0, framems = 0;
1201 parse = ast_strdupa(list);
1202 while ((this = strsep(&parse, ","))) {
1204 if ((psize = strrchr(this, ':'))) {
1206 ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
1207 framems = atoi(psize);
1211 ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
1214 if (!(format = ast_getformatbyname(this))) {
1215 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1227 /* Set up a preference list for audio. Do not include video in preferences
1228 since we can not transcode video and have to use whatever is offered
1230 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1231 if (strcasecmp(this, "all")) {
1233 ast_codec_pref_append(pref, format);
1234 ast_codec_pref_setsize(pref, format, framems);
1237 ast_codec_pref_remove(pref, format);
1238 } else if (!allowing) {
1239 memset(pref, 0, sizeof(*pref));
1246 static int g723_len(unsigned char buf)
1248 enum frame_type type = buf & TYPE_MASK;
1264 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
1269 static int g723_samples(unsigned char *buf, int maxlen)
1274 while(pos < maxlen) {
1275 res = g723_len(buf[pos]);
1284 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1286 int byte = bit / 8; /* byte containing first bit */
1287 int rem = 8 - (bit % 8); /* remaining bits in first byte */
1288 unsigned char ret = 0;
1290 if (n <= 0 || n > 8)
1294 ret = (data[byte] << (n - rem));
1295 ret |= (data[byte + 1] >> (8 - n + rem));
1297 ret = (data[byte] >> (rem - n));
1300 return (ret & (0xff >> (8 - n)));
1303 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1305 static int SpeexWBSubModeSz[] = {
1311 /* skip up to two wideband frames */
1312 if (((len * 8 - off) >= 5) &&
1313 get_n_bits_at(data, 1, off)) {
1314 c = get_n_bits_at(data, 3, off + 1);
1315 off += SpeexWBSubModeSz[c];
1317 if (((len * 8 - off) >= 5) &&
1318 get_n_bits_at(data, 1, off)) {
1319 c = get_n_bits_at(data, 3, off + 1);
1320 off += SpeexWBSubModeSz[c];
1322 if (((len * 8 - off) >= 5) &&
1323 get_n_bits_at(data, 1, off)) {
1324 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1333 static int speex_samples(unsigned char *data, int len)
1335 static int SpeexSubModeSz[] = {
1340 static int SpeexInBandSz[] = {
1350 while ((len * 8 - bit) >= 5) {
1351 /* skip wideband frames */
1352 off = speex_get_wb_sz_at(data, len, bit);
1354 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1359 if ((len * 8 - bit) < 5) {
1360 ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1364 /* get control bits */
1365 c = get_n_bits_at(data, 5, bit);
1371 } else if (c == 14) {
1372 /* in-band signal; next 4 bits contain signal id */
1373 c = get_n_bits_at(data, 4, bit);
1375 bit += SpeexInBandSz[c];
1376 } else if (c == 13) {
1377 /* user in-band; next 5 bits contain msg len */
1378 c = get_n_bits_at(data, 5, bit);
1385 /* skip number bits for submode (less the 5 control bits) */
1386 bit += SpeexSubModeSz[c] - 5;
1387 cnt += 160; /* new frame */
1393 int ast_codec_get_samples(struct ast_frame *f)
1396 switch(f->subclass) {
1397 case AST_FORMAT_SPEEX:
1398 samples = speex_samples(f->data, f->datalen);
1400 case AST_FORMAT_G723_1:
1401 samples = g723_samples(f->data, f->datalen);
1403 case AST_FORMAT_ILBC:
1404 samples = 240 * (f->datalen / 50);
1406 case AST_FORMAT_GSM:
1407 samples = 160 * (f->datalen / 33);
1409 case AST_FORMAT_G729A:
1410 samples = f->datalen * 8;
1412 case AST_FORMAT_SLINEAR:
1413 case AST_FORMAT_SLINEAR16:
1414 samples = f->datalen / 2;
1416 case AST_FORMAT_LPC10:
1417 /* assumes that the RTP packet contains one LPC10 frame */
1419 samples += (((char *)(f->data))[7] & 0x1) * 8;
1421 case AST_FORMAT_ULAW:
1422 case AST_FORMAT_ALAW:
1423 samples = f->datalen;
1425 case AST_FORMAT_G722:
1426 case AST_FORMAT_ADPCM:
1427 case AST_FORMAT_G726:
1428 case AST_FORMAT_G726_AAL2:
1429 samples = f->datalen * 2;
1432 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1437 int ast_codec_get_len(int format, int samples)
1441 /* XXX Still need speex, g723, and lpc10 XXX */
1443 case AST_FORMAT_G723_1:
1444 len = (samples / 240) * 20;
1446 case AST_FORMAT_ILBC:
1447 len = (samples / 240) * 50;
1449 case AST_FORMAT_GSM:
1450 len = (samples / 160) * 33;
1452 case AST_FORMAT_G729A:
1455 case AST_FORMAT_SLINEAR:
1456 case AST_FORMAT_SLINEAR16:
1459 case AST_FORMAT_ULAW:
1460 case AST_FORMAT_ALAW:
1463 case AST_FORMAT_G722:
1464 case AST_FORMAT_ADPCM:
1465 case AST_FORMAT_G726:
1466 case AST_FORMAT_G726_AAL2:
1470 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1476 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1479 short *fdata = f->data;
1480 short adjust_value = abs(adjustment);
1482 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
1488 for (count = 0; count < f->samples; count++) {
1489 if (adjustment > 0) {
1490 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1491 } else if (adjustment < 0) {
1492 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1499 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1502 short *data1, *data2;
1504 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
1507 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
1510 if (f1->samples != f2->samples)
1513 for (count = 0, data1 = f1->data, data2 = f2->data;
1514 count < f1->samples;
1515 count++, data1++, data2++)
1516 ast_slinear_saturated_add(data1, data2);