Thu Oct 11 06:47:15 2012

Asterisk developer's documentation


format_g726.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (c) 2004 - 2005, inAccess Networks
00005  *
00006  * Michael Manousos <manousos@inaccessnetworks.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 /*!\file
00020  *
00021  * \brief Headerless G.726 (16/24/32/40kbps) data format for Asterisk.
00022  * 
00023  * File name extensions:
00024  * \arg 40 kbps: g726-40
00025  * \arg 32 kbps: g726-32
00026  * \arg 24 kbps: g726-24
00027  * \arg 16 kbps: g726-16
00028  * \ingroup formats
00029  */
00030  
00031 #include "asterisk.h"
00032 
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 233694 $")
00034 
00035 #include "asterisk/mod_format.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/endian.h"
00038 
00039 #define  RATE_40     0
00040 #define  RATE_32     1
00041 #define  RATE_24     2
00042 #define  RATE_16     3
00043 
00044 /* We can only read/write chunks of FRAME_TIME ms G.726 data */
00045 #define  FRAME_TIME  10 /* 10 ms size */
00046 
00047 #define  BUF_SIZE (5*FRAME_TIME) /* max frame size in bytes ? */
00048 /* Frame sizes in bytes */
00049 static int frame_size[4] = { 
00050       FRAME_TIME * 5,
00051       FRAME_TIME * 4,
00052       FRAME_TIME * 3,
00053       FRAME_TIME * 2
00054 };
00055 
00056 struct g726_desc  {
00057    int rate;   /* RATE_* defines */
00058 };
00059 
00060 /*
00061  * Rate dependant format functions (open, rewrite)
00062  */
00063 static int g726_open(struct ast_filestream *tmp, int rate)
00064 {
00065    struct g726_desc *s = (struct g726_desc *)tmp->_private;
00066    s->rate = rate;
00067    ast_debug(1, "Created filestream G.726-%dk.\n", 40 - s->rate * 8);
00068    return 0;
00069 }
00070 
00071 static int g726_40_open(struct ast_filestream *s)
00072 {
00073    return g726_open(s, RATE_40);
00074 }
00075 
00076 static int g726_32_open(struct ast_filestream *s)
00077 {
00078    return g726_open(s, RATE_32);
00079 }
00080 
00081 static int g726_24_open(struct ast_filestream *s)
00082 {
00083    return g726_open(s, RATE_24);
00084 }
00085 
00086 static int g726_16_open(struct ast_filestream *s)
00087 {
00088    return g726_open(s, RATE_16);
00089 }
00090 
00091 static int g726_40_rewrite(struct ast_filestream *s, const char *comment)
00092 {
00093    return g726_open(s, RATE_40);
00094 }
00095 
00096 static int g726_32_rewrite(struct ast_filestream *s, const char *comment)
00097 {
00098    return g726_open(s, RATE_32);
00099 }
00100 
00101 static int g726_24_rewrite(struct ast_filestream *s, const char *comment)
00102 {
00103    return g726_open(s, RATE_24);
00104 }
00105 
00106 static int g726_16_rewrite(struct ast_filestream *s, const char *comment)
00107 {
00108    return g726_open(s, RATE_16);
00109 }
00110 
00111 /*
00112  * Rate independent format functions (read, write)
00113  */
00114 
00115 static struct ast_frame *g726_read(struct ast_filestream *s, int *whennext)
00116 {
00117    int res;
00118    struct g726_desc *fs = (struct g726_desc *)s->_private;
00119 
00120    /* Send a frame from the file to the appropriate channel */
00121    s->fr.frametype = AST_FRAME_VOICE;
00122    s->fr.subclass = AST_FORMAT_G726;
00123    s->fr.mallocd = 0;
00124    AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, frame_size[fs->rate]);
00125    s->fr.samples = 8 * FRAME_TIME;
00126    if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
00127       if (res)
00128          ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00129       return NULL;
00130    }
00131    *whennext = s->fr.samples;
00132    return &s->fr;
00133 }
00134 
00135 static int g726_write(struct ast_filestream *s, struct ast_frame *f)
00136 {
00137    int res;
00138    struct g726_desc *fs = (struct g726_desc *)s->_private;
00139 
00140    if (f->frametype != AST_FRAME_VOICE) {
00141       ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00142       return -1;
00143    }
00144    if (f->subclass != AST_FORMAT_G726) {
00145       ast_log(LOG_WARNING, "Asked to write non-G726 frame (%d)!\n", 
00146                   f->subclass);
00147       return -1;
00148    }
00149    if (f->datalen % frame_size[fs->rate]) {
00150       ast_log(LOG_WARNING, "Invalid data length %d, should be multiple of %d\n", 
00151                   f->datalen, frame_size[fs->rate]);
00152       return -1;
00153    }
00154    if ((res = fwrite(f->data.ptr, 1, f->datalen, s->f)) != f->datalen) {
00155       ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", 
00156             res, frame_size[fs->rate], strerror(errno));
00157          return -1;
00158    }
00159    return 0;
00160 }
00161 
00162 static int g726_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
00163 {
00164    return -1;
00165 }
00166 
00167 static int g726_trunc(struct ast_filestream *fs)
00168 {
00169    return -1;
00170 }
00171 
00172 static off_t g726_tell(struct ast_filestream *fs)
00173 {
00174    return -1;
00175 }
00176 
00177 static const struct ast_format f[] = {
00178    {
00179       .name = "g726-40",
00180       .exts = "g726-40",
00181       .format = AST_FORMAT_G726,
00182       .open = g726_40_open,
00183       .rewrite = g726_40_rewrite,
00184       .write = g726_write,
00185       .seek = g726_seek,
00186       .trunc = g726_trunc,
00187       .tell = g726_tell,
00188       .read = g726_read,
00189       .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00190       .desc_size = sizeof(struct g726_desc),
00191    },
00192    {
00193       .name = "g726-32",
00194       .exts = "g726-32",
00195       .format = AST_FORMAT_G726,
00196       .open = g726_32_open,
00197       .rewrite = g726_32_rewrite,
00198       .write = g726_write,
00199       .seek = g726_seek,
00200       .trunc = g726_trunc,
00201       .tell = g726_tell,
00202       .read = g726_read,
00203       .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00204       .desc_size = sizeof(struct g726_desc),
00205    },
00206    {
00207       .name = "g726-24",
00208       .exts = "g726-24",
00209       .format = AST_FORMAT_G726,
00210       .open = g726_24_open,
00211       .rewrite = g726_24_rewrite,
00212       .write = g726_write,
00213       .seek = g726_seek,
00214       .trunc = g726_trunc,
00215       .tell = g726_tell,
00216       .read = g726_read,
00217       .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00218       .desc_size = sizeof(struct g726_desc),
00219    },
00220    {
00221       .name = "g726-16",
00222       .exts = "g726-16",
00223       .format = AST_FORMAT_G726,
00224       .open = g726_16_open,
00225       .rewrite = g726_16_rewrite,
00226       .write = g726_write,
00227       .seek = g726_seek,
00228       .trunc = g726_trunc,
00229       .tell = g726_tell,
00230       .read = g726_read,
00231       .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00232       .desc_size = sizeof(struct g726_desc),
00233    },
00234    {  .format = 0 }  /* terminator */
00235 };
00236 
00237 static int load_module(void)
00238 {
00239    int i;
00240 
00241    for (i = 0; f[i].format ; i++) {
00242       if (ast_format_register(&f[i])) {   /* errors are fatal */
00243          ast_log(LOG_WARNING, "Failed to register format %s.\n", f[i].name);
00244          return AST_MODULE_LOAD_FAILURE;
00245       }
00246    }
00247    return AST_MODULE_LOAD_SUCCESS;
00248 }
00249 
00250 static int unload_module(void)
00251 {
00252    int i;
00253 
00254    for (i = 0; f[i].format ; i++) {
00255       if (ast_format_unregister(f[i].name))
00256          ast_log(LOG_WARNING, "Failed to unregister format %s.\n", f[i].name);
00257    }
00258    return(0);
00259 }  
00260 
00261 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw G.726 (16/24/32/40kbps) data",
00262    .load = load_module,
00263    .unload = unload_module,
00264    .load_pri = 10,
00265 );

Generated on Thu Oct 11 06:47:15 2012 for Asterisk - the Open Source PBX by  doxygen 1.5.6