aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--audio/decoders/quicktime.cpp19
-rw-r--r--audio/decoders/quicktime.h2
-rw-r--r--common/quicktime.cpp67
-rw-r--r--common/quicktime.h3
4 files changed, 85 insertions, 6 deletions
diff --git a/audio/decoders/quicktime.cpp b/audio/decoders/quicktime.cpp
index 62a6f6e404..e18ba7c480 100644
--- a/audio/decoders/quicktime.cpp
+++ b/audio/decoders/quicktime.cpp
@@ -76,7 +76,7 @@ void QuickTimeAudioDecoder::init() {
if (_audioStreamIndex >= 0) {
AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
- if (checkAudioCodecSupport(entry->codecTag)) {
+ if (checkAudioCodecSupport(entry->codecTag, _streams[_audioStreamIndex]->objectTypeMP4)) {
_audStream = makeQueuingAudioStream(entry->sampleRate, entry->channels == 2);
_curAudioChunk = 0;
@@ -140,7 +140,7 @@ Common::QuickTimeParser::SampleDesc *QuickTimeAudioDecoder::readSampleDesc(MOVSt
return 0;
}
-bool QuickTimeAudioDecoder::checkAudioCodecSupport(uint32 tag) {
+bool QuickTimeAudioDecoder::checkAudioCodecSupport(uint32 tag, byte objectTypeMP4) {
// Check if the codec is a supported codec
if (tag == MKID_BE('twos') || tag == MKID_BE('raw ') || tag == MKID_BE('ima4'))
return true;
@@ -150,9 +150,18 @@ bool QuickTimeAudioDecoder::checkAudioCodecSupport(uint32 tag) {
return true;
#endif
- if (tag == MKID_BE('mp4a'))
- warning("No MPEG-4 audio (AAC) support");
- else
+ if (tag == MKID_BE('mp4a')) {
+ Common::String audioType;
+ switch (objectTypeMP4) {
+ case 0x40:
+ audioType = "AAC";
+ break;
+ default:
+ audioType = "Unknown";
+ break;
+ }
+ warning("No MPEG-4 audio (%s) support", audioType.c_str());
+ } else
warning("Audio Codec Not Supported: \'%s\'", tag2str(tag));
return false;
diff --git a/audio/decoders/quicktime.h b/audio/decoders/quicktime.h
index be4d1097da..6e9f5b2c4e 100644
--- a/audio/decoders/quicktime.h
+++ b/audio/decoders/quicktime.h
@@ -72,7 +72,7 @@ protected:
virtual Common::QuickTimeParser::SampleDesc *readSampleDesc(MOVStreamContext *st, uint32 format);
AudioStream *createAudioStream(Common::SeekableReadStream *stream);
- bool checkAudioCodecSupport(uint32 tag);
+ bool checkAudioCodecSupport(uint32 tag, byte objectTypeMP4);
void init();
void queueNextAudioChunk();
diff --git a/common/quicktime.cpp b/common/quicktime.cpp
index fe48cfdcb1..a28f8180cf 100644
--- a/common/quicktime.cpp
+++ b/common/quicktime.cpp
@@ -170,6 +170,7 @@ void QuickTimeParser::initParseTable() {
{ &QuickTimeParser::readLeaf, MKID_BE('vmhd') },
{ &QuickTimeParser::readCMOV, MKID_BE('cmov') },
{ &QuickTimeParser::readWAVE, MKID_BE('wave') },
+ { &QuickTimeParser::readESDS, MKID_BE('esds') },
{ 0, 0 }
};
@@ -721,6 +722,71 @@ int QuickTimeParser::readWAVE(MOVatom atom) {
return 0;
}
+enum {
+ kMP4IODescTag = 2,
+ kMP4ESDescTag = 3,
+ kMP4DecConfigDescTag = 4,
+ kMP4DecSpecificDescTag = 5
+};
+
+static int readMP4DescLength(Common::SeekableReadStream *stream) {
+ int length = 0;
+ int count = 4;
+
+ while (count--) {
+ byte c = stream->readByte();
+ length = (length << 7) | (c & 0x7f);
+
+ if (!(c & 0x80))
+ break;
+ }
+
+ return length;
+}
+
+static void readMP4Desc(Common::SeekableReadStream *stream, byte &tag, int &length) {
+ tag = stream->readByte();
+ length = readMP4DescLength(stream);
+}
+
+int QuickTimeParser::readESDS(MOVatom atom) {
+ if (_numStreams < 1)
+ return 0;
+
+ MOVStreamContext *st = _streams[_numStreams - 1];
+
+ _fd->readUint32BE(); // version + flags
+
+ byte tag;
+ int length;
+
+ readMP4Desc(_fd, tag, length);
+ _fd->readUint16BE(); // id
+ if (tag == kMP4ESDescTag)
+ _fd->readByte(); // priority
+
+ // Check if we've got the Config MPEG-4 header
+ readMP4Desc(_fd, tag, length);
+ if (tag != kMP4DecConfigDescTag)
+ return 0;
+
+ st->objectTypeMP4 = _fd->readByte();
+ _fd->readByte(); // stream type
+ _fd->readUint16BE(); _fd->readByte(); // buffer size
+ _fd->readUint32BE(); // max bitrate
+ _fd->readUint32BE(); // avg bitrate
+
+ // Check if we've got the Specific MPEG-4 header
+ readMP4Desc(_fd, tag, length);
+ if (tag != kMP4DecSpecificDescTag)
+ return 0;
+
+ st->extradata = _fd->readStream(length);
+
+ debug(0, "MPEG-4 object type = %02x", st->objectTypeMP4);
+ return 0;
+}
+
void QuickTimeParser::close() {
for (uint32 i = 0; i < _numStreams; i++)
delete _streams[i];
@@ -761,6 +827,7 @@ QuickTimeParser::MOVStreamContext::MOVStreamContext() {
nb_frames = 0;
duration = 0;
start_time = 0;
+ objectTypeMP4 = 0;
}
QuickTimeParser::MOVStreamContext::~MOVStreamContext() {
diff --git a/common/quicktime.h b/common/quicktime.h
index 42b48bbb94..8e6b0ec64c 100644
--- a/common/quicktime.h
+++ b/common/quicktime.h
@@ -163,6 +163,8 @@ protected:
uint32 start_time;
Common::Rational scaleFactorX;
Common::Rational scaleFactorY;
+
+ byte objectTypeMP4;
};
virtual SampleDesc *readSampleDesc(MOVStreamContext *st, uint32 format) = 0;
@@ -198,6 +200,7 @@ protected:
int readSTTS(MOVatom atom);
int readCMOV(MOVatom atom);
int readWAVE(MOVatom atom);
+ int readESDS(MOVatom atom);
};
} // End of namespace Common