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