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: 377712 $")
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 static void framer_shutdown(void)
00991 {
00992 ast_cli_unregister_multiple(my_clis, ARRAY_LEN(my_clis));
00993 }
00994
00995 int init_framer(void)
00996 {
00997 ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis));
00998 ast_register_atexit(framer_shutdown);
00999 return 0;
01000 }
01001
01002 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
01003 {
01004 int x, differential = (int) 'A', mem;
01005 char *from, *to;
01006
01007 if (right) {
01008 from = pref->order;
01009 to = buf;
01010 mem = size;
01011 } else {
01012 to = pref->order;
01013 from = buf;
01014 mem = sizeof(format_t) * 8;
01015 }
01016
01017 memset(to, 0, mem);
01018 for (x = 0; x < sizeof(format_t) * 8; x++) {
01019 if (!from[x])
01020 break;
01021 to[x] = right ? (from[x] + differential) : (from[x] - differential);
01022 }
01023 }
01024
01025 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
01026 {
01027 int x;
01028 format_t codec;
01029 size_t total_len, slen;
01030 char *formatname;
01031
01032 memset(buf, 0, size);
01033 total_len = size;
01034 buf[0] = '(';
01035 total_len--;
01036 for (x = 0; x < sizeof(format_t) * 8; x++) {
01037 if (total_len <= 0)
01038 break;
01039 if (!(codec = ast_codec_pref_index(pref,x)))
01040 break;
01041 if ((formatname = ast_getformatname(codec))) {
01042 slen = strlen(formatname);
01043 if (slen > total_len)
01044 break;
01045 strncat(buf, formatname, total_len - 1);
01046 total_len -= slen;
01047 }
01048 if (total_len && x < sizeof(format_t) * 8 - 1 && ast_codec_pref_index(pref, x + 1)) {
01049 strncat(buf, "|", total_len - 1);
01050 total_len--;
01051 }
01052 }
01053 if (total_len) {
01054 strncat(buf, ")", total_len - 1);
01055 total_len--;
01056 }
01057
01058 return size - total_len;
01059 }
01060
01061 format_t ast_codec_pref_index(struct ast_codec_pref *pref, int idx)
01062 {
01063 int slot = 0;
01064
01065 if ((idx >= 0) && (idx < sizeof(pref->order))) {
01066 slot = pref->order[idx];
01067 }
01068
01069 return slot ? AST_FORMAT_LIST[slot - 1].bits : 0;
01070 }
01071
01072
01073 void ast_codec_pref_remove(struct ast_codec_pref *pref, format_t format)
01074 {
01075 struct ast_codec_pref oldorder;
01076 int x, y = 0;
01077 int slot;
01078 int size;
01079
01080 if (!pref->order[0])
01081 return;
01082
01083 memcpy(&oldorder, pref, sizeof(oldorder));
01084 memset(pref, 0, sizeof(*pref));
01085
01086 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01087 slot = oldorder.order[x];
01088 size = oldorder.framing[x];
01089 if (! slot)
01090 break;
01091 if (AST_FORMAT_LIST[slot-1].bits != format) {
01092 pref->order[y] = slot;
01093 pref->framing[y++] = size;
01094 }
01095 }
01096 }
01097
01098
01099 int ast_codec_pref_append(struct ast_codec_pref *pref, format_t format)
01100 {
01101 int x, newindex = 0;
01102
01103 ast_codec_pref_remove(pref, format);
01104
01105 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01106 if (AST_FORMAT_LIST[x].bits == format) {
01107 newindex = x + 1;
01108 break;
01109 }
01110 }
01111
01112 if (newindex) {
01113 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01114 if (!pref->order[x]) {
01115 pref->order[x] = newindex;
01116 break;
01117 }
01118 }
01119 }
01120
01121 return x;
01122 }
01123
01124
01125 void ast_codec_pref_prepend(struct ast_codec_pref *pref, format_t format, int only_if_existing)
01126 {
01127 int x, newindex = 0;
01128
01129
01130 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01131 if (AST_FORMAT_LIST[x].bits == format) {
01132 newindex = x + 1;
01133 break;
01134 }
01135 }
01136
01137 if (!newindex)
01138 return;
01139
01140
01141 for (x = 0; x < sizeof(format_t) * 8; x++) {
01142 if (!pref->order[x] || pref->order[x] == newindex)
01143 break;
01144 }
01145
01146
01147 if (x == sizeof(format_t) * 8) {
01148 --x;
01149 }
01150
01151 if (only_if_existing && !pref->order[x])
01152 return;
01153
01154
01155
01156 for (; x > 0; x--) {
01157 pref->order[x] = pref->order[x - 1];
01158 pref->framing[x] = pref->framing[x - 1];
01159 }
01160
01161
01162 pref->order[0] = newindex;
01163 pref->framing[0] = 0;
01164 }
01165
01166
01167 int ast_codec_pref_setsize(struct ast_codec_pref *pref, format_t format, int framems)
01168 {
01169 int x, idx = -1;
01170
01171 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01172 if (AST_FORMAT_LIST[x].bits == format) {
01173 idx = x;
01174 break;
01175 }
01176 }
01177
01178 if (idx < 0)
01179 return -1;
01180
01181
01182 if (!framems)
01183 framems = AST_FORMAT_LIST[idx].def_ms;
01184
01185 if (AST_FORMAT_LIST[idx].inc_ms && framems % AST_FORMAT_LIST[idx].inc_ms)
01186 framems -= framems % AST_FORMAT_LIST[idx].inc_ms;
01187
01188 if (framems < AST_FORMAT_LIST[idx].min_ms)
01189 framems = AST_FORMAT_LIST[idx].min_ms;
01190
01191 if (framems > AST_FORMAT_LIST[idx].max_ms)
01192 framems = AST_FORMAT_LIST[idx].max_ms;
01193
01194 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01195 if (pref->order[x] == (idx + 1)) {
01196 pref->framing[x] = framems;
01197 break;
01198 }
01199 }
01200
01201 return x;
01202 }
01203
01204
01205 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, format_t format)
01206 {
01207 int x, idx = -1, framems = 0;
01208 struct ast_format_list fmt = { 0, };
01209
01210 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01211 if (AST_FORMAT_LIST[x].bits == format) {
01212 fmt = AST_FORMAT_LIST[x];
01213 idx = x;
01214 break;
01215 }
01216 }
01217
01218 if (idx < 0) {
01219 ast_log(AST_LOG_WARNING, "Format %s unknown; unable to get preferred codec packet size\n", ast_getformatname(format));
01220 return fmt;
01221 }
01222
01223 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01224 if (pref->order[x] == (idx + 1)) {
01225 framems = pref->framing[x];
01226 break;
01227 }
01228 }
01229
01230
01231 if (!framems)
01232 framems = AST_FORMAT_LIST[idx].def_ms;
01233
01234 if (AST_FORMAT_LIST[idx].inc_ms && framems % AST_FORMAT_LIST[idx].inc_ms)
01235 framems -= framems % AST_FORMAT_LIST[idx].inc_ms;
01236
01237 if (framems < AST_FORMAT_LIST[idx].min_ms)
01238 framems = AST_FORMAT_LIST[idx].min_ms;
01239
01240 if (framems > AST_FORMAT_LIST[idx].max_ms)
01241 framems = AST_FORMAT_LIST[idx].max_ms;
01242
01243 fmt.cur_ms = framems;
01244
01245 return fmt;
01246 }
01247
01248
01249 format_t ast_codec_choose(struct ast_codec_pref *pref, format_t formats, int find_best)
01250 {
01251 int x, slot;
01252 format_t ret = 0;
01253
01254 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01255 slot = pref->order[x];
01256
01257 if (!slot)
01258 break;
01259 if (formats & AST_FORMAT_LIST[slot-1].bits) {
01260 ret = AST_FORMAT_LIST[slot-1].bits;
01261 break;
01262 }
01263 }
01264 if (ret & AST_FORMAT_AUDIO_MASK)
01265 return ret;
01266
01267 ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
01268
01269 return find_best ? ast_best_codec(formats) : 0;
01270 }
01271
01272 int ast_parse_allow_disallow(struct ast_codec_pref *pref, format_t *mask, const char *list, int allowing)
01273 {
01274 int errors = 0, framems = 0;
01275 char *parse = NULL, *this = NULL, *psize = NULL;
01276 format_t format = 0;
01277
01278 parse = ast_strdupa(list);
01279 while ((this = strsep(&parse, ","))) {
01280 framems = 0;
01281 if ((psize = strrchr(this, ':'))) {
01282 *psize++ = '\0';
01283 ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
01284 framems = atoi(psize);
01285 if (framems < 0) {
01286 framems = 0;
01287 errors++;
01288 ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
01289 }
01290 }
01291 if (!(format = ast_getformatbyname(this))) {
01292 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
01293 errors++;
01294 continue;
01295 }
01296
01297 if (mask) {
01298 if (allowing)
01299 *mask |= format;
01300 else
01301 *mask &= ~format;
01302 }
01303
01304
01305
01306
01307 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
01308 if (strcasecmp(this, "all")) {
01309 if (allowing) {
01310 ast_codec_pref_append(pref, format);
01311 ast_codec_pref_setsize(pref, format, framems);
01312 }
01313 else
01314 ast_codec_pref_remove(pref, format);
01315 } else if (!allowing) {
01316 memset(pref, 0, sizeof(*pref));
01317 }
01318 }
01319 }
01320 return errors;
01321 }
01322
01323 static int g723_len(unsigned char buf)
01324 {
01325 enum frame_type type = buf & TYPE_MASK;
01326
01327 switch(type) {
01328 case TYPE_DONTSEND:
01329 return 0;
01330 break;
01331 case TYPE_SILENCE:
01332 return 4;
01333 break;
01334 case TYPE_HIGH:
01335 return 24;
01336 break;
01337 case TYPE_LOW:
01338 return 20;
01339 break;
01340 default:
01341 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
01342 }
01343 return -1;
01344 }
01345
01346 static int g723_samples(unsigned char *buf, int maxlen)
01347 {
01348 int pos = 0;
01349 int samples = 0;
01350 int res;
01351 while(pos < maxlen) {
01352 res = g723_len(buf[pos]);
01353 if (res <= 0)
01354 break;
01355 samples += 240;
01356 pos += res;
01357 }
01358 return samples;
01359 }
01360
01361 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
01362 {
01363 int byte = bit / 8;
01364 int rem = 8 - (bit % 8);
01365 unsigned char ret = 0;
01366
01367 if (n <= 0 || n > 8)
01368 return 0;
01369
01370 if (rem < n) {
01371 ret = (data[byte] << (n - rem));
01372 ret |= (data[byte + 1] >> (8 - n + rem));
01373 } else {
01374 ret = (data[byte] >> (rem - n));
01375 }
01376
01377 return (ret & (0xff >> (8 - n)));
01378 }
01379
01380 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
01381 {
01382 static const int SpeexWBSubModeSz[] = {
01383 4, 36, 112, 192,
01384 352, 0, 0, 0 };
01385 int off = bit;
01386 unsigned char c;
01387
01388
01389 if (((len * 8 - off) >= 5) &&
01390 get_n_bits_at(data, 1, off)) {
01391 c = get_n_bits_at(data, 3, off + 1);
01392 off += SpeexWBSubModeSz[c];
01393
01394 if (((len * 8 - off) >= 5) &&
01395 get_n_bits_at(data, 1, off)) {
01396 c = get_n_bits_at(data, 3, off + 1);
01397 off += SpeexWBSubModeSz[c];
01398
01399 if (((len * 8 - off) >= 5) &&
01400 get_n_bits_at(data, 1, off)) {
01401 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
01402 return -1;
01403 }
01404 }
01405
01406 }
01407 return off - bit;
01408 }
01409
01410 static int speex_samples(unsigned char *data, int len)
01411 {
01412 static const int SpeexSubModeSz[] = {
01413 5, 43, 119, 160,
01414 220, 300, 364, 492,
01415 79, 0, 0, 0,
01416 0, 0, 0, 0 };
01417 static const int SpeexInBandSz[] = {
01418 1, 1, 4, 4,
01419 4, 4, 4, 4,
01420 8, 8, 16, 16,
01421 32, 32, 64, 64 };
01422 int bit = 0;
01423 int cnt = 0;
01424 int off;
01425 unsigned char c;
01426
01427 while ((len * 8 - bit) >= 5) {
01428
01429 off = speex_get_wb_sz_at(data, len, bit);
01430 if (off < 0) {
01431 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
01432 break;
01433 }
01434 bit += off;
01435
01436 if ((len * 8 - bit) < 5)
01437 break;
01438
01439
01440 c = get_n_bits_at(data, 5, bit);
01441 bit += 5;
01442
01443 if (c == 15) {
01444
01445 break;
01446 } else if (c == 14) {
01447
01448 c = get_n_bits_at(data, 4, bit);
01449 bit += 4;
01450 bit += SpeexInBandSz[c];
01451 } else if (c == 13) {
01452
01453 c = get_n_bits_at(data, 4, bit);
01454 bit += 4;
01455
01456 bit += 5 + c * 8;
01457 } else if (c > 8) {
01458
01459 ast_log(LOG_WARNING, "Unknown speex control frame %d\n", c);
01460 break;
01461 } else {
01462
01463 bit += SpeexSubModeSz[c] - 5;
01464 cnt += 160;
01465 }
01466 }
01467 return cnt;
01468 }
01469
01470 int ast_codec_get_samples(struct ast_frame *f)
01471 {
01472 int samples = 0;
01473 char tmp[64];
01474
01475 switch (f->subclass.codec) {
01476 case AST_FORMAT_SPEEX:
01477 samples = speex_samples(f->data.ptr, f->datalen);
01478 break;
01479 case AST_FORMAT_SPEEX16:
01480 samples = 2 * speex_samples(f->data.ptr, f->datalen);
01481 break;
01482 case AST_FORMAT_G723_1:
01483 samples = g723_samples(f->data.ptr, f->datalen);
01484 break;
01485 case AST_FORMAT_ILBC:
01486 samples = 240 * (f->datalen / 50);
01487 break;
01488 case AST_FORMAT_GSM:
01489 samples = 160 * (f->datalen / 33);
01490 break;
01491 case AST_FORMAT_G729A:
01492 samples = f->datalen * 8;
01493 break;
01494 case AST_FORMAT_SLINEAR:
01495 case AST_FORMAT_SLINEAR16:
01496 samples = f->datalen / 2;
01497 break;
01498 case AST_FORMAT_LPC10:
01499
01500 samples = 22 * 8;
01501 samples += (((char *)(f->data.ptr))[7] & 0x1) * 8;
01502 break;
01503 case AST_FORMAT_ULAW:
01504 case AST_FORMAT_ALAW:
01505 case AST_FORMAT_TESTLAW:
01506 samples = f->datalen;
01507 break;
01508 case AST_FORMAT_G722:
01509 case AST_FORMAT_ADPCM:
01510 case AST_FORMAT_G726:
01511 case AST_FORMAT_G726_AAL2:
01512 samples = f->datalen * 2;
01513 break;
01514 case AST_FORMAT_SIREN7:
01515
01516 samples = f->datalen * (16000 / 4000);
01517 break;
01518 case AST_FORMAT_SIREN14:
01519
01520 samples = (int) f->datalen * ((float) 32000 / 6000);
01521 break;
01522 case AST_FORMAT_G719:
01523
01524 samples = (int) f->datalen * ((float) 48000 / 8000);
01525 break;
01526 default:
01527 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), f->subclass.codec));
01528 }
01529 return samples;
01530 }
01531
01532 int ast_codec_get_len(format_t format, int samples)
01533 {
01534 int len = 0;
01535
01536
01537 switch(format) {
01538 case AST_FORMAT_G723_1:
01539 len = (samples / 240) * 20;
01540 break;
01541 case AST_FORMAT_ILBC:
01542 len = (samples / 240) * 50;
01543 break;
01544 case AST_FORMAT_GSM:
01545 len = (samples / 160) * 33;
01546 break;
01547 case AST_FORMAT_G729A:
01548 len = samples / 8;
01549 break;
01550 case AST_FORMAT_SLINEAR:
01551 case AST_FORMAT_SLINEAR16:
01552 len = samples * 2;
01553 break;
01554 case AST_FORMAT_ULAW:
01555 case AST_FORMAT_ALAW:
01556 case AST_FORMAT_TESTLAW:
01557 len = samples;
01558 break;
01559 case AST_FORMAT_G722:
01560 case AST_FORMAT_ADPCM:
01561 case AST_FORMAT_G726:
01562 case AST_FORMAT_G726_AAL2:
01563 len = samples / 2;
01564 break;
01565 case AST_FORMAT_SIREN7:
01566
01567 len = samples / (16000 / 4000);
01568 break;
01569 case AST_FORMAT_SIREN14:
01570
01571 len = (int) samples / ((float) 32000 / 6000);
01572 break;
01573 case AST_FORMAT_G719:
01574
01575 len = (int) samples / ((float) 48000 / 8000);
01576 break;
01577 default:
01578 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
01579 }
01580
01581 return len;
01582 }
01583
01584 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
01585 {
01586 int count;
01587 short *fdata = f->data.ptr;
01588 short adjust_value = abs(adjustment);
01589
01590 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass.codec != AST_FORMAT_SLINEAR))
01591 return -1;
01592
01593 if (!adjustment)
01594 return 0;
01595
01596 for (count = 0; count < f->samples; count++) {
01597 if (adjustment > 0) {
01598 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
01599 } else if (adjustment < 0) {
01600 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
01601 }
01602 }
01603
01604 return 0;
01605 }
01606
01607 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
01608 {
01609 int count;
01610 short *data1, *data2;
01611
01612 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass.codec != AST_FORMAT_SLINEAR))
01613 return -1;
01614
01615 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass.codec != AST_FORMAT_SLINEAR))
01616 return -1;
01617
01618 if (f1->samples != f2->samples)
01619 return -1;
01620
01621 for (count = 0, data1 = f1->data.ptr, data2 = f2->data.ptr;
01622 count < f1->samples;
01623 count++, data1++, data2++)
01624 ast_slinear_saturated_add(data1, data2);
01625
01626 return 0;
01627 }
01628
01629 int ast_frame_clear(struct ast_frame *frame)
01630 {
01631 struct ast_frame *next;
01632
01633 for (next = AST_LIST_NEXT(frame, frame_list);
01634 frame;
01635 frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
01636 memset(frame->data.ptr, 0, frame->datalen);
01637 }
01638 return 0;
01639 }