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