diff options
author | Travis Howell | 2006-04-23 02:11:49 +0000 |
---|---|---|
committer | Travis Howell | 2006-04-23 02:11:49 +0000 |
commit | f1a318ce150f4c7657278c4827a1e822549919f8 (patch) | |
tree | 9c9dc991a51503880f45f6a59cdc6b00ca4a30fd | |
parent | 660efce9b29fc412ad4ddf502de120f47966f4d7 (diff) | |
download | scummvm-rg350-f1a318ce150f4c7657278c4827a1e822549919f8.tar.gz scummvm-rg350-f1a318ce150f4c7657278c4827a1e822549919f8.tar.bz2 scummvm-rg350-f1a318ce150f4c7657278c4827a1e822549919f8.zip |
Fix audio and video sync. in videos of FF
svn-id: r22088
-rw-r--r-- | engines/simon/animation.cpp | 202 | ||||
-rw-r--r-- | engines/simon/animation.h | 13 |
2 files changed, 106 insertions, 109 deletions
diff --git a/engines/simon/animation.cpp b/engines/simon/animation.cpp index 5403f92c6e..9714958f57 100644 --- a/engines/simon/animation.cpp +++ b/engines/simon/animation.cpp @@ -71,7 +71,7 @@ bool MoviePlayer::load(const char *filename) { } _width = _fd.readUint16BE(); _height = _fd.readUint16BE(); - debug(5, "frames_count %d width %d height %d ticks %d", _framesCount, _width, _height, _frameTicks); + debug(0, "frames_count %d width %d height %d ticks %d", _framesCount, _width, _height, _frameTicks); _frameSize = _width * _height; _frameBuffer1 = (uint8 *)malloc(_frameSize); _frameBuffer2 = (uint8 *)malloc(_frameSize); @@ -85,20 +85,20 @@ bool MoviePlayer::load(const char *filename) { void MoviePlayer::play() { uint32 tag; - // Load OmniTV video - if (_vm->getBitFlag(40)) { - _vm->_variableArray[254] = 6747; - return; - } - if (_fd.isOpen() == false) { - debug(0, "MoviePlayer::play: No file loaded"); - return; + // Load OmniTV video + if (_vm->getBitFlag(40)) { + _vm->_variableArray[254] = 6747; + return; + } else { + debug(0, "MoviePlayer::play: No file loaded"); + return; + } } _mixer->stopAll(); - _currentFrame = 0; + _frameNum = 0; _leftButtonDown = false; _rightButtonDown = false; @@ -110,18 +110,48 @@ void MoviePlayer::play() { byte *buffer = (byte *)malloc(size); _fd.read(buffer, size); - // TODO: Audio and video sync. + _ticks = g_system->getMillis(); + Common::MemoryReadStream stream(buffer, size); - AudioStream *sndStream = makeWAVStream(stream); - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, NULL, sndStream); + _bgSoundStream = makeWAVStream(stream); + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_bgSound, _bgSoundStream); // Resolution is smaller in Amiga verison so always clear screen - if (_width != 640 && _height != 480) + if (_width == 384 && _height == 280) g_system->clearScreen(); - while (_currentFrame < _framesCount) { - handleNextFrame(); - ++_currentFrame; + while (_frameNum < _framesCount) { + decodeFrame(); + processFrame(); + g_system->updateScreen(); + _frameNum++; + + OSystem::Event event; + while (g_system->pollEvent(event)) { + switch (event.type) { + case OSystem::EVENT_LBUTTONDOWN: + _leftButtonDown = true; + break; + case OSystem::EVENT_RBUTTONDOWN: + _rightButtonDown = true; + break; + case OSystem::EVENT_LBUTTONUP: + _leftButtonDown = false; + break; + case OSystem::EVENT_RBUTTONUP: + _rightButtonDown = false; + break; + case OSystem::EVENT_QUIT: + g_system->quit(); + break; + default: + break; + } + } + + if (_leftButtonDown && _rightButtonDown && !_vm->getBitFlag(40)) { + _frameNum = _framesCount; + } } close(); @@ -141,7 +171,29 @@ void MoviePlayer::close() { free(_frameBuffer2); } -void MoviePlayer::handleNextFrame() { +void MoviePlayer::decodeZlib(uint8 *data, int size, int totalSize) { +#ifdef USE_ZLIB + uint8 *temp = (uint8 *)malloc(size); + if (temp) { + memcpy(temp, data, size); + z_stream d_stream; + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + d_stream.next_in = temp; + d_stream.avail_in = size; + d_stream.total_in = size; + d_stream.next_out = data; + d_stream.avail_out = totalSize; + inflateInit(&d_stream); + inflate(&d_stream, Z_FINISH); + inflateEnd(&d_stream); + free(temp); + } +#endif +} + +void MoviePlayer::decodeFrame() { uint32 tag = _fd.readUint32BE(); if (tag == MKID_BE('CMAP')) { uint8 rgb[768]; @@ -162,23 +214,17 @@ void MoviePlayer::handleNextFrame() { if (tag == MKID_BE('FRAM')) { uint8 type = _fd.readByte(); uint32 size = _fd.readUint32BE(); - debug(5, "frame %d type %d size %d", _currentFrame, type, size); + debug(0, "frame %d type %d size %d", _frameNum, type, size); _fd.read(_frameBuffer2, size); switch (type) { case 2: case 3: decodeZlib(_frameBuffer2, size, _frameSize); break; - case 4: - case 5: - decode0(_frameBuffer2, size); - break; - case 6: - case 7: - decode2(_frameBuffer2, size, _frameSize); - break; + default: + error("decodeFrame: Unknown compression type %d", type); } - if (type == 2 || type == 4 || type == 6) { + if (type == 2) { memcpy(_frameBuffer1, _frameBuffer2, _frameSize); } else { for (int j = 0; j < _height; ++j) { @@ -189,91 +235,39 @@ void MoviePlayer::handleNextFrame() { } } } +} +void MoviePlayer::processFrame() { if (_width == 640 && _height == 480) g_system->copyRectToScreen(_frameBuffer1, _width, 0, 0, _width, _height); else g_system->copyRectToScreen(_frameBuffer1, _width, 128, 100, _width, _height); - g_system->updateScreen(); - delay(_frameTicks); -} -void MoviePlayer::decodeZlib(uint8 *data, int size, int totalSize) { -#ifdef USE_ZLIB - uint8 *temp = (uint8 *)malloc(size); - if (temp) { - memcpy(temp, data, size); - z_stream d_stream; - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - d_stream.next_in = temp; - d_stream.avail_in = size; - d_stream.total_in = size; - d_stream.next_out = data; - d_stream.avail_out = totalSize; - inflateInit(&d_stream); - inflate(&d_stream, Z_FINISH); - inflateEnd(&d_stream); - free(temp); - } -#endif -} - -void MoviePlayer::decode0(uint8 *data, int size) { - error("decode0"); -} - -void MoviePlayer::decode2(uint8 *data, int size, int totalSize) { - error("decode2"); -} - -void MoviePlayer::delay(uint amount) { - OSystem::Event event; - - uint32 start = g_system->getMillis(); - uint32 cur = start; - uint this_delay; - - do { - while (g_system->pollEvent(event)) { - switch (event.type) { - case OSystem::EVENT_LBUTTONDOWN: - _leftButtonDown = true; - break; - case OSystem::EVENT_RBUTTONDOWN: - _rightButtonDown = true; - break; - case OSystem::EVENT_LBUTTONUP: - _leftButtonDown = false; - break; - case OSystem::EVENT_RBUTTONUP: - _rightButtonDown = false; - break; - case OSystem::EVENT_QUIT: - g_system->quit(); - break; - default: - break; - } - } - - if (_leftButtonDown && _rightButtonDown && !_vm->getBitFlag(40)) { - _currentFrame = _framesCount; - amount = 0; + // TODO Remove set frame rate, were video files use different rate. + if ((_bgSoundStream == NULL) || ((_mixer->getSoundElapsedTime(_bgSound) * 10) / 1000 < _frameNum + 1) || + _frameSkipped > 10) { + if (_frameSkipped > 10) { + warning("force frame %i redraw", _frameNum); + _frameSkipped = 0; } - if (amount == 0) - break; - - { - this_delay = 20 * 1; - if (this_delay > amount) - this_delay = amount; - g_system->delayMillis(this_delay); + if (_bgSoundStream && _mixer->isSoundHandleActive(_bgSound)) { + while (_mixer->isSoundHandleActive(_bgSound) && (_mixer->getSoundElapsedTime(_bgSound) * 10) / 1000 < _frameNum) { + g_system->delayMillis(10); + } + // In case the background sound ends prematurely, update + // _ticks so that we can still fall back on the no-sound + // sync case for the subsequent frames. + _ticks = g_system->getMillis(); + } else { + _ticks += _frameTicks; + while (g_system->getMillis() < _ticks) + g_system->delayMillis(10); } - cur = g_system->getMillis(); - } while (cur < start + amount); + } else { + warning("dropped frame %i", _frameNum); + _frameSkipped++; + } } } // End of namespace Simon diff --git a/engines/simon/animation.h b/engines/simon/animation.h index 29f4f5d213..78a9ea9974 100644 --- a/engines/simon/animation.h +++ b/engines/simon/animation.h @@ -37,6 +37,9 @@ class MoviePlayer { Audio::Mixer *_mixer; + Audio::SoundHandle _bgSound; + AudioStream *_bgSoundStream; + bool _playing; bool _leftButtonDown; bool _rightButtonDown; @@ -47,8 +50,10 @@ class MoviePlayer { uint16 _height; uint32 _frameSize; uint16 _framesCount; - uint16 _currentFrame; + uint16 _frameNum; uint32 _frameTicks; + uint _frameSkipped; + uint32 _ticks; public: MoviePlayer(SimonEngine *vm, Audio::Mixer *mixer); @@ -59,11 +64,9 @@ public: private: void close(); - void delay(uint amount); - void handleNextFrame(); + void decodeFrame(); + void processFrame(); void decodeZlib(uint8 *data, int size, int totalSize); - void decode0(uint8 *data, int size); - void decode2(uint8 *data, int size, int totalSize); }; } // End of namespace Simon |