aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTravis Howell2006-04-23 02:11:49 +0000
committerTravis Howell2006-04-23 02:11:49 +0000
commitf1a318ce150f4c7657278c4827a1e822549919f8 (patch)
tree9c9dc991a51503880f45f6a59cdc6b00ca4a30fd
parent660efce9b29fc412ad4ddf502de120f47966f4d7 (diff)
downloadscummvm-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.cpp202
-rw-r--r--engines/simon/animation.h13
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