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