diff options
author | Max Horn | 2006-11-13 19:46:52 +0000 |
---|---|---|
committer | Max Horn | 2006-11-13 19:46:52 +0000 |
commit | 1a2853f7e0786e0ae1d072f5ce97391ad5d67978 (patch) | |
tree | a2e83c8592662cdbba11344d362b1653e3d5583d | |
parent | 9f74b031828b2a309b8194a0da9fdee85dec0cd7 (diff) | |
download | scummvm-rg350-1a2853f7e0786e0ae1d072f5ce97391ad5d67978.tar.gz scummvm-rg350-1a2853f7e0786e0ae1d072f5ce97391ad5d67978.tar.bz2 scummvm-rg350-1a2853f7e0786e0ae1d072f5ce97391ad5d67978.zip |
Patch from bug #1584888 (SMUSH: Too dependent on accurate timers). Watch out for regressions in SMUSH movie playback / syncing
svn-id: r24709
-rw-r--r-- | engines/scumm/intern.h | 3 | ||||
-rw-r--r-- | engines/scumm/scumm.cpp | 9 | ||||
-rw-r--r-- | engines/scumm/smush/smush_mixer.cpp | 6 | ||||
-rw-r--r-- | engines/scumm/smush/smush_player.cpp | 110 | ||||
-rw-r--r-- | engines/scumm/smush/smush_player.h | 9 |
5 files changed, 88 insertions, 49 deletions
diff --git a/engines/scumm/intern.h b/engines/scumm/intern.h index edf4cbd851..6f60359952 100644 --- a/engines/scumm/intern.h +++ b/engines/scumm/intern.h @@ -593,9 +593,6 @@ protected: */ bool _smushVideoShouldFinish; - /** This flag is a hack to allow the pause dialog to pause SMUSH playback, too. */ - bool _smushPaused; - bool _smushActive; Insane *_insane; diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index a687e063de..48b8f056b8 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -822,7 +822,6 @@ ScummEngine_v7::ScummEngine_v7(OSystem *syst, const DetectorResult &dr) _smushFrameRate = 0; _smushVideoShouldFinish = false; - _smushPaused = false; _smushActive = false; _insaneRunning = false; _smixer = NULL; @@ -2157,13 +2156,9 @@ int ScummEngine::runDialog(Dialog &dialog) { #ifndef DISABLE_SCUMM_7_8 int ScummEngine_v7::runDialog(Dialog &dialog) { - bool oldSmushPaused = _smushPaused; - _smushPaused = true; - + _splayer->pause(); int result = ScummEngine::runDialog(dialog); - - _smushPaused = oldSmushPaused; - + _splayer->unpause(); return result; } #endif diff --git a/engines/scumm/smush/smush_mixer.cpp b/engines/scumm/smush/smush_mixer.cpp index 9b0f67045f..9e6631a365 100644 --- a/engines/scumm/smush/smush_mixer.cpp +++ b/engines/scumm/smush/smush_mixer.cpp @@ -45,14 +45,12 @@ SmushMixer::SmushMixer(Audio::Mixer *m) : } SmushMixer::~SmushMixer() { - Common::StackLock lock(_mutex); for (int32 i = 0; i < NUM_CHANNELS; i++) { _mixer->stopHandle(_channels[i].handle); } } SmushChannel *SmushMixer::findChannel(int32 track) { - Common::StackLock lock(_mutex); debugC(DEBUG_SMUSH, "SmushMixer::findChannel(%d)", track); for (int32 i = 0; i < NUM_CHANNELS; i++) { if (_channels[i].id == track) @@ -62,7 +60,6 @@ SmushChannel *SmushMixer::findChannel(int32 track) { } void SmushMixer::addChannel(SmushChannel *c) { - Common::StackLock lock(_mutex); int32 track = c->getTrackIdentifier(); int i; @@ -91,7 +88,6 @@ void SmushMixer::addChannel(SmushChannel *c) { } bool SmushMixer::handleFrame() { - Common::StackLock lock(_mutex); debugC(DEBUG_SMUSH, "SmushMixer::handleFrame()"); for (int i = 0; i < NUM_CHANNELS; i++) { if (_channels[i].id != -1) { @@ -136,7 +132,6 @@ bool SmushMixer::handleFrame() { } bool SmushMixer::stop() { - Common::StackLock lock(_mutex); debugC(DEBUG_SMUSH, "SmushMixer::stop()"); for (int i = 0; i < NUM_CHANNELS; i++) { if (_channels[i].id != -1) { @@ -154,7 +149,6 @@ bool SmushMixer::stop() { } bool SmushMixer::flush() { - Common::StackLock lock(_mutex); debugC(DEBUG_SMUSH, "SmushMixer::flush()"); for (int i = 0; i < NUM_CHANNELS; i++) { if (_channels[i].id != -1) { diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp index 952665ce80..bd4261d60c 100644 --- a/engines/scumm/smush/smush_player.cpp +++ b/engines/scumm/smush/smush_player.cpp @@ -27,7 +27,6 @@ #include "common/config-manager.h" #include "common/file.h" #include "common/system.h" -#include "common/timer.h" #include "common/util.h" #include "graphics/cursorman.h" @@ -220,18 +219,17 @@ static StringResource *getStrings(ScummEngine *vm, const char *file, bool is_enc return sr; } -void SmushPlayer::timerCallback(void *refCon) { - SmushPlayer *sp = (SmushPlayer *)refCon; - sp->parseNextFrame(); +void SmushPlayer::timerCallback() { + parseNextFrame(); #ifdef _WIN32_WCE - sp->_inTimer = true; - sp->_inTimerCount++; + _inTimer = true; + _inTimerCount++; #endif #ifdef __SYMBIAN32__ - if (sp->_closeOnTextTick) { - delete sp->_base; - sp->_base = NULL; - sp->_closeOnTextTick = false; + if (_closeOnTextTick) { + delete _base; + _base = NULL; + _closeOnTextTick = false; } #endif } @@ -267,6 +265,9 @@ SmushPlayer::SmushPlayer(ScummEngine_v7 *scumm) { _skipPalette = false; _IACTstream = NULL; _smixer = _vm->_smixer; + _paused = false; + _pauseStartTime = 0; + _pauseTime = 0; #ifdef _WIN32_WCE _inTimer = false; _inTimerCount = 0; @@ -307,8 +308,6 @@ void SmushPlayer::init(int32 speed) { _vm->_mixer->stopHandle(_IACTchannel); _vm->_smixer->stop(); - _vm->_timer->installTimerProc(&timerCallback, 1000000 / _speed, this); - _initDone = true; } @@ -322,7 +321,6 @@ void SmushPlayer::release() { User::After(15624); } #endif - _vm->_timer->removeTimerProc(&timerCallback); _vm->_smushVideoShouldFinish = true; @@ -1071,13 +1069,8 @@ void SmushPlayer::setupAnim(const char *file) { } void SmushPlayer::parseNextFrame() { - Common::StackLock lock(_mutex); - Chunk *sub; - if (_vm->_smushPaused) - return; - if (_seekPos >= 0) { if (_smixer) _smixer->stop(); @@ -1230,8 +1223,6 @@ void SmushPlayer::insanity(bool flag) { } void SmushPlayer::seekSan(const char *file, int32 pos, int32 contFrame) { - Common::StackLock lock(_mutex); - _seekFile = file ? file : ""; _seekPos = pos; _seekFrame = contFrame; @@ -1274,8 +1265,22 @@ void SmushPlayer::tryCmpFile(const char *filename) { #endif } -void SmushPlayer::play(const char *filename, int32 speed, int32 offset, int32 startFrame) { +void SmushPlayer::pause() { + if (!_paused) { + _paused = true; + _pauseStartTime = _vm->_system->getMillis(); + } +} + +void SmushPlayer::unpause() { + if (_paused) { + _paused = false; + _pauseTime += (_vm->_system->getMillis() - _pauseStartTime); + _pauseStartTime = 0; + } +} +void SmushPlayer::play(const char *filename, int32 speed, int32 offset, int32 startFrame) { // Verify the specified file exists ScummFile f; _vm->openFile(f, filename); @@ -1302,7 +1307,39 @@ void SmushPlayer::play(const char *filename, int32 speed, int32 offset, int32 st setupAnim(filename); init(speed); + uint32 startTime = _vm->_system->getMillis(); + + _pauseTime = 0; + uint frameNo = 0; + + int skipped = 0; + for (;;) { + uint32 elapsed; + bool skipFrame = false; + + if (_vm->_mixer->isSoundHandleActive(_compressedFileSoundHandle)) { + // Compressed SMUSH files. + elapsed = _vm->_mixer->getSoundElapsedTime(_compressedFileSoundHandle); + } else if (_vm->_mixer->isSoundHandleActive(_IACTchannel)) { + // Curse of Monkey Island SMUSH files. + elapsed = _vm->_mixer->getSoundElapsedTime(_IACTchannel); + } else { + // For other SMUSH files, we don't necessarily have any + // one channel to sync against, so we have to use + // elapsed real time. + uint32 now = _vm->_system->getMillis() - _pauseTime; + elapsed = now - startTime; + } + + if (elapsed >= (frameNo * 1000) / _speed) { + if (elapsed >= ((frameNo + 1) * 1000) / _speed) + skipFrame = true; + else + skipFrame = false; + timerCallback(); + } + if (_warpNeeded) { _vm->_system->warpMouse(_warpX, _warpY); _warpNeeded = false; @@ -1326,25 +1363,36 @@ void SmushPlayer::play(const char *filename, int32 speed, int32 offset, int32 st _palDirtyMax = -1; _palDirtyMin = 256; + skipFrame = false; } + if (skipFrame) { + if (++skipped > 10) { + skipFrame = false; + skipped = 0; + } + } else + skipped = 0; if (_updateNeeded) { - int w = _width, h = _height; + if (!skipFrame) { + int w = _width, h = _height; - // Workaround for bug #1386333: "FT DEMO: assertion triggered - // when playing movie". Some frames there are 384 x 224 - if (w > _vm->_screenWidth) - w = _vm->_screenWidth; + // Workaround for bug #1386333: "FT DEMO: assertion triggered + // when playing movie". Some frames there are 384 x 224 + if (w > _vm->_screenWidth) + w = _vm->_screenWidth; - if (h > _vm->_screenHeight) - h = _vm->_screenHeight; + if (h > _vm->_screenHeight) + h = _vm->_screenHeight; - _vm->_system->copyRectToScreen(_dst, _width, 0, 0, w, h); - _vm->_system->updateScreen(); - _updateNeeded = false; + _vm->_system->copyRectToScreen(_dst, _width, 0, 0, w, h); + _vm->_system->updateScreen(); + _updateNeeded = false; + } #ifdef _WIN32_WCE _inTimer = false; _inTimerCount = 0; #endif + frameNo++; } if (_endOfFile) break; diff --git a/engines/scumm/smush/smush_player.h b/engines/scumm/smush/smush_player.h index 53fee75f9c..a6e83ef8ed 100644 --- a/engines/scumm/smush/smush_player.h +++ b/engines/scumm/smush/smush_player.h @@ -91,12 +91,14 @@ private: #ifdef __SYMBIAN32__ bool _closeOnTextTick; #endif - Common::Mutex _mutex; public: SmushPlayer(ScummEngine_v7 *scumm); ~SmushPlayer(); + void pause(); + void unpause(); + void play(const char *filename, int32 speed, int32 offset = 0, int32 startFrame = 0); void release(); void warpMouse(int x, int y, int buttons); @@ -106,6 +108,9 @@ protected: int _width, _height; int _origPitch, _origNumStrips; + bool _paused; + uint32 _pauseStartTime; + uint32 _pauseTime; void insanity(bool); void setPalette(const byte *palette); @@ -139,7 +144,7 @@ private: void handleDeltaPalette(Chunk &); void readPalette(byte *, Chunk &); - static void timerCallback(void *ptr); + void timerCallback(); }; } // End of namespace Scumm |