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