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$")
36 #include "asterisk/lock.h"
37 #include "asterisk/frame.h"
38 #include "asterisk/logger.h"
39 #include "asterisk/options.h"
40 #include "asterisk/channel.h"
41 #include "asterisk/cli.h"
42 #include "asterisk/term.h"
43 #include "asterisk/utils.h"
44 #include "asterisk/threadstorage.h"
45 #include "asterisk/linkedlists.h"
46 #include "asterisk/translate.h"
50 static AST_LIST_HEAD_STATIC(headerlist
, ast_frame
);
53 #if !defined(LOW_MEMORY)
54 static void frame_cache_cleanup(void *data
);
56 /*! \brief A per-thread cache of frame headers */
57 AST_THREADSTORAGE_CUSTOM(frame_cache
, frame_cache_init
, frame_cache_cleanup
);
60 * \brief Maximum ast_frame cache size
62 * In most cases where the frame header cache will be useful, the size
63 * of the cache will stay very small. However, it is not always the case that
64 * the same thread that allocates the frame will be the one freeing them, so
65 * sometimes a thread will never have any frames in its cache, or the cache
66 * will never be pulled from. For the latter case, we limit the maximum size.
68 #define FRAME_CACHE_MAX_SIZE 10
70 /*! \brief This is just so ast_frames, a list head struct for holding a list of
71 * ast_frame structures, is defined. */
72 AST_LIST_HEAD_NOLOCK(ast_frames
, ast_frame
);
74 struct ast_frame_cache
{
75 struct ast_frames list
;
80 #define SMOOTHER_SIZE 8000
85 TYPE_SILENCE
, /* 0x2 */
86 TYPE_DONTSEND
/* 0x3 */
95 int optimizablestream
;
99 struct timeval delivery
;
100 char data
[SMOOTHER_SIZE
];
101 char framedata
[SMOOTHER_SIZE
+ AST_FRIENDLY_OFFSET
];
102 struct ast_frame
*opt
;
106 /*! \brief Definition of supported media formats (codecs) */
107 static struct ast_format_list AST_FORMAT_LIST
[] = { /*!< Bit number: comment - Bit numbers are hard coded in show_codec() */
108 { 1, AST_FORMAT_G723_1
, "g723" , "G.723.1", 24, 30, 300, 30, 30 }, /*!< 1 */
109 { 1, AST_FORMAT_GSM
, "gsm" , "GSM", 33, 20, 300, 20, 20 }, /*!< 2: codec_gsm.c */
110 { 1, AST_FORMAT_ULAW
, "ulaw", "G.711 u-law", 80, 10, 150, 10, 20 }, /*!< 3: codec_ulaw.c */
111 { 1, AST_FORMAT_ALAW
, "alaw", "G.711 A-law", 80, 10, 150, 10, 20 }, /*!< 4: codec_alaw.c */
112 { 1, AST_FORMAT_G726
, "g726", "G.726 RFC3551", 40, 10, 300, 10, 20 }, /*!< 5: codec_g726.c */
113 { 1, AST_FORMAT_ADPCM
, "adpcm" , "ADPCM", 40, 10, 300, 10, 20 }, /*!< 6: codec_adpcm.c */
114 { 1, AST_FORMAT_SLINEAR
, "slin", "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE
}, /*!< 7 */
115 { 1, AST_FORMAT_LPC10
, "lpc10", "LPC10", 7, 20, 20, 20, 20 }, /*!< 8: codec_lpc10.c */
116 { 1, AST_FORMAT_G729A
, "g729", "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729
}, /*!< 9: Binary commercial distribution */
117 { 1, AST_FORMAT_SPEEX
, "speex", "SpeeX", 10, 10, 60, 10, 20 }, /*!< 10: codec_speex.c */
118 { 1, AST_FORMAT_ILBC
, "ilbc", "iLBC", 50, 30, 30, 30, 30 }, /*!< 11: codec_ilbc.c */ /* inc=30ms - workaround */
119 { 1, AST_FORMAT_G726_AAL2
, "g726aal2", "G.726 AAL2", 40, 10, 300, 10, 20 }, /*!< 12: codec_g726.c */
120 { 1, AST_FORMAT_G722
, "g722", "G722"}, /*!< 13 */
121 { 0, 0, "nothing", "undefined" },
122 { 0, 0, "nothing", "undefined" },
123 { 0, 0, "nothing", "undefined" },
124 { 0, 0, "nothing", "undefined" },
125 { 0, AST_FORMAT_MAX_AUDIO
, "maxaudio", "Maximum audio format" },
126 { 1, AST_FORMAT_JPEG
, "jpeg", "JPEG image"}, /*!< 17: See format_jpeg.c */
127 { 1, AST_FORMAT_PNG
, "png", "PNG image"}, /*!< 18: Image format */
128 { 1, AST_FORMAT_H261
, "h261", "H.261 Video" }, /*!< 19: Video Passthrough */
129 { 1, AST_FORMAT_H263
, "h263", "H.263 Video" }, /*!< 20: Passthrough support, see format_h263.c */
130 { 1, AST_FORMAT_H263_PLUS
, "h263p", "H.263+ Video" }, /*!< 21: See format_h263.c */
131 { 1, AST_FORMAT_H264
, "h264", "H.264 Video" }, /*!< 22: Passthrough support, see format_h263.c */
132 { 0, 0, "nothing", "undefined" },
133 { 0, 0, "nothing", "undefined" },
134 { 0, 0, "nothing", "undefined" },
135 { 0, AST_FORMAT_MAX_VIDEO
, "maxvideo", "Maximum video format" },
138 struct ast_frame ast_null_frame
= { AST_FRAME_NULL
, };
140 void ast_smoother_reset(struct ast_smoother
*s
, int size
)
142 memset(s
, 0, sizeof(*s
));
146 struct ast_smoother
*ast_smoother_new(int size
)
148 struct ast_smoother
*s
;
151 if ((s
= ast_malloc(sizeof(*s
))))
152 ast_smoother_reset(s
, size
);
156 int ast_smoother_get_flags(struct ast_smoother
*s
)
161 void ast_smoother_set_flags(struct ast_smoother
*s
, int flags
)
166 int ast_smoother_test_flag(struct ast_smoother
*s
, int flag
)
168 return (s
->flags
& flag
);
171 int __ast_smoother_feed(struct ast_smoother
*s
, struct ast_frame
*f
, int swap
)
173 if (f
->frametype
!= AST_FRAME_VOICE
) {
174 ast_log(LOG_WARNING
, "Huh? Can't smooth a non-voice frame!\n");
178 s
->format
= f
->subclass
;
179 s
->samplesperbyte
= (float)f
->samples
/ (float)f
->datalen
;
180 } else if (s
->format
!= f
->subclass
) {
181 ast_log(LOG_WARNING
, "Smoother was working on %d format frames, now trying to feed %d?\n", s
->format
, f
->subclass
);
184 if (s
->len
+ f
->datalen
> SMOOTHER_SIZE
) {
185 ast_log(LOG_WARNING
, "Out of smoother space\n");
188 if (((f
->datalen
== s
->size
) || ((f
->datalen
< 10) && (s
->flags
& AST_SMOOTHER_FLAG_G729
)))
189 && !s
->opt
&& (f
->offset
>= AST_MIN_OFFSET
)) {
191 /* Optimize by sending the frame we just got
192 on the next read, thus eliminating the douple
195 ast_swapcopy_samples(f
->data
, f
->data
, f
->samples
);
199 s
->optimizablestream
++;
200 if (s
->optimizablestream
> 10) {
201 /* For the past 10 rounds, we have input and output
202 frames of the correct size for this smoother, yet
203 we were unable to optimize because there was still
204 some cruft left over. Lets just drop the cruft so
205 we can move to a fully optimized path */
207 ast_swapcopy_samples(f
->data
, f
->data
, f
->samples
);
214 s
->optimizablestream
= 0;
215 if (s
->flags
& AST_SMOOTHER_FLAG_G729
) {
217 ast_log(LOG_NOTICE
, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
222 ast_swapcopy_samples(s
->data
+s
->len
, f
->data
, f
->samples
);
224 memcpy(s
->data
+ s
->len
, f
->data
, f
->datalen
);
225 /* If either side is empty, reset the delivery time */
226 if (!s
->len
|| ast_tvzero(f
->delivery
) || ast_tvzero(s
->delivery
)) /* XXX really ? */
227 s
->delivery
= f
->delivery
;
228 s
->len
+= f
->datalen
;
232 struct ast_frame
*ast_smoother_read(struct ast_smoother
*s
)
234 struct ast_frame
*opt
;
237 /* IF we have an optimization frame, send it */
239 if (s
->opt
->offset
< AST_FRIENDLY_OFFSET
)
240 ast_log(LOG_WARNING
, "Returning a frame of inappropriate offset (%d).\n",
247 /* Make sure we have enough data */
248 if (s
->len
< s
->size
) {
249 /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
250 if (!((s
->flags
& AST_SMOOTHER_FLAG_G729
) && (s
->size
% 10)))
257 s
->f
.frametype
= AST_FRAME_VOICE
;
258 s
->f
.subclass
= s
->format
;
259 s
->f
.data
= s
->framedata
+ AST_FRIENDLY_OFFSET
;
260 s
->f
.offset
= AST_FRIENDLY_OFFSET
;
262 /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
263 s
->f
.samples
= len
* s
->samplesperbyte
; /* XXX rounding */
264 s
->f
.delivery
= s
->delivery
;
266 memcpy(s
->f
.data
, s
->data
, len
);
268 /* Move remaining data to the front if applicable */
270 /* In principle this should all be fine because if we are sending
271 G.729 VAD, the next timestamp will take over anyawy */
272 memmove(s
->data
, s
->data
+ len
, s
->len
);
273 if (!ast_tvzero(s
->delivery
)) {
274 /* If we have delivery time, increment it, otherwise, leave it at 0 */
275 s
->delivery
= ast_tvadd(s
->delivery
, ast_samp2tv(s
->f
.samples
, 8000));
282 void ast_smoother_free(struct ast_smoother
*s
)
287 static struct ast_frame
*ast_frame_header_new(void)
291 #if !defined(LOW_MEMORY)
292 struct ast_frame_cache
*frames
;
294 if ((frames
= ast_threadstorage_get(&frame_cache
, sizeof(*frames
)))) {
295 if ((f
= AST_LIST_REMOVE_HEAD(&frames
->list
, frame_list
))) {
296 size_t mallocd_len
= f
->mallocd_hdr_len
;
297 memset(f
, 0, sizeof(*f
));
298 f
->mallocd_hdr_len
= mallocd_len
;
299 f
->mallocd
= AST_MALLOCD_HDR
;
304 if (!(f
= ast_calloc_cache(1, sizeof(*f
))))
307 if (!(f
= ast_calloc(1, sizeof(*f
))))
311 f
->mallocd_hdr_len
= sizeof(*f
);
313 AST_LIST_LOCK(&headerlist
);
315 AST_LIST_INSERT_HEAD(&headerlist
, f
, frame_list
);
316 AST_LIST_UNLOCK(&headerlist
);
322 #if !defined(LOW_MEMORY)
323 static void frame_cache_cleanup(void *data
)
325 struct ast_frame_cache
*frames
= data
;
328 while ((f
= AST_LIST_REMOVE_HEAD(&frames
->list
, frame_list
)))
335 void ast_frame_free(struct ast_frame
*fr
, int cache
)
337 if (ast_test_flag(fr
, AST_FRFLAG_FROM_TRANSLATOR
))
338 ast_translate_frame_freed(fr
);
343 #if !defined(LOW_MEMORY)
344 if (cache
&& fr
->mallocd
== AST_MALLOCD_HDR
) {
345 /* Cool, only the header is malloc'd, let's just cache those for now
346 * to keep things simple... */
347 struct ast_frame_cache
*frames
;
349 if ((frames
= ast_threadstorage_get(&frame_cache
, sizeof(*frames
)))
350 && frames
->size
< FRAME_CACHE_MAX_SIZE
) {
351 AST_LIST_INSERT_HEAD(&frames
->list
, fr
, frame_list
);
358 if (fr
->mallocd
& AST_MALLOCD_DATA
) {
360 free(fr
->data
- fr
->offset
);
362 if (fr
->mallocd
& AST_MALLOCD_SRC
) {
364 free((char *)fr
->src
);
366 if (fr
->mallocd
& AST_MALLOCD_HDR
) {
368 AST_LIST_LOCK(&headerlist
);
370 AST_LIST_REMOVE(&headerlist
, fr
, frame_list
);
371 AST_LIST_UNLOCK(&headerlist
);
378 * \brief 'isolates' a frame by duplicating non-malloc'ed components
379 * (header, src, data).
380 * On return all components are malloc'ed
382 struct ast_frame
*ast_frisolate(struct ast_frame
*fr
)
384 struct ast_frame
*out
;
387 ast_clear_flag(fr
, AST_FRFLAG_FROM_TRANSLATOR
);
389 if (!(fr
->mallocd
& AST_MALLOCD_HDR
)) {
390 /* Allocate a new header if needed */
391 if (!(out
= ast_frame_header_new()))
393 out
->frametype
= fr
->frametype
;
394 out
->subclass
= fr
->subclass
;
395 out
->datalen
= fr
->datalen
;
396 out
->samples
= fr
->samples
;
397 out
->offset
= fr
->offset
;
398 out
->data
= fr
->data
;
399 /* Copy the timing data */
400 ast_copy_flags(out
, fr
, AST_FRFLAG_HAS_TIMING_INFO
);
401 if (ast_test_flag(fr
, AST_FRFLAG_HAS_TIMING_INFO
)) {
404 out
->seqno
= fr
->seqno
;
409 if (!(fr
->mallocd
& AST_MALLOCD_SRC
)) {
411 if (!(out
->src
= ast_strdup(fr
->src
))) {
420 if (!(fr
->mallocd
& AST_MALLOCD_DATA
)) {
421 if (!(newdata
= ast_malloc(fr
->datalen
+ AST_FRIENDLY_OFFSET
))) {
422 if (out
->src
!= fr
->src
)
423 free((void *) out
->src
);
428 newdata
+= AST_FRIENDLY_OFFSET
;
429 out
->offset
= AST_FRIENDLY_OFFSET
;
430 out
->datalen
= fr
->datalen
;
431 memcpy(newdata
, fr
->data
, fr
->datalen
);
435 out
->mallocd
= AST_MALLOCD_HDR
| AST_MALLOCD_SRC
| AST_MALLOCD_DATA
;
440 struct ast_frame
*ast_frdup(const struct ast_frame
*f
)
442 struct ast_frame
*out
= NULL
;
446 #if !defined(LOW_MEMORY)
447 struct ast_frame_cache
*frames
;
450 /* Start with standard stuff */
451 len
= sizeof(*out
) + AST_FRIENDLY_OFFSET
+ f
->datalen
;
452 /* If we have a source, add space for it */
454 * XXX Watch out here - if we receive a src which is not terminated
455 * properly, we can be easily attacked. Should limit the size we deal with.
458 srclen
= strlen(f
->src
);
462 #if !defined(LOW_MEMORY)
463 if ((frames
= ast_threadstorage_get(&frame_cache
, sizeof(*frames
)))) {
464 AST_LIST_TRAVERSE_SAFE_BEGIN(&frames
->list
, out
, frame_list
) {
465 if (out
->mallocd_hdr_len
>= len
) {
466 size_t mallocd_len
= out
->mallocd_hdr_len
;
467 AST_LIST_REMOVE_CURRENT(&frames
->list
, frame_list
);
468 memset(out
, 0, sizeof(*out
));
469 out
->mallocd_hdr_len
= mallocd_len
;
475 AST_LIST_TRAVERSE_SAFE_END
480 if (!(buf
= ast_calloc_cache(1, len
)))
483 out
->mallocd_hdr_len
= len
;
486 out
->frametype
= f
->frametype
;
487 out
->subclass
= f
->subclass
;
488 out
->datalen
= f
->datalen
;
489 out
->samples
= f
->samples
;
490 out
->delivery
= f
->delivery
;
491 /* Set us as having malloc'd header only, so it will eventually
493 out
->mallocd
= AST_MALLOCD_HDR
;
494 out
->offset
= AST_FRIENDLY_OFFSET
;
496 out
->data
= buf
+ sizeof(*out
) + AST_FRIENDLY_OFFSET
;
497 memcpy(out
->data
, f
->data
, out
->datalen
);
500 out
->src
= buf
+ sizeof(*out
) + AST_FRIENDLY_OFFSET
+ f
->datalen
;
501 /* Must have space since we allocated for it */
502 strcpy((char *)out
->src
, f
->src
);
504 ast_copy_flags(out
, f
, AST_FRFLAG_HAS_TIMING_INFO
);
507 out
->seqno
= f
->seqno
;
511 void ast_swapcopy_samples(void *dst
, const void *src
, int samples
)
514 unsigned short *dst_s
= dst
;
515 const unsigned short *src_s
= src
;
517 for (i
= 0; i
< samples
; i
++)
518 dst_s
[i
] = (src_s
[i
]<<8) | (src_s
[i
]>>8);
522 struct ast_format_list
*ast_get_format_list_index(int index
)
524 return &AST_FORMAT_LIST
[index
];
527 struct ast_format_list
*ast_get_format_list(size_t *size
)
529 *size
= (sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]));
530 return AST_FORMAT_LIST
;
533 char* ast_getformatname(int format
)
536 char *ret
= "unknown";
537 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
538 if(AST_FORMAT_LIST
[x
].visible
&& AST_FORMAT_LIST
[x
].bits
== format
) {
539 ret
= AST_FORMAT_LIST
[x
].name
;
546 char *ast_getformatname_multiple(char *buf
, size_t size
, int format
)
550 char *start
, *end
= buf
;
554 snprintf(end
, size
, "0x%x (", format
);
559 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
560 if (AST_FORMAT_LIST
[x
].visible
&& (AST_FORMAT_LIST
[x
].bits
& format
)) {
561 snprintf(end
, size
,"%s|",AST_FORMAT_LIST
[x
].name
);
568 snprintf(start
, size
, "nothing)");
574 static struct ast_codec_alias_table
{
577 } ast_codec_alias_table
[] = {
578 { "slinear", "slin"},
582 static const char *ast_expand_codec_alias(const char *in
)
586 for (x
= 0; x
< sizeof(ast_codec_alias_table
) / sizeof(ast_codec_alias_table
[0]); x
++) {
587 if(!strcmp(in
,ast_codec_alias_table
[x
].alias
))
588 return ast_codec_alias_table
[x
].realname
;
593 int ast_getformatbyname(const char *name
)
595 int x
, all
, format
= 0;
597 all
= strcasecmp(name
, "all") ? 0 : 1;
598 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
599 if(AST_FORMAT_LIST
[x
].visible
&& (all
||
600 !strcasecmp(AST_FORMAT_LIST
[x
].name
,name
) ||
601 !strcasecmp(AST_FORMAT_LIST
[x
].name
,ast_expand_codec_alias(name
)))) {
602 format
|= AST_FORMAT_LIST
[x
].bits
;
611 char *ast_codec2str(int codec
)
614 char *ret
= "unknown";
615 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
616 if(AST_FORMAT_LIST
[x
].visible
&& AST_FORMAT_LIST
[x
].bits
== codec
) {
617 ret
= AST_FORMAT_LIST
[x
].desc
;
624 static int show_codecs_deprecated(int fd
, int argc
, char *argv
[])
629 if ((argc
< 2) || (argc
> 3))
630 return RESULT_SHOWUSAGE
;
632 if (!ast_opt_dont_warn
)
633 ast_cli(fd
, "Disclaimer: this command is for informational purposes only.\n"
634 "\tIt does not indicate anything about your configuration.\n");
636 ast_cli(fd
, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
637 ast_cli(fd
, "--------------------------------------------------------------------------------\n");
638 if ((argc
== 2) || (!strcasecmp(argv
[1],"audio"))) {
641 snprintf(hex
,25,"(0x%x)",1<<i
);
642 ast_cli(fd
, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i
,i
,hex
,ast_getformatname(1<<i
),ast_codec2str(1<<i
));
646 if ((argc
== 2) || (!strcasecmp(argv
[1],"image"))) {
648 for (i
=16;i
<18;i
++) {
649 snprintf(hex
,25,"(0x%x)",1<<i
);
650 ast_cli(fd
, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i
,i
,hex
,ast_getformatname(1<<i
),ast_codec2str(1<<i
));
654 if ((argc
== 2) || (!strcasecmp(argv
[1],"video"))) {
656 for (i
=18;i
<22;i
++) {
657 snprintf(hex
,25,"(0x%x)",1<<i
);
658 ast_cli(fd
, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i
,i
,hex
,ast_getformatname(1<<i
),ast_codec2str(1<<i
));
663 return RESULT_SHOWUSAGE
;
665 return RESULT_SUCCESS
;
668 static int show_codecs(int fd
, int argc
, char *argv
[])
673 if ((argc
< 3) || (argc
> 4))
674 return RESULT_SHOWUSAGE
;
676 if (!ast_opt_dont_warn
)
677 ast_cli(fd
, "Disclaimer: this command is for informational purposes only.\n"
678 "\tIt does not indicate anything about your configuration.\n");
680 ast_cli(fd
, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
681 ast_cli(fd
, "--------------------------------------------------------------------------------\n");
682 if ((argc
== 3) || (!strcasecmp(argv
[3],"audio"))) {
685 snprintf(hex
,25,"(0x%x)",1<<i
);
686 ast_cli(fd
, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i
,i
,hex
,ast_getformatname(1<<i
),ast_codec2str(1<<i
));
690 if ((argc
== 3) || (!strcasecmp(argv
[3],"image"))) {
692 for (i
=16;i
<18;i
++) {
693 snprintf(hex
,25,"(0x%x)",1<<i
);
694 ast_cli(fd
, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i
,i
,hex
,ast_getformatname(1<<i
),ast_codec2str(1<<i
));
698 if ((argc
== 3) || (!strcasecmp(argv
[3],"video"))) {
700 for (i
=18;i
<22;i
++) {
701 snprintf(hex
,25,"(0x%x)",1<<i
);
702 ast_cli(fd
, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i
,i
,hex
,ast_getformatname(1<<i
),ast_codec2str(1<<i
));
707 return RESULT_SHOWUSAGE
;
709 return RESULT_SUCCESS
;
712 static char frame_show_codecs_usage
[] =
713 "Usage: core show codecs [audio|video|image]\n"
714 " Displays codec mapping\n";
716 static int show_codec_n_deprecated(int fd
, int argc
, char *argv
[])
718 int codec
, i
, found
=0;
721 return RESULT_SHOWUSAGE
;
723 if (sscanf(argv
[2],"%d",&codec
) != 1)
724 return RESULT_SHOWUSAGE
;
726 for (i
= 0; i
< 32; i
++)
727 if (codec
& (1 << i
)) {
729 ast_cli(fd
, "%11u (1 << %2d) %s\n",1 << i
,i
,ast_codec2str(1<<i
));
733 ast_cli(fd
, "Codec %d not found\n", codec
);
735 return RESULT_SUCCESS
;
738 static int show_codec_n(int fd
, int argc
, char *argv
[])
740 int codec
, i
, found
=0;
743 return RESULT_SHOWUSAGE
;
745 if (sscanf(argv
[3],"%d",&codec
) != 1)
746 return RESULT_SHOWUSAGE
;
748 for (i
= 0; i
< 32; i
++)
749 if (codec
& (1 << i
)) {
751 ast_cli(fd
, "%11u (1 << %2d) %s\n",1 << i
,i
,ast_codec2str(1<<i
));
755 ast_cli(fd
, "Codec %d not found\n", codec
);
757 return RESULT_SUCCESS
;
760 static char frame_show_codec_n_usage
[] =
761 "Usage: core show codec <number>\n"
762 " Displays codec mapping\n";
764 /*! Dump a frame for debugging purposes */
765 void ast_frame_dump(const char *name
, struct ast_frame
*f
, char *prefix
)
767 const char noname
[] = "unknown";
768 char ftype
[40] = "Unknown Frametype";
770 char subclass
[40] = "Unknown Subclass";
772 char moreinfo
[40] = "";
782 ast_verbose("%s [ %s (NULL) ] [%s]\n",
783 term_color(cp
, prefix
, COLOR_BRMAGENTA
, COLOR_BLACK
, sizeof(cp
)),
784 term_color(cft
, "HANGUP", COLOR_BRRED
, COLOR_BLACK
, sizeof(cft
)),
785 term_color(cn
, name
, COLOR_YELLOW
, COLOR_BLACK
, sizeof(cn
)));
788 /* XXX We should probably print one each of voice and video when the format changes XXX */
789 if (f
->frametype
== AST_FRAME_VOICE
)
791 if (f
->frametype
== AST_FRAME_VIDEO
)
793 switch(f
->frametype
) {
794 case AST_FRAME_DTMF_BEGIN
:
795 strcpy(ftype
, "DTMF Begin");
796 subclass
[0] = f
->subclass
;
799 case AST_FRAME_DTMF_END
:
800 strcpy(ftype
, "DTMF End");
801 subclass
[0] = f
->subclass
;
804 case AST_FRAME_CONTROL
:
805 strcpy(ftype
, "Control");
806 switch(f
->subclass
) {
807 case AST_CONTROL_HANGUP
:
808 strcpy(subclass
, "Hangup");
810 case AST_CONTROL_RING
:
811 strcpy(subclass
, "Ring");
813 case AST_CONTROL_RINGING
:
814 strcpy(subclass
, "Ringing");
816 case AST_CONTROL_ANSWER
:
817 strcpy(subclass
, "Answer");
819 case AST_CONTROL_BUSY
:
820 strcpy(subclass
, "Busy");
822 case AST_CONTROL_TAKEOFFHOOK
:
823 strcpy(subclass
, "Take Off Hook");
825 case AST_CONTROL_OFFHOOK
:
826 strcpy(subclass
, "Line Off Hook");
828 case AST_CONTROL_CONGESTION
:
829 strcpy(subclass
, "Congestion");
831 case AST_CONTROL_FLASH
:
832 strcpy(subclass
, "Flash");
834 case AST_CONTROL_WINK
:
835 strcpy(subclass
, "Wink");
837 case AST_CONTROL_OPTION
:
838 strcpy(subclass
, "Option");
840 case AST_CONTROL_RADIO_KEY
:
841 strcpy(subclass
, "Key Radio");
843 case AST_CONTROL_RADIO_UNKEY
:
844 strcpy(subclass
, "Unkey Radio");
847 strcpy(subclass
, "Stop generators");
850 snprintf(subclass
, sizeof(subclass
), "Unknown control '%d'", f
->subclass
);
854 strcpy(ftype
, "Null Frame");
855 strcpy(subclass
, "N/A");
858 /* Should never happen */
859 strcpy(ftype
, "IAX Specific");
860 snprintf(subclass
, sizeof(subclass
), "IAX Frametype %d", f
->subclass
);
863 strcpy(ftype
, "Text");
864 strcpy(subclass
, "N/A");
865 ast_copy_string(moreinfo
, f
->data
, sizeof(moreinfo
));
867 case AST_FRAME_IMAGE
:
868 strcpy(ftype
, "Image");
869 snprintf(subclass
, sizeof(subclass
), "Image format %s\n", ast_getformatname(f
->subclass
));
872 strcpy(ftype
, "HTML");
873 switch(f
->subclass
) {
875 strcpy(subclass
, "URL");
876 ast_copy_string(moreinfo
, f
->data
, sizeof(moreinfo
));
879 strcpy(subclass
, "Data");
882 strcpy(subclass
, "Begin");
885 strcpy(subclass
, "End");
887 case AST_HTML_LDCOMPLETE
:
888 strcpy(subclass
, "Load Complete");
890 case AST_HTML_NOSUPPORT
:
891 strcpy(subclass
, "No Support");
893 case AST_HTML_LINKURL
:
894 strcpy(subclass
, "Link URL");
895 ast_copy_string(moreinfo
, f
->data
, sizeof(moreinfo
));
897 case AST_HTML_UNLINK
:
898 strcpy(subclass
, "Unlink");
900 case AST_HTML_LINKREJECT
:
901 strcpy(subclass
, "Link Reject");
904 snprintf(subclass
, sizeof(subclass
), "Unknown HTML frame '%d'\n", f
->subclass
);
908 case AST_FRAME_MODEM
:
909 strcpy(ftype
, "Modem");
910 switch (f
->subclass
) {
912 strcpy(subclass
, "T.38");
915 strcpy(subclass
, "V.150");
918 snprintf(subclass
, sizeof(subclass
), "Unknown MODEM frame '%d'\n", f
->subclass
);
923 snprintf(ftype
, sizeof(ftype
), "Unknown Frametype '%d'", f
->frametype
);
925 if (!ast_strlen_zero(moreinfo
))
926 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
927 term_color(cp
, prefix
, COLOR_BRMAGENTA
, COLOR_BLACK
, sizeof(cp
)),
928 term_color(cft
, ftype
, COLOR_BRRED
, COLOR_BLACK
, sizeof(cft
)),
930 term_color(csub
, subclass
, COLOR_BRCYAN
, COLOR_BLACK
, sizeof(csub
)),
932 term_color(cmn
, moreinfo
, COLOR_BRGREEN
, COLOR_BLACK
, sizeof(cmn
)),
933 term_color(cn
, name
, COLOR_YELLOW
, COLOR_BLACK
, sizeof(cn
)));
935 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
936 term_color(cp
, prefix
, COLOR_BRMAGENTA
, COLOR_BLACK
, sizeof(cp
)),
937 term_color(cft
, ftype
, COLOR_BRRED
, COLOR_BLACK
, sizeof(cft
)),
939 term_color(csub
, subclass
, COLOR_BRCYAN
, COLOR_BLACK
, sizeof(csub
)),
941 term_color(cn
, name
, COLOR_YELLOW
, COLOR_BLACK
, sizeof(cn
)));
946 static int show_frame_stats_deprecated(int fd
, int argc
, char *argv
[])
951 return RESULT_SHOWUSAGE
;
952 AST_LIST_LOCK(&headerlist
);
953 ast_cli(fd
, " Framer Statistics \n");
954 ast_cli(fd
, "---------------------------\n");
955 ast_cli(fd
, "Total allocated headers: %d\n", headers
);
956 ast_cli(fd
, "Queue Dump:\n");
957 AST_LIST_TRAVERSE(&headerlist
, f
, frame_list
)
958 ast_cli(fd
, "%d. Type %d, subclass %d from %s\n", x
++, f
->frametype
, f
->subclass
, f
->src
? f
->src
: "<Unknown>");
959 AST_LIST_UNLOCK(&headerlist
);
960 return RESULT_SUCCESS
;
963 static int show_frame_stats(int fd
, int argc
, char *argv
[])
968 return RESULT_SHOWUSAGE
;
969 AST_LIST_LOCK(&headerlist
);
970 ast_cli(fd
, " Framer Statistics \n");
971 ast_cli(fd
, "---------------------------\n");
972 ast_cli(fd
, "Total allocated headers: %d\n", headers
);
973 ast_cli(fd
, "Queue Dump:\n");
974 AST_LIST_TRAVERSE(&headerlist
, f
, frame_list
)
975 ast_cli(fd
, "%d. Type %d, subclass %d from %s\n", x
++, f
->frametype
, f
->subclass
, f
->src
? f
->src
: "<Unknown>");
976 AST_LIST_UNLOCK(&headerlist
);
977 return RESULT_SUCCESS
;
980 static char frame_stats_usage
[] =
981 "Usage: core show frame stats\n"
982 " Displays debugging statistics from framer\n";
985 /* Builtin Asterisk CLI-commands for debugging */
986 static struct ast_cli_entry cli_show_codecs
= {
987 { "show", "codecs", NULL
},
988 show_codecs_deprecated
, NULL
,
991 static struct ast_cli_entry cli_show_audio_codecs
= {
992 { "show", "audio", "codecs", NULL
},
993 show_codecs_deprecated
, NULL
,
996 static struct ast_cli_entry cli_show_video_codecs
= {
997 { "show", "video", "codecs", NULL
},
998 show_codecs_deprecated
, NULL
,
1001 static struct ast_cli_entry cli_show_image_codecs
= {
1002 { "show", "image", "codecs", NULL
},
1003 show_codecs_deprecated
, NULL
,
1006 static struct ast_cli_entry cli_show_codec
= {
1007 { "show", "codec", NULL
},
1008 show_codec_n_deprecated
, NULL
,
1012 static struct ast_cli_entry cli_show_frame_stats
= {
1013 { "show", "frame", "stats", NULL
},
1014 show_frame_stats
, NULL
,
1018 static struct ast_cli_entry my_clis
[] = {
1019 { { "core", "show", "codecs", NULL
},
1020 show_codecs
, "Displays a list of codecs",
1021 frame_show_codecs_usage
, NULL
, &cli_show_codecs
},
1023 { { "core", "show", "audio", "codecs", NULL
},
1024 show_codecs
, "Displays a list of audio codecs",
1025 frame_show_codecs_usage
, NULL
, &cli_show_audio_codecs
},
1027 { { "core", "show", "video", "codecs", NULL
},
1028 show_codecs
, "Displays a list of video codecs",
1029 frame_show_codecs_usage
, NULL
, &cli_show_video_codecs
},
1031 { { "core", "show", "image", "codecs", NULL
},
1032 show_codecs
, "Displays a list of image codecs",
1033 frame_show_codecs_usage
, NULL
, &cli_show_image_codecs
},
1035 { { "core", "show", "codec", NULL
},
1036 show_codec_n
, "Shows a specific codec",
1037 frame_show_codec_n_usage
, NULL
, &cli_show_codec
},
1040 { { "core", "show", "frame", "stats", NULL
},
1041 show_frame_stats
, "Shows frame statistics",
1042 frame_stats_usage
, NULL
, &cli_show_frame_stats
},
1046 int init_framer(void)
1048 ast_cli_register_multiple(my_clis
, sizeof(my_clis
) / sizeof(struct ast_cli_entry
));
1052 void ast_codec_pref_convert(struct ast_codec_pref
*pref
, char *buf
, size_t size
, int right
)
1054 int x
, differential
= (int) 'A', mem
;
1068 for (x
= 0; x
< 32 ; x
++) {
1071 to
[x
] = right
? (from
[x
] + differential
) : (from
[x
] - differential
);
1075 int ast_codec_pref_string(struct ast_codec_pref
*pref
, char *buf
, size_t size
)
1078 size_t total_len
, slen
;
1085 for(x
= 0; x
< 32 ; x
++) {
1088 if(!(codec
= ast_codec_pref_index(pref
,x
)))
1090 if((formatname
= ast_getformatname(codec
))) {
1091 slen
= strlen(formatname
);
1092 if(slen
> total_len
)
1094 strncat(buf
,formatname
,total_len
);
1097 if(total_len
&& x
< 31 && ast_codec_pref_index(pref
, x
+ 1)) {
1098 strncat(buf
,"|",total_len
);
1103 strncat(buf
,")",total_len
);
1107 return size
- total_len
;
1110 int ast_codec_pref_index(struct ast_codec_pref
*pref
, int index
)
1115 if((index
>= 0) && (index
< sizeof(pref
->order
))) {
1116 slot
= pref
->order
[index
];
1119 return slot
? AST_FORMAT_LIST
[slot
-1].bits
: 0;
1122 /*! \brief Remove codec from pref list */
1123 void ast_codec_pref_remove(struct ast_codec_pref
*pref
, int format
)
1125 struct ast_codec_pref oldorder
;
1133 memcpy(&oldorder
, pref
, sizeof(oldorder
));
1134 memset(pref
, 0, sizeof(*pref
));
1136 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
1137 slot
= oldorder
.order
[x
];
1138 size
= oldorder
.framing
[x
];
1141 if(AST_FORMAT_LIST
[slot
-1].bits
!= format
) {
1142 pref
->order
[y
] = slot
;
1143 pref
->framing
[y
++] = size
;
1149 /*! \brief Append codec to list */
1150 int ast_codec_pref_append(struct ast_codec_pref
*pref
, int format
)
1152 int x
, newindex
= 0;
1154 ast_codec_pref_remove(pref
, format
);
1156 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
1157 if(AST_FORMAT_LIST
[x
].bits
== format
) {
1164 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
1165 if(!pref
->order
[x
]) {
1166 pref
->order
[x
] = newindex
;
1175 /*! \brief Prepend codec to list */
1176 void ast_codec_pref_prepend(struct ast_codec_pref
*pref
, int format
, int only_if_existing
)
1178 int x
, newindex
= 0;
1180 /* First step is to get the codecs "index number" */
1181 for (x
= 0; x
< ARRAY_LEN(AST_FORMAT_LIST
); x
++) {
1182 if (AST_FORMAT_LIST
[x
].bits
== format
) {
1187 /* Done if its unknown */
1191 /* Now find any existing occurrence, or the end */
1192 for (x
= 0; x
< 32; x
++) {
1193 if (!pref
->order
[x
] || pref
->order
[x
] == newindex
)
1197 if (only_if_existing
&& !pref
->order
[x
])
1200 /* Move down to make space to insert - either all the way to the end,
1201 or as far as the existing location (which will be overwritten) */
1202 for (; x
> 0; x
--) {
1203 pref
->order
[x
] = pref
->order
[x
- 1];
1204 pref
->framing
[x
] = pref
->framing
[x
- 1];
1207 /* And insert the new entry */
1208 pref
->order
[0] = newindex
;
1209 pref
->framing
[0] = 0; /* ? */
1212 /*! \brief Set packet size for codec */
1213 int ast_codec_pref_setsize(struct ast_codec_pref
*pref
, int format
, int framems
)
1217 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
1218 if(AST_FORMAT_LIST
[x
].bits
== format
) {
1227 /* size validation */
1229 framems
= AST_FORMAT_LIST
[index
].def_ms
;
1231 if(AST_FORMAT_LIST
[index
].inc_ms
&& framems
% AST_FORMAT_LIST
[index
].inc_ms
) /* avoid division by zero */
1232 framems
-= framems
% AST_FORMAT_LIST
[index
].inc_ms
;
1234 if(framems
< AST_FORMAT_LIST
[index
].min_ms
)
1235 framems
= AST_FORMAT_LIST
[index
].min_ms
;
1237 if(framems
> AST_FORMAT_LIST
[index
].max_ms
)
1238 framems
= AST_FORMAT_LIST
[index
].max_ms
;
1241 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
1242 if(pref
->order
[x
] == (index
+ 1)) {
1243 pref
->framing
[x
] = framems
;
1251 /*! \brief Get packet size for codec */
1252 struct ast_format_list
ast_codec_pref_getsize(struct ast_codec_pref
*pref
, int format
)
1254 int x
, index
= -1, framems
= 0;
1255 struct ast_format_list fmt
= {0};
1257 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
1258 if(AST_FORMAT_LIST
[x
].bits
== format
) {
1259 fmt
= AST_FORMAT_LIST
[x
];
1265 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
1266 if(pref
->order
[x
] == (index
+ 1)) {
1267 framems
= pref
->framing
[x
];
1272 /* size validation */
1274 framems
= AST_FORMAT_LIST
[index
].def_ms
;
1276 if(AST_FORMAT_LIST
[index
].inc_ms
&& framems
% AST_FORMAT_LIST
[index
].inc_ms
) /* avoid division by zero */
1277 framems
-= framems
% AST_FORMAT_LIST
[index
].inc_ms
;
1279 if(framems
< AST_FORMAT_LIST
[index
].min_ms
)
1280 framems
= AST_FORMAT_LIST
[index
].min_ms
;
1282 if(framems
> AST_FORMAT_LIST
[index
].max_ms
)
1283 framems
= AST_FORMAT_LIST
[index
].max_ms
;
1285 fmt
.cur_ms
= framems
;
1290 /*! \brief Pick a codec */
1291 int ast_codec_choose(struct ast_codec_pref
*pref
, int formats
, int find_best
)
1293 int x
, ret
= 0, slot
;
1295 for (x
= 0; x
< sizeof(AST_FORMAT_LIST
) / sizeof(AST_FORMAT_LIST
[0]); x
++) {
1296 slot
= pref
->order
[x
];
1300 if (formats
& AST_FORMAT_LIST
[slot
-1].bits
) {
1301 ret
= AST_FORMAT_LIST
[slot
-1].bits
;
1305 if(ret
& AST_FORMAT_AUDIO_MASK
)
1308 if (option_debug
> 3)
1309 ast_log(LOG_DEBUG
, "Could not find preferred codec - %s\n", find_best
? "Going for the best codec" : "Returning zero codec");
1311 return find_best
? ast_best_codec(formats
) : 0;
1314 void ast_parse_allow_disallow(struct ast_codec_pref
*pref
, int *mask
, const char *list
, int allowing
)
1316 char *parse
= NULL
, *this = NULL
, *psize
= NULL
;
1317 int format
= 0, framems
= 0;
1319 parse
= ast_strdupa(list
);
1320 while ((this = strsep(&parse
, ","))) {
1322 if ((psize
= strrchr(this, ':'))) {
1325 ast_log(LOG_DEBUG
,"Packetization for codec: %s is %s\n", this, psize
);
1326 framems
= atoi(psize
);
1330 if (!(format
= ast_getformatbyname(this))) {
1331 ast_log(LOG_WARNING
, "Cannot %s unknown format '%s'\n", allowing
? "allow" : "disallow", this);
1342 /* Set up a preference list for audio. Do not include video in preferences
1343 since we can not transcode video and have to use whatever is offered
1345 if (pref
&& (format
& AST_FORMAT_AUDIO_MASK
)) {
1346 if (strcasecmp(this, "all")) {
1348 ast_codec_pref_append(pref
, format
);
1349 ast_codec_pref_setsize(pref
, format
, framems
);
1352 ast_codec_pref_remove(pref
, format
);
1353 } else if (!allowing
) {
1354 memset(pref
, 0, sizeof(*pref
));
1360 static int g723_len(unsigned char buf
)
1362 enum frame_type type
= buf
& TYPE_MASK
;
1378 ast_log(LOG_WARNING
, "Badly encoded frame (%d)\n", type
);
1383 static int g723_samples(unsigned char *buf
, int maxlen
)
1388 while(pos
< maxlen
) {
1389 res
= g723_len(buf
[pos
]);
1398 static unsigned char get_n_bits_at(unsigned char *data
, int n
, int bit
)
1400 int byte
= bit
/ 8; /* byte containing first bit */
1401 int rem
= 8 - (bit
% 8); /* remaining bits in first byte */
1402 unsigned char ret
= 0;
1404 if (n
<= 0 || n
> 8)
1408 ret
= (data
[byte
] << (n
- rem
));
1409 ret
|= (data
[byte
+ 1] >> (8 - n
+ rem
));
1411 ret
= (data
[byte
] >> (rem
- n
));
1414 return (ret
& (0xff >> (8 - n
)));
1417 static int speex_get_wb_sz_at(unsigned char *data
, int len
, int bit
)
1419 static int SpeexWBSubModeSz
[] = {
1425 /* skip up to two wideband frames */
1426 if (((len
* 8 - off
) >= 5) &&
1427 get_n_bits_at(data
, 1, off
)) {
1428 c
= get_n_bits_at(data
, 3, off
+ 1);
1429 off
+= SpeexWBSubModeSz
[c
];
1431 if (((len
* 8 - off
) >= 5) &&
1432 get_n_bits_at(data
, 1, off
)) {
1433 c
= get_n_bits_at(data
, 3, off
+ 1);
1434 off
+= SpeexWBSubModeSz
[c
];
1436 if (((len
* 8 - off
) >= 5) &&
1437 get_n_bits_at(data
, 1, off
)) {
1438 ast_log(LOG_WARNING
, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1447 static int speex_samples(unsigned char *data
, int len
)
1449 static int SpeexSubModeSz
[] = {
1454 static int SpeexInBandSz
[] = {
1464 while ((len
* 8 - bit
) >= 5) {
1465 /* skip wideband frames */
1466 off
= speex_get_wb_sz_at(data
, len
, bit
);
1468 ast_log(LOG_WARNING
, "Had error while reading wideband frames for speex samples\n");
1473 if ((len
* 8 - bit
) < 5) {
1474 ast_log(LOG_WARNING
, "Not enough bits remaining after wide band for speex samples.\n");
1478 /* get control bits */
1479 c
= get_n_bits_at(data
, 5, bit
);
1485 } else if (c
== 14) {
1486 /* in-band signal; next 4 bits contain signal id */
1487 c
= get_n_bits_at(data
, 4, bit
);
1489 bit
+= SpeexInBandSz
[c
];
1490 } else if (c
== 13) {
1491 /* user in-band; next 5 bits contain msg len */
1492 c
= get_n_bits_at(data
, 5, bit
);
1499 /* skip number bits for submode (less the 5 control bits) */
1500 bit
+= SpeexSubModeSz
[c
] - 5;
1501 cnt
+= 160; /* new frame */
1507 int ast_codec_get_samples(struct ast_frame
*f
)
1510 switch(f
->subclass
) {
1511 case AST_FORMAT_SPEEX
:
1512 samples
= speex_samples(f
->data
, f
->datalen
);
1514 case AST_FORMAT_G723_1
:
1515 samples
= g723_samples(f
->data
, f
->datalen
);
1517 case AST_FORMAT_ILBC
:
1518 samples
= 240 * (f
->datalen
/ 50);
1520 case AST_FORMAT_GSM
:
1521 samples
= 160 * (f
->datalen
/ 33);
1523 case AST_FORMAT_G729A
:
1524 samples
= f
->datalen
* 8;
1526 case AST_FORMAT_SLINEAR
:
1527 samples
= f
->datalen
/ 2;
1529 case AST_FORMAT_LPC10
:
1530 /* assumes that the RTP packet contains one LPC10 frame */
1532 samples
+= (((char *)(f
->data
))[7] & 0x1) * 8;
1534 case AST_FORMAT_ULAW
:
1535 case AST_FORMAT_ALAW
:
1536 samples
= f
->datalen
;
1538 case AST_FORMAT_G722
:
1539 case AST_FORMAT_ADPCM
:
1540 case AST_FORMAT_G726
:
1541 case AST_FORMAT_G726_AAL2
:
1542 samples
= f
->datalen
* 2;
1545 ast_log(LOG_WARNING
, "Unable to calculate samples for format %s\n", ast_getformatname(f
->subclass
));
1550 int ast_codec_get_len(int format
, int samples
)
1554 /* XXX Still need speex, g723, and lpc10 XXX */
1556 case AST_FORMAT_ILBC
:
1557 len
= (samples
/ 240) * 50;
1559 case AST_FORMAT_GSM
:
1560 len
= (samples
/ 160) * 33;
1562 case AST_FORMAT_G729A
:
1565 case AST_FORMAT_SLINEAR
:
1568 case AST_FORMAT_ULAW
:
1569 case AST_FORMAT_ALAW
:
1572 case AST_FORMAT_G722
:
1573 case AST_FORMAT_ADPCM
:
1574 case AST_FORMAT_G726
:
1575 case AST_FORMAT_G726_AAL2
:
1579 ast_log(LOG_WARNING
, "Unable to calculate sample length for format %s\n", ast_getformatname(format
));
1585 int ast_frame_adjust_volume(struct ast_frame
*f
, int adjustment
)
1588 short *fdata
= f
->data
;
1589 short adjust_value
= abs(adjustment
);
1591 if ((f
->frametype
!= AST_FRAME_VOICE
) || (f
->subclass
!= AST_FORMAT_SLINEAR
))
1597 for (count
= 0; count
< f
->samples
; count
++) {
1598 if (adjustment
> 0) {
1599 ast_slinear_saturated_multiply(&fdata
[count
], &adjust_value
);
1600 } else if (adjustment
< 0) {
1601 ast_slinear_saturated_divide(&fdata
[count
], &adjust_value
);
1608 int ast_frame_slinear_sum(struct ast_frame
*f1
, struct ast_frame
*f2
)
1611 short *data1
, *data2
;
1613 if ((f1
->frametype
!= AST_FRAME_VOICE
) || (f1
->subclass
!= AST_FORMAT_SLINEAR
))
1616 if ((f2
->frametype
!= AST_FRAME_VOICE
) || (f2
->subclass
!= AST_FORMAT_SLINEAR
))
1619 if (f1
->samples
!= f2
->samples
)
1622 for (count
= 0, data1
= f1
->data
, data2
= f2
->data
;
1623 count
< f1
->samples
;
1624 count
++, data1
++, data2
++)
1625 ast_slinear_saturated_add(data1
, data2
);