xoreos  0.0.5
asf.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 /* Based on the ASF implementation in FFmpeg (<https://ffmpeg.org/)>,
26  * which is released under the terms of version 2 or later of the GNU
27  * Lesser General Public License.
28  *
29  * The original copyright note in libavformat/asf.c reads as follows:
30  *
31  * Copyright (c) 2000, 2001 Fabrice Bellard
32  *
33  * This file is part of FFmpeg.
34  *
35  * FFmpeg is free software; you can redistribute it and/or
36  * modify it under the terms of the GNU Lesser General Public
37  * License as published by the Free Software Foundation; either
38  * version 2.1 of the License, or (at your option) any later version.
39  *
40  * FFmpeg is distributed in the hope that it will be useful,
41  * but WITHOUT ANY WARRANTY; without even the implied warranty of
42  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43  * Lesser General Public License for more details.
44  *
45  * You should have received a copy of the GNU Lesser General Public
46  * License along with FFmpeg; if not, write to the Free Software
47  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
48  */
49 
50 #include "src/common/scopedptr.h"
52 #include "src/common/util.h"
53 #include "src/common/error.h"
55 
56 #include "src/sound/audiostream.h"
57 
58 #include "src/sound/decoders/asf.h"
59 #include "src/sound/decoders/wma.h"
61 
62 namespace Sound {
63 
64 class ASFGUID {
65 public:
67  stream.read(id, 16);
68  }
69 
70  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) {
71  id[0] = a0; id[1] = a1; id[2] = a2; id[3] = a3;
72  id[4] = a4; id[5] = a5; id[6] = a6; id[7] = a7;
73  id[8] = a8; id[9] = a9; id[10] = a10; id[11] = a11;
74  id[12] = a12; id[13] = a13; id[14] = a14; id[15] = a15;
75  }
76 
77  bool operator==(const ASFGUID &g) const {
78  return !std::memcmp(g.id, id, 16);
79  }
80 
81  bool operator!=(const ASFGUID &g) const {
82  return std::memcmp(g.id, id, 16) != 0;
83  }
84 
86  return Common::UString::format("%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x",
87  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]);
88  }
89 
90 private:
91  byte id[16];
92 };
93 
94 // GUID's that we need
95 static const ASFGUID s_asfHeader = ASFGUID(0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C);
96 static const ASFGUID s_asfFileHeader = ASFGUID(0xA1, 0xDC, 0xAB, 0x8C, 0x47, 0xA9, 0xCF, 0x11, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65);
97 static const ASFGUID s_asfHead1 = ASFGUID(0xb5, 0x03, 0xbf, 0x5f, 0x2E, 0xA9, 0xCF, 0x11, 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65);
98 static const ASFGUID s_asfComment = ASFGUID(0x33, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c);
99 static const ASFGUID s_asfStreamHeader = ASFGUID(0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65);
100 static const ASFGUID s_asfCodecComment = ASFGUID(0x40, 0x52, 0xD1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6);
101 static const ASFGUID s_asfDataHeader = ASFGUID(0x36, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c);
102 static const ASFGUID s_asfAudioStream = ASFGUID(0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B);
103 static const ASFGUID s_asfExtendedHeader = ASFGUID(0x40, 0xA4, 0xD0, 0xD2, 0x07, 0xE3, 0xD2, 0x11, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50);
104 static const ASFGUID s_asfStreamBitRate = ASFGUID(0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2);
105 
107 public:
108  ASFStream(Common::SeekableReadStream *stream, bool dispose);
109  ~ASFStream();
110 
111  size_t readBuffer(int16 *buffer, const size_t numSamples);
112 
113  bool endOfData() const;
114  int getChannels() const { return _channels; }
115  int getRate() const { return _sampleRate; }
116  uint64 getLength() const;
117  uint64 getDuration() const;
118 
119  bool rewind();
120 
121 private:
122  // Packet data
123  struct Packet {
124  Packet();
125  ~Packet();
126 
132 
133  struct Segment {
137  std::vector<Common::SeekableReadStream *> data;
138  };
139 
140  std::vector<Segment> segments;
141  };
142 
144 
145  void load();
146 
147  void parseStreamHeader();
148  void parseFileHeader();
149  Packet *readPacket();
151  void feedAudioData();
152  bool allDataLoaded() const;
153 
154  size_t _rewindPos;
158 
159  // Header object variables
163 
164  // Stream object variables
173 };
174 
176 }
177 
179  for (size_t i = 0; i < segments.size(); i++)
180  for (size_t j = 0; j < segments[i].data.size(); j++)
181  delete segments[i].data[j];
182 }
183 
184 ASFStream::ASFStream(Common::SeekableReadStream *stream, bool dispose) : _stream(stream, dispose) {
185  _curPacket = 0;
186  _curSequenceNumber = 1; // They always start at one
187 
188  load();
189 }
190 
192 }
193 
195  ASFGUID guid = ASFGUID(*_stream);
196  if (guid != s_asfHeader)
197  throw Common::Exception("ASFStream: Missing asf header");
198 
199  _stream->readUint64LE();
200  _stream->readUint32LE();
201  _stream->readByte();
202  _stream->readByte();
203 
204  for (;;) {
205  size_t startPos = _stream->pos();
206  guid = ASFGUID(*_stream);
207  uint64 size = _stream->readUint64LE();
208 
209  if (_stream->eos())
210  throw Common::Exception("ASFStream: Unexpected eos");
211 
212  // TODO: Parse each chunk
213  if (guid == s_asfFileHeader) {
214  parseFileHeader();
215  } else if (guid == s_asfHead1) {
216  // Should be safe to ignore
217  } else if (guid == s_asfComment) {
218  // Ignored
219  } else if (guid == s_asfStreamHeader) {
221  } else if (guid == s_asfCodecComment) {
222  // TODO
223  } else if (guid == s_asfDataHeader) {
224  // Done parsing the header
225  break;
226  } else if (guid == s_asfExtendedHeader) {
227  // TODO
228  } else if (guid == s_asfStreamBitRate) {
229  // Ignored
230  } else
231  warning("Found unknown ASF GUID: %s", guid.toString().c_str());
232 
233  _stream->seek(startPos + size);
234  }
235 
236  // Skip to the beginning of the packets
237  _stream->skip(26);
238  _rewindPos = _stream->pos();
239 }
240 
242  _stream->skip(16); // skip client GUID
243  /* uint64 fileSize = */ _stream->readUint64LE();
244  /* uint64 creationTime = */ _stream->readUint64LE();
245  _packetCount = _stream->readUint64LE();
246  /* uint64 endTimestamp = */ _stream->readUint64LE();
247  _duration = _stream->readUint64LE();
248  /* uint32 startTimestamp = */ _stream->readUint32LE();
249  /* uint32 unknown = */ _stream->readUint32LE();
250  /* uint32 flags = */ _stream->readUint32LE();
251  _minPacketSize = _stream->readUint32LE();
252  _maxPacketSize = _stream->readUint32LE();
253  /* uint32 uncFrameSize = */ _stream->readUint32LE();
254 
255  // We only know how to support packets of one length
257  throw Common::Exception("ASFStream::parseFileHeader(): Mismatched packet sizes: Min = %d, Max = %d", _minPacketSize, _maxPacketSize);
258 
259  // If we have no packets, bail out
260  if (_packetCount == 0)
261  throw Common::Exception("ASFStream::parseFileHeader(): No packets");
262 }
263 
265  if (_curAudioStream)
266  throw Common::Exception("ASFStream::parseStreamHeader(): Multiple stream headers found");
267 
268  ASFGUID guid = ASFGUID(*_stream);
269 
270  if (guid != s_asfAudioStream)
271  throw Common::Exception("ASFStream::parseStreamHeader(): Found non-audio stream");
272 
273  _stream->skip(16); // skip a guid
274  _stream->readUint64LE(); // total size
275  uint32 typeSpecificSize = _stream->readUint32LE();
276  _stream->readUint32LE();
277  _streamID = _stream->readUint16LE();
278  _stream->readUint32LE();
279 
280  // Parse the wave header
281  _compression = _stream->readUint16LE();
282  _channels = _stream->readUint16LE();
283  _sampleRate = _stream->readUint32LE();
284  _bitRate = _stream->readUint32LE() * 8;
285  _blockAlign = _stream->readUint16LE();
286  _bitsPerCodedSample = (typeSpecificSize == 14) ? 8 : _stream->readUint16LE();
287 
288  if (typeSpecificSize >= 18) {
289  uint32 cbSize = _stream->readUint16LE();
290  cbSize = MIN<int>(cbSize, typeSpecificSize - 18);
291  _extraData.reset(_stream->readStream(cbSize));
292  }
293 
295 }
296 
298  return (_duration * getRate()) / 10000000;
299 }
300 
302  return _duration / 10000;
303 }
304 
306  // Seek back to the start of the packets
307  _stream->seek(_rewindPos);
308 
309  // Reset our packet counter
310  _curPacket = 0;
311 
312  // Reset our underlying stream
314 
315  // Reset this too
316  _curSequenceNumber = 1;
317 
318  return true;
319 }
320 
322  if (_curPacket == _packetCount)
323  throw Common::Exception("ASFStream::readPacket(): Reading too many packets");
324 
325  size_t packetStartPos = _stream->pos();
326 
327  // Read a single ASF packet
328  if (_stream->readByte() != 0x82)
329  throw Common::Exception("ASFStream::readPacket(): Missing packet header");
330 
331  if (_stream->readUint16LE() != 0)
332  throw Common::Exception("ASFStream::readPacket(): Unknown is not zero");
333 
334  Packet *packet = new Packet();
335  packet->flags = _stream->readByte();
336  packet->segmentType = _stream->readByte();
337  packet->packetSize = (packet->flags & 0x40) ? _stream->readUint16LE() : 0;
338 
339  uint16 paddingSize = 0;
340  if (packet->flags & 0x10)
341  paddingSize = _stream->readUint16LE();
342  else if (packet->flags & 0x08)
343  paddingSize = _stream->readByte();
344 
345  packet->sendTime = _stream->readUint32LE();
346  packet->duration = _stream->readUint16LE();
347 
348  byte segmentCount = (packet->flags & 0x01) ? _stream->readByte() : 1;
349  packet->segments.resize(segmentCount & 0x3F);
350 
351  for (uint32 i = 0; i < packet->segments.size(); i++) {
352  Packet::Segment &segment = packet->segments[i];
353 
354  segment.streamID = _stream->readByte();
355  segment.sequenceNumber = _stream->readByte();
356  segment.isKeyframe = (segment.streamID & 0x80) != 0;
357  segment.streamID &= 0x7F;
358 
359  uint32 fragmentOffset = 0;
360  if (packet->segmentType == 0x55)
361  fragmentOffset = _stream->readByte();
362  else if (packet->segmentType == 0x59)
363  fragmentOffset = _stream->readUint16LE();
364  else if (packet->segmentType == 0x5D)
365  fragmentOffset = _stream->readUint32LE();
366  else
367  throw Common::Exception("ASFStream::readPacket(): Unknown packet segment type 0x%02x", packet->segmentType);
368 
369  byte flags = _stream->readByte();
370  if (flags == 1) {
371  //uint32 objectStartTime = fragmentOffset; // reused purpose
372  _stream->readByte(); // unknown
373 
374  size_t dataLength = (packet->segments.size() == 1) ? (_maxPacketSize - (_stream->pos() - packetStartPos) - paddingSize) : _stream->readUint16LE();
375  size_t startObjectPos = _stream->pos();
376 
377  while (_stream->pos() < dataLength + startObjectPos)
378  segment.data.push_back(_stream->readStream(_stream->readByte()));
379  } else if (flags == 8) {
380  /* uint32 objectLength = */ _stream->readUint32LE();
381  /* uint32 objectStartTime = */ _stream->readUint32LE();
382 
383  size_t dataLength = 0;
384  if (packet->segments.size() == 1)
385  dataLength = _maxPacketSize - (_stream->pos() - packetStartPos) - fragmentOffset - paddingSize;
386  else if (segmentCount & 0x40)
387  dataLength = _stream->readByte();
388  else
389  dataLength = _stream->readUint16LE();
390 
391  _stream->skip(fragmentOffset);
392  segment.data.push_back(_stream->readStream(dataLength));
393  } else
394  throw Common::Exception("ASFStream::readPacket(): Unknown packet flags 0x%02x", flags);
395  }
396 
397  // Skip any padding
398  _stream->skip(paddingSize);
399 
400  // We just read a packet
401  _curPacket++;
402 
403  if (_stream->pos() != packetStartPos + _maxPacketSize)
404  throw Common::Exception("ASFStream::readPacket(): Mismatching packet pos: %u (should be %u)", (uint)_stream->pos(), (uint)(_maxPacketSize + packetStartPos));
405 
406  return packet;
407 }
408 
410  switch (_compression) {
411  case kWaveWMAv2:
413  default:
414  throw Common::Exception("ASFStream::createAudioStream(): Unknown compression 0x%04x", _compression);
415  }
416 
417  return 0;
418 }
419 
422 
423  // TODO
424  if (packet->segments.size() != 1)
425  throw Common::Exception("ASFStream::feedAudioData(): Only single segment packets supported");
426 
427  Packet::Segment &segment = packet->segments[0];
428 
429  // We should only have one stream in a ASF audio file
430  if (segment.streamID != _streamID)
431  throw Common::Exception("ASFStream::feedAudioData(): Packet stream ID mismatch");
432 
433  // TODO
434  if (segment.sequenceNumber != _curSequenceNumber)
435  throw Common::Exception("ASFStream::feedAudioData(): Only one sequence number per packet supported");
436 
437  // This can overflow and needs to overflow!
439 
440  // TODO
441  if (segment.data.size() != 1)
442  throw Common::Exception("ASFStream::feedAudioData(): Packet grouping not supported");
443 
444  _curAudioStream->queuePacket(segment.data[0]);
445 
446  // The PacketizedAudioStream has taken ownership of the pointer; reset it here
447  segment.data[0] = 0;
448 }
449 
450 size_t ASFStream::readBuffer(int16 *buffer, const size_t numSamples) {
451  size_t samplesDecoded = 0;
452 
453  while (true) {
454  // Read as much out of the stream as possible
455  const size_t n = _curAudioStream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded);
456  if (n == kSizeInvalid)
457  return kSizeInvalid;
458 
459  samplesDecoded += n;
460 
461  // If we have decoded up to what is requested or have no more data, bail
462  if (samplesDecoded == numSamples || allDataLoaded())
463  break;
464 
465  // If we have no data, feed the beast
466  if (_curAudioStream->endOfData())
467  feedAudioData();
468  }
469 
470  return samplesDecoded;
471 }
472 
474  return _curPacket == _packetCount;
475 }
476 
477 bool ASFStream::endOfData() const {
478  return allDataLoaded() && _curAudioStream->endOfData();
479 }
480 
482  return new ASFStream(stream, disposeAfterUse);
483 }
484 
485 } // End of namespace Sound
bool rewind()
Rewinds the stream to its start.
Definition: asf.cpp:305
static const ASFGUID s_asfStreamHeader
Definition: asf.cpp:99
ASFGUID(Common::SeekableReadStream &stream)
Definition: asf.cpp:66
uint64 _packetCount
Definition: asf.cpp:160
Common::DisposablePtr< Common::SeekableReadStream > _stream
Definition: asf.cpp:143
uint16 _streamID
Definition: asf.cpp:165
static const ASFGUID s_asfFileHeader
Definition: asf.cpp:96
void feedAudioData()
Definition: asf.cpp:420
A class holding an UTF-8 string.
Definition: ustring.h:48
uint64 getLength() const
Estimate the total number of samples per channel in this stream.
Definition: asf.cpp:297
void reset(PointerType o=0)
Resets the pointer with the new value.
Definition: scopedptr.h:87
void parseFileHeader()
Definition: asf.cpp:241
uint64_t uint64
Definition: types.h:206
std::vector< Segment > segments
Definition: asf.cpp:140
uint32 _minPacketSize
Definition: asf.cpp:162
Implementing the reading stream interfaces for plain memory blocks.
static const ASFGUID s_asfHeader
Definition: asf.cpp:95
int getRate() const
Sample rate of the stream.
Definition: asf.cpp:115
Compression types in Microsoft&#39;s WAVEFORMAT(EX).
RewindableAudioStream * makeASFStream(Common::SeekableReadStream *stream, bool disposeAfterUse)
Try to load a ASF from the given seekable stream and create a RewindableAudioStream from that data...
Definition: asf.cpp:481
size_t readBuffer(int16 *buffer, const size_t numSamples)
Fill the given buffer with up to numSamples samples.
Definition: asf.cpp:450
int16_t int16
Definition: types.h:201
uint32 _maxPacketSize
Definition: asf.cpp:162
int getChannels() const
Return the number channels in this stream.
Definition: asf.cpp:114
Exception that provides a stack of explanations.
Definition: error.h:36
A simple scoped smart pointer template.
Common::ScopedPtr< PacketizedAudioStream > _curAudioStream
Definition: asf.cpp:156
Definition: game.h:37
byte id[16]
Definition: asf.cpp:91
Basic exceptions to throw.
A rewindable audio stream.
Definition: audiostream.h:125
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
bool operator!=(const ASFGUID &g) const
Definition: asf.cpp:81
static UString format(const char *s,...) GCC_PRINTF(1
Print formatted data into an UString object, similar to sprintf().
Definition: ustring.cpp:718
ASFStream(Common::SeekableReadStream *stream, bool dispose)
Definition: asf.cpp:184
uint16_t uint16
Definition: types.h:202
Utility templates and functions.
size_t _rewindPos
Definition: asf.cpp:154
static const size_t kSizeInvalid
Definition: audiostream.h:72
An AudioStream designed to work in terms of packets.
Definition: audiostream.h:271
Common::UString toString() const
Definition: asf.cpp:85
virtual size_t read(void *dataPtr, size_t dataSize)=0
Read data from the stream.
uint32 _bitRate
Definition: asf.cpp:169
StackException Exception
Definition: error.h:59
A scoped plain pointer, allowing pointer-y access and normal deletion.
Definition: scopedptr.h:120
Common::ScopedPtr< Common::SeekableReadStream > _extraData
Definition: asf.cpp:172
void warning(const char *s,...)
Definition: util.cpp:33
static const ASFGUID s_asfHead1
Definition: asf.cpp:97
uint16 _channels
Definition: asf.cpp:167
static const ASFGUID s_asfCodecComment
Definition: asf.cpp:100
Decoding Microsoft&#39;s Windows Media Audio.
bool allDataLoaded() const
Definition: asf.cpp:473
bool operator==(const ASFGUID &g) const
Definition: asf.cpp:77
static const ASFGUID s_asfComment
Definition: asf.cpp:98
uint16 _blockAlign
Definition: asf.cpp:170
A smart pointer with a deletion flag.
uint16 _bitsPerCodedSample
Definition: asf.cpp:171
uint64 getDuration() const
Estimate the total duration of the stream in milliseconds.
Definition: asf.cpp:301
uint32_t uint32
Definition: types.h:204
std::vector< Common::SeekableReadStream * > data
Definition: asf.cpp:137
bool endOfData() const
End of data reached? If this returns true, it means that at this time there is no data available in t...
Definition: asf.cpp:477
uint64 _duration
Definition: asf.cpp:161
uint64 _curPacket
Definition: asf.cpp:155
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)
Definition: asf.cpp:70
uint16 _compression
Definition: asf.cpp:166
void load()
Definition: asf.cpp:194
Decoding Microsoft&#39;s Advanced Streaming Format.
PacketizedAudioStream * createAudioStream()
Definition: asf.cpp:409
static const ASFGUID s_asfAudioStream
Definition: asf.cpp:102
PacketizedAudioStream * makeWMAStream(int version, uint32 sampleRate, uint8 channels, uint32 bitRate, uint32 blockAlign, Common::SeekableReadStream &extraData)
Create a PacketizedAudioStream that decodes WMA sound.
Definition: wma.cpp:1726
void parseStreamHeader()
Definition: asf.cpp:264
static const ASFGUID s_asfStreamBitRate
Definition: asf.cpp:104
Interface for a seekable & readable data stream.
Definition: readstream.h:265
Streaming audio.
static const ASFGUID s_asfDataHeader
Definition: asf.cpp:101
byte _curSequenceNumber
Definition: asf.cpp:157
Packet * readPacket()
Definition: asf.cpp:321
uint8 byte
Definition: types.h:209
unsigned int uint
Definition: types.h:211
int _sampleRate
Definition: asf.cpp:168
static const ASFGUID s_asfExtendedHeader
Definition: asf.cpp:103