diff options
author | Matthew Hoops | 2010-05-18 14:17:24 +0000 |
---|---|---|
committer | Matthew Hoops | 2010-05-18 14:17:24 +0000 |
commit | 11cbdd03180a655b2b23ee4a13f1a00a1d782b3c (patch) | |
tree | 5b0d84211308ea37a2fa2f7017d6f96314f3c6fb /engines/sci | |
parent | f3892a506b2f935bae0be6319394c503c786d368 (diff) | |
download | scummvm-rg350-11cbdd03180a655b2b23ee4a13f1a00a1d782b3c.tar.gz scummvm-rg350-11cbdd03180a655b2b23ee4a13f1a00a1d782b3c.tar.bz2 scummvm-rg350-11cbdd03180a655b2b23ee4a13f1a00a1d782b3c.zip |
Committing the rest of the VideoDecoder Rewrite from patch #2963496.
svn-id: r49079
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/console.cpp | 66 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 66 | ||||
-rw-r--r-- | engines/sci/video/seq_decoder.cpp | 80 | ||||
-rw-r--r-- | engines/sci/video/seq_decoder.h | 50 | ||||
-rw-r--r-- | engines/sci/video/vmd_decoder.cpp | 74 | ||||
-rw-r--r-- | engines/sci/video/vmd_decoder.h | 31 |
6 files changed, 192 insertions, 175 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 73b9788ca0..f2e5601c9e 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -222,42 +222,48 @@ void Console::postEnter() { if (!_videoFile.empty()) { _engine->_gfxCursor->kernelHide(); + Graphics::VideoDecoder *videoDecoder = 0; + if (_videoFile.hasSuffix(".seq")) { - SeqDecoder *seqDecoder = new SeqDecoder(); - Graphics::VideoPlayer *player = new Graphics::VideoPlayer(seqDecoder); - if (seqDecoder->loadFile(_videoFile.c_str(), _videoFrameDelay)) - player->playVideo(); - else - DebugPrintf("Failed to open movie file %s\n", _videoFile.c_str()); - seqDecoder->closeFile(); - delete player; - delete seqDecoder; - } else if (_videoFile.hasSuffix(".avi")) { - Graphics::AviDecoder *aviDecoder = new Graphics::AviDecoder(g_system->getMixer()); - Graphics::VideoPlayer *player = new Graphics::VideoPlayer(aviDecoder); - if (aviDecoder->loadFile(_videoFile.c_str())) - player->playVideo(); - else - DebugPrintf("Failed to open movie file %s\n", _videoFile.c_str()); - aviDecoder->closeFile(); - delete player; - delete aviDecoder; - } else if (_videoFile.hasSuffix(".vmd")) { + videoDecoder = new SeqDecoder(); + ((SeqDecoder *)videoDecoder)->setFrameDelay(_videoFrameDelay); #ifdef ENABLE_SCI32 - VMDDecoder *vmdDecoder = new VMDDecoder(g_system->getMixer()); - Graphics::VideoPlayer *player = new Graphics::VideoPlayer(vmdDecoder); - if (vmdDecoder->loadFile(_videoFile.c_str())) - player->playVideo(); - else - DebugPrintf("Failed to open movie file %s\n", _videoFile.c_str()); - vmdDecoder->closeFile(); - delete player; - delete vmdDecoder; + } else if (_videoFile.hasSuffix(".vmd")) { + videoDecoder = new VMDDecoder(g_system->getMixer()); #endif + } else if (_videoFile.hasSuffix(".avi")) { + videoDecoder = new Graphics::AviDecoder(g_system->getMixer()); } - _engine->_gfxCursor->kernelShow(); + if (videoDecoder && videoDecoder->loadFile(_videoFile)) { + uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; + uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2; + + while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) { + if (videoDecoder->needsUpdate()) { + Graphics::Surface *frame = videoDecoder->decodeNextFrame(); + if (frame) { + g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + if (videoDecoder->hasDirtyPalette()) + videoDecoder->setSystemPalette(); + + g_system->updateScreen(); + } + } + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) + ; + + g_system->delayMillis(10); + } + + delete videoDecoder; + } else + warning("Could not play video %s\n", _videoFile.c_str()); + + _engine->_gfxCursor->kernelShow(); _videoFile.clear(); _videoFrameDelay = 0; } diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index da18bc7e03..d587790b6c 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1078,8 +1078,6 @@ reg_t kDisplay(EngineState *s, int argc, reg_t *argv) { } reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { - bool playedVideo = false; - // Hide the cursor if it's showing and then show it again if it was // previously visible. bool reshowCursor; @@ -1087,30 +1085,29 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { reshowCursor = g_sci->_gfxCursor->isVisible(); if (reshowCursor) g_sci->_gfxCursor->kernelHide(); + + Graphics::VideoDecoder *videoDecoder = 0; if (argv[0].segment != 0) { + Common::String filename = s->_segMan->getString(argv[0]); + if (g_sci->getPlatform() == Common::kPlatformMacintosh) { // Mac QuickTime // The only argument is the string for the video - warning("TODO: Play QuickTime movie '%s'", s->_segMan->getString(argv[0]).c_str()); + warning("TODO: Play QuickTime movie '%s'", filename.c_str()); return s->r_acc; } else { // DOS SEQ // SEQ's are called with no subops, just the string and delay - Common::String filename = s->_segMan->getString(argv[0]); - int delay = argv[1].toUint16(); // Time between frames in ticks - SeqDecoder *seqDecoder = new SeqDecoder(); - Graphics::VideoPlayer *player = new Graphics::VideoPlayer(seqDecoder); - if (seqDecoder->loadFile(filename.c_str(), delay)) { - player->playVideo(); - playedVideo = true; - } else { + seqDecoder->setFrameDelay(argv[1].toUint16()); // Time between frames in ticks + videoDecoder = seqDecoder; + + if (!videoDecoder->loadFile(filename)) { warning("Failed to open movie file %s", filename.c_str()); + delete videoDecoder; + videoDecoder = 0; } - seqDecoder->closeFile(); - delete player; - delete seqDecoder; } } else { // Windows AVI (Macintosh QuickTime? Need to check KQ6 Macintosh) @@ -1130,17 +1127,13 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { case 0: { Common::String filename = s->_segMan->getString(argv[1]); - Graphics::AviDecoder *aviDecoder = new Graphics::AviDecoder(g_system->getMixer()); - Graphics::VideoPlayer *player = new Graphics::VideoPlayer(aviDecoder); - if (aviDecoder->loadFile(filename.c_str())) { - player->playVideo(); - playedVideo = true; - } else { + videoDecoder = new Graphics::AviDecoder(g_system->getMixer()); + + if (!videoDecoder->loadFile(filename.c_str())) { warning("Failed to open movie file %s", filename.c_str()); + delete videoDecoder; + videoDecoder = 0; } - aviDecoder->closeFile(); - delete player; - delete aviDecoder; break; } default: @@ -1148,8 +1141,33 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { } } - if (playedVideo) + if (videoDecoder) { + uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; + uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2; + + while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) { + if (videoDecoder->needsUpdate()) { + Graphics::Surface *frame = videoDecoder->decodeNextFrame(); + if (frame) { + g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + + if (videoDecoder->hasDirtyPalette()) + videoDecoder->setSystemPalette(); + + g_system->updateScreen(); + } + } + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) + ; + + g_system->delayMillis(10); + } + + delete videoDecoder; g_sci->_gfxScreen->kernelSyncWithFramebuffer(); + } if (reshowCursor) g_sci->_gfxCursor->kernelShow(); diff --git a/engines/sci/video/seq_decoder.cpp b/engines/sci/video/seq_decoder.cpp index ccce873a15..2c117ae329 100644 --- a/engines/sci/video/seq_decoder.cpp +++ b/engines/sci/video/seq_decoder.cpp @@ -35,10 +35,6 @@ namespace Sci { -// SEQ videos always run at 320x200 -#define SCREEN_WIDTH 320 -#define SCREEN_HEIGHT 200 - enum seqPalTypes { kSeqPalVariable = 0, kSeqPalConstant = 1 @@ -49,26 +45,24 @@ enum seqFrameTypes { kSeqFrameDiff = 1 }; -SeqDecoder::~SeqDecoder() { - closeFile(); +SeqDecoder::SeqDecoder() { + _fileStream = 0; + _surface = 0; + _dirtyPalette = false; } -bool SeqDecoder::loadFile(const char *fileName, int frameDelay) { - closeFile(); +SeqDecoder::~SeqDecoder() { + close(); +} - _fileStream = SearchMan.createReadStreamForMember(fileName); - if (!_fileStream) - return false; +bool SeqDecoder::load(Common::SeekableReadStream &stream) { + close(); - // Seek to the first frame - _videoInfo.currentFrame = -1; + _fileStream = &stream; + _surface = new Graphics::Surface(); + _surface->create(SEQ_SCREEN_WIDTH, SEQ_SCREEN_HEIGHT, 1); - _videoInfo.width = SCREEN_WIDTH; - _videoInfo.height = SCREEN_HEIGHT; - _videoInfo.frameCount = _fileStream->readUint16LE(); - // Our frameDelay is calculated in 1/100 ms, so we convert it here - _videoInfo.frameDelay = 100 * frameDelay * 1000 / 60; - _videoFrameBuffer = new byte[_videoInfo.width * _videoInfo.height]; + _frameCount = _fileStream->readUint16LE(); // Set palette int paletteSize = _fileStream->readUint32LE(); @@ -81,39 +75,38 @@ bool SeqDecoder::loadFile(const char *fileName, int frameDelay) { uint16 palColorStart = READ_LE_UINT16(paletteData + 25); uint16 palColorCount = READ_LE_UINT16(paletteData + 29); - byte palette[256 * 4]; int palOffset = 37; for (uint16 colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { if (palFormat == kSeqPalVariable) palOffset++; - palette[colorNo * 4 + 0] = paletteData[palOffset++]; - palette[colorNo * 4 + 1] = paletteData[palOffset++]; - palette[colorNo * 4 + 2] = paletteData[palOffset++]; - palette[colorNo * 4 + 3] = 0; + _palette[colorNo * 3 + 0] = paletteData[palOffset++]; + _palette[colorNo * 3 + 1] = paletteData[palOffset++]; + _palette[colorNo * 3 + 2] = paletteData[palOffset++]; } - g_system->setPalette(palette, 0, 256); - + _dirtyPalette = true; delete[] paletteData; - - _videoInfo.firstframeOffset = _fileStream->pos(); - return true; } -void SeqDecoder::closeFile() { +void SeqDecoder::close() { if (!_fileStream) return; + _frameDelay = 0; + delete _fileStream; _fileStream = 0; - delete[] _videoFrameBuffer; - _videoFrameBuffer = 0; + _surface->free(); + delete _surface; + _surface = 0; + + reset(); } -bool SeqDecoder::decodeNextFrame() { +Graphics::Surface *SeqDecoder::decodeNextFrame() { int16 frameWidth = _fileStream->readUint16LE(); int16 frameHeight = _fileStream->readUint16LE(); int16 frameLeft = _fileStream->readUint16LE(); @@ -129,42 +122,41 @@ bool SeqDecoder::decodeNextFrame() { _fileStream->seek(offset); - _videoInfo.currentFrame++; - - if (_videoInfo.currentFrame == 0) - _videoInfo.startTime = g_system->getMillis(); - if (frameType == kSeqFrameFull) { - byte *dst = _videoFrameBuffer + frameTop * SCREEN_WIDTH + frameLeft; + byte *dst = (byte *)_surface->pixels + frameTop * SEQ_SCREEN_WIDTH + frameLeft; byte *linebuf = new byte[frameWidth]; do { _fileStream->read(linebuf, frameWidth); memcpy(dst, linebuf, frameWidth); - dst += SCREEN_WIDTH; + dst += SEQ_SCREEN_WIDTH; } while (--frameHeight); delete[] linebuf; } else { byte *buf = new byte[frameSize]; _fileStream->read(buf, frameSize); - decodeFrame(buf, rleSize, buf + rleSize, frameSize - rleSize, _videoFrameBuffer + SCREEN_WIDTH * frameTop, frameLeft, frameWidth, frameHeight, colorKey); + decodeFrame(buf, rleSize, buf + rleSize, frameSize - rleSize, (byte *)_surface->pixels + SEQ_SCREEN_WIDTH * frameTop, frameLeft, frameWidth, frameHeight, colorKey); delete[] buf; } - return !endOfVideo(); + if (_curFrame == -1) + _startTime = g_system->getMillis(); + + _curFrame++; + return _surface; } #define WRITE_TO_BUFFER(n) \ - if (writeRow * SCREEN_WIDTH + writeCol + (n) > SCREEN_WIDTH * height) { \ + if (writeRow * SEQ_SCREEN_WIDTH + writeCol + (n) > SEQ_SCREEN_WIDTH * height) { \ warning("SEQ player: writing out of bounds, aborting"); \ return false; \ } \ if (litPos + (n) > litSize) { \ warning("SEQ player: reading out of bounds, aborting"); \ } \ - memcpy(dest + writeRow * SCREEN_WIDTH + writeCol, litData + litPos, n); + memcpy(dest + writeRow * SEQ_SCREEN_WIDTH + writeCol, litData + litPos, n); bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey) { int writeRow = 0; diff --git a/engines/sci/video/seq_decoder.h b/engines/sci/video/seq_decoder.h index 7c810db05d..416abb78fa 100644 --- a/engines/sci/video/seq_decoder.h +++ b/engines/sci/video/seq_decoder.h @@ -26,40 +26,50 @@ #ifndef SEQ_DECODER_H #define SEQ_DECODER_H -#include "graphics/video/video_player.h" +#include "graphics/video/video_decoder.h" namespace Sci { /** * Implementation of the Sierra SEQ decoder, used in KQ6 DOS floppy/CD and GK1 DOS */ -class SeqDecoder : public Graphics::VideoDecoder { +class SeqDecoder : public Graphics::FixedRateVideoDecoder { public: - SeqDecoder() {} + SeqDecoder(); virtual ~SeqDecoder(); - /** - * Load a SEQ encoded video file - * @param filename the filename to load - */ - bool loadFile(const char *fileName) { return loadFile(fileName, 10); } + bool load(Common::SeekableReadStream &stream); + void close(); - /** - * Load a SEQ encoded video file - * @param filename the filename to load - * @param frameDelay the delay between frames, in ticks - */ - bool loadFile(const char *fileName, int frameDelay); + void setFrameDelay(int frameDelay) { _frameDelay = frameDelay; } - /** - * Close a SEQ encoded video file - */ - void closeFile(); - - bool decodeNextFrame(); + bool isVideoLoaded() const { return _fileStream != 0; } + uint16 getWidth() const { return SEQ_SCREEN_WIDTH; } + uint16 getHeight() const { return SEQ_SCREEN_HEIGHT; } + uint32 getFrameCount() const { return _frameCount; } + Graphics::Surface *decodeNextFrame(); + Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } + byte *getPalette() { _dirtyPalette = false; return _palette; } + bool hasDirtyPalette() const { return _dirtyPalette; } + +protected: + Common::Rational getFrameRate() const { assert(_frameDelay); return Common::Rational(60, _frameDelay); } private: + enum { + SEQ_SCREEN_WIDTH = 320, + SEQ_SCREEN_HEIGHT = 200 + }; + bool decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey); + + uint16 _width, _height; + uint16 _frameDelay; + Common::SeekableReadStream *_fileStream; + byte _palette[256 * 3]; + bool _dirtyPalette; + uint32 _frameCount; + Graphics::Surface *_surface; }; } // End of namespace Sci diff --git a/engines/sci/video/vmd_decoder.cpp b/engines/sci/video/vmd_decoder.cpp index 9e95521ebb..93132bc5d6 100644 --- a/engines/sci/video/vmd_decoder.cpp +++ b/engines/sci/video/vmd_decoder.cpp @@ -27,7 +27,6 @@ #include "sci/video/vmd_decoder.h" -#include "common/archive.h" #include "common/endian.h" #include "common/util.h" #include "common/stream.h" @@ -42,54 +41,39 @@ namespace Sci { VMDDecoder::VMDDecoder(Audio::Mixer *mixer) : _mixer(mixer) { _vmdDecoder = new Graphics::Vmd(new Graphics::PaletteLUT(5, Graphics::PaletteLUT::kPaletteYUV)); + _surface = 0; + _dirtyPalette = false; + _fileStream = 0; } VMDDecoder::~VMDDecoder() { - closeFile(); -} - -uint32 VMDDecoder::getFrameWaitTime() { - return _vmdDecoder->getFrameWaitTime(); + close(); } -bool VMDDecoder::loadFile(const char *fileName) { - closeFile(); +bool VMDDecoder::load(Common::SeekableReadStream &stream) { + close(); - _fileStream = SearchMan.createReadStreamForMember(fileName); - if (!_fileStream) + if (!_vmdDecoder->load(stream)) return false; - if (!_vmdDecoder->load(*_fileStream)) - return false; + _fileStream = &stream; - if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesPalette) { - getPalette(); - setPalette(_palette); - } + if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesPalette) + loadPaletteFromVMD(); if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesSound) _vmdDecoder->enableSound(*_mixer); - _videoInfo.width = _vmdDecoder->getWidth(); - _videoInfo.height = _vmdDecoder->getHeight(); - _videoInfo.frameCount = _vmdDecoder->getFramesCount(); - _videoInfo.frameRate = _vmdDecoder->getFrameRate(); - _videoInfo.frameDelay = _videoInfo.frameRate * 100; - _videoInfo.currentFrame = -1; - _videoInfo.firstframeOffset = 0; // not really necessary for VMDs - if (_vmdDecoder->hasExtraData()) warning("This VMD video has extra embedded data, which is currently not handled"); - _videoFrameBuffer = new byte[_videoInfo.width * _videoInfo.height]; - memset(_videoFrameBuffer, 0, _videoInfo.width * _videoInfo.height); - - _vmdDecoder->setVideoMemory(_videoFrameBuffer, _videoInfo.width, _videoInfo.height); - + _surface = new Graphics::Surface(); + _surface->create(_vmdDecoder->getWidth(), _vmdDecoder->getHeight(), 1); + _vmdDecoder->setVideoMemory((byte *)_surface->pixels, _surface->w, _surface->h); return true; } -void VMDDecoder::closeFile() { +void VMDDecoder::close() { if (!_fileStream) return; @@ -98,27 +82,27 @@ void VMDDecoder::closeFile() { delete _fileStream; _fileStream = 0; - delete[] _videoFrameBuffer; - _videoFrameBuffer = 0; -} - -bool VMDDecoder::decodeNextFrame() { - _videoInfo.currentFrame++; + _surface->free(); + delete _surface; + _surface = 0; - if (_videoInfo.currentFrame == 0) - _videoInfo.startTime = g_system->getMillis(); + reset(); +} +Graphics::Surface *VMDDecoder::decodeNextFrame() { Graphics::CoktelVideo::State state = _vmdDecoder->nextFrame(); - if (state.flags & Graphics::CoktelVideo::kStatePalette) { - getPalette(); - setPalette(_palette); - } + if (state.flags & Graphics::CoktelVideo::kStatePalette) + loadPaletteFromVMD(); + + if (_curFrame == -1) + _startTime = g_system->getMillis(); - return !endOfVideo(); + _curFrame++; + return _surface; } -void VMDDecoder::getPalette() { +void VMDDecoder::loadPaletteFromVMD() { const byte *pal = _vmdDecoder->getPalette(); for (int i = 0; i < 256; i++) { @@ -126,6 +110,8 @@ void VMDDecoder::getPalette() { _palette[i * 3 + 1] = pal[i * 3 + 1] << 2; _palette[i * 3 + 2] = pal[i * 3 + 2] << 2; } + + _dirtyPalette = true; } } // End of namespace Graphics diff --git a/engines/sci/video/vmd_decoder.h b/engines/sci/video/vmd_decoder.h index 628be24e82..231da9202e 100644 --- a/engines/sci/video/vmd_decoder.h +++ b/engines/sci/video/vmd_decoder.h @@ -29,7 +29,7 @@ #define GRAPHICS_VIDEO_VMD_DECODER_H #include "graphics/video/coktelvideo/coktelvideo.h" -#include "graphics/video/video_player.h" +#include "graphics/video/video_decoder.h" #include "sound/mixer.h" namespace Sci { @@ -49,32 +49,37 @@ namespace Sci { * - Shivers 2: Harvest of Souls * - Torin's Passage */ -class VMDDecoder : public Graphics::VideoDecoder { +class VMDDecoder : public Graphics::FixedRateVideoDecoder { public: VMDDecoder(Audio::Mixer *mixer); virtual ~VMDDecoder(); uint32 getFrameWaitTime(); - /** - * Load a VMD encoded video file - * @param filename the filename to load - */ - bool loadFile(const char *filename); + bool load(Common::SeekableReadStream &stream); + void close(); - /** - * Close a VMD encoded video file - */ - void closeFile(); + bool isVideoLoaded() const { return _fileStream != 0; } + uint16 getWidth() const { return _surface->w; } + uint16 getHeight() const { return _surface->h; } + uint32 getFrameCount() const { return _vmdDecoder->getFramesCount(); } + Graphics::Surface *decodeNextFrame(); + Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } + byte *getPalette() { _dirtyPalette = false; return _palette; } + bool hasDirtyPalette() const { return _dirtyPalette; } - bool decodeNextFrame(); +protected: + Common::Rational getFrameRate() const { return _vmdDecoder->getFrameRate(); } private: Graphics::Vmd *_vmdDecoder; Audio::Mixer *_mixer; + Graphics::Surface *_surface; + Common::SeekableReadStream *_fileStream; byte _palette[256 * 3]; + bool _dirtyPalette; - void getPalette(); + void loadPaletteFromVMD(); }; } // End of namespace Graphics |