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;