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