Tue Aug 20 16:34:33 2013

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

Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1