[Scummvm-cvs-logs] SF.net SVN: scummvm:[49165] scummvm/trunk
mthreepwood at users.sourceforge.net
mthreepwood at users.sourceforge.net
Sun May 23 20:33:55 CEST 2010
Revision: 49165
http://scummvm.svn.sourceforge.net/scummvm/?rev=49165&view=rev
Author: mthreepwood
Date: 2010-05-23 18:33:55 +0000 (Sun, 23 May 2010)
Log Message:
-----------
Move Mohawk's QuickTime code to graphics/ (and QDM2 to sound, disabled when Mohawk is not enabled) so SCI can use the code.
Modified Paths:
--------------
scummvm/trunk/engines/mohawk/console.cpp
scummvm/trunk/engines/mohawk/graphics.cpp
scummvm/trunk/engines/mohawk/graphics.h
scummvm/trunk/engines/mohawk/module.mk
scummvm/trunk/engines/mohawk/mohawk.cpp
scummvm/trunk/engines/mohawk/myst.cpp
scummvm/trunk/engines/mohawk/myst_pict.cpp
scummvm/trunk/engines/mohawk/myst_pict.h
scummvm/trunk/engines/mohawk/myst_scripts.cpp
scummvm/trunk/engines/mohawk/riven.cpp
scummvm/trunk/engines/mohawk/riven_external.cpp
scummvm/trunk/engines/mohawk/riven_scripts.cpp
scummvm/trunk/graphics/conversion.h
scummvm/trunk/graphics/module.mk
scummvm/trunk/graphics/video/avi_decoder.cpp
scummvm/trunk/sound/module.mk
Added Paths:
-----------
scummvm/trunk/engines/mohawk/video.cpp
scummvm/trunk/engines/mohawk/video.h
scummvm/trunk/graphics/video/codecs/cinepak.cpp
scummvm/trunk/graphics/video/codecs/cinepak.h
scummvm/trunk/graphics/video/codecs/mjpeg.cpp
scummvm/trunk/graphics/video/codecs/mjpeg.h
scummvm/trunk/graphics/video/codecs/qtrle.cpp
scummvm/trunk/graphics/video/codecs/qtrle.h
scummvm/trunk/graphics/video/codecs/rpza.cpp
scummvm/trunk/graphics/video/codecs/rpza.h
scummvm/trunk/graphics/video/codecs/smc.cpp
scummvm/trunk/graphics/video/codecs/smc.h
scummvm/trunk/graphics/video/qt_decoder.cpp
scummvm/trunk/graphics/video/qt_decoder.h
scummvm/trunk/sound/decoders/qdm2.cpp
scummvm/trunk/sound/decoders/qdm2.h
scummvm/trunk/sound/decoders/qdm2data.h
Removed Paths:
-------------
scummvm/trunk/engines/mohawk/jpeg.cpp
scummvm/trunk/engines/mohawk/jpeg.h
scummvm/trunk/engines/mohawk/video/
Modified: scummvm/trunk/engines/mohawk/console.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/console.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/console.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -30,7 +30,7 @@
#include "mohawk/riven.h"
#include "mohawk/livingbooks.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
namespace Mohawk {
Modified: scummvm/trunk/engines/mohawk/graphics.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/graphics.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/graphics.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -78,8 +78,7 @@
error("Myst requires greater than 256 colors to run");
if (_vm->getFeatures() & GF_ME) {
- // We want to delete our own JPEG surfaces, so don't free after use.
- _jpegDecoder = new JPEGDecoder(false);
+ _jpegDecoder = new Graphics::JPEGDecoder();
_pictDecoder = new MystPICT(_jpegDecoder);
} else {
_jpegDecoder = NULL;
@@ -152,9 +151,10 @@
if (_vm->getFeatures() & GF_ME && _vm->getPlatform() == Common::kPlatformMacintosh && _pictureFile.picFile.isOpen()) {
for (uint32 i = 0; i < _pictureFile.pictureCount; i++)
if (_pictureFile.entries[i].id == image) {
- if (_pictureFile.entries[i].type == 0)
- surface = _jpegDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
- else if (_pictureFile.entries[i].type == 1)
+ if (_pictureFile.entries[i].type == 0) {
+ Graphics::Surface *jpegSurface = _jpegDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
+ surface->copyFrom(*jpegSurface);
+ } else if (_pictureFile.entries[i].type == 1)
surface = _pictDecoder->decodeImage(new Common::SeekableSubReadStream(&_pictureFile.picFile, _pictureFile.entries[i].offset, _pictureFile.entries[i].offset + _pictureFile.entries[i].size));
else
error ("Unknown Picture File type %d", _pictureFile.entries[i].type);
Modified: scummvm/trunk/engines/mohawk/graphics.h
===================================================================
--- scummvm/trunk/engines/mohawk/graphics.h 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/graphics.h 2010-05-23 18:33:55 UTC (rev 49165)
@@ -27,11 +27,11 @@
#define MOHAWK_GRAPHICS_H
#include "mohawk/bitmap.h"
-#include "mohawk/jpeg.h"
#include "mohawk/livingbooks.h"
#include "mohawk/myst_pict.h"
#include "common/file.h"
+#include "graphics/video/codecs/mjpeg.h"
namespace Mohawk {
@@ -96,8 +96,8 @@
void loadExternalPictureFile(uint16 stack);
void copyImageSectionToScreen(uint16 image, Common::Rect src, Common::Rect dest);
void copyImageToScreen(uint16 image, Common::Rect dest);
- void showCursor(void);
- void hideCursor(void);
+ void showCursor();
+ void hideCursor();
void changeCursor(uint16);
void drawRect(Common::Rect rect, bool active);
@@ -105,7 +105,7 @@
MohawkEngine_Myst *_vm;
MystBitmap *_bmpDecoder;
MystPICT *_pictDecoder;
- JPEGDecoder *_jpegDecoder;
+ Graphics::JPEGDecoder *_jpegDecoder;
Graphics::PixelFormat _pixelFormat;
struct PictureFile {
Deleted: scummvm/trunk/engines/mohawk/jpeg.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/jpeg.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/jpeg.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -1,87 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/system.h"
-#include "graphics/conversion.h" // For YUV2RGB
-
-#include "mohawk/jpeg.h"
-
-namespace Mohawk {
-
-JPEGDecoder::JPEGDecoder(bool freeSurfaceAfterUse) : Graphics::Codec(), _freeSurfaceAfterUse(freeSurfaceAfterUse) {
- _jpeg = new Graphics::JPEG();
- _pixelFormat = g_system->getScreenFormat();
- _surface = NULL;
-}
-
-JPEGDecoder::~JPEGDecoder() {
- delete _jpeg;
-
- if (_surface) {
- _surface->free();
- delete _surface;
- }
-}
-
-Graphics::Surface *JPEGDecoder::decodeImage(Common::SeekableReadStream* stream) {
- _jpeg->read(stream);
- Graphics::Surface *ySurface = _jpeg->getComponent(1);
- Graphics::Surface *uSurface = _jpeg->getComponent(2);
- Graphics::Surface *vSurface = _jpeg->getComponent(3);
-
- Graphics::Surface *destSurface = NULL;
-
- // If we should free the surface after use, use the internal _surface storage
- // (this should be used when using as a Codec, as the Codecs should free their
- // surfaces when deleting the Codec object). Otherwise, create a new Surface
- // as the destination.
- if (_freeSurfaceAfterUse) {
- if (!_surface) {
- _surface = new Graphics::Surface();
- _surface->create(ySurface->w, ySurface->h, _pixelFormat.bytesPerPixel);
- }
- destSurface = _surface;
- } else {
- destSurface = new Graphics::Surface();
- destSurface->create(ySurface->w, ySurface->h, _pixelFormat.bytesPerPixel);
- }
-
- assert(destSurface);
-
- for (uint16 i = 0; i < destSurface->h; i++) {
- for (uint16 j = 0; j < destSurface->w; j++) {
- byte r = 0, g = 0, b = 0;
- Graphics::YUV2RGB(*((byte *)ySurface->getBasePtr(j, i)), *((byte *)uSurface->getBasePtr(j, i)), *((byte *)vSurface->getBasePtr(j, i)), r, g, b);
- if (_pixelFormat.bytesPerPixel == 2)
- *((uint16 *)destSurface->getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
- else
- *((uint32 *)destSurface->getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
- }
- }
-
- return destSurface;
-}
-
-} // End of namespace Mohawk
Deleted: scummvm/trunk/engines/mohawk/jpeg.h
===================================================================
--- scummvm/trunk/engines/mohawk/jpeg.h 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/jpeg.h 2010-05-23 18:33:55 UTC (rev 49165)
@@ -1,59 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef MOHAWK_JPEG_H
-#define MOHAWK_JPEG_H
-
-#include "common/scummsys.h"
-#include "common/stream.h"
-
-#include "graphics/video/codecs/codec.h"
-#include "graphics/jpeg.h"
-#include "graphics/pixelformat.h"
-
-namespace Mohawk {
-
-// Mohawk's JPEG Decoder
-// Basically a wrapper around JPEG which converts to RGB and also functions
-// as a Codec.
-
-class JPEGDecoder : public Graphics::Codec {
-public:
- JPEGDecoder(bool freeSurfaceAfterUse);
- ~JPEGDecoder();
-
- Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
- Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
-
-private:
- Graphics::PixelFormat _pixelFormat;
- Graphics::JPEG *_jpeg;
- Graphics::Surface *_surface;
- bool _freeSurfaceAfterUse;
-};
-
-} // End of namespace Mohawk
-
-#endif
Modified: scummvm/trunk/engines/mohawk/module.mk
===================================================================
--- scummvm/trunk/engines/mohawk/module.mk 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/module.mk 2010-05-23 18:33:55 UTC (rev 49165)
@@ -6,7 +6,6 @@
detection.o \
dialogs.o \
graphics.o \
- jpeg.o \
livingbooks.o \
mohawk.o \
myst.o \
@@ -22,13 +21,7 @@
riven_scripts.o \
riven_vars.o \
sound.o \
- video/cinepak.o \
- video/qdm2.o \
- video/qtrle.o \
- video/qt_player.o \
- video/rpza.o \
- video/smc.o \
- video/video.o
+ video.o
# This module can be built as a plugin
Modified: scummvm/trunk/engines/mohawk/mohawk.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/mohawk.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/mohawk.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -35,7 +35,7 @@
#include "mohawk/mohawk.h"
#include "mohawk/dialogs.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "sound/mixer.h"
Modified: scummvm/trunk/engines/mohawk/myst.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/myst.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/myst.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -33,7 +33,7 @@
#include "mohawk/dialogs.h"
#include "mohawk/resource.h"
#include "mohawk/resource_cache.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
namespace Mohawk {
Modified: scummvm/trunk/engines/mohawk/myst_pict.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/myst_pict.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/myst_pict.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -32,7 +32,7 @@
// The PICT code is based off of the QuickDraw specs:
// http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-461.html
-MystPICT::MystPICT(JPEGDecoder *jpegDecoder) {
+MystPICT::MystPICT(Graphics::JPEGDecoder *jpegDecoder) {
_jpegDecoder = jpegDecoder;
_pixelFormat = g_system->getScreenFormat();
}
@@ -264,9 +264,6 @@
stream->seek(startPos + dataSize);
image->copyFrom(*jpegImage);
-
- jpegImage->free();
- delete jpegImage;
}
} // End of namespace Mohawk
Modified: scummvm/trunk/engines/mohawk/myst_pict.h
===================================================================
--- scummvm/trunk/engines/mohawk/myst_pict.h 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/myst_pict.h 2010-05-23 18:33:55 UTC (rev 49165)
@@ -32,18 +32,18 @@
#include "graphics/pixelformat.h"
#include "graphics/surface.h"
-#include "mohawk/jpeg.h"
+#include "graphics/video/codecs/mjpeg.h"
namespace Mohawk {
class MystPICT {
public:
- MystPICT(JPEGDecoder *jpegDecoder);
+ MystPICT(Graphics::JPEGDecoder *jpegDecoder);
~MystPICT() {}
Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
private:
- JPEGDecoder *_jpegDecoder;
+ Graphics::JPEGDecoder *_jpegDecoder;
Common::Rect _imageRect;
Graphics::PixelFormat _pixelFormat;
Modified: scummvm/trunk/engines/mohawk/myst_scripts.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/myst_scripts.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/myst_scripts.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -27,7 +27,7 @@
#include "mohawk/graphics.h"
#include "mohawk/myst_scripts.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "gui/message.h"
Modified: scummvm/trunk/engines/mohawk/riven.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/riven.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/riven.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -33,7 +33,7 @@
#include "mohawk/riven_external.h"
#include "mohawk/riven_saveload.h"
#include "mohawk/dialogs.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
namespace Mohawk {
Modified: scummvm/trunk/engines/mohawk/riven_external.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/riven_external.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/riven_external.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -27,7 +27,7 @@
#include "mohawk/riven.h"
#include "mohawk/riven_external.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "gui/message.h"
#include "common/events.h"
Modified: scummvm/trunk/engines/mohawk/riven_scripts.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/riven_scripts.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/engines/mohawk/riven_scripts.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -28,7 +28,7 @@
#include "mohawk/riven_external.h"
#include "mohawk/riven_scripts.h"
#include "mohawk/sound.h"
-#include "mohawk/video/video.h"
+#include "mohawk/video.h"
#include "common/stream.h"
#include "graphics/cursorman.h"
Copied: scummvm/trunk/engines/mohawk/video.cpp (from rev 49161, scummvm/trunk/engines/mohawk/video/video.cpp)
===================================================================
--- scummvm/trunk/engines/mohawk/video.cpp (rev 0)
+++ scummvm/trunk/engines/mohawk/video.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,377 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "mohawk/resource.h"
+#include "mohawk/video.h"
+
+#include "common/events.h"
+#include "graphics/video/qt_decoder.h"
+
+namespace Mohawk {
+
+VideoManager::VideoManager(MohawkEngine* vm) : _vm(vm) {
+}
+
+VideoManager::~VideoManager() {
+ _mlstRecords.clear();
+ stopVideos();
+}
+
+void VideoManager::pauseVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ _videoStreams[i]->pauseVideo(true);
+}
+
+void VideoManager::resumeVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ _videoStreams[i]->pauseVideo(false);
+}
+
+void VideoManager::stopVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ delete _videoStreams[i].video;
+ _videoStreams.clear();
+}
+
+void VideoManager::playMovie(Common::String filename, uint16 x, uint16 y, bool clearScreen) {
+ VideoHandle videoHandle = createVideoHandle(filename, x, y, false);
+ if (videoHandle == NULL_VID_HANDLE)
+ return;
+
+ // Clear screen if requested
+ if (clearScreen) {
+ _vm->_system->fillScreen(_vm->_system->getScreenFormat().RGBToColor(0, 0, 0));
+ _vm->_system->updateScreen();
+ }
+
+ waitUntilMovieEnds(videoHandle);
+}
+
+void VideoManager::playMovieCentered(Common::String filename, bool clearScreen) {
+ VideoHandle videoHandle = createVideoHandle(filename, 0, 0, false);
+ if (videoHandle == NULL_VID_HANDLE)
+ return;
+
+ // Clear screen if requested
+ if (clearScreen) {
+ _vm->_system->fillScreen(_vm->_system->getScreenFormat().RGBToColor(0, 0, 0));
+ _vm->_system->updateScreen();
+ }
+
+ _videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2;
+ _videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2;
+
+ waitUntilMovieEnds(videoHandle);
+}
+
+void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) {
+ bool continuePlaying = true;
+
+ while (!_videoStreams[videoHandle]->endOfVideo() && !_vm->shouldQuit() && continuePlaying) {
+ if (updateBackgroundMovies())
+ _vm->_system->updateScreen();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_RTL:
+ case Common::EVENT_QUIT:
+ continuePlaying = false;
+ break;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_SPACE:
+ _vm->pauseGame();
+ break;
+ case Common::KEYCODE_ESCAPE:
+ continuePlaying = false;
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ // Cut down on CPU usage
+ _vm->_system->delayMillis(10);
+ }
+
+ _videoStreams[videoHandle]->close();
+ _videoStreams.clear();
+}
+
+void VideoManager::playBackgroundMovie(Common::String filename, int16 x, int16 y, bool loop) {
+ VideoHandle videoHandle = createVideoHandle(filename, x, y, loop);
+ if (videoHandle == NULL_VID_HANDLE)
+ return;
+
+ // Center x if requested
+ if (x < 0)
+ _videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2;
+
+ // Center y if requested
+ if (y < 0)
+ _videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2;
+}
+
+bool VideoManager::updateBackgroundMovies() {
+ bool updateScreen = false;
+
+ for (uint32 i = 0; i < _videoStreams.size() && !_vm->shouldQuit(); i++) {
+ // Skip deleted videos
+ if (!_videoStreams[i].video)
+ continue;
+
+ // Remove any videos that are over
+ if (_videoStreams[i]->endOfVideo()) {
+ if (_videoStreams[i].loop) {
+ _videoStreams[i]->rewind();
+ } else {
+ delete _videoStreams[i].video;
+ memset(&_videoStreams[i], 0, sizeof(VideoEntry));
+ _videoStreams[i].video = NULL;
+ continue;
+ }
+ }
+
+ // Check if we need to draw a frame
+ if (_videoStreams[i]->needsUpdate()) {
+ Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame();
+ bool deleteFrame = false;
+
+ if (frame && _videoStreams[i].enabled) {
+ // Convert from 8bpp to the current screen format if necessary
+ if (frame->bytesPerPixel == 1) {
+ Graphics::Surface *newFrame = new Graphics::Surface();
+ Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();
+ byte *palette = _videoStreams[i]->getPalette();
+ assert(palette);
+
+ newFrame->create(frame->w, frame->h, pixelFormat.bytesPerPixel);
+
+ for (uint16 j = 0; j < frame->h; j++) {
+ for (uint16 k = 0; k < frame->w; k++) {
+ byte palIndex = *((byte *)frame->getBasePtr(k, j));
+ byte r = palette[palIndex * 3];
+ byte g = palette[palIndex * 3 + 1];
+ byte b = palette[palIndex * 3 + 2];
+ if (pixelFormat.bytesPerPixel == 2)
+ *((uint16 *)newFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
+ else
+ *((uint32 *)newFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
+ }
+ }
+
+ frame = newFrame;
+ deleteFrame = true;
+ }
+
+ // Clip the width/height to make sure we stay on the screen (Myst does this a few times)
+ uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x);
+ uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y);
+ _vm->_system->copyRectToScreen((byte*)frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);
+
+ // We've drawn something to the screen, make sure we update it
+ updateScreen = true;
+
+ // Delete the frame if we're using the buffer from the 8bpp conversion
+ if (deleteFrame) {
+ frame->free();
+ delete frame;
+ }
+ }
+ }
+
+ // Update the audio buffer too
+ _videoStreams[i]->updateAudioBuffer();
+ }
+
+ // Return true if we need to update the screen
+ return updateScreen;
+}
+
+void VideoManager::activateMLST(uint16 mlstId, uint16 card) {
+ Common::SeekableReadStream *mlstStream = _vm->getRawData(ID_MLST, card);
+ uint16 recordCount = mlstStream->readUint16BE();
+
+ for (uint16 i = 0; i < recordCount; i++) {
+ MLSTRecord mlstRecord;
+ mlstRecord.index = mlstStream->readUint16BE();
+ mlstRecord.movieID = mlstStream->readUint16BE();
+ mlstRecord.code = mlstStream->readUint16BE();
+ mlstRecord.left = mlstStream->readUint16BE();
+ mlstRecord.top = mlstStream->readUint16BE();
+
+ for (byte j = 0; j < 2; j++)
+ if (mlstStream->readUint16BE() != 0)
+ warning("u0[%d] in MLST non-zero", j);
+
+ if (mlstStream->readUint16BE() != 0xFFFF)
+ warning("u0[2] in MLST not 0xFFFF");
+
+ mlstRecord.loop = mlstStream->readUint16BE();
+ mlstRecord.volume = mlstStream->readUint16BE();
+ mlstRecord.u1 = mlstStream->readUint16BE();
+
+ if (mlstRecord.u1 != 1)
+ warning("mlstRecord.u1 not 1");
+
+ if (mlstRecord.index == mlstId) {
+ _mlstRecords.push_back(mlstRecord);
+ break;
+ }
+ }
+
+ delete mlstStream;
+}
+
+void VideoManager::playMovie(uint16 id) {
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id) {
+ debug(1, "Play tMOV %d (non-blocking) at (%d, %d) %s", _mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].loop != 0 ? "looping" : "non-looping");
+ createVideoHandle(_mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].loop != 0);
+ return;
+ }
+}
+
+void VideoManager::playMovieBlocking(uint16 id) {
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id) {
+ debug(1, "Play tMOV %d (blocking) at (%d, %d)", _mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top);
+ VideoHandle videoHandle = createVideoHandle(_mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, false);
+ waitUntilMovieEnds(videoHandle);
+ return;
+ }
+}
+
+void VideoManager::stopMovie(uint16 id) {
+ debug(2, "Stopping movie %d", id);
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_mlstRecords[i].movieID == _videoStreams[j].id) {
+ delete _videoStreams[i].video;
+ memset(&_videoStreams[i].video, 0, sizeof(VideoEntry));
+ return;
+ }
+}
+
+void VideoManager::enableMovie(uint16 id) {
+ debug(2, "Enabling movie %d", id);
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_mlstRecords[i].movieID == _videoStreams[j].id) {
+ _videoStreams[j].enabled = true;
+ return;
+ }
+}
+
+void VideoManager::disableMovie(uint16 id) {
+ debug(2, "Disabling movie %d", id);
+ for (uint16 i = 0; i < _mlstRecords.size(); i++)
+ if (_mlstRecords[i].code == id)
+ for (uint16 j = 0; j < _videoStreams.size(); j++)
+ if (_mlstRecords[i].movieID == _videoStreams[j].id) {
+ _videoStreams[j].enabled = false;
+ return;
+ }
+}
+
+void VideoManager::disableAllMovies() {
+ debug(2, "Disabling all movies");
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ _videoStreams[i].enabled = false;
+}
+
+VideoHandle VideoManager::createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop) {
+ // First, check to see if that video is already playing
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].id == id)
+ return i;
+
+ // Otherwise, create a new entry
+ VideoEntry entry;
+ entry.video = new Graphics::QuickTimeDecoder();
+ entry.x = x;
+ entry.y = y;
+ entry.filename = "";
+ entry.id = id;
+ entry.loop = loop;
+ entry.enabled = true;
+ entry->setChunkBeginOffset(_vm->getResourceOffset(ID_TMOV, id));
+ entry->load(*_vm->getRawData(ID_TMOV, id));
+
+ // Search for any deleted videos so we can take a formerly used slot
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (!_videoStreams[i].video) {
+ _videoStreams[i] = entry;
+ return i;
+ }
+
+ // Otherwise, just add it to the list
+ _videoStreams.push_back(entry);
+ return _videoStreams.size() - 1;
+}
+
+VideoHandle VideoManager::createVideoHandle(Common::String filename, uint16 x, uint16 y, bool loop) {
+ // First, check to see if that video is already playing
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].filename == filename)
+ return i;
+
+ // Otherwise, create a new entry
+ VideoEntry entry;
+ entry.video = new Graphics::QuickTimeDecoder();
+ entry.x = x;
+ entry.y = y;
+ entry.filename = filename;
+ entry.id = 0;
+ entry.loop = loop;
+ entry.enabled = true;
+
+ Common::File *file = new Common::File();
+ if (!file->open(filename)) {
+ delete file;
+ return NULL_VID_HANDLE;
+ }
+
+ entry->load(*file);
+
+ // Search for any deleted videos so we can take a formerly used slot
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (!_videoStreams[i].video) {
+ _videoStreams[i] = entry;
+ return i;
+ }
+
+ // Otherwise, just add it to the list
+ _videoStreams.push_back(entry);
+ return _videoStreams.size() - 1;
+}
+
+} // End of namespace Mohawk
Copied: scummvm/trunk/engines/mohawk/video.h (from rev 49161, scummvm/trunk/engines/mohawk/video/video.h)
===================================================================
--- scummvm/trunk/engines/mohawk/video.h (rev 0)
+++ scummvm/trunk/engines/mohawk/video.h 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,109 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MOHAWK_VIDEO_H
+#define MOHAWK_VIDEO_H
+
+#include "graphics/pixelformat.h"
+
+namespace Graphics {
+ class QuickTimeDecoder;
+}
+
+namespace Mohawk {
+
+class MohawkEngine;
+
+struct MLSTRecord {
+ uint16 index;
+ uint16 movieID;
+ uint16 code;
+ uint16 left;
+ uint16 top;
+ uint16 u0[3];
+ uint16 loop;
+ uint16 volume;
+ uint16 u1;
+};
+
+struct VideoEntry {
+ Graphics::QuickTimeDecoder *video;
+ uint16 x;
+ uint16 y;
+ bool loop;
+ Common::String filename;
+ uint16 id; // Riven only
+ bool enabled;
+
+ Graphics::QuickTimeDecoder *operator->() const { assert(video); return video; }
+};
+
+typedef int32 VideoHandle;
+
+enum {
+ NULL_VID_HANDLE = -1
+};
+
+class VideoManager {
+public:
+ VideoManager(MohawkEngine *vm);
+ ~VideoManager();
+
+ // Generic movie functions
+ void playMovie(Common::String filename, uint16 x = 0, uint16 y = 0, bool clearScreen = false);
+ void playMovieCentered(Common::String filename, bool clearScreen = true);
+ void playBackgroundMovie(Common::String filename, int16 x = -1, int16 y = -1, bool loop = false);
+ bool updateBackgroundMovies();
+ void pauseVideos();
+ void resumeVideos();
+ void stopVideos();
+
+ // Riven-related functions
+ void activateMLST(uint16 mlstId, uint16 card);
+ void enableMovie(uint16 id);
+ void disableMovie(uint16 id);
+ void disableAllMovies();
+ void playMovie(uint16 id);
+ void stopMovie(uint16 id);
+ void playMovieBlocking(uint16 id);
+
+ // Riven-related variables
+ Common::Array<MLSTRecord> _mlstRecords;
+
+private:
+ MohawkEngine *_vm;
+
+ void waitUntilMovieEnds(VideoHandle videoHandle);
+
+ // Keep tabs on any videos playing
+ Common::Array<VideoEntry> _videoStreams;
+
+ VideoHandle createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop);
+ VideoHandle createVideoHandle(Common::String filename, uint16 x, uint16 y, bool loop);
+};
+
+} // End of namespace Mohawk
+
+#endif
Modified: scummvm/trunk/graphics/conversion.h
===================================================================
--- scummvm/trunk/graphics/conversion.h 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/graphics/conversion.h 2010-05-23 18:33:55 UTC (rev 49165)
@@ -45,13 +45,6 @@
v = CLIP<int>( ((r * 512) >> 10) - ((g * 429) >> 10) - ((b * 83) >> 10) + 128, 0, 255);
}
-/** Converting a color from YUV to RGB colorspace, Cinepak style. */
-inline static void CPYUV2RGB(byte y, byte u, byte v, byte &r, byte &g, byte &b) {
- r = CLIP<int>(y + 2 * (v - 128), 0, 255);
- g = CLIP<int>(y - (u - 128) / 2 - (v - 128), 0, 255);
- b = CLIP<int>(y + 2 * (u - 128), 0, 255);
-}
-
// TODO: generic YUV to RGB blit
/**
Modified: scummvm/trunk/graphics/module.mk
===================================================================
--- scummvm/trunk/graphics/module.mk 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/graphics/module.mk 2010-05-23 18:33:55 UTC (rev 49165)
@@ -25,10 +25,16 @@
video/dxa_decoder.o \
video/flic_decoder.o \
video/mpeg_player.o \
+ video/qt_decoder.o \
video/smk_decoder.o \
video/video_decoder.o \
+ video/codecs/cinepak.o \
+ video/codecs/mjpeg.o \
video/codecs/msrle.o \
video/codecs/msvideo1.o \
+ video/codecs/qtrle.o \
+ video/codecs/rpza.o \
+ video/codecs/smc.o \
video/coktelvideo/indeo3.o \
video/coktelvideo/coktelvideo.o
Modified: scummvm/trunk/graphics/video/avi_decoder.cpp
===================================================================
--- scummvm/trunk/graphics/video/avi_decoder.cpp 2010-05-23 18:03:23 UTC (rev 49164)
+++ scummvm/trunk/graphics/video/avi_decoder.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -35,6 +35,7 @@
#include "graphics/video/avi_decoder.h"
// Codecs
+#include "graphics/video/codecs/cinepak.h"
#include "graphics/video/codecs/msvideo1.h"
#include "graphics/video/codecs/msrle.h"
@@ -379,6 +380,8 @@
return new MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount);
case ID_RLE :
return new MSRLEDecoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount);
+ case ID_CVID:
+ return new CinepakDecoder();
default:
warning ("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler));
}
Copied: scummvm/trunk/graphics/video/codecs/cinepak.cpp (from rev 49161, scummvm/trunk/engines/mohawk/video/cinepak.cpp)
===================================================================
--- scummvm/trunk/graphics/video/codecs/cinepak.cpp (rev 0)
+++ scummvm/trunk/graphics/video/codecs/cinepak.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,287 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "graphics/video/codecs/cinepak.h"
+
+#include "common/system.h"
+
+// Code here partially based off of ffmpeg ;)
+
+namespace Graphics {
+
+// Convert a color from YUV to RGB colorspace, Cinepak style.
+inline static void CPYUV2RGB(byte y, byte u, byte v, byte &r, byte &g, byte &b) {
+ r = CLIP<int>(y + 2 * (v - 128), 0, 255);
+ g = CLIP<int>(y - (u - 128) / 2 - (v - 128), 0, 255);
+ b = CLIP<int>(y + 2 * (u - 128), 0, 255);
+}
+
+#define PUT_PIXEL(offset, lum, u, v) \
+ CPYUV2RGB(lum, u, v, r, g, b); \
+ if (_pixelFormat.bytesPerPixel == 2) \
+ *((uint16 *)_curFrame.surface->pixels + offset) = _pixelFormat.RGBToColor(r, g, b); \
+ else \
+ *((uint32 *)_curFrame.surface->pixels + offset) = _pixelFormat.RGBToColor(r, g, b)
+
+CinepakDecoder::CinepakDecoder() : Codec() {
+ _curFrame.surface = NULL;
+ _curFrame.strips = NULL;
+ _y = 0;
+ _pixelFormat = g_system->getScreenFormat();
+}
+
+CinepakDecoder::~CinepakDecoder() {
+ if (_curFrame.surface)
+ _curFrame.surface->free();
+ delete[] _curFrame.strips;
+}
+
+Surface *CinepakDecoder::decodeImage(Common::SeekableReadStream *stream) {
+ _curFrame.flags = stream->readByte();
+ _curFrame.length = (stream->readByte() << 16) + stream->readUint16BE();
+ _curFrame.width = stream->readUint16BE();
+ _curFrame.height = stream->readUint16BE();
+ _curFrame.stripCount = stream->readUint16BE();
+
+ if (_curFrame.strips == NULL)
+ _curFrame.strips = new CinepakStrip[_curFrame.stripCount];
+
+ debug (4, "Cinepak Frame: Width = %d, Height = %d, Strip Count = %d", _curFrame.width, _curFrame.height, _curFrame.stripCount);
+
+#if 0
+ // Borrowed from FFMPEG. This should cut out the extra data Cinepak for Sega has (which is useless).
+ // The theory behind this is that this is here to confuse standard Cinepak decoders. But, we won't let that happen! ;)
+ if (_curFrame.length != (uint32)stream->size()) {
+ if (stream->readUint16BE() == 0xFE00)
+ stream->readUint32BE();
+ }
+#endif
+
+ if (!_curFrame.surface) {
+ _curFrame.surface = new Surface();
+ _curFrame.surface->create(_curFrame.width, _curFrame.height, _pixelFormat.bytesPerPixel);
+ }
+
+ // Reset the y variable.
+ _y = 0;
+
+ for (uint16 i = 0; i < _curFrame.stripCount; i++) {
+ if (i > 0 && !(_curFrame.flags & 1)) { // Use codebooks from last strip
+ for (uint16 j = 0; j < 256; j++) {
+ _curFrame.strips[i].v1_codebook[j] = _curFrame.strips[i - 1].v1_codebook[j];
+ _curFrame.strips[i].v4_codebook[j] = _curFrame.strips[i - 1].v4_codebook[j];
+ }
+ }
+
+ _curFrame.strips[i].id = stream->readUint16BE();
+ _curFrame.strips[i].length = stream->readUint16BE() - 12; // Subtract the 12 byte header
+ _curFrame.strips[i].rect.top = _y; stream->readUint16BE(); // Ignore, substitute with our own.
+ _curFrame.strips[i].rect.left = 0; stream->readUint16BE(); // Ignore, substitute with our own
+ _curFrame.strips[i].rect.bottom = _y + stream->readUint16BE();
+ _curFrame.strips[i].rect.right = _curFrame.width; stream->readUint16BE(); // Ignore, substitute with our own
+
+ //printf ("Left = %d, Top = %d, Right = %d, Bottom = %d\n", _curFrame.strips[i].rect.left, _curFrame.strips[i].rect.top, _curFrame.strips[i].rect.right, _curFrame.strips[i].rect.bottom);
+
+ // Sanity check. Because Cinepak is based on 4x4 blocks, the width and height of each strip needs to be divisible by 4.
+ assert(!(_curFrame.strips[i].rect.width() % 4) && !(_curFrame.strips[i].rect.height() % 4));
+
+ uint32 pos = stream->pos();
+
+ while ((uint32)stream->pos() < (pos + _curFrame.strips[i].length) && !stream->eos()) {
+ byte chunkID = stream->readByte();
+
+ if (stream->eos())
+ break;
+
+ // Chunk Size is 24-bit, ignore the first 4 bytes
+ uint32 chunkSize = stream->readByte() << 16;
+ chunkSize += stream->readUint16BE() - 4;
+
+ int32 startPos = stream->pos();
+
+ switch (chunkID) {
+ case 0x20:
+ case 0x21:
+ case 0x24:
+ case 0x25:
+ loadCodebook(stream, i, 4, chunkID, chunkSize);
+ break;
+ case 0x22:
+ case 0x23:
+ case 0x26:
+ case 0x27:
+ loadCodebook(stream, i, 1, chunkID, chunkSize);
+ break;
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ decodeVectors(stream, i, chunkID, chunkSize);
+ break;
+ default:
+ warning("Unknown Cinepak chunk ID %02x", chunkID);
+ return _curFrame.surface;
+ }
+
+ if (stream->pos() != startPos + (int32)chunkSize)
+ stream->seek(startPos + chunkSize);
+ }
+
+ _y = _curFrame.strips[i].rect.bottom;
+ }
+
+ return _curFrame.surface;
+}
+
+void CinepakDecoder::loadCodebook(Common::SeekableReadStream *stream, uint16 strip, byte codebookType, byte chunkID, uint32 chunkSize) {
+ CinepakCodebook *codebook = (codebookType == 1) ? _curFrame.strips[strip].v1_codebook : _curFrame.strips[strip].v4_codebook;
+
+ int32 startPos = stream->pos();
+ uint32 flag = 0, mask = 0;
+
+ for (uint16 i = 0; i < 256; i++) {
+ if ((chunkID & 0x01) && !(mask >>= 1)) {
+ if ((stream->pos() - startPos + 4) > (int32)chunkSize)
+ break;
+
+ flag = stream->readUint32BE();
+ mask = 0x80000000;
+ }
+
+ if (!(chunkID & 0x01) || (flag & mask)) {
+ byte n = (chunkID & 0x04) ? 4 : 6;
+ if ((stream->pos() - startPos + n) > (int32)chunkSize)
+ break;
+
+ for (byte j = 0; j < 4; j++)
+ codebook[i].y[j] = stream->readByte();
+
+ if (n == 6) {
+ codebook[i].u = stream->readByte() + 128;
+ codebook[i].v = stream->readByte() + 128;
+ } else {
+ /* this codebook type indicates either greyscale or
+ * palettized video; if palettized, U & V components will
+ * not be used so it is safe to set them to 128 for the
+ * benefit of greyscale rendering in YUV420P */
+ codebook[i].u = 128;
+ codebook[i].v = 128;
+ }
+ }
+ }
+}
+
+void CinepakDecoder::decodeVectors(Common::SeekableReadStream *stream, uint16 strip, byte chunkID, uint32 chunkSize) {
+ uint32 flag = 0, mask = 0;
+ uint32 iy[4];
+ int32 startPos = stream->pos();
+ byte r = 0, g = 0, b = 0;
+
+ for (uint16 y = _curFrame.strips[strip].rect.top; y < _curFrame.strips[strip].rect.bottom; y += 4) {
+ iy[0] = _curFrame.strips[strip].rect.left + y * _curFrame.width;
+ iy[1] = iy[0] + _curFrame.width;
+ iy[2] = iy[1] + _curFrame.width;
+ iy[3] = iy[2] + _curFrame.width;
+
+ for (uint16 x = _curFrame.strips[strip].rect.left; x < _curFrame.strips[strip].rect.right; x += 4) {
+ if ((chunkID & 0x01) && !(mask >>= 1)) {
+ if ((stream->pos() - startPos + 4) > (int32)chunkSize)
+ return;
+
+ flag = stream->readUint32BE();
+ mask = 0x80000000;
+ }
+
+ if (!(chunkID & 0x01) || (flag & mask)) {
+ if (!(chunkID & 0x02) && !(mask >>= 1)) {
+ if ((stream->pos() - startPos + 4) > (int32)chunkSize)
+ return;
+
+ flag = stream->readUint32BE();
+ mask = 0x80000000;
+ }
+
+ if ((chunkID & 0x02) || (~flag & mask)) {
+ if ((stream->pos() - startPos + 1) > (int32)chunkSize)
+ return;
+
+ // Get the codebook
+ CinepakCodebook codebook = _curFrame.strips[strip].v1_codebook[stream->readByte()];
+
+ PUT_PIXEL(iy[0] + 0, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[0] + 1, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 0, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 1, codebook.y[0], codebook.u, codebook.v);
+
+ PUT_PIXEL(iy[0] + 2, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[0] + 3, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 2, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 3, codebook.y[1], codebook.u, codebook.v);
+
+ PUT_PIXEL(iy[2] + 0, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[2] + 1, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 0, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 1, codebook.y[2], codebook.u, codebook.v);
+
+ PUT_PIXEL(iy[2] + 2, codebook.y[3], codebook.u, codebook.v);
+ PUT_PIXEL(iy[2] + 3, codebook.y[3], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 2, codebook.y[3], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 3, codebook.y[3], codebook.u, codebook.v);
+ } else if (flag & mask) {
+ if ((stream->pos() - startPos + 4) > (int32)chunkSize)
+ return;
+
+ CinepakCodebook codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
+ PUT_PIXEL(iy[0] + 0, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[0] + 1, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 0, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 1, codebook.y[3], codebook.u, codebook.v);
+
+ codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
+ PUT_PIXEL(iy[0] + 2, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[0] + 3, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 2, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[1] + 3, codebook.y[3], codebook.u, codebook.v);
+
+ codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
+ PUT_PIXEL(iy[2] + 0, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[2] + 1, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 0, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 1, codebook.y[3], codebook.u, codebook.v);
+
+ codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
+ PUT_PIXEL(iy[2] + 2, codebook.y[0], codebook.u, codebook.v);
+ PUT_PIXEL(iy[2] + 3, codebook.y[1], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 2, codebook.y[2], codebook.u, codebook.v);
+ PUT_PIXEL(iy[3] + 3, codebook.y[3], codebook.u, codebook.v);
+ }
+ }
+
+ for (byte i = 0; i < 4; i++)
+ iy[i] += 4;
+ }
+ }
+}
+
+} // End of namespace Graphics
Copied: scummvm/trunk/graphics/video/codecs/cinepak.h (from rev 49161, scummvm/trunk/engines/mohawk/video/cinepak.h)
===================================================================
--- scummvm/trunk/graphics/video/codecs/cinepak.h (rev 0)
+++ scummvm/trunk/graphics/video/codecs/cinepak.h 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,81 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GRAPHICS_CINEPAK_H
+#define GRAPHICS_CINEPAK_H
+
+#include "common/scummsys.h"
+#include "common/stream.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+#include "graphics/pixelformat.h"
+
+#include "graphics/video/codecs/codec.h"
+
+namespace Graphics {
+
+struct CinepakCodebook {
+ byte y[4];
+ byte u, v;
+};
+
+struct CinepakStrip {
+ uint16 id;
+ uint16 length;
+ Common::Rect rect;
+ CinepakCodebook v1_codebook[256], v4_codebook[256];
+};
+
+struct CinepakFrame {
+ byte flags;
+ uint32 length;
+ uint16 width;
+ uint16 height;
+ uint16 stripCount;
+ CinepakStrip *strips;
+
+ Surface *surface;
+};
+
+class CinepakDecoder : public Codec {
+public:
+ CinepakDecoder();
+ ~CinepakDecoder();
+
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const { return _pixelFormat; }
+
+private:
+ CinepakFrame _curFrame;
+ int32 _y;
+ PixelFormat _pixelFormat;
+
+ void loadCodebook(Common::SeekableReadStream *stream, uint16 strip, byte codebookType, byte chunkID, uint32 chunkSize);
+ void decodeVectors(Common::SeekableReadStream *stream, uint16 strip, byte chunkID, uint32 chunkSize);
+};
+
+} // End of namespace Graphics
+
+#endif
Copied: scummvm/trunk/graphics/video/codecs/mjpeg.cpp (from rev 49161, scummvm/trunk/engines/mohawk/jpeg.cpp)
===================================================================
--- scummvm/trunk/graphics/video/codecs/mjpeg.cpp (rev 0)
+++ scummvm/trunk/graphics/video/codecs/mjpeg.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/system.h"
+#include "graphics/conversion.h" // For YUV2RGB
+
+#include "graphics/video/codecs/mjpeg.h"
+
+namespace Graphics {
+
+JPEGDecoder::JPEGDecoder() : Codec() {
+ _jpeg = new JPEG();
+ _pixelFormat = g_system->getScreenFormat();
+ _surface = NULL;
+}
+
+JPEGDecoder::~JPEGDecoder() {
+ delete _jpeg;
+
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ }
+}
+
+Surface *JPEGDecoder::decodeImage(Common::SeekableReadStream* stream) {
+ _jpeg->read(stream);
+ Surface *ySurface = _jpeg->getComponent(1);
+ Surface *uSurface = _jpeg->getComponent(2);
+ Surface *vSurface = _jpeg->getComponent(3);
+
+ if (!_surface) {
+ _surface = new Surface();
+ _surface->create(ySurface->w, ySurface->h, _pixelFormat.bytesPerPixel);
+ }
+
+ for (uint16 i = 0; i < _surface->h; i++) {
+ for (uint16 j = 0; j < _surface->w; j++) {
+ byte r = 0, g = 0, b = 0;
+ YUV2RGB(*((byte *)ySurface->getBasePtr(j, i)), *((byte *)uSurface->getBasePtr(j, i)), *((byte *)vSurface->getBasePtr(j, i)), r, g, b);
+ if (_pixelFormat.bytesPerPixel == 2)
+ *((uint16 *)_surface->getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
+ else
+ *((uint32 *)_surface->getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
+ }
+ }
+
+ return _surface;
+}
+
+} // End of namespace Graphics
Copied: scummvm/trunk/graphics/video/codecs/mjpeg.h (from rev 49161, scummvm/trunk/engines/mohawk/jpeg.h)
===================================================================
--- scummvm/trunk/graphics/video/codecs/mjpeg.h (rev 0)
+++ scummvm/trunk/graphics/video/codecs/mjpeg.h 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,58 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GRAPHICS_MJPEG_H
+#define GRAPHICS_MJPEG_H
+
+#include "common/scummsys.h"
+#include "common/stream.h"
+
+#include "graphics/video/codecs/codec.h"
+#include "graphics/jpeg.h"
+#include "graphics/pixelformat.h"
+
+namespace Graphics {
+
+// Motion JPEG Decoder
+// Basically a wrapper around JPEG which converts to RGB and also functions
+// as a Codec.
+
+class JPEGDecoder : public Codec {
+public:
+ JPEGDecoder();
+ ~JPEGDecoder();
+
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const { return _pixelFormat; }
+
+private:
+ PixelFormat _pixelFormat;
+ JPEG *_jpeg;
+ Surface *_surface;
+};
+
+} // End of namespace Graphics
+
+#endif
Copied: scummvm/trunk/graphics/video/codecs/qtrle.cpp (from rev 49161, scummvm/trunk/engines/mohawk/video/qtrle.cpp)
===================================================================
--- scummvm/trunk/graphics/video/codecs/qtrle.cpp (rev 0)
+++ scummvm/trunk/graphics/video/codecs/qtrle.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,420 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+// QuickTime RLE Decoder
+// Based off ffmpeg's QuickTime RLE decoder (written by Mike Melanson)
+
+#include "graphics/video/codecs/qtrle.h"
+
+#include "common/scummsys.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "graphics/colormasks.h"
+#include "graphics/surface.h"
+
+namespace Graphics {
+
+QTRLEDecoder::QTRLEDecoder(uint16 width, uint16 height, byte bitsPerPixel) : Codec() {
+ _bitsPerPixel = bitsPerPixel;
+ _pixelFormat = g_system->getScreenFormat();
+
+ // We need to increase the surface size to a multiple of 4
+ uint16 wMod = width % 4;
+ if(wMod != 0)
+ width += 4 - wMod;
+
+ debug(2, "QTRLE corrected width: %d", width);
+
+ _surface = new Surface();
+ _surface->create(width, height, _bitsPerPixel <= 8 ? 1 : _pixelFormat.bytesPerPixel);
+}
+
+#define CHECK_STREAM_PTR(n) \
+ if ((stream->pos() + n) > stream->size()) { \
+ warning ("Problem: stream out of bounds (%d >= %d)", stream->pos() + n, stream->size()); \
+ return; \
+ }
+
+#define CHECK_PIXEL_PTR(n) \
+ if ((int32)pixelPtr + n > _surface->w * _surface->h) { \
+ warning ("Problem: pixel ptr = %d, pixel limit = %d", pixelPtr + n, _surface->w * _surface->h); \
+ return; \
+ } \
+
+void QTRLEDecoder::decode1(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
+ uint32 pixelPtr = 0;
+ byte *rgb = (byte *)_surface->pixels;
+
+ while (linesToChange) {
+ CHECK_STREAM_PTR(2);
+ byte skip = stream->readByte();
+ int8 rleCode = stream->readSByte();
+
+ if (rleCode == 0)
+ break;
+
+ if (skip & 0x80) {
+ linesToChange--;
+ rowPtr += _surface->w;
+ pixelPtr = rowPtr + 2 * (skip & 0x7f);
+ } else
+ pixelPtr += 2 * skip;
+
+ if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+ // get the next 2 bytes from the stream, treat them as groups of 8 pixels, and output them rleCode times */
+ CHECK_STREAM_PTR(2);
+ byte pi0 = stream->readByte();
+ byte pi1 = stream->readByte();
+ CHECK_PIXEL_PTR(rleCode * 2);
+
+ while (rleCode--) {
+ rgb[pixelPtr++] = pi0;
+ rgb[pixelPtr++] = pi1;
+ }
+ } else {
+ // copy the same pixel directly to output 2 times
+ rleCode *= 2;
+ CHECK_STREAM_PTR(rleCode);
+ CHECK_PIXEL_PTR(rleCode);
+
+ while (rleCode--)
+ rgb[pixelPtr++] = stream->readByte();
+ }
+ }
+}
+
+void QTRLEDecoder::decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange, byte bpp) {
+ uint32 pixelPtr = 0;
+ byte *rgb = (byte *)_surface->pixels;
+ byte numPixels = (bpp == 4) ? 8 : 16;
+
+ while (linesToChange--) {
+ CHECK_STREAM_PTR(2);
+ pixelPtr = rowPtr + (numPixels * (stream->readByte() - 1));
+
+ for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
+ if (rleCode == 0) {
+ // there's another skip code in the stream
+ CHECK_STREAM_PTR(1);
+ pixelPtr += (numPixels * (stream->readByte() - 1));
+ } else if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+
+ // get the next 4 bytes from the stream, treat them as palette indices, and output them rleCode times */
+ CHECK_STREAM_PTR(4);
+
+ byte pi[16]; // 16 palette indices
+
+ for (int8 i = numPixels - 1; i >= 0; i--) {
+ pi[numPixels - 1 - i] = (stream->readByte() >> ((i * bpp) & 0x07)) & ((1 << bpp) - 1);
+
+ // FIXME: Is this right?
+ //stream_ptr += ((i & ((num_pixels>>2)-1)) == 0);
+ if ((i & ((numPixels >> 2) - 1)) == 0)
+ stream->readByte();
+ }
+
+ CHECK_PIXEL_PTR(rleCode * numPixels);
+
+ while (rleCode--)
+ for (byte i = 0; i < numPixels; i++)
+ rgb[pixelPtr++] = pi[i];
+ } else {
+ // copy the same pixel directly to output 4 times
+ rleCode *= 4;
+ CHECK_STREAM_PTR(rleCode);
+ CHECK_PIXEL_PTR(rleCode * (numPixels >> 2));
+
+ while (rleCode--) {
+ byte temp = stream->readByte();
+ if (bpp == 4) {
+ rgb[pixelPtr++] = (temp >> 4) & 0x0f;
+ rgb[pixelPtr++] = temp & 0x0f;
+ } else {
+ rgb[pixelPtr++] = (temp >> 6) & 0x03;
+ rgb[pixelPtr++] = (temp >> 4) & 0x03;
+ rgb[pixelPtr++] = (temp >> 2) & 0x03;
+ rgb[pixelPtr++] = temp & 0x03;
+ }
+ }
+ }
+ }
+
+ rowPtr += _surface->w;
+ }
+}
+
+void QTRLEDecoder::decode8(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
+ uint32 pixelPtr = 0;
+ byte *rgb = (byte *)_surface->pixels;
+
+ while (linesToChange--) {
+ CHECK_STREAM_PTR(2);
+ pixelPtr = rowPtr + 4 * (stream->readByte() - 1);
+
+ for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
+ if (rleCode == 0) {
+ // there's another skip code in the stream
+ CHECK_STREAM_PTR(1);
+ pixelPtr += 4 * (stream->readByte() - 1);
+ } else if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+
+ // get the next 4 bytes from the stream, treat them as palette indices, and output them rleCode times
+ CHECK_STREAM_PTR(4);
+
+ byte pi[4]; // 4 palette indexes
+
+ for (byte i = 0; i < 4; i++)
+ pi[i] = stream->readByte();
+
+ CHECK_PIXEL_PTR(rleCode * 4);
+
+ while (rleCode--)
+ for (byte i = 0; i < 4; i++)
+ rgb[pixelPtr++] = pi[i];
+ } else {
+ // copy the same pixel directly to output 4 times
+ rleCode *= 4;
+ CHECK_STREAM_PTR(rleCode);
+ CHECK_PIXEL_PTR(rleCode);
+
+ while (rleCode--)
+ rgb[pixelPtr++] = stream->readByte();
+ }
+ }
+
+ rowPtr += _surface->w;
+ }
+}
+
+void QTRLEDecoder::decode16(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
+ uint32 pixelPtr = 0;
+ OverlayColor *rgb = (OverlayColor *)_surface->pixels;
+
+ while (linesToChange--) {
+ CHECK_STREAM_PTR(2);
+ pixelPtr = rowPtr + stream->readByte() - 1;
+
+ for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
+ if (rleCode == 0) {
+ // there's another skip code in the stream
+ CHECK_STREAM_PTR(1);
+ pixelPtr += stream->readByte() - 1;
+ } else if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+ CHECK_STREAM_PTR(2);
+
+ uint16 rgb16 = stream->readUint16BE();
+
+ CHECK_PIXEL_PTR(rleCode);
+
+ while (rleCode--) {
+ // Convert from RGB555 to the format specified by the Overlay
+ byte r = 0, g = 0, b = 0;
+ colorToRGB<ColorMasks<555> >(rgb16, r, g, b);
+ rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
+ }
+ } else {
+ CHECK_STREAM_PTR(rleCode * 2);
+ CHECK_PIXEL_PTR(rleCode);
+
+ // copy pixels directly to output
+ while (rleCode--) {
+ uint16 rgb16 = stream->readUint16BE();
+
+ // Convert from RGB555 to the format specified by the Overlay
+ byte r = 0, g = 0, b = 0;
+ colorToRGB<ColorMasks<555> >(rgb16, r, g, b);
+ rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
+ }
+ }
+ }
+
+ rowPtr += _surface->w;
+ }
+}
+
+void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
+ uint32 pixelPtr = 0;
+ OverlayColor *rgb = (OverlayColor *)_surface->pixels;
+
+ while (linesToChange--) {
+ CHECK_STREAM_PTR(2);
+ pixelPtr = rowPtr + stream->readByte() - 1;
+
+ for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
+ if (rleCode == 0) {
+ // there's another skip code in the stream
+ CHECK_STREAM_PTR(1);
+ pixelPtr += stream->readByte() - 1;
+ } else if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+
+ CHECK_STREAM_PTR(3);
+
+ byte r = stream->readByte();
+ byte g = stream->readByte();
+ byte b = stream->readByte();
+
+ CHECK_PIXEL_PTR(rleCode);
+
+ while (rleCode--)
+ rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
+ } else {
+ CHECK_STREAM_PTR(rleCode * 3);
+ CHECK_PIXEL_PTR(rleCode);
+
+ // copy pixels directly to output
+ while (rleCode--) {
+ byte r = stream->readByte();
+ byte g = stream->readByte();
+ byte b = stream->readByte();
+ rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
+ }
+ }
+ }
+
+ rowPtr += _surface->w;
+ }
+}
+
+void QTRLEDecoder::decode32(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
+ uint32 pixelPtr = 0;
+ OverlayColor *rgb = (OverlayColor *)_surface->pixels;
+
+ while (linesToChange--) {
+ CHECK_STREAM_PTR(2);
+ pixelPtr = rowPtr + stream->readByte() - 1;
+
+ for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
+ if (rleCode == 0) {
+ // there's another skip code in the stream
+ CHECK_STREAM_PTR(1);
+ pixelPtr += stream->readByte() - 1;
+ } else if (rleCode < 0) {
+ // decode the run length code
+ rleCode = -rleCode;
+
+ CHECK_STREAM_PTR(4);
+
+ byte a = stream->readByte();
+ byte r = stream->readByte();
+ byte g = stream->readByte();
+ byte b = stream->readByte();
+
+ CHECK_PIXEL_PTR(rleCode);
+
+ while (rleCode--)
+ rgb[pixelPtr++] = _pixelFormat.ARGBToColor(a, r, g, b);
+ } else {
+ CHECK_STREAM_PTR(rleCode * 4);
+ CHECK_PIXEL_PTR(rleCode);
+
+ // copy pixels directly to output
+ while (rleCode--) {
+ byte a = stream->readByte();
+ byte r = stream->readByte();
+ byte g = stream->readByte();
+ byte b = stream->readByte();
+ rgb[pixelPtr++] = _pixelFormat.ARGBToColor(a, r, g, b);
+ }
+ }
+ }
+
+ rowPtr += _surface->w;
+ }
+}
+
+Surface *QTRLEDecoder::decodeImage(Common::SeekableReadStream *stream) {
+ uint16 start_line = 0;
+ uint16 height = _surface->h;
+
+ // check if this frame is even supposed to change
+ if (stream->size() < 8)
+ return _surface;
+
+ // start after the chunk size
+ stream->readUint32BE();
+
+ // fetch the header
+ uint16 header = stream->readUint16BE();
+
+ // if a header is present, fetch additional decoding parameters
+ if (header & 8) {
+ if(stream->size() < 14)
+ return _surface;
+ start_line = stream->readUint16BE();
+ stream->readUint16BE(); // Unknown
+ height = stream->readUint16BE();
+ stream->readUint16BE(); // Unknown
+ }
+
+ uint32 row_ptr = _surface->w * start_line;
+
+ switch (_bitsPerPixel) {
+ case 1:
+ case 33:
+ decode1(stream, row_ptr, height);
+ break;
+ case 2:
+ case 34:
+ decode2_4(stream, row_ptr, height, 2);
+ break;
+ case 4:
+ case 36:
+ decode2_4(stream, row_ptr, height, 4);
+ break;
+ case 8:
+ case 40:
+ decode8(stream, row_ptr, height);
+ break;
+ case 16:
+ decode16(stream, row_ptr, height);
+ break;
+ case 24:
+ decode24(stream, row_ptr, height);
+ break;
+ case 32:
+ decode32(stream, row_ptr, height);
+ break;
+ default:
+ error ("Unsupported bits per pixel %d", _bitsPerPixel);
+ }
+
+ return _surface;
+}
+
+QTRLEDecoder::~QTRLEDecoder() {
+ _surface->free();
+}
+
+} // End of namespace Graphics
Copied: scummvm/trunk/graphics/video/codecs/qtrle.h (from rev 49161, scummvm/trunk/engines/mohawk/video/qtrle.h)
===================================================================
--- scummvm/trunk/graphics/video/codecs/qtrle.h (rev 0)
+++ scummvm/trunk/graphics/video/codecs/qtrle.h 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,58 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GRAPHICS_VIDEO_QTRLE_H
+#define GRAPHICS_VIDEO_QTRLE_H
+
+#include "graphics/pixelformat.h"
+#include "graphics/video/codecs/codec.h"
+
+namespace Graphics {
+
+class QTRLEDecoder : public Codec {
+public:
+ QTRLEDecoder(uint16 width, uint16 height, byte bitsPerPixel);
+ ~QTRLEDecoder();
+
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const { return _pixelFormat; }
+
+private:
+ byte _bitsPerPixel;
+
+ Surface *_surface;
+ PixelFormat _pixelFormat;
+
+ void decode1(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
+ void decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange, byte bpp);
+ void decode8(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
+ void decode16(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
+ void decode24(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
+ void decode32(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
+};
+
+} // End of namespace Graphics
+
+#endif
Copied: scummvm/trunk/graphics/video/codecs/rpza.cpp (from rev 49161, scummvm/trunk/engines/mohawk/video/rpza.cpp)
===================================================================
--- scummvm/trunk/graphics/video/codecs/rpza.cpp (rev 0)
+++ scummvm/trunk/graphics/video/codecs/rpza.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,208 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+ // Based off ffmpeg's RPZA decoder
+
+#include "graphics/video/codecs/rpza.h"
+
+#include "common/system.h"
+#include "graphics/colormasks.h"
+
+namespace Graphics {
+
+RPZADecoder::RPZADecoder(uint16 width, uint16 height) : Codec() {
+ _pixelFormat = g_system->getScreenFormat();
+
+ // We need to increase the surface size to a multiple of 4
+ uint16 wMod = width % 4;
+ if(wMod != 0)
+ width += 4 - wMod;
+
+ debug(2, "RPZA corrected width: %d", width);
+
+ _surface = new Surface();
+ _surface->create(width, height, _pixelFormat.bytesPerPixel);
+}
+
+#define ADVANCE_BLOCK() \
+ pixelPtr += 4; \
+ if (pixelPtr >= _surface->w) { \
+ pixelPtr = 0; \
+ rowPtr += _surface->w * 4; \
+ } \
+ totalBlocks--; \
+ if (totalBlocks < 0) \
+ error("block counter just went negative (this should not happen)") \
+
+// Convert from RGB555 to the format specified by the screen
+#define PUT_PIXEL(color) \
+ if ((int32)blockPtr < _surface->w * _surface->h) { \
+ byte r = 0, g = 0, b = 0; \
+ colorToRGB<ColorMasks<555> >(color, r, g, b); \
+ if (_pixelFormat.bytesPerPixel == 2) \
+ *((uint16 *)_surface->pixels + blockPtr) = _pixelFormat.RGBToColor(r, g, b); \
+ else \
+ *((uint32 *)_surface->pixels + blockPtr) = _pixelFormat.RGBToColor(r, g, b); \
+ } \
+ blockPtr++
+
+Surface *RPZADecoder::decodeImage(Common::SeekableReadStream *stream) {
+ uint16 colorA = 0, colorB = 0;
+ uint16 color4[4];
+
+ uint32 rowPtr = 0;
+ uint32 pixelPtr = 0;
+ uint32 blockPtr = 0;
+ uint32 rowInc = _surface->w - 4;
+ uint16 ta;
+ uint16 tb;
+
+ // First byte is always 0xe1. Warn if it's different
+ byte firstByte = stream->readByte();
+ if (firstByte != 0xe1)
+ warning("First RPZA chunk byte is 0x%02x instead of 0xe1", firstByte);
+
+ // Get chunk size, ingnoring first byte
+ uint32 chunkSize = stream->readUint16BE() << 8;
+ chunkSize += stream->readByte();
+
+ // If length mismatch use size from MOV file and try to decode anyway
+ if (chunkSize != (uint32)stream->size()) {
+ warning("MOV chunk size != encoded chunk size; using MOV chunk size");
+ chunkSize = stream->size();
+ }
+
+ // Number of 4x4 blocks in frame
+ int32 totalBlocks = ((_surface->w + 3) / 4) * ((_surface->h + 3) / 4);
+
+ // Process chunk data
+ while ((uint32)stream->pos() < chunkSize) {
+ byte opcode = stream->readByte(); // Get opcode
+ byte numBlocks = (opcode & 0x1f) + 1; // Extract block counter from opcode
+
+ // If opcode MSbit is 0, we need more data to decide what to do
+ if ((opcode & 0x80) == 0) {
+ colorA = (opcode << 8) | stream->readByte();
+ opcode = 0;
+ if (stream->readByte() & 0x80) {
+ // Must behave as opcode 110xxxxx, using colorA computed
+ // above. Use fake opcode 0x20 to enter switch block at
+ // the right place
+ opcode = 0x20;
+ numBlocks = 1;
+ }
+ stream->seek(-1, SEEK_CUR);
+ }
+
+ switch (opcode & 0xe0) {
+ case 0x80: // Skip blocks
+ while (numBlocks--) {
+ ADVANCE_BLOCK();
+ }
+ break;
+ case 0xa0: // Fill blocks with one color
+ colorA = stream->readUint16BE();
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+ for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (byte pixel_x = 0; pixel_x < 4; pixel_x++) {
+ PUT_PIXEL(colorA);
+ }
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // Fill blocks with 4 colors
+ case 0xc0:
+ colorA = stream->readUint16BE();
+ case 0x20:
+ colorB = stream->readUint16BE();
+
+ // Sort out the colors
+ color4[0] = colorB;
+ color4[1] = 0;
+ color4[2] = 0;
+ color4[3] = colorA;
+
+ // Red components
+ ta = (colorA >> 10) & 0x1F;
+ tb = (colorB >> 10) & 0x1F;
+ color4[1] |= ((11 * ta + 21 * tb) >> 5) << 10;
+ color4[2] |= ((21 * ta + 11 * tb) >> 5) << 10;
+
+ // Green components
+ ta = (colorA >> 5) & 0x1F;
+ tb = (colorB >> 5) & 0x1F;
+ color4[1] |= ((11 * ta + 21 * tb) >> 5) << 5;
+ color4[2] |= ((21 * ta + 11 * tb) >> 5) << 5;
+
+ // Blue components
+ ta = colorA & 0x1F;
+ tb = colorB & 0x1F;
+ color4[1] |= ((11 * ta + 21 * tb) >> 5);
+ color4[2] |= ((21 * ta + 11 * tb) >> 5);
+
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+ for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
+ byte index = stream->readByte();
+ for (byte pixel_x = 0; pixel_x < 4; pixel_x++){
+ byte idx = (index >> (2 * (3 - pixel_x))) & 0x03;
+ PUT_PIXEL(color4[idx]);
+ }
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // Fill block with 16 colors
+ case 0x00:
+ blockPtr = rowPtr + pixelPtr;
+ for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (byte pixel_x = 0; pixel_x < 4; pixel_x++){
+ // We already have color of upper left pixel
+ if (pixel_y != 0 || pixel_x != 0)
+ colorA = stream->readUint16BE();
+
+ PUT_PIXEL(colorA);
+ }
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ break;
+
+ // Unknown opcode
+ default:
+ error("Unknown opcode %02x in rpza chunk", opcode);
+ }
+ }
+
+ return _surface;
+}
+
+} // End of namespace Graphics
Copied: scummvm/trunk/graphics/video/codecs/rpza.h (from rev 49161, scummvm/trunk/engines/mohawk/video/rpza.h)
===================================================================
--- scummvm/trunk/graphics/video/codecs/rpza.h (rev 0)
+++ scummvm/trunk/graphics/video/codecs/rpza.h 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GRAPHICS_VIDEO_RPZA_H
+#define GRAPHICS_VIDEO_RPZA_H
+
+#include "graphics/pixelformat.h"
+#include "graphics/video/codecs/codec.h"
+
+namespace Graphics {
+
+class RPZADecoder : public Codec {
+public:
+ RPZADecoder(uint16 width, uint16 height);
+ ~RPZADecoder() { delete _surface; }
+
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const { return _pixelFormat; }
+
+private:
+ Surface *_surface;
+ PixelFormat _pixelFormat;
+};
+
+} // End of namespace Graphics
+
+#endif
Copied: scummvm/trunk/graphics/video/codecs/smc.cpp (from rev 49161, scummvm/trunk/engines/mohawk/video/smc.cpp)
===================================================================
--- scummvm/trunk/graphics/video/codecs/smc.cpp (rev 0)
+++ scummvm/trunk/graphics/video/codecs/smc.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,385 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+// Based off ffmpeg's SMC decoder
+
+#include "graphics/video/codecs/smc.h"
+
+namespace Graphics {
+
+#define GET_BLOCK_COUNT() \
+ (opcode & 0x10) ? (1 + stream->readByte()) : 1 + (opcode & 0x0F);
+
+#define ADVANCE_BLOCK() \
+{ \
+ pixelPtr += 4; \
+ if (pixelPtr >= _surface->w) { \
+ pixelPtr = 0; \
+ rowPtr += _surface->w * 4; \
+ } \
+ totalBlocks--; \
+ if (totalBlocks < 0) { \
+ warning("block counter just went negative (this should not happen)"); \
+ return _surface; \
+ } \
+}
+
+SMCDecoder::SMCDecoder(uint16 width, uint16 height) {
+ _surface = new Graphics::Surface();
+ _surface->create(width, height, 1);
+}
+
+Graphics::Surface *SMCDecoder::decodeImage(Common::SeekableReadStream *stream) {
+ byte *pixels = (byte *)_surface->pixels;
+
+ uint32 numBlocks = 0;
+ uint32 colorFlags = 0;
+ uint32 colorFlagsA = 0;
+ uint32 colorFlagsB = 0;
+
+ const uint16 rowInc = _surface->w - 4;
+ int32 rowPtr = 0;
+ int32 pixelPtr = 0;
+ uint32 blockPtr = 0;
+ uint32 prevBlockPtr = 0;
+ uint32 prevBlockPtr1 = 0, prevBlockPtr2 = 0;
+ byte prevBlockFlag = false;
+ byte pixel = 0;
+
+ uint32 colorPairIndex = 0;
+ uint32 colorQuadIndex = 0;
+ uint32 colorOctetIndex = 0;
+ uint32 colorTableIndex = 0; // indices to color pair, quad, or octet tables
+
+ int32 chunkSize = stream->readUint32BE() & 0x00FFFFFF;
+ if (chunkSize != stream->size())
+ warning("MOV chunk size != SMC chunk size (%d != %d); ignoring SMC chunk size", chunkSize, stream->size());
+
+ int32 totalBlocks = ((_surface->w + 3) / 4) * ((_surface->h + 3) / 4);
+
+ // traverse through the blocks
+ while (totalBlocks != 0) {
+ // sanity checks
+
+ // make sure stream ptr hasn't gone out of bounds
+ if (stream->pos() > stream->size()) {
+ warning("SMC decoder just went out of bounds (stream ptr = %d, chunk size = %d)", stream->pos(), stream->size());
+ return _surface;
+ }
+
+ // make sure the row pointer hasn't gone wild
+ if (rowPtr >= _surface->w * _surface->h) {
+ warning("SMC decoder just went out of bounds (row ptr = %d, size = %d)", rowPtr, _surface->w * _surface->h);
+ return _surface;
+ }
+
+ byte opcode = stream->readByte();
+
+ switch (opcode & 0xF0) {
+ // skip n blocks
+ case 0x00:
+ case 0x10:
+ numBlocks = GET_BLOCK_COUNT();
+ while (numBlocks--) {
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // repeat last block n times
+ case 0x20:
+ case 0x30:
+ numBlocks = GET_BLOCK_COUNT();
+
+ // sanity check
+ if (rowPtr == 0 && pixelPtr == 0) {
+ warning("encountered repeat block opcode (%02X) but no blocks rendered yet", opcode & 0xF0);
+ break;
+ }
+
+ // figure out where the previous block started
+ if (pixelPtr == 0)
+ prevBlockPtr1 = (rowPtr - _surface->w * 4) + _surface->w - 4;
+ else
+ prevBlockPtr1 = rowPtr + pixelPtr - 4;
+
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+ prevBlockPtr = prevBlockPtr1;
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++)
+ pixels[blockPtr++] = pixels[prevBlockPtr++];
+ blockPtr += rowInc;
+ prevBlockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // repeat previous pair of blocks n times
+ case 0x40:
+ case 0x50:
+ numBlocks = GET_BLOCK_COUNT();
+ numBlocks *= 2;
+
+ // sanity check
+ if (rowPtr == 0 && pixelPtr < 2 * 4) {
+ warning("encountered repeat block opcode (%02X) but not enough blocks rendered yet", opcode & 0xF0);
+ break;
+ }
+
+ // figure out where the previous 2 blocks started
+ if (pixelPtr == 0)
+ prevBlockPtr1 = (rowPtr - _surface->w * 4) + _surface->w - 4 * 2;
+ else if (pixelPtr == 4)
+ prevBlockPtr1 = (rowPtr - _surface->w * 4) + rowInc;
+ else
+ prevBlockPtr1 = rowPtr + pixelPtr - 4 * 2;
+
+ if (pixelPtr == 0)
+ prevBlockPtr2 = (rowPtr - _surface->w * 4) + rowInc;
+ else
+ prevBlockPtr2 = rowPtr + pixelPtr - 4;
+
+ prevBlockFlag = 0;
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+
+ if (prevBlockFlag)
+ prevBlockPtr = prevBlockPtr2;
+ else
+ prevBlockPtr = prevBlockPtr1;
+
+ prevBlockFlag = !prevBlockFlag;
+
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++)
+ pixels[blockPtr++] = pixels[prevBlockPtr++];
+
+ blockPtr += rowInc;
+ prevBlockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // 1-color block encoding
+ case 0x60:
+ case 0x70:
+ numBlocks = GET_BLOCK_COUNT();
+ pixel = stream->readByte();
+
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++)
+ pixels[blockPtr++] = pixel;
+
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // 2-color block encoding
+ case 0x80:
+ case 0x90:
+ numBlocks = (opcode & 0x0F) + 1;
+
+ // figure out which color pair to use to paint the 2-color block
+ if ((opcode & 0xF0) == 0x80) {
+ // fetch the next 2 colors from bytestream and store in next
+ // available entry in the color pair table
+ for (byte i = 0; i < CPAIR; i++) {
+ pixel = stream->readByte();
+ colorTableIndex = CPAIR * colorPairIndex + i;
+ _colorPairs[colorTableIndex] = pixel;
+ }
+
+ // this is the base index to use for this block
+ colorTableIndex = CPAIR * colorPairIndex;
+ colorPairIndex++;
+
+ // wraparound
+ if (colorPairIndex == COLORS_PER_TABLE)
+ colorPairIndex = 0;
+ } else
+ colorTableIndex = CPAIR * stream->readByte();
+
+ while (numBlocks--) {
+ colorFlags = stream->readUint16BE();
+ uint16 flagMask = 0x8000;
+ blockPtr = rowPtr + pixelPtr;
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++) {
+ if (colorFlags & flagMask)
+ pixel = colorTableIndex + 1;
+ else
+ pixel = colorTableIndex;
+
+ flagMask >>= 1;
+ pixels[blockPtr++] = _colorPairs[pixel];
+ }
+
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // 4-color block encoding
+ case 0xA0:
+ case 0xB0:
+ numBlocks = (opcode & 0x0F) + 1;
+
+ // figure out which color quad to use to paint the 4-color block
+ if ((opcode & 0xF0) == 0xA0) {
+ // fetch the next 4 colors from bytestream and store in next
+ // available entry in the color quad table
+ for (byte i = 0; i < CQUAD; i++) {
+ pixel = stream->readByte();
+ colorTableIndex = CQUAD * colorQuadIndex + i;
+ _colorQuads[colorTableIndex] = pixel;
+ }
+
+ // this is the base index to use for this block
+ colorTableIndex = CQUAD * colorQuadIndex;
+ colorQuadIndex++;
+
+ // wraparound
+ if (colorQuadIndex == COLORS_PER_TABLE)
+ colorQuadIndex = 0;
+ } else
+ colorTableIndex = CQUAD * stream->readByte();
+
+ while (numBlocks--) {
+ colorFlags = stream->readUint32BE();
+
+ // flag mask actually acts as a bit shift count here
+ byte flagMask = 30;
+ blockPtr = rowPtr + pixelPtr;
+
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++) {
+ pixel = colorTableIndex + ((colorFlags >> flagMask) & 0x03);
+ flagMask -= 2;
+ pixels[blockPtr++] = _colorQuads[pixel];
+ }
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // 8-color block encoding
+ case 0xC0:
+ case 0xD0:
+ numBlocks = (opcode & 0x0F) + 1;
+
+ // figure out which color octet to use to paint the 8-color block
+ if ((opcode & 0xF0) == 0xC0) {
+ // fetch the next 8 colors from bytestream and store in next
+ // available entry in the color octet table
+ for (byte i = 0; i < COCTET; i++) {
+ pixel = stream->readByte();
+ colorTableIndex = COCTET * colorOctetIndex + i;
+ _colorOctets[colorTableIndex] = pixel;
+ }
+
+ // this is the base index to use for this block
+ colorTableIndex = COCTET * colorOctetIndex;
+ colorOctetIndex++;
+
+ // wraparound
+ if (colorOctetIndex == COLORS_PER_TABLE)
+ colorOctetIndex = 0;
+ } else
+ colorTableIndex = COCTET * stream->readByte();
+
+ while (numBlocks--) {
+ /*
+ For this input of 6 hex bytes:
+ 01 23 45 67 89 AB
+ Mangle it to this output:
+ flags_a = xx012456, flags_b = xx89A37B
+ */
+
+ // build the color flags
+ byte flagData[6];
+ stream->read(flagData, 6);
+
+ colorFlagsA = ((READ_BE_UINT16(flagData) & 0xFFF0) << 8) | (READ_BE_UINT16(flagData + 2) >> 4);
+ colorFlagsB = ((READ_BE_UINT16(flagData + 4) & 0xFFF0) << 8) | ((flagData[1] & 0xF) << 8) |
+ ((flagData[3] & 0xF) << 4) | (flagData[5] & 0xf);
+
+ colorFlags = colorFlagsA;
+
+ // flag mask actually acts as a bit shift count here
+ byte flagMask = 21;
+ blockPtr = rowPtr + pixelPtr;
+ for (byte y = 0; y < 4; y++) {
+ // reload flags at third row (iteration y == 2)
+ if (y == 2) {
+ colorFlags = colorFlagsB;
+ flagMask = 21;
+ }
+
+ for (byte x = 0; x < 4; x++) {
+ pixel = colorTableIndex + ((colorFlags >> flagMask) & 0x07);
+ flagMask -= 3;
+ pixels[blockPtr++] = _colorOctets[pixel];
+ }
+
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ // 16-color block encoding (every pixel is a different color)
+ case 0xE0:
+ numBlocks = (opcode & 0x0F) + 1;
+
+ while (numBlocks--) {
+ blockPtr = rowPtr + pixelPtr;
+ for (byte y = 0; y < 4; y++) {
+ for (byte x = 0; x < 4; x++)
+ pixels[blockPtr++] = stream->readByte();
+
+ blockPtr += rowInc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ case 0xF0:
+ warning("0xF0 opcode seen in SMC chunk (contact the developers)");
+ break;
+ }
+ }
+
+ return _surface;
+}
+
+} // End of namespace Graphics
Copied: scummvm/trunk/graphics/video/codecs/smc.h (from rev 49161, scummvm/trunk/engines/mohawk/video/smc.h)
===================================================================
--- scummvm/trunk/graphics/video/codecs/smc.h (rev 0)
+++ scummvm/trunk/graphics/video/codecs/smc.h 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GRAPHICS_VIDEO_SMC_H
+#define GRAPHICS_VIDEO_SMC_H
+
+#include "graphics/video/codecs/codec.h"
+
+namespace Graphics {
+
+enum {
+ CPAIR = 2,
+ CQUAD = 4,
+ COCTET = 8,
+ COLORS_PER_TABLE = 256
+};
+
+class SMCDecoder : public Codec {
+public:
+ SMCDecoder(uint16 width, uint16 height);
+ ~SMCDecoder() { delete _surface; }
+
+ Surface *decodeImage(Common::SeekableReadStream *stream);
+ PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); }
+
+private:
+ Surface *_surface;
+
+ // SMC color tables
+ byte _colorPairs[COLORS_PER_TABLE * CPAIR];
+ byte _colorQuads[COLORS_PER_TABLE * CQUAD];
+ byte _colorOctets[COLORS_PER_TABLE * COCTET];
+};
+
+} // End of namespace Graphics
+
+#endif
Copied: scummvm/trunk/graphics/video/qt_decoder.cpp (from rev 49161, scummvm/trunk/engines/mohawk/video/qt_player.cpp)
===================================================================
--- scummvm/trunk/graphics/video/qt_decoder.cpp (rev 0)
+++ scummvm/trunk/graphics/video/qt_decoder.cpp 2010-05-23 18:33:55 UTC (rev 49165)
@@ -0,0 +1,1279 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+//
+// Heavily based on ffmpeg code.
+//
+// Copyright (c) 2001 Fabrice Bellard.
+// First version by Francois Revol revol at free.fr
+// Seek function by Gael Chardon gael.dev at 4now.net
+//
+
+#include "graphics/video/qt_decoder.h"
+
+#include "common/debug.h"
+#include "common/endian.h"
+#include "common/util.h"
+#include "common/zlib.h"
+
+// Audio codecs
+#include "sound/decoders/adpcm.h"
+#include "sound/decoders/raw.h"
+#include "sound/decoders/qdm2.h"
+
+// Video codecs
+#include "graphics/video/codecs/cinepak.h"
+#include "graphics/video/codecs/mjpeg.h"
+#include "graphics/video/codecs/qtrle.h"
+#include "graphics/video/codecs/rpza.h"
+#include "graphics/video/codecs/smc.h"
+
+namespace Graphics {
+
+////////////////////////////////////////////
+// QuickTimeDecoder
+////////////////////////////////////////////
+
+QuickTimeDecoder::QuickTimeDecoder() : VideoDecoder() {
+ _audStream = NULL;
+ _beginOffset = 0;
+ _videoCodec = NULL;
+ _curFrame = -1;
+ _startTime = _nextFrameStartTime = 0;
+ _audHandle = Audio::SoundHandle();
+ _numStreams = 0;
+ _fd = 0;
+ _scaledSurface = 0;
+ _dirtyPalette = false;
+}
+
+QuickTimeDecoder::~QuickTimeDecoder() {
+ close();
+}
+
+uint16 QuickTimeDecoder::getWidth() const {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ return _streams[_videoStreamIndex]->width / getScaleMode();
+}
+
+uint16 QuickTimeDecoder::getHeight() const {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ return _streams[_videoStreamIndex]->height / getScaleMode();
+}
+
+uint32 QuickTimeDecoder::getFrameCount() const {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ return _streams[_videoStreamIndex]->nb_frames;
+}
+
+byte QuickTimeDecoder::getBitsPerPixel() {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ return _streams[_videoStreamIndex]->bits_per_sample & 0x1F;
+}
+
+uint32 QuickTimeDecoder::getCodecTag() {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ return _streams[_videoStreamIndex]->codec_tag;
+}
+
+ScaleMode QuickTimeDecoder::getScaleMode() const {
+ if (_videoStreamIndex < 0)
+ return kScaleNormal;
+
+ return (ScaleMode)(_scaleMode * _streams[_videoStreamIndex]->scaleMode);
+}
+
+uint32 QuickTimeDecoder::getFrameDuration() {
+ if (_videoStreamIndex < 0)
+ return 0;
+
+ uint32 curFrameIndex = 0;
+ for (int32 i = 0; i < _streams[_videoStreamIndex]->stts_count; i++) {
+ curFrameIndex += _streams[_videoStreamIndex]->stts_data[i].count;
+ if ((uint32)_curFrame < curFrameIndex) {
+ // Ok, now we have what duration this frame has.
+ return _streams[_videoStreamIndex]->stts_data[i].duration;
+ }
+ }
+
+ // This should never occur
+ error ("Cannot find duration for frame %d", _curFrame);
+ return 0;
+}
+
+PixelFormat QuickTimeDecoder::getPixelFormat() const {
+ if (!_videoCodec)
+ return PixelFormat::createFormatCLUT8();
+
+ return _videoCodec->getPixelFormat();
+}
+
+void QuickTimeDecoder::rewind() {
+ delete _videoCodec; _videoCodec = NULL;
+ _curFrame = -1;
+ _startTime = _nextFrameStartTime = 0;
+
+ // Restart the audio too
+ stopAudio();
+ if (_audioStreamIndex >= 0) {
+ _curAudioChunk = 0;
+ _audStream = Audio::makeQueuingAudioStream(_streams[_audioStreamIndex]->sample_rate, _streams[_audioStreamIndex]->channels == 2);
+ }
+ startAudio();
+}
+
+Codec *QuickTimeDecoder::createCodec(uint32 codecTag, byte bitsPerPixel) {
+ if (codecTag == MKID_BE('cvid')) {
+ // Cinepak: As used by most Myst and all Riven videos as well as some Myst ME videos. "The Chief" videos also use this.
+ return new CinepakDecoder();
+ } else if (codecTag == MKID_BE('rpza')) {
+ // Apple Video ("Road Pizza"): Used by some Myst videos.
+ return new RPZADecoder(getWidth(), getHeight());
+ } else if (codecTag == MKID_BE('rle ')) {
+ // QuickTime RLE: Used by some Myst ME videos.
+ return new QTRLEDecoder(getWidth(), getHeight(), bitsPerPixel);
+ } else if (codecTag == MKID_BE('smc ')) {
+ // Apple SMC: Used by some Myst videos.
+ return new SMCDecoder(getWidth(), getHeight());
+ } else if (codecTag == MKID_BE('SVQ1')) {
+ // Sorenson Video 1: Used by some Myst ME videos.
+ warning ("Sorenson Video 1 not yet supported");
+ } else if (codecTag == MKID_BE('SVQ3')) {
+ // Sorenson Video 3: Used by some Myst ME videos.
+ warning ("Sorenson Video 3 not yet supported");
+ } else if (codecTag == MKID_BE('jpeg')) {
+ // Motion JPEG: Used by some Myst ME 10th Anniversary videos.
+ return new JPEGDecoder();
+ } else if (codecTag == MKID_BE('QkBk')) {
+ // CDToons: Used by most of the Broderbund games. This is an unknown format so far.
+ warning ("CDToons not yet supported");
+ } else {
+ warning ("Unsupported codec \'%s\'", tag2str(codecTag));
+ }
+
+ return NULL;
+}
+
+void QuickTimeDecoder::startAudio() {
+ if (_audStream) // No audio/audio not supported
+ g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audHandle, _audStream);
+}
+
+void QuickTimeDecoder::stopAudio() {
+ if (_audStream) {
+ g_system->getMixer()->stopHandle(_audHandle);
+ _audStream = NULL; // the mixer automatically frees the stream
+ }
+}
+
+void QuickTimeDecoder::pauseVideoIntern(bool pause) {
+ if (_audStream)
+ g_system->getMixer()->pauseHandle(_audHandle, pause);
+}
+
+Surface *QuickTimeDecoder::decodeNextFrame() {
+ if (!_videoCodec || _curFrame >= (int32)getFrameCount() - 1)
+ return NULL;
+
+ if (_startTime == 0)
+ _startTime = g_system->getMillis();
+
+ _curFrame++;
+ _nextFrameStartTime += getFrameDuration();
+
+ Common::SeekableReadStream *frameData = getNextFramePacket();
+
+ if (frameData) {
+ Surface *frame = _videoCodec->decodeImage(frameData);
+ delete frameData;
+ return scaleSurface(frame);
+ }
+
+ return NULL;
+}
+
+Surface *QuickTimeDecoder::scaleSurface(Surface *frame) {
+ if (getScaleMode() == kScaleNormal)
+ return frame;
+
+ assert(_scaledSurface);
+
+ for (uint32 j = 0; j < _scaledSurface->h; j++)
+ for (uint32 k = 0; k < _scaledSurface->w; k++)
+ memcpy(_scaledSurface->getBasePtr(k, j), frame->getBasePtr(k * getScaleMode(), j * getScaleMode()), frame->bytesPerPixel);
+
+ return _scaledSurface;
+}
+
+bool QuickTimeDecoder::endOfVideo() const {
+ return (!_audStream || _audStream->endOfData()) && (!_videoCodec || _curFrame >= (int32)getFrameCount() - 1);
+}
+
+bool QuickTimeDecoder::needsUpdate() const {
+ return !endOfVideo() && getTimeToNextFrame() == 0;
+}
+
+uint32 QuickTimeDecoder::getElapsedTime() const {
+ if (_audStream)
+ return g_system->getMixer()->getSoundElapsedTime(_audHandle);
+
+ return g_system->getMillis() - _startTime;
+}
+
+uint32 QuickTimeDecoder::getTimeToNextFrame() const {
+ if (endOfVideo() || _curFrame < 0)
+ return 0;
+
+ // Convert from the Sega FILM base to 1000
+ uint32 nextFrameStartTime = _nextFrameStartTime * 1000 / _streams[_videoStreamIndex]->time_scale;
+ uint32 elapsedTime = getElapsedTime();
+
+ if (nextFrameStartTime <= elapsedTime)
+ return 0;
+
+ return nextFrameStartTime - elapsedTime;
+}
+
+bool QuickTimeDecoder::load(Common::SeekableReadStream &stream) {
+ _fd = &stream;
+ _foundMOOV = _foundMDAT = false;
+ _numStreams = 0;
+ _partial = 0;
+ _videoStreamIndex = _audioStreamIndex = -1;
+ _startTime = 0;
+
+ initParseTable();
+
+ MOVatom atom = { 0, 0, 0xffffffff };
+
+ if (readDefault(atom) < 0 || (!_foundMOOV && !_foundMDAT))
+ return false;
+
+ debug(0, "on_parse_exit_offset=%d", _fd->pos());
+
+ // some cleanup : make sure we are on the mdat atom
+ if((uint32)_fd->pos() != _mdatOffset)
+ _fd->seek(_mdatOffset, SEEK_SET);
+
+ _next_chunk_offset = _mdatOffset; // initialise reading
+
+ for (uint32 i = 0; i < _numStreams;) {
+ if (_streams[i]->codec_type == CODEC_TYPE_MOV_OTHER) {// not audio, not video, delete
+ delete _streams[i];
+ for (uint32 j = i + 1; j < _numStreams; j++)
+ _streams[j - 1] = _streams[j];
+ _numStreams--;
+ } else
+ i++;
+ }
+
+ for (uint32 i = 0; i < _numStreams; i++) {
+ MOVStreamContext *sc = _streams[i];
+
+ if(!sc->time_rate)
+ sc->time_rate = 1;
+
+ if(!sc->time_scale)
+ sc->time_scale = _timeScale;
+
+ //av_set_pts_info(s->streams[i], 64, sc->time_rate, sc->time_scale);
+
+ sc->duration /= sc->time_rate;
+
+ sc->ffindex = i;
+ sc->is_ff_stream = 1;
+
+ if (sc->codec_type == CODEC_TYPE_VIDEO && _videoStreamIndex < 0)
+ _videoStreamIndex = i;
+ else if (sc->codec_type == CODEC_TYPE_AUDIO && _audioStreamIndex < 0)
+ _audioStreamIndex = i;
+ }
+
+ if (_audioStreamIndex >= 0 && checkAudioCodecSupport(_streams[_audioStreamIndex]->codec_tag)) {
+ _audStream = Audio::makeQueuingAudioStream(_streams[_audioStreamIndex]->sample_rate, _streams[_audioStreamIndex]->channels == 2);
+ _curAudioChunk = 0;
+
+ // Make sure the bits per sample transfers to the sample size
+ if (_streams[_audioStreamIndex]->codec_tag == MKID_BE('raw ') || _streams[_audioStreamIndex]->codec_tag == MKID_BE('twos'))
+ _streams[_audioStreamIndex]->sample_size = (_streams[_audioStreamIndex]->bits_per_sample / 8) * _streams[_audioStreamIndex]->channels;
+
+ startAudio();
+ }
+
+ if (_videoStreamIndex >= 0) {
+ _videoCodec = createCodec(getCodecTag(), getBitsPerPixel());
+
+ if (getScaleMode() != kScaleNormal) {
+ // We have to initialize the scaled surface
+ _scaledSurface = new Surface();
+ _scaledSurface->create(getWidth(), getHeight(), getPixelFormat().bytesPerPixel);
+ }
+ }
+
+ return true;
+}
+
+void QuickTimeDecoder::initParseTable() {
+ static const ParseTable p[] = {
+ { MKID_BE('dinf'), &QuickTimeDecoder::readDefault },
+ { MKID_BE('dref'), &QuickTimeDecoder::readLeaf },
+ { MKID_BE('edts'), &QuickTimeDecoder::readDefault },
+ { MKID_BE('elst'), &QuickTimeDecoder::readELST },
+ { MKID_BE('hdlr'), &QuickTimeDecoder::readHDLR },
+ { MKID_BE('mdat'), &QuickTimeDecoder::readMDAT },
+ { MKID_BE('mdhd'), &QuickTimeDecoder::readMDHD },
+ { MKID_BE('mdia'), &QuickTimeDecoder::readDefault },
+ { MKID_BE('minf'), &QuickTimeDecoder::readDefault },
+ { MKID_BE('moov'), &QuickTimeDecoder::readMOOV },
+ { MKID_BE('mvhd'), &QuickTimeDecoder::readMVHD },
+ { MKID_BE('smhd'), &QuickTimeDecoder::readLeaf },
+ { MKID_BE('stbl'), &QuickTimeDecoder::readDefault },
+ { MKID_BE('stco'), &QuickTimeDecoder::readSTCO },
+ { MKID_BE('stsc'), &QuickTimeDecoder::readSTSC },
+ { MKID_BE('stsd'), &QuickTimeDecoder::readSTSD },
+ { MKID_BE('stss'), &QuickTimeDecoder::readSTSS },
+ { MKID_BE('stsz'), &QuickTimeDecoder::readSTSZ },
+ { MKID_BE('stts'), &QuickTimeDecoder::readSTTS },
+ { MKID_BE('tkhd'), &QuickTimeDecoder::readTKHD },
+ { MKID_BE('trak'), &QuickTimeDecoder::readTRAK },
+ { MKID_BE('udta'), &QuickTimeDecoder::readLeaf },
+ { MKID_BE('vmhd'), &QuickTimeDecoder::readLeaf },
+ { MKID_BE('cmov'), &QuickTimeDecoder::readCMOV },
+ { MKID_BE('wave'), &QuickTimeDecoder::readWAVE },
+ { 0, 0 }
+ };
+
+ _parseTable = p;
+}
+
+int QuickTimeDecoder::readDefault(MOVatom atom) {
+ uint32 total_size = 0;
+ MOVatom a;
+ int err = 0;
+
+ a.offset = atom.offset;
+
+ while(((total_size + 8) < atom.size) && !_fd->eos() && !err) {
+ a.size = atom.size;
+ a.type = 0;
+
+ if (atom.size >= 8) {
+ a.size = _fd->readUint32BE();
+ a.type = _fd->readUint32BE();
+ }
+
+ total_size += 8;
+ a.offset += 8;
+ debug(4, "type: %08x %.4s sz: %x %x %x", a.type, tag2str(a.type), a.size, atom.size, total_size);
+
+ if (a.size == 1) { // 64 bit extended size
+ warning("64 bit extended size is not supported in QuickTime");
+ return -1;
+ }
+
+ if (a.size == 0) {
+ a.size = atom.size - total_size;
+ if (a.size <= 8)
+ break;
+ }
+
+ uint32 i = 0;
+
+ for (; _parseTable[i].type != 0 && _parseTable[i].type != a.type; i++)
+ // empty;
+
+ if (a.size < 8)
+ break;
+
+ a.size -= 8;
+
+ if (_parseTable[i].type == 0) { // skip leaf atoms data
+ debug(0, ">>> Skipped [%s]", tag2str(a.type));
+
+ _fd->seek(a.size, SEEK_CUR);
+ } else {
+ uint32 start_pos = _fd->pos();
+ err = (this->*_parseTable[i].func)(a);
+
+ uint32 left = a.size - _fd->pos() + start_pos;
+
+ if (left > 0) // skip garbage at atom end
+ _fd->seek(left, SEEK_CUR);
+ }
+
+ a.offset += a.size;
+ total_size += a.size;
+ }
+
+ if (!err && total_size < atom.size)
+ _fd->seek(atom.size - total_size, SEEK_SET);
+
+ return err;
+}
+
+int QuickTimeDecoder::readLeaf(MOVatom atom) {
+ if (atom.size > 1)
+ _fd->seek(atom.size, SEEK_SET);
+
+ return 0;
+}
+
+int QuickTimeDecoder::readMOOV(MOVatom atom) {
+ if (readDefault(atom) < 0)
+ return -1;
+
+ // we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat'
+ // so we don't parse the whole file if over a network
+ _foundMOOV = true;
+
+ if(_foundMDAT)
+ return 1; // found both, just go
+
+ return 0; // now go for mdat
+}
+
+int QuickTimeDecoder::readCMOV(MOVatom atom) {
+#ifdef USE_ZLIB
+ // Read in the dcom atom
+ _fd->readUint32BE();
+ if (_fd->readUint32BE() != MKID_BE('dcom'))
+ return -1;
+ if (_fd->readUint32BE() != MKID_BE('zlib')) {
+ warning("Unknown cmov compression type");
+ return -1;
+ }
+
+ // Read in the cmvd atom
+ uint32 compressedSize = _fd->readUint32BE() - 12;
+ if (_fd->readUint32BE() != MKID_BE('cmvd'))
+ return -1;
+ uint32 uncompressedSize = _fd->readUint32BE();
+
+ // Read in data
+ byte *compressedData = (byte *)malloc(compressedSize);
+ _fd->read(compressedData, compressedSize);
+
+ // Create uncompressed stream
+ byte *uncompressedData = (byte *)malloc(uncompressedSize);
+
+ // Uncompress the data
+ unsigned long dstLen = uncompressedSize;
+ if (!Common::uncompress(uncompressedData, &dstLen, compressedData, compressedSize)) {
+ warning ("Could not uncompress cmov chunk");
+ return -1;
+ }
+
+ // Load data into a new MemoryReadStream and assign _fd to be that
+ Common::SeekableReadStream *oldStream = _fd;
+ _fd = new Common::MemoryReadStream(uncompressedData, uncompressedSize, DisposeAfterUse::YES);
+
+ // Read the contents of the uncompressed data
+ MOVatom a = { MKID_BE('moov'), 0, uncompressedSize };
+ int err = readDefault(a);
+
+ // Assign the file handle back to the original handle
+ free(compressedData);
+ delete _fd;
+ _fd = oldStream;
+
+ return err;
+#else
+ warning ("zlib not found, cannot read QuickTime cmov atom");
+ return -1;
+#endif
+}
+
+int QuickTimeDecoder::readMVHD(MOVatom atom) {
+ byte version = _fd->readByte(); // version
+ _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
+
+ if (version == 1) {
+ warning("QuickTime version 1");
+ _fd->readUint32BE(); _fd->readUint32BE();
+ _fd->readUint32BE(); _fd->readUint32BE();
+ } else {
+ _fd->readUint32BE(); // creation time
+ _fd->readUint32BE(); // modification time
+ }
+
+ _timeScale = _fd->readUint32BE(); // time scale
+ debug(0, "time scale = %i\n", _timeScale);
+
+ // duration
+ _duration = (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE();
+ _fd->readUint32BE(); // preferred scale
+
+ _fd->readUint16BE(); // preferred volume
+
+ _fd->seek(10, SEEK_CUR); // reserved
+
+ // We only need two values from the movie display matrix. Most of the values are just
+ // skipped. xMod and yMod are 16:16 fixed point numbers, the last part of the 3x3 matrix
+ // is 2:30.
+ uint32 xMod = _fd->readUint32BE();
+ _fd->skip(12);
+ uint32 yMod = _fd->readUint32BE();
+ _fd->skip(16);
+
+ if (xMod != yMod)
+ error("X and Y resolution modifiers differ");
+
+ if (xMod == 0x8000)
+ _scaleMode = kScaleHalf;
+ else if (xMod == 0x4000)
+ _scaleMode = kScaleQuarter;
+ else
+ _scaleMode = kScaleNormal;
+
+ debug(1, "readMVHD(): scaleMode = %d", (int)_scaleMode);
+
+ _fd->readUint32BE(); // preview time
+ _fd->readUint32BE(); // preview duration
+ _fd->readUint32BE(); // poster time
+ _fd->readUint32BE(); // selection time
+ _fd->readUint32BE(); // selection duration
+ _fd->readUint32BE(); // current time
+ _fd->readUint32BE(); // next track ID
+
+ return 0;
+}
+
+int QuickTimeDecoder::readTRAK(MOVatom atom) {
+ MOVStreamContext *sc = new MOVStreamContext();
+
+ if (!sc)
+ return -1;
+
+ sc->sample_to_chunk_index = -1;
@@ Diff output truncated at 100000 characters. @@
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