diff options
Diffstat (limited to 'addons/mp3/interface.c')
-rw-r--r-- | addons/mp3/interface.c | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/addons/mp3/interface.c b/addons/mp3/interface.c new file mode 100644 index 000000000..9ced53342 --- /dev/null +++ b/addons/mp3/interface.c @@ -0,0 +1,323 @@ +#include <asterisk.h> +#include <asterisk/logger.h> + +#include <stdlib.h> +#include <stdio.h> + +#include "mpg123.h" +#include "mpglib.h" + + +void InitMP3Constants(void) +{ + init_layer3_const(); + make_decode_tables_const(); + +} + + +BOOL InitMP3(struct mpstr *mp, long outscale) +{ + /* quiet 4096 med 8192 */ + + memset(mp,0,sizeof(struct mpstr)); + + mp->framesize = 0; + mp->fsizeold = -1; + mp->bsize = 0; + mp->head = mp->tail = NULL; + mp->fr.single = 3; /* force mono */ + mp->bsnum = 0; + mp->synth_bo = 1; + mp->outsamplerate = 8000; + + make_decode_tables_scale(mp, outscale); + + init_layer3_sample_limits(mp, SBLIMIT); + + return !0; +} + +void ExitMP3(struct mpstr *mp) +{ + struct buf *b,*bn; + + b = mp->tail; + while(b) { + free(b->pnt); + bn = b->next; + free(b); + b = bn; + } +} + +static struct buf *addbuf(struct mpstr *mp,char *buf,int size) +{ + struct buf *nbuf; + + nbuf = malloc( sizeof(struct buf) ); + if(!nbuf) { + ast_log(LOG_WARNING,"Out of memory!\n"); + return NULL; + } + nbuf->pnt = malloc(size); + if(!nbuf->pnt) { + free(nbuf); + return NULL; + } + nbuf->size = size; + memcpy(nbuf->pnt,buf,size); + nbuf->next = NULL; + nbuf->prev = mp->head; + nbuf->pos = 0; + + if(!mp->tail) { + mp->tail = nbuf; + } + else { + mp->head->next = nbuf; + } + + mp->head = nbuf; + mp->bsize += size; + + return nbuf; +} + +static void remove_buf(struct mpstr *mp) +{ + struct buf *buf = mp->tail; + + mp->tail = buf->next; + if(mp->tail) + mp->tail->prev = NULL; + else { + mp->tail = mp->head = NULL; + } + + free(buf->pnt); + free(buf); + +} + +static int read_buf_byte(int *error, struct mpstr *mp) +{ + unsigned int b;int pos; + + pos = mp->tail->pos; + while(pos >= mp->tail->size) { + remove_buf(mp); + pos = mp->tail->pos; + if(!mp->tail) { + /* We may pick up this error a few times*/ + /* But things have gone pear shaped */ + ast_log(LOG_WARNING,"Fatal Buffer error!\n"); + *error = 1; + return (0); + } + } + + b = mp->tail->pnt[pos]; + mp->bsize--; + mp->tail->pos++; + + + return b; +} + +static int read_head(struct mpstr *mp) +{ + unsigned long head; + int error=0; + + + head = read_buf_byte(&error, mp); + head <<= 8; + head |= read_buf_byte(&error, mp); + head <<= 8; + head |= read_buf_byte(&error, mp); + head <<= 8; + head |= read_buf_byte(&error, mp); + + mp->header = head; + + if(error){ + return (1); + }else + return (0); + +} + +static int head_check(unsigned long head) +{ + if( (head & 0xffe00000) != 0xffe00000) + return FALSE; + if(!((head>>17)&3)) + return FALSE; + if( ((head>>12)&0xf) == 0xf || ((head>>12)&0xf) == 0) + return FALSE; + if( ((head>>10)&0x3) == 0x3 ) + return FALSE; + if ((head & 0xffff0000) == 0xfffe0000) + return FALSE; + + return TRUE; +} + +static int head_shift(struct mpstr *mp) +{ + unsigned long head; + int error = 0; + + head = mp->header; + + head <<= 8; + head |= read_buf_byte(&error, mp); + + mp->header = head; + + if (error){ + return (1); + }else + return (0); + +} + + +int decodeMP3(struct mpstr *mp,char *in,int isize,char *out, + int osize,int *done) +{ + int len; + long n,m; + int down_sample_sblimit; + + if(osize < 4608) { + ast_log(LOG_WARNING,"To less out space\n"); + return MP3_ERR; + } + + if(in) { + if(addbuf(mp,in,isize) == NULL) { + return MP3_ERR; + } + } + + /* First decode header */ + if(mp->framesize == 0) { + if(mp->bsize < 4) { + return MP3_NEED_MORE; + } + if (read_head(mp)) + return MP3_ERR; + + if(!head_check(mp->header) ) { + int i; + + ast_log(LOG_WARNING,"Junk at the beginning of frame %08lx\n",mp->header); + + /* step in byte steps through next 64K */ + for(i=0;i<65536;i++) { + if(!mp->bsize) + return MP3_NEED_MORE; + + if(head_shift(mp)) + return MP3_ERR; + + if(head_check(mp->header)) + break; + } + if(i == 65536) { + ast_log(LOG_WARNING,"Giving up searching valid MPEG header\n"); + return MP3_ERR; + } + } + + decode_header(&mp->fr,mp->header); + mp->framesize = mp->fr.framesize; + + if (!mp->initmp3){ + mp->initmp3 = 1; + + n = freqs[mp->fr.sampling_frequency]; + if (mp->outsamplerate) { + m = mp->outsamplerate; + } + else { + m =n; + } + + if (synth_ntom_set_step(n,m)) + return MP3_ERR; + + + if(n>m) { + down_sample_sblimit = SBLIMIT * m; + down_sample_sblimit /= n; + } + else { + down_sample_sblimit = SBLIMIT; + } + + init_layer3_sample_limits(mp, down_sample_sblimit); + + } + } + + + if(mp->fr.framesize > mp->bsize) + return MP3_NEED_MORE; + + (mp->worksample).wordpointer = mp->bsspace[mp->bsnum] + 512; + mp->bsnum = (mp->bsnum + 1) & 0x1; + (mp->worksample).bitindex = 0; + + len = 0; + while(len < mp->framesize) { + int nlen; + int blen = mp->tail->size - mp->tail->pos; + if( (mp->framesize - len) <= blen) { + nlen = mp->framesize-len; + } + else { + nlen = blen; + } + memcpy((mp->worksample).wordpointer+len,mp->tail->pnt+mp->tail->pos,nlen); + len += nlen; + mp->tail->pos += nlen; + mp->bsize -= nlen; + if(mp->tail->pos == mp->tail->size) { + remove_buf(mp); + } + } + + *done = 0; + if(mp->fr.error_protection) + getbits(mp, 16); + + if (do_layer3(mp,(unsigned char *) out,done)) + return MP3_ERR; + + mp->fsizeold = mp->framesize; + mp->framesize = 0; + + return MP3_OK; +} + +int set_pointer(struct mpstr *mp, long backstep) +{ + unsigned char *bsbufold; + if(mp->fsizeold < 0 && backstep > 0) { + ast_log(LOG_WARNING,"Can't step back %ld!\n",backstep); + return MP3_ERR; + } + bsbufold = mp->bsspace[mp->bsnum] + 512; + (mp->worksample).wordpointer -= backstep; + if (backstep) + memcpy((mp->worksample).wordpointer,bsbufold+mp->fsizeold-backstep,backstep); + (mp->worksample).bitindex = 0; + return MP3_OK; +} + + + + |