00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <asterisk.h>
00019
00020 #include "mpg123.h"
00021 #include "mpglib.h"
00022 #include <asterisk/lock.h>
00023 #include <asterisk/channel.h>
00024 #include <asterisk/file.h>
00025 #include <asterisk/logger.h>
00026 #include <asterisk/sched.h>
00027 #include <asterisk/module.h>
00028 #include <netinet/in.h>
00029 #include <arpa/inet.h>
00030 #include <stdlib.h>
00031 #include <sys/time.h>
00032 #include <stdio.h>
00033 #include <unistd.h>
00034 #include <errno.h>
00035 #include <string.h>
00036 #ifdef __linux__
00037 #include <endian.h>
00038 #else
00039 #include <machine/endian.h>
00040 #endif
00041
00042 #define AST_MODULE "format_mp3"
00043
00044 #define MP3_BUFLEN 320
00045 #define MP3_SCACHE 16384
00046 #define MP3_DCACHE 8192
00047
00048
00049
00050 struct mp3_private {
00051 char waste[AST_FRIENDLY_OFFSET];
00052 char empty;
00053 int lasttimeout;
00054 int maxlen;
00055 struct timeval last;
00056 struct mpstr mp;
00057 char sbuf[MP3_SCACHE];
00058 char dbuf[MP3_DCACHE];
00059 int buflen;
00060 int sbuflen;
00061 int dbuflen;
00062 int dbufoffset;
00063 int sbufoffset;
00064 int lastseek;
00065 int offset;
00066 long seek;
00067 };
00068
00069 static char *name = "mp3";
00070
00071 #define BLOCKSIZE 160
00072 #define OUTSCALE 4096
00073
00074 #define GAIN -4
00075
00076 #if __BYTE_ORDER == __LITTLE_ENDIAN
00077 #define htoll(b) (b)
00078 #define htols(b) (b)
00079 #define ltohl(b) (b)
00080 #define ltohs(b) (b)
00081 #else
00082 #if __BYTE_ORDER == __BIG_ENDIAN
00083 #define htoll(b) \
00084 (((((b) ) & 0xFF) << 24) | \
00085 ((((b) >> 8) & 0xFF) << 16) | \
00086 ((((b) >> 16) & 0xFF) << 8) | \
00087 ((((b) >> 24) & 0xFF) ))
00088 #define htols(b) \
00089 (((((b) ) & 0xFF) << 8) | \
00090 ((((b) >> 8) & 0xFF) ))
00091 #define ltohl(b) htoll(b)
00092 #define ltohs(b) htols(b)
00093 #else
00094 #error "Endianess not defined"
00095 #endif
00096 #endif
00097
00098
00099 static int mp3_open(struct ast_filestream *s)
00100 {
00101 struct mp3_private *p = s->private;
00102
00103 InitMP3(&p->mp, OUTSCALE);
00104 p->dbuflen = 0;
00105 s->fr.data = s->buf;
00106 s->fr.frametype = AST_FRAME_VOICE;
00107 s->fr.subclass = AST_FORMAT_SLINEAR;
00108
00109 s->fr.src = name;
00110 s->fr.mallocd = 0;
00111 p->offset = 0;
00112 return 0;
00113 }
00114
00115
00116 static void mp3_close(struct ast_filestream *s)
00117 {
00118 struct mp3_private *p = s->private;
00119
00120 ExitMP3(&p->mp);
00121 return;
00122 }
00123
00124 static int mp3_squeue(struct ast_filestream *s)
00125 {
00126 struct mp3_private *p = s->private;
00127 int res=0;
00128
00129 p->lastseek = ftell(s->f);
00130 p->sbuflen = fread(p->sbuf, 1, MP3_SCACHE, s->f);
00131 if(p->sbuflen < 0) {
00132 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", p->sbuflen, strerror(errno));
00133 return -1;
00134 }
00135 res = decodeMP3(&p->mp,p->sbuf,p->sbuflen,p->dbuf,MP3_DCACHE,&p->dbuflen);
00136 if(res != MP3_OK)
00137 return -1;
00138 p->sbuflen -= p->dbuflen;
00139 p->dbufoffset = 0;
00140 return 0;
00141 }
00142
00143 static int mp3_dqueue(struct ast_filestream *s)
00144 {
00145 struct mp3_private *p = s->private;
00146 int res=0;
00147
00148 if((res = decodeMP3(&p->mp,NULL,0,p->dbuf,MP3_DCACHE,&p->dbuflen)) == MP3_OK) {
00149 p->sbuflen -= p->dbuflen;
00150 p->dbufoffset = 0;
00151 }
00152 return res;
00153 }
00154
00155 static int mp3_queue(struct ast_filestream *s)
00156 {
00157 struct mp3_private *p = s->private;
00158 int res = 0, bytes = 0;
00159
00160 if(p->seek) {
00161 ExitMP3(&p->mp);
00162 InitMP3(&p->mp, OUTSCALE);
00163 fseek(s->f, 0, SEEK_SET);
00164 p->sbuflen = p->dbuflen = p->offset = 0;
00165 while(p->offset < p->seek) {
00166 if(mp3_squeue(s))
00167 return -1;
00168 while(p->offset < p->seek && ((res = mp3_dqueue(s))) == MP3_OK) {
00169 for(bytes = 0 ; bytes < p->dbuflen ; bytes++) {
00170 p->dbufoffset++;
00171 p->offset++;
00172 if(p->offset >= p->seek)
00173 break;
00174 }
00175 }
00176 if(res == MP3_ERR)
00177 return -1;
00178 }
00179
00180 p->seek = 0;
00181 return 0;
00182 }
00183 if(p->dbuflen == 0) {
00184 if(p->sbuflen) {
00185 res = mp3_dqueue(s);
00186 if(res == MP3_ERR)
00187 return -1;
00188 }
00189 if(! p->sbuflen || res != MP3_OK) {
00190 if(mp3_squeue(s))
00191 return -1;
00192 }
00193
00194 }
00195
00196 return 0;
00197 }
00198
00199 static struct ast_frame *mp3_read(struct ast_filestream *s, int *whennext)
00200 {
00201
00202 struct mp3_private *p = s->private;
00203 int delay =0;
00204 int save=0;
00205
00206
00207
00208 if(mp3_queue(s))
00209 return NULL;
00210
00211 if(p->dbuflen) {
00212 for(p->buflen=0; p->buflen < MP3_BUFLEN && p->buflen < p->dbuflen; p->buflen++) {
00213 s->buf[p->buflen] = p->dbuf[p->buflen+p->dbufoffset];
00214 p->sbufoffset++;
00215 }
00216 p->dbufoffset += p->buflen;
00217 p->dbuflen -= p->buflen;
00218
00219 if(p->buflen < MP3_BUFLEN) {
00220 if(mp3_queue(s))
00221 return NULL;
00222
00223 for(save = p->buflen; p->buflen < MP3_BUFLEN; p->buflen++) {
00224 s->buf[p->buflen] = p->dbuf[(p->buflen-save)+p->dbufoffset];
00225 p->sbufoffset++;
00226 }
00227 p->dbufoffset += (MP3_BUFLEN - save);
00228 p->dbuflen -= (MP3_BUFLEN - save);
00229
00230 }
00231
00232 }
00233
00234 p->offset += p->buflen;
00235 delay = p->buflen/2;
00236 s->fr.frametype = AST_FRAME_VOICE;
00237 s->fr.subclass = AST_FORMAT_SLINEAR;
00238 s->fr.offset = AST_FRIENDLY_OFFSET;
00239 s->fr.datalen = p->buflen;
00240 s->fr.data = s->buf;
00241 s->fr.mallocd = 0;
00242 s->fr.samples = delay;
00243 *whennext = delay;
00244 return &s->fr;
00245 }
00246
00247
00248 static int mp3_write(struct ast_filestream *fs, struct ast_frame *f)
00249 {
00250 ast_log(LOG_ERROR,"I Can't write MP3 only read them.\n");
00251 return -1;
00252
00253 }
00254
00255
00256 static int mp3_seek(struct ast_filestream *s, off_t sample_offset, int whence)
00257 {
00258 struct mp3_private *p = s->private;
00259 off_t min,max,cur;
00260 long offset=0,samples;
00261 samples = sample_offset * 2;
00262
00263 min = 0;
00264 fseek(s->f, 0, SEEK_END);
00265 max = ftell(s->f) * 100;
00266 cur = p->offset;
00267
00268 if (whence == SEEK_SET)
00269 offset = samples + min;
00270 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00271 offset = samples + cur;
00272 else if (whence == SEEK_END)
00273 offset = max - samples;
00274 if (whence != SEEK_FORCECUR) {
00275 offset = (offset > max)?max:offset;
00276 }
00277
00278 p->seek = offset;
00279 return p->seek;
00280
00281 }
00282
00283 static int mp3_rewrite(struct ast_filestream *s, const char *comment)
00284 {
00285 ast_log(LOG_ERROR,"I Can't write MP3 only read them.\n");
00286 return -1;
00287 }
00288
00289 static int mp3_trunc(struct ast_filestream *s)
00290 {
00291
00292 ast_log(LOG_ERROR,"I Can't write MP3 only read them.\n");
00293 return -1;
00294 }
00295
00296 static off_t mp3_tell(struct ast_filestream *s)
00297 {
00298 struct mp3_private *p = s->private;
00299
00300 return p->offset/2;
00301 }
00302
00303 static char *mp3_getcomment(struct ast_filestream *s)
00304 {
00305 return NULL;
00306 }
00307
00308 static const struct ast_format mp3_f = {
00309 .name = "mp3",
00310 .exts = "mp3",
00311 .format = AST_FORMAT_SLINEAR,
00312 .open = mp3_open,
00313 .write = mp3_write,
00314 .rewrite = mp3_rewrite,
00315 .seek = mp3_seek,
00316 .trunc = mp3_trunc,
00317 .tell = mp3_tell,
00318 .read = mp3_read,
00319 .close = mp3_close,
00320 .getcomment = mp3_getcomment,
00321 .buf_size = MP3_BUFLEN + AST_FRIENDLY_OFFSET,
00322 .desc_size = sizeof(struct mp3_private),
00323 };
00324
00325
00326 static int load_module(void)
00327 {
00328 InitMP3Constants();
00329 return ast_format_register(&mp3_f);
00330 }
00331
00332 static int unload_module(void)
00333 {
00334 return ast_format_unregister(name);
00335 }
00336
00337 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "MP3 format [Any rate but 8000hz mono is optimal]");