[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