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:
Filippos Karapetis
2014-12-16 01:58:55 +02:00
parent 67bd78a95f
commit 7f61a09478
19 changed files with 238 additions and 529 deletions
@@ -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
View File
@@ -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:
+68 -121
View File
@@ -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;
+85 -123
View File
@@ -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
+20
View File
@@ -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
+1
View File
@@ -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);