00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 233693 $")
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
00045 #define FRAME_TIME 10
00046
00047 #define BUF_SIZE (5*FRAME_TIME)
00048
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;
00058 };
00059
00060
00061
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
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
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 }
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])) {
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 );