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 */
91 struct timeval delivery;
92 char data[SMOOTHER_SIZE];
93 char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
94 struct ast_frame *opt;
98 /*! \brief Definition of supported media formats (codecs) */
99 static struct ast_format_list AST_FORMAT_LIST[] = {
100 { AST_FORMAT_G723_1 , "g723", 8000, "G.723.1", 20, 30, 300, 30, 30 }, /*!< G723.1 */
101 { AST_FORMAT_GSM, "gsm", 8000, "GSM", 33, 20, 300, 20, 20 }, /*!< codec_gsm.c */
102 { AST_FORMAT_ULAW, "ulaw", 8000, "G.711 u-law", 80, 10, 150, 10, 20 }, /*!< codec_ulaw.c */
103 { AST_FORMAT_ALAW, "alaw", 8000, "G.711 A-law", 80, 10, 150, 10, 20 }, /*!< codec_alaw.c */
104 { AST_FORMAT_G726, "g726", 8000, "G.726 RFC3551", 40, 10, 300, 10, 20 }, /*!< codec_g726.c */
105 { AST_FORMAT_ADPCM, "adpcm" , 8000, "ADPCM", 40, 10, 300, 10, 20 }, /*!< codec_adpcm.c */
106 { AST_FORMAT_SLINEAR, "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE }, /*!< Signed linear */
107 { AST_FORMAT_LPC10, "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20 }, /*!< codec_lpc10.c */
108 { AST_FORMAT_G729A, "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 }, /*!< Binary commercial distribution */
109 { AST_FORMAT_SPEEX, "speex", 8000, "SpeeX", 10, 10, 60, 10, 20 }, /*!< codec_speex.c */
110 { AST_FORMAT_ILBC, "ilbc", 8000, "iLBC", 50, 30, 30, 30, 30 }, /*!< codec_ilbc.c */ /* inc=30ms - workaround */
111 { AST_FORMAT_G726_AAL2, "g726aal2", 8000, "G.726 AAL2", 40, 10, 300, 10, 20 }, /*!< codec_g726.c */
112 { AST_FORMAT_G722, "g722", 16000, "G722", 80, 10, 150, 10, 20 }, /*!< codec_g722.c */
113 { AST_FORMAT_SLINEAR16, "slin16", 16000, "16 bit Signed Linear PCM (16kHz)", 320, 10, 70, 10, 20 }, /*!< Signed linear (16kHz) */
114 { AST_FORMAT_JPEG, "jpeg", 0, "JPEG image"}, /*!< See format_jpeg.c */
115 { AST_FORMAT_PNG, "png", 0, "PNG image"}, /*!< PNG Image format */
116 { AST_FORMAT_H261, "h261", 0, "H.261 Video" }, /*!< H.261 Video Passthrough */
117 { AST_FORMAT_H263, "h263", 0, "H.263 Video" }, /*!< H.263 Passthrough support, see format_h263.c */
118 { AST_FORMAT_H263_PLUS, "h263p", 0, "H.263+ Video" }, /*!< H.263plus passthrough support See format_h263.c */
119 { AST_FORMAT_H264, "h264", 0, "H.264 Video" }, /*!< Passthrough support, see format_h263.c */
120 { AST_FORMAT_MP4_VIDEO, "mpeg4", 0, "MPEG4 Video" }, /*!< Passthrough support for MPEG4 */
121 { AST_FORMAT_T140, "t140", 0, "Passthrough T.140 Realtime Text" }, /*!< Passthrough support for T.140 Realtime Text */
124 struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
126 void ast_smoother_reset(struct ast_smoother *s, int size)
128 memset(s, 0, sizeof(*s));
132 struct ast_smoother *ast_smoother_new(int size)
134 struct ast_smoother *s;
137 if ((s = ast_malloc(sizeof(*s))))
138 ast_smoother_reset(s, size);
142 int ast_smoother_get_flags(struct ast_smoother *s)
147 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
152 int ast_smoother_test_flag(struct ast_smoother *s, int flag)
154 return (s->flags & flag);
157 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
159 if (f->frametype != AST_FRAME_VOICE) {
160 ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
164 s->format = f->subclass;
165 s->samplesperbyte = (float)f->samples / (float)f->datalen;
166 } else if (s->format != f->subclass) {
167 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
170 if (s->len + f->datalen > SMOOTHER_SIZE) {
171 ast_log(LOG_WARNING, "Out of smoother space\n");
174 if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
175 && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
177 /* Optimize by sending the frame we just got
178 on the next read, thus eliminating the douple
181 ast_swapcopy_samples(f->data, f->data, f->samples);
186 if (s->flags & AST_SMOOTHER_FLAG_G729) {
188 ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
193 ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
195 memcpy(s->data + s->len, f->data, f->datalen);
196 /* If either side is empty, reset the delivery time */
197 if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) /* XXX really ? */
198 s->delivery = f->delivery;
199 s->len += f->datalen;
203 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
205 struct ast_frame *opt;
208 /* IF we have an optimization frame, send it */
210 if (s->opt->offset < AST_FRIENDLY_OFFSET)
211 ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
218 /* Make sure we have enough data */
219 if (s->len < s->size) {
220 /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
221 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
228 s->f.frametype = AST_FRAME_VOICE;
229 s->f.subclass = s->format;
230 s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
231 s->f.offset = AST_FRIENDLY_OFFSET;
233 /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
234 s->f.samples = len * s->samplesperbyte; /* XXX rounding */
235 s->f.delivery = s->delivery;
237 memcpy(s->f.data, s->data, len);
239 /* Move remaining data to the front if applicable */
241 /* In principle this should all be fine because if we are sending
242 G.729 VAD, the next timestamp will take over anyawy */
243 memmove(s->data, s->data + len, s->len);
244 if (!ast_tvzero(s->delivery)) {
245 /* If we have delivery time, increment it, otherwise, leave it at 0 */
246 s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
253 void ast_smoother_free(struct ast_smoother *s)
258 static struct ast_frame *ast_frame_header_new(void)
262 #if !defined(LOW_MEMORY)
263 struct ast_frame_cache *frames;
265 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
266 if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
267 size_t mallocd_len = f->mallocd_hdr_len;
268 memset(f, 0, sizeof(*f));
269 f->mallocd_hdr_len = mallocd_len;
270 f->mallocd = AST_MALLOCD_HDR;
275 if (!(f = ast_calloc_cache(1, sizeof(*f))))
278 if (!(f = ast_calloc(1, sizeof(*f))))
282 f->mallocd_hdr_len = sizeof(*f);
284 AST_LIST_LOCK(&headerlist);
286 AST_LIST_INSERT_HEAD(&headerlist, f, frame_list);
287 AST_LIST_UNLOCK(&headerlist);
293 #if !defined(LOW_MEMORY)
294 static void frame_cache_cleanup(void *data)
296 struct ast_frame_cache *frames = data;
299 while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
306 void ast_frame_free(struct ast_frame *fr, int cache)
308 if (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR))
309 ast_translate_frame_freed(fr);
314 #if !defined(LOW_MEMORY)
315 if (cache && fr->mallocd == AST_MALLOCD_HDR) {
316 /* Cool, only the header is malloc'd, let's just cache those for now
317 * to keep things simple... */
318 struct ast_frame_cache *frames;
320 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))
321 && frames->size < FRAME_CACHE_MAX_SIZE) {
322 AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
329 if (fr->mallocd & AST_MALLOCD_DATA) {
331 ast_free(fr->data - fr->offset);
333 if (fr->mallocd & AST_MALLOCD_SRC) {
335 ast_free((char *)fr->src);
337 if (fr->mallocd & AST_MALLOCD_HDR) {
339 AST_LIST_LOCK(&headerlist);
341 AST_LIST_REMOVE(&headerlist, fr, frame_list);
342 AST_LIST_UNLOCK(&headerlist);
349 * \brief 'isolates' a frame by duplicating non-malloc'ed components
350 * (header, src, data).
351 * On return all components are malloc'ed
353 struct ast_frame *ast_frisolate(struct ast_frame *fr)
355 struct ast_frame *out;
358 ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
360 if (!(fr->mallocd & AST_MALLOCD_HDR)) {
361 /* Allocate a new header if needed */
362 if (!(out = ast_frame_header_new()))
364 out->frametype = fr->frametype;
365 out->subclass = fr->subclass;
366 out->datalen = fr->datalen;
367 out->samples = fr->samples;
368 out->offset = fr->offset;
369 out->data = fr->data;
370 /* Copy the timing data */
371 ast_copy_flags(out, fr, AST_FRFLAG_HAS_TIMING_INFO);
372 if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
375 out->seqno = fr->seqno;
380 if (!(fr->mallocd & AST_MALLOCD_SRC)) {
382 if (!(out->src = ast_strdup(fr->src))) {
391 if (!(fr->mallocd & AST_MALLOCD_DATA)) {
392 if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
393 if (out->src != fr->src)
394 ast_free((void *) out->src);
399 newdata += AST_FRIENDLY_OFFSET;
400 out->offset = AST_FRIENDLY_OFFSET;
401 out->datalen = fr->datalen;
402 memcpy(newdata, fr->data, fr->datalen);
406 out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
411 struct ast_frame *ast_frdup(const struct ast_frame *f)
413 struct ast_frame *out = NULL;
417 #if !defined(LOW_MEMORY)
418 struct ast_frame_cache *frames;
421 /* Start with standard stuff */
422 len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
423 /* If we have a source, add space for it */
425 * XXX Watch out here - if we receive a src which is not terminated
426 * properly, we can be easily attacked. Should limit the size we deal with.
429 srclen = strlen(f->src);
433 #if !defined(LOW_MEMORY)
434 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
435 AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
436 if (out->mallocd_hdr_len >= len) {
437 size_t mallocd_len = out->mallocd_hdr_len;
439 AST_LIST_REMOVE_CURRENT(frame_list);
440 memset(out, 0, sizeof(*out));
441 out->mallocd_hdr_len = mallocd_len;
447 AST_LIST_TRAVERSE_SAFE_END;
452 if (!(buf = ast_calloc_cache(1, len)))
455 out->mallocd_hdr_len = len;
458 out->frametype = f->frametype;
459 out->subclass = f->subclass;
460 out->datalen = f->datalen;
461 out->samples = f->samples;
462 out->delivery = f->delivery;
463 /* Set us as having malloc'd header only, so it will eventually
465 out->mallocd = AST_MALLOCD_HDR;
466 out->offset = AST_FRIENDLY_OFFSET;
468 out->data = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
469 memcpy(out->data, f->data, out->datalen);
472 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
473 /* Must have space since we allocated for it */
474 strcpy((char *)out->src, f->src);
476 ast_copy_flags(out, f, AST_FRFLAG_HAS_TIMING_INFO);
479 out->seqno = f->seqno;
483 void ast_swapcopy_samples(void *dst, const void *src, int samples)
486 unsigned short *dst_s = dst;
487 const unsigned short *src_s = src;
489 for (i = 0; i < samples; i++)
490 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
494 struct ast_format_list *ast_get_format_list_index(int index)
496 return &AST_FORMAT_LIST[index];
499 struct ast_format_list *ast_get_format_list(size_t *size)
501 *size = (sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]));
502 return AST_FORMAT_LIST;
505 char* ast_getformatname(int format)
508 char *ret = "unknown";
509 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
510 if (AST_FORMAT_LIST[x].bits == format) {
511 ret = AST_FORMAT_LIST[x].name;
518 char *ast_getformatname_multiple(char *buf, size_t size, int format)
522 char *start, *end = buf;
526 snprintf(end, size, "0x%x (", format);
531 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
532 if (AST_FORMAT_LIST[x].bits & format) {
533 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
540 ast_copy_string(start, "nothing)", size);
546 static struct ast_codec_alias_table {
549 } ast_codec_alias_table[] = {
550 { "slinear", "slin"},
551 { "slinear16", "slin16"},
555 static const char *ast_expand_codec_alias(const char *in)
559 for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(ast_codec_alias_table[0]); x++) {
560 if (!strcmp(in,ast_codec_alias_table[x].alias))
561 return ast_codec_alias_table[x].realname;
566 int ast_getformatbyname(const char *name)
568 int x, all, format = 0;
570 all = strcasecmp(name, "all") ? 0 : 1;
571 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
573 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
574 !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name))) {
575 format |= AST_FORMAT_LIST[x].bits;
584 char *ast_codec2str(int codec)
587 char *ret = "unknown";
588 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
589 if (AST_FORMAT_LIST[x].bits == codec) {
590 ret = AST_FORMAT_LIST[x].desc;
597 static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
604 e->command = "core show codecs [audio|video|image]";
606 "Usage: core show codecs [audio|video|image]\n"
607 " Displays codec mapping\n";
613 if ((a->argc < 3) || (a->argc > 4))
614 return CLI_SHOWUSAGE;
616 if (!ast_opt_dont_warn)
617 ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
618 "\tIt does not indicate anything about your configuration.\n");
620 ast_cli(a->fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
621 ast_cli(a->fd, "--------------------------------------------------------------------------------\n");
622 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"audio"))) {
625 snprintf(hex,25,"(0x%x)",1<<i);
626 ast_cli(a->fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
630 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"image"))) {
632 for (i=16;i<18;i++) {
633 snprintf(hex,25,"(0x%x)",1<<i);
634 ast_cli(a->fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
638 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"video"))) {
640 for (i=18;i<22;i++) {
641 snprintf(hex,25,"(0x%x)",1<<i);
642 ast_cli(a->fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
647 return CLI_SHOWUSAGE;
652 static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
654 int codec, i, found=0;
658 e->command = "core show codec";
660 "Usage: core show codec <number>\n"
661 " Displays codec mapping\n";
668 return CLI_SHOWUSAGE;
670 if (sscanf(a->argv[3],"%d",&codec) != 1)
671 return CLI_SHOWUSAGE;
673 for (i = 0; i < 32; i++)
674 if (codec & (1 << i)) {
676 ast_cli(a->fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
680 ast_cli(a->fd, "Codec %d not found\n", codec);
685 /*! Dump a frame for debugging purposes */
686 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
688 const char noname[] = "unknown";
689 char ftype[40] = "Unknown Frametype";
691 char subclass[40] = "Unknown Subclass";
693 char moreinfo[40] = "";
697 const char *message = "Unknown";
704 ast_verbose("%s [ %s (NULL) ] [%s]\n",
705 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
706 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
707 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
710 /* XXX We should probably print one each of voice and video when the format changes XXX */
711 if (f->frametype == AST_FRAME_VOICE)
713 if (f->frametype == AST_FRAME_VIDEO)
715 switch(f->frametype) {
716 case AST_FRAME_DTMF_BEGIN:
717 strcpy(ftype, "DTMF Begin");
718 subclass[0] = f->subclass;
721 case AST_FRAME_DTMF_END:
722 strcpy(ftype, "DTMF End");
723 subclass[0] = f->subclass;
726 case AST_FRAME_CONTROL:
727 strcpy(ftype, "Control");
728 switch(f->subclass) {
729 case AST_CONTROL_HANGUP:
730 strcpy(subclass, "Hangup");
732 case AST_CONTROL_RING:
733 strcpy(subclass, "Ring");
735 case AST_CONTROL_RINGING:
736 strcpy(subclass, "Ringing");
738 case AST_CONTROL_ANSWER:
739 strcpy(subclass, "Answer");
741 case AST_CONTROL_BUSY:
742 strcpy(subclass, "Busy");
744 case AST_CONTROL_TAKEOFFHOOK:
745 strcpy(subclass, "Take Off Hook");
747 case AST_CONTROL_OFFHOOK:
748 strcpy(subclass, "Line Off Hook");
750 case AST_CONTROL_CONGESTION:
751 strcpy(subclass, "Congestion");
753 case AST_CONTROL_FLASH:
754 strcpy(subclass, "Flash");
756 case AST_CONTROL_WINK:
757 strcpy(subclass, "Wink");
759 case AST_CONTROL_OPTION:
760 strcpy(subclass, "Option");
762 case AST_CONTROL_RADIO_KEY:
763 strcpy(subclass, "Key Radio");
765 case AST_CONTROL_RADIO_UNKEY:
766 strcpy(subclass, "Unkey Radio");
768 case AST_CONTROL_HOLD:
769 strcpy(subclass, "Hold");
771 case AST_CONTROL_UNHOLD:
772 strcpy(subclass, "Unhold");
774 case AST_CONTROL_T38:
775 if (f->datalen != sizeof(enum ast_control_t38)) {
778 enum ast_control_t38 state = *((enum ast_control_t38 *) f->data);
779 if (state == AST_T38_REQUEST_NEGOTIATE)
780 message = "Negotiation Requested";
781 else if (state == AST_T38_REQUEST_TERMINATE)
782 message = "Negotiation Request Terminated";
783 else if (state == AST_T38_NEGOTIATED)
784 message = "Negotiated";
785 else if (state == AST_T38_TERMINATED)
786 message = "Terminated";
787 else if (state == AST_T38_REFUSED)
790 snprintf(subclass, sizeof(subclass), "T38/%s", message);
793 strcpy(subclass, "Stop generators");
796 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
800 strcpy(ftype, "Null Frame");
801 strcpy(subclass, "N/A");
804 /* Should never happen */
805 strcpy(ftype, "IAX Specific");
806 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
809 strcpy(ftype, "Text");
810 strcpy(subclass, "N/A");
811 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
813 case AST_FRAME_IMAGE:
814 strcpy(ftype, "Image");
815 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
818 strcpy(ftype, "HTML");
819 switch(f->subclass) {
821 strcpy(subclass, "URL");
822 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
825 strcpy(subclass, "Data");
828 strcpy(subclass, "Begin");
831 strcpy(subclass, "End");
833 case AST_HTML_LDCOMPLETE:
834 strcpy(subclass, "Load Complete");
836 case AST_HTML_NOSUPPORT:
837 strcpy(subclass, "No Support");
839 case AST_HTML_LINKURL:
840 strcpy(subclass, "Link URL");
841 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
843 case AST_HTML_UNLINK:
844 strcpy(subclass, "Unlink");
846 case AST_HTML_LINKREJECT:
847 strcpy(subclass, "Link Reject");
850 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
854 case AST_FRAME_MODEM:
855 strcpy(ftype, "Modem");
856 switch (f->subclass) {
858 strcpy(subclass, "T.38");
861 strcpy(subclass, "V.150");
864 snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
869 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
871 if (!ast_strlen_zero(moreinfo))
872 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%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(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
879 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
881 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
882 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
883 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
885 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
887 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
892 static char *show_frame_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
899 e->command = "core show frame stats";
901 "Usage: core show frame stats\n"
902 " Displays debugging statistics from framer\n";
909 return CLI_SHOWUSAGE;
910 AST_LIST_LOCK(&headerlist);
911 ast_cli(a->fd, " Framer Statistics \n");
912 ast_cli(a->fd, "---------------------------\n");
913 ast_cli(a->fd, "Total allocated headers: %d\n", headers);
914 ast_cli(a->fd, "Queue Dump:\n");
915 AST_LIST_TRAVERSE(&headerlist, f, frame_list)
916 ast_cli(a->fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
917 AST_LIST_UNLOCK(&headerlist);
922 /* Builtin Asterisk CLI-commands for debugging */
923 static struct ast_cli_entry my_clis[] = {
924 AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
925 AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
927 AST_CLI_DEFINE(show_frame_stats, "Shows frame statistics"),
931 int init_framer(void)
933 ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
937 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
939 int x, differential = (int) 'A', mem;
953 for (x = 0; x < 32 ; x++) {
956 to[x] = right ? (from[x] + differential) : (from[x] - differential);
960 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
963 size_t total_len, slen;
970 for(x = 0; x < 32 ; x++) {
973 if (!(codec = ast_codec_pref_index(pref,x)))
975 if ((formatname = ast_getformatname(codec))) {
976 slen = strlen(formatname);
977 if (slen > total_len)
979 strncat(buf, formatname, total_len - 1); /* safe */
982 if (total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
983 strncat(buf, "|", total_len - 1); /* safe */
988 strncat(buf, ")", total_len - 1); /* safe */
992 return size - total_len;
995 int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
1000 if ((index >= 0) && (index < sizeof(pref->order))) {
1001 slot = pref->order[index];
1004 return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
1007 /*! \brief Remove codec from pref list */
1008 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
1010 struct ast_codec_pref oldorder;
1015 if (!pref->order[0])
1018 memcpy(&oldorder, pref, sizeof(oldorder));
1019 memset(pref, 0, sizeof(*pref));
1021 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1022 slot = oldorder.order[x];
1023 size = oldorder.framing[x];
1026 if (AST_FORMAT_LIST[slot-1].bits != format) {
1027 pref->order[y] = slot;
1028 pref->framing[y++] = size;
1034 /*! \brief Append codec to list */
1035 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
1037 int x, newindex = 0;
1039 ast_codec_pref_remove(pref, format);
1041 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1042 if (AST_FORMAT_LIST[x].bits == format) {
1049 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1050 if (!pref->order[x]) {
1051 pref->order[x] = newindex;
1060 /*! \brief Prepend codec to list */
1061 void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing)
1063 int x, newindex = 0;
1065 /* First step is to get the codecs "index number" */
1066 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1067 if (AST_FORMAT_LIST[x].bits == format) {
1072 /* Done if its unknown */
1076 /* Now find any existing occurrence, or the end */
1077 for (x = 0; x < 32; x++) {
1078 if (!pref->order[x] || pref->order[x] == newindex)
1082 if (only_if_existing && !pref->order[x])
1085 /* Move down to make space to insert - either all the way to the end,
1086 or as far as the existing location (which will be overwritten) */
1087 for (; x > 0; x--) {
1088 pref->order[x] = pref->order[x - 1];
1089 pref->framing[x] = pref->framing[x - 1];
1092 /* And insert the new entry */
1093 pref->order[0] = newindex;
1094 pref->framing[0] = 0; /* ? */
1097 /*! \brief Set packet size for codec */
1098 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
1102 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1103 if (AST_FORMAT_LIST[x].bits == format) {
1112 /* size validation */
1114 framems = AST_FORMAT_LIST[index].def_ms;
1116 if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1117 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1119 if (framems < AST_FORMAT_LIST[index].min_ms)
1120 framems = AST_FORMAT_LIST[index].min_ms;
1122 if (framems > AST_FORMAT_LIST[index].max_ms)
1123 framems = AST_FORMAT_LIST[index].max_ms;
1126 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1127 if (pref->order[x] == (index + 1)) {
1128 pref->framing[x] = framems;
1136 /*! \brief Get packet size for codec */
1137 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
1139 int x, index = -1, framems = 0;
1140 struct ast_format_list fmt = { 0, };
1142 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1143 if (AST_FORMAT_LIST[x].bits == format) {
1144 fmt = AST_FORMAT_LIST[x];
1150 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1151 if (pref->order[x] == (index + 1)) {
1152 framems = pref->framing[x];
1157 /* size validation */
1159 framems = AST_FORMAT_LIST[index].def_ms;
1161 if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
1162 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
1164 if (framems < AST_FORMAT_LIST[index].min_ms)
1165 framems = AST_FORMAT_LIST[index].min_ms;
1167 if (framems > AST_FORMAT_LIST[index].max_ms)
1168 framems = AST_FORMAT_LIST[index].max_ms;
1170 fmt.cur_ms = framems;
1175 /*! \brief Pick a codec */
1176 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
1178 int x, ret = 0, slot;
1180 for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
1181 slot = pref->order[x];
1185 if (formats & AST_FORMAT_LIST[slot-1].bits) {
1186 ret = AST_FORMAT_LIST[slot-1].bits;
1190 if (ret & AST_FORMAT_AUDIO_MASK)
1193 ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1195 return find_best ? ast_best_codec(formats) : 0;
1198 int ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
1201 char *parse = NULL, *this = NULL, *psize = NULL;
1202 int format = 0, framems = 0;
1204 parse = ast_strdupa(list);
1205 while ((this = strsep(&parse, ","))) {
1207 if ((psize = strrchr(this, ':'))) {
1209 ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
1210 framems = atoi(psize);
1214 ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
1217 if (!(format = ast_getformatbyname(this))) {
1218 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1230 /* Set up a preference list for audio. Do not include video in preferences
1231 since we can not transcode video and have to use whatever is offered
1233 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1234 if (strcasecmp(this, "all")) {
1236 ast_codec_pref_append(pref, format);
1237 ast_codec_pref_setsize(pref, format, framems);
1240 ast_codec_pref_remove(pref, format);
1241 } else if (!allowing) {
1242 memset(pref, 0, sizeof(*pref));
1249 static int g723_len(unsigned char buf)
1251 enum frame_type type = buf & TYPE_MASK;
1267 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
1272 static int g723_samples(unsigned char *buf, int maxlen)
1277 while(pos < maxlen) {
1278 res = g723_len(buf[pos]);
1287 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1289 int byte = bit / 8; /* byte containing first bit */
1290 int rem = 8 - (bit % 8); /* remaining bits in first byte */
1291 unsigned char ret = 0;
1293 if (n <= 0 || n > 8)
1297 ret = (data[byte] << (n - rem));
1298 ret |= (data[byte + 1] >> (8 - n + rem));
1300 ret = (data[byte] >> (rem - n));
1303 return (ret & (0xff >> (8 - n)));
1306 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1308 static int SpeexWBSubModeSz[] = {
1314 /* skip up to two wideband frames */
1315 if (((len * 8 - off) >= 5) &&
1316 get_n_bits_at(data, 1, off)) {
1317 c = get_n_bits_at(data, 3, off + 1);
1318 off += SpeexWBSubModeSz[c];
1320 if (((len * 8 - off) >= 5) &&
1321 get_n_bits_at(data, 1, off)) {
1322 c = get_n_bits_at(data, 3, off + 1);
1323 off += SpeexWBSubModeSz[c];
1325 if (((len * 8 - off) >= 5) &&
1326 get_n_bits_at(data, 1, off)) {
1327 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1336 static int speex_samples(unsigned char *data, int len)
1338 static int SpeexSubModeSz[] = {
1343 static int SpeexInBandSz[] = {
1353 while ((len * 8 - bit) >= 5) {
1354 /* skip wideband frames */
1355 off = speex_get_wb_sz_at(data, len, bit);
1357 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1362 if ((len * 8 - bit) < 5) {
1363 ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
1367 /* get control bits */
1368 c = get_n_bits_at(data, 5, bit);
1374 } else if (c == 14) {
1375 /* in-band signal; next 4 bits contain signal id */
1376 c = get_n_bits_at(data, 4, bit);
1378 bit += SpeexInBandSz[c];
1379 } else if (c == 13) {
1380 /* user in-band; next 5 bits contain msg len */
1381 c = get_n_bits_at(data, 5, bit);
1388 /* skip number bits for submode (less the 5 control bits) */
1389 bit += SpeexSubModeSz[c] - 5;
1390 cnt += 160; /* new frame */
1396 int ast_codec_get_samples(struct ast_frame *f)
1399 switch(f->subclass) {
1400 case AST_FORMAT_SPEEX:
1401 samples = speex_samples(f->data, f->datalen);
1403 case AST_FORMAT_G723_1:
1404 samples = g723_samples(f->data, f->datalen);
1406 case AST_FORMAT_ILBC:
1407 samples = 240 * (f->datalen / 50);
1409 case AST_FORMAT_GSM:
1410 samples = 160 * (f->datalen / 33);
1412 case AST_FORMAT_G729A:
1413 samples = f->datalen * 8;
1415 case AST_FORMAT_SLINEAR:
1416 case AST_FORMAT_SLINEAR16:
1417 samples = f->datalen / 2;
1419 case AST_FORMAT_LPC10:
1420 /* assumes that the RTP packet contains one LPC10 frame */
1422 samples += (((char *)(f->data))[7] & 0x1) * 8;
1424 case AST_FORMAT_ULAW:
1425 case AST_FORMAT_ALAW:
1426 samples = f->datalen;
1428 case AST_FORMAT_G722:
1429 case AST_FORMAT_ADPCM:
1430 case AST_FORMAT_G726:
1431 case AST_FORMAT_G726_AAL2:
1432 samples = f->datalen * 2;
1435 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
1440 int ast_codec_get_len(int format, int samples)
1444 /* XXX Still need speex, g723, and lpc10 XXX */
1446 case AST_FORMAT_G723_1:
1447 len = (samples / 240) * 20;
1449 case AST_FORMAT_ILBC:
1450 len = (samples / 240) * 50;
1452 case AST_FORMAT_GSM:
1453 len = (samples / 160) * 33;
1455 case AST_FORMAT_G729A:
1458 case AST_FORMAT_SLINEAR:
1459 case AST_FORMAT_SLINEAR16:
1462 case AST_FORMAT_ULAW:
1463 case AST_FORMAT_ALAW:
1466 case AST_FORMAT_G722:
1467 case AST_FORMAT_ADPCM:
1468 case AST_FORMAT_G726:
1469 case AST_FORMAT_G726_AAL2:
1473 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1479 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1482 short *fdata = f->data;
1483 short adjust_value = abs(adjustment);
1485 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
1491 for (count = 0; count < f->samples; count++) {
1492 if (adjustment > 0) {
1493 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1494 } else if (adjustment < 0) {
1495 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1502 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1505 short *data1, *data2;
1507 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
1510 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
1513 if (f1->samples != f2->samples)
1516 for (count = 0, data1 = f1->data, data2 = f2->data;
1517 count < f1->samples;
1518 count++, data1++, data2++)
1519 ast_slinear_saturated_add(data1, data2);