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_MP3)
00357       return "MP3";
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, "mp3"))
00392       return AST_FORMAT_MP3;
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    return codecs[codec];
00445 }
00446 
00447 static int show_codecs(int fd, int argc, char *argv[])
00448 {
00449    int i, found=0;
00450 
00451    if ((argc < 2) || (argc > 3))
00452       return RESULT_SHOWUSAGE;
00453 
00454    if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
00455       found = 1;
00456       for (i=0;i<11;i++)
00457          ast_cli(fd, "%8d (1 << %2d)  %s\n",1 << i,i,ast_codec2str(i));
00458    }
00459 
00460    if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
00461       found = 1;
00462       for (i=16;i<18;i++)
00463          ast_cli(fd, "%8d (1 << %2d)  %s\n",1 << i,i,ast_codec2str(i));
00464    }
00465 
00466    if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
00467       found = 1;
00468       for (i=18;i<20;i++)
00469          ast_cli(fd, "%8d (1 << %2d)  %s\n",1 << i,i,ast_codec2str(i));
00470    }
00471 
00472    if (! found)
00473       return RESULT_SHOWUSAGE;
00474    else
00475       return RESULT_SUCCESS;
00476 }
00477 
00478 static char frame_show_codecs_usage[] =
00479 "Usage: show [audio|video|image] codecs\n"
00480 "       Displays codec mapping\n";
00481 
00482 struct ast_cli_entry cli_show_codecs =
00483 { { "show", "codecs", NULL }, show_codecs, "Shows codecs", frame_show_codecs_usage };
00484 struct ast_cli_entry cli_show_codecs_audio =
00485 { { "show", "audio", "codecs", NULL }, show_codecs, "Shows audio codecs", frame_show_codecs_usage };
00486 struct ast_cli_entry cli_show_codecs_video =
00487 { { "show", "video", "codecs", NULL }, show_codecs, "Shows video codecs", frame_show_codecs_usage };
00488 struct ast_cli_entry cli_show_codecs_image =
00489 { { "show", "image", "codecs", NULL }, show_codecs, "Shows image codecs", frame_show_codecs_usage };
00490 
00491 static int show_codec_n(int fd, int argc, char *argv[])
00492 {
00493    int codec, i, found=0;
00494 
00495    if (argc != 3)
00496       return RESULT_SHOWUSAGE;
00497 
00498    if (sscanf(argv[2],"%d",&codec) != 1)
00499       return RESULT_SHOWUSAGE;
00500 
00501    for (i=0;i<32;i++)
00502       if (codec == (1 << i)) {
00503          found = 1;
00504          ast_cli(fd, "%d (1 << %d)  %s\n",1 << i,i,ast_codec2str(i));
00505       }
00506 
00507    if (! found)
00508       ast_cli(fd, "Codec %d not found\n", codec);
00509 
00510    return RESULT_SUCCESS;
00511 }
00512 
00513 static char frame_show_codec_n_usage[] =
00514 "Usage: show codec <number>\n"
00515 "       Displays codec mapping\n";
00516 
00517 struct ast_cli_entry cli_show_codec_n =
00518 { { "show", "codec", NULL }, show_codec_n, "Shows a specific codec", frame_show_codec_n_usage };
00519 
00520 void ast_frame_dump(char *name, struct ast_frame *f, char *prefix)
00521 {
00522    char *n = "unknown";
00523    char ftype[40] = "Unknown Frametype";
00524    char cft[80];
00525    char subclass[40] = "Unknown Subclass";
00526    char csub[80];
00527    char moreinfo[40] = "";
00528    char cn[40];
00529    char cp[40];
00530    char cmn[40];
00531    if (name)
00532       n = name;
00533    if (!f) {
00534       ast_verbose("%s [ %s (NULL) ] [%s]\n", 
00535          term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00536          term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)), 
00537          term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00538       return;
00539    }
00540    /* XXX We should probably print one each of voice and video when the format changes XXX */
00541    if (f->frametype == AST_FRAME_VOICE)
00542       return;
00543    if (f->frametype == AST_FRAME_VIDEO)
00544       return;
00545    switch(f->frametype) {
00546    case AST_FRAME_DTMF:
00547       strcpy(ftype, "DTMF");
00548       subclass[0] = f->subclass;
00549       subclass[1] = '\0';
00550       break;
00551    case AST_FRAME_CONTROL:
00552       strcpy(ftype, "Control");
00553       switch(f->subclass) {
00554       case AST_CONTROL_HANGUP:
00555          strcpy(subclass, "Hangup");
00556          break;
00557       case AST_CONTROL_RING:
00558          strcpy(subclass, "Ring");
00559          break;
00560       case AST_CONTROL_RINGING:
00561          strcpy(subclass, "Ringing");
00562          break;
00563       case AST_CONTROL_ANSWER:
00564          strcpy(subclass, "Answer");
00565          break;
00566       case AST_CONTROL_BUSY:
00567          strcpy(subclass, "Busy");
00568          break;
00569       case AST_CONTROL_TAKEOFFHOOK:
00570          strcpy(subclass, "Take Off Hook");
00571          break;
00572       case AST_CONTROL_OFFHOOK:
00573          strcpy(subclass, "Line Off Hook");
00574          break;
00575       case AST_CONTROL_CONGESTION:
00576          strcpy(subclass, "Congestion");
00577          break;
00578       case AST_CONTROL_FLASH:
00579          strcpy(subclass, "Flash");
00580          break;
00581       case AST_CONTROL_WINK:
00582          strcpy(subclass, "Wink");
00583          break;
00584       case AST_CONTROL_OPTION:
00585          strcpy(subclass, "Option");
00586          break;
00587       case AST_CONTROL_RADIO_KEY:
00588          strcpy(subclass, "Key Radio");
00589          break;
00590       case AST_CONTROL_RADIO_UNKEY:
00591          strcpy(subclass, "Unkey Radio");
00592          break;
00593       default:
00594          snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
00595       }
00596    case AST_FRAME_NULL:
00597       strcpy(ftype, "Null Frame");
00598       strcpy(subclass, "N/A");
00599       break;
00600    case AST_FRAME_IAX:
00601       /* Should never happen */
00602       strcpy(ftype, "IAX Specific");
00603       snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
00604       break;
00605    case AST_FRAME_TEXT:
00606       strcpy(ftype, "Text");
00607       strcpy(subclass, "N/A");
00608       strncpy(moreinfo, f->data, sizeof(moreinfo) - 1);
00609       break;
00610    case AST_FRAME_IMAGE:
00611       strcpy(ftype, "Image");
00612       snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
00613       break;
00614    case AST_FRAME_HTML:
00615       strcpy(ftype, "HTML");
00616       switch(f->subclass) {
00617       case AST_HTML_URL:
00618          strcpy(subclass, "URL");
00619          strncpy(moreinfo, f->data, sizeof(moreinfo) - 1);
00620          break;
00621       case AST_HTML_DATA:
00622          strcpy(subclass, "Data");
00623          break;
00624       case AST_HTML_BEGIN:
00625          strcpy(subclass, "Begin");
00626          break;
00627       case AST_HTML_END:
00628          strcpy(subclass, "End");
00629          break;
00630       case AST_HTML_LDCOMPLETE:
00631          strcpy(subclass, "Load Complete");
00632          break;
00633       case AST_HTML_NOSUPPORT:
00634          strcpy(subclass, "No Support");
00635          break;
00636       case AST_HTML_LINKURL:
00637          strcpy(subclass, "Link URL");
00638          strncpy(moreinfo, f->data, sizeof(moreinfo) - 1);
00639          break;
00640       case AST_HTML_UNLINK:
00641          strcpy(subclass, "Unlink");
00642          break;
00643       case AST_HTML_LINKREJECT:
00644          strcpy(subclass, "Link Reject");
00645          break;
00646       default:
00647          snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
00648          break;
00649       }
00650       break;
00651    default:
00652       snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
00653    }
00654    if (strlen(moreinfo))
00655       ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",  
00656          term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00657          term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00658          f->frametype, 
00659          term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00660          f->subclass, 
00661          term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
00662          term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00663    else
00664       ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",  
00665          term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00666          term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00667          f->frametype, 
00668          term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00669          f->subclass, 
00670          term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00671 
00672 }
00673 
00674 
00675 #ifdef TRACE_FRAMES
00676 static int show_frame_stats(int fd, int argc, char *argv[])
00677 {
00678    struct ast_frame *f;
00679    int x=1;
00680    if (argc != 3)
00681       return RESULT_SHOWUSAGE;
00682    ast_cli(fd, "     Framer Statistics     \n");
00683    ast_cli(fd, "---------------------------\n");
00684    ast_cli(fd, "Total allocated headers: %d\n", headers);
00685    ast_cli(fd, "Queue Dump:\n");
00686    ast_mutex_lock(&framelock);
00687    for (f=headerlist; f; f = f->next) {
00688       ast_cli(fd, "%d.  Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
00689    }
00690    ast_mutex_unlock(&framelock);
00691    return RESULT_SUCCESS;
00692 }
00693 
00694 static char frame_stats_usage[] =
00695 "Usage: show frame stats\n"
00696 "       Displays debugging statistics from framer\n";
00697 
00698 struct ast_cli_entry cli_frame_stats =
00699 { { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage };
00700 #endif
00701 
00702 int init_framer(void)
00703 {
00704 #ifdef TRACE_FRAMES
00705    ast_cli_register(&cli_frame_stats);
00706 #endif
00707    ast_cli_register(&cli_show_codecs);
00708    ast_cli_register(&cli_show_codecs_audio);
00709    ast_cli_register(&cli_show_codecs_video);
00710    ast_cli_register(&cli_show_codecs_image);
00711    ast_cli_register(&cli_show_codec_n);
00712    return 0;   
00713 }

Generated on Fri Oct 31 07:05:06 2003 for Asterisk by doxygen 1.3.4