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