VIDEO: Remove the need to call updateAudioBuffer() externally for QuickTime
svn-id: r54929
This commit is contained in:
parent
1ead0d8436
commit
98a2bc8a9a
3 changed files with 37 additions and 15 deletions
|
@ -223,9 +223,6 @@ bool VideoManager::updateBackgroundMovies() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the audio buffer too
|
|
||||||
_videoStreams[i]->updateAudioBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if we need to update the screen
|
// Return true if we need to update the screen
|
||||||
|
|
|
@ -226,6 +226,9 @@ const Surface *QuickTimeDecoder::decodeNextFrame() {
|
||||||
_curFrame++;
|
_curFrame++;
|
||||||
_nextFrameStartTime += getFrameDuration();
|
_nextFrameStartTime += getFrameDuration();
|
||||||
|
|
||||||
|
// Update the audio while we're at it
|
||||||
|
updateAudioBuffer();
|
||||||
|
|
||||||
// Get the next packet
|
// Get the next packet
|
||||||
uint32 descId;
|
uint32 descId;
|
||||||
Common::SeekableReadStream *frameData = getNextFramePacket(descId);
|
Common::SeekableReadStream *frameData = getNextFramePacket(descId);
|
||||||
|
@ -1277,23 +1280,49 @@ Audio::AudioStream *QuickTimeDecoder::createAudioStream(Common::SeekableReadStre
|
||||||
return NULL;
|
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 - 1))
|
||||||
|
sampleCount = _streams[_audioStreamIndex]->sample_to_chunk[j].count;
|
||||||
|
|
||||||
|
return sampleCount;
|
||||||
|
}
|
||||||
|
|
||||||
void QuickTimeDecoder::updateAudioBuffer() {
|
void QuickTimeDecoder::updateAudioBuffer() {
|
||||||
if (!_audStream)
|
if (!_audStream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
STSDEntry *entry = &_streams[_audioStreamIndex]->stsdEntries[0];
|
STSDEntry *entry = &_streams[_audioStreamIndex]->stsdEntries[0];
|
||||||
|
|
||||||
|
// Calculate the amount of chunks we need in memory until the next frame
|
||||||
|
uint32 timeToNextFrame = getTimeToNextFrame();
|
||||||
|
uint32 numberOfChunksNeeded = 0;
|
||||||
|
uint32 timeFilled = 0;
|
||||||
|
uint32 curAudioChunk = _curAudioChunk - _audStream->numQueuedStreams();
|
||||||
|
|
||||||
|
for (; timeFilled < timeToNextFrame && curAudioChunk < _streams[_audioStreamIndex]->chunk_count; numberOfChunksNeeded++, curAudioChunk++) {
|
||||||
|
uint32 sampleCount = getAudioChunkSampleCount(curAudioChunk);
|
||||||
|
assert(sampleCount);
|
||||||
|
|
||||||
|
timeFilled += sampleCount * 1000 / entry->sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a couple extra to ensure we don't underrun
|
||||||
|
numberOfChunksNeeded += 3;
|
||||||
|
|
||||||
// Keep three streams in buffer so that if/when the first two end, it goes right into the next
|
// Keep three streams in buffer so that if/when the first two end, it goes right into the next
|
||||||
for (; _audStream->numQueuedStreams() < 3 && _curAudioChunk < _streams[_audioStreamIndex]->chunk_count; _curAudioChunk++) {
|
for (; _audStream->numQueuedStreams() < numberOfChunksNeeded && _curAudioChunk < _streams[_audioStreamIndex]->chunk_count; _curAudioChunk++) {
|
||||||
Common::MemoryWriteStreamDynamic *wStream = new Common::MemoryWriteStreamDynamic();
|
Common::MemoryWriteStreamDynamic *wStream = new Common::MemoryWriteStreamDynamic();
|
||||||
|
|
||||||
_fd->seek(_streams[_audioStreamIndex]->chunk_offsets[_curAudioChunk]);
|
_fd->seek(_streams[_audioStreamIndex]->chunk_offsets[_curAudioChunk]);
|
||||||
|
|
||||||
// First, we have to get the sample count
|
// First, we have to get the sample count
|
||||||
uint32 sampleCount = 0;
|
uint32 sampleCount = getAudioChunkSampleCount(_curAudioChunk);
|
||||||
for (uint32 j = 0; j < _streams[_audioStreamIndex]->sample_to_chunk_sz; j++)
|
|
||||||
if (_curAudioChunk >= (_streams[_audioStreamIndex]->sample_to_chunk[j].first - 1))
|
|
||||||
sampleCount = _streams[_audioStreamIndex]->sample_to_chunk[j].count;
|
|
||||||
assert(sampleCount);
|
assert(sampleCount);
|
||||||
|
|
||||||
// Then calculate the right sizes
|
// Then calculate the right sizes
|
||||||
|
|
|
@ -116,13 +116,7 @@ public:
|
||||||
// RewindableVideoDecoder API
|
// RewindableVideoDecoder API
|
||||||
void rewind();
|
void rewind();
|
||||||
|
|
||||||
// TODO: This audio function need to be removed from the public and/or added to
|
private:
|
||||||
// the VideoDecoder API directly. I plan on replacing this function with something
|
|
||||||
// that can figure out how much audio is needed instead of constantly keeping two
|
|
||||||
// chunks in memory.
|
|
||||||
void updateAudioBuffer();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// This is the file handle from which data is read from. It can be the actual file handle or a decompressed stream.
|
// This is the file handle from which data is read from. It can be the actual file handle or a decompressed stream.
|
||||||
Common::SeekableReadStream *_fd;
|
Common::SeekableReadStream *_fd;
|
||||||
|
|
||||||
|
@ -245,6 +239,8 @@ protected:
|
||||||
Audio::QueuingAudioStream *_audStream;
|
Audio::QueuingAudioStream *_audStream;
|
||||||
void startAudio();
|
void startAudio();
|
||||||
void stopAudio();
|
void stopAudio();
|
||||||
|
void updateAudioBuffer();
|
||||||
|
uint32 getAudioChunkSampleCount(uint chunk);
|
||||||
int8 _audioStreamIndex;
|
int8 _audioStreamIndex;
|
||||||
uint _curAudioChunk;
|
uint _curAudioChunk;
|
||||||
Audio::SoundHandle _audHandle;
|
Audio::SoundHandle _audHandle;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue