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