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: 224935 $")
00029
00030 #include "asterisk/_private.h"
00031 #include "asterisk/lock.h"
00032 #include "asterisk/frame.h"
00033 #include "asterisk/channel.h"
00034 #include "asterisk/cli.h"
00035 #include "asterisk/term.h"
00036 #include "asterisk/utils.h"
00037 #include "asterisk/threadstorage.h"
00038 #include "asterisk/linkedlists.h"
00039 #include "asterisk/translate.h"
00040 #include "asterisk/dsp.h"
00041 #include "asterisk/file.h"
00042
00043 #if !defined(LOW_MEMORY)
00044 static void frame_cache_cleanup(void *data);
00045
00046
00047 AST_THREADSTORAGE_CUSTOM(frame_cache, NULL, frame_cache_cleanup);
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #define FRAME_CACHE_MAX_SIZE 10
00059
00060
00061
00062 AST_LIST_HEAD_NOLOCK(ast_frames, ast_frame);
00063
00064 struct ast_frame_cache {
00065 struct ast_frames list;
00066 size_t size;
00067 };
00068 #endif
00069
00070 #define SMOOTHER_SIZE 8000
00071
00072 enum frame_type {
00073 TYPE_HIGH,
00074 TYPE_LOW,
00075 TYPE_SILENCE,
00076 TYPE_DONTSEND
00077 };
00078
00079 #define TYPE_MASK 0x3
00080
00081 struct ast_smoother {
00082 int size;
00083 int format;
00084 int flags;
00085 float samplesperbyte;
00086 unsigned int opt_needs_swap:1;
00087 struct ast_frame f;
00088 struct timeval delivery;
00089 char data[SMOOTHER_SIZE];
00090 char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
00091 struct ast_frame *opt;
00092 int len;
00093 };
00094
00095
00096 static struct ast_format_list AST_FORMAT_LIST[] = {
00097 { AST_FORMAT_G723_1 , "g723", 8000, "G.723.1", 20, 30, 300, 30, 30 },
00098 { AST_FORMAT_GSM, "gsm", 8000, "GSM", 33, 20, 300, 20, 20 },
00099 { AST_FORMAT_ULAW, "ulaw", 8000, "G.711 u-law", 80, 10, 150, 10, 20 },
00100 { AST_FORMAT_ALAW, "alaw", 8000, "G.711 A-law", 80, 10, 150, 10, 20 },
00101 { AST_FORMAT_G726, "g726", 8000, "G.726 RFC3551", 40, 10, 300, 10, 20 },
00102 { AST_FORMAT_ADPCM, "adpcm" , 8000, "ADPCM", 40, 10, 300, 10, 20 },
00103 { AST_FORMAT_SLINEAR, "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE },
00104 { AST_FORMAT_LPC10, "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20 },
00105 { AST_FORMAT_G729A, "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 },
00106 { AST_FORMAT_SPEEX, "speex", 8000, "SpeeX", 10, 10, 60, 10, 20 },
00107 { AST_FORMAT_ILBC, "ilbc", 8000, "iLBC", 50, 30, 30, 30, 30 },
00108 { AST_FORMAT_G726_AAL2, "g726aal2", 8000, "G.726 AAL2", 40, 10, 300, 10, 20 },
00109 { AST_FORMAT_G722, "g722", 16000, "G722", 80, 10, 150, 10, 20 },
00110 { AST_FORMAT_SLINEAR16, "slin16", 16000, "16 bit Signed Linear PCM (16kHz)", 320, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE },
00111 { AST_FORMAT_JPEG, "jpeg", 0, "JPEG image"},
00112 { AST_FORMAT_PNG, "png", 0, "PNG image"},
00113 { AST_FORMAT_H261, "h261", 0, "H.261 Video" },
00114 { AST_FORMAT_H263, "h263", 0, "H.263 Video" },
00115 { AST_FORMAT_H263_PLUS, "h263p", 0, "H.263+ Video" },
00116 { AST_FORMAT_H264, "h264", 0, "H.264 Video" },
00117 { AST_FORMAT_MP4_VIDEO, "mpeg4", 0, "MPEG4 Video" },
00118 { AST_FORMAT_T140RED, "red", 1, "T.140 Realtime Text with redundancy"},
00119 { AST_FORMAT_T140, "t140", 0, "Passthrough T.140 Realtime Text" },
00120 };
00121
00122 struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
00123
00124 static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
00125 {
00126 if (s->flags & AST_SMOOTHER_FLAG_G729) {
00127 if (s->len % 10) {
00128 ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
00129 return 0;
00130 }
00131 }
00132 if (swap) {
00133 ast_swapcopy_samples(s->data + s->len, f->data.ptr, f->samples);
00134 } else {
00135 memcpy(s->data + s->len, f->data.ptr, f->datalen);
00136 }
00137
00138 if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) {
00139 s->delivery = f->delivery;
00140 }
00141 s->len += f->datalen;
00142
00143 return 0;
00144 }
00145
00146 void ast_smoother_reset(struct ast_smoother *s, int bytes)
00147 {
00148 memset(s, 0, sizeof(*s));
00149 s->size = bytes;
00150 }
00151
00152 void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
00153 {
00154
00155 if (s->size == bytes) {
00156 return;
00157 }
00158
00159 s->size = bytes;
00160
00161
00162
00163 if (!s->opt) {
00164 return;
00165 }
00166
00167
00168
00169
00170 smoother_frame_feed(s, s->opt, s->opt_needs_swap);
00171 s->opt = NULL;
00172 }
00173
00174 struct ast_smoother *ast_smoother_new(int size)
00175 {
00176 struct ast_smoother *s;
00177 if (size < 1)
00178 return NULL;
00179 if ((s = ast_malloc(sizeof(*s))))
00180 ast_smoother_reset(s, size);
00181 return s;
00182 }
00183
00184 int ast_smoother_get_flags(struct ast_smoother *s)
00185 {
00186 return s->flags;
00187 }
00188
00189 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
00190 {
00191 s->flags = flags;
00192 }
00193
00194 int ast_smoother_test_flag(struct ast_smoother *s, int flag)
00195 {
00196 return (s->flags & flag);
00197 }
00198
00199 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
00200 {
00201 if (f->frametype != AST_FRAME_VOICE) {
00202 ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
00203 return -1;
00204 }
00205 if (!s->format) {
00206 s->format = f->subclass;
00207 s->samplesperbyte = (float)f->samples / (float)f->datalen;
00208 } else if (s->format != f->subclass) {
00209 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
00210 return -1;
00211 }
00212 if (s->len + f->datalen > SMOOTHER_SIZE) {
00213 ast_log(LOG_WARNING, "Out of smoother space\n");
00214 return -1;
00215 }
00216 if (((f->datalen == s->size) ||
00217 ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
00218 !s->opt &&
00219 !s->len &&
00220 (f->offset >= AST_MIN_OFFSET)) {
00221
00222
00223
00224 if (swap)
00225 ast_swapcopy_samples(f->data.ptr, f->data.ptr, f->samples);
00226 s->opt = f;
00227 s->opt_needs_swap = swap ? 1 : 0;
00228 return 0;
00229 }
00230
00231 return smoother_frame_feed(s, f, swap);
00232 }
00233
00234 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
00235 {
00236 struct ast_frame *opt;
00237 int len;
00238
00239
00240 if (s->opt) {
00241 if (s->opt->offset < AST_FRIENDLY_OFFSET)
00242 ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
00243 s->opt->offset);
00244 opt = s->opt;
00245 s->opt = NULL;
00246 return opt;
00247 }
00248
00249
00250 if (s->len < s->size) {
00251
00252 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->len % 10)))
00253 return NULL;
00254 }
00255 len = s->size;
00256 if (len > s->len)
00257 len = s->len;
00258
00259 s->f.frametype = AST_FRAME_VOICE;
00260 s->f.subclass = s->format;
00261 s->f.data.ptr = s->framedata + AST_FRIENDLY_OFFSET;
00262 s->f.offset = AST_FRIENDLY_OFFSET;
00263 s->f.datalen = len;
00264
00265 s->f.samples = len * s->samplesperbyte;
00266 s->f.delivery = s->delivery;
00267
00268 memcpy(s->f.data.ptr, s->data, len);
00269 s->len -= len;
00270
00271 if (s->len) {
00272
00273
00274 memmove(s->data, s->data + len, s->len);
00275 if (!ast_tvzero(s->delivery)) {
00276
00277 s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, ast_format_rate(s->format)));
00278 }
00279 }
00280
00281 return &s->f;
00282 }
00283
00284 void ast_smoother_free(struct ast_smoother *s)
00285 {
00286 ast_free(s);
00287 }
00288
00289 static struct ast_frame *ast_frame_header_new(void)
00290 {
00291 struct ast_frame *f;
00292
00293 #if !defined(LOW_MEMORY)
00294 struct ast_frame_cache *frames;
00295
00296 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
00297 if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
00298 size_t mallocd_len = f->mallocd_hdr_len;
00299 memset(f, 0, sizeof(*f));
00300 f->mallocd_hdr_len = mallocd_len;
00301 f->mallocd = AST_MALLOCD_HDR;
00302 frames->size--;
00303 return f;
00304 }
00305 }
00306 if (!(f = ast_calloc_cache(1, sizeof(*f))))
00307 return NULL;
00308 #else
00309 if (!(f = ast_calloc(1, sizeof(*f))))
00310 return NULL;
00311 #endif
00312
00313 f->mallocd_hdr_len = sizeof(*f);
00314
00315 return f;
00316 }
00317
00318 #if !defined(LOW_MEMORY)
00319 static void frame_cache_cleanup(void *data)
00320 {
00321 struct ast_frame_cache *frames = data;
00322 struct ast_frame *f;
00323
00324 while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
00325 ast_free(f);
00326
00327 ast_free(frames);
00328 }
00329 #endif
00330
00331 static void __frame_free(struct ast_frame *fr, int cache)
00332 {
00333 if (!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.ptr)
00353 ast_free(fr->data.ptr - 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.ptr, fr->datalen);
00447 out->data.ptr = 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.ptr = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
00517 memcpy(out->data.ptr, f->data.ptr, out->datalen);
00518 } else {
00519 out->data.uint32 = f->data.uint32;
00520 }
00521 if (srclen > 0) {
00522
00523 char *src;
00524 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
00525 src = (char *) out->src;
00526
00527 strcpy(src, f->src);
00528 }
00529 ast_copy_flags(out, f, AST_FRFLAG_HAS_TIMING_INFO);
00530 out->ts = f->ts;
00531 out->len = f->len;
00532 out->seqno = f->seqno;
00533 return out;
00534 }
00535
00536 void ast_swapcopy_samples(void *dst, const void *src, int samples)
00537 {
00538 int i;
00539 unsigned short *dst_s = dst;
00540 const unsigned short *src_s = src;
00541
00542 for (i = 0; i < samples; i++)
00543 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
00544 }
00545
00546
00547 struct ast_format_list *ast_get_format_list_index(int idx)
00548 {
00549 return &AST_FORMAT_LIST[idx];
00550 }
00551
00552 struct ast_format_list *ast_get_format_list(size_t *size)
00553 {
00554 *size = ARRAY_LEN(AST_FORMAT_LIST);
00555 return AST_FORMAT_LIST;
00556 }
00557
00558 char* ast_getformatname(int format)
00559 {
00560 int x;
00561 char *ret = "unknown";
00562 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00563 if (AST_FORMAT_LIST[x].bits == format) {
00564 ret = AST_FORMAT_LIST[x].name;
00565 break;
00566 }
00567 }
00568 return ret;
00569 }
00570
00571 char *ast_getformatname_multiple(char *buf, size_t size, int format)
00572 {
00573 int x;
00574 unsigned len;
00575 char *start, *end = buf;
00576
00577 if (!size)
00578 return buf;
00579 snprintf(end, size, "0x%x (", format);
00580 len = strlen(end);
00581 end += len;
00582 size -= len;
00583 start = end;
00584 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00585 if (AST_FORMAT_LIST[x].bits & format) {
00586 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
00587 len = strlen(end);
00588 end += len;
00589 size -= len;
00590 }
00591 }
00592 if (start == end)
00593 ast_copy_string(start, "nothing)", size);
00594 else if (size > 1)
00595 *(end -1) = ')';
00596 return buf;
00597 }
00598
00599 static struct ast_codec_alias_table {
00600 char *alias;
00601 char *realname;
00602 } ast_codec_alias_table[] = {
00603 { "slinear", "slin"},
00604 { "slinear16", "slin16"},
00605 { "g723.1", "g723"},
00606 };
00607
00608 static const char *ast_expand_codec_alias(const char *in)
00609 {
00610 int x;
00611
00612 for (x = 0; x < ARRAY_LEN(ast_codec_alias_table); x++) {
00613 if (!strcmp(in,ast_codec_alias_table[x].alias))
00614 return ast_codec_alias_table[x].realname;
00615 }
00616 return in;
00617 }
00618
00619 int ast_getformatbyname(const char *name)
00620 {
00621 int x, all, format = 0;
00622
00623 all = strcasecmp(name, "all") ? 0 : 1;
00624 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00625 if (all ||
00626 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
00627 !strcasecmp(AST_FORMAT_LIST[x].name, ast_expand_codec_alias(name))) {
00628 format |= AST_FORMAT_LIST[x].bits;
00629 if (!all)
00630 break;
00631 }
00632 }
00633
00634 return format;
00635 }
00636
00637 char *ast_codec2str(int codec)
00638 {
00639 int x;
00640 char *ret = "unknown";
00641 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00642 if (AST_FORMAT_LIST[x].bits == codec) {
00643 ret = AST_FORMAT_LIST[x].desc;
00644 break;
00645 }
00646 }
00647 return ret;
00648 }
00649
00650 static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00651 {
00652 int i, found=0;
00653 char hex[25];
00654
00655 switch (cmd) {
00656 case CLI_INIT:
00657 e->command = "core show codecs [audio|video|image]";
00658 e->usage =
00659 "Usage: core show codecs [audio|video|image]\n"
00660 " Displays codec mapping\n";
00661 return NULL;
00662 case CLI_GENERATE:
00663 return NULL;
00664 }
00665
00666 if ((a->argc < 3) || (a->argc > 4))
00667 return CLI_SHOWUSAGE;
00668
00669 if (!ast_opt_dont_warn)
00670 ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
00671 "\tIt does not indicate anything about your configuration.\n");
00672
00673 ast_cli(a->fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
00674 ast_cli(a->fd, "--------------------------------------------------------------------------------\n");
00675 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"audio"))) {
00676 found = 1;
00677 for (i=0;i<13;i++) {
00678 snprintf(hex,25,"(0x%x)",1<<i);
00679 ast_cli(a->fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00680 }
00681 }
00682
00683 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"image"))) {
00684 found = 1;
00685 for (i=16;i<18;i++) {
00686 snprintf(hex,25,"(0x%x)",1<<i);
00687 ast_cli(a->fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00688 }
00689 }
00690
00691 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"video"))) {
00692 found = 1;
00693 for (i=18;i<22;i++) {
00694 snprintf(hex,25,"(0x%x)",1<<i);
00695 ast_cli(a->fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00696 }
00697 }
00698
00699 if (!found)
00700 return CLI_SHOWUSAGE;
00701 else
00702 return CLI_SUCCESS;
00703 }
00704
00705 static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00706 {
00707 int codec, i, found=0;
00708
00709 switch (cmd) {
00710 case CLI_INIT:
00711 e->command = "core show codec";
00712 e->usage =
00713 "Usage: core show codec <number>\n"
00714 " Displays codec mapping\n";
00715 return NULL;
00716 case CLI_GENERATE:
00717 return NULL;
00718 }
00719
00720 if (a->argc != 4)
00721 return CLI_SHOWUSAGE;
00722
00723 if (sscanf(a->argv[3], "%30d", &codec) != 1)
00724 return CLI_SHOWUSAGE;
00725
00726 for (i = 0; i < 32; i++)
00727 if (codec & (1 << i)) {
00728 found = 1;
00729 ast_cli(a->fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
00730 }
00731
00732 if (!found)
00733 ast_cli(a->fd, "Codec %d not found\n", codec);
00734
00735 return CLI_SUCCESS;
00736 }
00737
00738
00739 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
00740 {
00741 const char noname[] = "unknown";
00742 char ftype[40] = "Unknown Frametype";
00743 char cft[80];
00744 char subclass[40] = "Unknown Subclass";
00745 char csub[80];
00746 char moreinfo[40] = "";
00747 char cn[60];
00748 char cp[40];
00749 char cmn[40];
00750 const char *message = "Unknown";
00751
00752 if (!name)
00753 name = noname;
00754
00755
00756 if (!f) {
00757 ast_verbose("%s [ %s (NULL) ] [%s]\n",
00758 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00759 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00760 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00761 return;
00762 }
00763
00764 if (f->frametype == AST_FRAME_VOICE)
00765 return;
00766 if (f->frametype == AST_FRAME_VIDEO)
00767 return;
00768 switch(f->frametype) {
00769 case AST_FRAME_DTMF_BEGIN:
00770 strcpy(ftype, "DTMF Begin");
00771 subclass[0] = f->subclass;
00772 subclass[1] = '\0';
00773 break;
00774 case AST_FRAME_DTMF_END:
00775 strcpy(ftype, "DTMF End");
00776 subclass[0] = f->subclass;
00777 subclass[1] = '\0';
00778 break;
00779 case AST_FRAME_CONTROL:
00780 strcpy(ftype, "Control");
00781 switch(f->subclass) {
00782 case AST_CONTROL_HANGUP:
00783 strcpy(subclass, "Hangup");
00784 break;
00785 case AST_CONTROL_RING:
00786 strcpy(subclass, "Ring");
00787 break;
00788 case AST_CONTROL_RINGING:
00789 strcpy(subclass, "Ringing");
00790 break;
00791 case AST_CONTROL_ANSWER:
00792 strcpy(subclass, "Answer");
00793 break;
00794 case AST_CONTROL_BUSY:
00795 strcpy(subclass, "Busy");
00796 break;
00797 case AST_CONTROL_TAKEOFFHOOK:
00798 strcpy(subclass, "Take Off Hook");
00799 break;
00800 case AST_CONTROL_OFFHOOK:
00801 strcpy(subclass, "Line Off Hook");
00802 break;
00803 case AST_CONTROL_CONGESTION:
00804 strcpy(subclass, "Congestion");
00805 break;
00806 case AST_CONTROL_FLASH:
00807 strcpy(subclass, "Flash");
00808 break;
00809 case AST_CONTROL_WINK:
00810 strcpy(subclass, "Wink");
00811 break;
00812 case AST_CONTROL_OPTION:
00813 strcpy(subclass, "Option");
00814 break;
00815 case AST_CONTROL_RADIO_KEY:
00816 strcpy(subclass, "Key Radio");
00817 break;
00818 case AST_CONTROL_RADIO_UNKEY:
00819 strcpy(subclass, "Unkey Radio");
00820 break;
00821 case AST_CONTROL_HOLD:
00822 strcpy(subclass, "Hold");
00823 break;
00824 case AST_CONTROL_UNHOLD:
00825 strcpy(subclass, "Unhold");
00826 break;
00827 case AST_CONTROL_T38_PARAMETERS:
00828 if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
00829 message = "Invalid";
00830 } else {
00831 struct ast_control_t38_parameters *parameters = f->data.ptr;
00832 enum ast_control_t38 state = parameters->request_response;
00833 if (state == AST_T38_REQUEST_NEGOTIATE)
00834 message = "Negotiation Requested";
00835 else if (state == AST_T38_REQUEST_TERMINATE)
00836 message = "Negotiation Request Terminated";
00837 else if (state == AST_T38_NEGOTIATED)
00838 message = "Negotiated";
00839 else if (state == AST_T38_TERMINATED)
00840 message = "Terminated";
00841 else if (state == AST_T38_REFUSED)
00842 message = "Refused";
00843 }
00844 snprintf(subclass, sizeof(subclass), "T38_Parameters/%s", message);
00845 break;
00846 case -1:
00847 strcpy(subclass, "Stop generators");
00848 break;
00849 default:
00850 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
00851 }
00852 break;
00853 case AST_FRAME_NULL:
00854 strcpy(ftype, "Null Frame");
00855 strcpy(subclass, "N/A");
00856 break;
00857 case AST_FRAME_IAX:
00858
00859 strcpy(ftype, "IAX Specific");
00860 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
00861 break;
00862 case AST_FRAME_TEXT:
00863 strcpy(ftype, "Text");
00864 strcpy(subclass, "N/A");
00865 ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
00866 break;
00867 case AST_FRAME_IMAGE:
00868 strcpy(ftype, "Image");
00869 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
00870 break;
00871 case AST_FRAME_HTML:
00872 strcpy(ftype, "HTML");
00873 switch(f->subclass) {
00874 case AST_HTML_URL:
00875 strcpy(subclass, "URL");
00876 ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
00877 break;
00878 case AST_HTML_DATA:
00879 strcpy(subclass, "Data");
00880 break;
00881 case AST_HTML_BEGIN:
00882 strcpy(subclass, "Begin");
00883 break;
00884 case AST_HTML_END:
00885 strcpy(subclass, "End");
00886 break;
00887 case AST_HTML_LDCOMPLETE:
00888 strcpy(subclass, "Load Complete");
00889 break;
00890 case AST_HTML_NOSUPPORT:
00891 strcpy(subclass, "No Support");
00892 break;
00893 case AST_HTML_LINKURL:
00894 strcpy(subclass, "Link URL");
00895 ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
00896 break;
00897 case AST_HTML_UNLINK:
00898 strcpy(subclass, "Unlink");
00899 break;
00900 case AST_HTML_LINKREJECT:
00901 strcpy(subclass, "Link Reject");
00902 break;
00903 default:
00904 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
00905 break;
00906 }
00907 break;
00908 case AST_FRAME_MODEM:
00909 strcpy(ftype, "Modem");
00910 switch (f->subclass) {
00911 case AST_MODEM_T38:
00912 strcpy(subclass, "T.38");
00913 break;
00914 case AST_MODEM_V150:
00915 strcpy(subclass, "V.150");
00916 break;
00917 default:
00918 snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
00919 break;
00920 }
00921 break;
00922 default:
00923 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
00924 }
00925 if (!ast_strlen_zero(moreinfo))
00926 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
00927 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00928 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00929 f->frametype,
00930 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00931 f->subclass,
00932 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
00933 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00934 else
00935 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
00936 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00937 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00938 f->frametype,
00939 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00940 f->subclass,
00941 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00942 }
00943
00944
00945
00946 static struct ast_cli_entry my_clis[] = {
00947 AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
00948 AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
00949 };
00950
00951 int init_framer(void)
00952 {
00953 ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
00954 return 0;
00955 }
00956
00957 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
00958 {
00959 int x, differential = (int) 'A', mem;
00960 char *from, *to;
00961
00962 if (right) {
00963 from = pref->order;
00964 to = buf;
00965 mem = size;
00966 } else {
00967 to = pref->order;
00968 from = buf;
00969 mem = 32;
00970 }
00971
00972 memset(to, 0, mem);
00973 for (x = 0; x < 32 ; x++) {
00974 if (!from[x])
00975 break;
00976 to[x] = right ? (from[x] + differential) : (from[x] - differential);
00977 }
00978 }
00979
00980 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
00981 {
00982 int x, codec;
00983 size_t total_len, slen;
00984 char *formatname;
00985
00986 memset(buf,0,size);
00987 total_len = size;
00988 buf[0] = '(';
00989 total_len--;
00990 for(x = 0; x < 32 ; x++) {
00991 if (total_len <= 0)
00992 break;
00993 if (!(codec = ast_codec_pref_index(pref,x)))
00994 break;
00995 if ((formatname = ast_getformatname(codec))) {
00996 slen = strlen(formatname);
00997 if (slen > total_len)
00998 break;
00999 strncat(buf, formatname, total_len - 1);
01000 total_len -= slen;
01001 }
01002 if (total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
01003 strncat(buf, "|", total_len - 1);
01004 total_len--;
01005 }
01006 }
01007 if (total_len) {
01008 strncat(buf, ")", total_len - 1);
01009 total_len--;
01010 }
01011
01012 return size - total_len;
01013 }
01014
01015 int ast_codec_pref_index(struct ast_codec_pref *pref, int idx)
01016 {
01017 int slot = 0;
01018
01019 if ((idx >= 0) && (idx < sizeof(pref->order))) {
01020 slot = pref->order[idx];
01021 }
01022
01023 return slot ? AST_FORMAT_LIST[slot - 1].bits : 0;
01024 }
01025
01026
01027 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
01028 {
01029 struct ast_codec_pref oldorder;
01030 int x, y = 0;
01031 int slot;
01032 int size;
01033
01034 if (!pref->order[0])
01035 return;
01036
01037 memcpy(&oldorder, pref, sizeof(oldorder));
01038 memset(pref, 0, sizeof(*pref));
01039
01040 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01041 slot = oldorder.order[x];
01042 size = oldorder.framing[x];
01043 if (! slot)
01044 break;
01045 if (AST_FORMAT_LIST[slot-1].bits != format) {
01046 pref->order[y] = slot;
01047 pref->framing[y++] = size;
01048 }
01049 }
01050
01051 }
01052
01053
01054 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
01055 {
01056 int x, newindex = 0;
01057
01058 ast_codec_pref_remove(pref, format);
01059
01060 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01061 if (AST_FORMAT_LIST[x].bits == format) {
01062 newindex = x + 1;
01063 break;
01064 }
01065 }
01066
01067 if (newindex) {
01068 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01069 if (!pref->order[x]) {
01070 pref->order[x] = newindex;
01071 break;
01072 }
01073 }
01074 }
01075
01076 return x;
01077 }
01078
01079
01080 void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing)
01081 {
01082 int x, newindex = 0;
01083
01084
01085 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01086 if (AST_FORMAT_LIST[x].bits == format) {
01087 newindex = x + 1;
01088 break;
01089 }
01090 }
01091
01092 if (!newindex)
01093 return;
01094
01095
01096 for (x = 0; x < 32; x++) {
01097 if (!pref->order[x] || pref->order[x] == newindex)
01098 break;
01099 }
01100
01101 if (only_if_existing && !pref->order[x])
01102 return;
01103
01104
01105
01106 for (; x > 0; x--) {
01107 pref->order[x] = pref->order[x - 1];
01108 pref->framing[x] = pref->framing[x - 1];
01109 }
01110
01111
01112 pref->order[0] = newindex;
01113 pref->framing[0] = 0;
01114 }
01115
01116
01117 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
01118 {
01119 int x, idx = -1;
01120
01121 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01122 if (AST_FORMAT_LIST[x].bits == format) {
01123 idx = x;
01124 break;
01125 }
01126 }
01127
01128 if (idx < 0)
01129 return -1;
01130
01131
01132 if (!framems)
01133 framems = AST_FORMAT_LIST[idx].def_ms;
01134
01135 if (AST_FORMAT_LIST[idx].inc_ms && framems % AST_FORMAT_LIST[idx].inc_ms)
01136 framems -= framems % AST_FORMAT_LIST[idx].inc_ms;
01137
01138 if (framems < AST_FORMAT_LIST[idx].min_ms)
01139 framems = AST_FORMAT_LIST[idx].min_ms;
01140
01141 if (framems > AST_FORMAT_LIST[idx].max_ms)
01142 framems = AST_FORMAT_LIST[idx].max_ms;
01143
01144 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01145 if (pref->order[x] == (idx + 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, idx = -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 idx = x;
01164 break;
01165 }
01166 }
01167
01168 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01169 if (pref->order[x] == (idx + 1)) {
01170 framems = pref->framing[x];
01171 break;
01172 }
01173 }
01174
01175
01176 if (!framems)
01177 framems = AST_FORMAT_LIST[idx].def_ms;
01178
01179 if (AST_FORMAT_LIST[idx].inc_ms && framems % AST_FORMAT_LIST[idx].inc_ms)
01180 framems -= framems % AST_FORMAT_LIST[idx].inc_ms;
01181
01182 if (framems < AST_FORMAT_LIST[idx].min_ms)
01183 framems = AST_FORMAT_LIST[idx].min_ms;
01184
01185 if (framems > AST_FORMAT_LIST[idx].max_ms)
01186 framems = AST_FORMAT_LIST[idx].max_ms;
01187
01188 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.ptr, f->datalen);
01420 break;
01421 case AST_FORMAT_G723_1:
01422 samples = g723_samples(f->data.ptr, 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.ptr))[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.ptr;
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.ptr, data2 = f2->data.ptr;
01535 count < f1->samples;
01536 count++, data1++, data2++)
01537 ast_slinear_saturated_add(data1, data2);
01538
01539 return 0;
01540 }