diff options
-rw-r--r-- | audio/decoders/quicktime.cpp | 84 | ||||
-rw-r--r-- | audio/decoders/quicktime.h | 8 | ||||
-rw-r--r-- | video/qt_decoder.cpp | 66 |
3 files changed, 82 insertions, 76 deletions
diff --git a/audio/decoders/quicktime.cpp b/audio/decoders/quicktime.cpp index af59d8803f..53cce30125 100644 --- a/audio/decoders/quicktime.cpp +++ b/audio/decoders/quicktime.cpp @@ -43,6 +43,7 @@ QuickTimeAudioDecoder::QuickTimeAudioDecoder() : Common::QuickTimeParser() { } QuickTimeAudioDecoder::~QuickTimeAudioDecoder() { + delete _audStream; } bool QuickTimeAudioDecoder::loadFile(const Common::String &filename) { @@ -245,6 +246,64 @@ void QuickTimeAudioDecoder::queueNextAudioChunk() { _curAudioChunk++; } +void QuickTimeAudioDecoder::setAudioStreamPos(const Timestamp &where) { + if (!_audStream) + return; + + // Re-create the audio stream + delete _audStream; + 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 + Audio::Timestamp curAudioTime(0, _streams[_audioStreamIndex]->time_scale); + uint sample = 0; + bool done = false; + for (int32 i = 0; i < _streams[_audioStreamIndex]->stts_count && !done; i++) { + for (int32 j = 0; j < _streams[_audioStreamIndex]->stts_data[i].count; j++) { + curAudioTime = curAudioTime.addFrames(_streams[_audioStreamIndex]->stts_data[i].duration); + + if (curAudioTime > where) { + done = true; + break; + } + + sample++; + } + } + + // Now to track down what chunk it's in + _curAudioChunk = 0; + uint32 totalSamples = 0; + for (uint32 i = 0; i < _streams[_audioStreamIndex]->chunk_count; i++, _curAudioChunk++) { + int sampleToChunkIndex = -1; + + for (uint32 j = 0; j < _streams[_audioStreamIndex]->sample_to_chunk_sz; j++) + if (i >= _streams[_audioStreamIndex]->sample_to_chunk[j].first) + sampleToChunkIndex = j; + + assert(sampleToChunkIndex >= 0); + + totalSamples += _streams[_audioStreamIndex]->sample_to_chunk[sampleToChunkIndex].count; + + if (sample < totalSamples) { + totalSamples -= _streams[_audioStreamIndex]->sample_to_chunk[sampleToChunkIndex].count; + break; + } + } + + // Reposition the audio stream + 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!) + int16 *tempBuffer = new int16[sample - totalSamples]; + _audStream->readBuffer(tempBuffer, sample - totalSamples); + delete[] tempBuffer; + debug(3, "Skipping %d audio samples", sample - totalSamples); + } +} + QuickTimeAudioDecoder::AudioSampleDesc::AudioSampleDesc() : Common::QuickTimeParser::SampleDesc() { channels = 0; sampleRate = 0; @@ -255,13 +314,10 @@ QuickTimeAudioDecoder::AudioSampleDesc::AudioSampleDesc() : Common::QuickTimePar /** * A wrapper around QuickTimeAudioDecoder that implements the RewindableAudioStream API */ -class QuickTimeAudioStream : public RewindableAudioStream, public QuickTimeAudioDecoder { +class QuickTimeAudioStream : public SeekableAudioStream, public QuickTimeAudioDecoder { public: QuickTimeAudioStream() {} - - ~QuickTimeAudioStream() { - delete _audStream; - } + ~QuickTimeAudioStream() {} bool loadFile(const Common::String &filename) { return QuickTimeAudioDecoder::loadFile(filename) && _audioStreamIndex >= 0 && _audStream; @@ -285,19 +341,21 @@ public: int getRate() const { return _audStream->getRate(); } bool endOfData() const { return _curAudioChunk >= _streams[_audioStreamIndex]->chunk_count && _audStream->endOfData(); } - // RewindableAudioStream API - bool rewind() { - // Reset our parent stream - _curAudioChunk = 0; - delete _audStream; + // SeekableAudioStream API + bool seek(const Timestamp &where) { + if (where > getLength()) + return false; - AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0]; - _audStream = makeQueuingAudioStream(entry->sampleRate, entry->channels == 2); + setAudioStreamPos(where); return true; } + + Timestamp getLength() const { + return Timestamp(0, _streams[_audioStreamIndex]->duration, _streams[_audioStreamIndex]->time_scale); + } }; -RewindableAudioStream *makeQuickTimeStream(const Common::String &filename) { +SeekableAudioStream *makeQuickTimeStream(const Common::String &filename) { QuickTimeAudioStream *audioStream = new QuickTimeAudioStream(); if (!audioStream->loadFile(filename)) { diff --git a/audio/decoders/quicktime.h b/audio/decoders/quicktime.h index eb0f791748..9e2e95b705 100644 --- a/audio/decoders/quicktime.h +++ b/audio/decoders/quicktime.h @@ -80,16 +80,18 @@ protected: int8 _audioStreamIndex; uint _curAudioChunk; QueuingAudioStream *_audStream; + + void setAudioStreamPos(const Timestamp &where); }; /** - * Try to load a QuickTime sound file from the given file name and create a RewindableAudioStream + * Try to load a QuickTime sound file from the given file name and create a SeekableAudioStream * from that data. * * @param filename the filename of the file from which to read the data - * @return a new RewindableAudioStream, or NULL, if an error occurred + * @return a new SeekableAudioStream, or NULL, if an error occurred */ -RewindableAudioStream *makeQuickTimeStream(const Common::String &filename); +SeekableAudioStream *makeQuickTimeStream(const Common::String &filename); } // End of namespace Audio diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp index 71f31d6415..de4a284ec9 100644 --- a/video/qt_decoder.cpp +++ b/video/qt_decoder.cpp @@ -168,58 +168,9 @@ void QuickTimeDecoder::seekToFrame(uint32 frame) { if (_audioStreamIndex >= 0) { _audioStartOffset = curVideoTime; - // Re-create the audio stream - 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 - Audio::Timestamp curAudioTime(0, _streams[_audioStreamIndex]->time_scale); - uint sample = 0; - bool done = false; - for (int32 i = 0; i < _streams[_audioStreamIndex]->stts_count && !done; i++) { - for (int32 j = 0; j < _streams[_audioStreamIndex]->stts_data[i].count; j++) { - curAudioTime = curAudioTime.addFrames(_streams[_audioStreamIndex]->stts_data[i].duration); - - if (curAudioTime > curVideoTime) { - done = true; - break; - } - - sample++; - } - } + // Seek to the new audio location + setAudioStreamPos(_audioStartOffset); - // Now to track down what chunk it's in - _curAudioChunk = 0; - uint32 totalSamples = 0; - for (uint32 i = 0; i < _streams[_audioStreamIndex]->chunk_count; i++, _curAudioChunk++) { - int sampleToChunkIndex = -1; - - for (uint32 j = 0; j < _streams[_audioStreamIndex]->sample_to_chunk_sz; j++) - if (i >= _streams[_audioStreamIndex]->sample_to_chunk[j].first) - sampleToChunkIndex = j; - - assert(sampleToChunkIndex >= 0); - - totalSamples += _streams[_audioStreamIndex]->sample_to_chunk[sampleToChunkIndex].count; - - if (sample < totalSamples) { - totalSamples -= _streams[_audioStreamIndex]->sample_to_chunk[sampleToChunkIndex].count; - break; - } - } - - // Reposition the audio stream - 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!) - int16 *tempBuffer = new int16[sample - totalSamples]; - _audStream->readBuffer(tempBuffer, sample - totalSamples); - delete[] tempBuffer; - debug(3, "Skipping %d audio samples", sample - totalSamples); - } - // Restart the audio startAudio(); } @@ -282,17 +233,15 @@ Codec *QuickTimeDecoder::createCodec(uint32 codecTag, byte bitsPerPixel) { } void QuickTimeDecoder::startAudio() { - if (_audStream) { // No audio/audio not supported + if (_audStream) { updateAudioBuffer(); - g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audHandle, _audStream); - } + g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audHandle, _audStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); + } // else no audio or the audio compression is not supported } void QuickTimeDecoder::stopAudio() { - if (_audStream) { + if (_audStream) g_system->getMixer()->stopHandle(_audHandle); - _audStream = NULL; // the mixer automatically frees the stream - } } void QuickTimeDecoder::pauseVideoIntern(bool pause) { @@ -550,9 +499,6 @@ void QuickTimeDecoder::close() { _scaledSurface = 0; } - // The audio stream is deleted automatically - _audStream = NULL; - Common::QuickTimeParser::close(); SeekableVideoDecoder::reset(); } |