00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <asterisk/lock.h>
00015 #include <asterisk/frame.h>
00016 #include <asterisk/logger.h>
00017 #include <asterisk/options.h>
00018 #include <asterisk/channel.h>
00019 #include <asterisk/cli.h>
00020 #include <asterisk/term.h>
00021 #include <asterisk/utils.h>
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <string.h>
00025 #include <errno.h>
00026 #include <stdio.h>
00027 #include "asterisk.h"
00028
00029 #ifdef TRACE_FRAMES
00030 static int headers = 0;
00031 static struct ast_frame *headerlist = NULL;
00032 AST_MUTEX_DEFINE_STATIC(framelock);
00033 #endif
00034
00035 #define SMOOTHER_SIZE 8000
00036
00037 struct ast_format_list {
00038 int visible;
00039 int bits;
00040 char *name;
00041 char *desc;
00042 };
00043
00044 struct ast_smoother {
00045 int size;
00046 int format;
00047 int readdata;
00048 int optimizablestream;
00049 int flags;
00050 float samplesperbyte;
00051 struct ast_frame f;
00052 struct timeval delivery;
00053 char data[SMOOTHER_SIZE];
00054 char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
00055 struct ast_frame *opt;
00056 int len;
00057 };
00058
00059 void ast_smoother_reset(struct ast_smoother *s, int size)
00060 {
00061 memset(s, 0, sizeof(struct ast_smoother));
00062 s->size = size;
00063 }
00064
00065 struct ast_smoother *ast_smoother_new(int size)
00066 {
00067 struct ast_smoother *s;
00068 if (size < 1)
00069 return NULL;
00070 s = malloc(sizeof(struct ast_smoother));
00071 if (s)
00072 ast_smoother_reset(s, size);
00073 return s;
00074 }
00075
00076 int ast_smoother_get_flags(struct ast_smoother *s)
00077 {
00078 return s->flags;
00079 }
00080
00081 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
00082 {
00083 s->flags = flags;
00084 }
00085
00086 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
00087 {
00088 if (f->frametype != AST_FRAME_VOICE) {
00089 ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
00090 return -1;
00091 }
00092 if (!s->format) {
00093 s->format = f->subclass;
00094 s->samplesperbyte = (float)f->samples / (float)f->datalen;
00095 } else if (s->format != f->subclass) {
00096 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
00097 return -1;
00098 }
00099 if (s->len + f->datalen > SMOOTHER_SIZE) {
00100 ast_log(LOG_WARNING, "Out of smoother space\n");
00101 return -1;
00102 }
00103 if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
00104 && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
00105 if (!s->len) {
00106
00107
00108
00109 s->opt = f;
00110 return 0;
00111 } else {
00112 s->optimizablestream++;
00113 if (s->optimizablestream > 10) {
00114
00115
00116
00117
00118
00119 s->len = 0;
00120 s->opt = f;
00121 return 0;
00122 }
00123 }
00124 } else
00125 s->optimizablestream = 0;
00126 if (s->flags & AST_SMOOTHER_FLAG_G729) {
00127 if (s->len % 10) {
00128 ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
00129 return 0;
00130 }
00131 }
00132 if (swap)
00133 ast_memcpy_byteswap(s->data+s->len, f->data, f->samples);
00134 else
00135 memcpy(s->data + s->len, f->data, f->datalen);
00136
00137 if (!s->len || (!f->delivery.tv_sec && !f->delivery.tv_usec) ||
00138 (!s->delivery.tv_sec && !s->delivery.tv_usec))
00139 s->delivery = f->delivery;
00140 s->len += f->datalen;
00141 return 0;
00142 }
00143
00144 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
00145 {
00146 struct ast_frame *opt;
00147 int len;
00148
00149 if (s->opt) {
00150 if (s->opt->offset < AST_FRIENDLY_OFFSET)
00151 ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).",
00152 s->opt->offset);
00153 opt = s->opt;
00154 s->opt = NULL;
00155 return opt;
00156 }
00157
00158
00159 if (s->len < s->size) {
00160
00161 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
00162 return NULL;
00163 }
00164 len = s->size;
00165 if (len > s->len)
00166 len = s->len;
00167
00168 s->f.frametype = AST_FRAME_VOICE;
00169 s->f.subclass = s->format;
00170 s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
00171 s->f.offset = AST_FRIENDLY_OFFSET;
00172 s->f.datalen = len;
00173
00174 s->f.samples = len * s->samplesperbyte;
00175 s->f.delivery = s->delivery;
00176
00177 memcpy(s->f.data, s->data, len);
00178 s->len -= len;
00179
00180 if (s->len) {
00181
00182
00183 memmove(s->data, s->data + len, s->len);
00184 if (s->delivery.tv_sec || s->delivery.tv_usec) {
00185
00186 s->delivery.tv_sec += (len * s->samplesperbyte) / 8000.0;
00187 s->delivery.tv_usec += (((int)(len * s->samplesperbyte)) % 8000) * 125;
00188 if (s->delivery.tv_usec > 1000000) {
00189 s->delivery.tv_usec -= 1000000;
00190 s->delivery.tv_sec += 1;
00191 }
00192 }
00193 }
00194
00195 return &s->f;
00196 }
00197
00198 void ast_smoother_free(struct ast_smoother *s)
00199 {
00200 free(s);
00201 }
00202
00203 static struct ast_frame *ast_frame_header_new(void)
00204 {
00205 struct ast_frame *f;
00206 f = malloc(sizeof(struct ast_frame));
00207 if (f)
00208 memset(f, 0, sizeof(struct ast_frame));
00209 #ifdef TRACE_FRAMES
00210 if (f) {
00211 headers++;
00212 f->prev = NULL;
00213 ast_mutex_lock(&framelock);
00214 f->next = headerlist;
00215 if (headerlist)
00216 headerlist->prev = f;
00217 headerlist = f;
00218 ast_mutex_unlock(&framelock);
00219 }
00220 #endif
00221 return f;
00222 }
00223
00224
00225
00226
00227
00228
00229 void ast_frfree(struct ast_frame *fr)
00230 {
00231 if (fr->mallocd & AST_MALLOCD_DATA) {
00232 if (fr->data)
00233 free(fr->data - fr->offset);
00234 }
00235 if (fr->mallocd & AST_MALLOCD_SRC) {
00236 if (fr->src)
00237 free(fr->src);
00238 }
00239 if (fr->mallocd & AST_MALLOCD_HDR) {
00240 #ifdef TRACE_FRAMES
00241 headers--;
00242 ast_mutex_lock(&framelock);
00243 if (fr->next)
00244 fr->next->prev = fr->prev;
00245 if (fr->prev)
00246 fr->prev->next = fr->next;
00247 else
00248 headerlist = fr->next;
00249 ast_mutex_unlock(&framelock);
00250 #endif
00251 free(fr);
00252 }
00253 }
00254
00255 struct ast_frame *ast_frisolate(struct ast_frame *fr)
00256 {
00257 struct ast_frame *out;
00258 if (!(fr->mallocd & AST_MALLOCD_HDR)) {
00259
00260 out = ast_frame_header_new();
00261 if (!out) {
00262 ast_log(LOG_WARNING, "Out of memory\n");
00263 return NULL;
00264 }
00265 out->frametype = fr->frametype;
00266 out->subclass = fr->subclass;
00267 out->datalen = 0;
00268 out->samples = fr->samples;
00269 out->offset = 0;
00270 out->src = NULL;
00271 out->data = NULL;
00272 } else {
00273 out = fr;
00274 }
00275 if (!(fr->mallocd & AST_MALLOCD_SRC)) {
00276 if (fr->src)
00277 out->src = strdup(fr->src);
00278 } else
00279 out->src = fr->src;
00280 if (!(fr->mallocd & AST_MALLOCD_DATA)) {
00281 out->data = malloc(fr->datalen + AST_FRIENDLY_OFFSET);
00282 if (!out->data) {
00283 free(out);
00284 ast_log(LOG_WARNING, "Out of memory\n");
00285 return NULL;
00286 }
00287 out->data += AST_FRIENDLY_OFFSET;
00288 out->offset = AST_FRIENDLY_OFFSET;
00289 out->datalen = fr->datalen;
00290 memcpy(out->data, fr->data, fr->datalen);
00291 }
00292 out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
00293 return out;
00294 }
00295
00296 struct ast_frame *ast_frdup(struct ast_frame *f)
00297 {
00298 struct ast_frame *out;
00299 int len, srclen = 0;
00300 void *buf;
00301
00302 len = sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET + f->datalen;
00303
00304 if (f->src)
00305 srclen = strlen(f->src);
00306 if (srclen > 0)
00307 len += srclen + 1;
00308 buf = malloc(len);
00309 if (!buf)
00310 return NULL;
00311 out = buf;
00312
00313
00314 out->frametype = f->frametype;
00315 out->subclass = f->subclass;
00316 out->datalen = f->datalen;
00317 out->samples = f->samples;
00318 out->delivery = f->delivery;
00319 out->mallocd = AST_MALLOCD_HDR;
00320 out->offset = AST_FRIENDLY_OFFSET;
00321 out->data = buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
00322 if (srclen > 0) {
00323 out->src = out->data + f->datalen;
00324
00325 strcpy(out->src, f->src);
00326 } else
00327 out->src = NULL;
00328 out->prev = NULL;
00329 out->next = NULL;
00330 memcpy(out->data, f->data, out->datalen);
00331 return out;
00332 }
00333
00334 struct ast_frame *ast_fr_fdread(int fd)
00335 {
00336 char buf[65536];
00337 int res;
00338 int ttl = sizeof(struct ast_frame);
00339 struct ast_frame *f = (struct ast_frame *)buf;
00340
00341
00342
00343 while(ttl) {
00344 res = read(fd, buf, ttl);
00345 if (res < 0) {
00346 ast_log(LOG_WARNING, "Bad read on %d: %s\n", fd, strerror(errno));
00347 return NULL;
00348 }
00349 ttl -= res;
00350 }
00351
00352
00353 f->mallocd = 0;
00354
00355 f->data = buf + sizeof(struct ast_frame);
00356 f->offset = 0;
00357
00358 f->mallocd = 0;
00359
00360 f->src = (char *)__FUNCTION__;
00361 if (f->datalen > sizeof(buf) - sizeof(struct ast_frame)) {
00362
00363 ast_log(LOG_WARNING, "Strange read (%d bytes)\n", f->datalen);
00364 return NULL;
00365 }
00366 if (f->datalen) {
00367 if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
00368
00369 ast_log(LOG_WARNING, "How very strange, expected %d, got %d\n", f->datalen, res);
00370 return NULL;
00371 }
00372 }
00373 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
00374 return NULL;
00375 }
00376 return ast_frisolate(f);
00377 }
00378
00379
00380
00381
00382 int ast_fr_fdwrite(int fd, struct ast_frame *frame)
00383 {
00384
00385 if (write(fd, frame, sizeof(struct ast_frame)) != sizeof(struct ast_frame)) {
00386 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
00387 return -1;
00388 }
00389 if (write(fd, frame->data, frame->datalen) != frame->datalen) {
00390 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
00391 return -1;
00392 }
00393 return 0;
00394 }
00395
00396 int ast_fr_fdhangup(int fd)
00397 {
00398 struct ast_frame hangup = {
00399 AST_FRAME_CONTROL,
00400 AST_CONTROL_HANGUP
00401 };
00402 return ast_fr_fdwrite(fd, &hangup);
00403 }
00404
00405 void ast_memcpy_byteswap(void *dst, void *src, int samples)
00406 {
00407 int i;
00408 unsigned short *dst_s = dst;
00409 unsigned short *src_s = src;
00410
00411 for (i=0; i<samples; i++)
00412 dst_s[i] = (src_s[i]<<8)|(src_s[i]>>8);
00413 }
00414
00415 static struct ast_format_list AST_FORMAT_LIST[] = {
00416 { 1, AST_FORMAT_G723_1 , "g723" , "G.723.1"},
00417 { 1, AST_FORMAT_GSM, "gsm" , "GSM"},
00418 { 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law" },
00419 { 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law" },
00420 { 1, AST_FORMAT_G726, "g726", "G.726" },
00421 { 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM"},
00422 { 1, AST_FORMAT_SLINEAR, "slin", "16 bit Signed Linear PCM"},
00423 { 1, AST_FORMAT_LPC10, "lpc10", "LPC10" },
00424 { 1, AST_FORMAT_G729A, "g729", "G.729A" },
00425 { 1, AST_FORMAT_SPEEX, "speex", "SpeeX" },
00426 { 1, AST_FORMAT_ILBC, "ilbc", "iLBC"},
00427 { 0, 0, "nothing", "undefined" },
00428 { 0, 0, "nothing", "undefined" },
00429 { 0, 0, "nothing", "undefined" },
00430 { 0, 0, "nothing", "undefined" },
00431 { 0, AST_FORMAT_MAX_AUDIO, "maxaudio", "Maximum audio format" },
00432 { 1, AST_FORMAT_JPEG, "jpeg", "JPEG image"},
00433 { 1, AST_FORMAT_PNG, "png", "PNG image"},
00434 { 1, AST_FORMAT_H261, "h261", "H.261 Video" },
00435 { 1, AST_FORMAT_H263, "h263", "H.263 Video" },
00436 { 0, 0, "nothing", "undefined" },
00437 { 0, 0, "nothing", "undefined" },
00438 { 0, 0, "nothing", "undefined" },
00439 { 0, 0, "nothing", "undefined" },
00440 { 0, AST_FORMAT_MAX_VIDEO, "maxvideo", "Maximum video format" },
00441 };
00442
00443 struct ast_format_list *ast_get_format_list_index(int index) {
00444 return &AST_FORMAT_LIST[index];
00445 }
00446
00447 struct ast_format_list *ast_get_format_list(size_t *size) {
00448 *size = (sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list));
00449 return AST_FORMAT_LIST;
00450 }
00451
00452 char* ast_getformatname(int format)
00453 {
00454 int x = 0;
00455 char *ret = "unknown";
00456 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00457 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
00458 ret = AST_FORMAT_LIST[x].name;
00459 break;
00460 }
00461 }
00462 return ret;
00463 }
00464
00465 char *ast_getformatname_multiple(char *buf, size_t size, int format) {
00466
00467 int x = 0;
00468 unsigned len;
00469 char *end = buf;
00470 char *start = buf;
00471 if (!size) return buf;
00472 snprintf(end, size, "0x%x (", format);
00473 len = strlen(end);
00474 end += len;
00475 size -= len;
00476 start = end;
00477 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00478 if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
00479 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
00480 len = strlen(end);
00481 end += len;
00482 size -= len;
00483 }
00484 }
00485 if (start == end)
00486 snprintf(start, size, "nothing)");
00487 else if (size > 1)
00488 *(end -1) = ')';
00489 return buf;
00490 }
00491
00492 static struct ast_codec_alias_table {
00493 char *alias;
00494 char *realname;
00495
00496 } ast_codec_alias_table[] = {
00497 {"slinear","slin"},
00498 {"g723.1","g723"},
00499 };
00500
00501 static char *ast_expand_codec_alias(char *in) {
00502 int x = 0;
00503
00504 for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(struct ast_codec_alias_table) ; x++) {
00505 if(!strcmp(in,ast_codec_alias_table[x].alias))
00506 return ast_codec_alias_table[x].realname;
00507 }
00508 return in;
00509 }
00510
00511 int ast_getformatbyname(char *name)
00512 {
00513 int x = 0, all = 0, format = 0;
00514
00515 all = strcasecmp(name, "all") ? 0 : 1;
00516 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00517 if(AST_FORMAT_LIST[x].visible && (all ||
00518 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
00519 !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
00520 format |= AST_FORMAT_LIST[x].bits;
00521 if(!all)
00522 break;
00523 }
00524 }
00525
00526 return format;
00527 }
00528
00529 char *ast_codec2str(int codec) {
00530 int x = 0;
00531 char *ret = "unknown";
00532 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00533 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
00534 ret = AST_FORMAT_LIST[x].desc;
00535 break;
00536 }
00537 }
00538 return ret;
00539 }
00540
00541 static int show_codecs(int fd, int argc, char *argv[])
00542 {
00543 int i, found=0;
00544 char hex[25];
00545
00546 if ((argc < 2) || (argc > 3))
00547 return RESULT_SHOWUSAGE;
00548
00549 if (getenv("I_AM_NOT_AN_IDIOT") == NULL)
00550 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
00551 "\tIt does not indicate anything about your configuration.\n");
00552
00553 ast_cli(fd, "%11s %9s %10s TYPE %5s %s\n","INT","BINARY","HEX","NAME","DESC");
00554 ast_cli(fd, "--------------------------------------------------------------------------------\n");
00555 if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
00556 found = 1;
00557 for (i=0;i<11;i++) {
00558 snprintf(hex,25,"(0x%x)",1<<i);
00559 ast_cli(fd, "%11u (1 << %2d) %10s audio %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00560 }
00561 }
00562
00563 if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
00564 found = 1;
00565 for (i=16;i<18;i++) {
00566 snprintf(hex,25,"(0x%x)",1<<i);
00567 ast_cli(fd, "%11u (1 << %2d) %10s image %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00568 }
00569 }
00570
00571 if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
00572 found = 1;
00573 for (i=18;i<20;i++) {
00574 snprintf(hex,25,"(0x%x)",1<<i);
00575 ast_cli(fd, "%11u (1 << %2d) %10s video %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00576 }
00577 }
00578
00579 if (! found)
00580 return RESULT_SHOWUSAGE;
00581 else
00582 return RESULT_SUCCESS;
00583 }
00584
00585 static char frame_show_codecs_usage[] =
00586 "Usage: show [audio|video|image] codecs\n"
00587 " Displays codec mapping\n";
00588
00589 struct ast_cli_entry cli_show_codecs =
00590 { { "show", "codecs", NULL }, show_codecs, "Shows codecs", frame_show_codecs_usage };
00591 struct ast_cli_entry cli_show_codecs_audio =
00592 { { "show", "audio", "codecs", NULL }, show_codecs, "Shows audio codecs", frame_show_codecs_usage };
00593 struct ast_cli_entry cli_show_codecs_video =
00594 { { "show", "video", "codecs", NULL }, show_codecs, "Shows video codecs", frame_show_codecs_usage };
00595 struct ast_cli_entry cli_show_codecs_image =
00596 { { "show", "image", "codecs", NULL }, show_codecs, "Shows image codecs", frame_show_codecs_usage };
00597
00598 static int show_codec_n(int fd, int argc, char *argv[])
00599 {
00600 int codec, i, found=0;
00601
00602 if (argc != 3)
00603 return RESULT_SHOWUSAGE;
00604
00605 if (sscanf(argv[2],"%d",&codec) != 1)
00606 return RESULT_SHOWUSAGE;
00607
00608 for (i=0;i<32;i++)
00609 if (codec & (1 << i)) {
00610 found = 1;
00611 ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
00612 }
00613
00614 if (! found)
00615 ast_cli(fd, "Codec %d not found\n", codec);
00616
00617 return RESULT_SUCCESS;
00618 }
00619
00620 static char frame_show_codec_n_usage[] =
00621 "Usage: show codec <number>\n"
00622 " Displays codec mapping\n";
00623
00624 struct ast_cli_entry cli_show_codec_n =
00625 { { "show", "codec", NULL }, show_codec_n, "Shows a specific codec", frame_show_codec_n_usage };
00626
00627 void ast_frame_dump(char *name, struct ast_frame *f, char *prefix)
00628 {
00629 char *n = "unknown";
00630 char ftype[40] = "Unknown Frametype";
00631 char cft[80];
00632 char subclass[40] = "Unknown Subclass";
00633 char csub[80];
00634 char moreinfo[40] = "";
00635 char cn[60];
00636 char cp[40];
00637 char cmn[40];
00638 if (name)
00639 n = name;
00640 if (!f) {
00641 ast_verbose("%s [ %s (NULL) ] [%s]\n",
00642 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00643 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00644 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00645 return;
00646 }
00647
00648 if (f->frametype == AST_FRAME_VOICE)
00649 return;
00650 if (f->frametype == AST_FRAME_VIDEO)
00651 return;
00652 switch(f->frametype) {
00653 case AST_FRAME_DTMF:
00654 strcpy(ftype, "DTMF");
00655 subclass[0] = f->subclass;
00656 subclass[1] = '\0';
00657 break;
00658 case AST_FRAME_CONTROL:
00659 strcpy(ftype, "Control");
00660 switch(f->subclass) {
00661 case AST_CONTROL_HANGUP:
00662 strcpy(subclass, "Hangup");
00663 break;
00664 case AST_CONTROL_RING:
00665 strcpy(subclass, "Ring");
00666 break;
00667 case AST_CONTROL_RINGING:
00668 strcpy(subclass, "Ringing");
00669 break;
00670 case AST_CONTROL_ANSWER:
00671 strcpy(subclass, "Answer");
00672 break;
00673 case AST_CONTROL_BUSY:
00674 strcpy(subclass, "Busy");
00675 break;
00676 case AST_CONTROL_TAKEOFFHOOK:
00677 strcpy(subclass, "Take Off Hook");
00678 break;
00679 case AST_CONTROL_OFFHOOK:
00680 strcpy(subclass, "Line Off Hook");
00681 break;
00682 case AST_CONTROL_CONGESTION:
00683 strcpy(subclass, "Congestion");
00684 break;
00685 case AST_CONTROL_FLASH:
00686 strcpy(subclass, "Flash");
00687 break;
00688 case AST_CONTROL_WINK:
00689 strcpy(subclass, "Wink");
00690 break;
00691 case AST_CONTROL_OPTION:
00692 strcpy(subclass, "Option");
00693 break;
00694 case AST_CONTROL_RADIO_KEY:
00695 strcpy(subclass, "Key Radio");
00696 break;
00697 case AST_CONTROL_RADIO_UNKEY:
00698 strcpy(subclass, "Unkey Radio");
00699 break;
00700 case -1:
00701 strcpy(subclass, "Stop generators");
00702 break;
00703 default:
00704 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
00705 }
00706 break;
00707 case AST_FRAME_NULL:
00708 strcpy(ftype, "Null Frame");
00709 strcpy(subclass, "N/A");
00710 break;
00711 case AST_FRAME_IAX:
00712
00713 strcpy(ftype, "IAX Specific");
00714 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
00715 break;
00716 case AST_FRAME_TEXT:
00717 strcpy(ftype, "Text");
00718 strcpy(subclass, "N/A");
00719 strncpy(moreinfo, f->data, sizeof(moreinfo) - 1);
00720 break;
00721 case AST_FRAME_IMAGE:
00722 strcpy(ftype, "Image");
00723 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
00724 break;
00725 case AST_FRAME_HTML:
00726 strcpy(ftype, "HTML");
00727 switch(f->subclass) {
00728 case AST_HTML_URL:
00729 strcpy(subclass, "URL");
00730 strncpy(moreinfo, f->data, sizeof(moreinfo) - 1);
00731 break;
00732 case AST_HTML_DATA:
00733 strcpy(subclass, "Data");
00734 break;
00735 case AST_HTML_BEGIN:
00736 strcpy(subclass, "Begin");
00737 break;
00738 case AST_HTML_END:
00739 strcpy(subclass, "End");
00740 break;
00741 case AST_HTML_LDCOMPLETE:
00742 strcpy(subclass, "Load Complete");
00743 break;
00744 case AST_HTML_NOSUPPORT:
00745 strcpy(subclass, "No Support");
00746 break;
00747 case AST_HTML_LINKURL:
00748 strcpy(subclass, "Link URL");
00749 strncpy(moreinfo, f->data, sizeof(moreinfo) - 1);
00750 break;
00751 case AST_HTML_UNLINK:
00752 strcpy(subclass, "Unlink");
00753 break;
00754 case AST_HTML_LINKREJECT:
00755 strcpy(subclass, "Link Reject");
00756 break;
00757 default:
00758 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
00759 break;
00760 }
00761 break;
00762 default:
00763 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
00764 }
00765 if (!ast_strlen_zero(moreinfo))
00766 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
00767 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00768 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00769 f->frametype,
00770 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00771 f->subclass,
00772 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
00773 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00774 else
00775 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
00776 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00777 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00778 f->frametype,
00779 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00780 f->subclass,
00781 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00782
00783 }
00784
00785
00786 #ifdef TRACE_FRAMES
00787 static int show_frame_stats(int fd, int argc, char *argv[])
00788 {
00789 struct ast_frame *f;
00790 int x=1;
00791 if (argc != 3)
00792 return RESULT_SHOWUSAGE;
00793 ast_cli(fd, " Framer Statistics \n");
00794 ast_cli(fd, "---------------------------\n");
00795 ast_cli(fd, "Total allocated headers: %d\n", headers);
00796 ast_cli(fd, "Queue Dump:\n");
00797 ast_mutex_lock(&framelock);
00798 for (f=headerlist; f; f = f->next) {
00799 ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
00800 }
00801 ast_mutex_unlock(&framelock);
00802 return RESULT_SUCCESS;
00803 }
00804
00805 static char frame_stats_usage[] =
00806 "Usage: show frame stats\n"
00807 " Displays debugging statistics from framer\n";
00808
00809 struct ast_cli_entry cli_frame_stats =
00810 { { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage };
00811 #endif
00812
00813 int init_framer(void)
00814 {
00815 #ifdef TRACE_FRAMES
00816 ast_cli_register(&cli_frame_stats);
00817 #endif
00818 ast_cli_register(&cli_show_codecs);
00819 ast_cli_register(&cli_show_codecs_audio);
00820 ast_cli_register(&cli_show_codecs_video);
00821 ast_cli_register(&cli_show_codecs_image);
00822 ast_cli_register(&cli_show_codec_n);
00823 return 0;
00824 }
00825
00826 void ast_codec_pref_shift(struct ast_codec_pref *pref, char *buf, size_t size, int right)
00827 {
00828 int x = 0, differential = 65, mem = 0;
00829 char *from = NULL, *to = NULL;
00830
00831 if(right) {
00832 from = pref->order;
00833 to = buf;
00834 mem = size;
00835 } else {
00836 to = pref->order;
00837 from = buf;
00838 mem = 32;
00839 }
00840
00841 memset(to, 0, mem);
00842 for (x = 0; x < 32 ; x++) {
00843 if(!from[x])
00844 break;
00845 to[x] = right ? (from[x] + differential) : (from[x] - differential);
00846 }
00847 }
00848
00849 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
00850 {
00851 int x = 0, codec = 0;
00852 size_t total_len = 0, slen = 0;
00853 char *formatname = 0;
00854
00855 memset(buf,0,size);
00856 total_len = size;
00857 buf[0] = '(';
00858 total_len--;
00859 for(x = 0; x < 32 ; x++) {
00860 if(total_len <= 0)
00861 break;
00862 if(!(codec = ast_codec_pref_index(pref,x)))
00863 break;
00864 if((formatname = ast_getformatname(codec))) {
00865 slen = strlen(formatname);
00866 if(slen > total_len)
00867 break;
00868 strncat(buf,formatname,total_len);
00869 total_len -= slen;
00870 }
00871 if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
00872 strncat(buf,"|",total_len);
00873 total_len--;
00874 }
00875 }
00876 if(total_len) {
00877 strncat(buf,")",total_len);
00878 total_len--;
00879 }
00880
00881 return size - total_len;
00882 }
00883
00884 int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
00885 {
00886 int slot = 0;
00887
00888
00889 if((index >= 0) && (index < sizeof(pref->order))) {
00890 slot = pref->order[index];
00891 }
00892
00893 return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
00894 }
00895
00896
00897 void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
00898 {
00899 struct ast_codec_pref oldorder;
00900 int x=0, y=0;
00901 size_t size = 0;
00902 int slot = 0;
00903
00904 if(!pref->order[0])
00905 return;
00906
00907 size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
00908
00909 memcpy(&oldorder,pref,sizeof(struct ast_codec_pref));
00910 memset(pref,0,sizeof(struct ast_codec_pref));
00911
00912 for (x = 0; x < size; x++) {
00913 slot = oldorder.order[x];
00914 if(! slot)
00915 break;
00916 if(AST_FORMAT_LIST[slot-1].bits != format)
00917 pref->order[y++] = slot;
00918 }
00919
00920 }
00921
00922
00923 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
00924 {
00925 size_t size = 0;
00926 int x = 0, newindex = -1;
00927
00928 ast_codec_pref_remove(pref, format);
00929 size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
00930
00931 for (x = 0; x < size; x++) {
00932 if(AST_FORMAT_LIST[x].bits == format) {
00933 newindex = x + 1;
00934 break;
00935 }
00936 }
00937
00938 if(newindex) {
00939 for (x = 0; x < size; x++) {
00940 if(!pref->order[x]) {
00941 pref->order[x] = newindex;
00942 break;
00943 }
00944 }
00945 }
00946
00947 return x;
00948 }
00949
00950
00951
00952 int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
00953 {
00954 size_t size = 0;
00955 int x = 0, ret = 0, slot = 0;
00956
00957 size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
00958 for (x = 0; x < size; x++) {
00959 slot = pref->order[x];
00960
00961 if(!slot)
00962 break;
00963 if ( formats & AST_FORMAT_LIST[slot-1].bits ) {
00964 ret = AST_FORMAT_LIST[slot-1].bits;
00965 break;
00966 }
00967 }
00968 if(ret)
00969 return ret;
00970
00971 return find_best ? ast_best_codec(formats) : 0;
00972 }
00973
00974 void ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, char *list, int allowing)
00975 {
00976 int format_i = 0;
00977 char *next_format = NULL, *last_format = NULL;
00978
00979 last_format = ast_strdupa(list);
00980 while(last_format) {
00981 if((next_format = strchr(last_format, ','))) {
00982 *next_format = '\0';
00983 next_format++;
00984 }
00985 if ((format_i = ast_getformatbyname(last_format)) > 0) {
00986 if (mask) {
00987 if (allowing)
00988 (*mask) |= format_i;
00989 else
00990 (*mask) &= ~format_i;
00991 }
00992
00993 if(pref && strcasecmp(last_format, "all")) {
00994 if(allowing)
00995 ast_codec_pref_append(pref, format_i);
00996 else
00997 ast_codec_pref_remove(pref, format_i);
00998 } else if(!allowing)
00999 memset(pref, 0, sizeof(struct ast_codec_pref));
01000 } else
01001 ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", last_format);
01002
01003 last_format = next_format;
01004 }
01005 }
01006
01007