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 #include <stdlib.h>
00026 #include <unistd.h>
00027 #include <string.h>
00028 #include <errno.h>
00029 #include <stdio.h>
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 43924 $")
00034
00035 #include "asterisk/lock.h"
00036 #include "asterisk/frame.h"
00037 #include "asterisk/logger.h"
00038 #include "asterisk/options.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/cli.h"
00041 #include "asterisk/term.h"
00042 #include "asterisk/utils.h"
00043
00044 #ifdef TRACE_FRAMES
00045 static int headers = 0;
00046 static struct ast_frame *headerlist = NULL;
00047 AST_MUTEX_DEFINE_STATIC(framelock);
00048 #endif
00049
00050 #define SMOOTHER_SIZE 8000
00051
00052 #define TYPE_HIGH 0x0
00053 #define TYPE_LOW 0x1
00054 #define TYPE_SILENCE 0x2
00055 #define TYPE_DONTSEND 0x3
00056 #define TYPE_MASK 0x3
00057
00058 struct ast_format_list {
00059 int visible;
00060 int bits;
00061 char *name;
00062 char *desc;
00063 };
00064
00065 struct ast_smoother {
00066 int size;
00067 int format;
00068 int readdata;
00069 int optimizablestream;
00070 int flags;
00071 float samplesperbyte;
00072 struct ast_frame f;
00073 struct timeval delivery;
00074 char data[SMOOTHER_SIZE];
00075 char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
00076 struct ast_frame *opt;
00077 int len;
00078 };
00079
00080
00081 static struct ast_format_list AST_FORMAT_LIST[] = {
00082 { 1, AST_FORMAT_G723_1 , "g723" , "G.723.1"},
00083 { 1, AST_FORMAT_GSM, "gsm" , "GSM"},
00084 { 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law" },
00085 { 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law" },
00086 { 1, AST_FORMAT_G726, "g726", "G.726" },
00087 { 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM"},
00088 { 1, AST_FORMAT_SLINEAR, "slin", "16 bit Signed Linear PCM"},
00089 { 1, AST_FORMAT_LPC10, "lpc10", "LPC10" },
00090 { 1, AST_FORMAT_G729A, "g729", "G.729A" },
00091 { 1, AST_FORMAT_SPEEX, "speex", "SpeeX" },
00092 { 1, AST_FORMAT_ILBC, "ilbc", "iLBC"},
00093 { 0, 0, "nothing", "undefined" },
00094 { 0, 0, "nothing", "undefined" },
00095 { 0, 0, "nothing", "undefined" },
00096 { 0, 0, "nothing", "undefined" },
00097 { 0, AST_FORMAT_MAX_AUDIO, "maxaudio", "Maximum audio format" },
00098 { 1, AST_FORMAT_JPEG, "jpeg", "JPEG image"},
00099 { 1, AST_FORMAT_PNG, "png", "PNG image"},
00100 { 1, AST_FORMAT_H261, "h261", "H.261 Video" },
00101 { 1, AST_FORMAT_H263, "h263", "H.263 Video" },
00102 { 1, AST_FORMAT_H263_PLUS, "h263p", "H.263+ Video" },
00103 { 0, 0, "nothing", "undefined" },
00104 { 0, 0, "nothing", "undefined" },
00105 { 0, 0, "nothing", "undefined" },
00106 { 0, 0, "nothing", "undefined" },
00107 { 0, AST_FORMAT_MAX_VIDEO, "maxvideo", "Maximum video format" },
00108 };
00109
00110 void ast_smoother_reset(struct ast_smoother *s, int size)
00111 {
00112 memset(s, 0, sizeof(struct ast_smoother));
00113 s->size = size;
00114 }
00115
00116 struct ast_smoother *ast_smoother_new(int size)
00117 {
00118 struct ast_smoother *s;
00119 if (size < 1)
00120 return NULL;
00121 s = malloc(sizeof(struct ast_smoother));
00122 if (s)
00123 ast_smoother_reset(s, size);
00124 return s;
00125 }
00126
00127 int ast_smoother_get_flags(struct ast_smoother *s)
00128 {
00129 return s->flags;
00130 }
00131
00132 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
00133 {
00134 s->flags = flags;
00135 }
00136
00137 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
00138 {
00139 if (f->frametype != AST_FRAME_VOICE) {
00140 ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
00141 return -1;
00142 }
00143 if (!s->format) {
00144 s->format = f->subclass;
00145 s->samplesperbyte = (float)f->samples / (float)f->datalen;
00146 } else if (s->format != f->subclass) {
00147 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
00148 return -1;
00149 }
00150 if (s->len + f->datalen > SMOOTHER_SIZE) {
00151 ast_log(LOG_WARNING, "Out of smoother space\n");
00152 return -1;
00153 }
00154 if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
00155 && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
00156 if (!s->len) {
00157
00158
00159
00160 s->opt = f;
00161 return 0;
00162 } else {
00163 s->optimizablestream++;
00164 if (s->optimizablestream > 10) {
00165
00166
00167
00168
00169
00170 s->len = 0;
00171 s->opt = f;
00172 return 0;
00173 }
00174 }
00175 } else
00176 s->optimizablestream = 0;
00177 if (s->flags & AST_SMOOTHER_FLAG_G729) {
00178 if (s->len % 10) {
00179 ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
00180 return 0;
00181 }
00182 }
00183 if (swap)
00184 ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
00185 else
00186 memcpy(s->data + s->len, f->data, f->datalen);
00187
00188 if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery))
00189 s->delivery = f->delivery;
00190 s->len += f->datalen;
00191 return 0;
00192 }
00193
00194 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
00195 {
00196 struct ast_frame *opt;
00197 int len;
00198
00199 if (s->opt) {
00200 if (s->opt->offset < AST_FRIENDLY_OFFSET)
00201 ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
00202 s->opt->offset);
00203 opt = s->opt;
00204 s->opt = NULL;
00205 return opt;
00206 }
00207
00208
00209 if (s->len < s->size) {
00210
00211 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
00212 return NULL;
00213 }
00214 len = s->size;
00215 if (len > s->len)
00216 len = s->len;
00217
00218 s->f.frametype = AST_FRAME_VOICE;
00219 s->f.subclass = s->format;
00220 s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
00221 s->f.offset = AST_FRIENDLY_OFFSET;
00222 s->f.datalen = len;
00223
00224 s->f.samples = len * s->samplesperbyte;
00225 s->f.delivery = s->delivery;
00226
00227 memcpy(s->f.data, s->data, len);
00228 s->len -= len;
00229
00230 if (s->len) {
00231
00232
00233 memmove(s->data, s->data + len, s->len);
00234 if (!ast_tvzero(s->delivery)) {
00235
00236 s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
00237 }
00238 }
00239
00240 return &s->f;
00241 }
00242
00243 void ast_smoother_free(struct ast_smoother *s)
00244 {
00245 free(s);
00246 }
00247
00248 static struct ast_frame *ast_frame_header_new(void)
00249 {
00250 struct ast_frame *f;
00251 f = malloc(sizeof(struct ast_frame));
00252 if (f)
00253 memset(f, 0, sizeof(struct ast_frame));
00254 #ifdef TRACE_FRAMES
00255 if (f) {
00256 f->prev = NULL;
00257 ast_mutex_lock(&framelock);
00258 headers++;
00259 f->next = headerlist;
00260 if (headerlist)
00261 headerlist->prev = f;
00262 headerlist = f;
00263 ast_mutex_unlock(&framelock);
00264 }
00265 #endif
00266 return f;
00267 }
00268
00269
00270
00271
00272
00273 void ast_frfree(struct ast_frame *fr)
00274 {
00275 if (fr->mallocd & AST_MALLOCD_DATA) {
00276 if (fr->data)
00277 free(fr->data - fr->offset);
00278 }
00279 if (fr->mallocd & AST_MALLOCD_SRC) {
00280 if (fr->src)
00281 free((char *)fr->src);
00282 }
00283 if (fr->mallocd & AST_MALLOCD_HDR) {
00284 #ifdef TRACE_FRAMES
00285 ast_mutex_lock(&framelock);
00286 headers--;
00287 if (fr->next)
00288 fr->next->prev = fr->prev;
00289 if (fr->prev)
00290 fr->prev->next = fr->next;
00291 else
00292 headerlist = fr->next;
00293 ast_mutex_unlock(&framelock);
00294 #endif
00295 free(fr);
00296 }
00297 }
00298
00299
00300
00301
00302
00303
00304 struct ast_frame *ast_frisolate(struct ast_frame *fr)
00305 {
00306 struct ast_frame *out;
00307 void *newdata;
00308
00309 if (!(fr->mallocd & AST_MALLOCD_HDR)) {
00310
00311 out = ast_frame_header_new();
00312 if (!out) {
00313 ast_log(LOG_WARNING, "Out of memory\n");
00314 return NULL;
00315 }
00316 out->frametype = fr->frametype;
00317 out->subclass = fr->subclass;
00318 out->datalen = fr->datalen;
00319 out->samples = fr->samples;
00320 out->offset = fr->offset;
00321 out->src = NULL;
00322 out->data = fr->data;
00323 } else
00324 out = fr;
00325
00326 if (!(fr->mallocd & AST_MALLOCD_SRC)) {
00327 if (fr->src) {
00328 out->src = strdup(fr->src);
00329 if (!out->src) {
00330 if (out != fr)
00331 free(out);
00332 ast_log(LOG_WARNING, "Out of memory\n");
00333 return NULL;
00334 }
00335 }
00336 } else
00337 out->src = fr->src;
00338
00339 if (!(fr->mallocd & AST_MALLOCD_DATA)) {
00340 newdata = malloc(fr->datalen + AST_FRIENDLY_OFFSET);
00341 if (!newdata) {
00342 if (out->src != fr->src)
00343 free((void *) out->src);
00344 if (out != fr)
00345 free(out);
00346 ast_log(LOG_WARNING, "Out of memory\n");
00347 return NULL;
00348 }
00349 newdata += AST_FRIENDLY_OFFSET;
00350 out->offset = AST_FRIENDLY_OFFSET;
00351 out->datalen = fr->datalen;
00352 memcpy(newdata, fr->data, fr->datalen);
00353 out->data = newdata;
00354 }
00355
00356 out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
00357
00358 return out;
00359 }
00360
00361 struct ast_frame *ast_frdup(struct ast_frame *f)
00362 {
00363 struct ast_frame *out;
00364 int len, srclen = 0;
00365 void *buf;
00366
00367 len = sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET + f->datalen;
00368
00369
00370
00371
00372
00373 if (f->src)
00374 srclen = strlen(f->src);
00375 if (srclen > 0)
00376 len += srclen + 1;
00377 buf = calloc(1, len);
00378 if (!buf)
00379 return NULL;
00380 out = buf;
00381
00382
00383 out->frametype = f->frametype;
00384 out->subclass = f->subclass;
00385 out->datalen = f->datalen;
00386 out->samples = f->samples;
00387 out->delivery = f->delivery;
00388 out->mallocd = AST_MALLOCD_HDR;
00389 out->offset = AST_FRIENDLY_OFFSET;
00390 if (out->datalen) {
00391 out->data = buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
00392 memcpy(out->data, f->data, out->datalen);
00393 }
00394 if (srclen > 0) {
00395 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
00396
00397 strcpy((char *)out->src, f->src);
00398 }
00399 return out;
00400 }
00401
00402 #if 0
00403
00404
00405
00406
00407
00408
00409 struct ast_frame *ast_fr_fdread(int fd)
00410 {
00411 char buf[65536];
00412 int res;
00413 int ttl = sizeof(struct ast_frame);
00414 struct ast_frame *f = (struct ast_frame *)buf;
00415
00416
00417
00418 while(ttl) {
00419 res = read(fd, buf, ttl);
00420 if (res < 0) {
00421 ast_log(LOG_WARNING, "Bad read on %d: %s\n", fd, strerror(errno));
00422 return NULL;
00423 }
00424 ttl -= res;
00425 }
00426
00427
00428 f->mallocd = 0;
00429
00430 f->data = buf + sizeof(struct ast_frame);
00431 f->offset = 0;
00432
00433 f->mallocd = 0;
00434
00435 f->src = (char *)__FUNCTION__;
00436 if (f->datalen > sizeof(buf) - sizeof(struct ast_frame)) {
00437
00438 ast_log(LOG_WARNING, "Strange read (%d bytes)\n", f->datalen);
00439 return NULL;
00440 }
00441 if (f->datalen) {
00442 if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
00443
00444 ast_log(LOG_WARNING, "How very strange, expected %d, got %d\n", f->datalen, res);
00445 return NULL;
00446 }
00447 }
00448 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
00449 return NULL;
00450 }
00451 return ast_frisolate(f);
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 int ast_fr_fdwrite(int fd, struct ast_frame *frame)
00463 {
00464
00465 if (write(fd, frame, sizeof(struct ast_frame)) != sizeof(struct ast_frame)) {
00466 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
00467 return -1;
00468 }
00469 if (write(fd, frame->data, frame->datalen) != frame->datalen) {
00470 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
00471 return -1;
00472 }
00473 return 0;
00474 }
00475
00476 int ast_fr_fdhangup(int fd)
00477 {
00478 struct ast_frame hangup = {
00479 AST_FRAME_CONTROL,
00480 AST_CONTROL_HANGUP
00481 };
00482 return ast_fr_fdwrite(fd, &hangup);
00483 }
00484
00485 #endif
00486 void ast_swapcopy_samples(void *dst, const void *src, int samples)
00487 {
00488 int i;
00489 unsigned short *dst_s = dst;
00490 const unsigned short *src_s = src;
00491
00492 for (i=0; i<samples; i++)
00493 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
00494 }
00495
00496
00497 struct ast_format_list *ast_get_format_list_index(int index)
00498 {
00499 return &AST_FORMAT_LIST[index];
00500 }
00501
00502 struct ast_format_list *ast_get_format_list(size_t *size)
00503 {
00504 *size = (sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list));
00505 return AST_FORMAT_LIST;
00506 }
00507
00508 char* ast_getformatname(int format)
00509 {
00510 int x = 0;
00511 char *ret = "unknown";
00512 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00513 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
00514 ret = AST_FORMAT_LIST[x].name;
00515 break;
00516 }
00517 }
00518 return ret;
00519 }
00520
00521 char *ast_getformatname_multiple(char *buf, size_t size, int format) {
00522
00523 int x = 0;
00524 unsigned len;
00525 char *end = buf;
00526 char *start = buf;
00527 if (!size) return buf;
00528 snprintf(end, size, "0x%x (", format);
00529 len = strlen(end);
00530 end += len;
00531 size -= len;
00532 start = end;
00533 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00534 if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
00535 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
00536 len = strlen(end);
00537 end += len;
00538 size -= len;
00539 }
00540 }
00541 if (start == end)
00542 snprintf(start, size, "nothing)");
00543 else if (size > 1)
00544 *(end -1) = ')';
00545 return buf;
00546 }
00547
00548 static struct ast_codec_alias_table {
00549 char *alias;
00550 char *realname;
00551
00552 } ast_codec_alias_table[] = {
00553 {"slinear","slin"},
00554 {"g723.1","g723"},
00555 };
00556
00557 static char *ast_expand_codec_alias(char *in) {
00558 int x = 0;
00559
00560 for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(struct ast_codec_alias_table) ; x++) {
00561 if(!strcmp(in,ast_codec_alias_table[x].alias))
00562 return ast_codec_alias_table[x].realname;
00563 }
00564 return in;
00565 }
00566
00567 int ast_getformatbyname(char *name)
00568 {
00569 int x = 0, all = 0, format = 0;
00570
00571 all = strcasecmp(name, "all") ? 0 : 1;
00572 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00573 if(AST_FORMAT_LIST[x].visible && (all ||
00574 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
00575 !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
00576 format |= AST_FORMAT_LIST[x].bits;
00577 if(!all)
00578 break;
00579 }
00580 }
00581
00582 return format;
00583 }
00584
00585 char *ast_codec2str(int codec) {
00586 int x = 0;
00587 char *ret = "unknown";
00588 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00589 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
00590 ret = AST_FORMAT_LIST[x].desc;
00591 break;
00592 }
00593 }
00594 return ret;
00595 }
00596
00597 static int show_codecs(int fd, int argc, char *argv[])
00598 {
00599 int i, found=0;
00600 char hex[25];
00601
00602 if ((argc < 2) || (argc > 3))
00603 return RESULT_SHOWUSAGE;
00604
00605 if (!option_dontwarn)
00606 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
00607 "\tIt does not indicate anything about your configuration.\n");
00608
00609 ast_cli(fd, "%11s %9s %10s TYPE %5s %s\n","INT","BINARY","HEX","NAME","DESC");
00610 ast_cli(fd, "--------------------------------------------------------------------------------\n");
00611 if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
00612 found = 1;
00613 for (i=0;i<11;i++) {
00614 snprintf(hex,25,"(0x%x)",1<<i);
00615 ast_cli(fd, "%11u (1 << %2d) %10s audio %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00616 }
00617 }
00618
00619 if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
00620 found = 1;
00621 for (i=16;i<18;i++) {
00622 snprintf(hex,25,"(0x%x)",1<<i);
00623 ast_cli(fd, "%11u (1 << %2d) %10s image %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00624 }
00625 }
00626
00627 if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
00628 found = 1;
00629 for (i=18;i<21;i++) {
00630 snprintf(hex,25,"(0x%x)",1<<i);
00631 ast_cli(fd, "%11u (1 << %2d) %10s video %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00632 }
00633 }
00634
00635 if (! found)
00636 return RESULT_SHOWUSAGE;
00637 else
00638 return RESULT_SUCCESS;
00639 }
00640
00641 static char frame_show_codecs_usage[] =
00642 "Usage: show [audio|video|image] codecs\n"
00643 " Displays codec mapping\n";
00644
00645 static int show_codec_n(int fd, int argc, char *argv[])
00646 {
00647 int codec, i, found=0;
00648
00649 if (argc != 3)
00650 return RESULT_SHOWUSAGE;
00651
00652 if (sscanf(argv[2],"%d",&codec) != 1)
00653 return RESULT_SHOWUSAGE;
00654
00655 for (i=0;i<32;i++)
00656 if (codec & (1 << i)) {
00657 found = 1;
00658 ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
00659 }
00660
00661 if (! found)
00662 ast_cli(fd, "Codec %d not found\n", codec);
00663
00664 return RESULT_SUCCESS;
00665 }
00666
00667 static char frame_show_codec_n_usage[] =
00668 "Usage: show codec <number>\n"
00669 " Displays codec mapping\n";
00670
00671
00672 void ast_frame_dump(char *name, struct ast_frame *f, char *prefix)
00673 {
00674 char *n = "unknown";
00675 char ftype[40] = "Unknown Frametype";
00676 char cft[80];
00677 char subclass[40] = "Unknown Subclass";
00678 char csub[80];
00679 char moreinfo[40] = "";
00680 char cn[60];
00681 char cp[40];
00682 char cmn[40];
00683 if (name)
00684 n = name;
00685 if (!f) {
00686 ast_verbose("%s [ %s (NULL) ] [%s]\n",
00687 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00688 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00689 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00690 return;
00691 }
00692
00693 if (f->frametype == AST_FRAME_VOICE)
00694 return;
00695 if (f->frametype == AST_FRAME_VIDEO)
00696 return;
00697 switch(f->frametype) {
00698 case AST_FRAME_DTMF:
00699 strcpy(ftype, "DTMF");
00700 subclass[0] = f->subclass;
00701 subclass[1] = '\0';
00702 break;
00703 case AST_FRAME_CONTROL:
00704 strcpy(ftype, "Control");
00705 switch(f->subclass) {
00706 case AST_CONTROL_HANGUP:
00707 strcpy(subclass, "Hangup");
00708 break;
00709 case AST_CONTROL_RING:
00710 strcpy(subclass, "Ring");
00711 break;
00712 case AST_CONTROL_RINGING:
00713 strcpy(subclass, "Ringing");
00714 break;
00715 case AST_CONTROL_ANSWER:
00716 strcpy(subclass, "Answer");
00717 break;
00718 case AST_CONTROL_BUSY:
00719 strcpy(subclass, "Busy");
00720 break;
00721 case AST_CONTROL_TAKEOFFHOOK:
00722 strcpy(subclass, "Take Off Hook");
00723 break;
00724 case AST_CONTROL_OFFHOOK:
00725 strcpy(subclass, "Line Off Hook");
00726 break;
00727 case AST_CONTROL_CONGESTION:
00728 strcpy(subclass, "Congestion");
00729 break;
00730 case AST_CONTROL_FLASH:
00731 strcpy(subclass, "Flash");
00732 break;
00733 case AST_CONTROL_WINK:
00734 strcpy(subclass, "Wink");
00735 break;
00736 case AST_CONTROL_OPTION:
00737 strcpy(subclass, "Option");
00738 break;
00739 case AST_CONTROL_RADIO_KEY:
00740 strcpy(subclass, "Key Radio");
00741 break;
00742 case AST_CONTROL_RADIO_UNKEY:
00743 strcpy(subclass, "Unkey Radio");
00744 break;
00745 case -1:
00746 strcpy(subclass, "Stop generators");
00747 break;
00748 default:
00749 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
00750 }
00751 break;
00752 case AST_FRAME_NULL:
00753 strcpy(ftype, "Null Frame");
00754 strcpy(subclass, "N/A");
00755 break;
00756 case AST_FRAME_IAX:
00757
00758 strcpy(ftype, "IAX Specific");
00759 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
00760 break;
00761 case AST_FRAME_TEXT:
00762 strcpy(ftype, "Text");
00763 strcpy(subclass, "N/A");
00764 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00765 break;
00766 case AST_FRAME_IMAGE:
00767 strcpy(ftype, "Image");
00768 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
00769 break;
00770 case AST_FRAME_HTML:
00771 strcpy(ftype, "HTML");
00772 switch(f->subclass) {
00773 case AST_HTML_URL:
00774 strcpy(subclass, "URL");
00775 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00776 break;
00777 case AST_HTML_DATA:
00778 strcpy(subclass, "Data");
00779 break;
00780 case AST_HTML_BEGIN:
00781 strcpy(subclass, "Begin");
00782 break;
00783 case AST_HTML_END:
00784 strcpy(subclass, "End");
00785 break;
00786 case AST_HTML_LDCOMPLETE:
00787 strcpy(subclass, "Load Complete");
00788 break;
00789 case AST_HTML_NOSUPPORT:
00790 strcpy(subclass, "No Support");
00791 break;
00792 case AST_HTML_LINKURL:
00793 strcpy(subclass, "Link URL");
00794 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00795 break;
00796 case AST_HTML_UNLINK:
00797 strcpy(subclass, "Unlink");
00798 break;
00799 case AST_HTML_LINKREJECT:
00800 strcpy(subclass, "Link Reject");
00801 break;
00802 default:
00803 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
00804 break;
00805 }
00806 break;
00807 default:
00808 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
00809 }
00810 if (!ast_strlen_zero(moreinfo))
00811 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
00812 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00813 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00814 f->frametype,
00815 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00816 f->subclass,
00817 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
00818 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00819 else
00820 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
00821 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00822 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00823 f->frametype,
00824 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00825 f->subclass,
00826 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00827
00828 }
00829
00830
00831 #ifdef TRACE_FRAMES
00832 static int show_frame_stats(int fd, int argc, char *argv[])
00833 {
00834 struct ast_frame *f;
00835 int x=1;
00836 if (argc != 3)
00837 return RESULT_SHOWUSAGE;
00838 ast_mutex_lock(&framelock);
00839 ast_cli(fd, " Framer Statistics \n");
00840 ast_cli(fd, "---------------------------\n");
00841 ast_cli(fd, "Total allocated headers: %d\n", headers);
00842 ast_cli(fd, "Queue Dump:\n");
00843 for (f=headerlist; f; f = f->next) {
00844 ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
00845 }
00846 ast_mutex_unlock(&framelock);
00847 return RESULT_SUCCESS;
00848 }
00849
00850 static char frame_stats_usage[] =
00851 "Usage: show frame stats\n"
00852 " Displays debugging statistics from framer\n";
00853 #endif
00854
00855
00856 static struct ast_cli_entry my_clis[] = {
00857 { { "show", "codecs", NULL }, show_codecs, "Shows codecs", frame_show_codecs_usage },
00858 { { "show", "audio", "codecs", NULL }, show_codecs, "Shows audio codecs", frame_show_codecs_usage },
00859 { { "show", "video", "codecs", NULL }, show_codecs, "Shows video codecs", frame_show_codecs_usage },
00860 { { "show", "image", "codecs", NULL }, show_codecs, "Shows image codecs", frame_show_codecs_usage },
00861 { { "show", "codec", NULL }, show_codec_n, "Shows a specific codec", frame_show_codec_n_usage },
00862 #ifdef TRACE_FRAMES
00863 { { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage },
00864 #endif
00865 };
00866
00867 int init_framer(void)
00868 {
00869 ast_cli_register_multiple(my_clis, sizeof(my_clis)/sizeof(my_clis[0]) );
00870 return 0;
00871 }
00872
00873 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
00874 {
00875 int x = 0, differential = (int) 'A', mem = 0;
00876 char *from = NULL, *to = NULL;
00877
00878 if(right) {
00879 from = pref->order;
00880 to = buf;
00881 mem = size;
00882 } else {
00883 to = pref->order;
00884 from = buf;
00885 mem = 32;
00886 }
00887
00888 memset(to, 0, mem);
00889 for (x = 0; x < 32 ; x++) {
00890 if(!from[x])
00891 break;
00892 to[x] = right ? (from[x] + differential) : (from[x] - differential);
00893 }
00894 }
00895
00896 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
00897 {
00898 int x = 0, codec = 0;
00899 size_t total_len = 0, slen = 0;
00900 char *formatname = 0;
00901
00902 memset(buf,0,size);
00903 total_len = size;
00904 buf[0] = '(';
00905 total_len--;
00906 for(x = 0; x < 32 ; x++) {
00907 if(total_len <= 0)
00908 break;
00909 if(!(codec = ast_codec_pref_index(pref,x)))
00910 break;
00911 if((formatname = ast_getformatname(codec))) {
00912 slen = strlen(formatname);
00913 if(slen > total_len)
00914 break;
00915 strncat(buf,formatname,total_len);
00916 total_len -= slen;
00917 }
00918 if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
00919 strncat(buf,"|",total_len);
00920 total_len--;
00921 }
00922 }
00923 if(total_len) {
00924 strncat(buf,")",total_len);
00925 total_len--;
00926 }
00927
00928 return size - total_len;
00929 }
00930
00931 int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
00932 {
00933 int slot = 0;
00934
00935
00936 if((index >= 0) && (index < sizeof(pref->order))) {
00937 slot = pref->order[index];
00938 }
00939
00940 return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
00941 }
00942
00943
00944 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
00945 {
00946 struct ast_codec_pref oldorder;
00947 int x=0, y=0;
00948 size_t size = 0;
00949 int slot = 0;
00950
00951 if(!pref->order[0])
00952 return;
00953
00954 size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
00955
00956 memcpy(&oldorder,pref,sizeof(struct ast_codec_pref));
00957 memset(pref,0,sizeof(struct ast_codec_pref));
00958
00959 for (x = 0; x < size; x++) {
00960 slot = oldorder.order[x];
00961 if(! slot)
00962 break;
00963 if(AST_FORMAT_LIST[slot-1].bits != format)
00964 pref->order[y++] = slot;
00965 }
00966
00967 }
00968
00969
00970 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
00971 {
00972 size_t size = 0;
00973 int x = 0, newindex = -1;
00974
00975 ast_codec_pref_remove(pref, format);
00976 size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
00977
00978 for (x = 0; x < size; x++) {
00979 if(AST_FORMAT_LIST[x].bits == format) {
00980 newindex = x + 1;
00981 break;
00982 }
00983 }
00984
00985 if(newindex) {
00986 for (x = 0; x < size; x++) {
00987 if(!pref->order[x]) {
00988 pref->order[x] = newindex;
00989 break;
00990 }
00991 }
00992 }
00993
00994 return x;
00995 }
00996
00997
00998
00999 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
01000 {
01001 size_t size = 0;
01002 int x = 0, ret = 0, slot = 0;
01003
01004 size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
01005 for (x = 0; x < size; x++) {
01006 slot = pref->order[x];
01007
01008 if(!slot)
01009 break;
01010 if ( formats & AST_FORMAT_LIST[slot-1].bits ) {
01011 ret = AST_FORMAT_LIST[slot-1].bits;
01012 break;
01013 }
01014 }
01015 if(ret)
01016 return ret;
01017
01018 return find_best ? ast_best_codec(formats) : 0;
01019 }
01020
01021 void ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
01022 {
01023 char *parse;
01024 char *this;
01025 int format;
01026
01027 parse = ast_strdupa(list);
01028 while ((this = strsep(&parse, ","))) {
01029 if (!(format = ast_getformatbyname(this))) {
01030 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
01031 continue;
01032 }
01033
01034 if (mask) {
01035 if (allowing)
01036 *mask |= format;
01037 else
01038 *mask &= ~format;
01039 }
01040
01041 if (pref) {
01042 if (strcasecmp(this, "all")) {
01043 if (allowing)
01044 ast_codec_pref_append(pref, format);
01045 else
01046 ast_codec_pref_remove(pref, format);
01047 } else if (!allowing) {
01048 memset(pref, 0, sizeof(*pref));
01049 }
01050 }
01051 }
01052 }
01053
01054 static int g723_len(unsigned char buf)
01055 {
01056 switch(buf & TYPE_MASK) {
01057 case TYPE_DONTSEND:
01058 return 0;
01059 break;
01060 case TYPE_SILENCE:
01061 return 4;
01062 break;
01063 case TYPE_HIGH:
01064 return 24;
01065 break;
01066 case TYPE_LOW:
01067 return 20;
01068 break;
01069 default:
01070 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
01071 }
01072 return -1;
01073 }
01074
01075 static int g723_samples(unsigned char *buf, int maxlen)
01076 {
01077 int pos = 0;
01078 int samples = 0;
01079 int res;
01080 while(pos < maxlen) {
01081 res = g723_len(buf[pos]);
01082 if (res <= 0)
01083 break;
01084 samples += 240;
01085 pos += res;
01086 }
01087 return samples;
01088 }
01089
01090 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
01091 {
01092 int byte = bit / 8;
01093 int rem = 8 - (bit % 8);
01094 unsigned char ret = 0;
01095
01096 if (n <= 0 || n > 8)
01097 return 0;
01098
01099 if (rem < n) {
01100 ret = (data[byte] << (n - rem));
01101 ret |= (data[byte + 1] >> (8 - n + rem));
01102 } else {
01103 ret = (data[byte] >> (rem - n));
01104 }
01105
01106 return (ret & (0xff >> (8 - n)));
01107 }
01108
01109 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
01110 {
01111 static int SpeexWBSubModeSz[] = {
01112 0, 36, 112, 192,
01113 352, 0, 0, 0 };
01114 int off = bit;
01115 unsigned char c;
01116
01117
01118 if (((len * 8 - off) >= 5) &&
01119 get_n_bits_at(data, 1, off)) {
01120 c = get_n_bits_at(data, 3, off + 1);
01121 off += SpeexWBSubModeSz[c];
01122
01123 if (((len * 8 - off) >= 5) &&
01124 get_n_bits_at(data, 1, off)) {
01125 c = get_n_bits_at(data, 3, off + 1);
01126 off += SpeexWBSubModeSz[c];
01127
01128 if (((len * 8 - off) >= 5) &&
01129 get_n_bits_at(data, 1, off)) {
01130 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
01131 return -1;
01132 }
01133 }
01134
01135 }
01136 return off - bit;
01137 }
01138
01139 static int speex_samples(unsigned char *data, int len)
01140 {
01141 static int SpeexSubModeSz[] = {
01142 5, 43, 119, 160,
01143 220, 300, 364, 492,
01144 79, 0, 0, 0,
01145 0, 0, 0, 0 };
01146 static int SpeexInBandSz[] = {
01147 1, 1, 4, 4,
01148 4, 4, 4, 4,
01149 8, 8, 16, 16,
01150 32, 32, 64, 64 };
01151 int bit = 0;
01152 int cnt = 0;
01153 int off = 0;
01154 unsigned char c;
01155
01156 while ((len * 8 - bit) >= 5) {
01157
01158 off = speex_get_wb_sz_at(data, len, bit);
01159 if (off < 0) {
01160 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
01161 break;
01162 }
01163 bit += off;
01164
01165 if ((len * 8 - bit) < 5) {
01166 ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
01167 break;
01168 }
01169
01170
01171 c = get_n_bits_at(data, 5, bit);
01172 bit += 5;
01173
01174 if (c == 15) {
01175
01176 break;
01177 } else if (c == 14) {
01178
01179 c = get_n_bits_at(data, 4, bit);
01180 bit += 4;
01181 bit += SpeexInBandSz[c];
01182 } else if (c == 13) {
01183
01184 c = get_n_bits_at(data, 5, bit);
01185 bit += 5;
01186 bit += c * 8;
01187 } else if (c > 8) {
01188
01189 break;
01190 } else {
01191
01192 bit += SpeexSubModeSz[c] - 5;
01193 cnt += 160;
01194 }
01195 }
01196 return cnt;
01197 }
01198
01199 int ast_codec_get_samples(struct ast_frame *f)
01200 {
01201 int samples=0;
01202 switch(f->subclass) {
01203 case AST_FORMAT_SPEEX:
01204 samples = speex_samples(f->data, f->datalen);
01205 break;
01206 case AST_FORMAT_G723_1:
01207 samples = g723_samples(f->data, f->datalen);
01208 break;
01209 case AST_FORMAT_ILBC:
01210 samples = 240 * (f->datalen / 50);
01211 break;
01212 case AST_FORMAT_GSM:
01213 samples = 160 * (f->datalen / 33);
01214 break;
01215 case AST_FORMAT_G729A:
01216 samples = f->datalen * 8;
01217 break;
01218 case AST_FORMAT_SLINEAR:
01219 samples = f->datalen / 2;
01220 break;
01221 case AST_FORMAT_LPC10:
01222
01223 samples = 22 * 8;
01224 samples += (((char *)(f->data))[7] & 0x1) * 8;
01225 break;
01226 case AST_FORMAT_ULAW:
01227 case AST_FORMAT_ALAW:
01228 samples = f->datalen;
01229 break;
01230 case AST_FORMAT_ADPCM:
01231 case AST_FORMAT_G726:
01232 samples = f->datalen * 2;
01233 break;
01234 default:
01235 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
01236 }
01237 return samples;
01238 }
01239
01240 int ast_codec_get_len(int format, int samples)
01241 {
01242 int len = 0;
01243
01244
01245 switch(format) {
01246 case AST_FORMAT_ILBC:
01247 len = (samples / 240) * 50;
01248 break;
01249 case AST_FORMAT_GSM:
01250 len = (samples / 160) * 33;
01251 break;
01252 case AST_FORMAT_G729A:
01253 len = samples / 8;
01254 break;
01255 case AST_FORMAT_SLINEAR:
01256 len = samples * 2;
01257 break;
01258 case AST_FORMAT_ULAW:
01259 case AST_FORMAT_ALAW:
01260 len = samples;
01261 break;
01262 case AST_FORMAT_ADPCM:
01263 case AST_FORMAT_G726:
01264 len = samples / 2;
01265 break;
01266 default:
01267 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
01268 }
01269
01270 return len;
01271 }
01272
01273 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
01274 {
01275 int count;
01276 short *fdata = f->data;
01277 short adjust_value = abs(adjustment);
01278
01279 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
01280 return -1;
01281
01282 if (!adjustment)
01283 return 0;
01284
01285 for (count = 0; count < f->samples; count++) {
01286 if (adjustment > 0) {
01287 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
01288 } else if (adjustment < 0) {
01289 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
01290 }
01291 }
01292
01293 return 0;
01294 }
01295
01296 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
01297 {
01298 int count;
01299 short *data1, *data2;
01300
01301 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
01302 return -1;
01303
01304 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
01305 return -1;
01306
01307 if (f1->samples != f2->samples)
01308 return -1;
01309
01310 for (count = 0, data1 = f1->data, data2 = f2->data;
01311 count < f1->samples;
01312 count++, data1++, data2++)
01313 ast_slinear_saturated_add(data1, data2);
01314
01315 return 0;
01316 }