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