ref: 94641c20ec3a009c19c256d7a3f751bef7eca4dc
parent: 6dfb69251fda7c62b3313def17af3e1c4c3eff6d
author: menno <menno>
date: Sat Apr 26 06:02:42 EDT 2003
raw AAC support for foobar2000 plugin
--- a/plugins/foo_mp4/foo_mp4.cpp
+++ b/plugins/foo_mp4/foo_mp4.cpp
@@ -16,7 +16,7 @@
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
-** $Id: foo_mp4.cpp,v 1.17 2003/04/02 21:11:56 menno Exp $
+** $Id: foo_mp4.cpp,v 1.18 2003/04/26 10:02:42 menno Exp $
**/
#include <mp4.h>
@@ -34,8 +34,8 @@
}
DECLARE_COMPONENT_VERSION ("MPEG-4 AAC decoder",
- STRIP_REVISION("$Revision: 1.17 $"),
- "Based on FAAD2 v" FAAD2_VERSION "\nhttp://www.audiocoding.com\n""\n""Copyright (C) 2002-2003 M. Bakker" );
+ STRIP_REVISION("$Revision: 1.18 $"),
+ "Based on FAAD2 v" FAAD2_VERSION "\nCopyright (C) 2002-2003 http://www.audiocoding.com" );
class input_mp4 : public input
{
@@ -43,15 +43,19 @@
virtual int test_filename(const char * fn,const char * ext)
{
- return !stricmp(ext,"MP4");
+ int is_mp4 = !stricmp(ext,"MP4");
+ int is_aac = !stricmp(ext,"AAC");
+
+ if (is_aac)
+ m_stream_type = 1;
+ else if (is_mp4)
+ m_stream_type = 0;
+
+ return is_mp4 || is_aac;
}
virtual int open(reader *r, file_info *info, int full_open)
{
- unsigned __int8 *buffer;
- unsigned __int32 buffer_size;
- unsigned __int8 channels;
- unsigned __int32 samplerate;
faacDecConfigurationPtr config;
m_reader = r;
@@ -67,6 +71,105 @@
config->outputFormat = FAAD_FMT_DOUBLE;
faacDecSetConfiguration(hDecoder, config);
+ if (m_stream_type == 0)
+ return open_mp4(info, full_open);
+ else if (m_stream_type == 1)
+ return open_aac(info, full_open);
+ else
+ return 0;
+ }
+
+ input_mp4()
+ {
+ m_stream_type = -1;
+ hFile = MP4_INVALID_FILE_HANDLE;
+ hDecoder = NULL;
+ m_aac_buffer = NULL;
+ }
+
+ ~input_mp4()
+ {
+ if (hFile != MP4_INVALID_FILE_HANDLE)
+ MP4Close(hFile);
+ if (hDecoder)
+ faacDecClose(hDecoder);
+ if (m_aac_buffer)
+ free(m_aac_buffer);
+ }
+
+ virtual int run(audio_chunk * chunk)
+ {
+ if (m_stream_type == 0)
+ return decode_chunk_mp4(chunk);
+ else if (m_stream_type == 1)
+ return decode_chunk_aac(chunk);
+ else
+ return 0;
+ }
+
+ virtual int set_info(reader *r,const file_info * info)
+ {
+ m_reader = r;
+
+ if (m_stream_type == 0)
+ return set_info_mp4(info);
+// else if (m_stream_type == 1)
+// return set_info_aac(info);
+ else
+ return 0;
+ }
+
+ virtual int seek(double seconds)
+ {
+ if (m_stream_type == 0)
+ {
+ MP4Duration duration;
+
+ duration = MP4ConvertToTrackDuration(hFile,
+ track, seconds, MP4_SECS_TIME_SCALE);
+ sampleId = MP4GetSampleIdFromTime(hFile,
+ track, duration, 0);
+
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ virtual int is_our_content_type(const char *url, const char *type)
+ {
+ return !strcmp(type, "audio/mp4") || !strcmp(type, "audio/x-mp4") ||
+ !strcmp(type, "audio/aac") || !strcmp(type, "audio/x-aac");
+ }
+
+private:
+
+ reader *m_reader;
+ int m_stream_type;
+
+ faacDecHandle hDecoder;
+
+ /* MP4 file stuff */
+ MP4FileHandle hFile;
+ MP4SampleId sampleId, numSamples;
+ MP4TrackId track;
+ /* end MP4 file stuff */
+
+ /* AAC file stuff */
+ long m_aac_bytes_read;
+ long m_aac_bytes_into_buffer;
+ long m_aac_bytes_consumed;
+ unsigned char *m_aac_buffer;
+ int m_at_eof;
+ /* end AAC file stuff */
+
+ int open_mp4(file_info *info, int full_open)
+ {
+ unsigned __int8 *buffer;
+ unsigned __int32 buffer_size;
+ unsigned __int8 channels;
+ unsigned __int32 samplerate;
+
hFile = MP4ReadCb(0, open_cb, close_cb, read_cb, write_cb,
setpos_cb, getpos_cb, filesize_cb, (void*)m_reader);
if (hFile == MP4_INVALID_FILE_HANDLE)
@@ -119,21 +222,58 @@
return 1;
}
- input_mp4()
+ int open_aac(file_info *info, int full_open)
{
- hFile = MP4_INVALID_FILE_HANDLE;
- hDecoder = NULL;
- }
+ int tagsize = 0, tmp = 0;
+ int bread = 0;
+ unsigned char channels = 0;
+ unsigned long samplerate = 0;
- ~input_mp4()
- {
- if (hFile != MP4_INVALID_FILE_HANDLE)
- MP4Close(hFile);
- if (hDecoder)
- faacDecClose(hDecoder);
+ m_at_eof = 0;
+
+ if (!(m_aac_buffer = (unsigned char*)malloc(768*6)))
+ {
+ console::error("Memory allocation error.", "foo_mp4");
+ return 0;
+ }
+ memset(m_aac_buffer, 0, 768*6);
+
+ bread = m_reader->read(m_aac_buffer, 768*6);
+ m_aac_bytes_read = bread;
+ m_aac_bytes_into_buffer = bread;
+
+ if (bread != 768*6)
+ m_at_eof = 1;
+
+ if (!stricmp((const char*)m_aac_buffer, "ID3"))
+ {
+ /* high bit is not used */
+ tagsize = (m_aac_buffer[6] << 21) | (m_aac_buffer[7] << 14) |
+ (m_aac_buffer[8] << 7) | (m_aac_buffer[9] << 0);
+
+ tagsize += 10;
+ }
+
+ if ((m_aac_bytes_consumed = faacDecInit(hDecoder,
+ m_aac_buffer+tagsize, m_aac_bytes_into_buffer,
+ &samplerate, &channels)) < 0)
+ {
+ console::error("Can't initialize decoder library.", "foo_mp4");
+ return 0;
+ }
+ m_aac_bytes_consumed += tagsize;
+ m_aac_bytes_into_buffer -= m_aac_bytes_consumed;
+
+ info->set_length(0);
+
+ info->info_set_int("bitrate", 0);
+ info->info_set_int("channels", (__int64)channels);
+ info->info_set_int("samplerate", (__int64)samplerate);
+
+ return 1;
}
- virtual int run(audio_chunk * chunk)
+ int decode_chunk_mp4(audio_chunk * chunk)
{
faacDecFrameInfo frameInfo;
unsigned char *buffer;
@@ -176,10 +316,62 @@
return 1;
}
- virtual int set_info(reader *r,const file_info * info)
+ int decode_chunk_aac(audio_chunk * chunk)
{
- m_reader = r;
+ int bread = 0;
+ faacDecFrameInfo frameInfo;
+ void *sample_buffer;
+ do
+ {
+ if (m_aac_bytes_consumed > 0)
+ {
+ if (m_aac_bytes_into_buffer)
+ {
+ memmove((void*)m_aac_buffer, (void*)(m_aac_buffer + m_aac_bytes_consumed),
+ m_aac_bytes_into_buffer*sizeof(unsigned char));
+ }
+
+ if (!m_at_eof)
+ {
+ bread = m_reader->read((void*)(m_aac_buffer + m_aac_bytes_into_buffer),
+ m_aac_bytes_consumed);
+
+ if (bread != m_aac_bytes_consumed)
+ m_at_eof = 1;
+
+ m_aac_bytes_read += bread;
+ m_aac_bytes_into_buffer += bread;
+ }
+
+ m_aac_bytes_consumed = 0;
+ }
+
+ sample_buffer = faacDecDecode(hDecoder, &frameInfo,
+ m_aac_buffer, m_aac_bytes_into_buffer);
+
+ m_aac_bytes_consumed += frameInfo.bytesconsumed;
+ m_aac_bytes_into_buffer -= frameInfo.bytesconsumed;
+
+ } while (!frameInfo.samples && !frameInfo.error);
+
+ if (frameInfo.error || (m_aac_bytes_into_buffer == 0))
+ {
+ if (frameInfo.error)
+ console::error(faacDecGetErrorMessage(frameInfo.error), "foo_mp4");
+ return 0;
+ }
+
+ chunk->data = (audio_sample*)sample_buffer;
+ chunk->samples = frameInfo.samples/frameInfo.channels;
+ chunk->nch = frameInfo.channels;
+ chunk->srate = frameInfo.samplerate;
+
+ return 1;
+ }
+
+ int set_info_mp4(const file_info * info)
+ {
hFile = MP4ModifyCb(0, 0, open_cb, close_cb, read_cb, write_cb,
setpos_cb, getpos_cb, filesize_cb, (void*)m_reader);
if (hFile == MP4_INVALID_FILE_HANDLE) return 0;
@@ -227,33 +419,6 @@
/* end */
return 1;
}
-
- virtual int seek(double seconds)
- {
- MP4Duration duration;
-
- duration = MP4ConvertToTrackDuration(hFile,
- track, seconds, MP4_SECS_TIME_SCALE);
- sampleId = MP4GetSampleIdFromTime(hFile,
- track, duration, 0);
-
- return 1;
- }
-
- virtual int is_our_content_type(const char *url, const char *type)
- {
- return !strcmp(type, "audio/mp4") || !strcmp(type, "audio/x-mp4");
- }
-
-private:
-
- reader *m_reader;
-
- MP4FileHandle hFile;
- MP4SampleId sampleId, numSamples;
- MP4TrackId track;
-
- faacDecHandle hDecoder;
int ReadMP4Tag(file_info *info)
{