ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

asf.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 // Based on xoreos' ASF code which is in turn
00024 // Largely based on the ASF implementation found in FFmpeg.
00025 
00026 #include "common/textconsole.h"
00027 #include "common/stream.h"
00028 #include "common/util.h"
00029 
00030 #include "audio/audiostream.h"
00031 #include "audio/decoders/asf.h"
00032 #include "audio/decoders/wma.h"
00033 #include "audio/decoders/wave_types.h"
00034 
00035 namespace Audio {
00036 
00037 class ASFGUID {
00038 public:
00039     ASFGUID(Common::SeekableReadStream &stream) {
00040         stream.read(id, 16);
00041     }
00042 
00043     ASFGUID(byte a0, byte a1, byte a2, byte a3, byte a4, byte a5, byte a6, byte a7, byte a8, byte a9, byte a10, byte a11, byte a12, byte a13, byte a14, byte a15) {
00044         id[0]  = a0;   id[1]  = a1;  id[2]  = a2;  id[3]  = a3;
00045         id[4]  = a4;   id[5]  = a5;  id[6]  = a6;  id[7]  = a7;
00046         id[8]  = a8;   id[9]  = a9;  id[10] = a10; id[11] = a11;
00047         id[12] = a12;  id[13] = a13; id[14] = a14; id[15] = a15;
00048     }
00049 
00050     bool operator==(const ASFGUID &g) const {
00051         return !memcmp(g.id, id, 16);
00052     }
00053 
00054     bool operator!=(const ASFGUID &g) const {
00055         return memcmp(g.id, id, 16);
00056     }
00057 
00058     Common::String toString() const {
00059         return Common::String::format("%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x",
00060                 id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11], id[12], id[13], id[14], id[15]);
00061     }
00062 
00063 private:
00064     byte id[16];
00065 };
00066 
00067 // GUID's that we need
00068 static const ASFGUID s_asfHeader         = ASFGUID(0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C);
00069 static const ASFGUID s_asfFileHeader     = ASFGUID(0xA1, 0xDC, 0xAB, 0x8C, 0x47, 0xA9, 0xCF, 0x11, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65);
00070 static const ASFGUID s_asfHead1          = ASFGUID(0xb5, 0x03, 0xbf, 0x5f, 0x2E, 0xA9, 0xCF, 0x11, 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65);
00071 static const ASFGUID s_asfComment        = ASFGUID(0x33, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c);
00072 static const ASFGUID s_asfStreamHeader   = ASFGUID(0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65);
00073 static const ASFGUID s_asfCodecComment   = ASFGUID(0x40, 0x52, 0xD1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6);
00074 static const ASFGUID s_asfDataHeader     = ASFGUID(0x36, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c);
00075 static const ASFGUID s_asfAudioStream    = ASFGUID(0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B);
00076 static const ASFGUID s_asfExtendedHeader = ASFGUID(0x40, 0xA4, 0xD0, 0xD2, 0x07, 0xE3, 0xD2, 0x11, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50);
00077 static const ASFGUID s_asfStreamBitRate  = ASFGUID(0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2);
00078 
00079 class ASFStream : public SeekableAudioStream {
00080 public:
00081     ASFStream(Common::SeekableReadStream *stream,
00082             DisposeAfterUse::Flag disposeAfterUse);
00083     ~ASFStream();
00084 
00085     int readBuffer(int16 *buffer, const int numSamples);
00086 
00087     bool endOfData() const;
00088     bool isStereo() const { return _channels == 2; }
00089     int getRate() const { return _sampleRate; }
00090     Timestamp getLength() const { return Audio::Timestamp(_duration / 10000, _sampleRate); }
00091     bool seek(const Timestamp &where);
00092     bool rewind();
00093 
00094 private:
00095     // Packet data
00096     struct Packet {
00097         Packet();
00098         ~Packet();
00099 
00100         byte flags;
00101         byte segmentType;
00102         uint16 packetSize;
00103         uint32 sendTime;
00104         uint16 duration;
00105 
00106         struct Segment {
00107             byte streamID;
00108             byte sequenceNumber;
00109             bool isKeyframe;
00110             Common::Array<Common::SeekableReadStream *> data;
00111         };
00112 
00113         Common::Array<Segment> segments;
00114     };
00115 
00116     Common::SeekableReadStream *_stream;
00117     DisposeAfterUse::Flag _disposeAfterUse;
00118 
00119     void parseStreamHeader();
00120     void parseFileHeader();
00121     Packet *readPacket();
00122     Codec *createCodec();
00123     AudioStream *createAudioStream();
00124 
00125     uint32 _rewindPos;
00126     uint64 _curPacket;
00127     Packet *_lastPacket;
00128     Codec *_codec;
00129     AudioStream *_curAudioStream;
00130     byte _curSequenceNumber;
00131 
00132     // Header object variables
00133     uint64 _packetCount;
00134     uint64 _duration;
00135     uint32 _minPacketSize, _maxPacketSize;
00136 
00137     // Stream object variables
00138     uint16 _streamID;
00139     uint16 _compression;
00140     uint16 _channels;
00141     int _sampleRate;
00142     uint32 _bitRate;
00143     uint16 _blockAlign;
00144     uint16 _bitsPerCodedSample;
00145     Common::SeekableReadStream *_extraData;
00146 };
00147 
00148 ASFStream::Packet::Packet() {
00149 }
00150 
00151 ASFStream::Packet::~Packet() {
00152     for (uint32 i = 0; i < segments.size(); i++)
00153         for (uint32 j = 0; j < segments[i].data.size(); j++)
00154                 delete segments[i].data[j];
00155 }
00156 
00157 ASFStream::ASFStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) : _stream(stream), _disposeAfterUse(disposeAfterUse) {
00158     _extraData = 0;
00159     _lastPacket = 0;
00160     _curPacket = 0;
00161     _codec = 0;
00162     _curAudioStream = 0;
00163     _curSequenceNumber = 1; // They always start at one
00164 
00165     ASFGUID guid = ASFGUID(*_stream);
00166     if (guid != s_asfHeader)
00167         error("ASFStream: Missing asf header");
00168 
00169     _stream->readUint64LE();
00170     _stream->readUint32LE();
00171     _stream->readByte();
00172     _stream->readByte();
00173 
00174     for (;;) {
00175         uint64 startPos = _stream->pos();
00176         guid = ASFGUID(*_stream);
00177         uint64 size = _stream->readUint64LE();
00178 
00179         if (_stream->eos())
00180             error("ASFStream: Unexpected eos");
00181 
00182         // TODO: Parse each chunk
00183         if (guid == s_asfFileHeader) {
00184             parseFileHeader();
00185         } else if (guid == s_asfHead1) {
00186             // Should be safe to ignore
00187         } else if (guid == s_asfComment) {
00188             // Ignored
00189         } else if (guid == s_asfStreamHeader) {
00190             parseStreamHeader();
00191         } else if (guid == s_asfCodecComment) {
00192             // TODO
00193         } else if (guid == s_asfDataHeader) {
00194             // Done parsing the header
00195             break;
00196         } else if (guid == s_asfExtendedHeader) {
00197             // TODO
00198         } else if (guid == s_asfStreamBitRate) {
00199             // Ignored
00200         } else
00201             warning("Found unknown ASF GUID: %s", guid.toString().c_str());
00202 
00203         _stream->seek(startPos + size);
00204     }
00205 
00206     // Skip to the beginning of the packets
00207     _stream->skip(26);
00208     _rewindPos = _stream->pos();
00209 }
00210 
00211 ASFStream::~ASFStream() {
00212     if (_disposeAfterUse)
00213         delete _stream;
00214 
00215     delete _lastPacket;
00216     delete _curAudioStream;
00217     delete _codec;
00218 }
00219 
00220 void ASFStream::parseFileHeader() {
00221     _stream->skip(16); // skip client GUID
00222     /* uint64 fileSize = */ _stream->readUint64LE();
00223     /* uint64 creationTime = */ _stream->readUint64LE();
00224     _packetCount = _stream->readUint64LE();
00225     /* uint64 endTimestamp = */ _stream->readUint64LE();
00226     _duration = _stream->readUint64LE();
00227     /* uint32 startTimestamp = */ _stream->readUint32LE();
00228     /* uint32 unknown = */ _stream->readUint32LE();
00229     /* uint32 flags = */ _stream->readUint32LE();
00230     _minPacketSize = _stream->readUint32LE();
00231     _maxPacketSize = _stream->readUint32LE();
00232     /* uint32 uncFrameSize = */ _stream->readUint32LE();
00233 
00234     // We only know how to support packets of one length
00235     if (_minPacketSize != _maxPacketSize)
00236         error("ASFStream::parseFileHeader(): Mismatched packet sizes: Min = %d, Max = %d", _minPacketSize, _maxPacketSize);
00237 }
00238 
00239 void ASFStream::parseStreamHeader() {
00240     ASFGUID guid = ASFGUID(*_stream);
00241 
00242     if (guid != s_asfAudioStream)
00243         error("ASFStream::parseStreamHeader(): Found non-audio stream");
00244 
00245     _stream->skip(16); // skip a guid
00246     _stream->readUint64LE(); // total size
00247     uint32 typeSpecificSize = _stream->readUint32LE();
00248     _stream->readUint32LE();
00249     _streamID = _stream->readUint16LE();
00250     _stream->readUint32LE();
00251 
00252     // Parse the wave header
00253     _compression = _stream->readUint16LE();
00254     _channels = _stream->readUint16LE();
00255     _sampleRate = _stream->readUint32LE();
00256     _bitRate = _stream->readUint32LE() * 8;
00257     _blockAlign = _stream->readUint16LE();
00258     _bitsPerCodedSample = (typeSpecificSize == 14) ? 8 : _stream->readUint16LE();
00259 
00260     if (typeSpecificSize >= 18) {
00261         uint32 cbSize = _stream->readUint16LE();
00262         cbSize = MIN<int>(cbSize, typeSpecificSize - 18);
00263         _extraData = _stream->readStream(cbSize);
00264     }
00265 
00266     _codec = createCodec();
00267 }
00268 
00269 bool ASFStream::seek(const Timestamp &where) {
00270     if (where == 0) {
00271         return rewind();
00272     }
00273 
00274     // Seeking is not supported
00275     return false;
00276 }
00277 
00278 bool ASFStream::rewind() {
00279     // Seek back to the start of the packets
00280     _stream->seek(_rewindPos);
00281 
00282     // Reset our packet counter
00283     _curPacket = 0;
00284     delete _lastPacket; _lastPacket = 0;
00285 
00286     // Delete a stream if we have one
00287     delete _curAudioStream; _curAudioStream = 0;
00288 
00289     // Reset this too
00290     _curSequenceNumber = 1;
00291 
00292     return true;
00293 }
00294 
00295 ASFStream::Packet *ASFStream::readPacket() {
00296     if (_curPacket == _packetCount)
00297         error("ASFStream::readPacket(): Reading too many packets");
00298 
00299     uint32 packetStartPos = _stream->pos();
00300 
00301     // Read a single ASF packet
00302     if (_stream->readByte() != 0x82)
00303         error("ASFStream::readPacket(): Missing packet header");
00304 
00305     if (_stream->readUint16LE() != 0)
00306         error("ASFStream::readPacket(): Unknown is not zero");
00307 
00308     Packet *packet = new Packet();
00309     packet->flags = _stream->readByte();
00310     packet->segmentType = _stream->readByte();
00311     packet->packetSize = (packet->flags & 0x40) ? _stream->readUint16LE() : 0;
00312 
00313     uint16 paddingSize = 0;
00314     if (packet->flags & 0x10)
00315         paddingSize = _stream->readUint16LE();
00316     else if (packet->flags & 0x08)
00317         paddingSize = _stream->readByte();
00318 
00319     packet->sendTime = _stream->readUint32LE();
00320     packet->duration = _stream->readUint16LE();
00321 
00322     byte segmentCount = (packet->flags & 0x01) ? _stream->readByte() : 1;
00323     packet->segments.resize(segmentCount & 0x3F);
00324 
00325     for (uint32 i = 0; i < packet->segments.size(); i++) {
00326         Packet::Segment &segment = packet->segments[i];
00327 
00328         segment.streamID = _stream->readByte();
00329         segment.sequenceNumber = _stream->readByte();
00330         segment.isKeyframe = (segment.streamID & 0x80) != 0;
00331         segment.streamID &= 0x7F;
00332 
00333         uint32 fragmentOffset = 0;
00334         if (packet->segmentType == 0x55)
00335             fragmentOffset = _stream->readByte();
00336         else if (packet->segmentType == 0x59)
00337             fragmentOffset = _stream->readUint16LE();
00338         else if (packet->segmentType == 0x5D)
00339             fragmentOffset = _stream->readUint32LE();
00340         else
00341             error("ASFStream::readPacket(): Unknown packet segment type 0x%02x", packet->segmentType);
00342 
00343         byte flags = _stream->readByte();
00344         if (flags == 1) {
00345             //uint32 objectStartTime = fragmentOffset; // reused purpose
00346             _stream->readByte(); // unknown
00347 
00348             uint32 dataLength = (packet->segments.size() == 1) ? (_maxPacketSize - (_stream->pos() - packetStartPos) - paddingSize) : _stream->readUint16LE();
00349             uint32 startObjectPos = _stream->pos();
00350 
00351             while ((uint32)_stream->pos() < dataLength + startObjectPos)
00352                 segment.data.push_back(_stream->readStream(_stream->readByte()));
00353         } else if (flags == 8) {
00354             /* uint32 objectLength = */ _stream->readUint32LE();
00355             /* uint32 objectStartTime = */ _stream->readUint32LE();
00356 
00357             uint32 dataLength = 0;
00358             if (packet->segments.size() == 1)
00359                 dataLength = _maxPacketSize - (_stream->pos() - packetStartPos) - fragmentOffset - paddingSize;
00360             else if (segmentCount & 0x40)
00361                 dataLength = _stream->readByte();
00362             else
00363                 dataLength = _stream->readUint16LE();
00364 
00365             _stream->skip(fragmentOffset);
00366             segment.data.push_back(_stream->readStream(dataLength));
00367         } else
00368             error("ASFStream::readPacket(): Unknown packet flags 0x%02x", flags);
00369     }
00370 
00371     // Skip any padding
00372     _stream->skip(paddingSize);
00373 
00374     // We just read a packet
00375     _curPacket++;
00376 
00377     if ((uint32)_stream->pos() != packetStartPos + _maxPacketSize)
00378         error("ASFStream::readPacket(): Mismatching packet pos: %d (should be %d)", _stream->pos(), _maxPacketSize + packetStartPos);
00379 
00380     return packet;
00381 }
00382 
00383 Codec *ASFStream::createCodec() {
00384     switch (_compression) {
00385     case kWaveWMAv2:
00386         return new WMACodec(2, _sampleRate, _channels, _bitRate, _blockAlign, _extraData);
00387     default:
00388         error("ASFStream::createAudioStream(): Unknown compression 0x%04x", _compression);
00389     }
00390 
00391     return 0;
00392 }
00393 
00394 AudioStream *ASFStream::createAudioStream() {
00395     delete _lastPacket;
00396     _lastPacket = readPacket();
00397 
00398     // TODO
00399     if (_lastPacket->segments.size() != 1)
00400         error("ASFStream::createAudioStream(): Only single segment packets supported");
00401 
00402     Packet::Segment &segment = _lastPacket->segments[0];
00403 
00404     // We should only have one stream in a ASF audio file
00405     if (segment.streamID != _streamID)
00406         error("ASFStream::createAudioStream(): Packet stream ID mismatch");
00407 
00408     // TODO
00409     if (segment.sequenceNumber != _curSequenceNumber)
00410         error("ASFStream::createAudioStream(): Only one sequence number per packet supported");
00411 
00412     // This can overflow and needs to overflow!
00413     _curSequenceNumber++;
00414 
00415     // TODO
00416     if (segment.data.size() != 1)
00417         error("ASFStream::createAudioStream(): Packet grouping not supported");
00418 
00419     Common::SeekableReadStream *stream = segment.data[0];
00420     if (_codec)
00421         return _codec->decodeFrame(*stream);
00422 
00423     return 0;
00424 }
00425 
00426 int ASFStream::readBuffer(int16 *buffer, const int numSamples) {
00427     int samplesDecoded = 0;
00428 
00429     for (;;) {
00430         if (_curAudioStream) {
00431             samplesDecoded += _curAudioStream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded);
00432 
00433             if (_curAudioStream->endOfData()) {
00434                 delete _curAudioStream;
00435                 _curAudioStream = 0;
00436             }
00437         }
00438 
00439         if (samplesDecoded == numSamples || endOfData())
00440             break;
00441 
00442         if (!_curAudioStream) {
00443             _curAudioStream = createAudioStream();
00444         }
00445 
00446     }
00447 
00448     return samplesDecoded;
00449 }
00450 
00451 bool ASFStream::endOfData() const {
00452     return _curPacket == _packetCount && !_curAudioStream;
00453 }
00454 
00455 SeekableAudioStream *makeASFStream(
00456     Common::SeekableReadStream *stream,
00457     DisposeAfterUse::Flag disposeAfterUse) {
00458     SeekableAudioStream *s = new ASFStream(stream, disposeAfterUse);
00459 
00460     if (s && s->endOfData()) {
00461         delete s;
00462         return 0;
00463     }
00464 
00465     return s;
00466 }
00467 
00468 } // End of namespace Audio


Generated on Sat May 18 2019 05:00:55 for ResidualVM by doxygen 1.7.1
curved edge   curved edge