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: 33036 $")
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).",
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 headers++;
00257 f->prev = NULL;
00258 ast_mutex_lock(&framelock);
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 headers--;
00286 ast_mutex_lock(&framelock);
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 = malloc(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 out->data = buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
00391 if (srclen > 0) {
00392 out->src = out->data + f->datalen;
00393
00394 strcpy((char *)out->src, f->src);
00395 } else
00396 out->src = NULL;
00397 out->prev = NULL;
00398 out->next = NULL;
00399 memcpy(out->data, f->data, out->datalen);
00400 return out;
00401 }
00402
00403 #if 0
00404
00405
00406
00407
00408
00409
00410 struct ast_frame *ast_fr_fdread(int fd)
00411 {
00412 char buf[65536];
00413 int res;
00414 int ttl = sizeof(struct ast_frame);
00415 struct ast_frame *f = (struct ast_frame *)buf;
00416
00417
00418
00419 while(ttl) {
00420 res = read(fd, buf, ttl);
00421 if (res < 0) {
00422 ast_log(LOG_WARNING, "Bad read on %d: %s\n", fd, strerror(errno));
00423 return NULL;
00424 }
00425 ttl -= res;
00426 }
00427
00428
00429 f->mallocd = 0;
00430
00431 f->data = buf + sizeof(struct ast_frame);
00432 f->offset = 0;
00433
00434 f->mallocd = 0;
00435
00436 f->src = (char *)__FUNCTION__;
00437 if (f->datalen > sizeof(buf) - sizeof(struct ast_frame)) {
00438
00439 ast_log(LOG_WARNING, "Strange read (%d bytes)\n", f->datalen);
00440 return NULL;
00441 }
00442 if (f->datalen) {
00443 if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
00444
00445 ast_log(LOG_WARNING, "How very strange, expected %d, got %d\n", f->datalen, res);
00446 return NULL;
00447 }
00448 }
00449 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
00450 return NULL;
00451 }
00452 return ast_frisolate(f);
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 int ast_fr_fdwrite(int fd, struct ast_frame *frame)
00464 {
00465
00466 if (write(fd, frame, sizeof(struct ast_frame)) != sizeof(struct ast_frame)) {
00467 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
00468 return -1;
00469 }
00470 if (write(fd, frame->data, frame->datalen) != frame->datalen) {
00471 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
00472 return -1;
00473 }
00474 return 0;
00475 }
00476
00477 int ast_fr_fdhangup(int fd)
00478 {
00479 struct ast_frame hangup = {
00480 AST_FRAME_CONTROL,
00481 AST_CONTROL_HANGUP
00482 };
00483 return ast_fr_fdwrite(fd, &hangup);
00484 }
00485
00486 #endif
00487 void ast_swapcopy_samples(void *dst, const void *src, int samples)
00488 {
00489 int i;
00490 unsigned short *dst_s = dst;
00491 const unsigned short *src_s = src;
00492
00493 for (i=0; i<samples; i++)
00494 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
00495 }
00496
00497
00498 struct ast_format_list *ast_get_format_list_index(int index)
00499 {
00500 return &AST_FORMAT_LIST[index];
00501 }
00502
00503 struct ast_format_list *ast_get_format_list(size_t *size)
00504 {
00505 *size = (sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list));
00506 return AST_FORMAT_LIST;
00507 }
00508
00509 char* ast_getformatname(int format)
00510 {
00511 int x = 0;
00512 char *ret = "unknown";
00513 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00514 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
00515 ret = AST_FORMAT_LIST[x].name;
00516 break;
00517 }
00518 }
00519 return ret;
00520 }
00521
00522 char *ast_getformatname_multiple(char *buf, size_t size, int format) {
00523
00524 int x = 0;
00525 unsigned len;
00526 char *end = buf;
00527 char *start = buf;
00528 if (!size) return buf;
00529 snprintf(end, size, "0x%x (", format);
00530 len = strlen(end);
00531 end += len;
00532 size -= len;
00533 start = end;
00534 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00535 if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
00536 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
00537 len = strlen(end);
00538 end += len;
00539 size -= len;
00540 }
00541 }
00542 if (start == end)
00543 snprintf(start, size, "nothing)");
00544 else if (size > 1)
00545 *(end -1) = ')';
00546 return buf;
00547 }
00548
00549 static struct ast_codec_alias_table {
00550 char *alias;
00551 char *realname;
00552
00553 } ast_codec_alias_table[] = {
00554 {"slinear","slin"},
00555 {"g723.1","g723"},
00556 };
00557
00558 static char *ast_expand_codec_alias(char *in) {
00559 int x = 0;
00560
00561 for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(struct ast_codec_alias_table) ; x++) {
00562 if(!strcmp(in,ast_codec_alias_table[x].alias))
00563 return ast_codec_alias_table[x].realname;
00564 }
00565 return in;
00566 }
00567
00568 int ast_getformatbyname(char *name)
00569 {
00570 int x = 0, all = 0, format = 0;
00571
00572 all = strcasecmp(name, "all") ? 0 : 1;
00573 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00574 if(AST_FORMAT_LIST[x].visible && (all ||
00575 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
00576 !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
00577 format |= AST_FORMAT_LIST[x].bits;
00578 if(!all)
00579 break;
00580 }
00581 }
00582
00583 return format;
00584 }
00585
00586 char *ast_codec2str(int codec) {
00587 int x = 0;
00588 char *ret = "unknown";
00589 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00590 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
00591 ret = AST_FORMAT_LIST[x].desc;
00592 break;
00593 }
00594 }
00595 return ret;
00596 }
00597
00598 static int show_codecs(int fd, int argc, char *argv[])
00599 {
00600 int i, found=0;
00601 char hex[25];
00602
00603 if ((argc < 2) || (argc > 3))
00604 return RESULT_SHOWUSAGE;
00605
00606 if (!option_dontwarn)
00607 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
00608 "\tIt does not indicate anything about your configuration.\n");
00609
00610 ast_cli(fd, "%11s %9s %10s TYPE %5s %s\n","INT","BINARY","HEX","NAME","DESC");
00611 ast_cli(fd, "--------------------------------------------------------------------------------\n");
00612 if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
00613 found = 1;
00614 for (i=0;i<11;i++) {
00615 snprintf(hex,25,"(0x%x)",1<<i);
00616 ast_cli(fd, "%11u (1 << %2d) %10s audio %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00617 }
00618 }
00619
00620 if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
00621 found = 1;
00622 for (i=16;i<18;i++) {
00623 snprintf(hex,25,"(0x%x)",1<<i);
00624 ast_cli(fd, "%11u (1 << %2d) %10s image %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00625 }
00626 }
00627
00628 if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
00629 found = 1;
00630 for (i=18;i<21;i++) {
00631 snprintf(hex,25,"(0x%x)",1<<i);
00632 ast_cli(fd, "%11u (1 << %2d) %10s video %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00633 }
00634 }
00635
00636 if (! found)
00637 return RESULT_SHOWUSAGE;
00638 else
00639 return RESULT_SUCCESS;
00640 }
00641
00642 static char frame_show_codecs_usage[] =
00643 "Usage: show [audio|video|image] codecs\n"
00644 " Displays codec mapping\n";
00645
00646 static int show_codec_n(int fd, int argc, char *argv[])
00647 {
00648 int codec, i, found=0;
00649
00650 if (argc != 3)
00651 return RESULT_SHOWUSAGE;
00652
00653 if (sscanf(argv[2],"%d",&codec) != 1)
00654 return RESULT_SHOWUSAGE;
00655
00656 for (i=0;i<32;i++)
00657 if (codec & (1 << i)) {
00658 found = 1;
00659 ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
00660 }
00661
00662 if (! found)
00663 ast_cli(fd, "Codec %d not found\n", codec);
00664
00665 return RESULT_SUCCESS;
00666 }
00667
00668 static char frame_show_codec_n_usage[] =
00669 "Usage: show codec <number>\n"
00670 " Displays codec mapping\n";
00671
00672
00673 void ast_frame_dump(char *name, struct ast_frame *f, char *prefix)
00674 {
00675 char *n = "unknown";
00676 char ftype[40] = "Unknown Frametype";
00677 char cft[80];
00678 char subclass[40] = "Unknown Subclass";
00679 char csub[80];
00680 char moreinfo[40] = "";
00681 char cn[60];
00682 char cp[40];
00683 char cmn[40];
00684 if (name)
00685 n = name;
00686 if (!f) {
00687 ast_verbose("%s [ %s (NULL) ] [%s]\n",
00688 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00689 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00690 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00691 return;
00692 }
00693
00694 if (f->frametype == AST_FRAME_VOICE)
00695 return;
00696 if (f->frametype == AST_FRAME_VIDEO)
00697 return;
00698 switch(f->frametype) {
00699 case AST_FRAME_DTMF:
00700 strcpy(ftype, "DTMF");
00701 subclass[0] = f->subclass;
00702 subclass[1] = '\0';
00703 break;
00704 case AST_FRAME_CONTROL:
00705 strcpy(ftype, "Control");
00706 switch(f->subclass) {
00707 case AST_CONTROL_HANGUP:
00708 strcpy(subclass, "Hangup");
00709 break;
00710 case AST_CONTROL_RING:
00711 strcpy(subclass, "Ring");
00712 break;
00713 case AST_CONTROL_RINGING:
00714 strcpy(subclass, "Ringing");
00715 break;
00716 case AST_CONTROL_ANSWER:
00717 strcpy(subclass, "Answer");
00718 break;
00719 case AST_CONTROL_BUSY:
00720 strcpy(subclass, "Busy");
00721 break;
00722 case AST_CONTROL_TAKEOFFHOOK:
00723 strcpy(subclass, "Take Off Hook");
00724 break;
00725 case AST_CONTROL_OFFHOOK:
00726 strcpy(subclass, "Line Off Hook");
00727 break;
00728 case AST_CONTROL_CONGESTION:
00729 strcpy(subclass, "Congestion");
00730 break;
00731 case AST_CONTROL_FLASH:
00732 strcpy(subclass, "Flash");
00733 break;
00734 case AST_CONTROL_WINK:
00735 strcpy(subclass, "Wink");
00736 break;
00737 case AST_CONTROL_OPTION:
00738 strcpy(subclass, "Option");
00739 break;
00740 case AST_CONTROL_RADIO_KEY:
00741 strcpy(subclass, "Key Radio");
00742 break;
00743 case AST_CONTROL_RADIO_UNKEY:
00744 strcpy(subclass, "Unkey Radio");
00745 break;
00746 case -1:
00747 strcpy(subclass, "Stop generators");
00748 break;
00749 default:
00750 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
00751 }
00752 break;
00753 case AST_FRAME_NULL:
00754 strcpy(ftype, "Null Frame");
00755 strcpy(subclass, "N/A");
00756 break;
00757 case AST_FRAME_IAX:
00758
00759 strcpy(ftype, "IAX Specific");
00760 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
00761 break;
00762 case AST_FRAME_TEXT:
00763 strcpy(ftype, "Text");
00764 strcpy(subclass, "N/A");
00765 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00766 break;
00767 case AST_FRAME_IMAGE:
00768 strcpy(ftype, "Image");
00769 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
00770 break;
00771 case AST_FRAME_HTML:
00772 strcpy(ftype, "HTML");
00773 switch(f->subclass) {
00774 case AST_HTML_URL:
00775 strcpy(subclass, "URL");
00776 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00777 break;
00778 case AST_HTML_DATA:
00779 strcpy(subclass, "Data");
00780 break;
00781 case AST_HTML_BEGIN:
00782 strcpy(subclass, "Begin");
00783 break;
00784 case AST_HTML_END:
00785 strcpy(subclass, "End");
00786 break;
00787 case AST_HTML_LDCOMPLETE:
00788 strcpy(subclass, "Load Complete");
00789 break;
00790 case AST_HTML_NOSUPPORT:
00791 strcpy(subclass, "No Support");
00792 break;
00793 case AST_HTML_LINKURL:
00794 strcpy(subclass, "Link URL");
00795 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00796 break;
00797 case AST_HTML_UNLINK:
00798 strcpy(subclass, "Unlink");
00799 break;
00800 case AST_HTML_LINKREJECT:
00801 strcpy(subclass, "Link Reject");
00802 break;
00803 default:
00804 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
00805 break;
00806 }
00807 break;
00808 default:
00809 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
00810 }
00811 if (!ast_strlen_zero(moreinfo))
00812 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
00813 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00814 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00815 f->frametype,
00816 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00817 f->subclass,
00818 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
00819 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00820 else
00821 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
00822 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00823 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00824 f->frametype,
00825 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00826 f->subclass,
00827 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00828
00829 }
00830
00831
00832 #ifdef TRACE_FRAMES
00833 static int show_frame_stats(int fd, int argc, char *argv[])
00834 {
00835 struct ast_frame *f;
00836 int x=1;
00837 if (argc != 3)
00838 return RESULT_SHOWUSAGE;
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 ast_mutex_lock(&framelock);
00844 for (f=headerlist; f; f = f->next) {
00845 ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
00846 }
00847 ast_mutex_unlock(&framelock);
00848 return RESULT_SUCCESS;
00849 }
00850
00851 static char frame_stats_usage[] =
00852 "Usage: show frame stats\n"
00853 " Displays debugging statistics from framer\n";
00854 #endif
00855
00856
00857 static struct ast_cli_entry my_clis[] = {
00858 { { "show", "codecs", NULL }, show_codecs, "Shows codecs", frame_show_codecs_usage },
00859 { { "show", "audio", "codecs", NULL }, show_codecs, "Shows audio codecs", frame_show_codecs_usage },
00860 { { "show", "video", "codecs", NULL }, show_codecs, "Shows video codecs", frame_show_codecs_usage },
00861 { { "show", "image", "codecs", NULL }, show_codecs, "Shows image codecs", frame_show_codecs_usage },
00862 { { "show", "codec", NULL }, show_codec_n, "Shows a specific codec", frame_show_codec_n_usage },
00863 #ifdef TRACE_FRAMES
00864 { { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage },
00865 #endif
00866 };
00867
00868 int init_framer(void)
00869 {
00870 ast_cli_register_multiple(my_clis, sizeof(my_clis)/sizeof(my_clis[0]) );
00871 return 0;
00872 }
00873
00874 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
00875 {
00876 int x = 0, differential = (int) 'A', mem = 0;
00877 char *from = NULL, *to = NULL;
00878
00879 if(right) {
00880 from = pref->order;
00881 to = buf;
00882 mem = size;
00883 } else {
00884 to = pref->order;
00885 from = buf;
00886 mem = 32;
00887 }
00888
00889 memset(to, 0, mem);
00890 for (x = 0; x < 32 ; x++) {
00891 if(!from[x])
00892 break;
00893 to[x] = right ? (from[x] + differential) : (from[x] - differential);
00894 }
00895 }
00896
00897 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
00898 {
00899 int x = 0, codec = 0;
00900 size_t total_len = 0, slen = 0;
00901 char *formatname = 0;
00902
00903 memset(buf,0,size);
00904 total_len = size;
00905 buf[0] = '(';
00906 total_len--;
00907 for(x = 0; x < 32 ; x++) {
00908 if(total_len <= 0)
00909 break;
00910 if(!(codec = ast_codec_pref_index(pref,x)))
00911 break;
00912 if((formatname = ast_getformatname(codec))) {
00913 slen = strlen(formatname);
00914 if(slen > total_len)
00915 break;
00916 strncat(buf,formatname,total_len);
00917 total_len -= slen;
00918 }
00919 if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
00920 strncat(buf,"|",total_len);
00921 total_len--;
00922 }
00923 }
00924 if(total_len) {
00925 strncat(buf,")",total_len);
00926 total_len--;
00927 }
00928
00929 return size - total_len;
00930 }
00931
00932 int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
00933 {
00934 int slot = 0;
00935
00936
00937 if((index >= 0) && (index < sizeof(pref->order))) {
00938 slot = pref->order[index];
00939 }
00940
00941 return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
00942 }
00943
00944
00945 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
00946 {
00947 struct ast_codec_pref oldorder;
00948 int x=0, y=0;
00949 size_t size = 0;
00950 int slot = 0;
00951
00952 if(!pref->order[0])
00953 return;
00954
00955 size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
00956
00957 memcpy(&oldorder,pref,sizeof(struct ast_codec_pref));
00958 memset(pref,0,sizeof(struct ast_codec_pref));
00959
00960 for (x = 0; x < size; x++) {
00961 slot = oldorder.order[x];
00962 if(! slot)
00963 break;
00964 if(AST_FORMAT_LIST[slot-1].bits != format)
00965 pref->order[y++] = slot;
00966 }
00967
00968 }
00969
00970
00971 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
00972 {
00973 size_t size = 0;
00974 int x = 0, newindex = -1;
00975
00976 ast_codec_pref_remove(pref, format);
00977 size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
00978
00979 for (x = 0; x < size; x++) {
00980 if(AST_FORMAT_LIST[x].bits == format) {
00981 newindex = x + 1;
00982 break;
00983 }
00984 }
00985
00986 if(newindex) {
00987 for (x = 0; x < size; x++) {
00988 if(!pref->order[x]) {
00989 pref->order[x] = newindex;
00990 break;
00991 }
00992 }
00993 }
00994
00995 return x;
00996 }
00997
00998
00999
01000 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
01001 {
01002 size_t size = 0;
01003 int x = 0, ret = 0, slot = 0;
01004
01005 size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
01006 for (x = 0; x < size; x++) {
01007 slot = pref->order[x];
01008
01009 if(!slot)
01010 break;
01011 if ( formats & AST_FORMAT_LIST[slot-1].bits ) {
01012 ret = AST_FORMAT_LIST[slot-1].bits;
01013 break;
01014 }
01015 }
01016 if(ret)
01017 return ret;
01018
01019 return find_best ? ast_best_codec(formats) : 0;
01020 }
01021
01022 void ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
01023 {
01024 char *parse;
01025 char *this;
01026 int format;
01027
01028 parse = ast_strdupa(list);
01029 while ((this = strsep(&parse, ","))) {
01030 if (!(format = ast_getformatbyname(this))) {
01031 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
01032 continue;
01033 }
01034
01035 if (mask) {
01036 if (allowing)
01037 *mask |= format;
01038 else
01039 *mask &= ~format;
01040 }
01041
01042 if (pref) {
01043 if (strcasecmp(this, "all")) {
01044 if (allowing)
01045 ast_codec_pref_append(pref, format);
01046 else
01047 ast_codec_pref_remove(pref, format);
01048 } else if (!allowing) {
01049 memset(pref, 0, sizeof(*pref));
01050 }
01051 }
01052 }
01053 }
01054
01055 static int g723_len(unsigned char buf)
01056 {
01057 switch(buf & TYPE_MASK) {
01058 case TYPE_DONTSEND:
01059 return 0;
01060 break;
01061 case TYPE_SILENCE:
01062 return 4;
01063 break;
01064 case TYPE_HIGH:
01065 return 24;
01066 break;
01067 case TYPE_LOW:
01068 return 20;
01069 break;
01070 default:
01071 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
01072 }
01073 return -1;
01074 }
01075
01076 static int g723_samples(unsigned char *buf, int maxlen)
01077 {
01078 int pos = 0;
01079 int samples = 0;
01080 int res;
01081 while(pos < maxlen) {
01082 res = g723_len(buf[pos]);
01083 if (res <= 0)
01084 break;
01085 samples += 240;
01086 pos += res;
01087 }
01088 return samples;
01089 }
01090
01091 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
01092 {
01093 int byte = bit / 8;
01094 int rem = 8 - (bit % 8);
01095 unsigned char ret = 0;
01096
01097 if (n <= 0 || n > 8)
01098 return 0;
01099
01100 if (rem < n) {
01101 ret = (data[byte] << (n - rem));
01102 ret |= (data[byte + 1] >> (8 - n + rem));
01103 } else {
01104 ret = (data[byte] >> (rem - n));
01105 }
01106
01107 return (ret & (0xff >> (8 - n)));
01108 }
01109
01110 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
01111 {
01112 static int SpeexWBSubModeSz[] = {
01113 0, 36, 112, 192,
01114 352, 0, 0, 0 };
01115 int off = bit;
01116 unsigned char c;
01117
01118
01119 if (((len * 8 - off) >= 5) &&
01120 get_n_bits_at(data, 1, off)) {
01121 c = get_n_bits_at(data, 3, off + 1);
01122 off += SpeexWBSubModeSz[c];
01123
01124 if (((len * 8 - off) >= 5) &&
01125 get_n_bits_at(data, 1, off)) {
01126 c = get_n_bits_at(data, 3, off + 1);
01127 off += SpeexWBSubModeSz[c];
01128
01129 if (((len * 8 - off) >= 5) &&
01130 get_n_bits_at(data, 1, off)) {
01131 ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
01132 return -1;
01133 }
01134 }
01135
01136 }
01137 return off - bit;
01138 }
01139
01140 static int speex_samples(unsigned char *data, int len)
01141 {
01142 static int SpeexSubModeSz[] = {
01143 5, 43, 119, 160,
01144 220, 300, 364, 492,
01145 79, 0, 0, 0,
01146 0, 0, 0, 0 };
01147 static int SpeexInBandSz[] = {
01148 1, 1, 4, 4,
01149 4, 4, 4, 4,
01150 8, 8, 16, 16,
01151 32, 32, 64, 64 };
01152 int bit = 0;
01153 int cnt = 0;
01154 int off = 0;
01155 unsigned char c;
01156
01157 while ((len * 8 - bit) >= 5) {
01158
01159 off = speex_get_wb_sz_at(data, len, bit);
01160 if (off < 0) {
01161 ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
01162 break;
01163 }
01164 bit += off;
01165
01166 if ((len * 8 - bit) < 5) {
01167 ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
01168 break;
01169 }
01170
01171
01172 c = get_n_bits_at(data, 5, bit);
01173 bit += 5;
01174
01175 if (c == 15) {
01176
01177 break;
01178 } else if (c == 14) {
01179
01180 c = get_n_bits_at(data, 4, bit);
01181 bit += 4;
01182 bit += SpeexInBandSz[c];
01183 } else if (c == 13) {
01184
01185 c = get_n_bits_at(data, 5, bit);
01186 bit += 5;
01187 bit += c * 8;
01188 } else if (c > 8) {
01189
01190 break;
01191 } else {
01192
01193 bit += SpeexSubModeSz[c] - 5;
01194 cnt += 160;
01195 }
01196 }
01197 return cnt;
01198 }
01199
01200 int ast_codec_get_samples(struct ast_frame *f)
01201 {
01202 int samples=0;
01203 switch(f->subclass) {
01204 case AST_FORMAT_SPEEX:
01205 samples = speex_samples(f->data, f->datalen);
01206 break;
01207 case AST_FORMAT_G723_1:
01208 samples = g723_samples(f->data, f->datalen);
01209 break;
01210 case AST_FORMAT_ILBC:
01211 samples = 240 * (f->datalen / 50);
01212 break;
01213 case AST_FORMAT_GSM:
01214 samples = 160 * (f->datalen / 33);
01215 break;
01216 case AST_FORMAT_G729A:
01217 samples = f->datalen * 8;
01218 break;
01219 case AST_FORMAT_SLINEAR:
01220 samples = f->datalen / 2;
01221 break;
01222 case AST_FORMAT_LPC10:
01223
01224 samples = 22 * 8;
01225 samples += (((char *)(f->data))[7] & 0x1) * 8;
01226 break;
01227 case AST_FORMAT_ULAW:
01228 case AST_FORMAT_ALAW:
01229 samples = f->datalen;
01230 break;
01231 case AST_FORMAT_ADPCM:
01232 case AST_FORMAT_G726:
01233 samples = f->datalen * 2;
01234 break;
01235 default:
01236 ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
01237 }
01238 return samples;
01239 }
01240
01241 int ast_codec_get_len(int format, int samples)
01242 {
01243 int len = 0;
01244
01245
01246 switch(format) {
01247 case AST_FORMAT_ILBC:
01248 len = (samples / 240) * 50;
01249 break;
01250 case AST_FORMAT_GSM:
01251 len = (samples / 160) * 33;
01252 break;
01253 case AST_FORMAT_G729A:
01254 len = samples / 8;
01255 break;
01256 case AST_FORMAT_SLINEAR:
01257 len = samples * 2;
01258 break;
01259 case AST_FORMAT_ULAW:
01260 case AST_FORMAT_ALAW:
01261 len = samples;
01262 break;
01263 case AST_FORMAT_ADPCM:
01264 case AST_FORMAT_G726:
01265 len = samples / 2;
01266 break;
01267 default:
01268 ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
01269 }
01270
01271 return len;
01272 }
01273
01274 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
01275 {
01276 int count;
01277 short *fdata = f->data;
01278 short adjust_value = abs(adjustment);
01279
01280 if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
01281 return -1;
01282
01283 if (!adjustment)
01284 return 0;
01285
01286 for (count = 0; count < f->samples; count++) {
01287 if (adjustment > 0) {
01288 ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
01289 } else if (adjustment < 0) {
01290 ast_slinear_saturated_divide(&fdata[count], &adjust_value);
01291 }
01292 }
01293
01294 return 0;
01295 }
01296
01297 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
01298 {
01299 int count;
01300 short *data1, *data2;
01301
01302 if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
01303 return -1;
01304
01305 if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
01306 return -1;
01307
01308 if (f1->samples != f2->samples)
01309 return -1;
01310
01311 for (count = 0, data1 = f1->data, data2 = f2->data;
01312 count < f1->samples;
01313 count++, data1++, data2++)
01314 ast_slinear_saturated_add(data1, data2);
01315
01316 return 0;
01317 }