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