Mon Mar 20 08:25:42 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

format_g723.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! 
00020  * \file
00021  *
00022  * \brief Old-style G.723.1 frame/timestamp format.
00023  * 
00024  * \arg Extensions: g723, g723sf
00025  * \ingroup formats
00026  */
00027  
00028 #include <unistd.h>
00029 #include <netinet/in.h>
00030 #include <arpa/inet.h>
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033 #include <errno.h>
00034 #include <string.h>
00035 #include <sys/time.h>
00036 
00037 #include "asterisk.h"
00038 
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00040 
00041 #include "asterisk/lock.h"
00042 #include "asterisk/channel.h"
00043 #include "asterisk/file.h"
00044 #include "asterisk/logger.h"
00045 #include "asterisk/sched.h"
00046 #include "asterisk/module.h"
00047 
00048 #include "../channels/adtranvofr.h"
00049 
00050 
00051 #define G723_MAX_SIZE 1024
00052 
00053 struct ast_filestream {
00054    /* First entry MUST be reserved for the channel type */
00055    void *reserved[AST_RESERVED_POINTERS];
00056    /* This is what a filestream means to us */
00057    FILE *f; /* Descriptor */
00058    struct ast_filestream *next;
00059    struct ast_frame *fr;   /* Frame representation of buf */
00060    struct timeval orig; /* Original frame time */
00061    char buf[G723_MAX_SIZE + AST_FRIENDLY_OFFSET];  /* Buffer for sending frames, etc */
00062 };
00063 
00064 
00065 AST_MUTEX_DEFINE_STATIC(g723_lock);
00066 static int glistcnt = 0;
00067 
00068 static char *name = "g723sf";
00069 static char *desc = "G.723.1 Simple Timestamp File Format";
00070 static char *exts = "g723|g723sf";
00071 
00072 static struct ast_filestream *g723_open(FILE *f)
00073 {
00074    /* We don't have any header to read or anything really, but
00075       if we did, it would go here.  We also might want to check
00076       and be sure it's a valid file.  */
00077    struct ast_filestream *tmp;
00078    if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00079       memset(tmp, 0, sizeof(struct ast_filestream));
00080       if (ast_mutex_lock(&g723_lock)) {
00081          ast_log(LOG_WARNING, "Unable to lock g723 list\n");
00082          free(tmp);
00083          return NULL;
00084       }
00085       tmp->f = f;
00086       tmp->fr = (struct ast_frame *)tmp->buf;
00087       tmp->fr->data = tmp->buf + sizeof(struct ast_frame);
00088       tmp->fr->frametype = AST_FRAME_VOICE;
00089       tmp->fr->subclass = AST_FORMAT_G723_1;
00090       /* datalen will vary for each frame */
00091       tmp->fr->src = name;
00092       tmp->fr->mallocd = 0;
00093       glistcnt++;
00094       ast_mutex_unlock(&g723_lock);
00095       ast_update_use_count();
00096    }
00097    return tmp;
00098 }
00099 
00100 static struct ast_filestream *g723_rewrite(FILE *f, const char *comment)
00101 {
00102    /* We don't have any header to read or anything really, but
00103       if we did, it would go here.  We also might want to check
00104       and be sure it's a valid file.  */
00105    struct ast_filestream *tmp;
00106    if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00107       memset(tmp, 0, sizeof(struct ast_filestream));
00108       if (ast_mutex_lock(&g723_lock)) {
00109          ast_log(LOG_WARNING, "Unable to lock g723 list\n");
00110          free(tmp);
00111          return NULL;
00112       }
00113       tmp->f = f;
00114       glistcnt++;
00115       ast_mutex_unlock(&g723_lock);
00116       ast_update_use_count();
00117    } else
00118       ast_log(LOG_WARNING, "Out of memory\n");
00119    return tmp;
00120 }
00121 
00122 static struct ast_frame *g723_read(struct ast_filestream *s, int *whennext)
00123 {
00124    unsigned short size;
00125    int res;
00126    int delay;
00127    /* Read the delay for the next packet, and schedule again if necessary */
00128    if (fread(&delay, 1, 4, s->f) == 4) 
00129       delay = ntohl(delay);
00130    else
00131       delay = -1;
00132    if (fread(&size, 1, 2, s->f) != 2) {
00133       /* Out of data, or the file is no longer valid.  In any case
00134          go ahead and stop the stream */
00135       return NULL;
00136    }
00137    /* Looks like we have a frame to read from here */
00138    size = ntohs(size);
00139    if (size > G723_MAX_SIZE - sizeof(struct ast_frame)) {
00140       ast_log(LOG_WARNING, "Size %d is invalid\n", size);
00141       /* The file is apparently no longer any good, as we
00142          shouldn't ever get frames even close to this 
00143          size.  */
00144       return NULL;
00145    }
00146    /* Read the data into the buffer */
00147    s->fr->offset = AST_FRIENDLY_OFFSET;
00148    s->fr->datalen = size;
00149    s->fr->data = s->buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
00150    if ((res = fread(s->fr->data, 1, size, s->f)) != size) {
00151       ast_log(LOG_WARNING, "Short read (%d of %d bytes) (%s)!\n", res, size, strerror(errno));
00152       return NULL;
00153    }
00154 #if 0
00155       /* Average out frames <= 50 ms */
00156       if (delay < 50)
00157          s->fr->timelen = 30;
00158       else
00159          s->fr->timelen = delay;
00160 #else
00161       s->fr->samples = 240;
00162 #endif
00163    *whennext = s->fr->samples;
00164    return s->fr;
00165 }
00166 
00167 static void g723_close(struct ast_filestream *s)
00168 {
00169    if (ast_mutex_lock(&g723_lock)) {
00170       ast_log(LOG_WARNING, "Unable to lock g723 list\n");
00171       return;
00172    }
00173    glistcnt--;
00174    ast_mutex_unlock(&g723_lock);
00175    ast_update_use_count();
00176    fclose(s->f);
00177    free(s);
00178    s = NULL;
00179 }
00180 
00181 
00182 static int g723_write(struct ast_filestream *fs, struct ast_frame *f)
00183 {
00184    u_int32_t delay;
00185    u_int16_t size;
00186    int res;
00187    if (fs->fr) {
00188       ast_log(LOG_WARNING, "Asked to write on a read stream??\n");
00189       return -1;
00190    }
00191    if (f->frametype != AST_FRAME_VOICE) {
00192       ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00193       return -1;
00194    }
00195    if (f->subclass != AST_FORMAT_G723_1) {
00196       ast_log(LOG_WARNING, "Asked to write non-g723 frame!\n");
00197       return -1;
00198    }
00199    delay = 0;
00200    if (f->datalen <= 0) {
00201       ast_log(LOG_WARNING, "Short frame ignored (%d bytes long?)\n", f->datalen);
00202       return 0;
00203    }
00204    if ((res = fwrite(&delay, 1, 4, fs->f)) != 4) {
00205       ast_log(LOG_WARNING, "Unable to write delay: res=%d (%s)\n", res, strerror(errno));
00206       return -1;
00207    }
00208    size = htons(f->datalen);
00209    if ((res = fwrite(&size, 1, 2, fs->f)) != 2) {
00210       ast_log(LOG_WARNING, "Unable to write size: res=%d (%s)\n", res, strerror(errno));
00211       return -1;
00212    }
00213    if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
00214       ast_log(LOG_WARNING, "Unable to write frame: res=%d (%s)\n", res, strerror(errno));
00215       return -1;
00216    }  
00217    return 0;
00218 }
00219 
00220 static int g723_seek(struct ast_filestream *fs, long sample_offset, int whence)
00221 {
00222    return -1;
00223 }
00224 
00225 static int g723_trunc(struct ast_filestream *fs)
00226 {
00227    /* Truncate file to current length */
00228    if (ftruncate(fileno(fs->f), ftell(fs->f)) < 0)
00229       return -1;
00230    return 0;
00231 }
00232 
00233 static long g723_tell(struct ast_filestream *fs)
00234 {
00235    return -1;
00236 }
00237 
00238 static char *g723_getcomment(struct ast_filestream *s)
00239 {
00240    return NULL;
00241 }
00242 
00243 int load_module()
00244 {
00245    return ast_format_register(name, exts, AST_FORMAT_G723_1,
00246                         g723_open,
00247                         g723_rewrite,
00248                         g723_write,
00249                         g723_seek,
00250                         g723_trunc,
00251                         g723_tell,
00252                         g723_read,
00253                         g723_close,
00254                         g723_getcomment);
00255                         
00256                         
00257 }
00258 
00259 int unload_module()
00260 {
00261    return ast_format_unregister(name);
00262 }  
00263 
00264 int usecount()
00265 {
00266    return glistcnt;
00267 }
00268 
00269 char *description()
00270 {
00271    return desc;
00272 }
00273 
00274 
00275 char *key()
00276 {
00277    return ASTERISK_GPL_KEY;
00278 }

Generated on Mon Mar 20 08:25:42 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1