shithub: aacdec

Download patch

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)
     {