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/cli.h>
00019
#include <asterisk/term.h>
00020
#include <asterisk/utils.h>
00021
#include <stdlib.h>
00022
#include <unistd.h>
00023
#include <string.h>
00024
#include <errno.h>
00025
#include <stdio.h>
00026
#include "asterisk.h"
00027
00028
#ifdef TRACE_FRAMES
00029
static int headers = 0;
00030
static struct ast_frame *headerlist = NULL;
00031
AST_MUTEX_DEFINE_STATIC(framelock);
00032
#endif
00033
00034 #define SMOOTHER_SIZE 8000
00035
00036 struct ast_smoother {
00037 int size;
00038 int format;
00039 int readdata;
00040 int optimizablestream;
00041 int flags;
00042 float samplesperbyte;
00043 struct ast_frame f;
00044 struct timeval delivery;
00045 char data[
SMOOTHER_SIZE];
00046 char framedata[
SMOOTHER_SIZE +
AST_FRIENDLY_OFFSET];
00047 struct ast_frame *
opt;
00048 int len;
00049 };
00050
00051 void ast_smoother_reset(
struct ast_smoother *s,
int size)
00052 {
00053 memset(
s, 0,
sizeof(
struct ast_smoother));
00054
s->size = size;
00055 }
00056
00057 struct ast_smoother *
ast_smoother_new(
int size)
00058 {
00059
struct ast_smoother *
s;
00060
if (size < 1)
00061
return NULL;
00062
s =
malloc(
sizeof(
struct ast_smoother));
00063
if (
s)
00064
ast_smoother_reset(
s, size);
00065
return s;
00066 }
00067
00068 int ast_smoother_get_flags(
struct ast_smoother *s)
00069 {
00070
return s->flags;
00071 }
00072
00073 void ast_smoother_set_flags(
struct ast_smoother *s,
int flags)
00074 {
00075
s->flags = flags;
00076 }
00077
00078 int ast_smoother_feed(
struct ast_smoother *s,
struct ast_frame *f)
00079 {
00080
if (f->
frametype !=
AST_FRAME_VOICE) {
00081
ast_log(
LOG_WARNING,
"Huh? Can't smooth a non-voice frame!\n");
00082
return -1;
00083 }
00084
if (!
s->format) {
00085
s->format = f->
subclass;
00086
s->samplesperbyte = (
float)f->
samples / (
float)f->
datalen;
00087 }
else if (
s->format != f->
subclass) {
00088
ast_log(
LOG_WARNING,
"Smoother was working on %d format frames, now trying to feed %d?\n",
s->format, f->
subclass);
00089
return -1;
00090 }
00091
if (
s->len + f->
datalen >
SMOOTHER_SIZE) {
00092
ast_log(
LOG_WARNING,
"Out of smoother space\n");
00093
return -1;
00094 }
00095
if (((f->
datalen ==
s->size) || ((f->
datalen < 10) && (
s->flags &
AST_SMOOTHER_FLAG_G729)))
00096 && !
s->opt && (f->
offset >=
AST_MIN_OFFSET)) {
00097
if (!
s->len) {
00098
00099
00100
00101
s->opt = f;
00102
return 0;
00103 }
else {
00104
s->optimizablestream++;
00105
if (
s->optimizablestream > 10) {
00106
00107
00108
00109
00110
00111
s->len = 0;
00112
s->opt = f;
00113
return 0;
00114 }
00115 }
00116 }
else
00117
s->optimizablestream = 0;
00118
if (
s->flags &
AST_SMOOTHER_FLAG_G729) {
00119
if (
s->len % 10) {
00120
ast_log(
LOG_NOTICE,
"Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
00121
return 0;
00122 }
00123 }
00124 memcpy(
s->data +
s->len, f->
data, f->
datalen);
00125
00126
if (!
s->len || (!f->
delivery.tv_sec && !f->
delivery.tv_usec) ||
00127 (!
s->delivery.tv_sec && !
s->delivery.tv_usec))
00128
s->delivery = f->
delivery;
00129
s->len += f->
datalen;
00130
return 0;
00131 }
00132
00133 struct ast_frame *
ast_smoother_read(
struct ast_smoother *s)
00134 {
00135
struct ast_frame *opt;
00136
int len;
00137
00138
if (
s->opt) {
00139 opt =
s->opt;
00140
s->opt = NULL;
00141
return opt;
00142 }
00143
00144
00145
if (
s->len <
s->size) {
00146
00147
if (!((
s->flags &
AST_SMOOTHER_FLAG_G729) && (
s->size % 10)))
00148
return NULL;
00149 }
00150 len =
s->size;
00151
if (len >
s->len)
00152 len =
s->len;
00153
00154
s->f.frametype =
AST_FRAME_VOICE;
00155
s->f.subclass =
s->format;
00156
s->f.data =
s->framedata +
AST_FRIENDLY_OFFSET;
00157
s->f.offset =
AST_FRIENDLY_OFFSET;
00158
s->f.datalen = len;
00159
00160
s->f.samples = len *
s->samplesperbyte;
00161
s->f.delivery =
s->delivery;
00162
00163 memcpy(
s->f.data,
s->data, len);
00164
s->len -= len;
00165
00166
if (
s->len) {
00167
00168
00169 memmove(
s->data,
s->data + len,
s->len);
00170
if (
s->delivery.tv_sec ||
s->delivery.tv_usec) {
00171
00172
s->delivery.tv_sec += (len *
s->samplesperbyte) / 8000.0;
00173
s->delivery.tv_usec += (((
int)(len *
s->samplesperbyte)) % 8000) * 125;
00174
if (
s->delivery.tv_usec > 1000000) {
00175
s->delivery.tv_usec -= 1000000;
00176
s->delivery.tv_sec += 1;
00177 }
00178 }
00179 }
00180
00181
return &
s->f;
00182 }
00183
00184 void ast_smoother_free(
struct ast_smoother *s)
00185 {
00186
free(
s);
00187 }
00188
00189
static struct ast_frame *ast_frame_header_new(
void)
00190 {
00191
struct ast_frame *f;
00192 f =
malloc(
sizeof(
struct ast_frame));
00193
if (f)
00194 memset(f, 0,
sizeof(
struct ast_frame));
00195
#ifdef TRACE_FRAMES
00196
if (f) {
00197 headers++;
00198 f->prev = NULL;
00199
ast_mutex_lock(&framelock);
00200 f->next = headerlist;
00201
if (headerlist)
00202 headerlist->prev = f;
00203 headerlist = f;
00204
ast_mutex_unlock(&framelock);
00205 }
00206
#endif
00207
return f;
00208 }
00209
00210
00211
00212
00213
00214
00215 void ast_frfree(
struct ast_frame *fr)
00216 {
00217
if (fr->
mallocd &
AST_MALLOCD_DATA) {
00218
if (fr->
data)
00219
free(fr->
data - fr->
offset);
00220 }
00221
if (fr->
mallocd &
AST_MALLOCD_SRC) {
00222
if (fr->
src)
00223
free(fr->
src);
00224 }
00225
if (fr->
mallocd &
AST_MALLOCD_HDR) {
00226
#ifdef TRACE_FRAMES
00227
headers--;
00228
ast_mutex_lock(&framelock);
00229
if (fr->
next)
00230 fr->
next->
prev = fr->
prev;
00231
if (fr->
prev)
00232 fr->
prev->
next = fr->
next;
00233
else
00234 headerlist = fr->
next;
00235
ast_mutex_unlock(&framelock);
00236
#endif
00237
free(fr);
00238 }
00239 }
00240
00241 struct ast_frame *
ast_frisolate(
struct ast_frame *fr)
00242 {
00243
struct ast_frame *out;
00244
if (!(fr->
mallocd &
AST_MALLOCD_HDR)) {
00245
00246 out = ast_frame_header_new();
00247
if (!out) {
00248
ast_log(
LOG_WARNING,
"Out of memory\n");
00249
return NULL;
00250 }
00251 out->frametype = fr->
frametype;
00252 out->subclass = fr->
subclass;
00253 out->datalen = 0;
00254 out->samples = fr->
samples;
00255 out->offset = 0;
00256 out->src = NULL;
00257 out->data = NULL;
00258 }
else {
00259 out = fr;
00260 }
00261
if (!(fr->
mallocd &
AST_MALLOCD_SRC)) {
00262
if (fr->
src)
00263 out->
src =
strdup(fr->
src);
00264 }
else
00265 out->src = fr->
src;
00266
if (!(fr->
mallocd &
AST_MALLOCD_DATA)) {
00267 out->data =
malloc(fr->
datalen +
AST_FRIENDLY_OFFSET);
00268
if (!out->data) {
00269
free(out);
00270
ast_log(
LOG_WARNING,
"Out of memory\n");
00271
return NULL;
00272 }
00273 out->data +=
AST_FRIENDLY_OFFSET;
00274 out->offset =
AST_FRIENDLY_OFFSET;
00275 out->datalen = fr->
datalen;
00276 memcpy(out->data, fr->
data, fr->
datalen);
00277 }
00278 out->mallocd =
AST_MALLOCD_HDR |
AST_MALLOCD_SRC |
AST_MALLOCD_DATA;
00279
return out;
00280 }
00281
00282 struct ast_frame *
ast_frdup(
struct ast_frame *f)
00283 {
00284
struct ast_frame *out;
00285
int len, srclen = 0;
00286
void *buf;
00287
00288 len =
sizeof(
struct ast_frame) +
AST_FRIENDLY_OFFSET + f->datalen;
00289
00290
if (f->
src)
00291 srclen = strlen(f->
src);
00292
if (srclen > 0)
00293 len += srclen + 1;
00294 buf =
malloc(len);
00295
if (!buf)
00296
return NULL;
00297 out = buf;
00298
00299
00300 out->frametype = f->
frametype;
00301 out->subclass = f->
subclass;
00302 out->datalen = f->
datalen;
00303 out->samples = f->
samples;
00304 out->delivery = f->
delivery;
00305 out->mallocd =
AST_MALLOCD_HDR;
00306 out->offset =
AST_FRIENDLY_OFFSET;
00307 out->data = buf +
sizeof(
struct ast_frame) +
AST_FRIENDLY_OFFSET;
00308
if (srclen > 0) {
00309 out->src = out->data + f->
datalen;
00310
00311 strcpy(out->src, f->
src);
00312 }
else
00313 out->src = NULL;
00314 out->prev = NULL;
00315 out->next = NULL;
00316 memcpy(out->data, f->
data, out->datalen);
00317
return out;
00318 }
00319
00320 struct ast_frame *
ast_fr_fdread(
int fd)
00321 {
00322
char buf[65536];
00323
int res;
00324
int ttl =
sizeof(
struct ast_frame);
00325
struct ast_frame *f = (
struct ast_frame *)buf;
00326
00327
00328
00329
while(ttl) {
00330 res = read(fd, buf, ttl);
00331
if (res < 0) {
00332
ast_log(
LOG_WARNING,
"Bad read on %d: %s\n", fd, strerror(errno));
00333
return NULL;
00334 }
00335 ttl -= res;
00336 }
00337
00338
00339 f->mallocd = 0;
00340
00341 f->data = buf +
sizeof(
struct ast_frame);
00342 f->offset = 0;
00343
00344 f->mallocd = 0;
00345
00346 f->src = __FUNCTION__;
00347
if (f->datalen >
sizeof(buf) -
sizeof(
struct ast_frame)) {
00348
00349
ast_log(
LOG_WARNING,
"Strange read (%d bytes)\n", f->datalen);
00350
return NULL;
00351 }
00352
if (f->datalen) {
00353
if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
00354
00355
ast_log(
LOG_WARNING,
"How very strange, expected %d, got %d\n", f->datalen, res);
00356
return NULL;
00357 }
00358 }
00359
if ((f->frametype ==
AST_FRAME_CONTROL) && (f->subclass ==
AST_CONTROL_HANGUP)) {
00360
return NULL;
00361 }
00362
return ast_frisolate(f);
00363 }
00364
00365
00366
00367
00368 int ast_fr_fdwrite(
int fd,
struct ast_frame *frame)
00369 {
00370
00371
if (write(fd, frame,
sizeof(
struct ast_frame)) !=
sizeof(
struct ast_frame)) {
00372
ast_log(
LOG_WARNING,
"Write error: %s\n", strerror(errno));
00373
return -1;
00374 }
00375
if (write(fd, frame->
data, frame->
datalen) != frame->
datalen) {
00376
ast_log(
LOG_WARNING,
"Write error: %s\n", strerror(errno));
00377
return -1;
00378 }
00379
return 0;
00380 }
00381
00382 int ast_fr_fdhangup(
int fd)
00383 {
00384
struct ast_frame hangup = {
00385
AST_FRAME_CONTROL,
00386
AST_CONTROL_HANGUP
00387 };
00388
return ast_fr_fdwrite(fd, &hangup);
00389 }
00390
00391 char*
ast_getformatname(
int format)
00392 {
00393
if (format ==
AST_FORMAT_G723_1)
00394
return "G723";
00395
else if (format ==
AST_FORMAT_GSM)
00396
return "GSM";
00397
else if (format ==
AST_FORMAT_ULAW)
00398
return "ULAW";
00399
else if (format ==
AST_FORMAT_ALAW)
00400
return "ALAW";
00401
else if (format ==
AST_FORMAT_G726)
00402
return "G726";
00403
else if (format ==
AST_FORMAT_SLINEAR)
00404
return "SLINR";
00405
else if (format ==
AST_FORMAT_LPC10)
00406
return "LPC10";
00407
else if (format ==
AST_FORMAT_ADPCM)
00408
return "ADPCM";
00409
else if (format ==
AST_FORMAT_G729A)
00410
return "G729A";
00411
else if (format ==
AST_FORMAT_SPEEX)
00412
return "SPEEX";
00413
else if (format ==
AST_FORMAT_ILBC)
00414
return "ILBC";
00415
else if (format ==
AST_FORMAT_JPEG)
00416
return "JPEG";
00417
else if (format ==
AST_FORMAT_PNG)
00418
return "PNG";
00419
else if (format ==
AST_FORMAT_H261)
00420
return "H261";
00421
else if (format ==
AST_FORMAT_H263)
00422
return "H263";
00423
return "UNKN";
00424 }
00425
00426 char*
ast_getformatname_multiple(
char *buf,
unsigned n,
int format) {
00427
unsigned u=1;
00428
unsigned len;
00429
char *b = buf;
00430
char *start = buf;
00431
if (!n)
return buf;
00432 snprintf(b,n,
"0x%x(",format);
00433 len = strlen(b);
00434 b += len;
00435 n -= len;
00436 start = b;
00437
while (u) {
00438
if (u&format) {
00439 snprintf(b,n,
"%s|",
ast_getformatname(u));
00440 len = strlen(b);
00441 b += len;
00442 n -= len;
00443 }
00444 u *= 2;
00445 }
00446
if (start==b)
00447 snprintf(start,n,
"EMPTY)");
00448
else if (n>1)
00449 b[-1]=
')';
00450
return buf;
00451 }
00452
00453 int ast_getformatbyname(
char *name)
00454 {
00455
if (!strcasecmp(name,
"g723.1"))
00456
return AST_FORMAT_G723_1;
00457
else if (!strcasecmp(name,
"gsm"))
00458
return AST_FORMAT_GSM;
00459
else if (!strcasecmp(name,
"ulaw"))
00460
return AST_FORMAT_ULAW;
00461
else if (!strcasecmp(name,
"alaw"))
00462
return AST_FORMAT_ALAW;
00463
else if (!strcasecmp(name,
"g726"))
00464
return AST_FORMAT_G726;
00465
else if (!strcasecmp(name,
"slinear"))
00466
return AST_FORMAT_SLINEAR;
00467
else if (!strcasecmp(name,
"lpc10"))
00468
return AST_FORMAT_LPC10;
00469
else if (!strcasecmp(name,
"adpcm"))
00470
return AST_FORMAT_ADPCM;
00471
else if (!strcasecmp(name,
"g729"))
00472
return AST_FORMAT_G729A;
00473
else if (!strcasecmp(name,
"speex"))
00474
return AST_FORMAT_SPEEX;
00475
else if (!strcasecmp(name,
"ilbc"))
00476
return AST_FORMAT_ILBC;
00477
else if (!strcasecmp(name,
"h261"))
00478
return AST_FORMAT_H261;
00479
else if (!strcasecmp(name,
"h263"))
00480
return AST_FORMAT_H263;
00481
else if (!strcasecmp(name,
"all"))
00482
return 0x7FFFFFFF;
00483
return 0;
00484 }
00485
00486 char *
ast_codec2str(
int codec) {
00487
static char codecs[25][30] = {
00488
00489
"G.723.1",
00490
"GSM",
00491
"G.711 u-law",
00492
"G.711 A-law",
00493
"G.726",
00494
"ADPCM",
00495
"16 bit Signed Linear PCM",
00496
"LPC10",
00497
"G.729A audio",
00498
"SpeeX",
00499
"iLBC",
00500
"undefined",
00501
"undefined",
00502
"undefined",
00503
"undefined",
00504
"Maximum audio format",
00505
00506
"JPEG image",
00507
"PNG image",
00508
"H.261 Video",
00509
"H.263 Video",
00510
"undefined",
00511
"undefined",
00512
"undefined",
00513
"undefined",
00514
"Maximum video format",
00515 };
00516
if ((codec >= 0) && (codec <= 24))
00517
return codecs[codec];
00518
else
00519
return "unknown";
00520 }
00521
00522
static int show_codecs(
int fd,
int argc,
char *argv[])
00523 {
00524
int i, found=0;
00525
00526
if ((argc < 2) || (argc > 3))
00527
return RESULT_SHOWUSAGE;
00528
00529
if (getenv(
"I_AM_NOT_AN_IDIOT") == NULL)
00530
ast_cli(fd,
"Disclaimer: this command is for informational purposes only.\n"
00531
"\tIt does not indicate anything about your configuration.\n");
00532
00533
if ((argc == 2) || (!strcasecmp(argv[1],
"audio"))) {
00534 found = 1;
00535
for (i=0;i<11;i++)
00536
ast_cli(fd,
"%11u (1 << %2d) %s\n",1 << i,i,
ast_codec2str(i));
00537 }
00538
00539
if ((argc == 2) || (!strcasecmp(argv[1],
"image"))) {
00540 found = 1;
00541
for (i=16;i<18;i++)
00542
ast_cli(fd,
"%11u (1 << %2d) %s\n",1 << i,i,
ast_codec2str(i));
00543 }
00544
00545
if ((argc == 2) || (!strcasecmp(argv[1],
"video"))) {
00546 found = 1;
00547
for (i=18;i<20;i++)
00548
ast_cli(fd,
"%11u (1 << %2d) %s\n",1 << i,i,
ast_codec2str(i));
00549 }
00550
00551
if (! found)
00552
return RESULT_SHOWUSAGE;
00553
else
00554
return RESULT_SUCCESS;
00555 }
00556
00557
static char frame_show_codecs_usage[] =
00558
"Usage: show [audio|video|image] codecs\n"
00559
" Displays codec mapping\n";
00560
00561 struct ast_cli_entry cli_show_codecs =
00562 { {
"show",
"codecs", NULL }, show_codecs,
"Shows codecs", frame_show_codecs_usage };
00563 struct ast_cli_entry cli_show_codecs_audio =
00564 { {
"show",
"audio",
"codecs", NULL }, show_codecs,
"Shows audio codecs", frame_show_codecs_usage };
00565 struct ast_cli_entry cli_show_codecs_video =
00566 { {
"show",
"video",
"codecs", NULL }, show_codecs,
"Shows video codecs", frame_show_codecs_usage };
00567 struct ast_cli_entry cli_show_codecs_image =
00568 { {
"show",
"image",
"codecs", NULL }, show_codecs,
"Shows image codecs", frame_show_codecs_usage };
00569
00570
static int show_codec_n(
int fd,
int argc,
char *argv[])
00571 {
00572
int codec, i, found=0;
00573
00574
if (argc != 3)
00575
return RESULT_SHOWUSAGE;
00576
00577
if (sscanf(argv[2],
"%d",&codec) != 1)
00578
return RESULT_SHOWUSAGE;
00579
00580
for (i=0;i<32;i++)
00581
if (codec & (1 << i)) {
00582 found = 1;
00583
ast_cli(fd,
"%11u (1 << %2d) %s\n",1 << i,i,
ast_codec2str(i));
00584 }
00585
00586
if (! found)
00587
ast_cli(fd,
"Codec %d not found\n", codec);
00588
00589
return RESULT_SUCCESS;
00590 }
00591
00592
static char frame_show_codec_n_usage[] =
00593
"Usage: show codec <number>\n"
00594
" Displays codec mapping\n";
00595
00596 struct ast_cli_entry cli_show_codec_n =
00597 { {
"show",
"codec", NULL }, show_codec_n,
"Shows a specific codec", frame_show_codec_n_usage };
00598
00599 void ast_frame_dump(
char *name,
struct ast_frame *f,
char *prefix)
00600 {
00601
char *n =
"unknown";
00602
char ftype[40] =
"Unknown Frametype";
00603
char cft[80];
00604
char subclass[40] =
"Unknown Subclass";
00605
char csub[80];
00606
char moreinfo[40] =
"";
00607
char cn[40];
00608
char cp[40];
00609
char cmn[40];
00610
if (name)
00611 n = name;
00612
if (!f) {
00613
ast_verbose(
"%s [ %s (NULL) ] [%s]\n",
00614
term_color(cp, prefix,
COLOR_BRMAGENTA,
COLOR_BLACK,
sizeof(cp)),
00615
term_color(cft,
"HANGUP",
COLOR_BRRED,
COLOR_BLACK,
sizeof(cft)),
00616
term_color(cn, n,
COLOR_YELLOW,
COLOR_BLACK,
sizeof(cn)));
00617
return;
00618 }
00619
00620
if (f->
frametype ==
AST_FRAME_VOICE)
00621
return;
00622
if (f->
frametype ==
AST_FRAME_VIDEO)
00623
return;
00624
switch(f->
frametype) {
00625
case AST_FRAME_DTMF:
00626 strcpy(ftype,
"DTMF");
00627 subclass[0] = f->
subclass;
00628 subclass[1] =
'\0';
00629
break;
00630
case AST_FRAME_CONTROL:
00631 strcpy(ftype,
"Control");
00632
switch(f->
subclass) {
00633
case AST_CONTROL_HANGUP:
00634 strcpy(subclass,
"Hangup");
00635
break;
00636
case AST_CONTROL_RING:
00637 strcpy(subclass,
"Ring");
00638
break;
00639
case AST_CONTROL_RINGING:
00640 strcpy(subclass,
"Ringing");
00641
break;
00642
case AST_CONTROL_ANSWER:
00643 strcpy(subclass,
"Answer");
00644
break;
00645
case AST_CONTROL_BUSY:
00646 strcpy(subclass,
"Busy");
00647
break;
00648
case AST_CONTROL_TAKEOFFHOOK:
00649 strcpy(subclass,
"Take Off Hook");
00650
break;
00651
case AST_CONTROL_OFFHOOK:
00652 strcpy(subclass,
"Line Off Hook");
00653
break;
00654
case AST_CONTROL_CONGESTION:
00655 strcpy(subclass,
"Congestion");
00656
break;
00657
case AST_CONTROL_FLASH:
00658 strcpy(subclass,
"Flash");
00659
break;
00660
case AST_CONTROL_WINK:
00661 strcpy(subclass,
"Wink");
00662
break;
00663
case AST_CONTROL_OPTION:
00664 strcpy(subclass,
"Option");
00665
break;
00666
case AST_CONTROL_RADIO_KEY:
00667 strcpy(subclass,
"Key Radio");
00668
break;
00669
case AST_CONTROL_RADIO_UNKEY:
00670 strcpy(subclass,
"Unkey Radio");
00671
break;
00672
default:
00673 snprintf(subclass,
sizeof(subclass),
"Unknown control '%d'", f->
subclass);
00674 }
00675
case AST_FRAME_NULL:
00676 strcpy(ftype,
"Null Frame");
00677 strcpy(subclass,
"N/A");
00678
break;
00679
case AST_FRAME_IAX:
00680
00681 strcpy(ftype,
"IAX Specific");
00682 snprintf(subclass,
sizeof(subclass),
"IAX Frametype %d", f->
subclass);
00683
break;
00684
case AST_FRAME_TEXT:
00685 strcpy(ftype,
"Text");
00686 strcpy(subclass,
"N/A");
00687 strncpy(moreinfo, f->
data,
sizeof(moreinfo) - 1);
00688
break;
00689
case AST_FRAME_IMAGE:
00690 strcpy(ftype,
"Image");
00691 snprintf(subclass,
sizeof(subclass),
"Image format %s\n",
ast_getformatname(f->
subclass));
00692
break;
00693
case AST_FRAME_HTML:
00694 strcpy(ftype,
"HTML");
00695
switch(f->
subclass) {
00696
case AST_HTML_URL:
00697 strcpy(subclass,
"URL");
00698 strncpy(moreinfo, f->
data,
sizeof(moreinfo) - 1);
00699
break;
00700
case AST_HTML_DATA:
00701 strcpy(subclass,
"Data");
00702
break;
00703
case AST_HTML_BEGIN:
00704 strcpy(subclass,
"Begin");
00705
break;
00706
case AST_HTML_END:
00707 strcpy(subclass,
"End");
00708
break;
00709
case AST_HTML_LDCOMPLETE:
00710 strcpy(subclass,
"Load Complete");
00711
break;
00712
case AST_HTML_NOSUPPORT:
00713 strcpy(subclass,
"No Support");
00714
break;
00715
case AST_HTML_LINKURL:
00716 strcpy(subclass,
"Link URL");
00717 strncpy(moreinfo, f->
data,
sizeof(moreinfo) - 1);
00718
break;
00719
case AST_HTML_UNLINK:
00720 strcpy(subclass,
"Unlink");
00721
break;
00722
case AST_HTML_LINKREJECT:
00723 strcpy(subclass,
"Link Reject");
00724
break;
00725
default:
00726 snprintf(subclass,
sizeof(subclass),
"Unknown HTML frame '%d'\n", f->
subclass);
00727
break;
00728 }
00729
break;
00730
default:
00731 snprintf(ftype,
sizeof(ftype),
"Unknown Frametype '%d'", f->
frametype);
00732 }
00733
if (!ast_strlen_zero(moreinfo))
00734
ast_verbose(
"%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
00735
term_color(cp, prefix,
COLOR_BRMAGENTA,
COLOR_BLACK,
sizeof(cp)),
00736
term_color(cft, ftype,
COLOR_BRRED,
COLOR_BLACK,
sizeof(cft)),
00737 f->
frametype,
00738
term_color(csub, subclass,
COLOR_BRCYAN,
COLOR_BLACK,
sizeof(csub)),
00739 f->
subclass,
00740
term_color(cmn, moreinfo,
COLOR_BRGREEN,
COLOR_BLACK,
sizeof(cmn)),
00741
term_color(cn, n,
COLOR_YELLOW,
COLOR_BLACK,
sizeof(cn)));
00742
else
00743
ast_verbose(
"%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
00744
term_color(cp, prefix,
COLOR_BRMAGENTA,
COLOR_BLACK,
sizeof(cp)),
00745
term_color(cft, ftype,
COLOR_BRRED,
COLOR_BLACK,
sizeof(cft)),
00746 f->
frametype,
00747
term_color(csub, subclass,
COLOR_BRCYAN,
COLOR_BLACK,
sizeof(csub)),
00748 f->
subclass,
00749
term_color(cn, n,
COLOR_YELLOW,
COLOR_BLACK,
sizeof(cn)));
00750
00751 }
00752
00753
00754
#ifdef TRACE_FRAMES
00755
static int show_frame_stats(
int fd,
int argc,
char *argv[])
00756 {
00757
struct ast_frame *f;
00758
int x=1;
00759
if (argc != 3)
00760
return RESULT_SHOWUSAGE;
00761
ast_cli(fd,
" Framer Statistics \n");
00762
ast_cli(fd,
"---------------------------\n");
00763
ast_cli(fd,
"Total allocated headers: %d\n", headers);
00764
ast_cli(fd,
"Queue Dump:\n");
00765
ast_mutex_lock(&framelock);
00766
for (f=headerlist; f; f = f->next) {
00767
ast_cli(fd,
"%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src :
"<Unknown>");
00768 }
00769
ast_mutex_unlock(&framelock);
00770
return RESULT_SUCCESS;
00771 }
00772
00773
static char frame_stats_usage[] =
00774
"Usage: show frame stats\n"
00775
" Displays debugging statistics from framer\n";
00776
00777
struct ast_cli_entry cli_frame_stats =
00778 { {
"show",
"frame",
"stats", NULL }, show_frame_stats,
"Shows frame statistics", frame_stats_usage };
00779
#endif
00780
00781 int init_framer(
void)
00782 {
00783
#ifdef TRACE_FRAMES
00784
ast_cli_register(&cli_frame_stats);
00785
#endif
00786
ast_cli_register(&
cli_show_codecs);
00787
ast_cli_register(&
cli_show_codecs_audio);
00788
ast_cli_register(&
cli_show_codecs_video);
00789
ast_cli_register(&
cli_show_codecs_image);
00790
ast_cli_register(&
cli_show_codec_n);
00791
return 0;
00792 }