[Scummvm-cvs-logs] SF.net SVN: scummvm:[51854] scummvm/trunk/graphics/video

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Sun Aug 8 02:36:19 CEST 2010


Revision: 51854
          http://scummvm.svn.sourceforge.net/scummvm/?rev=51854&view=rev
Author:   drmccoy
Date:     2010-08-08 00:36:19 +0000 (Sun, 08 Aug 2010)

Log Message:
-----------
VIDEO: Bare PreIMD decoding

Implemented bare PreIMD decoding using the new CoktelDecoder interface.
No fancy stuff yet, only basic vieo frames.

Modified Paths:
--------------
    scummvm/trunk/graphics/video/coktel_decoder.cpp
    scummvm/trunk/graphics/video/coktel_decoder.h

Modified: scummvm/trunk/graphics/video/coktel_decoder.cpp
===================================================================
--- scummvm/trunk/graphics/video/coktel_decoder.cpp	2010-08-08 00:35:50 UTC (rev 51853)
+++ scummvm/trunk/graphics/video/coktel_decoder.cpp	2010-08-08 00:36:19 UTC (rev 51854)
@@ -68,34 +68,193 @@
 
 
 PreIMDDecoder::PreIMDDecoder(uint16 width, uint16 height,
-	Audio::Mixer &mixer, Audio::Mixer::SoundType soundType) : CoktelDecoder(mixer, soundType) {
+	Audio::Mixer &mixer, Audio::Mixer::SoundType soundType) : CoktelDecoder(mixer, soundType),
+	_stream(0), _videoBuffer(0), _videoBufferSize(0) {
 
 	_width  = width;
 	_height = height;
 }
 
 PreIMDDecoder::~PreIMDDecoder() {
+	close();
 }
 
-bool PreIMDDecoder::seek(uint32 frame, int whence, bool restart) {
-	return false;
+bool PreIMDDecoder::seek(int32 frame, int whence, bool restart) {
+	if (!isVideoLoaded())
+		// Nothing to do
+		return false;
+
+	// Find the frame to which to seek
+	if      (whence == SEEK_CUR)
+		frame += _curFrame;
+	else if (whence == SEEK_END)
+		frame = _frameCount - frame - 1;
+	else if (whence == SEEK_SET)
+		frame--;
+	else
+		return false;
+
+	if ((frame < -1) || (((uint32) frame) >= _frameCount))
+		// Out of range
+		return false;
+
+	if (frame == _curFrame)
+		// Nothing to do
+		return true;
+
+	// Run through the frames
+	_curFrame = -1;
+	_stream->seek(2);
+	while (_curFrame != frame) {
+		uint16 frameSize = _stream->readUint16LE();
+
+		_stream->skip(frameSize + 2);
+
+		_curFrame++;
+	}
+
+	return true;
 }
 
 bool PreIMDDecoder::load(Common::SeekableReadStream &stream) {
-	return false;
+	// Since PreIMDs don't have any width and height values stored,
+	// we need them to be specified in the constructor
+	assert((_width > 0) && (_height > 0));
+
+	close();
+
+	_stream = &stream;
+
+	_stream->seek(0);
+
+	_frameCount = _stream->readUint16LE();
+
+	_surface.create(_width, _height, 1);
+
+	_videoBufferSize = _width * _height;
+	_videoBuffer     = new byte[_videoBufferSize];
+
+	memset(_videoBuffer, 0, _videoBufferSize);
+
+	return true;
 }
 
 void PreIMDDecoder::close() {
+	reset();
+
+	_surface.free();
+
+	delete _stream;
+
+	delete[] _videoBuffer;
+
+	_stream = 0;
+
+	_videoBuffer     = 0;
+	_videoBufferSize = 0;
 }
 
 bool PreIMDDecoder::isVideoLoaded() const {
-	return false;
+	return _stream != 0;
 }
 
 Surface *PreIMDDecoder::decodeNextFrame() {
-	return 0;
+	if (!isVideoLoaded() || endOfVideo())
+		return 0;
+
+	processFrame();
+	renderFrame();
+
+	_curFrame++;
+
+	return &_surface;
 }
 
+void PreIMDDecoder::processFrame() {
+	uint16 frameSize = _stream->readUint16LE();
+
+	uint32 nextFramePos = _stream->pos() + frameSize + 2;
+
+	byte cmd;
+
+	cmd = _stream->readByte();
+	frameSize--;
+
+	if (cmd == 0) {
+		// Palette. Ignored by Fascination, though
+
+		_stream->skip(768);
+
+		frameSize -= 769;
+
+		cmd = _stream->readByte();
+	}
+
+	if (cmd != 2) {
+		// Partial frame data
+
+		uint32 fSize   = frameSize;
+		uint32 vidSize = _videoBufferSize;
+
+		byte *vidBuffer = _videoBuffer;
+
+		while ((fSize > 0) && (vidSize > 0)) {
+			uint32 n = _stream->readByte();
+			fSize--;
+
+			if ((n & 0x80) != 0) {
+				// Data
+
+				n = MIN<uint32>((n & 0x7F) + 1, MIN(fSize, vidSize));
+
+				_stream->read(vidBuffer, n);
+
+				vidBuffer += n;
+				vidSize   -= n;
+				fSize     -= n;
+
+			} else {
+				// Skip
+
+				n = MIN<uint32>(n + 1, vidSize);
+
+				vidBuffer += n;
+				vidSize   -= n;
+			}
+		}
+
+	} else {
+		// Full direct frame
+
+		uint32 vidSize = MIN<uint32>(_videoBufferSize, frameSize);
+
+		_stream->read(_videoBuffer, vidSize);
+	}
+
+	_stream->seek(nextFramePos);
+}
+
+void PreIMDDecoder::renderFrame() {
+	uint16 w = MIN<uint16>(_surface.w, _width);
+	uint16 h = MIN<uint16>(_surface.h, _height);
+
+	const byte *src = _videoBuffer;
+	      byte *dst = (byte *) _surface.pixels; // + x/y
+
+	uint32 frameDataSize = _videoBufferSize;
+
+	while (h-- > 0) {
+		uint32 n = MIN<uint32>(w, frameDataSize);
+
+		memcpy(dst, src, n);
+
+		src += _width;
+		dst += _surface.pitch;
+
+		frameDataSize -= n;
+	}
+}
+
 PixelFormat PreIMDDecoder::getPixelFormat() const {
 	return PixelFormat::createFormatCLUT8();
 }

Modified: scummvm/trunk/graphics/video/coktel_decoder.h
===================================================================
--- scummvm/trunk/graphics/video/coktel_decoder.h	2010-08-08 00:35:50 UTC (rev 51853)
+++ scummvm/trunk/graphics/video/coktel_decoder.h	2010-08-08 00:36:19 UTC (rev 51854)
@@ -62,7 +62,7 @@
 			Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
 	~CoktelDecoder();
 
-	virtual bool seek(uint32 frame, int whence = SEEK_SET, bool restart = false) = 0;
+	virtual bool seek(int32 frame, int whence = SEEK_SET, bool restart = false) = 0;
 
 	// VideoDecoder interface
 
@@ -98,7 +98,7 @@
 			Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
 	~PreIMDDecoder();
 
-	bool seek(uint32 frame, int whence = SEEK_SET, bool restart = false);
+	bool seek(int32 frame, int whence = SEEK_SET, bool restart = false);
 
 	// VideoDecoder interface
 
@@ -110,6 +110,17 @@
 	Surface *decodeNextFrame();
 
 	PixelFormat getPixelFormat() const;
+
+private:
+	Common::SeekableReadStream *_stream;
+
+	byte  *_videoBuffer;
+	uint32 _videoBufferSize;
+
+	Surface _surface;
+
+	void processFrame();
+	void renderFrame();
 };
 
 } // 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