00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 180378 $")
00029
00030 #include "asterisk/_private.h"
00031 #include "asterisk/lock.h"
00032 #include "asterisk/frame.h"
00033 #include "asterisk/channel.h"
00034 #include "asterisk/cli.h"
00035 #include "asterisk/term.h"
00036 #include "asterisk/utils.h"
00037 #include "asterisk/threadstorage.h"
00038 #include "asterisk/linkedlists.h"
00039 #include "asterisk/translate.h"
00040 #include "asterisk/dsp.h"
00041 #include "asterisk/file.h"
00042
00043 #ifdef TRACE_FRAMES
00044 static int headers;
00045 static AST_LIST_HEAD_STATIC(headerlist, ast_frame);
00046 #endif
00047
00048 #if !defined(LOW_MEMORY)
00049 static void frame_cache_cleanup(void *data);
00050
00051
00052 AST_THREADSTORAGE_CUSTOM(frame_cache, NULL, frame_cache_cleanup);
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #define FRAME_CACHE_MAX_SIZE 10
00064
00065
00066
00067 AST_LIST_HEAD_NOLOCK(ast_frames, ast_frame);
00068
00069 struct ast_frame_cache {
00070 struct ast_frames list;
00071 size_t size;
00072 };
00073 #endif
00074
00075 #define SMOOTHER_SIZE 8000
00076
00077 enum frame_type {
00078 TYPE_HIGH,
00079 TYPE_LOW,
00080 TYPE_SILENCE,
00081 TYPE_DONTSEND
00082 };
00083
00084 #define TYPE_MASK 0x3
00085
00086 struct ast_smoother {
00087 int size;
00088 int format;
00089 int flags;
00090 float samplesperbyte;
00091 unsigned int opt_needs_swap:1;
00092 struct ast_frame f;
00093 struct timeval delivery;
00094 char data[SMOOTHER_SIZE];
00095 char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
00096 struct ast_frame *opt;
00097 int len;
00098 };
00099
00100
00101 static struct ast_format_list AST_FORMAT_LIST[] = {
00102 { AST_FORMAT_G723_1 , "g723", 8000, "G.723.1", 20, 30, 300, 30, 30 },
00103 { AST_FORMAT_GSM, "gsm", 8000, "GSM", 33, 20, 300, 20, 20 },
00104 { AST_FORMAT_ULAW, "ulaw", 8000, "G.711 u-law", 80, 10, 150, 10, 20 },
00105 { AST_FORMAT_ALAW, "alaw", 8000, "G.711 A-law", 80, 10, 150, 10, 20 },
00106 { AST_FORMAT_G726, "g726", 8000, "G.726 RFC3551", 40, 10, 300, 10, 20 },
00107 { AST_FORMAT_ADPCM, "adpcm" , 8000, "ADPCM", 40, 10, 300, 10, 20 },
00108 { AST_FORMAT_SLINEAR, "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE },
00109 { AST_FORMAT_LPC10, "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20 },
00110 { AST_FORMAT_G729A, "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 },
00111 { AST_FORMAT_SPEEX, "speex", 8000, "SpeeX", 10, 10, 60, 10, 20 },
00112 { AST_FORMAT_ILBC, "ilbc", 8000, "iLBC", 50, 30, 30, 30, 30 },
00113 { AST_FORMAT_G726_AAL2, "g726aal2", 8000, "G.726 AAL2", 40, 10, 300, 10, 20 },
00114 { AST_FORMAT_G722, "g722", 16000, "G722", 80, 10, 150, 10, 20 },
00115 { AST_FORMAT_SLINEAR16, "slin16", 16000, "16 bit Signed Linear PCM (16kHz)", 320, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE },
00116 { AST_FORMAT_JPEG, "jpeg", 0, "JPEG image"},
00117 { AST_FORMAT_PNG, "png", 0, "PNG image"},
00118 { AST_FORMAT_H261, "h261", 0, "H.261 Video" },
00119 { AST_FORMAT_H263, "h263", 0, "H.263 Video" },
00120 { AST_FORMAT_H263_PLUS, "h263p", 0, "H.263+ Video" },
00121 { AST_FORMAT_H264, "h264", 0, "H.264 Video" },
00122 { AST_FORMAT_MP4_VIDEO, "mpeg4", 0, "MPEG4 Video" },
00123 { AST_FORMAT_T140RED, "red", 1, "T.140 Realtime Text with redundancy"},
00124 { AST_FORMAT_T140, "t140", 0, "Passthrough T.140 Realtime Text" },
00125 };
00126
00127 struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
00128
00129 static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
00130 {
00131 if (s->flags & AST_SMOOTHER_FLAG_G729) {
00132 if (s->len % 10) {
00133 ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
00134 return 0;
00135 }
00136 }
00137 if (swap) {
00138 ast_swapcopy_samples(s->data + s->len, f->data.ptr, f->samples);
00139 } else {
00140 memcpy(s->data + s->len, f->data.ptr, f->datalen);
00141 }
00142
00143 if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) {
00144 s->delivery = f->delivery;
00145 }
00146 s->len += f->datalen;
00147
00148 return 0;
00149 }
00150
00151 void ast_smoother_reset(struct ast_smoother *s, int bytes)
00152 {
00153 memset(s, 0, sizeof(*s));
00154 s->size = bytes;
00155 }
00156
00157 void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
00158 {
00159
00160 if (s->size == bytes) {
00161 return;
00162 }
00163
00164 s->size = bytes;
00165
00166
00167
00168 if (!s->opt) {
00169 return;
00170 }
00171
00172
00173
00174
00175 smoother_frame_feed(s, s->opt, s->opt_needs_swap);
00176 s->opt = NULL;
00177 }
00178
00179 struct ast_smoother *ast_smoother_new(int size)
00180 {
00181 struct ast_smoother *s;
00182 if (size < 1)
00183 return NULL;
00184 if ((s = ast_malloc(sizeof(*s))))
00185 ast_smoother_reset(s, size);
00186 return s;
00187 }
00188
00189 int ast_smoother_get_flags(struct ast_smoother *s)
00190 {
00191 return s->flags;
00192 }
00193
00194 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
00195 {
00196 s->flags = flags;
00197 }
00198
00199 int ast_smoother_test_flag(struct ast_smoother *s, int flag)
00200 {
00201 return (s->flags & flag);
00202 }
00203
00204 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
00205 {
00206 if (f->frametype != AST_FRAME_VOICE) {
00207 ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
00208 return -1;
00209 }
00210 if (!s->format) {
00211 s->format = f->subclass;
00212 s->samplesperbyte = (float)f->samples / (float)f->datalen;
00213 } else if (s->format != f->subclass) {
00214 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
00215 return -1;
00216 }
00217 if (s->len + f->datalen > SMOOTHER_SIZE) {
00218 ast_log(LOG_WARNING, "Out of smoother space\n");
00219 return -1;
00220 }
00221 if (((f->datalen == s->size) ||
00222 ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
00223 !s->opt &&
00224 !s->len &&
00225 (f->offset >= AST_MIN_OFFSET)) {
00226
00227
00228
00229 if (swap)
00230 ast_swapcopy_samples(f->data.ptr, f->data.ptr, f->samples);
00231 s->opt = f;
00232 s->opt_needs_swap = swap ? 1 : 0;
00233 return 0;
00234 }
00235
00236 return smoother_frame_feed(s, f, swap);
00237 }
00238
00239 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
00240 {
00241 struct ast_frame *opt;
00242 int len;
00243
00244
00245 if (s->opt) {
00246 if (s->opt->offset < AST_FRIENDLY_OFFSET)
00247 ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
00248 s->opt->offset);
00249 opt = s->opt;
00250 s->opt = NULL;
00251 return opt;
00252 }
00253
00254
00255 if (s->len < s->size) {
00256
00257 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
00258 return NULL;
00259 }
00260 len = s->size;
00261 if (len > s->len)
00262 len = s->len;
00263
00264 s->f.frametype = AST_FRAME_VOICE;
00265 s->f.subclass = s->format;
00266 s->f.data.ptr = s->framedata + AST_FRIENDLY_OFFSET;
00267 s->f.offset = AST_FRIENDLY_OFFSET;
00268 s->f.datalen = len;
00269
00270 s->f.samples = len * s->samplesperbyte;
00271 s->f.delivery = s->delivery;
00272
00273 memcpy(s->f.data.ptr, s->data, len);
00274 s->len -= len;
00275
00276 if (s->len) {
00277
00278
00279 memmove(s->data, s->data + len, s->len);
00280 if (!ast_tvzero(s->delivery)) {
00281
00282 s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, ast_format_rate(s->format)));
00283 }
00284 }
00285
00286 return &s->f;
00287 }
00288
00289 void ast_smoother_free(struct ast_smoother *s)
00290 {
00291 ast_free(s);
00292 }
00293
00294 static struct ast_frame *ast_frame_header_new(void)
00295 {
00296 struct ast_frame *f;
00297
00298 #if !defined(LOW_MEMORY)
00299 struct ast_frame_cache *frames;
00300
00301 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
00302 if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
00303 size_t mallocd_len = f->mallocd_hdr_len;
00304 memset(f, 0, sizeof(*f));
00305 f->mallocd_hdr_len = mallocd_len;
00306 f->mallocd = AST_MALLOCD_HDR;
00307 frames->size--;
00308 return f;
00309 }
00310 }
00311 if (!(f = ast_calloc_cache(1, sizeof(*f))))
00312 return NULL;
00313 #else
00314 if (!(f = ast_calloc(1, sizeof(*f))))
00315 return NULL;
00316 #endif
00317
00318 f->mallocd_hdr_len = sizeof(*f);
00319 #ifdef TRACE_FRAMES
00320 AST_LIST_LOCK(&headerlist);
00321 headers++;
00322 AST_LIST_INSERT_HEAD(&headerlist, f, frame_list);
00323 AST_LIST_UNLOCK(&headerlist);
00324 #endif
00325
00326 return f;
00327 }
00328
00329 #if !defined(LOW_MEMORY)
00330 static void frame_cache_cleanup(void *data)
00331 {
00332 struct ast_frame_cache *frames = data;
00333 struct ast_frame *f;
00334
00335 while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
00336 ast_free(f);
00337
00338 ast_free(frames);
00339 }
00340 #endif
00341
00342 void ast_frame_free(struct ast_frame *fr, int cache)
00343 {
00344 if (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR)) {
00345 ast_translate_frame_freed(fr);
00346 } else if (ast_test_flag(fr, AST_FRFLAG_FROM_DSP)) {
00347 ast_dsp_frame_freed(fr);
00348 } else if (ast_test_flag(fr, AST_FRFLAG_FROM_FILESTREAM)) {
00349 ast_filestream_frame_freed(fr);
00350 }
00351
00352 if (!fr->mallocd)
00353 return;
00354
00355 #if !defined(LOW_MEMORY)
00356 if (cache && fr->mallocd == AST_MALLOCD_HDR) {
00357
00358
00359 struct ast_frame_cache *frames;
00360
00361 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))
00362 && frames->size < FRAME_CACHE_MAX_SIZE) {
00363 AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
00364 frames->size++;
00365 return;
00366 }
00367 }
00368 #endif
00369
00370 if (fr->mallocd & AST_MALLOCD_DATA) {
00371 if (fr->data.ptr)
00372 ast_free(fr->data.ptr - fr->offset);
00373 }
00374 if (fr->mallocd & AST_MALLOCD_SRC) {
00375 if (fr->src)
00376 ast_free((char *)fr->src);
00377 }
00378 if (fr->mallocd & AST_MALLOCD_HDR) {
00379 #ifdef TRACE_FRAMES
00380 AST_LIST_LOCK(&headerlist);
00381 headers--;
00382 AST_LIST_REMOVE(&headerlist, fr, frame_list);
00383 AST_LIST_UNLOCK(&headerlist);
00384 #endif
00385 ast_free(fr);
00386 }
00387 }
00388
00389
00390
00391
00392
00393
00394 struct ast_frame *ast_frisolate(struct ast_frame *fr)
00395 {
00396 struct ast_frame *out;
00397 void *newdata;
00398
00399 ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
00400 ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
00401
00402 if (!(fr->mallocd & AST_MALLOCD_HDR)) {
00403
00404 if (!(out = ast_frame_header_new()))
00405 return NULL;
00406 out->frametype = fr->frametype;
00407 out->subclass = fr->subclass;
00408 out->datalen = fr->datalen;
00409 out->samples = fr->samples;
00410 out->offset = fr->offset;
00411 out->data = fr->data;
00412
00413 ast_copy_flags(out, fr, AST_FRFLAG_HAS_TIMING_INFO);
00414 if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
00415 out->ts = fr->ts;
00416 out->len = fr->len;
00417 out->seqno = fr->seqno;
00418 }
00419 } else
00420 out = fr;
00421
00422 if (!(fr->mallocd & AST_MALLOCD_SRC)) {
00423 if (fr->src) {
00424 if (!(out->src = ast_strdup(fr->src))) {
00425 if (out != fr)
00426 ast_free(out);
00427 return NULL;
00428 }
00429 }
00430 } else
00431 out->src = fr->src;
00432
00433 if (!(fr->mallocd & AST_MALLOCD_DATA)) {
00434 if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
00435 if (out->src != fr->src)
00436 ast_free((void *) out->src);
00437 if (out != fr)
00438 ast_free(out);
00439 return NULL;
00440 }
00441 newdata += AST_FRIENDLY_OFFSET;
00442 out->offset = AST_FRIENDLY_OFFSET;
00443 out->datalen = fr->datalen;
00444 memcpy(newdata, fr->data.ptr, fr->datalen);
00445 out->data.ptr = newdata;
00446 }
00447
00448 out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
00449
00450 return out;
00451 }
00452
00453 struct ast_frame *ast_frdup(const struct ast_frame *f)
00454 {
00455 struct ast_frame *out = NULL;
00456 int len, srclen = 0;
00457 void *buf = NULL;
00458
00459 #if !defined(LOW_MEMORY)
00460 struct ast_frame_cache *frames;
00461 #endif
00462
00463
00464 len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
00465
00466
00467
00468
00469
00470 if (f->src)
00471 srclen = strlen(f->src);
00472 if (srclen > 0)
00473 len += srclen + 1;
00474
00475 #if !defined(LOW_MEMORY)
00476 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
00477 AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
00478 if (out->mallocd_hdr_len >= len) {
00479 size_t mallocd_len = out->mallocd_hdr_len;
00480
00481 AST_LIST_REMOVE_CURRENT(frame_list);
00482 memset(out, 0, sizeof(*out));
00483 out->mallocd_hdr_len = mallocd_len;
00484 buf = out;
00485 frames->size--;
00486 break;
00487 }
00488 }
00489 AST_LIST_TRAVERSE_SAFE_END;
00490 }
00491 #endif
00492
00493 if (!buf) {
00494 if (!(buf = ast_calloc_cache(1, len)))
00495 return NULL;
00496 out = buf;
00497 out->mallocd_hdr_len = len;
00498 }
00499
00500 out->frametype = f->frametype;
00501 out->subclass = f->subclass;
00502 out->datalen = f->datalen;
00503 out->samples = f->samples;
00504 out->delivery = f->delivery;
00505
00506
00507 out->mallocd = AST_MALLOCD_HDR;
00508 out->offset = AST_FRIENDLY_OFFSET;
00509 if (out->datalen) {
00510 out->data.ptr = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
00511 memcpy(out->data.ptr, f->data.ptr, out->datalen);
00512 } else {
00513 out->data.uint32 = f->data.uint32;
00514 }
00515 if (srclen > 0) {
00516
00517 char *src;
00518 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
00519 src = (char *) out->src;
00520
00521 strcpy(src, f->src);
00522 }
00523 ast_copy_flags(out, f, AST_FRFLAG_HAS_TIMING_INFO);
00524 out->ts = f->ts;
00525 out->len = f->len;
00526 out->seqno = f->seqno;
00527 return out;
00528 }
00529
00530 void ast_swapcopy_samples(void *dst, const void *src, int samples)
00531 {
00532 int i;
00533 unsigned short *dst_s = dst;
00534 const unsigned short *src_s = src;
00535
00536 for (i = 0; i < samples; i++)
00537 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
00538 }
00539
00540
00541 struct ast_format_list *ast_get_format_list_index(int idx)
00542 {
00543 return &AST_FORMAT_LIST[idx];
00544 }
00545
00546 struct ast_format_list *ast_get_format_list(size_t *size)
00547 {
00548 *size = ARRAY_LEN(AST_FORMAT_LIST);
00549 return AST_FORMAT_LIST;
00550 }
00551
00552 char* ast_getformatname(int format)
00553 {
00554 int x;
00555 char *ret = "unknown";
00556 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00557 if (AST_FORMAT_LIST[x].bits == format) {
00558 ret = AST_FORMAT_LIST[x].name;
00559 break;
00560 }
00561 }
00562 return ret;
00563 }
00564
00565 char *ast_getformatname_multiple(char *buf, size_t size, int format)
00566 {
00567 int x;
00568 unsigned len;
00569 char *start, *end = buf;
00570
00571 if (!size)
00572 return buf;
00573 snprintf(end, size, "0x%x (", format);
00574 len = strlen(end);
00575 end += len;
00576 size -= len;
00577 start = end;
00578 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00579 if (AST_FORMAT_LIST[x].bits & format) {
00580 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
00581 len = strlen(end);
00582 end += len;
00583 size -= len;
00584 }
00585 }
00586 if (start == end)
00587 ast_copy_string(start, "nothing)", size);
00588 else if (size > 1)
00589 *(end -1) = ')';
00590 return buf;
00591 }
00592
00593 static struct ast_codec_alias_table {
00594 char *alias;
00595 char *realname;
00596 } ast_codec_alias_table[] = {
00597 { "slinear", "slin"},
00598 { "slinear16", "slin16"},
00599 { "g723.1", "g723"},
00600 };
00601
00602 static const char *ast_expand_codec_alias(const char *in)
00603 {
00604 int x;
00605
00606 for (x = 0; x < ARRAY_LEN(ast_codec_alias_table); x++) {
00607 if (!strcmp(in,ast_codec_alias_table[x].alias))
00608 return ast_codec_alias_table[x].realname;
00609 }
00610 return in;
00611 }
00612
00613 int ast_getformatbyname(const char *name)
00614 {
00615 int x, all, format = 0;
00616
00617 all = strcasecmp(name, "all") ? 0 : 1;
00618 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00619 if (all ||
00620 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
00621 !strcasecmp(AST_FORMAT_LIST[x].name, ast_expand_codec_alias(name))) {
00622 format |= AST_FORMAT_LIST[x].bits;
00623 if (!all)
00624 break;
00625 }
00626 }
00627
00628 return format;
00629 }
00630
00631 char *ast_codec2str(int codec)
00632 {
00633 int x;
00634 char *ret = "unknown";
00635 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00636 if (AST_FORMAT_LIST[x].bits == codec) {
00637 ret = AST_FORMAT_LIST[x].desc;
00638 break;
00639 }
00640 }
00641 return ret;
00642 }
00643
00644 static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00645 {
00646 int i, found=0;
00647 char hex[25];
00648
00649 switch (cmd) {
00650 case CLI_INIT:
00651 e->command = "core show codecs [audio|video|image]";
00652 e->usage =
00653 "Usage: core show codecs [audio|video|image]\n"
00654 " Displays codec mapping\n";
00655 return NULL;
00656 case CLI_GENERATE:
00657 return NULL;
00658 }
00659
00660 if ((a->argc < 3) || (a->argc > 4))
00661 return CLI_SHOWUSAGE;
00662
00663 if (!ast_opt_dont_warn)
00664 ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
00665 "\tIt does not indicate anything about your configuration.\n");
00666
00667 ast_cli(a->fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
00668 ast_cli(a->fd, "--------------------------------------------------------------------------------\n");
00669 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"audio"))) {
00670 found = 1;
00671 for (i=0;i<13;i++) {
00672 snprintf(hex,25,"(0x%x)",1<<i);
00673 ast_cli(a->fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00674 }
00675 }
00676
00677 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"image"))) {
00678 found = 1;
00679 for (i=16;i<18;i++) {
00680 snprintf(hex,25,"(0x%x)",1<<i);
00681 ast_cli(a->fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00682 }
00683 }
00684
00685 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"video"))) {
00686 found = 1;
00687 for (i=18;i<22;i++) {
00688 snprintf(hex,25,"(0x%x)",1<<i);
00689 ast_cli(a->fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00690 }
00691 }
00692
00693 if (!found)
00694 return CLI_SHOWUSAGE;
00695 else
00696 return CLI_SUCCESS;
00697 }
00698
00699 static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00700 {
00701 int codec, i, found=0;
00702
00703 switch (cmd) {
00704 case CLI_INIT:
00705 e->command = "core show codec";
00706 e->usage =
00707 "Usage: core show codec <number>\n"
00708 " Displays codec mapping\n";
00709 return NULL;
00710 case CLI_GENERATE:
00711 return NULL;
00712 }
00713
00714 if (a->argc != 4)
00715 return CLI_SHOWUSAGE;
00716
00717 if (sscanf(a->argv[3],"%d",&codec) != 1)
00718 return CLI_SHOWUSAGE;
00719
00720 for (i = 0; i < 32; i++)
00721 if (codec & (1 << i)) {
00722 found = 1;
00723 ast_cli(a->fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
00724 }
00725
00726 if (!found)
00727 ast_cli(a->fd, "Codec %d not found\n", codec);
00728
00729 return CLI_SUCCESS;
00730 }
00731
00732
00733 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
00734 {
00735 const char noname[] = "unknown";
00736 char ftype[40] = "Unknown Frametype";
00737 char cft[80];
00738 char subclass[40] = "Unknown Subclass";
00739 char csub[80];
00740 char moreinfo[40] = "";
00741 char cn[60];
00742 char cp[40];
00743 char cmn[40];
00744 const char *message = "Unknown";
00745
00746 if (!name)
00747 name = noname;
00748
00749
00750 if (!f) {
00751 ast_verbose("%s [ %s (NULL) ] [%s]\n",
00752 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00753 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00754 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00755 return;
00756 }
00757
00758 if (f->frametype == AST_FRAME_VOICE)
00759 return;
00760 if (f->frametype == AST_FRAME_VIDEO)
00761 return;
00762 switch(f->frametype) {
00763 case AST_FRAME_DTMF_BEGIN:
00764 strcpy(ftype, "DTMF Begin");
00765 subclass[0] = f->subclass;
00766 subclass[1] = '\0';
00767 break;
00768 case AST_FRAME_DTMF_END:
00769 strcpy(ftype, "DTMF End");
00770 subclass[0] = f->subclass;
00771 subclass[1] = '\0';
00772 break;
00773 case AST_FRAME_CONTROL:
00774 strcpy(ftype, "Control");
00775 switch(f->subclass) {
00776 case AST_CONTROL_HANGUP:
00777 strcpy(subclass, "Hangup");
00778 break;
00779 case AST_CONTROL_RING:
00780 strcpy(subclass, "Ring");
00781 break;
00782 case AST_CONTROL_RINGING:
00783 strcpy(subclass, "Ringing");
00784 break;
00785 case AST_CONTROL_ANSWER:
00786 strcpy(subclass, "Answer");
00787 break;
00788 case AST_CONTROL_BUSY:
00789 strcpy(subclass, "Busy");
00790 break;
00791 case AST_CONTROL_TAKEOFFHOOK:
00792 strcpy(subclass, "Take Off Hook");
00793 break;
00794 case AST_CONTROL_OFFHOOK:
00795 strcpy(subclass, "Line Off Hook");
00796 break;
00797 case AST_CONTROL_CONGESTION:
00798 strcpy(subclass, "Congestion");
00799 break;
00800 case AST_CONTROL_FLASH:
00801 strcpy(subclass, "Flash");
00802 break;
00803 case AST_CONTROL_WINK:
00804 strcpy(subclass, "Wink");
00805 break;
00806 case AST_CONTROL_OPTION:
00807 strcpy(subclass, "Option");
00808 break;
00809 case AST_CONTROL_RADIO_KEY:
00810 strcpy(subclass, "Key Radio");
00811 break;
00812 case AST_CONTROL_RADIO_UNKEY:
00813 strcpy(subclass, "Unkey Radio");
00814 break;
00815 case AST_CONTROL_HOLD:
00816 strcpy(subclass, "Hold");
00817 break;
00818 case AST_CONTROL_UNHOLD:
00819 strcpy(subclass, "Unhold");
00820 break;
00821 case AST_CONTROL_T38:
00822 if (f->datalen != sizeof(enum ast_control_t38)) {
00823 message = "Invalid";
00824 } else {
00825 enum ast_control_t38 state = *((enum ast_control_t38 *) f->data.ptr);
00826 if (state == AST_T38_REQUEST_NEGOTIATE)
00827 message = "Negotiation Requested";
00828 else if (state == AST_T38_REQUEST_TERMINATE)
00829 message = "Negotiation Request Terminated";
00830 else if (state == AST_T38_NEGOTIATED)
00831 message = "Negotiated";
00832 else if (state == AST_T38_TERMINATED)
00833 message = "Terminated";
00834 else if (state == AST_T38_REFUSED)
00835 message = "Refused";
00836 }
00837 snprintf(subclass, sizeof(subclass), "T38/%s", message);
00838 break;
00839 case -1:
00840 strcpy(subclass, "Stop generators");
00841 break;
00842 default:
00843 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
00844 }
00845 break;
00846 case AST_FRAME_NULL:
00847 strcpy(ftype, "Null Frame");
00848 strcpy(subclass, "N/A");
00849 break;
00850 case AST_FRAME_IAX:
00851
00852 strcpy(ftype, "IAX Specific");
00853 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
00854 break;
00855 case AST_FRAME_TEXT:
00856 strcpy(ftype, "Text");
00857 strcpy(subclass, "N/A");
00858 ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
00859 break;
00860 case AST_FRAME_IMAGE:
00861 strcpy(ftype, "Image");
00862 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
00863 break;
00864 case AST_FRAME_HTML:
00865 strcpy(ftype, "HTML");
00866 switch(f->subclass) {
00867 case AST_HTML_URL:
00868 strcpy(subclass, "URL");
00869 ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
00870 break;
00871 case AST_HTML_DATA:
00872 strcpy(subclass, "Data");
00873 break;
00874 case AST_HTML_BEGIN:
00875 strcpy(subclass, "Begin");
00876 break;
00877 case AST_HTML_END:
00878 strcpy(subclass, "End");
00879 break;
00880 case AST_HTML_LDCOMPLETE:
00881 strcpy(subclass, "Load Complete");
00882 break;
00883 case AST_HTML_NOSUPPORT:
00884 strcpy(subclass, "No Support");
00885 break;
00886 case AST_HTML_LINKURL:
00887 strcpy(subclass, "Link URL");
00888 ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
00889 break;
00890 case AST_HTML_UNLINK:
00891 strcpy(subclass, "Unlink");
00892 break;
00893 case AST_HTML_LINKREJECT:
00894 strcpy(subclass, "Link Reject");
00895 break;
00896 default:
00897 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
00898 break;
00899 }
00900 break;
00901 case AST_FRAME_MODEM:
00902 strcpy(ftype, "Modem");
00903 switch (f->subclass) {
00904 case AST_MODEM_T38:
00905 strcpy(subclass, "T.38");
00906 break;
00907 case AST_MODEM_V150:
00908 strcpy(subclass, "V.150");
00909 break;
00910 default:
00911 snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
00912 break;
00913 }
00914 break;
00915 default:
00916 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
00917 }
00918 if (!ast_strlen_zero(moreinfo))
00919 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
00920 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00921 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00922 f->frametype,
00923 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00924 f->subclass,
00925 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
00926 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00927 else
00928 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
00929 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00930 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00931 f->frametype,
00932 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00933 f->subclass,
00934 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00935 }
00936
00937
00938 #ifdef TRACE_FRAMES
00939 static char *show_frame_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00940 {
00941 struct ast_frame *f;
00942 int x=1;
00943
00944 switch (cmd) {
00945 case CLI_INIT:
00946 e->command = "core show frame stats";
00947 e->usage =
00948 "Usage: core show frame stats\n"
00949 " Displays debugging statistics from framer\n";
00950 return NULL;
00951 case CLI_GENERATE:
00952 return NULL;
00953 }
00954
00955 if (a->argc != 4)
00956 return CLI_SHOWUSAGE;
00957 AST_LIST_LOCK(&headerlist);
00958 ast_cli(a->fd, " Framer Statistics \n");
00959 ast_cli(a->fd, "---------------------------\n");
00960 ast_cli(a->fd, "Total allocated headers: %d\n", headers);
00961 ast_cli(a->fd, "Queue Dump:\n");
00962 AST_LIST_TRAVERSE(&headerlist, f, frame_list)
00963 ast_cli(a->fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
00964 AST_LIST_UNLOCK(&headerlist);
00965 return CLI_SUCCESS;
00966 }
00967 #endif
00968
00969
00970 static struct ast_cli_entry my_clis[] = {
00971 AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
00972 AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
00973 #ifdef TRACE_FRAMES
00974 AST_CLI_DEFINE(show_frame_stats, "Shows frame statistics"),
00975 #endif
00976 };
00977
00978 int init_framer(void)
00979 {
00980 ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
00981 return 0;
00982 }
00983
00984 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
00985 {
00986 int x, differential = (int) 'A', mem;
00987 char *from, *to;
00988
00989 if (right) {
00990 from = pref->order;
00991 to = buf;
00992 mem = size;
00993 } else {
00994 to = pref->order;
00995 from = buf;
00996 mem = 32;
00997 }
00998
00999 memset(to, 0, mem);
01000 for (x = 0; x < 32 ; x++) {
01001 if (!from[x])
01002 break;
01003 to[x] = right ? (from[x] + differential) : (from[x] - differential);
01004 }
01005 }
01006
01007 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
01008 {
01009 int x, codec;
01010 size_t total_len, slen;
01011 char *formatname;
01012
01013 memset(buf,0,size);
01014 total_len = size;
01015 buf[0] = '(';
01016 total_len--;
01017 for(x = 0; x < 32 ; x++) {
01018 if (total_len <= 0)
01019 break;
01020 if (!(codec = ast_codec_pref_index(pref,x)))
01021 break;
01022 if ((formatname = ast_getformatname(codec))) {
01023 slen = strlen(formatname);
01024 if (slen > total_len)
01025 break;
01026 strncat(buf, formatname, total_len - 1);
01027 total_len -= slen;
01028 }
01029 if (total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
01030 strncat(buf, "|", total_len - 1);
01031 total_len--;
01032 }
01033 }
01034 if (total_len) {
01035 strncat(buf, ")", total_len - 1);
01036 total_len--;
01037 }
01038
01039 return size - total_len;
01040 }
01041
01042 int ast_codec_pref_index(struct ast_codec_pref *pref, int idx)
01043 {
01044 int slot = 0;
01045
01046 if ((idx >= 0) && (idx < sizeof(pref->order))) {
01047 slot = pref->order[idx];
01048 }
01049
01050 return slot ? AST_FORMAT_LIST[slot - 1].bits : 0;
01051 }
01052
01053
01054 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
01055 {
01056 struct ast_codec_pref oldorder;
01057 int x, y = 0;
01058 int slot;
01059 int size;
01060
01061 if (!pref->order[0])
01062 return;
01063
01064 memcpy(&oldorder, pref, sizeof(oldorder));
01065 memset(pref, 0, sizeof(*pref));
01066
01067 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01068 slot = oldorder.order[x];
01069 size = oldorder.framing[x];
01070 if (! slot)
01071 break;
01072 if (AST_FORMAT_LIST[slot-1].bits != format) {
01073 pref->order[y] = slot;
01074 pref->framing[y++] = size;
01075 }
01076 }
01077
01078 }
01079
01080
01081 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
01082 {
01083 int x, newindex = 0;
01084
01085 ast_codec_pref_remove(pref, format);
01086
01087 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01088 if (AST_FORMAT_LIST[x].bits == format) {
01089 newindex = x + 1;
01090 break;
01091 }
01092 }
01093
01094 if (newindex) {
01095 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01096 if (!pref->order[x]) {
01097 pref->order[x] = newindex;
01098 break;
01099 }
01100 }
01101 }
01102
01103 return x;
01104 }
01105
01106
01107 void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing)
01108 {
01109 int x, newindex = 0;
01110
01111
01112 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01113 if (AST_FORMAT_LIST[x].bits == format) {
01114 newindex = x + 1;
01115 break;
01116 }
01117 }
01118
01119 if (!newindex)
01120 return;
01121
01122
01123 for (x = 0; x < 32; x++) {
01124 if (!pref->order[x] || pref->order[x] == newindex)
01125 break;
01126 }
01127
01128 if (only_if_existing && !pref->order[x])
01129 return;
01130
01131
01132
01133 for (; x > 0; x--) {
01134 pref->order[x] = pref->order[x - 1];
01135 pref->framing[x] = pref->framing[x - 1];
01136 }
01137
01138
01139 pref->order[0] = newindex;
01140 pref->framing[0] = 0;
01141 }
01142
01143
01144 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
01145 {
01146 int x, idx = -1;
01147
01148 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01149 if (AST_FORMAT_LIST[x].bits == format) {
01150 idx = x;
01151 break;
01152 }
01153 }
01154
01155 if (idx < 0)
01156 return -1;
01157
01158
01159 if (!framems)
01160 framems = AST_FORMAT_LIST[idx].def_ms;
01161
01162 if (AST_FORMAT_LIST[idx].inc_ms && framems % AST_FORMAT_LIST[idx].inc_ms)
01163 framems -= framems % AST_FORMAT_LIST[idx].inc_ms;
01164
01165 if (framems < AST_FORMAT_LIST[idx].min_ms)
01166 framems = AST_FORMAT_LIST[idx].min_ms;
01167
01168 if (framems > AST_FORMAT_LIST[idx].max_ms)
01169 framems = AST_FORMAT_LIST[idx].max_ms;
01170
01171 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01172 if (pref->order[x] == (idx + 1)) {
01173 pref->framing[x] = framems;
01174 break;
01175 }
01176 }
01177
01178 return x;
01179 }
01180
01181
01182 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
01183 {
01184 int x, idx = -1, framems = 0;
01185 struct ast_format_list fmt = { 0, };
01186
01187 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01188 if (AST_FORMAT_LIST[x].bits == format) {
01189 fmt = AST_FORMAT_LIST[x];
01190 idx = x;
01191 break;
01192 }
01193 }
01194
01195 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01196 if (pref->order[x] == (idx + 1)) {
01197 framems = pref->framing[x];
01198 break;
01199 }
01200 }
01201
01202
01203 if (!framems)
01204 framems = AST_FORMAT_LIST[idx].def_ms;
01205
01206 if (AST_FORMAT_LIST[idx].inc_ms && framems % AST_FORMAT_LIST[idx].inc_ms)
01207 framems -= framems % AST_FORMAT_LIST[idx].inc_ms;
01208
01209 if (framems < AST_FORMAT_LIST[idx].min_ms)
01210 framems = AST_FORMAT_LIST[idx].min_ms;
01211
01212 if (framems > AST_FORMAT_LIST[idx].max_ms)
01213 framems = AST_FORMAT_LIST[idx].max_ms;
01214
01215 fmt.cur_ms = framems;
01216
01217 return fmt;
01218 }
01219
01220
01221 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
01222 {
01223 int x, ret = 0, slot;
01224
01225 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01226 slot = pref->order[x];
01227
01228 if (!slot)
01229 break;
01230 if (formats & AST_FORMAT_LIST[slot-1].bits) {
01231 ret = AST_FORMAT_LIST[slot-1].bits;
01232 break;
01233 }
01234 }
01235 if (ret & AST_FORMAT_AUDIO_MASK)
01236 return ret;
01237
01238 ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
01239
01240 return find_best ? ast_best_codec(formats) : 0;
01241 }
01242
01243 int ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
01244 {
01245 int errors = 0;
01246 char *parse = NULL, *this = NULL, *psize = NULL;
01247 int format = 0, framems = 0;
01248
01249 parse = ast_strdupa(list);
01250 while ((this = strsep(&parse, ","))) {
01251 framems = 0;
01252 if ((psize = strrchr(this, ':'))) {
01253 *psize++ = '\0';
01254 ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
01255 framems = atoi(psize);
01256 if (framems < 0) {
01257 framems = 0;
01258 errors++;
01259 ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
01260 }
01261 }
01262 if (!(format = ast_getformatbyname(this))) {
01263 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
01264 errors++;
01265 continue;
01266 }
01267
01268 if (mask) {
01269 if (allowing)
01270 *mask |= format;
01271 else
01272 *mask &= ~format;
01273 }
01274
01275
01276
01277
01278 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
01279 if (strcasecmp(this, "all")) {
01280 if (allowing) {
01281 ast_codec_pref_append(pref, format);
01282 ast_codec_pref_setsize(pref, format, framems);
01283 }
01284 else
01285 ast_codec_pref_remove(pref, format);
01286 } else if (!allowing) {
01287 memset(pref, 0, sizeof(*pref));
01288 }
01289 }
01290 }
01291 return errors;
01292 }
01293
01294 static int g723_len(unsigned char buf)
01295 {
01296 enum frame_type type = buf & TYPE_MASK;
01297
01298 switch(type) {
01299 case TYPE_DONTSEND:
01300 return 0;
01301 break;
01302 case TYPE_SILENCE:
01303 return 4;
01304 break;
01305 case TYPE_HIGH:
01306 return 24;
01307 break;
01308 case TYPE_LOW:
01309 return 20;
01310 break;
01311 default:
01312 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
01313 }
01314 return -1;
01315 }
01316
01317 static int g723_samples(unsigned char *buf, int maxlen)
01318 {
01319 int pos = 0;
01320 int samples = 0;
01321 int res;
01322 while(pos < maxlen) {
01323 res = g723_len(buf[pos]);
01324 if (res <= 0)
01325 break;
01326 samples += 240;
01327 pos += res;
01328 }
01329 return samples;
01330 }
01331
01332 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
01333 {
01334 int byte = bit / 8;
01335 int rem = 8 - (bit % 8);
01336 unsigned char ret = 0;
01337
01338 if (n <= 0 || n > 8)
01339 return 0;
01340
01341 if (rem < n) {
01342 ret = (data[byte] << (n - rem));
01343 ret |= (data[byte + 1] >> (8 - n + rem));
01344 } else {
01345 ret = (data[byte] >> (rem - n));
01346 }
01347
01348 return (ret & (0xff >> (8 - n)));
01349 }
01350
01351 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
01352 {
01353 static int SpeexWBSubModeSz[] = {
01354 0, 36, 112, 192,
01355 352, 0, 0, 0 };
01356 int off = bit;
01357 unsigned char c;
01358
01359
01360 if (((len * 8 - off) >= 5) &&
01361 get_n_bits_at(data, 1, off)) {
01362 c = get_n_bits_at(data, 3, off + 1);
01363 off += SpeexWBSubModeSz[c];
01364
01365 if (((len * 8 - off) >= 5) &&
01366 get_n_bits_at(data, 1, off)) {
01367 c = get_n_bits_at(data, 3, off + 1);
01368 off += SpeexWBSubModeSz[c];
01369
01370 if (((len * 8 - off) >= 5) &&
01371 get_n_bits_at(data, 1, off)) {
01372 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
01373 return -1;
01374 }
01375 }
01376
01377 }
01378 return off - bit;
01379 }
01380
01381 static int speex_samples(unsigned char *data, int len)
01382 {
01383 static int SpeexSubModeSz[] = {
01384 5, 43, 119, 160,
01385 220, 300, 364, 492,
01386 79, 0, 0, 0,
01387 0, 0, 0, 0 };
01388 static int SpeexInBandSz[] = {
01389 1, 1, 4, 4,
01390 4, 4, 4, 4,
01391 8, 8, 16, 16,
01392 32, 32, 64, 64 };
01393 int bit = 0;
01394 int cnt = 0;
01395 int off;
01396 unsigned char c;
01397
01398 while ((len * 8 - bit) >= 5) {
01399
01400 off = speex_get_wb_sz_at(data, len, bit);
01401 if (off < 0) {
01402 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
01403 break;
01404 }
01405 bit += off;
01406
01407 if ((len * 8 - bit) < 5) {
01408 ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
01409 break;
01410 }
01411
01412
01413 c = get_n_bits_at(data, 5, bit);
01414 bit += 5;
01415
01416 if (c == 15) {
01417
01418 break;
01419 } else if (c == 14) {
01420
01421 c = get_n_bits_at(data, 4, bit);
01422 bit += 4;
01423 bit += SpeexInBandSz[c];
01424 } else if (c == 13) {
01425
01426 c = get_n_bits_at(data, 5, bit);
01427 bit += 5;
01428 bit += c * 8;
01429 } else if (c > 8) {
01430
01431 break;
01432 } else {
01433
01434 bit += SpeexSubModeSz[c] - 5;
01435 cnt += 160;
01436 }
01437 }
01438 return cnt;
01439 }
01440
01441 int ast_codec_get_samples(struct ast_frame *f)
01442 {
01443 int samples=0;
01444 switch(f->subclass) {
01445 case AST_FORMAT_SPEEX:
01446 samples = speex_samples(f->data.ptr, f->datalen);
01447 break;
01448 case AST_FORMAT_G723_1:
01449 samples = g723_samples(f->data.ptr, f->datalen);
01450 break;
01451 case AST_FORMAT_ILBC:
01452 samples = 240 * (f->datalen / 50);
01453 break;
01454 case AST_FORMAT_GSM:
01455 samples = 160 * (f->datalen / 33);
01456 break;
01457 case AST_FORMAT_G729A:
01458 samples = f->datalen * 8;
01459 break;
01460 case AST_FORMAT_SLINEAR:
01461 case AST_FORMAT_SLINEAR16:
01462 samples = f->datalen / 2;
01463 break;
01464 case AST_FORMAT_LPC10:
01465
01466 samples = 22 * 8;
01467 samples += (((char *)(f->data.ptr))[7] & 0x1) * 8;
01468 break;
01469 case AST_FORMAT_ULAW:
01470 case AST_FORMAT_ALAW:
01471 samples = f->datalen;
01472 break;
01473 case AST_FORMAT_G722:
01474 case AST_FORMAT_ADPCM:
01475 case AST_FORMAT_G726:
01476 case AST_FORMAT_G726_AAL2:
01477 samples = f->datalen * 2;
01478 break;
01479 default:
01480 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
01481 }
01482 return samples;
01483 }
01484
01485 int ast_codec_get_len(int format, int samples)
01486 {
01487 int len = 0;
01488
01489
01490 switch(format) {
01491 case AST_FORMAT_G723_1:
01492 len = (samples / 240) * 20;
01493 break;
01494 case AST_FORMAT_ILBC:
01495 len = (samples / 240) * 50;
01496 break;
01497 case AST_FORMAT_GSM:
01498 len = (samples / 160) * 33;
01499 break;
01500 case AST_FORMAT_G729A:
01501 len = samples / 8;
01502 break;
01503 case AST_FORMAT_SLINEAR:
01504 case AST_FORMAT_SLINEAR16:
01505 len = samples * 2;
01506 break;
01507 case AST_FORMAT_ULAW:
01508 case AST_FORMAT_ALAW:
01509 len = samples;
01510 break;
01511 case AST_FORMAT_G722:
01512 case AST_FORMAT_ADPCM:
01513 case AST_FORMAT_G726:
01514 case AST_FORMAT_G726_AAL2:
01515 len = samples / 2;
01516 break;
01517 default:
01518 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
01519 }
01520
01521 return len;
01522 }
01523
01524 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
01525 {
01526 int count;
01527 short *fdata = f->data.ptr;
01528 short adjust_value = abs(adjustment);
01529
01530 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
01531 return -1;
01532
01533 if (!adjustment)
01534 return 0;
01535
01536 for (count = 0; count < f->samples; count++) {
01537 if (adjustment > 0) {
01538 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
01539 } else if (adjustment < 0) {
01540 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
01541 }
01542 }
01543
01544 return 0;
01545 }
01546
01547 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
01548 {
01549 int count;
01550 short *data1, *data2;
01551
01552 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
01553 return -1;
01554
01555 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
01556 return -1;
01557
01558 if (f1->samples != f2->samples)
01559 return -1;
01560
01561 for (count = 0, data1 = f1->data.ptr, data2 = f2->data.ptr;
01562 count < f1->samples;
01563 count++, data1++, data2++)
01564 ast_slinear_saturated_add(data1, data2);
01565
01566 return 0;
01567 }