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");
784 strcpy(subclass, "Stop generators");
787 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
791 strcpy(ftype, "Null Frame");
792 strcpy(subclass, "N/A");
795 /* Should never happen */
796 strcpy(ftype, "IAX Specific");
797 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
800 strcpy(ftype, "Text");
801 strcpy(subclass, "N/A");
802 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
804 case AST_FRAME_IMAGE:
805 strcpy(ftype, "Image");
806 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
809 strcpy(ftype, "HTML");
810 switch(f->subclass) {
812 strcpy(subclass, "URL");
813 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
816 strcpy(subclass, "Data");
819 strcpy(subclass, "Begin");
822 strcpy(subclass, "End");
824 case AST_HTML_LDCOMPLETE:
825 strcpy(subclass, "Load Complete");
827 case AST_HTML_NOSUPPORT:
828 strcpy(subclass, "No Support");
830 case AST_HTML_LINKURL:
831 strcpy(subclass, "Link URL");
832 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
834 case AST_HTML_UNLINK:
835 strcpy(subclass, "Unlink");
837 case AST_HTML_LINKREJECT:
838 strcpy(subclass, "Link Reject");
841 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
845 case AST_FRAME_MODEM:
846 strcpy(ftype, "Modem");
847 switch (f->subclass) {
849 strcpy(subclass, "T.38");
852 strcpy(subclass, "V.150");
855 snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
860 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
862 if (!ast_strlen_zero(moreinfo))
863 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
864 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
865 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
867 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
869 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
870 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
872 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
873 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
874 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
876 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
878 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
883 static char *show_frame_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
890 e->command = "core show frame stats";
892 "Usage: core show frame stats\n"
893 " Displays debugging statistics from framer\n";
900 return CLI_SHOWUSAGE;
901 AST_LIST_LOCK(&headerlist);
902 ast_cli(a->fd, " Framer Statistics \n");
903 ast_cli(a->fd, "---------------------------\n");
904 ast_cli(a->fd, "Total allocated headers: %d\n", headers);
905 ast_cli(a->fd, "Queue Dump:\n");
906 AST_LIST_TRAVERSE(&headerlist, f, frame_list)
907 ast_cli(a->fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
908 AST_LIST_UNLOCK(&headerlist);
913 /* Builtin Asterisk CLI-commands for debugging */
914 static struct ast_cli_entry my_clis[] = {
915 AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
916 AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
918 AST_CLI_DEFINE(show_frame_stats, "Shows frame statistics"),
922 int init_framer(void)
924 ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
928 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
930 int x, differential = (int) 'A', mem;
944 for (x = 0; x < 32 ; x++) {
947 to[x] = right ? (from[x] + differential) : (from[x] - differential);
951 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
954 size_t total_len, slen;
961 for(x = 0; x < 32 ; x++) {
964 if (!(codec = ast_codec_pref_index(pref,x)))
966 if ((formatname = ast_getformatname(codec))) {
967 slen = strlen(formatname);
968 if (slen > total_len)
970 strncat(buf,formatname,total_len);
973 if (total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
974 strncat(buf,"|",total_len);
979 strncat(buf,")",total_len);
983 return size - total_len;
986 int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
991 if ((index >= 0) && (index < sizeof(pref->order))) {
992 slot = pref->order[index];
995 return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
998 /*! \brief Remove codec from pref list */
999 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
1001 struct ast_codec_pref oldorder;
1006 if (!pref->order[0])
1009 memcpy(&oldorder, pref, sizeof(oldorder));
1010 memset(pref, 0, sizeof(*pref));
1012 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1013 slot = oldorder.order[x];
1014 size = oldorder.framing[x];
1017 if (AST_FORMAT_LIST[slot-1].bits != format) {
1018 pref->order[y] = slot;
1019 pref->framing[y++] = size;
1025 /*! \brief Append codec to list */
1026 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
1028 int x, newindex = 0;
1030 ast_codec_pref_remove(pref, format);
1032 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1033 if (AST_FORMAT_LIST[x].bits == format) {
1040 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1041 if (!pref->order[x]) {
1042 pref->order[x] = newindex;
1051 /*! \brief Prepend codec to list */
1052 void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing)
1054 int x, newindex = 0;
1056 /* First step is to get the codecs "index number" */
1057 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1058 if (AST_FORMAT_LIST[x].bits == format) {
1063 /* Done if its unknown */
1067 /* Now find any existing occurrence, or the end */
1068 for (x = 0; x < 32; x++) {
1069 if (!pref->order[x] || pref->order[x] == newindex)
1073 if (only_if_existing && !pref->order[x])
1076 /* Move down to make space to insert - either all the way to the end,
1077 or as far as the existing location (which will be overwritten) */
1078 for (; x > 0; x--) {
1079 pref->order[x] = pref->order[x - 1];
1080 pref->framing[x] = pref->framing[x - 1];
1083 /* And insert the new entry */
1084 pref->order[0] = newindex;
1085 pref->framing[0] = 0; /* ? */
1088 /*! \brief Set packet size for codec */
1089 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
1093 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1094 if (AST_FORMAT_LIST[x].bits == format) {
1103 /* size validation */
1105 framems = AST_FORMAT_LIST[index].def_ms;
1107 if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1108 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1110 if (framems < AST_FORMAT_LIST[index].min_ms)
1111 framems = AST_FORMAT_LIST[index].min_ms;
1113 if (framems > AST_FORMAT_LIST[index].max_ms)
1114 framems = AST_FORMAT_LIST[index].max_ms;
1117 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1118 if (pref->order[x] == (index + 1)) {
1119 pref->framing[x] = framems;
1127 /*! \brief Get packet size for codec */
1128 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
1130 int x, index = -1, framems = 0;
1131 struct ast_format_list fmt = { 0, };
1133 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1134 if (AST_FORMAT_LIST[x].bits == format) {
1135 fmt = AST_FORMAT_LIST[x];
1141 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1142 if (pref->order[x] == (index + 1)) {
1143 framems = pref->framing[x];
1148 /* size validation */
1150 framems = AST_FORMAT_LIST[index].def_ms;
1152 if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1153 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1155 if (framems < AST_FORMAT_LIST[index].min_ms)
1156 framems = AST_FORMAT_LIST[index].min_ms;
1158 if (framems > AST_FORMAT_LIST[index].max_ms)
1159 framems = AST_FORMAT_LIST[index].max_ms;
1161 fmt.cur_ms = framems;
1166 /*! \brief Pick a codec */
1167 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
1169 int x, ret = 0, slot;
1171 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1172 slot = pref->order[x];
1176 if (formats & AST_FORMAT_LIST[slot-1].bits) {
1177 ret = AST_FORMAT_LIST[slot-1].bits;
1181 if (ret & AST_FORMAT_AUDIO_MASK)
1184 ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1186 return find_best ? ast_best_codec(formats) : 0;
1189 int ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
1192 char *parse = NULL, *this = NULL, *psize = NULL;
1193 int format = 0, framems = 0;
1195 parse = ast_strdupa(list);
1196 while ((this = strsep(&parse, ","))) {
1198 if ((psize = strrchr(this, ':'))) {
1200 ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
1201 framems = atoi(psize);
1205 ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
1208 if (!(format = ast_getformatbyname(this))) {
1209 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1221 /* Set up a preference list for audio. Do not include video in preferences
1222 since we can not transcode video and have to use whatever is offered
1224 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1225 if (strcasecmp(this, "all")) {
1227 ast_codec_pref_append(pref, format);
1228 ast_codec_pref_setsize(pref, format, framems);
1231 ast_codec_pref_remove(pref, format);
1232 } else if (!allowing) {
1233 memset(pref, 0, sizeof(*pref));
1240 static int g723_len(unsigned char buf)
1242 enum frame_type type = buf & TYPE_MASK;
1258 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
1263 static int g723_samples(unsigned char *buf, int maxlen)
1268 while(pos < maxlen) {
1269 res = g723_len(buf[pos]);
1278 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1280 int byte = bit / 8; /* byte containing first bit */
1281 int rem = 8 - (bit % 8); /* remaining bits in first byte */
1282 unsigned char ret = 0;
1284 if (n <= 0 || n > 8)
1288 ret = (data[byte] << (n - rem));
1289 ret |= (data[byte + 1] >> (8 - n + rem));
1291 ret = (data[byte] >> (rem - n));
1294 return (ret & (0xff >> (8 - n)));
1297 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1299 static int SpeexWBSubModeSz[] = {
1305 /* skip up to two wideband frames */
1306 if (((len * 8 - off) >= 5) &&
1307 get_n_bits_at(data, 1, off)) {
1308 c = get_n_bits_at(data, 3, off + 1);
1309 off += SpeexWBSubModeSz[c];
1311 if (((len * 8 - off) >= 5) &&
1312 get_n_bits_at(data, 1, off)) {
1313 c = get_n_bits_at(data, 3, off + 1);
1314 off += SpeexWBSubModeSz[c];
1316 if (((len * 8 - off) >= 5) &&
1317 get_n_bits_at(data, 1, off)) {
1318 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1327 static int speex_samples(unsigned char *data, int len)
1329 static int SpeexSubModeSz[] = {
1334 static int SpeexInBandSz[] = {
1344 while ((len * 8 - bit) >= 5) {
1345 /* skip wideband frames */
1346 off = speex_get_wb_sz_at(data, len, bit);
1348 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1353 if ((len * 8 - bit) < 5) {
1354 ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1358 /* get control bits */
1359 c = get_n_bits_at(data, 5, bit);
1365 } else if (c == 14) {
1366 /* in-band signal; next 4 bits contain signal id */
1367 c = get_n_bits_at(data, 4, bit);
1369 bit += SpeexInBandSz[c];
1370 } else if (c == 13) {
1371 /* user in-band; next 5 bits contain msg len */
1372 c = get_n_bits_at(data, 5, bit);
1379 /* skip number bits for submode (less the 5 control bits) */
1380 bit += SpeexSubModeSz[c] - 5;
1381 cnt += 160; /* new frame */
1387 int ast_codec_get_samples(struct ast_frame *f)
1390 switch(f->subclass) {
1391 case AST_FORMAT_SPEEX:
1392 samples = speex_samples(f->data, f->datalen);
1394 case AST_FORMAT_G723_1:
1395 samples = g723_samples(f->data, f->datalen);
1397 case AST_FORMAT_ILBC:
1398 samples = 240 * (f->datalen / 50);
1400 case AST_FORMAT_GSM:
1401 samples = 160 * (f->datalen / 33);
1403 case AST_FORMAT_G729A:
1404 samples = f->datalen * 8;
1406 case AST_FORMAT_SLINEAR:
1407 case AST_FORMAT_SLINEAR16:
1408 samples = f->datalen / 2;
1410 case AST_FORMAT_LPC10:
1411 /* assumes that the RTP packet contains one LPC10 frame */
1413 samples += (((char *)(f->data))[7] & 0x1) * 8;
1415 case AST_FORMAT_ULAW:
1416 case AST_FORMAT_ALAW:
1417 samples = f->datalen;
1419 case AST_FORMAT_G722:
1420 case AST_FORMAT_ADPCM:
1421 case AST_FORMAT_G726:
1422 case AST_FORMAT_G726_AAL2:
1423 samples = f->datalen * 2;
1426 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1431 int ast_codec_get_len(int format, int samples)
1435 /* XXX Still need speex, g723, and lpc10 XXX */
1437 case AST_FORMAT_G723_1:
1438 len = (samples / 240) * 20;
1440 case AST_FORMAT_ILBC:
1441 len = (samples / 240) * 50;
1443 case AST_FORMAT_GSM:
1444 len = (samples / 160) * 33;
1446 case AST_FORMAT_G729A:
1449 case AST_FORMAT_SLINEAR:
1450 case AST_FORMAT_SLINEAR16:
1453 case AST_FORMAT_ULAW:
1454 case AST_FORMAT_ALAW:
1457 case AST_FORMAT_G722:
1458 case AST_FORMAT_ADPCM:
1459 case AST_FORMAT_G726:
1460 case AST_FORMAT_G726_AAL2:
1464 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1470 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1473 short *fdata = f->data;
1474 short adjust_value = abs(adjustment);
1476 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
1482 for (count = 0; count < f->samples; count++) {
1483 if (adjustment > 0) {
1484 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1485 } else if (adjustment < 0) {
1486 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1493 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1496 short *data1, *data2;
1498 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
1501 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
1504 if (f1->samples != f2->samples)
1507 for (count = 0, data1 = f1->data, data2 = f2->data;
1508 count < f1->samples;
1509 count++, data1++, data2++)
1510 ast_slinear_saturated_add(data1, data2);