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

Generated on Thu Apr 16 06:27:34 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6