diff options
-rw-r--r-- | audio/decoders/quicktime.cpp | 19 | ||||
-rw-r--r-- | audio/decoders/quicktime.h | 2 | ||||
-rw-r--r-- | common/quicktime.cpp | 67 | ||||
-rw-r--r-- | common/quicktime.h | 3 |
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 |