From 9f0cbe9e496d950e796e3b07bca8db8841bb2798 Mon Sep 17 00:00:00 2001 From: Warren Dukes Date: Mon, 31 May 2004 02:56:14 +0000 Subject: aac_plugin git-svn-id: https://svn.musicpd.org/mpd/trunk@1250 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/Makefile.am | 6 +- src/aac_decode.c | 400 -------------------------------------- src/aac_decode.h | 35 ---- src/inputPlugins/aac_plugin.c | 438 ++++++++++++++++++++++++++++++++++++++++++ src/tag.c | 18 -- 5 files changed, 441 insertions(+), 456 deletions(-) delete mode 100644 src/aac_decode.c delete mode 100644 src/aac_decode.h create mode 100644 src/inputPlugins/aac_plugin.c diff --git a/src/Makefile.am b/src/Makefile.am index e9b1f1a0e..ad1544e35 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,14 +3,14 @@ SUBDIRS = $(ID3_SUBDIR) $(MAD_SUBDIR) $(MP4FF_SUBDIR) mpd_inputPlugins = inputPlugins/mp3_plugin.c inputPlugins/ogg_plugin.c \ inputPlugins/flac_plugin.c inputPlugins/audiofile_plugin.c \ - inputPlugins/mp4_plugin.c + inputPlugins/mp4_plugin.c inputPlugins/aac_plugin.c mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \ song.h list.h directory.h tables.h utils.h path.h \ tag.h player.h listen.h conf.h volume.h \ audio.h playerData.h stats.h myfprintf.h sig_handlers.h decode.h log.h \ charConv.h permission.h mpd_types.h pcm_utils.h \ - aac_decode.h signal_check.h utf8.h inputStream.h \ + signal_check.h utf8.h inputStream.h \ outputBuffer.h replayGain.h inputStream_file.h inputStream_http.h \ inputPlugin.h mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \ @@ -18,7 +18,7 @@ mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \ tag.c player.c listen.c conf.c volume.c \ audio.c playerData.c stats.c myfprintf.c sig_handlers.c decode.c log.c \ charConv.c permission.c pcm_utils.c \ - aac_decode.c signal_check.c utf8.c inputStream.c outputBuffer.c \ + signal_check.c utf8.c inputStream.c outputBuffer.c \ replayGain.c inputStream_file.c inputStream_http.c inputPlugin.c \ $(mpd_headers) $(mpd_inputPlugins) diff --git a/src/aac_decode.c b/src/aac_decode.c deleted file mode 100644 index 6dbaea1bc..000000000 --- a/src/aac_decode.c +++ /dev/null @@ -1,400 +0,0 @@ -/* the Music Player Daemon (MPD) - * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "aac_decode.h" - -#ifdef HAVE_FAAD - -#define AAC_MAX_CHANNELS 6 - -#include "command.h" -#include "utils.h" -#include "audio.h" -#include "log.h" -#include "inputStream.h" -#include "outputBuffer.h" - -#include -#include -#include -#include -#include - -/* all code here is either based on or copied from FAAD2's frontend code */ -typedef struct { - InputStream * inStream; - long bytesIntoBuffer; - long bytesConsumed; - long fileOffset; - unsigned char *buffer; - int atEof; -} AacBuffer; - -void fillAacBuffer(AacBuffer *b) { - if(b->bytesConsumed > 0) { - int bread; - - if(b->bytesIntoBuffer) { - memmove((void *)b->buffer,(void*)(b->buffer+ - b->bytesConsumed),b->bytesIntoBuffer); - } - - if(!b->atEof) { - bread = readFromInputStream(b->inStream, - (void *)(b->buffer+b->bytesIntoBuffer), - 1,b->bytesConsumed); - if(bread!=b->bytesConsumed) b->atEof = 1; - b->bytesIntoBuffer+=bread; - } - - b->bytesConsumed = 0; - - if(b->bytesIntoBuffer > 3) { - if(memcmp(b->buffer,"TAG",3)==0) b->bytesIntoBuffer = 0; - } - if(b->bytesIntoBuffer > 11) { - if(memcmp(b->buffer,"LYRICSBEGIN",11)==0) { - b->bytesIntoBuffer = 0; - } - } - if(b->bytesIntoBuffer > 8) { - if(memcmp(b->buffer,"APETAGEX",8)==0) { - b->bytesIntoBuffer = 0; - } - } - } -} - -void advanceAacBuffer(AacBuffer * b, int bytes) { - b->fileOffset+=bytes; - b->bytesConsumed = bytes; - b->bytesIntoBuffer-=bytes; -} - -static int adtsSampleRates[] = {96000,88200,64000,48000,44100,32000,24000,22050, - 16000,12000,11025,8000,7350,0,0,0}; - -int adtsParse(AacBuffer * b, float * length) { - int frames, frameLength; - int tFrameLength = 0; - int sampleRate = 0; - float framesPerSec, bytesPerFrame; - - /* Read all frames to ensure correct time and bitrate */ - for(frames = 0; ;frames++) { - fillAacBuffer(b); - - if(b->bytesIntoBuffer > 7) { - /* check syncword */ - if (!((b->buffer[0] == 0xFF) && - ((b->buffer[1] & 0xF6) == 0xF0))) - { - break; - } - - if(frames==0) { - sampleRate = adtsSampleRates[ - (b->buffer[2]&0x3c)>>2]; - } - - frameLength = ((((unsigned int)b->buffer[3] & 0x3)) - << 11) | (((unsigned int)b->buffer[4]) - << 3) | (b->buffer[5] >> 5); - - tFrameLength+=frameLength; - - if(frameLength > b->bytesIntoBuffer) break; - - advanceAacBuffer(b,frameLength); - } - else break; - } - - framesPerSec = (float)sampleRate/1024.0; - if(frames!=0) { - bytesPerFrame = (float)tFrameLength/(float)(frames*1000); - } - else bytesPerFrame = 0; - if(framesPerSec!=0) *length = (float)frames/framesPerSec; - - return 1; -} - -void initAacBuffer(InputStream * inStream, AacBuffer * b, float * length, - size_t * retFileread, size_t * retTagsize) -{ - size_t fileread; - size_t bread; - size_t tagsize; - - if(length) *length = -1; - - memset(b,0,sizeof(AacBuffer)); - - b->inStream = inStream; - - fileread = inStream->size; - - b->buffer = malloc(FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); - memset(b->buffer,0,FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); - - bread = readFromInputStream(inStream,b->buffer,1, - FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); - b->bytesIntoBuffer = bread; - b->bytesConsumed = 0; - b->fileOffset = 0; - - if(bread!=FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS) b->atEof = 1; - - tagsize = 0; - if(!memcmp(b->buffer,"ID3",3)) { - tagsize = (b->buffer[6] << 21) | (b->buffer[7] << 14) | - (b->buffer[8] << 7) | (b->buffer[9] << 0); - - tagsize+=10; - advanceAacBuffer(b,tagsize); - fillAacBuffer(b); - } - - if(retFileread) *retFileread = fileread; - if(retTagsize) *retTagsize = tagsize; - - if(length==NULL) return; - - if((b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) { - adtsParse(b, length); - seekInputStream(b->inStream, tagsize, SEEK_SET); - - bread = readFromInputStream(b->inStream, b->buffer, 1, - FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); - if(bread != FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS) b->atEof = 1; - else b->atEof = 0; - b->bytesIntoBuffer = bread; - b->bytesConsumed = 0; - b->fileOffset = tagsize; - } - else if(memcmp(b->buffer,"ADIF",4) == 0) { - int bitRate; - int skipSize = (b->buffer[4] & 0x80) ? 9 : 0; - bitRate = ((unsigned int)(b->buffer[4 + skipSize] & 0x0F)<<19) | - ((unsigned int)b->buffer[5 + skipSize]<<11) | - ((unsigned int)b->buffer[6 + skipSize]<<3) | - ((unsigned int)b->buffer[7 + skipSize] & 0xE0); - - *length = fileread; - if(*length!=0 && bitRate!=0) *length = *length*8.0/bitRate; - } -} - -float getAacFloatTotalTime(char * file) { - AacBuffer b; - float length; - size_t fileread, tagsize; - faacDecHandle decoder; - faacDecConfigurationPtr config; - unsigned long sampleRate; - unsigned char channels; - InputStream inStream; - size_t bread; - - if(openInputStream(&inStream,file) < 0) return -1; - - initAacBuffer(&inStream,&b,&length,&fileread,&tagsize); - - if(length < 0) { - decoder = faacDecOpen(); - - config = faacDecGetCurrentConfiguration(decoder); - config->outputFormat = FAAD_FMT_16BIT; - faacDecSetConfiguration(decoder,config); - - fillAacBuffer(&b); -#ifdef HAVE_FAAD_BUFLEN_FUNCS - bread = faacDecInit(decoder,b.buffer,b.bytesIntoBuffer, - &sampleRate,&channels); -#else - bread = faacDecInit(decoder,b.buffer,&sampleRate,&channels); -#endif - if(bread >= 0 && sampleRate > 0 && channels > 0) length = 0; - - faacDecClose(decoder); - } - - if(b.buffer) free(b.buffer); - closeInputStream(&inStream); - - return length; -} - -int getAacTotalTime(char * file) { - int time = -1; - float length; - - if((length = getAacFloatTotalTime(file))>=0) time = length+0.5; - - return time; -} - - -int aac_decode(OutputBuffer * cb, DecoderControl * dc) { - float time; - float totalTime; - faacDecHandle decoder; - faacDecFrameInfo frameInfo; - faacDecConfigurationPtr config; - size_t bread; - unsigned long sampleRate; - unsigned char channels; - int eof = 0; - unsigned int sampleCount; - char * sampleBuffer; - size_t sampleBufferLen; - /*float * seekTable; - long seekTableEnd = -1; - int seekPositionFound = 0;*/ - mpd_uint16 bitRate = 0; - AacBuffer b; - InputStream inStream; - - if((totalTime = getAacFloatTotalTime(dc->file)) < 0) return -1; - - if(openInputStream(&inStream,dc->file) < 0) return -1; - - initAacBuffer(&inStream,&b,NULL,NULL,NULL); - - decoder = faacDecOpen(); - - config = faacDecGetCurrentConfiguration(decoder); - config->outputFormat = FAAD_FMT_16BIT; -#ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX - config->downMatrix = 1; -#endif -#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR - config->dontUpSampleImplicitSBR = 0; -#endif - faacDecSetConfiguration(decoder,config); - - fillAacBuffer(&b); - -#ifdef HAVE_FAAD_BUFLEN_FUNCS - bread = faacDecInit(decoder,b.buffer,b.bytesIntoBuffer, - &sampleRate,&channels); -#else - bread = faacDecInit(decoder,b.buffer,&sampleRate,&channels); -#endif - if(bread < 0) { - ERROR("Error not a AAC stream.\n"); - faacDecClose(decoder); - closeInputStream(b.inStream); - if(b.buffer) free(b.buffer); - return -1; - } - - dc->audioFormat.bits = 16; - - dc->totalTime = totalTime; - - time = 0.0; - - advanceAacBuffer(&b,bread); - - while(!eof) { - fillAacBuffer(&b); - - if(b.bytesIntoBuffer==0) { - eof = 1; - break; - } - -#ifdef HAVE_FAAD_BUFLEN_FUNCS - sampleBuffer = faacDecDecode(decoder,&frameInfo,b.buffer, - b.bytesIntoBuffer); -#else - sampleBuffer = faacDecDecode(decoder,&frameInfo,b.buffer); -#endif - - if(frameInfo.error > 0) { - ERROR("error decoding AAC file: %s\n",dc->file); - ERROR("faad2 error: %s\n", - faacDecGetErrorMessage(frameInfo.error)); - eof = 1; - break; - } - -#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE - sampleRate = frameInfo.samplerate; -#endif - - if(dc->state != DECODE_STATE_DECODE) { - dc->audioFormat.channels = frameInfo.channels; - dc->audioFormat.sampleRate = sampleRate; - getOutputAudioFormat(&(dc->audioFormat), - &(cb->audioFormat)); - dc->state = DECODE_STATE_DECODE; - } - - advanceAacBuffer(&b,frameInfo.bytesconsumed); - - sampleCount = (unsigned long)(frameInfo.samples); - - if(sampleCount>0) { - bitRate = frameInfo.bytesconsumed*8.0* - frameInfo.channels*sampleRate/ - frameInfo.samples/1000+0.5; - time+= (float)(frameInfo.samples)/frameInfo.channels/ - sampleRate; - } - - sampleBufferLen = sampleCount*2; - - sendDataToOutputBuffer(cb, NULL, dc, 0, sampleBuffer, - sampleBufferLen, time, bitRate); - if(dc->seek) { - dc->seekError = 1; - dc->seek = 0; - } - else if(dc->stop) { - eof = 1; - break; - } - } while (!eof); - - flushOutputBuffer(cb); - - faacDecClose(decoder); - closeInputStream(b.inStream); - if(b.buffer) free(b.buffer); - - if(dc->state != DECODE_STATE_DECODE) return -1; - - if(dc->seek) { - dc->seekError = 1; - dc->seek = 0; - } - - if(dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } - else dc->state = DECODE_STATE_STOP; - - return 0; -} - -#endif /* HAVE_FAAD */ -/* vim:set shiftwidth=4 tabstop=8 expandtab: */ diff --git a/src/aac_decode.h b/src/aac_decode.h deleted file mode 100644 index 3d1636726..000000000 --- a/src/aac_decode.h +++ /dev/null @@ -1,35 +0,0 @@ -/* the Music Player Daemon (MPD) - * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef AAC_DECODE_H -#define AAC_DECODE_H - -#include "../config.h" - -#ifdef HAVE_FAAD - -#include "playerData.h" - -int getAacTotalTime(char * file); - -int aac_decode(OutputBuffer * cb, DecoderControl * dc); - -#endif /* HAVE_FAAD */ - -#endif -/* vim:set shiftwidth=4 tabstop=8 expandtab: */ diff --git a/src/inputPlugins/aac_plugin.c b/src/inputPlugins/aac_plugin.c new file mode 100644 index 000000000..0dd23f955 --- /dev/null +++ b/src/inputPlugins/aac_plugin.c @@ -0,0 +1,438 @@ +/* the Music Player Daemon (MPD) + * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) + * This project's homepage is: http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "../inputPlugin.h" + +#ifdef HAVE_FAAD + +#define AAC_MAX_CHANNELS 6 + +#include "../utils.h" +#include "../audio.h" +#include "../log.h" +#include "../inputStream.h" +#include "../outputBuffer.h" + +#include +#include +#include +#include +#include + +/* all code here is either based on or copied from FAAD2's frontend code */ +typedef struct { + InputStream * inStream; + long bytesIntoBuffer; + long bytesConsumed; + long fileOffset; + unsigned char *buffer; + int atEof; +} AacBuffer; + +void fillAacBuffer(AacBuffer *b) { + if(b->bytesConsumed > 0) { + int bread; + + if(b->bytesIntoBuffer) { + memmove((void *)b->buffer,(void*)(b->buffer+ + b->bytesConsumed),b->bytesIntoBuffer); + } + + if(!b->atEof) { + bread = readFromInputStream(b->inStream, + (void *)(b->buffer+b->bytesIntoBuffer), + 1,b->bytesConsumed); + if(bread!=b->bytesConsumed) b->atEof = 1; + b->bytesIntoBuffer+=bread; + } + + b->bytesConsumed = 0; + + if(b->bytesIntoBuffer > 3) { + if(memcmp(b->buffer,"TAG",3)==0) b->bytesIntoBuffer = 0; + } + if(b->bytesIntoBuffer > 11) { + if(memcmp(b->buffer,"LYRICSBEGIN",11)==0) { + b->bytesIntoBuffer = 0; + } + } + if(b->bytesIntoBuffer > 8) { + if(memcmp(b->buffer,"APETAGEX",8)==0) { + b->bytesIntoBuffer = 0; + } + } + } +} + +void advanceAacBuffer(AacBuffer * b, int bytes) { + b->fileOffset+=bytes; + b->bytesConsumed = bytes; + b->bytesIntoBuffer-=bytes; +} + +static int adtsSampleRates[] = {96000,88200,64000,48000,44100,32000,24000,22050, + 16000,12000,11025,8000,7350,0,0,0}; + +int adtsParse(AacBuffer * b, float * length) { + int frames, frameLength; + int tFrameLength = 0; + int sampleRate = 0; + float framesPerSec, bytesPerFrame; + + /* Read all frames to ensure correct time and bitrate */ + for(frames = 0; ;frames++) { + fillAacBuffer(b); + + if(b->bytesIntoBuffer > 7) { + /* check syncword */ + if (!((b->buffer[0] == 0xFF) && + ((b->buffer[1] & 0xF6) == 0xF0))) + { + break; + } + + if(frames==0) { + sampleRate = adtsSampleRates[ + (b->buffer[2]&0x3c)>>2]; + } + + frameLength = ((((unsigned int)b->buffer[3] & 0x3)) + << 11) | (((unsigned int)b->buffer[4]) + << 3) | (b->buffer[5] >> 5); + + tFrameLength+=frameLength; + + if(frameLength > b->bytesIntoBuffer) break; + + advanceAacBuffer(b,frameLength); + } + else break; + } + + framesPerSec = (float)sampleRate/1024.0; + if(frames!=0) { + bytesPerFrame = (float)tFrameLength/(float)(frames*1000); + } + else bytesPerFrame = 0; + if(framesPerSec!=0) *length = (float)frames/framesPerSec; + + return 1; +} + +void initAacBuffer(InputStream * inStream, AacBuffer * b, float * length, + size_t * retFileread, size_t * retTagsize) +{ + size_t fileread; + size_t bread; + size_t tagsize; + + if(length) *length = -1; + + memset(b,0,sizeof(AacBuffer)); + + b->inStream = inStream; + + fileread = inStream->size; + + b->buffer = malloc(FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); + memset(b->buffer,0,FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); + + bread = readFromInputStream(inStream,b->buffer,1, + FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); + b->bytesIntoBuffer = bread; + b->bytesConsumed = 0; + b->fileOffset = 0; + + if(bread!=FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS) b->atEof = 1; + + tagsize = 0; + if(!memcmp(b->buffer,"ID3",3)) { + tagsize = (b->buffer[6] << 21) | (b->buffer[7] << 14) | + (b->buffer[8] << 7) | (b->buffer[9] << 0); + + tagsize+=10; + advanceAacBuffer(b,tagsize); + fillAacBuffer(b); + } + + if(retFileread) *retFileread = fileread; + if(retTagsize) *retTagsize = tagsize; + + if(length==NULL) return; + + if((b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) { + adtsParse(b, length); + seekInputStream(b->inStream, tagsize, SEEK_SET); + + bread = readFromInputStream(b->inStream, b->buffer, 1, + FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); + if(bread != FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS) b->atEof = 1; + else b->atEof = 0; + b->bytesIntoBuffer = bread; + b->bytesConsumed = 0; + b->fileOffset = tagsize; + } + else if(memcmp(b->buffer,"ADIF",4) == 0) { + int bitRate; + int skipSize = (b->buffer[4] & 0x80) ? 9 : 0; + bitRate = ((unsigned int)(b->buffer[4 + skipSize] & 0x0F)<<19) | + ((unsigned int)b->buffer[5 + skipSize]<<11) | + ((unsigned int)b->buffer[6 + skipSize]<<3) | + ((unsigned int)b->buffer[7 + skipSize] & 0xE0); + + *length = fileread; + if(*length!=0 && bitRate!=0) *length = *length*8.0/bitRate; + } +} + +float getAacFloatTotalTime(char * file) { + AacBuffer b; + float length; + size_t fileread, tagsize; + faacDecHandle decoder; + faacDecConfigurationPtr config; + unsigned long sampleRate; + unsigned char channels; + InputStream inStream; + size_t bread; + + if(openInputStream(&inStream,file) < 0) return -1; + + initAacBuffer(&inStream,&b,&length,&fileread,&tagsize); + + if(length < 0) { + decoder = faacDecOpen(); + + config = faacDecGetCurrentConfiguration(decoder); + config->outputFormat = FAAD_FMT_16BIT; + faacDecSetConfiguration(decoder,config); + + fillAacBuffer(&b); +#ifdef HAVE_FAAD_BUFLEN_FUNCS + bread = faacDecInit(decoder,b.buffer,b.bytesIntoBuffer, + &sampleRate,&channels); +#else + bread = faacDecInit(decoder,b.buffer,&sampleRate,&channels); +#endif + if(bread >= 0 && sampleRate > 0 && channels > 0) length = 0; + + faacDecClose(decoder); + } + + if(b.buffer) free(b.buffer); + closeInputStream(&inStream); + + return length; +} + +int getAacTotalTime(char * file) { + int time = -1; + float length; + + if((length = getAacFloatTotalTime(file))>=0) time = length+0.5; + + return time; +} + + +int aac_decode(OutputBuffer * cb, DecoderControl * dc) { + float time; + float totalTime; + faacDecHandle decoder; + faacDecFrameInfo frameInfo; + faacDecConfigurationPtr config; + size_t bread; + unsigned long sampleRate; + unsigned char channels; + int eof = 0; + unsigned int sampleCount; + char * sampleBuffer; + size_t sampleBufferLen; + /*float * seekTable; + long seekTableEnd = -1; + int seekPositionFound = 0;*/ + mpd_uint16 bitRate = 0; + AacBuffer b; + InputStream inStream; + + if((totalTime = getAacFloatTotalTime(dc->file)) < 0) return -1; + + if(openInputStream(&inStream,dc->file) < 0) return -1; + + initAacBuffer(&inStream,&b,NULL,NULL,NULL); + + decoder = faacDecOpen(); + + config = faacDecGetCurrentConfiguration(decoder); + config->outputFormat = FAAD_FMT_16BIT; +#ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX + config->downMatrix = 1; +#endif +#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR + config->dontUpSampleImplicitSBR = 0; +#endif + faacDecSetConfiguration(decoder,config); + + fillAacBuffer(&b); + +#ifdef HAVE_FAAD_BUFLEN_FUNCS + bread = faacDecInit(decoder,b.buffer,b.bytesIntoBuffer, + &sampleRate,&channels); +#else + bread = faacDecInit(decoder,b.buffer,&sampleRate,&channels); +#endif + if(bread < 0) { + ERROR("Error not a AAC stream.\n"); + faacDecClose(decoder); + closeInputStream(b.inStream); + if(b.buffer) free(b.buffer); + return -1; + } + + dc->audioFormat.bits = 16; + + dc->totalTime = totalTime; + + time = 0.0; + + advanceAacBuffer(&b,bread); + + while(!eof) { + fillAacBuffer(&b); + + if(b.bytesIntoBuffer==0) { + eof = 1; + break; + } + +#ifdef HAVE_FAAD_BUFLEN_FUNCS + sampleBuffer = faacDecDecode(decoder,&frameInfo,b.buffer, + b.bytesIntoBuffer); +#else + sampleBuffer = faacDecDecode(decoder,&frameInfo,b.buffer); +#endif + + if(frameInfo.error > 0) { + ERROR("error decoding AAC file: %s\n",dc->file); + ERROR("faad2 error: %s\n", + faacDecGetErrorMessage(frameInfo.error)); + eof = 1; + break; + } + +#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE + sampleRate = frameInfo.samplerate; +#endif + + if(dc->state != DECODE_STATE_DECODE) { + dc->audioFormat.channels = frameInfo.channels; + dc->audioFormat.sampleRate = sampleRate; + getOutputAudioFormat(&(dc->audioFormat), + &(cb->audioFormat)); + dc->state = DECODE_STATE_DECODE; + } + + advanceAacBuffer(&b,frameInfo.bytesconsumed); + + sampleCount = (unsigned long)(frameInfo.samples); + + if(sampleCount>0) { + bitRate = frameInfo.bytesconsumed*8.0* + frameInfo.channels*sampleRate/ + frameInfo.samples/1000+0.5; + time+= (float)(frameInfo.samples)/frameInfo.channels/ + sampleRate; + } + + sampleBufferLen = sampleCount*2; + + sendDataToOutputBuffer(cb, NULL, dc, 0, sampleBuffer, + sampleBufferLen, time, bitRate); + if(dc->seek) { + dc->seekError = 1; + dc->seek = 0; + } + else if(dc->stop) { + eof = 1; + break; + } + } while (!eof); + + flushOutputBuffer(cb); + + faacDecClose(decoder); + closeInputStream(b.inStream); + if(b.buffer) free(b.buffer); + + if(dc->state != DECODE_STATE_DECODE) return -1; + + if(dc->seek) { + dc->seekError = 1; + dc->seek = 0; + } + + if(dc->stop) { + dc->state = DECODE_STATE_STOP; + dc->stop = 0; + } + else dc->state = DECODE_STATE_STOP; + + return 0; +} + +MpdTag * aacTagDup(char * file) { + MpdTag * ret = NULL; + int time; + + time = getAacTotalTime(file); + + if(time>=0) { + if((ret = id3Dup(file))==NULL) ret = newMpdTag(); + ret->time = time; + } + + return ret; +} + +char * aacSuffixes[] = {"aac", NULL}; + +InputPlugin aacPlugin = +{ + "aac", + NULL, + aac_decode, + aacTagDup, + INPUT_PLUGIN_STREAM_FILE, + aacSuffixes, + NULL +}; + +#else + +InputPlugin aacPlugin = +{ + NULL, + NULL, + NULL, + NULL, + 0, + NULL, + NULL, +}; + +#endif /* HAVE_FAAD */ diff --git a/src/tag.c b/src/tag.c index d9fef82b9..954019eea 100644 --- a/src/tag.c +++ b/src/tag.c @@ -148,24 +148,6 @@ MpdTag * id3Dup(char * file) { return ret; } -#ifdef HAVE_FAAD -MpdTag * aacTagDup(char * utf8file) { - MpdTag * ret = NULL; - int time; - - time = getAacTotalTime(rmp2amp(utf8ToFsCharset(utf8file))); - - if(time>=0) { - if((ret = id3Dup(utf8file))==NULL) ret = newMpdTag(); - ret->time = time; - } - - if(ret) validateUtf8Tag(ret); - - return ret; -} -#endif - MpdTag * newMpdTag() { MpdTag * ret = malloc(sizeof(MpdTag)); ret->album = NULL; -- cgit v1.2.3