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