diff options
author | Matthew Hoops | 2012-08-16 12:17:23 -0400 |
---|---|---|
committer | Matthew Hoops | 2012-08-16 12:17:23 -0400 |
commit | 7294a1cbcf1cf5e8c846faf8838e537bd8c638dc (patch) | |
tree | 37f8c97ba038b72744e8341f9b23add9fcd68281 | |
parent | 92432a136bff7c327b5328cc10a84198f571b0d0 (diff) | |
download | scummvm-rg350-7294a1cbcf1cf5e8c846faf8838e537bd8c638dc.tar.gz scummvm-rg350-7294a1cbcf1cf5e8c846faf8838e537bd8c638dc.tar.bz2 scummvm-rg350-7294a1cbcf1cf5e8c846faf8838e537bd8c638dc.zip |
VIDEO: Remove the Coktel video code from using the VideoDecoder API
After discussing with DrMcCoy, we felt this the best way to proceed. A wrapper class that implements AdvancedVideoDecoder is still around for use in SCI.
-rw-r--r-- | engines/sci/console.cpp | 5 | ||||
-rw-r--r-- | engines/sci/engine/kvideo.cpp | 7 | ||||
-rw-r--r-- | video/coktel_decoder.cpp | 166 | ||||
-rw-r--r-- | video/coktel_decoder.h | 116 |
4 files changed, 231 insertions, 63 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 9b5ef35e92..de852ca9c0 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -253,7 +253,7 @@ void Console::postEnter() { videoDecoder = new SEQDecoder(_videoFrameDelay); #ifdef ENABLE_SCI32 } else if (_videoFile.hasSuffix(".vmd")) { - videoDecoder = new Video::VMDDecoder(g_system->getMixer()); + videoDecoder = new Video::AdvancedVMDDecoder(); } else if (_videoFile.hasSuffix(".rbt")) { videoDecoder = new RobotDecoder(_engine->getPlatform() == Common::kPlatformMacintosh); } else if (_videoFile.hasSuffix(".duk")) { @@ -267,8 +267,7 @@ void Console::postEnter() { } if (videoDecoder && videoDecoder->loadFile(_videoFile)) { - if (!_videoFile.hasSuffix(".vmd")) // TODO: Remove after new API is complete - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); _engine->_gfxCursor->kernelHide(); diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index da63aa3a8d..3e0f35c037 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -50,6 +50,8 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { if (!videoDecoder) return; + ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); + byte *scaleBuffer = 0; byte bytesPerPixel = videoDecoder->getPixelFormat().bytesPerPixel; uint16 width = videoDecoder->getWidth(); @@ -219,7 +221,6 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { } if (videoDecoder) { - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); // TODO: Remove after new API is complete playVideo(videoDecoder, s->_videoState); // HACK: Switch back to 8bpp if we played a true color video. @@ -349,7 +350,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { break; } case 6: // Play - videoDecoder = new Video::VMDDecoder(g_system->getMixer()); + videoDecoder = new Video::AdvancedVMDDecoder(); if (s->_videoState.fileName.empty()) { // Happens in Lighthouse @@ -414,8 +415,6 @@ reg_t kPlayDuck(EngineState *s, int argc, reg_t *argv) { break; } - ((Video::AdvancedVideoDecoder *)videoDecoder)->start(); - if (reshowCursor) g_sci->_gfxCursor->kernelHide(); diff --git a/video/coktel_decoder.cpp b/video/coktel_decoder.cpp index 0c7ade1b8a..42033fb01f 100644 --- a/video/coktel_decoder.cpp +++ b/video/coktel_decoder.cpp @@ -53,7 +53,8 @@ CoktelDecoder::CoktelDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundT _mixer(mixer), _soundType(soundType), _width(0), _height(0), _x(0), _y(0), _defaultX(0), _defaultY(0), _features(0), _frameCount(0), _paletteDirty(false), _ownSurface(true), _frameRate(12), _hasSound(false), _soundEnabled(false), - _soundStage(kSoundNone), _audioStream(0) { + _soundStage(kSoundNone), _audioStream(0), _startTime(0), _pauseStartTime(0), + _isPaused(false) { assert(_mixer); @@ -261,6 +262,10 @@ bool CoktelDecoder::isPaletted() const { return true; } +int CoktelDecoder::getCurFrame() const { + return _curFrame; +} + void CoktelDecoder::close() { disableSound(); freeSurface(); @@ -273,9 +278,14 @@ void CoktelDecoder::close() { _features = 0; - _frameCount = 0; + _curFrame = -1; + _frameCount = 0; + + _startTime = 0; _hasSound = false; + + _isPaused = false; } uint16 CoktelDecoder::getWidth() const { @@ -291,6 +301,7 @@ uint32 CoktelDecoder::getFrameCount() const { } const byte *CoktelDecoder::getPalette() { + _paletteDirty = false; return _palette; } @@ -625,14 +636,45 @@ Common::Rational CoktelDecoder::getFrameRate() const { return _frameRate; } +uint32 CoktelDecoder::getTimeToNextFrame() const { + if (endOfVideo() || _curFrame < 0) + return 0; + + uint32 elapsedTime = g_system->getMillis() - _startTime; + uint32 nextFrameStartTime = (Common::Rational((_curFrame + 1) * 1000) / getFrameRate()).toInt(); + + if (nextFrameStartTime <= elapsedTime) + return 0; + + return nextFrameStartTime - elapsedTime; +} + uint32 CoktelDecoder::getStaticTimeToNextFrame() const { return (1000 / _frameRate).toInt(); } +void CoktelDecoder::pauseVideo(bool pause) { + if (_isPaused != pause) { + if (_isPaused) { + // Add the time we were paused to the initial starting time + _startTime += g_system->getMillis() - _pauseStartTime; + } else { + // Store the time we paused for use later + _pauseStartTime = g_system->getMillis(); + } + + _isPaused = pause; + } +} + inline void CoktelDecoder::unsignedToSigned(byte *buffer, int length) { while (length-- > 0) *buffer++ ^= 0x80; } +bool CoktelDecoder::endOfVideo() const { + return !isVideoLoaded() || (getCurFrame() >= (int32)getFrameCount() - 1); +} + PreIMDDecoder::PreIMDDecoder(uint16 width, uint16 height, Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : CoktelDecoder(mixer, soundType), @@ -705,8 +747,6 @@ bool PreIMDDecoder::loadStream(Common::SeekableReadStream *stream) { } void PreIMDDecoder::close() { - reset(); - CoktelDecoder::close(); delete _stream; @@ -1159,8 +1199,6 @@ bool IMDDecoder::loadFrameTables(uint32 framePosPos, uint32 frameCoordsPos) { } void IMDDecoder::close() { - reset(); - CoktelDecoder::close(); delete _stream; @@ -1225,8 +1263,6 @@ void IMDDecoder::processFrame() { _dirtyRects.clear(); - _paletteDirty = false; - uint32 cmd = 0; bool hasNextCmd = false; bool startSound = false; @@ -1273,7 +1309,7 @@ void IMDDecoder::processFrame() { // Set palette if (cmd == kCommandPalette) { _stream->skip(2); - + _paletteDirty = true; for (int i = 0; i < 768; i++) @@ -1322,7 +1358,7 @@ void IMDDecoder::processFrame() { // Start the audio stream if necessary if (startSound && _soundEnabled) { _mixer->playStream(_soundType, &_audioHandle, _audioStream, - -1, getVolume(), getBalance(), DisposeAfterUse::NO); + -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); _soundStage = kSoundPlaying; } @@ -1504,16 +1540,6 @@ Graphics::PixelFormat IMDDecoder::getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } -void IMDDecoder::updateVolume() { - if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) - g_system->getMixer()->setChannelVolume(_audioHandle, getVolume()); -} - -void IMDDecoder::updateBalance() { - if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) - g_system->getMixer()->setChannelBalance(_audioHandle, getBalance()); -} - VMDDecoder::File::File() { offset = 0; @@ -1552,7 +1578,7 @@ VMDDecoder::VMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : _soundLastFilledFrame(0), _audioFormat(kAudioFormat8bitRaw), _hasVideo(false), _videoCodec(0), _blitMode(0), _bytesPerPixel(0), _firstFramePos(0), _videoBufferSize(0), _externalCodec(false), _codec(0), - _subtitle(-1), _isPaletted(true) { + _subtitle(-1), _isPaletted(true), _autoStartSound(true) { _videoBuffer [0] = 0; _videoBuffer [1] = 0; @@ -2014,8 +2040,6 @@ bool VMDDecoder::readFiles() { } void VMDDecoder::close() { - reset(); - CoktelDecoder::close(); delete _stream; @@ -2095,7 +2119,6 @@ void VMDDecoder::processFrame() { _dirtyRects.clear(); - _paletteDirty = false; _subtitle = -1; bool startSound = false; @@ -2215,8 +2238,9 @@ void VMDDecoder::processFrame() { if (startSound && _soundEnabled) { if (_hasSound && _audioStream) { - _mixer->playStream(_soundType, &_audioHandle, _audioStream, - -1, getVolume(), getBalance(), DisposeAfterUse::NO); + if (_autoStartSound) + _mixer->playStream(_soundType, &_audioHandle, _audioStream, + -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); _soundStage = kSoundPlaying; } else _soundStage = kSoundNone; @@ -2742,14 +2766,92 @@ bool VMDDecoder::isPaletted() const { return _isPaletted; } -void VMDDecoder::updateVolume() { - if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) - g_system->getMixer()->setChannelVolume(_audioHandle, getVolume()); +void VMDDecoder::setAutoStartSound(bool autoStartSound) { + _autoStartSound = autoStartSound; +} + +AdvancedVMDDecoder::AdvancedVMDDecoder(Audio::Mixer::SoundType soundType) { + _decoder = new VMDDecoder(g_system->getMixer(), soundType); + _decoder->setAutoStartSound(false); +} + +AdvancedVMDDecoder::~AdvancedVMDDecoder() { + close(); + delete _decoder; +} + +bool AdvancedVMDDecoder::loadStream(Common::SeekableReadStream *stream) { + close(); + + if (!_decoder->loadStream(stream)) + return false; + + if (_decoder->hasVideo()) { + _videoTrack = new VMDVideoTrack(_decoder); + addTrack(_videoTrack); + } + + if (_decoder->hasSound()) { + _audioTrack = new VMDAudioTrack(_decoder); + addTrack(_audioTrack); + } + + return true; +} + +void AdvancedVMDDecoder::close() { + AdvancedVideoDecoder::close(); + _decoder->close(); +} + +AdvancedVMDDecoder::VMDVideoTrack::VMDVideoTrack(VMDDecoder *decoder) : _decoder(decoder) { +} + +uint16 AdvancedVMDDecoder::VMDVideoTrack::getWidth() const { + return _decoder->getWidth(); +} + +uint16 AdvancedVMDDecoder::VMDVideoTrack::getHeight() const { + return _decoder->getHeight(); +} + +Graphics::PixelFormat AdvancedVMDDecoder::VMDVideoTrack::getPixelFormat() const { + return _decoder->getPixelFormat(); +} + +int AdvancedVMDDecoder::VMDVideoTrack::getCurFrame() const { + return _decoder->getCurFrame(); +} + +int AdvancedVMDDecoder::VMDVideoTrack::getFrameCount() const { + return _decoder->getFrameCount(); +} + +const Graphics::Surface *AdvancedVMDDecoder::VMDVideoTrack::decodeNextFrame() { + return _decoder->decodeNextFrame(); +} + +const byte *AdvancedVMDDecoder::VMDVideoTrack::getPalette() const { + return _decoder->getPalette(); +} + +bool AdvancedVMDDecoder::VMDVideoTrack::hasDirtyPalette() const { + return _decoder->hasDirtyPalette(); +} + +Common::Rational AdvancedVMDDecoder::VMDVideoTrack::getFrameRate() const { + return _decoder->getFrameRate(); +} + +AdvancedVMDDecoder::VMDAudioTrack::VMDAudioTrack(VMDDecoder *decoder) : _decoder(decoder) { +} + +Audio::Mixer::SoundType AdvancedVMDDecoder::VMDAudioTrack::getSoundType() const { + return _decoder->_soundType; } -void VMDDecoder::updateBalance() { - if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) - g_system->getMixer()->setChannelBalance(_audioHandle, getBalance()); +Audio::AudioStream *AdvancedVMDDecoder::VMDAudioTrack::getAudioStream() const { + return _decoder->_audioStream; } } // End of namespace Video diff --git a/video/coktel_decoder.h b/video/coktel_decoder.h index c88d982191..117a55658f 100644 --- a/video/coktel_decoder.h +++ b/video/coktel_decoder.h @@ -64,7 +64,7 @@ class Codec; * - gob * - sci */ -class CoktelDecoder : public FixedRateVideoDecoder { +class CoktelDecoder { public: struct State { /** Set accordingly to what was done. */ @@ -77,7 +77,7 @@ public: CoktelDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); - ~CoktelDecoder(); + virtual ~CoktelDecoder(); /** Replace the current video stream with this identical one. */ virtual bool reloadStream(Common::SeekableReadStream *stream) = 0; @@ -138,21 +138,47 @@ public: /** Is the video paletted or true color? */ virtual bool isPaletted() const; + /** + * Get the current frame + * @see VideoDecoder::getCurFrame() + */ + int getCurFrame() const; - // VideoDecoder interface + /** + * Decode the next frame + * @see VideoDecoder::decodeNextFrame() + */ + virtual const Graphics::Surface *decodeNextFrame() = 0; + /** + * Load a video from a stream + * @see VideoDecoder::loadStream() + */ + virtual bool loadStream(Common::SeekableReadStream *stream) = 0; + + /** Has a video been loaded? */ + virtual bool isVideoLoaded() const = 0; + + /** Has the end of the video been reached? */ + bool endOfVideo() const; + + /** Close the video. */ void close(); uint16 getWidth() const; uint16 getHeight() const; + virtual Graphics::PixelFormat getPixelFormat() const = 0; uint32 getFrameCount() const; const byte *getPalette(); bool hasDirtyPalette() const; + uint32 getTimeToNextFrame() const; uint32 getStaticTimeToNextFrame() const; + void pauseVideo(bool pause); + protected: enum SoundStage { kSoundNone = 0, ///< No sound. @@ -186,8 +212,11 @@ protected: uint32 _features; + int32 _curFrame; uint32 _frameCount; + uint32 _startTime; + byte _palette[768]; bool _paletteDirty; @@ -208,6 +237,8 @@ protected: bool evaluateSeekFrame(int32 &frame, int whence) const; + Common::Rational getFrameRate() const; + // Surface management bool hasSurface(); void createSurface(); @@ -228,10 +259,9 @@ protected: // Sound helper functions inline void unsignedToSigned(byte *buffer, int length); - - // FixedRateVideoDecoder interface - - Common::Rational getFrameRate() const; +private: + uint32 _pauseStartTime; + bool _isPaused; }; class PreIMDDecoder : public CoktelDecoder { @@ -244,9 +274,6 @@ public: bool seek(int32 frame, int whence = SEEK_SET, bool restart = false); - - // VideoDecoder interface - bool loadStream(Common::SeekableReadStream *stream); void close(); @@ -279,9 +306,6 @@ public: void setXY(uint16 x, uint16 y); - - // VideoDecoder interface - bool loadStream(Common::SeekableReadStream *stream); void close(); @@ -291,11 +315,6 @@ public: Graphics::PixelFormat getPixelFormat() const; -protected: - // VideoDecoder API - void updateVolume(); - void updateBalance(); - private: enum Command { kCommandNextSound = 0xFF00, @@ -367,6 +386,8 @@ private: }; class VMDDecoder : public CoktelDecoder { +friend class AdvancedVMDDecoder; + public: VMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); ~VMDDecoder(); @@ -390,9 +411,6 @@ public: bool hasVideo() const; bool isPaletted() const; - - // VideoDecoder interface - bool loadStream(Common::SeekableReadStream *stream); void close(); @@ -403,9 +421,7 @@ public: Graphics::PixelFormat getPixelFormat() const; protected: - // VideoDecoder API - void updateVolume(); - void updateBalance(); + void setAutoStartSound(bool autoStartSound); private: enum PartType { @@ -478,6 +494,7 @@ private: uint32 _soundDataSize; uint32 _soundLastFilledFrame; AudioFormat _audioFormat; + bool _autoStartSound; // Video properties bool _hasVideo; @@ -532,6 +549,57 @@ private: bool getPartCoords(int16 frame, PartType type, int16 &x, int16 &y, int16 &width, int16 &height); }; +/** + * A wrapper around the VMD code that implements the AdvancedVideoDecoder + * API. + */ +class AdvancedVMDDecoder : public AdvancedVideoDecoder { +public: + AdvancedVMDDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); + ~AdvancedVMDDecoder(); + + bool loadStream(Common::SeekableReadStream *stream); + void close(); + +private: + class VMDVideoTrack : public FixedRateVideoTrack { + public: + VMDVideoTrack(VMDDecoder *decoder); + + uint16 getWidth() const; + uint16 getHeight() const; + Graphics::PixelFormat getPixelFormat() const; + int getCurFrame() const; + int getFrameCount() const; + const Graphics::Surface *decodeNextFrame(); + const byte *getPalette() const; + bool hasDirtyPalette() const; + + protected: + Common::Rational getFrameRate() const; + + private: + VMDDecoder *_decoder; + }; + + class VMDAudioTrack : public AudioTrack { + public: + VMDAudioTrack(VMDDecoder *decoder); + + Audio::Mixer::SoundType getSoundType() const; + + protected: + virtual Audio::AudioStream *getAudioStream() const; + + private: + VMDDecoder *_decoder; + }; + + VMDDecoder *_decoder; + VMDVideoTrack *_videoTrack; + VMDAudioTrack *_audioTrack; +}; + } // End of namespace Video #endif // VIDEO_COKTELDECODER_H |