Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

frame.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- A telephony toolkit for Linux.
00003  *
00004  * Frame manipulation routines
00005  * 
00006  * Copyright (C) 1999, Mark Spencer
00007  *
00008  * Mark Spencer <markster@linux-support.net>
00009  *
00010  * This program is free software, distributed under the terms of
00011  * the GNU General Public License
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 <stdlib.h>
00021 #include <unistd.h>
00022 #include <string.h>
00023 #include <errno.h>
00024 #include <pthread.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 static ast_mutex_t framelock = AST_MUTEX_INITIALIZER;
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    float samplesperbyte;
00042    struct ast_frame f;
00043    char data[SMOOTHER_SIZE];
00044    char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
00045    struct ast_frame *opt;
00046    int len;
00047 };
00048 
00049 void ast_smoother_reset(struct ast_smoother *s, int size)
00050 {
00051    memset(s, 0, sizeof(struct ast_smoother));
00052    s->size = size;
00053 }
00054 
00055 struct ast_smoother *ast_smoother_new(int size)
00056 {
00057    struct ast_smoother *s;
00058    if (size < 1)
00059       return NULL;
00060    s = malloc(sizeof(struct ast_smoother));
00061    if (s)
00062       ast_smoother_reset(s, size);
00063    return s;
00064 }
00065 
00066 int ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f)
00067 {
00068    if (f->frametype != AST_FRAME_VOICE) {
00069       ast_log(LOG_WARNING, "Huh?  Can't smooth a non-voice frame!\n");
00070       return -1;
00071    }
00072    if (!s->format) {
00073       s->format = f->subclass;
00074       s->samplesperbyte = (float)f->samples / (float)f->datalen;
00075    } else if (s->format != f->subclass) {
00076       ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
00077       return -1;
00078    }
00079    if (s->len + f->datalen > SMOOTHER_SIZE) {
00080       ast_log(LOG_WARNING, "Out of smoother space\n");
00081       return -1;
00082    }
00083    if ((f->datalen == s->size) && !s->opt) {
00084       if (!s->len) {
00085          /* Optimize by sending the frame we just got
00086             on the next read, thus eliminating the douple
00087             copy */
00088          s->opt = f;
00089          return 0;
00090       } else {
00091          s->optimizablestream++;
00092          if (s->optimizablestream > 10) {
00093             /* For the past 10 rounds, we have input and output
00094                frames of the correct size for this smoother, yet
00095                we were unable to optimize because there was still
00096                some cruft left over.  Lets just drop the cruft so
00097                we can move to a fully optimized path */
00098             s->len = 0;
00099             s->opt = f;
00100             return 0;
00101          }
00102       }
00103    } else 
00104       s->optimizablestream = 0;
00105    memcpy(s->data + s->len, f->data, f->datalen);
00106    s->len += f->datalen;
00107    return 0;
00108 }
00109 
00110 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
00111 {
00112    struct ast_frame *opt;
00113 
00114    /* IF we have an optimization frame, send it */
00115    if (s->opt) {
00116       opt = s->opt;
00117       s->opt = NULL;
00118       return opt;
00119    }
00120 
00121    /* Make sure we have enough data */
00122    if (s->len < s->size) {
00123       return NULL;
00124    }
00125    /* Make frame */
00126    s->f.frametype = AST_FRAME_VOICE;
00127    s->f.subclass = s->format;
00128    s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
00129    s->f.offset = AST_FRIENDLY_OFFSET;
00130    s->f.datalen = s->size;
00131    s->f.samples = s->size * s->samplesperbyte;
00132    /* Fill Data */
00133    memcpy(s->f.data, s->data, s->size);
00134    s->len -= s->size;
00135    /* Move remaining data to the front if applicable */
00136    if (s->len) 
00137       memmove(s->data, s->data + s->size, s->len);
00138    /* Return frame */
00139    return &s->f;
00140 }
00141 
00142 void ast_smoother_free(struct ast_smoother *s)
00143 {
00144    free(s);
00145 }
00146 
00147 static struct ast_frame *ast_frame_header_new(void)
00148 {
00149    struct ast_frame *f;
00150    f = malloc(sizeof(struct ast_frame));
00151    if (f)
00152       memset(f, 0, sizeof(struct ast_frame));
00153 #ifdef TRACE_FRAMES
00154    if (f) {
00155       headers++;
00156       f->prev = NULL;
00157       ast_mutex_lock(&framelock);
00158       f->next = headerlist;
00159       if (headerlist)
00160          headerlist->prev = f;
00161       headerlist = f;
00162       ast_mutex_unlock(&framelock);
00163    }
00164 #endif   
00165    return f;
00166 }
00167 
00168 /*
00169  * Important: I should be made more efficient.  Frame headers should
00170  * most definitely be cached
00171  */
00172 
00173 void ast_frfree(struct ast_frame *fr)
00174 {
00175    if (fr->mallocd & AST_MALLOCD_DATA) {
00176       if (fr->data) 
00177          free(fr->data - fr->offset);
00178    }
00179    if (fr->mallocd & AST_MALLOCD_SRC) {
00180       if (fr->src)
00181          free(fr->src);
00182    }
00183    if (fr->mallocd & AST_MALLOCD_HDR) {
00184 #ifdef TRACE_FRAMES
00185       headers--;
00186       ast_mutex_lock(&framelock);
00187       if (fr->next)
00188          fr->next->prev = fr->prev;
00189       if (fr->prev)
00190          fr->prev->next = fr->next;
00191       else
00192          headerlist = fr->next;
00193       ast_mutex_unlock(&framelock);
00194 #endif         
00195       free(fr);
00196    }
00197 }
00198 
00199 struct ast_frame *ast_frisolate(struct ast_frame *fr)
00200 {
00201    struct ast_frame *out;
00202    if (!(fr->mallocd & AST_MALLOCD_HDR)) {
00203       /* Allocate a new header if needed */
00204       out = ast_frame_header_new();
00205       if (!out) {
00206          ast_log(LOG_WARNING, "Out of memory\n");
00207          return NULL;
00208       }
00209       out->frametype = fr->frametype;
00210       out->subclass = fr->subclass;
00211       out->datalen = 0;
00212       out->samples = fr->samples;
00213       out->offset = 0;
00214       out->src = NULL;
00215       out->data = NULL;
00216    } else {
00217       out = fr;
00218    }
00219    if (!(fr->mallocd & AST_MALLOCD_SRC)) {
00220       if (fr->src)
00221          out->src = strdup(fr->src);
00222    } else
00223       out->src = fr->src;
00224    if (!(fr->mallocd & AST_MALLOCD_DATA))  {
00225       out->data = malloc(fr->datalen + AST_FRIENDLY_OFFSET);
00226       if (!out->data) {
00227          free(out);
00228          ast_log(LOG_WARNING, "Out of memory\n");
00229          return NULL;
00230       }
00231       out->data += AST_FRIENDLY_OFFSET;
00232       out->offset = AST_FRIENDLY_OFFSET;
00233       out->datalen = fr->datalen;
00234       memcpy(out->data, fr->data, fr->datalen);
00235    }
00236    out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
00237    return out;
00238 }
00239 
00240 struct ast_frame *ast_frdup(struct ast_frame *f)
00241 {
00242    struct ast_frame *out;
00243    int len;
00244    void *buf;
00245    /* Start with standard stuff */
00246    len = sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET + f->datalen;
00247    /* If we have a source, add space for it */
00248    if (f->src && strlen(f->src))
00249       len += strlen(f->src) + 1;
00250    buf = malloc(len);
00251    if (!buf)
00252       return NULL;
00253    out = buf;
00254    /* Set us as having malloc'd header only, so it will eventually
00255       get freed. */
00256    out->frametype = f->frametype;
00257    out->subclass = f->subclass;
00258    out->datalen = f->datalen;
00259    out->samples = f->samples;
00260    out->mallocd = AST_MALLOCD_HDR;
00261    out->offset = AST_FRIENDLY_OFFSET;
00262    out->data = buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
00263    if (f->src && strlen(f->src)) {
00264       out->src = out->data + f->datalen;
00265       /* Must have space since we allocated for it */
00266       strcpy(out->src, f->src);
00267    } else
00268       out->src = NULL;
00269    out->prev = NULL;
00270    out->next = NULL;
00271    memcpy(out->data, f->data, out->datalen); 
00272    return out;
00273 }
00274 
00275 struct ast_frame *ast_fr_fdread(int fd)
00276 {
00277    char buf[65536];
00278    int res;
00279    int ttl = sizeof(struct ast_frame);
00280    struct ast_frame *f = (struct ast_frame *)buf;
00281    /* Read a frame directly from there.  They're always in the
00282       right format. */
00283    
00284    while(ttl) {
00285       res = read(fd, buf, ttl);
00286       if (res < 0) {
00287          ast_log(LOG_WARNING, "Bad read on %d: %s\n", fd, strerror(errno));
00288          return NULL;
00289       }
00290       ttl -= res;
00291    }
00292    
00293    /* read the frame header */
00294    f->mallocd = 0;
00295    /* Re-write data position */
00296    f->data = buf + sizeof(struct ast_frame);
00297    f->offset = 0;
00298    /* Forget about being mallocd */
00299    f->mallocd = 0;
00300    /* Re-write the source */
00301    f->src = __FUNCTION__;
00302    if (f->datalen > sizeof(buf) - sizeof(struct ast_frame)) {
00303       /* Really bad read */
00304       ast_log(LOG_WARNING, "Strange read (%d bytes)\n", f->datalen);
00305       return NULL;
00306    }
00307    if (f->datalen) {
00308       if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
00309          /* Bad read */
00310          ast_log(LOG_WARNING, "How very strange, expected %d, got %d\n", f->datalen, res);
00311          return NULL;
00312       }
00313    }
00314    if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
00315       return NULL;
00316    }
00317    return ast_frisolate(f);
00318 }
00319 
00320 /* Some convenient routines for sending frames to/from stream or datagram
00321    sockets, pipes, etc (maybe even files) */
00322 
00323 int ast_fr_fdwrite(int fd, struct ast_frame *frame)
00324 {
00325    /* Write the frame exactly */
00326    if (write(fd, frame, sizeof(struct ast_frame)) != sizeof(struct ast_frame)) {
00327       ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
00328       return -1;
00329    }
00330    if (write(fd, frame->data, frame->datalen) != frame->datalen) {
00331       ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
00332       return -1;
00333    }
00334    return 0;
00335 }
00336 
00337 int ast_fr_fdhangup(int fd)
00338 {
00339    struct ast_frame hangup = {
00340       AST_FRAME_CONTROL,
00341       AST_CONTROL_HANGUP
00342    };
00343    return ast_fr_fdwrite(fd, &hangup);
00344 }
00345 
00346 char* ast_getformatname(int format)
00347 {
00348    if (format == AST_FORMAT_G723_1) 
00349       return "G723";
00350    else if (format == AST_FORMAT_GSM)
00351       return "GSM";
00352    else if (format == AST_FORMAT_ULAW)
00353       return "ULAW";
00354    else if (format == AST_FORMAT_ALAW)
00355       return "ALAW";
00356    else if (format == AST_FORMAT_G726)
00357       return "G726";
00358    else if (format == AST_FORMAT_SLINEAR)
00359       return "SLINR";
00360    else if (format == AST_FORMAT_LPC10)
00361       return "LPC10";
00362    else if (format == AST_FORMAT_ADPCM)
00363       return "ADPCM";
00364    else if (format == AST_FORMAT_G729A)
00365       return "G729A";
00366    else if (format == AST_FORMAT_SPEEX)
00367       return "SPEEX";
00368    else if (format == AST_FORMAT_ILBC)
00369       return "ILBC";
00370    else if (format == AST_FORMAT_JPEG)
00371       return "JPEG";
00372    else if (format == AST_FORMAT_PNG)
00373       return "PNG";
00374    else if (format == AST_FORMAT_H261)
00375       return "H261";
00376    else if (format == AST_FORMAT_H263)
00377       return "H263";
00378    return "UNKN";
00379 }
00380 
00381 int ast_getformatbyname(char *name)
00382 {
00383    if (!strcasecmp(name, "g723.1")) 
00384       return AST_FORMAT_G723_1;
00385    else if (!strcasecmp(name, "gsm"))
00386       return AST_FORMAT_GSM;
00387    else if (!strcasecmp(name, "ulaw"))
00388       return AST_FORMAT_ULAW;
00389    else if (!strcasecmp(name, "alaw"))
00390       return AST_FORMAT_ALAW;
00391    else if (!strcasecmp(name, "g726"))
00392       return AST_FORMAT_G726;
00393    else if (!strcasecmp(name, "slinear"))
00394       return AST_FORMAT_SLINEAR;
00395    else if (!strcasecmp(name, "lpc10"))
00396       return AST_FORMAT_LPC10;
00397    else if (!strcasecmp(name, "adpcm"))
00398       return AST_FORMAT_ADPCM;
00399    else if (!strcasecmp(name, "g729"))
00400       return AST_FORMAT_G729A;
00401    else if (!strcasecmp(name, "speex"))
00402       return AST_FORMAT_SPEEX;
00403    else if (!strcasecmp(name, "ilbc"))
00404       return AST_FORMAT_ILBC;
00405    else if (!strcasecmp(name, "h261"))
00406       return AST_FORMAT_H261;
00407    else if (!strcasecmp(name, "h263"))
00408       return AST_FORMAT_H263;
00409    else if (!strcasecmp(name, "all"))
00410       return 0x7FFFFFFF;
00411    return 0;
00412 }
00413 
00414 char *ast_codec2str(int codec) {
00415    static char codecs[25][30] = {
00416       /* Audio formats */
00417       "G.723.1",                    /*  0 */
00418       "GSM",                        /*  1 */
00419       "G.711 u-law",                /*  2 */
00420       "G.711 A-law",                /*  3 */
00421       "MPEG-2 layer 3",             /*  4 */
00422       "ADPCM",                      /*  5 */
00423       "16 bit Signed Linear PCM",   /*  6 */
00424       "LPC10",                      /*  7 */
00425       "G.729A audio",               /*  8 */
00426       "SpeeX",                      /*  9 */
00427       "iLBC",                       /* 10 */
00428       "undefined",                  /* 11 */
00429       "undefined",                  /* 12 */
00430       "undefined",                  /* 13 */
00431       "undefined",                  /* 14 */
00432       "Maximum audio format",       /* 15 */
00433         /* Image formats */
00434       "JPEG image",                 /* 16 */
00435       "PNG image",                  /* 17 */
00436       "H.261 Video",                /* 18 */
00437       "H.263 Video",                /* 19 */
00438       "undefined",                  /* 20 */
00439       "undefined",                  /* 21 */
00440       "undefined",                  /* 22 */
00441       "undefined",                  /* 23 */
00442         "Maximum video format",       /* 24 */
00443       };
00444    if ((codec >= 0) && (codec <= 24))
00445       return codecs[codec];
00446    else
00447       return "unknown";
00448 }
00449 
00450 static int show_codecs(int fd, int argc, char *argv[])
00451 {
00452    int i, found=0;
00453 
00454    if ((argc < 2) || (argc > 3))
00455       return RESULT_SHOWUSAGE;
00456 
00457    if (getenv("I_AM_NOT_AN_IDIOT") == NULL)
00458       ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
00459             "\tIt does not indicate anything about your configuration.\n");
00460 
00461    if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
00462       found = 1;
00463       for (i=0;i<11;i++)
00464          ast_cli(fd, "%11u (1 << %2d)  %s\n",1 << i,i,ast_codec2str(i));
00465    }
00466 
00467    if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
00468       found = 1;
00469       for (i=16;i<18;i++)
00470          ast_cli(fd, "%11u (1 << %2d)  %s\n",1 << i,i,ast_codec2str(i));
00471    }
00472 
00473    if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
00474       found = 1;
00475       for (i=18;i<20;i++)
00476          ast_cli(fd, "%11u (1 << %2d)  %s\n",1 << i,i,ast_codec2str(i));
00477    }
00478 
00479    if (! found)
00480       return RESULT_SHOWUSAGE;
00481    else
00482       return RESULT_SUCCESS;
00483 }
00484 
00485 static char frame_show_codecs_usage[] =
00486 "Usage: show [audio|video|image] codecs\n"
00487 "       Displays codec mapping\n";
00488 
00489 struct ast_cli_entry cli_show_codecs =
00490 { { "show", "codecs", NULL }, show_codecs, "Shows codecs", frame_show_codecs_usage };
00491 struct ast_cli_entry cli_show_codecs_audio =
00492 { { "show", "audio", "codecs", NULL }, show_codecs, "Shows audio codecs", frame_show_codecs_usage };
00493 struct ast_cli_entry cli_show_codecs_video =
00494 { { "show", "video", "codecs", NULL }, show_codecs, "Shows video codecs", frame_show_codecs_usage };
00495 struct ast_cli_entry cli_show_codecs_image =
00496 { { "show", "image", "codecs", NULL }, show_codecs, "Shows image codecs", frame_show_codecs_usage };
00497 
00498 static int show_codec_n(int fd, int argc, char *argv[])
00499 {
00500    int codec, i, found=0;
00501 
00502    if (argc != 3)
00503       return RESULT_SHOWUSAGE;
00504 
00505    if (sscanf(argv[2],"%d",&codec) != 1)
00506       return RESULT_SHOWUSAGE;
00507 
00508    for (i=0;i<32;i++)
00509       if (codec & (1 << i)) {
00510          found = 1;
00511          ast_cli(fd, "%11u (1 << %2d)  %s\n",1 << i,i,ast_codec2str(i));
00512       }
00513 
00514    if (! found)
00515       ast_cli(fd, "Codec %d not found\n", codec);
00516 
00517    return RESULT_SUCCESS;
00518 }
00519 
00520 static char frame_show_codec_n_usage[] =
00521 "Usage: show codec <number>\n"
00522 "       Displays codec mapping\n";
00523 
00524 struct ast_cli_entry cli_show_codec_n =
00525 { { "show", "codec", NULL }, show_codec_n, "Shows a specific codec", frame_show_codec_n_usage };
00526 
00527 void ast_frame_dump(char *name, struct ast_frame *f, char *prefix)
00528 {
00529    char *n = "unknown";
00530    char ftype[40] = "Unknown Frametype";
00531    char cft[80];
00532    char subclass[40] = "Unknown Subclass";
00533    char csub[80];
00534    char moreinfo[40] = "";
00535    char cn[40];
00536    char cp[40];
00537    char cmn[40];
00538    if (name)
00539       n = name;
00540    if (!f) {
00541       ast_verbose("%s [ %s (NULL) ] [%s]\n", 
00542          term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00543          term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)), 
00544          term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00545       return;
00546    }
00547    /* XXX We should probably print one each of voice and video when the format changes XXX */
00548    if (f->frametype == AST_FRAME_VOICE)
00549       return;
00550    if (f->frametype == AST_FRAME_VIDEO)
00551       return;
00552    switch(f->frametype) {
00553    case AST_FRAME_DTMF:
00554       strcpy(ftype, "DTMF");
00555       subclass[0] = f->subclass;
00556       subclass[1] = '\0';
00557       break;
00558    case AST_FRAME_CONTROL:
00559       strcpy(ftype, "Control");
00560       switch(f->subclass) {
00561       case AST_CONTROL_HANGUP:
00562          strcpy(subclass, "Hangup");
00563          break;
00564       case AST_CONTROL_RING:
00565          strcpy(subclass, "Ring");
00566          break;
00567       case AST_CONTROL_RINGING:
00568          strcpy(subclass, "Ringing");
00569          break;
00570       case AST_CONTROL_ANSWER:
00571          strcpy(subclass, "Answer");
00572          break;
00573       case AST_CONTROL_BUSY:
00574          strcpy(subclass, "Busy");
00575          break;
00576       case AST_CONTROL_TAKEOFFHOOK:
00577          strcpy(subclass, "Take Off Hook");
00578          break;
00579       case AST_CONTROL_OFFHOOK:
00580          strcpy(subclass, "Line Off Hook");
00581          break;
00582       case AST_CONTROL_CONGESTION:
00583          strcpy(subclass, "Congestion");
00584          break;
00585       case AST_CONTROL_FLASH:
00586          strcpy(subclass, "Flash");
00587          break;
00588       case AST_CONTROL_WINK:
00589          strcpy(subclass, "Wink");
00590          break;
00591       case AST_CONTROL_OPTION:
00592          strcpy(subclass, "Option");
00593          break;
00594       case AST_CONTROL_RADIO_KEY:
00595          strcpy(subclass, "Key Radio");
00596          break;
00597       case AST_CONTROL_RADIO_UNKEY:
00598          strcpy(subclass, "Unkey Radio");
00599          break;
00600       default:
00601          snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
00602       }
00603    case AST_FRAME_NULL:
00604       strcpy(ftype, "Null Frame");
00605       strcpy(subclass, "N/A");
00606       break;
00607    case AST_FRAME_IAX:
00608       /* Should never happen */
00609       strcpy(ftype, "IAX Specific");
00610       snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
00611       break;
00612    case AST_FRAME_TEXT:
00613       strcpy(ftype, "Text");
00614       strcpy(subclass, "N/A");
00615       strncpy(moreinfo, f->data, sizeof(moreinfo) - 1);
00616       break;
00617    case AST_FRAME_IMAGE:
00618       strcpy(ftype, "Image");
00619       snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
00620       break;
00621    case AST_FRAME_HTML:
00622       strcpy(ftype, "HTML");
00623       switch(f->subclass) {
00624       case AST_HTML_URL:
00625          strcpy(subclass, "URL");
00626          strncpy(moreinfo, f->data, sizeof(moreinfo) - 1);
00627          break;
00628       case AST_HTML_DATA:
00629          strcpy(subclass, "Data");
00630          break;
00631       case AST_HTML_BEGIN:
00632          strcpy(subclass, "Begin");
00633          break;
00634       case AST_HTML_END:
00635          strcpy(subclass, "End");
00636          break;
00637       case AST_HTML_LDCOMPLETE:
00638          strcpy(subclass, "Load Complete");
00639          break;
00640       case AST_HTML_NOSUPPORT:
00641          strcpy(subclass, "No Support");
00642          break;
00643       case AST_HTML_LINKURL:
00644          strcpy(subclass, "Link URL");
00645          strncpy(moreinfo, f->data, sizeof(moreinfo) - 1);
00646          break;
00647       case AST_HTML_UNLINK:
00648          strcpy(subclass, "Unlink");
00649          break;
00650       case AST_HTML_LINKREJECT:
00651          strcpy(subclass, "Link Reject");
00652          break;
00653       default:
00654          snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
00655          break;
00656       }
00657       break;
00658    default:
00659       snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
00660    }
00661    if (strlen(moreinfo))
00662       ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",  
00663          term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00664          term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00665          f->frametype, 
00666          term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00667          f->subclass, 
00668          term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
00669          term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00670    else
00671       ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",  
00672          term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00673          term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00674          f->frametype, 
00675          term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00676          f->subclass, 
00677          term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00678 
00679 }
00680 
00681 
00682 #ifdef TRACE_FRAMES
00683 static int show_frame_stats(int fd, int argc, char *argv[])
00684 {
00685    struct ast_frame *f;
00686    int x=1;
00687    if (argc != 3)
00688       return RESULT_SHOWUSAGE;
00689    ast_cli(fd, "     Framer Statistics     \n");
00690    ast_cli(fd, "---------------------------\n");
00691    ast_cli(fd, "Total allocated headers: %d\n", headers);
00692    ast_cli(fd, "Queue Dump:\n");
00693    ast_mutex_lock(&framelock);
00694    for (f=headerlist; f; f = f->next) {
00695       ast_cli(fd, "%d.  Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
00696    }
00697    ast_mutex_unlock(&framelock);
00698    return RESULT_SUCCESS;
00699 }
00700 
00701 static char frame_stats_usage[] =
00702 "Usage: show frame stats\n"
00703 "       Displays debugging statistics from framer\n";
00704 
00705 struct ast_cli_entry cli_frame_stats =
00706 { { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage };
00707 #endif
00708 
00709 int init_framer(void)
00710 {
00711 #ifdef TRACE_FRAMES
00712    ast_cli_register(&cli_frame_stats);
00713 #endif
00714    ast_cli_register(&cli_show_codecs);
00715    ast_cli_register(&cli_show_codecs_audio);
00716    ast_cli_register(&cli_show_codecs_video);
00717    ast_cli_register(&cli_show_codecs_image);
00718    ast_cli_register(&cli_show_codec_n);
00719    return 0;   
00720 }

Generated on Fri Feb 27 12:19:42 2004 for Asterisk by doxygen 1.3.5