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: 201093 $")
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 (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR)) {
00334 ast_translate_frame_freed(fr);
00335 } else if (ast_test_flag(fr, AST_FRFLAG_FROM_DSP)) {
00336 ast_dsp_frame_freed(fr);
00337 } else if (ast_test_flag(fr, AST_FRFLAG_FROM_FILESTREAM)) {
00338 ast_filestream_frame_freed(fr);
00339 }
00340
00341 if (!fr->mallocd)
00342 return;
00343
00344 #if !defined(LOW_MEMORY)
00345 if (cache && fr->mallocd == AST_MALLOCD_HDR) {
00346
00347
00348 struct ast_frame_cache *frames;
00349
00350 if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&
00351 (frames->size < FRAME_CACHE_MAX_SIZE)) {
00352 AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
00353 frames->size++;
00354 return;
00355 }
00356 }
00357 #endif
00358
00359 if (fr->mallocd & AST_MALLOCD_DATA) {
00360 if (fr->data)
00361 ast_free(fr->data - fr->offset);
00362 }
00363 if (fr->mallocd & AST_MALLOCD_SRC) {
00364 if (fr->src)
00365 ast_free((void *) fr->src);
00366 }
00367 if (fr->mallocd & AST_MALLOCD_HDR) {
00368 ast_free(fr);
00369 }
00370 }
00371
00372
00373 void ast_frame_free(struct ast_frame *frame, int cache)
00374 {
00375 struct ast_frame *next;
00376
00377 for (next = AST_LIST_NEXT(frame, frame_list);
00378 frame;
00379 frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
00380 __frame_free(frame, cache);
00381 }
00382 }
00383
00384
00385
00386
00387
00388
00389 struct ast_frame *ast_frisolate(struct ast_frame *fr)
00390 {
00391 struct ast_frame *out;
00392 void *newdata;
00393
00394
00395
00396
00397 if (fr->mallocd == 0) {
00398 return ast_frdup(fr);
00399 }
00400
00401
00402 if ((fr->mallocd & (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) ==
00403 (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) {
00404 return fr;
00405 }
00406
00407 if (!(fr->mallocd & AST_MALLOCD_HDR)) {
00408
00409 if (!(out = ast_frame_header_new())) {
00410 return NULL;
00411 }
00412 out->frametype = fr->frametype;
00413 out->subclass = fr->subclass;
00414 out->datalen = fr->datalen;
00415 out->samples = fr->samples;
00416 out->offset = fr->offset;
00417
00418 ast_copy_flags(out, fr, AST_FRFLAG_HAS_TIMING_INFO);
00419 if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
00420 out->ts = fr->ts;
00421 out->len = fr->len;
00422 out->seqno = fr->seqno;
00423 }
00424 } else {
00425 ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
00426 ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
00427 ast_clear_flag(fr, AST_FRFLAG_FROM_FILESTREAM);
00428 out = fr;
00429 }
00430
00431 if (!(fr->mallocd & AST_MALLOCD_SRC) && fr->src) {
00432 if (!(out->src = ast_strdup(fr->src))) {
00433 if (out != fr) {
00434 ast_free(out);
00435 }
00436 return NULL;
00437 }
00438 } else {
00439 out->src = fr->src;
00440 fr->src = NULL;
00441 fr->mallocd &= ~AST_MALLOCD_SRC;
00442 }
00443
00444 if (!(fr->mallocd & AST_MALLOCD_DATA)) {
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, fr->datalen);
00458 out->data = 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 = f->subclass;
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 = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
00528 memcpy(out->data, f->data, out->datalen);
00529 }
00530 if (srclen > 0) {
00531
00532 char *src;
00533 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
00534 src = (char *) out->src;
00535
00536 strcpy(src, f->src);
00537 }
00538 ast_copy_flags(out, f, AST_FRFLAG_HAS_TIMING_INFO);
00539 out->ts = f->ts;
00540 out->len = f->len;
00541 out->seqno = f->seqno;
00542 return out;
00543 }
00544
00545 void ast_swapcopy_samples(void *dst, const void *src, int samples)
00546 {
00547 int i;
00548 unsigned short *dst_s = dst;
00549 const unsigned short *src_s = src;
00550
00551 for (i = 0; i < samples; i++)
00552 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
00553 }
00554
00555
00556 struct ast_format_list *ast_get_format_list_index(int index)
00557 {
00558 return &AST_FORMAT_LIST[index];
00559 }
00560
00561 struct ast_format_list *ast_get_format_list(size_t *size)
00562 {
00563 *size = ARRAY_LEN(AST_FORMAT_LIST);
00564 return AST_FORMAT_LIST;
00565 }
00566
00567 char* ast_getformatname(int format)
00568 {
00569 int x;
00570 char *ret = "unknown";
00571 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00572 if (AST_FORMAT_LIST[x].bits == format) {
00573 ret = AST_FORMAT_LIST[x].name;
00574 break;
00575 }
00576 }
00577 return ret;
00578 }
00579
00580 char *ast_getformatname_multiple(char *buf, size_t size, int format)
00581 {
00582 int x;
00583 unsigned len;
00584 char *start, *end = buf;
00585
00586 if (!size)
00587 return buf;
00588 snprintf(end, size, "0x%x (", format);
00589 len = strlen(end);
00590 end += len;
00591 size -= len;
00592 start = end;
00593 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00594 if (AST_FORMAT_LIST[x].bits & format) {
00595 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
00596 len = strlen(end);
00597 end += len;
00598 size -= len;
00599 }
00600 }
00601 if (start == end)
00602 ast_copy_string(start, "nothing)", size);
00603 else if (size > 1)
00604 *(end -1) = ')';
00605 return buf;
00606 }
00607
00608 static struct ast_codec_alias_table {
00609 char *alias;
00610 char *realname;
00611 } ast_codec_alias_table[] = {
00612 { "slinear", "slin"},
00613 { "slinear16", "slin16"},
00614 { "g723.1", "g723"},
00615 };
00616
00617 static const char *ast_expand_codec_alias(const char *in)
00618 {
00619 int x;
00620
00621 for (x = 0; x < ARRAY_LEN(ast_codec_alias_table); x++) {
00622 if (!strcmp(in,ast_codec_alias_table[x].alias))
00623 return ast_codec_alias_table[x].realname;
00624 }
00625 return in;
00626 }
00627
00628 int ast_getformatbyname(const char *name)
00629 {
00630 int x, all, format = 0;
00631
00632 all = strcasecmp(name, "all") ? 0 : 1;
00633 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00634 if (all ||
00635 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
00636 !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name))) {
00637 format |= AST_FORMAT_LIST[x].bits;
00638 if (!all)
00639 break;
00640 }
00641 }
00642
00643 return format;
00644 }
00645
00646 char *ast_codec2str(int codec)
00647 {
00648 int x;
00649 char *ret = "unknown";
00650 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
00651 if (AST_FORMAT_LIST[x].bits == codec) {
00652 ret = AST_FORMAT_LIST[x].desc;
00653 break;
00654 }
00655 }
00656 return ret;
00657 }
00658
00659 static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00660 {
00661 int i, found=0;
00662 char hex[25];
00663
00664 switch (cmd) {
00665 case CLI_INIT:
00666 e->command = "core show codecs [audio|video|image]";
00667 e->usage =
00668 "Usage: core show codecs [audio|video|image]\n"
00669 " Displays codec mapping\n";
00670 return NULL;
00671 case CLI_GENERATE:
00672 return NULL;
00673 }
00674
00675 if ((a->argc < 3) || (a->argc > 4))
00676 return CLI_SHOWUSAGE;
00677
00678 if (!ast_opt_dont_warn)
00679 ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
00680 "\tIt does not indicate anything about your configuration.\n");
00681
00682 ast_cli(a->fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
00683 ast_cli(a->fd, "--------------------------------------------------------------------------------\n");
00684 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"audio"))) {
00685 found = 1;
00686 for (i=0;i<13;i++) {
00687 snprintf(hex,25,"(0x%x)",1<<i);
00688 ast_cli(a->fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00689 }
00690 }
00691
00692 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"image"))) {
00693 found = 1;
00694 for (i=16;i<18;i++) {
00695 snprintf(hex,25,"(0x%x)",1<<i);
00696 ast_cli(a->fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00697 }
00698 }
00699
00700 if ((a->argc == 3) || (!strcasecmp(a->argv[3],"video"))) {
00701 found = 1;
00702 for (i=18;i<22;i++) {
00703 snprintf(hex,25,"(0x%x)",1<<i);
00704 ast_cli(a->fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00705 }
00706 }
00707
00708 if (!found)
00709 return CLI_SHOWUSAGE;
00710 else
00711 return CLI_SUCCESS;
00712 }
00713
00714 static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00715 {
00716 int codec, i, found=0;
00717
00718 switch (cmd) {
00719 case CLI_INIT:
00720 e->command = "core show codec";
00721 e->usage =
00722 "Usage: core show codec <number>\n"
00723 " Displays codec mapping\n";
00724 return NULL;
00725 case CLI_GENERATE:
00726 return NULL;
00727 }
00728
00729 if (a->argc != 4)
00730 return CLI_SHOWUSAGE;
00731
00732 if (sscanf(a->argv[3],"%d",&codec) != 1)
00733 return CLI_SHOWUSAGE;
00734
00735 for (i = 0; i < 32; i++)
00736 if (codec & (1 << i)) {
00737 found = 1;
00738 ast_cli(a->fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
00739 }
00740
00741 if (!found)
00742 ast_cli(a->fd, "Codec %d not found\n", codec);
00743
00744 return CLI_SUCCESS;
00745 }
00746
00747
00748 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
00749 {
00750 const char noname[] = "unknown";
00751 char ftype[40] = "Unknown Frametype";
00752 char cft[80];
00753 char subclass[40] = "Unknown Subclass";
00754 char csub[80];
00755 char moreinfo[40] = "";
00756 char cn[60];
00757 char cp[40];
00758 char cmn[40];
00759 const char *message = "Unknown";
00760
00761 if (!name)
00762 name = noname;
00763
00764
00765 if (!f) {
00766 ast_verbose("%s [ %s (NULL) ] [%s]\n",
00767 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00768 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00769 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00770 return;
00771 }
00772
00773 if (f->frametype == AST_FRAME_VOICE)
00774 return;
00775 if (f->frametype == AST_FRAME_VIDEO)
00776 return;
00777 switch(f->frametype) {
00778 case AST_FRAME_DTMF_BEGIN:
00779 strcpy(ftype, "DTMF Begin");
00780 subclass[0] = f->subclass;
00781 subclass[1] = '\0';
00782 break;
00783 case AST_FRAME_DTMF_END:
00784 strcpy(ftype, "DTMF End");
00785 subclass[0] = f->subclass;
00786 subclass[1] = '\0';
00787 break;
00788 case AST_FRAME_CONTROL:
00789 strcpy(ftype, "Control");
00790 switch(f->subclass) {
00791 case AST_CONTROL_HANGUP:
00792 strcpy(subclass, "Hangup");
00793 break;
00794 case AST_CONTROL_RING:
00795 strcpy(subclass, "Ring");
00796 break;
00797 case AST_CONTROL_RINGING:
00798 strcpy(subclass, "Ringing");
00799 break;
00800 case AST_CONTROL_ANSWER:
00801 strcpy(subclass, "Answer");
00802 break;
00803 case AST_CONTROL_BUSY:
00804 strcpy(subclass, "Busy");
00805 break;
00806 case AST_CONTROL_TAKEOFFHOOK:
00807 strcpy(subclass, "Take Off Hook");
00808 break;
00809 case AST_CONTROL_OFFHOOK:
00810 strcpy(subclass, "Line Off Hook");
00811 break;
00812 case AST_CONTROL_CONGESTION:
00813 strcpy(subclass, "Congestion");
00814 break;
00815 case AST_CONTROL_FLASH:
00816 strcpy(subclass, "Flash");
00817 break;
00818 case AST_CONTROL_WINK:
00819 strcpy(subclass, "Wink");
00820 break;
00821 case AST_CONTROL_OPTION:
00822 strcpy(subclass, "Option");
00823 break;
00824 case AST_CONTROL_RADIO_KEY:
00825 strcpy(subclass, "Key Radio");
00826 break;
00827 case AST_CONTROL_RADIO_UNKEY:
00828 strcpy(subclass, "Unkey Radio");
00829 break;
00830 case AST_CONTROL_HOLD:
00831 strcpy(subclass, "Hold");
00832 break;
00833 case AST_CONTROL_UNHOLD:
00834 strcpy(subclass, "Unhold");
00835 break;
00836 case AST_CONTROL_T38:
00837 if (f->datalen != sizeof(enum ast_control_t38)) {
00838 message = "Invalid";
00839 } else {
00840 enum ast_control_t38 state = *((enum ast_control_t38 *) f->data);
00841 if (state == AST_T38_REQUEST_NEGOTIATE)
00842 message = "Negotiation Requested";
00843 else if (state == AST_T38_REQUEST_TERMINATE)
00844 message = "Negotiation Request Terminated";
00845 else if (state == AST_T38_NEGOTIATED)
00846 message = "Negotiated";
00847 else if (state == AST_T38_TERMINATED)
00848 message = "Terminated";
00849 else if (state == AST_T38_REFUSED)
00850 message = "Refused";
00851 }
00852 snprintf(subclass, sizeof(subclass), "T38/%s", message);
00853 break;
00854 case -1:
00855 strcpy(subclass, "Stop generators");
00856 break;
00857 default:
00858 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
00859 }
00860 break;
00861 case AST_FRAME_NULL:
00862 strcpy(ftype, "Null Frame");
00863 strcpy(subclass, "N/A");
00864 break;
00865 case AST_FRAME_IAX:
00866
00867 strcpy(ftype, "IAX Specific");
00868 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
00869 break;
00870 case AST_FRAME_TEXT:
00871 strcpy(ftype, "Text");
00872 strcpy(subclass, "N/A");
00873 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00874 break;
00875 case AST_FRAME_IMAGE:
00876 strcpy(ftype, "Image");
00877 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
00878 break;
00879 case AST_FRAME_HTML:
00880 strcpy(ftype, "HTML");
00881 switch(f->subclass) {
00882 case AST_HTML_URL:
00883 strcpy(subclass, "URL");
00884 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00885 break;
00886 case AST_HTML_DATA:
00887 strcpy(subclass, "Data");
00888 break;
00889 case AST_HTML_BEGIN:
00890 strcpy(subclass, "Begin");
00891 break;
00892 case AST_HTML_END:
00893 strcpy(subclass, "End");
00894 break;
00895 case AST_HTML_LDCOMPLETE:
00896 strcpy(subclass, "Load Complete");
00897 break;
00898 case AST_HTML_NOSUPPORT:
00899 strcpy(subclass, "No Support");
00900 break;
00901 case AST_HTML_LINKURL:
00902 strcpy(subclass, "Link URL");
00903 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00904 break;
00905 case AST_HTML_UNLINK:
00906 strcpy(subclass, "Unlink");
00907 break;
00908 case AST_HTML_LINKREJECT:
00909 strcpy(subclass, "Link Reject");
00910 break;
00911 default:
00912 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
00913 break;
00914 }
00915 break;
00916 case AST_FRAME_MODEM:
00917 strcpy(ftype, "Modem");
00918 switch (f->subclass) {
00919 case AST_MODEM_T38:
00920 strcpy(subclass, "T.38");
00921 break;
00922 case AST_MODEM_V150:
00923 strcpy(subclass, "V.150");
00924 break;
00925 default:
00926 snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
00927 break;
00928 }
00929 break;
00930 default:
00931 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
00932 }
00933 if (!ast_strlen_zero(moreinfo))
00934 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
00935 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00936 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00937 f->frametype,
00938 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00939 f->subclass,
00940 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
00941 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00942 else
00943 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
00944 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00945 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00946 f->frametype,
00947 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00948 f->subclass,
00949 term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00950 }
00951
00952
00953
00954 static struct ast_cli_entry my_clis[] = {
00955 AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
00956 AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
00957 };
00958
00959 int init_framer(void)
00960 {
00961 ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
00962 return 0;
00963 }
00964
00965 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
00966 {
00967 int x, differential = (int) 'A', mem;
00968 char *from, *to;
00969
00970 if (right) {
00971 from = pref->order;
00972 to = buf;
00973 mem = size;
00974 } else {
00975 to = pref->order;
00976 from = buf;
00977 mem = 32;
00978 }
00979
00980 memset(to, 0, mem);
00981 for (x = 0; x < 32 ; x++) {
00982 if (!from[x])
00983 break;
00984 to[x] = right ? (from[x] + differential) : (from[x] - differential);
00985 }
00986 }
00987
00988 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
00989 {
00990 int x, codec;
00991 size_t total_len, slen;
00992 char *formatname;
00993
00994 memset(buf,0,size);
00995 total_len = size;
00996 buf[0] = '(';
00997 total_len--;
00998 for(x = 0; x < 32 ; x++) {
00999 if (total_len <= 0)
01000 break;
01001 if (!(codec = ast_codec_pref_index(pref,x)))
01002 break;
01003 if ((formatname = ast_getformatname(codec))) {
01004 slen = strlen(formatname);
01005 if (slen > total_len)
01006 break;
01007 strncat(buf, formatname, total_len - 1);
01008 total_len -= slen;
01009 }
01010 if (total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
01011 strncat(buf, "|", total_len - 1);
01012 total_len--;
01013 }
01014 }
01015 if (total_len) {
01016 strncat(buf, ")", total_len - 1);
01017 total_len--;
01018 }
01019
01020 return size - total_len;
01021 }
01022
01023 int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
01024 {
01025 int slot = 0;
01026
01027
01028 if ((index >= 0) && (index < sizeof(pref->order))) {
01029 slot = pref->order[index];
01030 }
01031
01032 return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
01033 }
01034
01035
01036 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
01037 {
01038 struct ast_codec_pref oldorder;
01039 int x, y = 0;
01040 int slot;
01041 int size;
01042
01043 if (!pref->order[0])
01044 return;
01045
01046 memcpy(&oldorder, pref, sizeof(oldorder));
01047 memset(pref, 0, sizeof(*pref));
01048
01049 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01050 slot = oldorder.order[x];
01051 size = oldorder.framing[x];
01052 if (! slot)
01053 break;
01054 if (AST_FORMAT_LIST[slot-1].bits != format) {
01055 pref->order[y] = slot;
01056 pref->framing[y++] = size;
01057 }
01058 }
01059
01060 }
01061
01062
01063 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
01064 {
01065 int x, newindex = 0;
01066
01067 ast_codec_pref_remove(pref, format);
01068
01069 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01070 if (AST_FORMAT_LIST[x].bits == format) {
01071 newindex = x + 1;
01072 break;
01073 }
01074 }
01075
01076 if (newindex) {
01077 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01078 if (!pref->order[x]) {
01079 pref->order[x] = newindex;
01080 break;
01081 }
01082 }
01083 }
01084
01085 return x;
01086 }
01087
01088
01089 void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing)
01090 {
01091 int x, newindex = 0;
01092
01093
01094 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01095 if (AST_FORMAT_LIST[x].bits == format) {
01096 newindex = x + 1;
01097 break;
01098 }
01099 }
01100
01101 if (!newindex)
01102 return;
01103
01104
01105 for (x = 0; x < 32; x++) {
01106 if (!pref->order[x] || pref->order[x] == newindex)
01107 break;
01108 }
01109
01110 if (only_if_existing && !pref->order[x])
01111 return;
01112
01113
01114
01115 for (; x > 0; x--) {
01116 pref->order[x] = pref->order[x - 1];
01117 pref->framing[x] = pref->framing[x - 1];
01118 }
01119
01120
01121 pref->order[0] = newindex;
01122 pref->framing[0] = 0;
01123 }
01124
01125
01126 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
01127 {
01128 int x, index = -1;
01129
01130 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01131 if (AST_FORMAT_LIST[x].bits == format) {
01132 index = x;
01133 break;
01134 }
01135 }
01136
01137 if (index < 0)
01138 return -1;
01139
01140
01141 if (!framems)
01142 framems = AST_FORMAT_LIST[index].def_ms;
01143
01144 if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms)
01145 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
01146
01147 if (framems < AST_FORMAT_LIST[index].min_ms)
01148 framems = AST_FORMAT_LIST[index].min_ms;
01149
01150 if (framems > AST_FORMAT_LIST[index].max_ms)
01151 framems = AST_FORMAT_LIST[index].max_ms;
01152
01153
01154 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01155 if (pref->order[x] == (index + 1)) {
01156 pref->framing[x] = framems;
01157 break;
01158 }
01159 }
01160
01161 return x;
01162 }
01163
01164
01165 struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
01166 {
01167 int x, index = -1, framems = 0;
01168 struct ast_format_list fmt = { 0, };
01169
01170 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01171 if (AST_FORMAT_LIST[x].bits == format) {
01172 fmt = AST_FORMAT_LIST[x];
01173 index = x;
01174 break;
01175 }
01176 }
01177
01178 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01179 if (pref->order[x] == (index + 1)) {
01180 framems = pref->framing[x];
01181 break;
01182 }
01183 }
01184
01185
01186 if (!framems)
01187 framems = AST_FORMAT_LIST[index].def_ms;
01188
01189 if (AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms)
01190 framems -= framems % AST_FORMAT_LIST[index].inc_ms;
01191
01192 if (framems < AST_FORMAT_LIST[index].min_ms)
01193 framems = AST_FORMAT_LIST[index].min_ms;
01194
01195 if (framems > AST_FORMAT_LIST[index].max_ms)
01196 framems = AST_FORMAT_LIST[index].max_ms;
01197
01198 fmt.cur_ms = framems;
01199
01200 return fmt;
01201 }
01202
01203
01204 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
01205 {
01206 int x, ret = 0, slot;
01207
01208 for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
01209 slot = pref->order[x];
01210
01211 if (!slot)
01212 break;
01213 if (formats & AST_FORMAT_LIST[slot-1].bits) {
01214 ret = AST_FORMAT_LIST[slot-1].bits;
01215 break;
01216 }
01217 }
01218 if (ret & AST_FORMAT_AUDIO_MASK)
01219 return ret;
01220
01221 ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
01222
01223 return find_best ? ast_best_codec(formats) : 0;
01224 }
01225
01226 int ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
01227 {
01228 int errors = 0;
01229 char *parse = NULL, *this = NULL, *psize = NULL;
01230 int format = 0, framems = 0;
01231
01232 parse = ast_strdupa(list);
01233 while ((this = strsep(&parse, ","))) {
01234 framems = 0;
01235 if ((psize = strrchr(this, ':'))) {
01236 *psize++ = '\0';
01237 ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
01238 framems = atoi(psize);
01239 if (framems < 0) {
01240 framems = 0;
01241 errors++;
01242 ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
01243 }
01244 }
01245 if (!(format = ast_getformatbyname(this))) {
01246 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
01247 errors++;
01248 continue;
01249 }
01250
01251 if (mask) {
01252 if (allowing)
01253 *mask |= format;
01254 else
01255 *mask &= ~format;
01256 }
01257
01258
01259
01260
01261 if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
01262 if (strcasecmp(this, "all")) {
01263 if (allowing) {
01264 ast_codec_pref_append(pref, format);
01265 ast_codec_pref_setsize(pref, format, framems);
01266 }
01267 else
01268 ast_codec_pref_remove(pref, format);
01269 } else if (!allowing) {
01270 memset(pref, 0, sizeof(*pref));
01271 }
01272 }
01273 }
01274 return errors;
01275 }
01276
01277 static int g723_len(unsigned char buf)
01278 {
01279 enum frame_type type = buf & TYPE_MASK;
01280
01281 switch(type) {
01282 case TYPE_DONTSEND:
01283 return 0;
01284 break;
01285 case TYPE_SILENCE:
01286 return 4;
01287 break;
01288 case TYPE_HIGH:
01289 return 24;
01290 break;
01291 case TYPE_LOW:
01292 return 20;
01293 break;
01294 default:
01295 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
01296 }
01297 return -1;
01298 }
01299
01300 static int g723_samples(unsigned char *buf, int maxlen)
01301 {
01302 int pos = 0;
01303 int samples = 0;
01304 int res;
01305 while(pos < maxlen) {
01306 res = g723_len(buf[pos]);
01307 if (res <= 0)
01308 break;
01309 samples += 240;
01310 pos += res;
01311 }
01312 return samples;
01313 }
01314
01315 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
01316 {
01317 int byte = bit / 8;
01318 int rem = 8 - (bit % 8);
01319 unsigned char ret = 0;
01320
01321 if (n <= 0 || n > 8)
01322 return 0;
01323
01324 if (rem < n) {
01325 ret = (data[byte] << (n - rem));
01326 ret |= (data[byte + 1] >> (8 - n + rem));
01327 } else {
01328 ret = (data[byte] >> (rem - n));
01329 }
01330
01331 return (ret & (0xff >> (8 - n)));
01332 }
01333
01334 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
01335 {
01336 static int SpeexWBSubModeSz[] = {
01337 0, 36, 112, 192,
01338 352, 0, 0, 0 };
01339 int off = bit;
01340 unsigned char c;
01341
01342
01343 if (((len * 8 - off) >= 5) &&
01344 get_n_bits_at(data, 1, off)) {
01345 c = get_n_bits_at(data, 3, off + 1);
01346 off += SpeexWBSubModeSz[c];
01347
01348 if (((len * 8 - off) >= 5) &&
01349 get_n_bits_at(data, 1, off)) {
01350 c = get_n_bits_at(data, 3, off + 1);
01351 off += SpeexWBSubModeSz[c];
01352
01353 if (((len * 8 - off) >= 5) &&
01354 get_n_bits_at(data, 1, off)) {
01355 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
01356 return -1;
01357 }
01358 }
01359
01360 }
01361 return off - bit;
01362 }
01363
01364 static int speex_samples(unsigned char *data, int len)
01365 {
01366 static int SpeexSubModeSz[] = {
01367 5, 43, 119, 160,
01368 220, 300, 364, 492,
01369 79, 0, 0, 0,
01370 0, 0, 0, 0 };
01371 static int SpeexInBandSz[] = {
01372 1, 1, 4, 4,
01373 4, 4, 4, 4,
01374 8, 8, 16, 16,
01375 32, 32, 64, 64 };
01376 int bit = 0;
01377 int cnt = 0;
01378 int off;
01379 unsigned char c;
01380
01381 while ((len * 8 - bit) >= 5) {
01382
01383 off = speex_get_wb_sz_at(data, len, bit);
01384 if (off < 0) {
01385 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
01386 break;
01387 }
01388 bit += off;
01389
01390 if ((len * 8 - bit) < 5) {
01391 ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
01392 break;
01393 }
01394
01395
01396 c = get_n_bits_at(data, 5, bit);
01397 bit += 5;
01398
01399 if (c == 15) {
01400
01401 break;
01402 } else if (c == 14) {
01403
01404 c = get_n_bits_at(data, 4, bit);
01405 bit += 4;
01406 bit += SpeexInBandSz[c];
01407 } else if (c == 13) {
01408
01409 c = get_n_bits_at(data, 5, bit);
01410 bit += 5;
01411 bit += c * 8;
01412 } else if (c > 8) {
01413
01414 break;
01415 } else {
01416
01417 bit += SpeexSubModeSz[c] - 5;
01418 cnt += 160;
01419 }
01420 }
01421 return cnt;
01422 }
01423
01424 int ast_codec_get_samples(struct ast_frame *f)
01425 {
01426 int samples=0;
01427 switch(f->subclass) {
01428 case AST_FORMAT_SPEEX:
01429 samples = speex_samples(f->data, f->datalen);
01430 break;
01431 case AST_FORMAT_G723_1:
01432 samples = g723_samples(f->data, f->datalen);
01433 break;
01434 case AST_FORMAT_ILBC:
01435 samples = 240 * (f->datalen / 50);
01436 break;
01437 case AST_FORMAT_GSM:
01438 samples = 160 * (f->datalen / 33);
01439 break;
01440 case AST_FORMAT_G729A:
01441 samples = f->datalen * 8;
01442 break;
01443 case AST_FORMAT_SLINEAR:
01444 case AST_FORMAT_SLINEAR16:
01445 samples = f->datalen / 2;
01446 break;
01447 case AST_FORMAT_LPC10:
01448
01449 samples = 22 * 8;
01450 samples += (((char *)(f->data))[7] & 0x1) * 8;
01451 break;
01452 case AST_FORMAT_ULAW:
01453 case AST_FORMAT_ALAW:
01454 samples = f->datalen;
01455 break;
01456 case AST_FORMAT_G722:
01457 case AST_FORMAT_ADPCM:
01458 case AST_FORMAT_G726:
01459 case AST_FORMAT_G726_AAL2:
01460 samples = f->datalen * 2;
01461 break;
01462 default:
01463 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
01464 }
01465 return samples;
01466 }
01467
01468 int ast_codec_get_len(int format, int samples)
01469 {
01470 int len = 0;
01471
01472
01473 switch(format) {
01474 case AST_FORMAT_G723_1:
01475 len = (samples / 240) * 20;
01476 break;
01477 case AST_FORMAT_ILBC:
01478 len = (samples / 240) * 50;
01479 break;
01480 case AST_FORMAT_GSM:
01481 len = (samples / 160) * 33;
01482 break;
01483 case AST_FORMAT_G729A:
01484 len = samples / 8;
01485 break;
01486 case AST_FORMAT_SLINEAR:
01487 case AST_FORMAT_SLINEAR16:
01488 len = samples * 2;
01489 break;
01490 case AST_FORMAT_ULAW:
01491 case AST_FORMAT_ALAW:
01492 len = samples;
01493 break;
01494 case AST_FORMAT_G722:
01495 case AST_FORMAT_ADPCM:
01496 case AST_FORMAT_G726:
01497 case AST_FORMAT_G726_AAL2:
01498 len = samples / 2;
01499 break;
01500 default:
01501 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
01502 }
01503
01504 return len;
01505 }
01506
01507 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
01508 {
01509 int count;
01510 short *fdata = f->data;
01511 short adjust_value = abs(adjustment);
01512
01513 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
01514 return -1;
01515
01516 if (!adjustment)
01517 return 0;
01518
01519 for (count = 0; count < f->samples; count++) {
01520 if (adjustment > 0) {
01521 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
01522 } else if (adjustment < 0) {
01523 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
01524 }
01525 }
01526
01527 return 0;
01528 }
01529
01530 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
01531 {
01532 int count;
01533 short *data1, *data2;
01534
01535 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
01536 return -1;
01537
01538 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
01539 return -1;
01540
01541 if (f1->samples != f2->samples)
01542 return -1;
01543
01544 for (count = 0, data1 = f1->data, data2 = f2->data;
01545 count < f1->samples;
01546 count++, data1++, data2++)
01547 ast_slinear_saturated_add(data1, data2);
01548
01549 return 0;
01550 }