Files
asterisk/addons/mp3/interface.c
Kevin P. Fleming fff17a25dd Use "local" instead of "system" header file inclusion.
Now that these files are in the tree, they should prefer the tree's local
copy of all Asterisk headers over any that may be installed.



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@254931 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2010-03-25 23:38:58 +00:00

324 lines
5.5 KiB
C

#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;
}