shithub: aacdec

Download patch

ref: a00ace376fd9a64be5423268d00c3fcf2c9bb478
parent: 783631ddf502782473605d8a91be9eac70631d54
author: menno <menno>
date: Sun Apr 27 13:22:33 EDT 2003

seeking forward and file info for foobar 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.24 2003/04/27 12:16:15 menno Exp $
+** $Id: foo_mp4.cpp,v 1.25 2003/04/27 17:22:33 menno Exp $
 **/
 
 #include <mp4.h>
@@ -35,7 +35,7 @@
 }
 
 DECLARE_COMPONENT_VERSION ("MPEG-4 AAC decoder",
-                           STRIP_REVISION("$Revision: 1.24 $"),
+                           STRIP_REVISION("$Revision: 1.25 $"),
                            "Based on FAAD2 v" FAAD2_VERSION "\nCopyright (C) 2002-2003 http://www.audiocoding.com" );
 
 class input_mp4 : public input
@@ -55,6 +55,7 @@
         unsigned __int32 samplerate;
 
         faacDecConfigurationPtr config;
+        mp4AudioSpecificConfig mp4ASC;
 
         m_reader = r;
 
@@ -93,6 +94,8 @@
             return 0;
         }
 
+        AudioSpecificConfig((unsigned char*)buffer, buffer_size, &mp4ASC);
+
         int rc = faacDecInit2(hDecoder, (unsigned char*)buffer, buffer_size,
             (unsigned long*)&samplerate, (unsigned char*)&channels);
         if (buffer) free(buffer);
@@ -116,6 +119,13 @@
         info->info_set_int("channels", (__int64)channels);
         info->info_set_int("samplerate", (__int64)samplerate);
 
+#if 0
+        if (mp4ASC.sbr_present_flag)
+            info->info_set("codec", "AAC+SBR");
+        else
+#endif
+            info->info_set("codec", "AAC");
+
         ReadMP4Tag(info);
 
         return 1;
@@ -384,6 +394,8 @@
     {
         int tagsize = 0, tmp = 0;
         int bread = 0;
+        double length = 1.;
+        __int64 bitrate = 128;
         unsigned char channels = 0;
         unsigned long samplerate = 0;
 
@@ -414,8 +426,8 @@
         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;
+        m_aac_bytes_consumed = 0;
 
         if (bread != 768*6)
             m_at_eof = 1;
@@ -429,27 +441,72 @@
             tagsize += 10;
         }
 
+        if (tagsize)
+        {
+            advance_buffer(tagsize);
+            fill_buffer();
+        }
+
+        m_header_type = 0;
+        if ((m_aac_buffer[0] == 0xFF) && ((m_aac_buffer[1] & 0xF6) == 0xF0))
+        {
+            if (m_reader->can_seek())
+            {
+                adts_parse(&bitrate, &length);
+                m_reader->seek(tagsize);
+
+                bread = m_reader->read(m_aac_buffer, 768*6);
+                if (bread != 768*6)
+                    m_at_eof = 1;
+                else
+                    m_at_eof = 0;
+                m_aac_bytes_into_buffer = bread;
+                m_aac_bytes_consumed = 0;
+
+                m_header_type = 1;
+            }
+        } else if (memcmp(m_aac_buffer, "ADIF", 4) == 0) {
+            int skip_size = (m_aac_buffer[4] & 0x80) ? 9 : 0;
+            bitrate =  ((unsigned int)(m_aac_buffer[4 + skip_size] & 0x0F)<<19) |
+                ((unsigned int)m_aac_buffer[4 + skip_size]<<11) |
+                ((unsigned int)m_aac_buffer[4 + skip_size]<<3) |
+                ((unsigned int)m_aac_buffer[4 + skip_size] & 0xE0);
+
+            length = (double)m_reader->get_length();
+            if (length == -1.)
+                length = 1.;
+            else
+                length = (double)bitrate/((double)length*8.) + 0.5;
+
+            bitrate = (__int64)((double)bitrate/1000.0 + 0.5);
+
+            m_header_type = 2;
+        }
+
         if ((m_aac_bytes_consumed = faacDecInit(hDecoder,
-            m_aac_buffer+tagsize, m_aac_bytes_into_buffer,
+            m_aac_buffer, 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;
+        advance_buffer(m_aac_bytes_consumed);
 
-        info->set_length(0);
+        info->set_length(length);
 
-        info->info_set_int("bitrate", 0);
+        info->info_set_int("bitrate", bitrate);
         info->info_set_int("channels", (__int64)channels);
         info->info_set_int("samplerate", (__int64)samplerate);
 
+        m_samplerate = samplerate;
+
         return 1;
     }
 
     input_aac()
     {
+        cur_pos_sec = 0.0;
+        m_samplerate = 0;
         hDecoder = NULL;
         m_aac_buffer = NULL;
     }
@@ -464,7 +521,6 @@
 
     virtual int run(audio_chunk * chunk)
     {
-        int bread = 0;
         faacDecFrameInfo frameInfo;
         void *sample_buffer;
 
@@ -472,52 +528,14 @@
 
         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));
-                }
+            fill_buffer();
 
-                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;
-
-                if (m_aac_bytes_into_buffer > 3)
-                {
-                    if (memcmp(m_aac_buffer, "TAG", 3) == 0)
-                        m_aac_bytes_into_buffer = 0;
-                }
-                if (m_aac_bytes_into_buffer > 11)
-                {
-                    if (memcmp(m_aac_buffer, "LYRICSBEGIN", 11) == 0)
-                        m_aac_bytes_into_buffer = 0;
-                }
-                if (m_aac_bytes_into_buffer > 8)
-                {
-                    if (memcmp(m_aac_buffer, "APETAGEX", 8) == 0)
-                        m_aac_bytes_into_buffer = 0;
-                }
-            }
-
             if (m_aac_bytes_into_buffer != 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;
+                advance_buffer(frameInfo.bytesconsumed);
             } else {
                 break;
             }
@@ -534,22 +552,40 @@
             return 0;
         }
 
-        chunk->data = (audio_sample*)sample_buffer;
-        chunk->samples = frameInfo.samples/frameInfo.channels;
-        chunk->nch = frameInfo.channels;
-        chunk->srate = frameInfo.samplerate;
+        if (chunk)
+        {
+            chunk->data = (audio_sample*)sample_buffer;
+            chunk->samples = frameInfo.samples/frameInfo.channels;
+            chunk->nch = frameInfo.channels;
+            chunk->srate = frameInfo.samplerate;
+        }
+        m_samplerate = frameInfo.samplerate;
 
+        cur_pos_sec += 1024.0/(double)m_samplerate;
+
         return 1;
     }
 
     virtual int set_info(reader *r,const file_info * info)
     {
-        return 0;
+        return tag_writer::process_file(r, info);
     }
 
     virtual int seek(double seconds)
     {
-        return 0;
+        int i;
+        int frames = (int)((seconds - cur_pos_sec)*((double)m_samplerate/1024.0) + 0.5);
+
+        if (frames > 0)
+        {
+            for (i = 0; i < frames; i++)
+            {
+                if (!run(NULL))
+                    break;
+            }
+        }
+
+        return 1;
     }
     
     virtual int is_our_content_type(const char *url, const char *type)
@@ -563,11 +599,115 @@
 
     faacDecHandle hDecoder;
 
-    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;
+
+    unsigned long m_samplerate;
+    double cur_pos_sec;
+    int m_header_type;
+
+    int fill_buffer()
+    {
+        int bread;
+
+        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_into_buffer += bread;
+            }
+
+            m_aac_bytes_consumed = 0;
+
+            if (m_aac_bytes_into_buffer > 3)
+            {
+                if (memcmp(m_aac_buffer, "TAG", 3) == 0)
+                    m_aac_bytes_into_buffer = 0;
+            }
+            if (m_aac_bytes_into_buffer > 11)
+            {
+                if (memcmp(m_aac_buffer, "LYRICSBEGIN", 11) == 0)
+                    m_aac_bytes_into_buffer = 0;
+            }
+            if (m_aac_bytes_into_buffer > 8)
+            {
+                if (memcmp(m_aac_buffer, "APETAGEX", 8) == 0)
+                    m_aac_bytes_into_buffer = 0;
+            }
+        }
+
+        return 1;
+    }
+
+    int advance_buffer(int bytes)
+    {
+        m_aac_bytes_consumed = bytes;
+        m_aac_bytes_into_buffer -= bytes;
+    }
+
+    int adts_parse(__int64 *bitrate, double *length)
+    {
+        static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
+        int frames, frame_length;
+        int t_framelength = 0;
+        int samplerate;
+        double frames_per_sec, bytes_per_frame;
+
+        /* Read all frames to ensure correct time and bitrate */
+        for (frames = 0; /* */; frames++)
+        {
+            fill_buffer();
+
+            if (m_aac_bytes_into_buffer > 7)
+            {
+                /* check syncword */
+                if (!((m_aac_buffer[0] == 0xFF)&&((m_aac_buffer[1] & 0xF6) == 0xF0)))
+                    break;
+
+                if (frames == 0)
+                    samplerate = sample_rates[(m_aac_buffer[2]&0x3c)>>2];
+
+                frame_length = ((((unsigned int)m_aac_buffer[3] & 0x3)) << 11)
+                    | (((unsigned int)m_aac_buffer[4]) << 3) | (m_aac_buffer[5] >> 5);
+
+                t_framelength += frame_length;
+
+                if (frame_length > m_aac_bytes_into_buffer)
+                    break;
+
+                advance_buffer(frame_length);
+            } else {
+                break;
+            }
+        }
+
+        frames_per_sec = (double)samplerate/1024.0;
+        if (frames != 0)
+            bytes_per_frame = (double)t_framelength/(double)(frames*1000);
+        else
+            bytes_per_frame = 0;
+        *bitrate = (__int64)(8. * bytes_per_frame * frames_per_sec + 0.5);
+        if (frames_per_sec != 0)
+            *length = (double)frames/frames_per_sec;
+        else
+            *length = 1;
+
+        return 1;
+    }
 };
 
 static service_factory_t<input,input_mp4> foo_mp4;