[Scummvm-cvs-logs] SF.net SVN: scummvm:[51866] scummvm/trunk
drmccoy at users.sourceforge.net
drmccoy at users.sourceforge.net
Sun Aug 8 02:42:30 CEST 2010
Revision: 51866
http://scummvm.svn.sourceforge.net/scummvm/?rev=51866&view=rev
Author: drmccoy
Date: 2010-08-08 00:42:30 +0000 (Sun, 08 Aug 2010)
Log Message:
-----------
VIDEO/GOB: Implement IMD frame decoding
Rendering the frame video data is still stubbed out.
Modified Paths:
--------------
scummvm/trunk/engines/gob/videoplayer.cpp
scummvm/trunk/graphics/video/coktel_decoder.cpp
scummvm/trunk/graphics/video/coktel_decoder.h
Modified: scummvm/trunk/engines/gob/videoplayer.cpp
===================================================================
--- scummvm/trunk/engines/gob/videoplayer.cpp 2010-08-08 00:41:56 UTC (rev 51865)
+++ scummvm/trunk/engines/gob/videoplayer.cpp 2010-08-08 00:42:30 UTC (rev 51866)
@@ -365,7 +365,7 @@
_vm->_util->processInput();
if (_vm->shouldQuit()) {
- // video.decoder->disableSound();
+ video.decoder->disableSound();
properties.canceled = true;
return;
@@ -377,7 +377,7 @@
_vm->_inter->storeKey(_vm->_util->checkKey());
if (VAR(0) == (unsigned) properties.breakKey) {
- // video.decoder->disableSound();
+ video.decoder->disableSound();
// Seek to the last frame. Some scripts depend on that.
video.decoder->seek(properties.endFrame + 1, SEEK_SET, true);
@@ -571,12 +571,10 @@
}
void VideoPlayer::evalBgShading(Video &video) {
- /*
- if (video.isSoundPlaying())
+ if (video.decoder->isSoundPlaying())
_vm->_sound->bgShade();
else
_vm->_sound->bgUnshade();
- */
}
Common::String VideoPlayer::findFile(const Common::String &file, Properties &properties) {
Modified: scummvm/trunk/graphics/video/coktel_decoder.cpp
===================================================================
--- scummvm/trunk/graphics/video/coktel_decoder.cpp 2010-08-08 00:41:56 UTC (rev 51865)
+++ scummvm/trunk/graphics/video/coktel_decoder.cpp 2010-08-08 00:42:30 UTC (rev 51866)
@@ -206,7 +206,11 @@
return _frameRate;
}
+inline void CoktelDecoder::unsignedToSigned(byte *buffer, int length) {
+ while (length-- > 0) *buffer++ ^= 0x80;
+}
+
PreIMDDecoder::PreIMDDecoder(uint16 width, uint16 height,
Audio::Mixer &mixer, Audio::Mixer::SoundType soundType) : CoktelDecoder(mixer, soundType),
_stream(0), _videoBuffer(0), _videoBufferSize(0) {
@@ -638,8 +642,9 @@
_frameRate = Common::Rational(_soundFreq) / _soundSliceSize;
- _hasSound = true;
- _soundStage = kSoundLoaded;
+ _hasSound = true;
+ _soundEnabled = true;
+ _soundStage = kSoundLoaded;
_audioStream = Audio::makeQueuingAudioStream(_soundFreq, false);
}
@@ -737,20 +742,172 @@
}
void IMDDecoder::processFrame() {
+ _curFrame++;
- // TODO
+ _dirtyRects.clear();
- _curFrame++;
+ _paletteDirty = false;
+
+ uint32 cmd = 0;
+ bool hasNextCmd = false;
+ bool startSound = false;
+
+ do {
+ calcFrameCoords(_curFrame);
+
+ cmd = _stream->readUint16LE();
+
+ if ((cmd & kCommandBreakMask) == kCommandBreak) {
+ // Flow control
+
+ if (cmd == kCommandBreak) {
+ _stream->skip(2);
+ cmd = _stream->readUint16LE();
+ }
+
+ // Break
+ if (cmd == kCommandBreakSkip0) {
+ continue;
+ } else if (cmd == kCommandBreakSkip16) {
+ cmd = _stream->readUint16LE();
+ _stream->skip(cmd);
+ continue;
+ } else if (cmd == kCommandBreakSkip32) {
+ cmd = _stream->readUint32LE();
+ _stream->skip(cmd);
+ continue;
+ }
+ }
+
+ // Audio
+ if (_soundStage != kSoundNone) {
+ if (cmd == kCommandNextSound) {
+
+ nextSoundSlice(hasNextCmd);
+ cmd = _stream->readUint16LE();
+
+ } else if (cmd == kCommandStartSound) {
+
+ startSound = initialSoundSlice(hasNextCmd);
+ cmd = _stream->readUint16LE();
+
+ } else
+ emptySoundSlice(hasNextCmd);
+ }
+
+ // Set palette
+ if (cmd == kCommandPalette) {
+ _stream->skip(2);
+
+ _paletteDirty = true;
+
+ _stream->read(_palette, 768);
+ cmd = _stream->readUint16LE();
+ }
+
+ hasNextCmd = false;
+
+ if (cmd == kCommandJump) {
+ // Jump to frame
+
+ int16 frame = _stream->readSint16LE();
+ if (_framePos) {
+ _curFrame = frame - 1;
+ _stream->seek(_framePos[frame]);
+
+ hasNextCmd = true;
+ }
+
+ } else if (cmd == kCommandVideoData) {
+ videoData(_stream->readUint32LE() + 2);
+
+ } else if (cmd != 0)
+ videoData(cmd + 2);
+ else
+ _dirtyRects.pop_back();
+
+ } while (hasNextCmd);
+
+ if (startSound && _soundEnabled) {
+ _mixer->playStream(_soundType, &_audioHandle, _audioStream);
+ _soundStage = kSoundPlaying;
+ }
+
+ if ((_curFrame >= (int32)(_frameCount - 1)) && (_soundStage == kSoundPlaying)) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ _audioStream = 0;
+ _soundStage = kSoundNone;
+ }
+
}
+void IMDDecoder::calcFrameCoords(uint32 frame) {
+ if (frame == 0)
+ _dirtyRects.push_back(Common::Rect(_x, _y, _x + _width, _y + _height));
+ else if (_frameCoords && ((_frameCoords[frame].left != -1)))
+ _dirtyRects.push_back(Common::Rect(_frameCoords[frame].left , _frameCoords[frame].top,
+ _frameCoords[frame].right + 1, _frameCoords[frame].bottom + 1));
+ else if (_stdX != -1)
+ _dirtyRects.push_back(Common::Rect(_stdX, _stdY, _stdX + _stdWidth, _stdY + _stdHeight));
+ else
+ _dirtyRects.push_back(Common::Rect(_x, _y, _x + _width, _y + _height));
+}
+
+void IMDDecoder::videoData(uint32 size) {
+ _stream->read(_frameData, size);
+ _frameDataLen = size;
+
+ renderFrame();
+}
+
void IMDDecoder::renderFrame() {
- _dirtyRects.clear();
-
// TODO
+}
- _dirtyRects.push_back(Common::Rect(_x, _y, _x + _width, _y + _height));
+void IMDDecoder::nextSoundSlice(bool hasNextCmd) {
+ if (hasNextCmd || !_soundEnabled) {
+ _stream->skip(_soundSliceSize);
+ return;
+ }
+
+ byte *soundBuf = (byte *)malloc(_soundSliceSize);
+
+ _stream->read(soundBuf, _soundSliceSize);
+ unsignedToSigned(soundBuf, _soundSliceSize);
+
+ _audioStream->queueBuffer(soundBuf, _soundSliceSize, DisposeAfterUse::YES, 0);
}
+bool IMDDecoder::initialSoundSlice(bool hasNextCmd) {
+ int dataLength = _soundSliceSize * _soundSlicesCount;
+
+ if (hasNextCmd || !_soundEnabled) {
+ _stream->skip(dataLength);
+ return false;
+ }
+
+ byte *soundBuf = (byte *)malloc(dataLength);
+
+ _stream->read(soundBuf, dataLength);
+ unsignedToSigned(soundBuf, dataLength);
+
+ _audioStream->queueBuffer(soundBuf, dataLength, DisposeAfterUse::YES, 0);
+
+ return _soundStage == kSoundLoaded;
+}
+
+void IMDDecoder::emptySoundSlice(bool hasNextCmd) {
+ if (hasNextCmd || !_soundEnabled)
+ return;
+
+ byte *soundBuf = (byte *)malloc(_soundSliceSize);
+
+ memset(soundBuf, 0, _soundSliceSize);
+
+ _audioStream->queueBuffer(soundBuf, _soundSliceSize, DisposeAfterUse::YES, 0);
+}
+
PixelFormat IMDDecoder::getPixelFormat() const {
return PixelFormat::createFormatCLUT8();
}
Modified: scummvm/trunk/graphics/video/coktel_decoder.h
===================================================================
--- scummvm/trunk/graphics/video/coktel_decoder.h 2010-08-08 00:41:56 UTC (rev 51865)
+++ scummvm/trunk/graphics/video/coktel_decoder.h 2010-08-08 00:42:30 UTC (rev 51866)
@@ -159,6 +159,8 @@
void createSurface();
void freeSurface();
+ inline void unsignedToSigned(byte *buffer, int length);
+
// FixedRateVideoDecoder interface
Common::Rational getFrameRate() const;
};
@@ -273,7 +275,15 @@
bool loadFrameTables(uint32 framePosPos, uint32 frameCoordsPos);
void processFrame();
+
+ void calcFrameCoords(uint32 frame);
+
+ void videoData(uint32 size);
void renderFrame();
+
+ void nextSoundSlice(bool hasNextCmd);
+ bool initialSoundSlice(bool hasNextCmd);
+ void emptySoundSlice(bool hasNextCmd);
};
} // End of namespace Graphics
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list