aboutsummaryrefslogtreecommitdiff
path: root/video/qt_decoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'video/qt_decoder.cpp')
-rw-r--r--video/qt_decoder.cpp215
1 files changed, 16 insertions, 199 deletions
diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp
index c25b76a5f2..71f31d6415 100644
--- a/video/qt_decoder.cpp
+++ b/video/qt_decoder.cpp
@@ -38,11 +38,6 @@
#include "common/memstream.h"
#include "common/util.h"
-// Audio codecs
-#include "audio/decoders/adpcm.h"
-#include "audio/decoders/raw.h"
-#include "video/codecs/qdm2.h"
-
// Video codecs
#include "video/codecs/cinepak.h"
#include "video/codecs/mjpeg.h"
@@ -58,7 +53,6 @@ namespace Video {
////////////////////////////////////////////
QuickTimeDecoder::QuickTimeDecoder() {
- _audStream = NULL;
_curFrame = -1;
_startTime = _nextFrameStartTime = 0;
_audHandle = Audio::SoundHandle();
@@ -175,7 +169,7 @@ void QuickTimeDecoder::seekToFrame(uint32 frame) {
_audioStartOffset = curVideoTime;
// Re-create the audio stream
- AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
+ Audio::QuickTimeAudioDecoder::AudioSampleDesc *entry = (Audio::QuickTimeAudioDecoder::AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
_audStream = Audio::makeQueuingAudioStream(entry->sampleRate, entry->channels == 2);
// First, we need to track down what audio sample we need
@@ -216,7 +210,7 @@ void QuickTimeDecoder::seekToFrame(uint32 frame) {
}
// Reposition the audio stream
- readNextAudioChunk();
+ queueNextAudioChunk();
if (sample != totalSamples) {
// HACK: Skip a certain amount of samples from the stream
// (There's got to be a better way to do this!)
@@ -232,7 +226,7 @@ void QuickTimeDecoder::seekToFrame(uint32 frame) {
}
void QuickTimeDecoder::seekToTime(Audio::Timestamp time) {
- // TODO: Audio-only seeking (or really, have QuickTime sounds)
+ // Use makeQuickTimeStream() instead
if (_videoStreamIndex < 0)
error("Audio-only seeking not supported");
@@ -404,10 +398,7 @@ bool QuickTimeDecoder::loadFile(const Common::String &filename) {
if (!Common::QuickTimeParser::loadFile(filename))
return false;
- _videoStreamIndex = _audioStreamIndex = -1;
- _startTime = 0;
init();
-
return true;
}
@@ -415,39 +406,24 @@ bool QuickTimeDecoder::loadStream(Common::SeekableReadStream *stream) {
if (!Common::QuickTimeParser::loadStream(stream))
return false;
- _videoStreamIndex = _audioStreamIndex = -1;
- _startTime = 0;
init();
-
return true;
}
void QuickTimeDecoder::init() {
- Common::QuickTimeParser::init();
+ Audio::QuickTimeAudioDecoder::init();
+
+ _videoStreamIndex = -1;
+ _startTime = 0;
- // Find audio/video streams
- for (uint32 i = 0; i < _numStreams; i++) {
+ // Find video streams
+ for (uint32 i = 0; i < _numStreams; i++)
if (_streams[i]->codec_type == CODEC_TYPE_VIDEO && _videoStreamIndex < 0)
_videoStreamIndex = i;
- else if (_streams[i]->codec_type == CODEC_TYPE_AUDIO && _audioStreamIndex < 0)
- _audioStreamIndex = i;
- }
-
- // Initialize audio, if present
- if (_audioStreamIndex >= 0) {
- AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
-
- if (checkAudioCodecSupport(entry->codecTag)) {
- _audStream = Audio::makeQueuingAudioStream(entry->sampleRate, entry->channels == 2);
- _curAudioChunk = 0;
-
- // Make sure the bits per sample transfers to the sample size
- if (entry->codecTag == MKID_BE('raw ') || entry->codecTag == MKID_BE('twos'))
- _streams[_audioStreamIndex]->sample_size = (entry->bitsPerSample / 8) * entry->channels;
-
- startAudio();
- }
+ // Start the audio codec if we've got one that we can handle
+ if (_audStream) {
+ startAudio();
_audioStartOffset = Audio::Timestamp(0);
}
@@ -559,56 +535,10 @@ Common::QuickTimeParser::SampleDesc *QuickTimeDecoder::readSampleDesc(MOVStreamC
}
return entry;
- } else if (st->codec_type == CODEC_TYPE_AUDIO) {
- debug(0, "Audio Codec FourCC: \'%s\'", tag2str(format));
-
- AudioSampleDesc *entry = new AudioSampleDesc();
- entry->codecTag = format;
-
- uint16 stsdVersion = _fd->readUint16BE();
- _fd->readUint16BE(); // revision level
- _fd->readUint32BE(); // vendor
-
- entry->channels = _fd->readUint16BE(); // channel count
- entry->bitsPerSample = _fd->readUint16BE(); // sample size
-
- _fd->readUint16BE(); // compression id = 0
- _fd->readUint16BE(); // packet size = 0
-
- entry->sampleRate = (_fd->readUint32BE() >> 16);
-
- debug(0, "stsd version =%d", stsdVersion);
- if (stsdVersion == 0) {
- // Not used, except in special cases. See below.
- entry->samplesPerFrame = entry->bytesPerFrame = 0;
- } else if (stsdVersion == 1) {
- // Read QT version 1 fields. In version 0 these dont exist.
- entry->samplesPerFrame = _fd->readUint32BE();
- debug(0, "stsd samples_per_frame =%d",entry->samplesPerFrame);
- _fd->readUint32BE(); // bytes per packet
- entry->bytesPerFrame = _fd->readUint32BE();
- debug(0, "stsd bytes_per_frame =%d", entry->bytesPerFrame);
- _fd->readUint32BE(); // bytes per sample
- } else {
- warning("Unsupported QuickTime STSD audio version %d", stsdVersion);
- delete entry;
- return 0;
- }
-
- // Version 0 videos (such as the Riven ones) don't have this set,
- // but we need it later on. Add it in here.
- if (format == MKID_BE('ima4')) {
- entry->samplesPerFrame = 64;
- entry->bytesPerFrame = 34 * entry->channels;
- }
-
- if (entry->sampleRate == 0 && st->time_scale > 1)
- entry->sampleRate = st->time_scale;
-
- return entry;
}
- return 0;
+ // Pass it on up
+ return Audio::QuickTimeAudioDecoder::readSampleDesc(st, format);
}
void QuickTimeDecoder::close() {
@@ -681,112 +611,6 @@ Common::SeekableReadStream *QuickTimeDecoder::getNextFramePacket(uint32 &descId)
return _fd->readStream(_streams[_videoStreamIndex]->sample_sizes[getCurFrame()]);
}
-bool QuickTimeDecoder::checkAudioCodecSupport(uint32 tag) {
- // Check if the codec is a supported codec
- if (tag == MKID_BE('twos') || tag == MKID_BE('raw ') || tag == MKID_BE('ima4'))
- return true;
-
-#ifdef VIDEO_CODECS_QDM2_H
- if (tag == MKID_BE('QDM2'))
- return true;
-#endif
-
- if (tag == MKID_BE('mp4a'))
- warning("No MPEG-4 audio (AAC) support");
- else
- warning("Audio Codec Not Supported: \'%s\'", tag2str(tag));
-
- return false;
-}
-
-Audio::AudioStream *QuickTimeDecoder::createAudioStream(Common::SeekableReadStream *stream) {
- if (!stream || _audioStreamIndex < 0)
- return NULL;
-
- AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
-
- if (entry->codecTag == MKID_BE('twos') || entry->codecTag == MKID_BE('raw ')) {
- // Fortunately, most of the audio used in Myst videos is raw...
- uint16 flags = 0;
- if (entry->codecTag == MKID_BE('raw '))
- flags |= Audio::FLAG_UNSIGNED;
- if (entry->channels == 2)
- flags |= Audio::FLAG_STEREO;
- if (entry->bitsPerSample == 16)
- flags |= Audio::FLAG_16BITS;
- uint32 dataSize = stream->size();
- byte *data = (byte *)malloc(dataSize);
- stream->read(data, dataSize);
- delete stream;
- return Audio::makeRawStream(data, dataSize, entry->sampleRate, flags);
- } else if (entry->codecTag == MKID_BE('ima4')) {
- // Riven uses this codec (as do some Myst ME videos)
- return Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMApple, entry->sampleRate, entry->channels, 34);
-#ifdef VIDEO_CODECS_QDM2_H
- } else if (entry->codecTag == MKID_BE('QDM2')) {
- // Several Myst ME videos use this codec
- return makeQDM2Stream(stream, _streams[_audioStreamIndex]->extradata);
-#endif
- }
-
- error("Unsupported audio codec");
-
- return NULL;
-}
-
-uint32 QuickTimeDecoder::getAudioChunkSampleCount(uint chunk) {
- if (_audioStreamIndex < 0)
- return 0;
-
- uint32 sampleCount = 0;
-
- for (uint32 j = 0; j < _streams[_audioStreamIndex]->sample_to_chunk_sz; j++)
- if (chunk >= _streams[_audioStreamIndex]->sample_to_chunk[j].first)
- sampleCount = _streams[_audioStreamIndex]->sample_to_chunk[j].count;
-
- return sampleCount;
-}
-
-void QuickTimeDecoder::readNextAudioChunk() {
- AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
- Common::MemoryWriteStreamDynamic *wStream = new Common::MemoryWriteStreamDynamic();
-
- _fd->seek(_streams[_audioStreamIndex]->chunk_offsets[_curAudioChunk]);
-
- // First, we have to get the sample count
- uint32 sampleCount = getAudioChunkSampleCount(_curAudioChunk);
- assert(sampleCount);
-
- // Then calculate the right sizes
- while (sampleCount > 0) {
- uint32 samples = 0, size = 0;
-
- if (entry->samplesPerFrame >= 160) {
- samples = entry->samplesPerFrame;
- size = entry->bytesPerFrame;
- } else if (entry->samplesPerFrame > 1) {
- samples = MIN<uint32>((1024 / entry->samplesPerFrame) * entry->samplesPerFrame, sampleCount);
- size = (samples / entry->samplesPerFrame) * entry->bytesPerFrame;
- } else {
- samples = MIN<uint32>(1024, sampleCount);
- size = samples * _streams[_audioStreamIndex]->sample_size;
- }
-
- // Now, we read in the data for this data and output it
- byte *data = (byte *)malloc(size);
- _fd->read(data, size);
- wStream->write(data, size);
- free(data);
- sampleCount -= samples;
- }
-
- // Now queue the buffer
- _audStream->queueAudioStream(createAudioStream(new Common::MemoryReadStream(wStream->getData(), wStream->size(), DisposeAfterUse::YES)));
- delete wStream;
-
- _curAudioChunk++;
-}
-
void QuickTimeDecoder::updateAudioBuffer() {
if (!_audStream)
return;
@@ -797,7 +621,7 @@ void QuickTimeDecoder::updateAudioBuffer() {
// If we're on the last frame, make sure all audio remaining is buffered
numberOfChunksNeeded = _streams[_audioStreamIndex]->chunk_count;
} else {
- AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
+ Audio::QuickTimeAudioDecoder::AudioSampleDesc *entry = (Audio::QuickTimeAudioDecoder::AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
// Calculate the amount of chunks we need in memory until the next frame
uint32 timeToNextFrame = getTimeToNextFrame();
@@ -817,7 +641,7 @@ void QuickTimeDecoder::updateAudioBuffer() {
// Keep three streams in buffer so that if/when the first two end, it goes right into the next
while (_audStream->numQueuedStreams() < numberOfChunksNeeded && _curAudioChunk < _streams[_audioStreamIndex]->chunk_count)
- readNextAudioChunk();
+ queueNextAudioChunk();
}
QuickTimeDecoder::VideoSampleDesc::VideoSampleDesc() : Common::QuickTimeParser::SampleDesc() {
@@ -832,11 +656,4 @@ QuickTimeDecoder::VideoSampleDesc::~VideoSampleDesc() {
delete videoCodec;
}
-QuickTimeDecoder::AudioSampleDesc::AudioSampleDesc() : Common::QuickTimeParser::SampleDesc() {
- channels = 0;
- sampleRate = 0;
- samplesPerFrame = 0;
- bytesPerFrame = 0;
-}
-
} // End of namespace Video