mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
ZVISION: Make the RLF decoder a subclass of the common video decoder
This way, the redundant MetaAnimation class can now be removed
This commit is contained in:
@@ -1,132 +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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "zvision/animation/meta_animation.h"
|
||||
|
||||
#include "zvision/zvision.h"
|
||||
#include "zvision/graphics/render_manager.h"
|
||||
#include "zvision/scripting/script_manager.h"
|
||||
#include "zvision/video/rlf_decoder.h"
|
||||
#include "zvision/video/zork_avi_decoder.h"
|
||||
|
||||
#include "video/video_decoder.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
MetaAnimation::MetaAnimation(const Common::String &fileName, ZVision *engine)
|
||||
: _fileType(RLF),
|
||||
_curFrame(NULL) {
|
||||
Common::String tmpFileName = fileName;
|
||||
tmpFileName.toLowercase();
|
||||
if (tmpFileName.hasSuffix(".rlf")) {
|
||||
_fileType = RLF;
|
||||
Common::File *_file = engine->getSearchManager()->openFile(tmpFileName);
|
||||
_animation.rlf = new RLFDecoder(_file, false);
|
||||
_frmDelay = _animation.rlf->frameTime();
|
||||
} else if (tmpFileName.hasSuffix(".avi")) {
|
||||
_fileType = AVI;
|
||||
Common::File *_file = engine->getSearchManager()->openFile(tmpFileName);
|
||||
_animation.avi = new ZorkAVIDecoder();
|
||||
_animation.avi->loadStream(_file);
|
||||
_frmDelay = 1000.0 / _animation.avi->getDuration().framerate();
|
||||
} else {
|
||||
warning("Unrecognized animation file type: %s", fileName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
MetaAnimation::~MetaAnimation() {
|
||||
if (_fileType == RLF) {
|
||||
delete _animation.rlf;
|
||||
} else if (_fileType == AVI) {
|
||||
delete _animation.avi;
|
||||
}
|
||||
}
|
||||
|
||||
uint MetaAnimation::frameCount() {
|
||||
if (_fileType == RLF) {
|
||||
return _animation.rlf->frameCount();
|
||||
} else
|
||||
return _animation.avi->getFrameCount();
|
||||
|
||||
}
|
||||
|
||||
uint MetaAnimation::width() {
|
||||
if (_fileType == RLF) {
|
||||
return _animation.rlf->width();
|
||||
} else
|
||||
return _animation.avi->getWidth();
|
||||
}
|
||||
uint MetaAnimation::height() {
|
||||
if (_fileType == RLF) {
|
||||
return _animation.rlf->height();
|
||||
} else
|
||||
return _animation.avi->getHeight();
|
||||
}
|
||||
uint32 MetaAnimation::frameTime() {
|
||||
return _frmDelay;
|
||||
}
|
||||
|
||||
void MetaAnimation::seekToFrame(int frameNumber) {
|
||||
if (frameNumber >= (int)frameCount())
|
||||
frameNumber = frameCount() - 1;
|
||||
|
||||
if (_fileType == RLF) {
|
||||
_animation.rlf->seekToFrame(frameNumber);
|
||||
} else
|
||||
_animation.avi->seekToFrame(frameNumber);
|
||||
}
|
||||
|
||||
const Graphics::Surface *MetaAnimation::decodeNextFrame() {
|
||||
if (_fileType == RLF)
|
||||
_curFrame = _animation.rlf->decodeNextFrame();
|
||||
else
|
||||
_curFrame = _animation.avi->decodeNextFrame();
|
||||
|
||||
return _curFrame;
|
||||
}
|
||||
|
||||
const Graphics::Surface *MetaAnimation::getFrameData(uint frameNumber) {
|
||||
if (frameNumber >= frameCount())
|
||||
frameNumber = frameCount() - 1;
|
||||
|
||||
if (_fileType == RLF) {
|
||||
_curFrame = _animation.rlf->getFrameData(frameNumber);
|
||||
return _curFrame;
|
||||
} else {
|
||||
_animation.avi->seekToFrame(frameNumber);
|
||||
_curFrame = _animation.avi->decodeNextFrame();
|
||||
return _curFrame;
|
||||
}
|
||||
}
|
||||
|
||||
bool MetaAnimation::endOfAnimation() {
|
||||
if (_fileType == RLF) {
|
||||
return _animation.rlf->endOfAnimation();
|
||||
} else
|
||||
return _animation.avi->endOfVideo();
|
||||
}
|
||||
|
||||
} // End of namespace ZVision
|
||||
@@ -1,98 +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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ZVISION_METAANIM_NODE_H
|
||||
#define ZVISION_METAANIM_NODE_H
|
||||
|
||||
#include "zvision/scripting/sidefx.h"
|
||||
#include "zvision/zvision.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/list.h"
|
||||
|
||||
namespace Common {
|
||||
class String;
|
||||
}
|
||||
|
||||
namespace Video {
|
||||
class VideoDecoder;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
struct Surface;
|
||||
}
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class ZVision;
|
||||
class RLFDecoder;
|
||||
|
||||
class MetaAnimation {
|
||||
public:
|
||||
MetaAnimation(const Common::String &fileName, ZVision *engine);
|
||||
~MetaAnimation();
|
||||
|
||||
struct playnode {
|
||||
Common::Rect pos;
|
||||
int32 slot;
|
||||
int32 start;
|
||||
int32 stop;
|
||||
int32 loop;
|
||||
int32 _curFrame;
|
||||
int32 _delay;
|
||||
Graphics::Surface *_scaled;
|
||||
};
|
||||
|
||||
private:
|
||||
enum FileType {
|
||||
RLF = 1,
|
||||
AVI = 2
|
||||
};
|
||||
|
||||
private:
|
||||
union {
|
||||
RLFDecoder *rlf;
|
||||
Video::VideoDecoder *avi;
|
||||
} _animation;
|
||||
|
||||
FileType _fileType;
|
||||
int32 _frmDelay;
|
||||
|
||||
const Graphics::Surface *_curFrame;
|
||||
|
||||
public:
|
||||
|
||||
uint frameCount();
|
||||
uint width();
|
||||
uint height();
|
||||
uint32 frameTime();
|
||||
|
||||
void seekToFrame(int frameNumber);
|
||||
|
||||
const Graphics::Surface *decodeNextFrame();
|
||||
const Graphics::Surface *getFrameData(uint frameNumber);
|
||||
|
||||
bool endOfAnimation();
|
||||
};
|
||||
|
||||
} // End of namespace ZVision
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,6 @@
|
||||
MODULE := engines/zvision
|
||||
|
||||
MODULE_OBJS := \
|
||||
animation/meta_animation.o \
|
||||
core/console.o \
|
||||
core/events.o \
|
||||
core/menu.o \
|
||||
|
||||
@@ -22,20 +22,19 @@
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "zvision/scripting/controls/fist_control.h"
|
||||
|
||||
#include "zvision/zvision.h"
|
||||
#include "zvision/scripting/script_manager.h"
|
||||
#include "zvision/scripting/controls/fist_control.h"
|
||||
#include "zvision/graphics/render_manager.h"
|
||||
#include "zvision/cursors/cursor_manager.h"
|
||||
#include "zvision/animation/meta_animation.h"
|
||||
#include "zvision/utility/utility.h"
|
||||
#include "zvision/video/rlf_decoder.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/file.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
#include "video/video_decoder.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
@@ -106,7 +105,8 @@ void FistControl::renderFrame(uint frameNumber) {
|
||||
const Graphics::Surface *frameData;
|
||||
|
||||
if (_animation) {
|
||||
frameData = _animation->getFrameData(frameNumber);
|
||||
_animation->seekToFrame(frameNumber);
|
||||
frameData = _animation->decodeNextFrame();
|
||||
if (frameData)
|
||||
_engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _anmRect);
|
||||
}
|
||||
@@ -121,7 +121,7 @@ bool FistControl::process(uint32 deltaTimeInMillis) {
|
||||
_frameTime -= deltaTimeInMillis;
|
||||
|
||||
if (_frameTime <= 0) {
|
||||
_frameTime = _animation->frameTime();
|
||||
_frameTime = 1000.0 / _animation->getDuration().framerate();
|
||||
|
||||
renderFrame(_frameCur);
|
||||
|
||||
@@ -194,7 +194,7 @@ void FistControl::readDescFile(const Common::String &fileName) {
|
||||
if (param.matchString("animation_id", true)) {
|
||||
// Not used
|
||||
} else if (param.matchString("animation", true)) {
|
||||
_animation = new MetaAnimation(values, _engine);
|
||||
_animation = _engine->loadAnimation(values);
|
||||
} else if (param.matchString("anim_rect", true)) {
|
||||
int left, top, right, bottom;
|
||||
sscanf(values.c_str(), "%d %d %d %d", &left, &top, &right, &bottom);
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace ZVision {
|
||||
namespace Video {
|
||||
class VideoDecoder;
|
||||
}
|
||||
|
||||
class MetaAnimation;
|
||||
namespace ZVision {
|
||||
|
||||
class FistControl : public Control {
|
||||
public:
|
||||
@@ -58,7 +60,7 @@ private:
|
||||
|
||||
Common::Array<entries> _entries;
|
||||
|
||||
MetaAnimation *_animation;
|
||||
Video::VideoDecoder *_animation;
|
||||
Common::Rect _anmRect;
|
||||
int32 _soundKey;
|
||||
int32 _frameCur;
|
||||
|
||||
@@ -28,14 +28,13 @@
|
||||
#include "zvision/scripting/script_manager.h"
|
||||
#include "zvision/graphics/render_manager.h"
|
||||
#include "zvision/cursors/cursor_manager.h"
|
||||
#include "zvision/animation/meta_animation.h"
|
||||
#include "zvision/utility/utility.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/file.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
#include "video/video_decoder.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
@@ -79,7 +78,7 @@ HotMovControl::HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadSt
|
||||
char filename[64];
|
||||
sscanf(values.c_str(), "%s", filename);
|
||||
values = Common::String(filename);
|
||||
_animation = new MetaAnimation(values, _engine);
|
||||
_animation = _engine->loadAnimation(values);
|
||||
} else if (param.matchString("venus_id", true)) {
|
||||
_venusId = atoi(values.c_str());
|
||||
}
|
||||
@@ -106,7 +105,8 @@ void HotMovControl::renderFrame(uint frameNumber) {
|
||||
const Graphics::Surface *frameData;
|
||||
|
||||
if (_animation) {
|
||||
frameData = _animation->getFrameData(frameNumber);
|
||||
_animation->seekToFrame(frameNumber);
|
||||
frameData = _animation->decodeNextFrame();
|
||||
if (frameData)
|
||||
_engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _rectangle);
|
||||
}
|
||||
@@ -130,7 +130,7 @@ bool HotMovControl::process(uint32 deltaTimeInMillis) {
|
||||
else
|
||||
_engine->getScriptManager()->setStateValue(_key, 2);
|
||||
|
||||
_frameTime = _animation->frameTime();
|
||||
_frameTime = 1000.0 / _animation->getDuration().framerate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace ZVision {
|
||||
namespace Video {
|
||||
class VideoDecoder;
|
||||
}
|
||||
|
||||
class MetaAnimation;
|
||||
namespace ZVision {
|
||||
|
||||
class HotMovControl : public Control {
|
||||
public:
|
||||
@@ -44,7 +46,7 @@ private:
|
||||
int32 _lastRenderedFrame;
|
||||
int32 _cycle;
|
||||
int32 _cyclesCount;
|
||||
MetaAnimation *_animation;
|
||||
Video::VideoDecoder *_animation;
|
||||
Common::Rect _rectangle;
|
||||
Common::Array<Common::Rect> _frames;
|
||||
public:
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "common/str.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/rect.h"
|
||||
#include "video/video_decoder.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
@@ -96,7 +97,7 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre
|
||||
|
||||
sscanf(values.c_str(), "%25s %*u", fileName);
|
||||
|
||||
_animation = new MetaAnimation(fileName, _engine);
|
||||
_animation = _engine->loadAnimation(fileName);
|
||||
_frame = -1;
|
||||
_frameDelay = 0;
|
||||
} else if (param.matchString("focus", true)) {
|
||||
@@ -213,16 +214,17 @@ bool InputControl::process(uint32 deltaTimeInMillis) {
|
||||
bool needDraw = true;// = _textChanged;
|
||||
_frameDelay -= deltaTimeInMillis;
|
||||
if (_frameDelay <= 0) {
|
||||
_frame = (_frame + 1) % _animation->frameCount();
|
||||
_frameDelay = _animation->frameTime();
|
||||
_frame = (_frame + 1) % _animation->getFrameCount();
|
||||
_frameDelay = 1000.0 / _animation->getDuration().framerate();
|
||||
needDraw = true;
|
||||
}
|
||||
|
||||
if (needDraw) {
|
||||
const Graphics::Surface *srf = _animation->getFrameData(_frame);
|
||||
_animation->seekToFrame(_frame);
|
||||
const Graphics::Surface *srf = _animation->decodeNextFrame();
|
||||
uint32 xx = _textRectangle.left + _txtWidth;
|
||||
if (xx >= _textRectangle.left + (_textRectangle.width() - _animation->width()))
|
||||
xx = _textRectangle.left + _textRectangle.width() - _animation->width();
|
||||
if (xx >= _textRectangle.left + (_textRectangle.width() - (int16)_animation->getWidth()))
|
||||
xx = _textRectangle.left + _textRectangle.width() - (int16)_animation->getWidth();
|
||||
_engine->getRenderManager()->blitSurfaceToBkg(*srf, xx, _textRectangle.top);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,15 @@
|
||||
#define ZVISION_INPUT_CONTROL_H
|
||||
|
||||
#include "zvision/scripting/control.h"
|
||||
#include "zvision/animation/meta_animation.h"
|
||||
#include "zvision/text/text.h"
|
||||
#include "zvision/text/string_manager.h"
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Video {
|
||||
class VideoDecoder;
|
||||
}
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class InputControl : public Control {
|
||||
@@ -51,7 +54,7 @@ private:
|
||||
bool _readOnly;
|
||||
|
||||
int16 _txtWidth;
|
||||
MetaAnimation *_animation;
|
||||
Video::VideoDecoder *_animation;
|
||||
int32 _frameDelay;
|
||||
int16 _frame;
|
||||
|
||||
|
||||
@@ -28,15 +28,14 @@
|
||||
#include "zvision/scripting/script_manager.h"
|
||||
#include "zvision/graphics/render_manager.h"
|
||||
#include "zvision/cursors/cursor_manager.h"
|
||||
#include "zvision/animation/meta_animation.h"
|
||||
#include "zvision/utility/utility.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/file.h"
|
||||
#include "common/tokenizer.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
#include "video/video_decoder.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
@@ -106,7 +105,7 @@ void LeverControl::parseLevFile(const Common::String &fileName) {
|
||||
if (param.matchString("animation_id", true)) {
|
||||
// Not used
|
||||
} else if (param.matchString("filename", true)) {
|
||||
_animation = new MetaAnimation(values, _engine);
|
||||
_animation = _engine->loadAnimation(values);
|
||||
} else if (param.matchString("skipcolor", true)) {
|
||||
// Not used
|
||||
} else if (param.matchString("anim_coords", true)) {
|
||||
@@ -374,7 +373,8 @@ void LeverControl::renderFrame(uint frameNumber) {
|
||||
|
||||
const Graphics::Surface *frameData;
|
||||
|
||||
frameData = _animation->getFrameData(frameNumber);
|
||||
_animation->seekToFrame(frameNumber);
|
||||
frameData = _animation->decodeNextFrame();
|
||||
if (frameData)
|
||||
_engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _animationCoords);
|
||||
}
|
||||
|
||||
@@ -28,10 +28,11 @@
|
||||
#include "common/list.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace ZVision {
|
||||
namespace Video {
|
||||
class VideoDecoder;
|
||||
}
|
||||
|
||||
class ZorkAVIDecoder;
|
||||
class MetaAnimation;
|
||||
namespace ZVision {
|
||||
|
||||
class LeverControl : public Control {
|
||||
public:
|
||||
@@ -59,7 +60,7 @@ private:
|
||||
};
|
||||
|
||||
private:
|
||||
MetaAnimation *_animation;
|
||||
Video::VideoDecoder *_animation;
|
||||
|
||||
int _cursor;
|
||||
Common::Rect _animationCoords;
|
||||
|
||||
@@ -28,15 +28,14 @@
|
||||
#include "zvision/scripting/script_manager.h"
|
||||
#include "zvision/graphics/render_manager.h"
|
||||
#include "zvision/cursors/cursor_manager.h"
|
||||
#include "zvision/animation/meta_animation.h"
|
||||
#include "zvision/utility/utility.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/file.h"
|
||||
#include "common/tokenizer.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
#include "video/video_decoder.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
@@ -65,7 +64,7 @@ SafeControl::SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream
|
||||
|
||||
while (!stream.eos() && !line.contains('}')) {
|
||||
if (param.matchString("animation", true)) {
|
||||
_animation = new MetaAnimation(values, _engine);
|
||||
_animation = _engine->loadAnimation(values);
|
||||
} else if (param.matchString("rectangle", true)) {
|
||||
int x;
|
||||
int y;
|
||||
@@ -129,7 +128,8 @@ void SafeControl::renderFrame(uint frameNumber) {
|
||||
int x = _rectangle.left;
|
||||
int y = _rectangle.top;
|
||||
|
||||
frameData = _animation->getFrameData(frameNumber);
|
||||
_animation->seekToFrame(frameNumber);
|
||||
frameData = _animation->decodeNextFrame();
|
||||
if (frameData)
|
||||
_engine->getRenderManager()->blitSurfaceToBkg(*frameData, x, y);
|
||||
}
|
||||
@@ -149,7 +149,7 @@ bool SafeControl::process(uint32 deltaTimeInMillis) {
|
||||
_curFrame--;
|
||||
renderFrame(_curFrame);
|
||||
}
|
||||
_frameTime = _animation->frameTime();
|
||||
_frameTime = 1000.0 / _animation->getDuration().framerate();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -28,10 +28,11 @@
|
||||
#include "common/list.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace ZVision {
|
||||
namespace Video {
|
||||
class VideoDecoder;
|
||||
}
|
||||
|
||||
class ZorkAVIDecoder;
|
||||
class MetaAnimation;
|
||||
namespace ZVision {
|
||||
|
||||
class SafeControl : public Control {
|
||||
public:
|
||||
@@ -41,7 +42,7 @@ public:
|
||||
private:
|
||||
int16 _statesCount;
|
||||
int16 _curState;
|
||||
MetaAnimation *_animation;
|
||||
Video::VideoDecoder *_animation;
|
||||
Common::Point _center;
|
||||
Common::Rect _rectangle;
|
||||
int16 _innerRaduis;
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
#include "zvision/zvision.h"
|
||||
#include "zvision/graphics/render_manager.h"
|
||||
#include "zvision/scripting/script_manager.h"
|
||||
#include "zvision/animation/meta_animation.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
#include "video/video_decoder.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
@@ -39,8 +39,8 @@ AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::S
|
||||
_mask(mask),
|
||||
_animation(NULL) {
|
||||
|
||||
_animation = new MetaAnimation(fileName, engine);
|
||||
_frmDelay = _animation->frameTime();
|
||||
_animation = engine->loadAnimation(fileName);
|
||||
_frmDelay = 1000.0 / _animation->getDuration().framerate();
|
||||
|
||||
if (frate > 0)
|
||||
_frmDelay = 1000.0 / frate;
|
||||
@@ -164,8 +164,8 @@ void AnimationNode::addPlayNode(int32 slot, int x, int y, int x2, int y2, int st
|
||||
nod.start = startFrame;
|
||||
nod.stop = endFrame;
|
||||
|
||||
if (nod.stop >= (int)_animation->frameCount())
|
||||
nod.stop = _animation->frameCount() - 1;
|
||||
if (nod.stop >= (int)_animation->getFrameCount())
|
||||
nod.stop = _animation->getFrameCount() - 1;
|
||||
|
||||
nod.slot = slot;
|
||||
nod._curFrame = -1;
|
||||
|
||||
@@ -27,18 +27,17 @@
|
||||
#include "common/rect.h"
|
||||
#include "common/list.h"
|
||||
|
||||
namespace Common {
|
||||
class String;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
struct Surface;
|
||||
}
|
||||
|
||||
namespace Video {
|
||||
class VideoDecoder;
|
||||
}
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class ZVision;
|
||||
class MetaAnimation;
|
||||
|
||||
class AnimationNode : public SideFX {
|
||||
public:
|
||||
@@ -64,7 +63,7 @@ private:
|
||||
int32 _mask;
|
||||
bool _DisposeAfterUse;
|
||||
|
||||
MetaAnimation *_animation;
|
||||
Video::VideoDecoder *_animation;
|
||||
int32 _frmDelay;
|
||||
|
||||
public:
|
||||
|
||||
@@ -34,75 +34,46 @@
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
RLFDecoder::RLFDecoder(const Common::String &fileName, bool stream)
|
||||
: _stream(stream),
|
||||
_readStream(NULL),
|
||||
_lastFrameRead(0),
|
||||
_frameCount(0),
|
||||
_width(0),
|
||||
_height(0),
|
||||
_frameTime(0),
|
||||
_frames(0),
|
||||
_nextFrame(0),
|
||||
_frameBufferByteSize(0) {
|
||||
|
||||
Common::File *_file = new Common::File;
|
||||
if (!_file->open(fileName)) {
|
||||
warning("RLF animation file %s could not be opened", fileName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
_readStream = _file;
|
||||
|
||||
if (!readHeader()) {
|
||||
warning("%s is not a RLF animation file. Wrong magic number", fileName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
_currentFrameBuffer.create(_width, _height, Graphics::createPixelFormat<565>());
|
||||
_frameBufferByteSize = _width * _height * sizeof(uint16);
|
||||
|
||||
if (!stream) {
|
||||
_frames = new Frame[_frameCount];
|
||||
|
||||
// Read in each frame
|
||||
for (uint i = 0; i < _frameCount; ++i) {
|
||||
_frames[i] = readNextFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RLFDecoder::RLFDecoder(Common::SeekableReadStream *rstream, bool stream)
|
||||
: _stream(stream),
|
||||
_readStream(rstream),
|
||||
_lastFrameRead(0),
|
||||
_frameCount(0),
|
||||
_width(0),
|
||||
_height(0),
|
||||
_frameTime(0),
|
||||
_frames(0),
|
||||
_nextFrame(0),
|
||||
_frameBufferByteSize(0) {
|
||||
|
||||
if (!readHeader()) {
|
||||
warning("Stream is not a RLF animation. Wrong magic number");
|
||||
return;
|
||||
}
|
||||
|
||||
_currentFrameBuffer.create(_width, _height, Graphics::createPixelFormat<565>());
|
||||
_frameBufferByteSize = _width * _height * sizeof(uint16);
|
||||
|
||||
if (!stream) {
|
||||
_frames = new Frame[_frameCount];
|
||||
|
||||
// Read in each frame
|
||||
for (uint i = 0; i < _frameCount; ++i) {
|
||||
_frames[i] = readNextFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RLFDecoder::~RLFDecoder() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool RLFDecoder::loadStream(Common::SeekableReadStream *stream) {
|
||||
close();
|
||||
|
||||
addTrack(new RLFVideoTrack(stream));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RLFDecoder::RLFVideoTrack::RLFVideoTrack(Common::SeekableReadStream *stream)
|
||||
: _readStream(stream),
|
||||
_lastFrameRead(0),
|
||||
_frameCount(0),
|
||||
_width(0),
|
||||
_height(0),
|
||||
_frameTime(0),
|
||||
_frames(0),
|
||||
_curFrame(0),
|
||||
_frameBufferByteSize(0) {
|
||||
|
||||
if (!readHeader()) {
|
||||
warning("Not a RLF animation file. Wrong magic number");
|
||||
return;
|
||||
}
|
||||
|
||||
_currentFrameBuffer.create(_width, _height, Graphics::createPixelFormat<565>());
|
||||
_frameBufferByteSize = _width * _height * sizeof(uint16);
|
||||
|
||||
_frames = new Frame[_frameCount];
|
||||
|
||||
// Read in each frame
|
||||
for (uint i = 0; i < _frameCount; ++i) {
|
||||
_frames[i] = readNextFrame();
|
||||
}
|
||||
}
|
||||
|
||||
RLFDecoder::RLFVideoTrack::~RLFVideoTrack() {
|
||||
for (uint i = 0; i < _frameCount; ++i) {
|
||||
delete[] _frames[i].encodedData;
|
||||
}
|
||||
@@ -111,7 +82,7 @@ RLFDecoder::~RLFDecoder() {
|
||||
_currentFrameBuffer.free();
|
||||
}
|
||||
|
||||
bool RLFDecoder::readHeader() {
|
||||
bool RLFDecoder::RLFVideoTrack::readHeader() {
|
||||
if (_readStream->readUint32BE() != MKTAG('F', 'E', 'L', 'R')) {
|
||||
return false;
|
||||
}
|
||||
@@ -160,8 +131,8 @@ bool RLFDecoder::readHeader() {
|
||||
return true;
|
||||
}
|
||||
|
||||
RLFDecoder::Frame RLFDecoder::readNextFrame() {
|
||||
RLFDecoder::Frame frame;
|
||||
RLFDecoder::RLFVideoTrack::Frame RLFDecoder::RLFVideoTrack::readNextFrame() {
|
||||
RLFDecoder::RLFVideoTrack::Frame frame;
|
||||
|
||||
_readStream->readUint32BE(); // Magic number MARF
|
||||
uint32 size = _readStream->readUint32LE(); // Size
|
||||
@@ -188,30 +159,30 @@ RLFDecoder::Frame RLFDecoder::readNextFrame() {
|
||||
return frame;
|
||||
}
|
||||
|
||||
void RLFDecoder::seekToFrame(int frameNumber) {
|
||||
assert(!_stream);
|
||||
assert(frameNumber < (int)_frameCount || frameNumber >= -1);
|
||||
bool RLFDecoder::RLFVideoTrack::seek(const Audio::Timestamp &time) {
|
||||
uint frame = getFrameAtTime(time);
|
||||
assert(frame < (int)_frameCount);
|
||||
|
||||
if (_nextFrame == frameNumber)
|
||||
return;
|
||||
if ((uint)_curFrame == frame)
|
||||
return true;
|
||||
|
||||
if (frameNumber < 0) {
|
||||
_nextFrame = 0;
|
||||
return;
|
||||
if (frame < 0) {
|
||||
_curFrame = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
int closestFrame = _nextFrame;
|
||||
int distance = (int)frameNumber - _nextFrame;
|
||||
int closestFrame = _curFrame;
|
||||
int distance = (int)frame - _curFrame;
|
||||
|
||||
if (distance < 0) {
|
||||
for (uint i = 0; i < _completeFrames.size(); ++i) {
|
||||
if ((int)_completeFrames[i] > frameNumber)
|
||||
if ((int)_completeFrames[i] > frame)
|
||||
break;
|
||||
closestFrame = _completeFrames[i];
|
||||
}
|
||||
} else {
|
||||
for (uint i = 0; i < _completeFrames.size(); ++i) {
|
||||
int newDistance = (int)frameNumber - (int)(_completeFrames[i]);
|
||||
int newDistance = (int)frame - (int)(_completeFrames[i]);
|
||||
if (newDistance < 0)
|
||||
break;
|
||||
if (newDistance < distance) {
|
||||
@@ -221,43 +192,27 @@ void RLFDecoder::seekToFrame(int frameNumber) {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = closestFrame; i < frameNumber; ++i) {
|
||||
for (uint i = closestFrame; i < frame; ++i) {
|
||||
applyFrameToCurrent(i);
|
||||
}
|
||||
|
||||
_nextFrame = frameNumber;
|
||||
_curFrame = frame;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const Graphics::Surface *RLFDecoder::getFrameData(uint frameNumber) {
|
||||
assert(!_stream);
|
||||
assert(frameNumber < _frameCount);
|
||||
const Graphics::Surface *RLFDecoder::RLFVideoTrack::decodeNextFrame() {
|
||||
// When an animation ends, rewind
|
||||
if (_curFrame == (int)_frameCount)
|
||||
seek(Audio::Timestamp(0, getFrameRate().toInt()));
|
||||
|
||||
applyFrameToCurrent(_curFrame);
|
||||
|
||||
// Since this method is so expensive, first check to see if we can use
|
||||
// decodeNextFrame() it's cheap.
|
||||
if ((int)frameNumber == _nextFrame - 1) {
|
||||
return &_currentFrameBuffer;
|
||||
} else if (_nextFrame == (int)frameNumber) {
|
||||
return decodeNextFrame();
|
||||
}
|
||||
|
||||
seekToFrame(frameNumber);
|
||||
return decodeNextFrame();
|
||||
}
|
||||
|
||||
const Graphics::Surface *RLFDecoder::decodeNextFrame() {
|
||||
assert(_nextFrame < (int)_frameCount);
|
||||
|
||||
if (_stream) {
|
||||
applyFrameToCurrent(readNextFrame());
|
||||
} else {
|
||||
applyFrameToCurrent(_nextFrame);
|
||||
}
|
||||
|
||||
_nextFrame++;
|
||||
_curFrame++;
|
||||
return &_currentFrameBuffer;
|
||||
}
|
||||
|
||||
void RLFDecoder::applyFrameToCurrent(uint frameNumber) {
|
||||
void RLFDecoder::RLFVideoTrack::applyFrameToCurrent(uint frameNumber) {
|
||||
if (_frames[frameNumber].type == Masked) {
|
||||
decodeMaskedRunLengthEncoding(_frames[frameNumber].encodedData, (int8 *)_currentFrameBuffer.getPixels(), _frames[frameNumber].encodedSize, _frameBufferByteSize);
|
||||
} else if (_frames[frameNumber].type == Simple) {
|
||||
@@ -265,15 +220,7 @@ void RLFDecoder::applyFrameToCurrent(uint frameNumber) {
|
||||
}
|
||||
}
|
||||
|
||||
void RLFDecoder::applyFrameToCurrent(const RLFDecoder::Frame &frame) {
|
||||
if (frame.type == Masked) {
|
||||
decodeMaskedRunLengthEncoding(frame.encodedData, (int8 *)_currentFrameBuffer.getPixels(), frame.encodedSize, _frameBufferByteSize);
|
||||
} else if (frame.type == Simple) {
|
||||
decodeSimpleRunLengthEncoding(frame.encodedData, (int8 *)_currentFrameBuffer.getPixels(), frame.encodedSize, _frameBufferByteSize);
|
||||
}
|
||||
}
|
||||
|
||||
void RLFDecoder::decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const {
|
||||
void RLFDecoder::RLFVideoTrack::decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const {
|
||||
uint32 sourceOffset = 0;
|
||||
uint32 destOffset = 0;
|
||||
int16 numberOfCopy = 0;
|
||||
@@ -320,7 +267,7 @@ void RLFDecoder::decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint32
|
||||
}
|
||||
}
|
||||
|
||||
void RLFDecoder::decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const {
|
||||
void RLFDecoder::RLFVideoTrack::decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const {
|
||||
uint32 sourceOffset = 0;
|
||||
uint32 destOffset = 0;
|
||||
int16 numberOfCopy = 0;
|
||||
|
||||
@@ -24,147 +24,109 @@
|
||||
#define ZVISION_RLF_DECODER_H
|
||||
|
||||
#include "common/file.h"
|
||||
#include "video/video_decoder.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Common {
|
||||
class String;
|
||||
}
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class RLFDecoder {
|
||||
class RLFDecoder : public Video::VideoDecoder {
|
||||
public:
|
||||
RLFDecoder(const Common::String &fileName, bool stream = true);
|
||||
RLFDecoder(Common::SeekableReadStream *rstream, bool stream);
|
||||
RLFDecoder() {}
|
||||
~RLFDecoder();
|
||||
|
||||
private:
|
||||
enum EncodingType {
|
||||
Masked,
|
||||
Simple
|
||||
};
|
||||
|
||||
struct Frame {
|
||||
EncodingType type;
|
||||
int8 *encodedData;
|
||||
uint32 encodedSize;
|
||||
};
|
||||
bool loadStream(Common::SeekableReadStream *stream);
|
||||
|
||||
private:
|
||||
Common::SeekableReadStream *_readStream;
|
||||
bool _stream;
|
||||
uint _lastFrameRead;
|
||||
class RLFVideoTrack : public FixedRateVideoTrack {
|
||||
public:
|
||||
RLFVideoTrack(Common::SeekableReadStream *stream);
|
||||
~RLFVideoTrack();
|
||||
|
||||
uint _frameCount;
|
||||
uint _width;
|
||||
uint _height;
|
||||
uint32 _frameTime; // In milliseconds
|
||||
Frame *_frames;
|
||||
Common::Array<uint> _completeFrames;
|
||||
uint16 getWidth() const { return _width; }
|
||||
uint16 getHeight() const { return _height; }
|
||||
Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); /*RGB 565*/ }
|
||||
int getCurFrame() const { return _curFrame; }
|
||||
int getFrameCount() const { return _frameCount; }
|
||||
const Graphics::Surface *decodeNextFrame();
|
||||
bool isSeekable() const { return true; }
|
||||
bool seek(const Audio::Timestamp &time);
|
||||
|
||||
int _nextFrame;
|
||||
Graphics::Surface _currentFrameBuffer;
|
||||
uint32 _frameBufferByteSize;
|
||||
protected:
|
||||
Common::Rational getFrameRate() const { return Common::Rational(60, _frameTime); }
|
||||
|
||||
public:
|
||||
uint frameCount() {
|
||||
return _frameCount;
|
||||
}
|
||||
uint width() {
|
||||
return _width;
|
||||
}
|
||||
uint height() {
|
||||
return _height;
|
||||
}
|
||||
uint32 frameTime() {
|
||||
return _frameTime;
|
||||
}
|
||||
private:
|
||||
enum EncodingType {
|
||||
Masked,
|
||||
Simple
|
||||
};
|
||||
|
||||
/**
|
||||
* Seeks to the frameNumber and updates the internal Surface with
|
||||
* the new frame data. If frameNumber == -1, it only sets _currentFrame,
|
||||
* the internal Surface is unchanged. This function requires _stream = false
|
||||
*
|
||||
* @param frameNumber The frame number to seek to
|
||||
*/
|
||||
void seekToFrame(int frameNumber);
|
||||
struct Frame {
|
||||
EncodingType type;
|
||||
int8 *encodedData;
|
||||
uint32 encodedSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the pixel data of the frame specified. It will try to use
|
||||
* decodeNextFrame() if possible. If not, it uses seekToFrame() to
|
||||
* update the internal Surface and then returns a pointer to it.
|
||||
* This function requires _stream = false
|
||||
*
|
||||
* @param frameNumber The frame number to get data for
|
||||
* @return A pointer to the pixel data. Do NOT delete this.
|
||||
*/
|
||||
const Graphics::Surface *getFrameData(uint frameNumber);
|
||||
/**
|
||||
* Returns the pixel data of current frame and go to next. It is up to the user to
|
||||
* check if the current frame is valid before calling this.
|
||||
* IE. Use endOfAnimation()
|
||||
*
|
||||
* @return A pointer to the pixel data. Do NOT delete this.
|
||||
*/
|
||||
const Graphics::Surface *decodeNextFrame();
|
||||
/**
|
||||
* @return Is the currentFrame is the last frame in the animation?
|
||||
*/
|
||||
bool endOfAnimation() {
|
||||
return _nextFrame == (int)_frameCount;
|
||||
}
|
||||
/**
|
||||
* Reads in the header of the RLF file
|
||||
*
|
||||
* @return Will return false if the header magic number is wrong
|
||||
*/
|
||||
bool readHeader();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Reads in the header of the RLF file
|
||||
*
|
||||
* @return Will return false if the header magic number is wrong
|
||||
*/
|
||||
bool readHeader();
|
||||
/**
|
||||
* Reads the next frame from the RLF file, stores the data in
|
||||
* a Frame object, then returns the object
|
||||
*
|
||||
* @return A Frame object representing the frame data
|
||||
*/
|
||||
Frame readNextFrame();
|
||||
/**
|
||||
* Reads the next frame from the RLF file, stores the data in
|
||||
* a Frame object, then returns the object
|
||||
*
|
||||
* @return A Frame object representing the frame data
|
||||
*/
|
||||
Frame readNextFrame();
|
||||
|
||||
/**
|
||||
* Applies the frame corresponding to frameNumber on top of _currentFrameBuffer.
|
||||
* This function requires _stream = false so it can look up the Frame object
|
||||
* referenced by frameNumber.
|
||||
*
|
||||
* @param frameNumber The frame number to apply to _currentFrameBuffer
|
||||
*/
|
||||
void applyFrameToCurrent(uint frameNumber);
|
||||
/**
|
||||
* Applies the data from a Frame object on top of a _currentFrameBuffer.
|
||||
*
|
||||
* @param frame A Frame object to apply to _currentFrameBuffer
|
||||
*/
|
||||
void applyFrameToCurrent(const RLFDecoder::Frame &frame);
|
||||
/**
|
||||
* Applies the frame corresponding to frameNumber on top of _currentFrameBuffer.
|
||||
* This function requires _stream = false so it can look up the Frame object
|
||||
* referenced by frameNumber.
|
||||
*
|
||||
* @param frameNumber The frame number to apply to _currentFrameBuffer
|
||||
*/
|
||||
void applyFrameToCurrent(uint frameNumber);
|
||||
|
||||
/**
|
||||
* Decode frame data that uses masked run length encoding. This is the encoding
|
||||
* used by P-frames.
|
||||
*
|
||||
* @param source The source pixel data
|
||||
* @param dest The destination buffer
|
||||
* @param sourceSize The size of the source pixel data
|
||||
* @param destSize The size of the destination buffer
|
||||
*/
|
||||
void decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const;
|
||||
/**
|
||||
* Decode frame data that uses simple run length encoding. This is the encoding
|
||||
* used by I-frames.
|
||||
*
|
||||
* @param source The source pixel data
|
||||
* @param dest The destination buffer
|
||||
* @param sourceSize The size of the source pixel data
|
||||
* @param destSize The size of the destination buffer
|
||||
*/
|
||||
void decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const;
|
||||
/**
|
||||
* Decode frame data that uses masked run length encoding. This is the encoding
|
||||
* used by P-frames.
|
||||
*
|
||||
* @param source The source pixel data
|
||||
* @param dest The destination buffer
|
||||
* @param sourceSize The size of the source pixel data
|
||||
* @param destSize The size of the destination buffer
|
||||
*/
|
||||
void decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const;
|
||||
/**
|
||||
* Decode frame data that uses simple run length encoding. This is the encoding
|
||||
* used by I-frames.
|
||||
*
|
||||
* @param source The source pixel data
|
||||
* @param dest The destination buffer
|
||||
* @param sourceSize The size of the source pixel data
|
||||
* @param destSize The size of the destination buffer
|
||||
*/
|
||||
void decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const;
|
||||
|
||||
uint _lastFrameRead;
|
||||
|
||||
uint _frameCount;
|
||||
uint _width;
|
||||
uint _height;
|
||||
uint32 _frameTime; // In milliseconds
|
||||
Frame *_frames;
|
||||
Common::Array<uint> _completeFrames;
|
||||
|
||||
int _curFrame;
|
||||
Graphics::Surface _currentFrameBuffer;
|
||||
uint32 _frameBufferByteSize;
|
||||
|
||||
Common::SeekableReadStream *_readStream;
|
||||
}; // RLFVideoTrack
|
||||
};
|
||||
|
||||
} // End of namespace ZVision
|
||||
|
||||
@@ -30,9 +30,29 @@
|
||||
#include "zvision/utility/clock.h"
|
||||
#include "zvision/graphics/render_manager.h"
|
||||
#include "zvision/graphics/subtitles.h"
|
||||
#include "zvision/video/rlf_decoder.h"
|
||||
#include "zvision/video/zork_avi_decoder.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
Video::VideoDecoder *ZVision::loadAnimation(const Common::String &fileName) {
|
||||
Common::String tmpFileName = fileName;
|
||||
tmpFileName.toLowercase();
|
||||
Video::VideoDecoder *animation = NULL;
|
||||
|
||||
if (tmpFileName.hasSuffix(".rlf"))
|
||||
animation = new RLFDecoder();
|
||||
else if (tmpFileName.hasSuffix(".avi"))
|
||||
animation = new ZorkAVIDecoder();
|
||||
else
|
||||
error("Unknown suffix for animation %s", fileName.c_str());
|
||||
|
||||
Common::File *_file = getSearchManager()->openFile(tmpFileName);
|
||||
animation->loadStream(_file);
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
void ZVision::playVideo(Video::VideoDecoder &vid, const Common::Rect &destRect, bool skippable, Subtitle *sub) {
|
||||
Common::Rect dst = destRect;
|
||||
// If destRect is empty, no specific scaling was requested. However, we may choose to do scaling anyway
|
||||
|
||||
@@ -173,6 +173,7 @@ public:
|
||||
* @param skippable If true, the video can be skipped at any time using [Spacebar]
|
||||
*/
|
||||
void playVideo(Video::VideoDecoder &videoDecoder, const Common::Rect &destRect = Common::Rect(0, 0, 0, 0), bool skippable = true, Subtitle *sub = NULL);
|
||||
Video::VideoDecoder *loadAnimation(const Common::String &fileName);
|
||||
|
||||
void rotateTo(int16 to, int16 time);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user