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