aboutsummaryrefslogtreecommitdiff
path: root/audio/decoders/quicktime.cpp
diff options
context:
space:
mode:
authorMatthew Hoops2011-04-08 10:50:16 -0400
committerMatthew Hoops2011-04-08 10:54:13 -0400
commit88ebf13077a072ac0b3100e54f2949db46960e5e (patch)
tree14f3acc5e71404beebbb7f6ded56cc532a203814 /audio/decoders/quicktime.cpp
parent5c4d7baa06530cb17d7fdf91eb1c93d62274827a (diff)
downloadscummvm-rg350-88ebf13077a072ac0b3100e54f2949db46960e5e.tar.gz
scummvm-rg350-88ebf13077a072ac0b3100e54f2949db46960e5e.tar.bz2
scummvm-rg350-88ebf13077a072ac0b3100e54f2949db46960e5e.zip
AUDIO: Allow for seeking in a QuickTimeAudioStream
Diffstat (limited to 'audio/decoders/quicktime.cpp')
-rw-r--r--audio/decoders/quicktime.cpp84
1 files changed, 71 insertions, 13 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)) {