diff options
author | Warren Dukes <warren.dukes@gmail.com> | 2004-03-21 21:32:23 +0000 |
---|---|---|
committer | Warren Dukes <warren.dukes@gmail.com> | 2004-03-21 21:32:23 +0000 |
commit | 4c1eb9225d5a741e1234d48eb38a8df3da908259 (patch) | |
tree | 28d8821623d6f9cce26f316e18342f2c08250785 /src | |
parent | b72f591641e9d311e813fb8e2ece643cc6562e56 (diff) | |
download | mpd-4c1eb9225d5a741e1234d48eb38a8df3da908259.tar.gz mpd-4c1eb9225d5a741e1234d48eb38a8df3da908259.tar.xz mpd-4c1eb9225d5a741e1234d48eb38a8df3da908259.zip |
add aac_decode.[ch] and start working on it
also, if locale is C or POSIX, set fs charset to iso-8859-1
git-svn-id: https://svn.musicpd.org/mpd/trunk@347 09075e82-0dd4-0310-85a5-a0d7c8717e4f
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/aac_decode.c | 460 | ||||
-rw-r--r-- | src/aac_decode.h | 36 | ||||
-rw-r--r-- | src/directory.c | 12 | ||||
-rw-r--r-- | src/main.c | 12 | ||||
-rw-r--r-- | src/mp4_decode.h | 2 | ||||
-rw-r--r-- | src/path.c | 40 | ||||
-rw-r--r-- | src/tag.c | 170 |
8 files changed, 544 insertions, 192 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7e4b12090..16f74d57f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,13 +5,13 @@ mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \ tag.h player.h listen.h conf.h ogg_decode.h volume.h flac_decode.h \ audio.h playerData.h stats.h myfprintf.h sig_handlers.h decode.h log.h \ audiofile_decode.h charConv.h permission.h mpd_types.h pcm_utils.h \ - mp4_decode.h + mp4_decode.h aac_decode.h mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \ song.c list.c directory.c tables.c utils.c path.c mp3_decode.c \ tag.c player.c listen.c conf.c ogg_decode.c volume.c flac_decode.c \ audio.c playerData.c stats.c myfprintf.c sig_handlers.c decode.c log.c \ audiofile_decode.c charConv.c permission.c pcm_utils.c mp4_decode.c \ - $(mpd_headers) + aac_decode.c $(mpd_headers) mpd_CFLAGS = $(MPD_CFLAGS) mpd_LDADD = $(MPD_LIBS) $(ID3_LIB) $(MAD_LIB) $(MP4FF_LIB) diff --git a/src/aac_decode.c b/src/aac_decode.c new file mode 100644 index 000000000..26e430d06 --- /dev/null +++ b/src/aac_decode.c @@ -0,0 +1,460 @@ +/* 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 + * + * libaudiofile (wave) support added by Eric Wong <normalperson@yhbt.net> + * + * 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 <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <faad.h> + +/* all code here is either based on or copied from FAAD2's frontend code */ +typedef struct { + long bytesIntoBuffer; + long bytesConsumed; + long fileOffset; + unsigned char *buffer; + int atEof; + FILE *infile; +} 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 = fread((void *)(b->buffer+b->bytesIntoBuffer),1, + b->bytesConsumed,b->infile); + 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; +} + +int initAacBuffer(char * file, AacBuffer * b, float * length) { + size_t fileread; + size_t bread; + size_t tagsize; + + *length = -1; + + memset(b,0,sizeof(AacBuffer)); + + b->infile = fopen(file,"r"); + if(b->infile == NULL) return -1; + + fseek(b->infile,0,SEEK_END); + fileread = ftell(b->infile); + fseek(b->infile,0,SEEK_SET); + + b->buffer = malloc(FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); + memset(b->buffer,0,FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); + + bread = fread(b->buffer,1,FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS, + b->infile); + 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((b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) { + adtsParse(b, length); + fseek(b->infile, tagsize, SEEK_SET); + + bread = fread(b->buffer, 1, + FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS, + b->infile); + 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; + } + + if(*length<0) return -1; + + return 0; +} + +int getAacTotalTime(char * file) { + AacBuffer b; + float length; + + if(initAacBuffer(file,&b,&length) < 0) return -1; + + if(b.buffer) free(b.buffer); + fclose(b.infile); + + return (int)(length+0.5); +} + + +int aac_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc) { + /*FILE * fh; + mp4ff_t * mp4fh; + mp4ff_callback_t * mp4cb; + int32_t track; + float time; + int32_t scale; + faacDecHandle decoder; + faacDecFrameInfo frameInfo; + faacDecConfigurationPtr config; + unsigned char * mp4Buffer; + int mp4BufferSize; + unsigned long sampleRate; + unsigned char channels; + long sampleId; + long numSamples; + int eof = 0; + long dur; + unsigned int sampleCount; + char * sampleBuffer; + size_t sampleBufferLen; + unsigned int initial = 1; + int chunkLen = 0; + float * seekTable; + long seekTableEnd = -1; + int seekPositionFound = 0; + long offset; + mpd_uint16 bitRate = 0; + + fh = fopen(dc->file,"r"); + if(!fh) { + ERROR("failed to open %s\n",dc->file); + return -1; + } + + mp4cb = malloc(sizeof(mp4ff_callback_t)); + mp4cb->read = mp4_readCallback; + mp4cb->seek = mp4_seekCallback; + mp4cb->user_data = fh; + + mp4fh = mp4ff_open_read(mp4cb); + if(!mp4fh) { + ERROR("Input does not appear to be a mp4 stream.\n"); + free(mp4cb); + fclose(fh); + return -1; + } + + track = mp4_getAACTrack(mp4fh); + if(track < 0) { + ERROR("No AAC track found in mp4 stream.\n"); + mp4ff_close(mp4fh); + fclose(fh); + free(mp4cb); + return -1; + } + + 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); + + af->bits = 16; + + mp4Buffer = NULL; + mp4BufferSize = 0; + mp4ff_get_decoder_config(mp4fh,track,&mp4Buffer,&mp4BufferSize); + + if(faacDecInit2(decoder,mp4Buffer,mp4BufferSize,&sampleRate,&channels) + < 0) + { + ERROR("Error initializing AAC decoder library.\n"); + faacDecClose(decoder); + mp4ff_close(mp4fh); + free(mp4cb); + fclose(fh); + return -1; + } + + af->sampleRate = sampleRate; + af->channels = channels; + time = mp4ff_get_track_duration_use_offsets(mp4fh,track); + scale = mp4ff_time_scale(mp4fh,track); + + if(mp4Buffer) free(mp4Buffer); + + if(scale < 0) { + ERROR("Error getting audio format of mp4 AAC track.\n"); + faacDecClose(decoder); + mp4ff_close(mp4fh); + fclose(fh); + free(mp4cb); + return -1; + } + cb->totalTime = ((float)time)/scale; + + numSamples = mp4ff_num_samples(mp4fh,track); + + dc->state = DECODE_STATE_DECODE; + dc->start = 0; + time = 0.0; + + seekTable = malloc(sizeof(float)*numSamples); + + for(sampleId=0; sampleId<numSamples && !eof; sampleId++) { + if(dc->seek && seekTableEnd>1 && + seekTable[seekTableEnd]>=dc->seekWhere) + { + int i = 2; + while(seekTable[i]<dc->seekWhere) i++; + sampleId = i-1; + time = seekTable[sampleId]; + } + + dur = mp4ff_get_sample_duration(mp4fh,track,sampleId); + offset = mp4ff_get_sample_offset(mp4fh,track,sampleId); + + if(sampleId>seekTableEnd) { + seekTable[sampleId] = time; + seekTableEnd = sampleId; + } + + if(sampleId==0) dur = 0; + if(offset>dur) dur = 0; + else dur-=offset; + time+=((float)dur)/scale; + + if(dc->seek && time>dc->seekWhere) seekPositionFound = 1; + + if(dc->seek && seekPositionFound) { + seekPositionFound = 0; + chunkLen = 0; + cb->end = 0; + cb->wrap = 0; + dc->seek = 0; + } + + if(dc->seek) continue; + + if(mp4ff_read_sample(mp4fh,track,sampleId,&mp4Buffer, + &mp4BufferSize) == 0) + { + eof = 1; + continue; + } + + sampleBuffer = faacDecDecode(decoder,&frameInfo,mp4Buffer, + mp4BufferSize); + if(mp4Buffer) free(mp4Buffer); + if(frameInfo.error > 0) { + eof = 1; + break; + } + + if(channels*(dur+offset) > frameInfo.samples) { + dur = frameInfo.samples; + offset = 0; + } + + sampleCount = (unsigned long)(dur*channels); + + if(sampleCount>0) { + initial =0; + bitRate = frameInfo.bytesconsumed*8.0* + frameInfo.channels*scale/ + frameInfo.samples/1024+0.5; + } + + + sampleBufferLen = sampleCount*2; + + sampleBuffer+=offset*channels*2; + + while(sampleBufferLen>0 && !dc->seek) { + size_t size = sampleBufferLen>CHUNK_SIZE-chunkLen ? + CHUNK_SIZE-chunkLen: + sampleBufferLen; + while(cb->begin==cb->end && cb->wrap && + !dc->stop && !dc->seek) + { + usleep(10000); + } + if(dc->stop) { + eof = 1; + break; + } + else if(!dc->seek) { + sampleBufferLen-=size; + memcpy(cb->chunks+cb->end*CHUNK_SIZE+chunkLen, + sampleBuffer,size); + cb->times[cb->end] = time; + cb->bitRate[cb->end] = bitRate; + sampleBuffer+=size; + chunkLen+=size; + if(chunkLen>=CHUNK_SIZE) { + cb->chunkSize[cb->end] = CHUNK_SIZE; + ++cb->end; + + if(cb->end>=buffered_chunks) { + cb->end = 0; + cb->wrap = 1; + } + chunkLen = 0; + } + } + } + } + + if(!dc->stop && !dc->seek && chunkLen>0) { + cb->chunkSize[cb->end] = chunkLen; + ++cb->end; + + if(cb->end>=buffered_chunks) { + cb->end = 0; + cb->wrap = 1; + } + chunkLen = 0; + } + + free(seekTable); + faacDecClose(decoder); + mp4ff_close(mp4fh); + fclose(fh); + free(mp4cb); + + if(dc->seek) 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 */ diff --git a/src/aac_decode.h b/src/aac_decode.h new file mode 100644 index 000000000..ad0d75d75 --- /dev/null +++ b/src/aac_decode.h @@ -0,0 +1,36 @@ +/* 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 + * + * libaudiofile (wave) support added by Eric Wong <normalperson@yhbt.net> + * + * 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(Buffer * cb, AudioFormat * af, DecoderControl * dc); + +#endif /* HAVE_FAAD */ + +#endif diff --git a/src/directory.c b/src/directory.c index 673754044..2d672afce 100644 --- a/src/directory.c +++ b/src/directory.c @@ -548,7 +548,8 @@ int readDirectoryDB() { else if(0==strncmp(DIRECTORY_FS_CHARSET,buffer, strlen(DIRECTORY_FS_CHARSET))) { - char * fsCharset; + char * fsCharset; + char * tempCharset; if(foundFsCharset) { ERROR("already found " @@ -560,15 +561,14 @@ int readDirectoryDB() { fsCharset = &(buffer[strlen( DIRECTORY_FS_CHARSET)]); - if(getConf()[CONF_FS_CHARSET] && - strcmp(fsCharset, - getFsCharset())) + if((tempCharset = + getConf()[CONF_FS_CHARSET]) && + strcmp(fsCharset,tempCharset)) { ERROR("Using \"%s\" for the " "filesystem charset " "instead of \"%s\"\n", - fsCharset, - getFsCharset()); + fsCharset,tempCharset); ERROR("maybe you need to " "recreate the db?\n"); setFsCharset(fsCharset); diff --git a/src/main.c b/src/main.c index 20bb06cbe..6fbb14d0b 100644 --- a/src/main.c +++ b/src/main.c @@ -69,12 +69,12 @@ void usage(char * argv[]) { SYSTEM_CONFIG_FILE_LOCATION); ERROR("\n"); ERROR("options:\n"); - ERROR(" --help this usage statement\n"); - ERROR(" --no-daemon don't detach from console\n"); - ERROR(" --create-db force (re)creation database\n"); - ERROR(" --no-create-db don't create database\n"); - ERROR(" --verbose verbose logging\n"); - ERROR(" --version prints version information\n"); + ERROR(" --help this usage statement\n"); + ERROR(" --no-daemon don't detach from console\n"); + ERROR(" --create-db force (re)creation database\n"); + ERROR(" --no-create-db don't create database\n"); + ERROR(" --verbose verbose logging\n"); + ERROR(" --version prints version information\n"); } void version() { diff --git a/src/mp4_decode.h b/src/mp4_decode.h index 14d0e495c..58d40aeff 100644 --- a/src/mp4_decode.h +++ b/src/mp4_decode.h @@ -19,7 +19,7 @@ */ #ifndef MP4_DECODE_H -#define MP$_DECODE_H +#define MP4_DECODE_H #include "../config.h" diff --git a/src/path.c b/src/path.c index 5a73baa86..e209b671d 100644 --- a/src/path.c +++ b/src/path.c @@ -87,40 +87,52 @@ char * getFsCharset() { } void initPaths() { -#ifdef HAVE_LOCALE -#ifdef HAVE_LANGINFO - char * originalLocale; -#endif -#endif char * charset = NULL; + char * originalLocale; if(getConf()[CONF_FS_CHARSET]) { charset = strdup(getConf()[CONF_FS_CHARSET]); } #ifdef HAVE_LOCALE #ifdef HAVE_LANGINFO - else if((originalLocale = setlocale(LC_CTYPE,""))) { + else if((originalLocale = setlocale(LC_CTYPE,NULL))) { char * temp; + char * currentLocale; + originalLocale = strdup(originalLocale); - if((temp = nl_langinfo(CODESET))) { - charset = strdup(temp); + if(!(currentLocale = setlocale(LC_CTYPE,""))) { + ERROR("problems setting current locale with " + "setlocale()\n"); } - else ERROR("problems getting charset for locale\n"); - if(!setlocale(LC_CTYPE,originalLocale)) { - ERROR("problems resetting locale with setlocale()\n"); + else { + if(strcmp(currentLocale,"C")==0 || + strcmp(currentLocale,"POSIX")==0) + { + ERROR("current locale is \"%s\"\n", + currentLocale); + } + else if((temp = nl_langinfo(CODESET))) { + charset = strdup(temp); + } + else ERROR("problems getting charset for locale\n"); + if(!setlocale(LC_CTYPE,originalLocale)) { + ERROR("problems resetting locale with setlocale()\n"); + } } + + free(originalLocale); } + else ERROR("problems getting locale with setlocale()\n"); #endif #endif - else ERROR("problems getting locale with setlocale()\n"); if(charset) { setFsCharset(charset); free(charset); } else { - ERROR("setting filesystem charset to UTF-8\n"); - setFsCharset("UTF-8"); + ERROR("setting filesystem charset to ISO-8859-1\n"); + setFsCharset("ISO-8859-1"); } } @@ -23,6 +23,7 @@ #include "mp3_decode.h" #include "audiofile_decode.h" #include "mp4_decode.h" +#include "aac_decode.h" #include "utils.h" #include <sys/stat.h> @@ -46,7 +47,6 @@ #endif #endif #ifdef HAVE_FAAD -#include <faad.h> #include "mp4ff/mp4ff.h" #endif @@ -173,177 +173,21 @@ MpdTag * mp3TagDup(char * utf8file) { #endif #ifdef HAVE_FAAD -typedef struct { - long bytesIntoBuffer; - long bytesConsumed; - long fileOffset; - unsigned char *buffer; - int atEof; - FILE *infile; -} 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 = fread((void *)(b->buffer+b->bytesIntoBuffer),1, - b->bytesConsumed,b->infile); - 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; -} - -#define AAC_MAX_CHANNELS 6 - MpdTag * aacTagDup(char * utf8file) { MpdTag * ret = NULL; - AacBuffer b; - size_t fileread; - size_t bread; - size_t tagsize; - float length = -1; - - memset(&b,0,sizeof(AacBuffer)); + int time; blockSignals(); - b.infile = fopen(rmp2amp(utf8ToFsCharset(utf8file)),"r"); - if(b.infile == NULL) return NULL; - - fseek(b.infile,0,SEEK_END); - fileread = ftell(b.infile); - fseek(b.infile,0,SEEK_SET); - - b.buffer = malloc(FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); - memset(b.buffer,0,FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS); - - bread = fread(b.buffer,1,FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS,b.infile); - b.bytesIntoBuffer = bread; - b.bytesConsumed = 0; - b.fileOffset = 0; - - if(bread!=FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS) b.atEof = 1; + time = getAacTotalTime(rmp2amp(utf8ToFsCharset(utf8file))); - 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((b.buffer[0] == 0xFF) && ((b.buffer[1] & 0xF6) == 0xF0)) { - adtsParse(&b,&length); - fseek(b.infile,tagsize, SEEK_SET); - - bread = fread(b.buffer,1,FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS, - b.infile); - 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) length = length*8.0/bitRate; - } - - if(b.buffer) free(b.buffer); - fclose(b.infile); - - if(length>=0) { + if(time>=0) { if((ret = id3Dup(utf8file))==NULL) ret = newMpdTag(); - ret->time = length+0.5; + ret->time = time; } + unblockSignals(); + return ret; } |