77 #ifdef ENABLE_XVIDCORE 88 static char string[5];
89 string[0] = (tag >> 24) & 0xff;
90 string[1] = (tag >> 16) & 0xff;
91 string[2] = (tag >> 8) & 0xff;
92 string[3] = tag & 0xff;
98 _foundMOOV(false), _videoTrackIndex(-1) {
111 Atom atom = { 0, 0, 0xffffffff };
117 for (
size_t i = 0; i <
_tracks.size(); i++) {
125 for (
size_t i = 0; i <
_tracks.size(); i++) {
173 track->
width = width;
184 _fd->read(codecName, 32);
185 if (codecName[0] <= 31) {
186 std::memcpy(entry->_codecName, &codecName[1], codecName[0]);
187 entry->_codecName[codecName[0]] = 0;
190 entry->_bitsPerSample =
_fd->readUint16BE();
191 entry->_colorTableId =
_fd->readUint16BE();
194 byte colorDepth = entry->_bitsPerSample & 0x1F;
197 if (colorDepth == 2 || colorDepth == 4 || colorDepth == 8)
204 uint16 stsdVersion =
_fd->readUint16BE();
208 entry->_channels =
_fd->readUint16BE();
209 entry->_bitsPerSample =
_fd->readUint16BE();
214 entry->_sampleRate = (
_fd->readUint32BE() >> 16);
216 if (stsdVersion == 0) {
218 entry->_samplesPerFrame = entry->_bytesPerFrame = 0;
219 }
else if (stsdVersion == 1) {
221 entry->_samplesPerFrame =
_fd->readUint32BE();
223 entry->_bytesPerFrame =
_fd->readUint32BE();
226 warning(
"Unsupported QuickTime STSD audio version %d", stsdVersion);
232 if (format ==
MKTAG(
'i',
'm',
'a',
'4')) {
233 entry->_samplesPerFrame = 64;
234 entry->_bytesPerFrame = 34 * entry->_channels;
237 if (entry->_sampleRate == 0 && track->
timeScale > 1)
296 while (((total_size + 8) < atom.
size) && !
_fd->eos() &&
_fd->pos() <
_fd->size() && !err) {
300 if (atom.
size >= 8) {
314 warning(
"64 bit extended size is not supported in QuickTime");
338 size_t start_pos =
_fd->pos();
341 size_t left = a.
size -
_fd->pos() + start_pos;
348 total_size += a.
size;
351 if (!err && total_size < atom.
size)
352 _fd->seek(atom.
size - total_size);
374 byte version =
_fd->readByte();
375 _fd->readByte();
_fd->readByte();
_fd->readByte();
378 warning(
"QuickTime version 1");
379 _fd->readUint32BE();
_fd->readUint32BE();
380 _fd->readUint32BE();
_fd->readUint32BE();
409 _fd->readByte();
_fd->readByte();
_fd->readByte();
412 for (
uint32 i = 0; i < editCount; i++){
419 warning(
"Multiple edit list entries. Things may go awry");
428 _fd->readByte();
_fd->readByte();
_fd->readByte();
434 if (type ==
MKTAG(
'v',
'i',
'd',
'e'))
436 else if (type ==
MKTAG(
's',
'o',
'u',
'n'))
457 byte version =
_fd->readByte();
462 _fd->readByte();
_fd->readByte();
466 _fd->readUint32BE();
_fd->readUint32BE();
467 _fd->readUint32BE();
_fd->readUint32BE();
474 track->
duration = (version == 1) ? (
_fd->readUint32BE(),
_fd->readUint32BE()) :
_fd->readUint32BE();
486 _fd->readByte();
_fd->readByte();
_fd->readByte();
491 for (
uint32 i = 0; i < entryCount; i++) {
492 Atom a = { 0, 0, 0 };
493 size_t start_pos =
_fd->pos();
494 int size =
_fd->readUint32BE();
505 _fd->skip(size - (
_fd->pos() - start_pos));
509 a.
size = size - (
_fd->pos() - start_pos);
523 _fd->readByte();
_fd->readByte();
_fd->readByte();
546 _fd->readByte();
_fd->readByte();
_fd->readByte();
564 _fd->readByte();
_fd->readByte();
_fd->readByte();
585 uint32 totalSampleCount = 0;
588 _fd->readByte();
_fd->readByte();
_fd->readByte();
609 _fd->readByte();
_fd->readByte();
_fd->readByte();
636 length = (length << 7) | (c & 0x7f);
679 _fd->readUint16BE();
_fd->readByte();
700 sampleSize(0), sampleCount(0), keyframeCount(0), timeScale(0), width(0), height(0),
715 if (_codecTag ==
MKTAG(
't',
'w',
'o',
's') ||
716 _codecTag ==
MKTAG(
'r',
'a',
'w',
' ') ||
717 _codecTag ==
MKTAG(
'i',
'm',
'a',
'4'))
720 if (_codecTag ==
MKTAG(
'm',
'p',
'4',
'a')) {
723 switch (_objectTypeMP4) {
732 audioType =
"Unknown";
736 warning(
"No MPEG-4 audio (%s) support", audioType.
c_str());
745 case MKTAG(
't',
'w',
'o',
's'):
746 case MKTAG(
'r',
'a',
'w',
' '): {
748 if (_codecTag ==
MKTAG(
'r',
'a',
'w',
' '))
750 if (_bitsPerSample == 16)
754 case MKTAG(
'i',
'm',
'a',
'4'):
756 case MKTAG(
'm',
'p',
'4',
'a'):
757 switch (_objectTypeMP4) {
783 if (_codecTag ==
MKTAG(
'm',
'p',
'4',
'v')) {
787 switch (_objectTypeMP4) {
792 warning(
"Missing h.263 extra data; cannot decode");
796 #ifdef ENABLE_XVIDCORE 797 _videoCodec.reset(
makeH263Codec(_parentTrack->width, _parentTrack->height, *_extraData));
799 warning(
"H.263 decoding disabled when building without xvidcore");
804 videoType =
"Unknown";
809 warning(
"MPEG-4 Video (%s) not yet supported", videoType.
c_str());
811 }
else if (_codecTag ==
MKTAG(
'S',
'V',
'Q',
'3')) {
813 warning(
"Sorenson Video 3 not yet supported");
821 _parentTrack = parentTrack;
831 _stream.reset(static_cast<AudioSampleDesc *>(_parentTrack->sampleDescs[0])->createAudioStream());
832 _skipAACPrimer =
true;
843 _skipAACPrimer =
false;
847 _stream->queuePacket(stream.
release());
849 }
while (!allAudioQueued() &&
Common::Timestamp(0, _samplesQueued, getRate()) < length);
851 if (allAudioQueued())
856 return _parentTrack->timeToSampleCount == 1 && _parentTrack->timeToSample[0].duration == 1;
863 _decoder->_fd->seek(_parentTrack->chunkOffsets[chunk]);
866 uint32 sampleCount = getAudioChunkSampleCount(chunk);
867 assert(sampleCount != 0);
869 if (isOldDemuxing()) {
873 while (sampleCount > 0) {
874 uint32 samples = 0, size = 0;
883 samples = MIN<uint32>(1024, sampleCount);
884 size = samples * _parentTrack->sampleSize;
889 _decoder->_fd->read(data.
get(), size);
890 wStream->write(data.
get(), size);
891 sampleCount -= samples;
898 for (
uint32 i = 0; i < chunk; i++)
899 startSample += getAudioChunkSampleCount(i);
901 for (
uint32 i = 0; i < sampleCount; i++) {
902 uint32 size = (_parentTrack->sampleSize != 0) ? _parentTrack->sampleSize : _parentTrack->sampleSizes[i + startSample];
906 _decoder->_fd->read(data.get(), size);
907 wStream->write(data.get(), size);
917 for (
uint32 i = 0; i < _parentTrack->sampleToChunkCount; i++)
918 if (chunk >= _parentTrack->sampleToChunk[i].first)
919 sampleCount = _parentTrack->sampleToChunk[i].count;
925 uint32 chunkSampleCount = getAudioChunkSampleCount(chunk);
931 return Common::Timestamp(0, getAACSampleTime(chunkSampleCount, skipAACPrimer), getRate());
938 for (
int32 i = 0; i < _parentTrack->timeToSampleCount; i++) {
939 uint32 sampleCount = _parentTrack->timeToSample[i].count;
941 if (totalSampleCount < curSample + sampleCount) {
942 time += (totalSampleCount - curSample) * _parentTrack->timeToSample[i].duration;
946 time += _parentTrack->timeToSample[i].count * _parentTrack->timeToSample[i].duration;
947 curSample += sampleCount;
958 assert(_parentTrack->timeToSampleCount > 0);
959 time -= _parentTrack->timeToSample[0].duration;
973 return _parent->width;
977 return _parent->height;
981 return _parent->frameCount;
993 _nextFrameStartTime += getFrameDuration();
999 if (!frameData || !descId || descId > _parent->sampleDescs.size())
1007 entry.
_videoCodec->decodeFrame(surface, *frameData);
1013 int32 totalSampleCount = 0;
1014 int32 sampleInChunk = 0;
1015 int32 actualChunk = -1;
1016 uint32 sampleToChunkIndex = 0;
1018 for (
uint32 i = 0; i < _parent->chunkCount; i++) {
1019 if (sampleToChunkIndex < _parent->sampleToChunkCount && i >= _parent->sampleToChunk[sampleToChunkIndex].first)
1020 sampleToChunkIndex++;
1022 totalSampleCount += _parent->sampleToChunk[sampleToChunkIndex - 1].count;
1024 if (totalSampleCount > _curFrame) {
1026 descId = _parent->sampleToChunk[sampleToChunkIndex - 1].id;
1027 sampleInChunk = _parent->sampleToChunk[sampleToChunkIndex - 1].count - totalSampleCount + _curFrame;
1032 if (actualChunk < 0)
1033 error(
"Could not find data for frame %d", _curFrame);
1036 _decoder->_fd->seek(_parent->chunkOffsets[actualChunk]);
1039 for (
int32 i = _curFrame - sampleInChunk; i < _curFrame; i++) {
1040 if (_parent->sampleSize != 0)
1041 _decoder->_fd->skip(_parent->sampleSize);
1043 _decoder->_fd->skip(_parent->sampleSizes[i]);
1049 if (_parent->sampleSize != 0)
1050 return _decoder->_fd->readStream(_parent->sampleSize);
1052 return _decoder->_fd->readStream(_parent->sampleSizes[_curFrame]);
1056 uint32 curFrameIndex = 0;
1057 for (
int32 i = 0; i < _parent->timeToSampleCount; i++) {
1058 curFrameIndex += _parent->timeToSample[i].count;
1059 if ((
uint32)_curFrame < curFrameIndex) {
1061 return _parent->timeToSample[i].duration;
1071 : _decoder(decoder), _audioTrack(audioTrack) {
1075 _audioTrack->queueAudio(endTime);
1083 return !_audioTrack->endOfStream();
Common::ScopedPtr< Graphics::Surface > _surface
The video's surface.
PacketizedAudioStream * makePacketizedADPCMStream(ADPCMTypes type, int rate, int channels, uint32 blockAlign)
Creates a PacketizedAudioStream that will automatically queue packets as individual AudioStreams like...
QuickTimeTrack * _parentTrack
Common::ScopedArray< TimeToSampleEntry > timeToSample
#define MKTAG(a0, a1, a2, a3)
A wrapper macro used around four character constants, like 'DATA', to ensure portability.
void checkAudioBuffer(AudioTrack &track, const Common::Timestamp &endTime)
Ensure that there is enough audio buffered in the given track to reach the given timestamp.
AudioSampleDesc(QuickTimeTrack *parentTrack, uint32 codecTag)
int64 totalNumberOfFrames() const
Return the time in frames described by this timestamp.
PacketizedAudioStream * makePacketizedPCMStream(int rate, byte flags, int channels)
Creates a PacketizedAudioStream that will automatically queue packets as individual AudioStreams like...
An abstract representation of an audio track.
AudioTrackHandler(QuickTimeDecoder *decoder, QuickTimeAudioTrack *audioTrack)
A stream that dynamically grows as it's written to.
bool decodeNextFrame(Graphics::Surface &surface)
Common::Timestamp getChunkLength(uint chunk, bool skipAACPrimer=false) const
A class holding an UTF-8 string.
bool canBufferData() const
PacketizedAudioStream * makeAACStream(Common::SeekableReadStream &extraData)
Create a PacketizedAudioStream that decodes AAC sound.
VideoSampleDesc(QuickTimeTrack *parentTrack, uint32 codecTag)
void reset(PointerType o=0)
Resets the pointer with the new value.
PointerType release()
Returns the plain pointer value and releases ScopedPtr.
void addTrack(Track *track, bool isExternal=false)
Define a track to be used by this class.
bool _needCopy
Is new frame content available that needs to by copied?
Sound::PacketizedAudioStream * createAudioStream() const
Common::ScopedPtr< Common::SeekableReadStream > _fd
Common::ScopedArray< uint32 > chunkOffsets
void updateBuffer(const Common::Timestamp &endTime)
Implementing the reading stream interfaces for plain memory blocks.
Sound::AudioStream * getAudioStream() const
Common::ScopedArray< SampleToChunkEntry > sampleToChunk
Common::SeekableReadStream * readAudioChunk(uint chunk)
unsigned samples (default: signed)
Decoding PCM (Pulse Code Modulation).
uint32 getAACSampleTime(uint32 totalSampleCount, bool skipAACPrimer=false) const
static void readMP4Desc(Common::SeekableReadStream *stream, byte &tag, int &length)
SampleDesc(QuickTimeTrack *parentTrack, uint32 codecTag)
uint32 getHeight() const
Get the height of this track.
void initVideo()
Create a surface for video of these dimensions.
VideoTrackHandler(QuickTimeDecoder *decoder, QuickTimeTrack *parent)
uint32 getFrameDuration()
Basic exceptions to throw.
Decoding ADPCM (Adaptive Differential Pulse Code Modulation).
const char * c_str() const
Return the (utf8 encoded) string data.
static const char * tag2str(uint32 tag)
Common::PtrVector< SampleDesc > sampleDescs
QuickTimeDecoder(Common::SeekableReadStream *stream)
bool isAudioCodecSupported() const
Implementing the writing stream interfaces for memory blocks.
An AudioStream designed to work in terms of packets.
Common::Timestamp getDuration() const
Get the duration of the track.
void queueAudio(const Common::Timestamp &length=Common::Timestamp())
Common::ScopedPtr< Codec > _videoCodec
Simple memory based 'stream', which implements the ReadStream interface for a plain memory block...
uint32 getWidth() const
Get the width of this track.
An abstract representation of a video track.
A scoped plain pointer, allowing pointer-y access and normal deletion.
SampleDesc * readSampleDesc(QuickTimeTrack *track, uint32 format)
void warning(const char *s,...)
Common::ScopedArray< uint32 > sampleSizes
Common::ScopedArray< uint32 > keyframes
Common::Timestamp getNextFrameStartTime() const
Get the start time of the next frame since the start of the video.
uint32 getCodecTag() const
sound is 16 bits wide (default: 8bit)
Generic audio input stream.
PointerType get() const
Returns the plain pointer value.
QuickTimeAudioTrack(QuickTimeDecoder *decoder, QuickTimeTrack *parentTrack)
static int readMP4DescLength(Common::SeekableReadStream *stream)
bool isOldDemuxing() const
Decoding Apple QuickTime videos.
void decodeNextTrackFrame(VideoTrack &track)
Decode enough data for the next frame.
Common::PtrVector< QuickTimeTrack > _tracks
Common::ScopedPtr< Common::SeekableReadStream > _extraData
Decoder for QuickTime videos.
Low-level detection of architecture/system properties.
Timestamps allow specifying points in time and measuring time intervals with a sub-millisecond granul...
Codec * makeH263Codec(int width, int height, Common::SeekableReadStream &extraData)
Create a Codec capable of decoding h.263 frames.
int readDefault(Atom atom)
Common::PtrVector< QuickTimeAudioTrack > _audioTracks
void NORETURN_PRE error(const char *s,...)
uint32 getAudioChunkSampleCount(uint chunk) const
const ParseTable * _parseTable
Common::SeekableReadStream * getNextFramePacket(uint32 &descId)
int(QuickTimeDecoder::* func)(Atom atom)
Interface for a seekable & readable data stream.
uint32 sampleToChunkCount
byte readByte()
Read an unsigned byte from the stream and return it.
Codec * findDefaultVideoCodec() const
Timestamp convertToFramerate(uint64 newFramerate) const
Return a timestamp which represents as closely as possible the point in time describes by this timest...
int getFrameCount() const
Get the frame count of this track.