aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Hoops2012-08-16 12:17:23 -0400
committerMatthew Hoops2012-08-16 12:17:23 -0400
commit7294a1cbcf1cf5e8c846faf8838e537bd8c638dc (patch)
tree37f8c97ba038b72744e8341f9b23add9fcd68281
parent92432a136bff7c327b5328cc10a84198f571b0d0 (diff)
downloadscummvm-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.cpp5
-rw-r--r--engines/sci/engine/kvideo.cpp7
-rw-r--r--video/coktel_decoder.cpp166
-rw-r--r--video/coktel_decoder.h116
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