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