aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/saga/introproc_fta2.cpp119
-rw-r--r--graphics/module.mk3
-rw-r--r--graphics/video/dxa_player.cpp186
-rw-r--r--graphics/video/dxa_player.h89
-rw-r--r--graphics/video/smk_player.cpp128
-rw-r--r--graphics/video/smk_player.h90
-rw-r--r--graphics/video/video_player.cpp216
-rw-r--r--graphics/video/video_player.h170
8 files changed, 528 insertions, 473 deletions
diff --git a/engines/saga/introproc_fta2.cpp b/engines/saga/introproc_fta2.cpp
index 72d824d610..8d2e73b7a6 100644
--- a/engines/saga/introproc_fta2.cpp
+++ b/engines/saga/introproc_fta2.cpp
@@ -37,110 +37,24 @@
#include "common/events.h"
#include "common/system.h"
+#include "common/list.h"
namespace Saga {
-class MoviePlayerSMK : Graphics::SMKPlayer {
-protected:
- virtual void setPalette(byte *pal);
-public:
- MoviePlayerSMK(SagaEngine *vm): _vm(vm), SMKPlayer(vm->_mixer),
- _eventMan(vm->_system->getEventManager()) {
- }
- ~MoviePlayerSMK(void) { }
-
- void playVideo(const char *filename);
-private:
- void processFrame();
- void processEvents();
- PalEntry _smkPalette[256];
- bool _skipVideo;
- SagaEngine *_vm;
- Common::EventManager *_eventMan;
-};
-
-void MoviePlayerSMK::setPalette(byte *pal) {
- for (int i = 0; i < 256; i++) {
- _smkPalette[i].red = *pal++;
- _smkPalette[i].green = *pal++;
- _smkPalette[i].blue = *pal++;
- }
-
- _vm->_gfx->setPalette(_smkPalette, true);
-}
-
-void MoviePlayerSMK::processEvents() {
- Common::Event curEvent;
- // Process events, and skip video if esc is pressed
- while (_eventMan->pollEvent(curEvent)) {
- switch (curEvent.type) {
- case Common::EVENT_KEYDOWN:
- if (curEvent.kbd.keycode == Common::KEYCODE_ESCAPE)
- _skipVideo = true;
- break;
- case Common::EVENT_RTL:
- case Common::EVENT_QUIT:
- _skipVideo = true;
- break;
- default:
- break;
- }
- }
-}
-
-void MoviePlayerSMK::playVideo(const char *filename) {
- _skipVideo = false;
- debug(0, "Playing video %s", filename);
-
- if (!loadFile(filename)) {
- warning("Failed to load video file %s", filename);
- return;
- }
-
- while (getCurFrame() < getFrameCount() && !_skipVideo && !_vm->shouldQuit()) {
- processEvents();
- processFrame();
- }
-
- closeFile();
-}
-
-void MoviePlayerSMK::processFrame() {
- uint32 startTime = 0;
- decodeNextFrame();
-
- Graphics::Surface *screen = _vm->_system->lockScreen();
- copyFrameToBuffer((byte *)screen->pixels,
- (_vm->getDisplayInfo().width - getWidth()) / 2,
- (_vm->getDisplayInfo().height - getHeight()) / 2,
- _vm->getDisplayInfo().width);
- _vm->_system->unlockScreen();
-
- uint32 waitTime = getFrameWaitTime();
-
- if (!waitTime) {
- warning("dropped frame %i", getCurFrame());
- return;
- }
-
- // Update the screen
- _vm->_system->updateScreen();
-
- startTime = _vm->_system->getMillis();
-
- // Wait before showing the next frame
- while (_vm->_system->getMillis() < startTime + waitTime && !_skipVideo && !_vm->shouldQuit()) {
- processEvents();
- _vm->_system->delayMillis(10);
- }
-}
+Common::List<Common::Event> stopEvents;
int Scene::FTA2StartProc() {
_vm->_gfx->showCursor(false);
- MoviePlayerSMK *smkPlayer = new MoviePlayerSMK(_vm);
- smkPlayer->playVideo("trimark.smk"); // Show Ignite logo
- smkPlayer->playVideo("intro.smk"); // Play introduction
+ Common::Event stopEvent;
+ stopEvents.clear();
+ stopEvent.type = Common::EVENT_KEYDOWN;
+ stopEvent.kbd = Common::KEYCODE_ESCAPE;
+ stopEvents.push_back(stopEvent);
+
+ Graphics::SMKPlayer *smkPlayer = new Graphics::SMKPlayer(_vm->_mixer);
+ smkPlayer->playVideo("trimark.smk", &stopEvents); // Show Ignite logo
+ smkPlayer->playVideo("intro.smk", &stopEvents); // Play introduction
delete smkPlayer;
// HACK: Forcibly quit here
@@ -174,9 +88,16 @@ int Scene::FTA2EndProc(FTA2Endings whichEnding) {
_vm->_gfx->showCursor(false);
+
+ Common::Event stopEvent;
+ stopEvents.clear();
+ stopEvent.type = Common::EVENT_KEYDOWN;
+ stopEvent.kbd = Common::KEYCODE_ESCAPE;
+ stopEvents.push_back(stopEvent);
+
// Play ending
- MoviePlayerSMK *smkPlayer = new MoviePlayerSMK(_vm);
- smkPlayer->playVideo(videoName);
+ Graphics::SMKPlayer *smkPlayer = new Graphics::SMKPlayer(_vm->_mixer);
+ smkPlayer->playVideo(videoName, &stopEvents);
delete smkPlayer;
return SUCCESS;
diff --git a/graphics/module.mk b/graphics/module.mk
index ea755ac7bd..75aea2b7da 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -21,7 +21,8 @@ MODULE_OBJS := \
video/dxa_player.o \
video/flic_player.o \
video/mpeg_player.o \
- video/smk_player.o
+ video/smk_player.o \
+ video/video_player.o
ifndef DISABLE_SCALERS
MODULE_OBJS += \
diff --git a/graphics/video/dxa_player.cpp b/graphics/video/dxa_player.cpp
index c1d3f6f7cf..89ca280ce1 100644
--- a/graphics/video/dxa_player.cpp
+++ b/graphics/video/dxa_player.cpp
@@ -40,7 +40,7 @@ DXAPlayer::DXAPlayer() {
_frameBuffer1 = 0;
_frameBuffer2 = 0;
_scaledBuffer = 0;
- _drawBuffer = 0;
+ _videoFrameBuffer = 0;
_inBuffer = 0;
_inBufferSize = 0;
@@ -48,14 +48,14 @@ DXAPlayer::DXAPlayer() {
_decompBuffer = 0;
_decompBufferSize = 0;
- _width = 0;
- _height = 0;
+ _videoInfo.width = 0;
+ _videoInfo.height = 0;
_frameSize = 0;
- _framesCount = 0;
- _frameNum = 0;
- _framesPerSec = 0;
- _frameTicks = 0;
+ _videoInfo.frameCount = 0;
+ _videoInfo.currentFrame = 0;
+ _videoInfo.frameRate = 0;
+ _videoInfo.frameDelay = 0;
_scaleMode = S_NONE;
}
@@ -64,47 +64,12 @@ DXAPlayer::~DXAPlayer() {
closeFile();
}
-int DXAPlayer::getWidth() {
- if (!_fileStream)
- return 0;
- return _width;
-}
-
-int DXAPlayer::getHeight() {
- if (!_fileStream)
- return 0;
- return _height;
-}
-
-int32 DXAPlayer::getCurFrame() {
- if (!_fileStream)
- return -1;
- return _frameNum;
-}
-
-int32 DXAPlayer::getFrameCount() {
- if (!_fileStream)
- return 0;
- return _framesCount;
-}
-
-int32 DXAPlayer::getFrameRate() {
- if (!_fileStream)
- return 0;
- return _framesPerSec;
-}
-
-int32 DXAPlayer::getFrameDelay() {
- if (!_fileStream)
- return 0;
-
- return _frameTicks;
-}
-
bool DXAPlayer::loadFile(const char *fileName) {
uint32 tag;
int32 frameRate;
+ closeFile();
+
_fileStream = SearchMan.openFile(fileName);
if (!_fileStream)
return false;
@@ -113,38 +78,37 @@ bool DXAPlayer::loadFile(const char *fileName) {
assert(tag == MKID_BE('DEXA'));
uint8 flags = _fileStream->readByte();
- _framesCount = _fileStream->readUint16BE();
- frameRate = _fileStream->readUint32BE();
-
- if (frameRate > 0)
- _framesPerSec = 1000 / frameRate;
- else if (frameRate < 0)
- _framesPerSec = 100000 / (-frameRate);
- else
- _framesPerSec = 10;
-
- if (frameRate < 0)
- _frameTicks = -frameRate / 100;
- else
- _frameTicks = frameRate;
+ _videoInfo.frameCount = _fileStream->readUint16BE();
+ frameRate = _fileStream->readSint32BE();
+
+ if (frameRate > 0) {
+ _videoInfo.frameRate = 1000 / frameRate;
+ _videoInfo.frameDelay = frameRate * 100;
+ } else if (frameRate < 0) {
+ _videoInfo.frameRate = 100000 / (-frameRate);
+ _videoInfo.frameDelay = -frameRate;
+ } else {
+ _videoInfo.frameRate = 10;
+ _videoInfo.frameDelay = 10000;
+ }
- _width = _fileStream->readUint16BE();
- _height = _fileStream->readUint16BE();
+ _videoInfo.width = _fileStream->readUint16BE();
+ _videoInfo.height = _fileStream->readUint16BE();
if (flags & 0x80) {
_scaleMode = S_INTERLACED;
- _curHeight = _height / 2;
+ _curHeight = _videoInfo.height / 2;
} else if (flags & 0x40) {
_scaleMode = S_DOUBLE;
- _curHeight = _height / 2;
+ _curHeight = _videoInfo.height / 2;
} else {
_scaleMode = S_NONE;
- _curHeight = _height;
+ _curHeight = _videoInfo.height;
}
debug(2, "flags 0x0%x framesCount %d width %d height %d rate %d ticks %d", flags, getFrameCount(), getWidth(), getHeight(), getFrameRate(), getFrameDelay());
- _frameSize = _width * _height;
+ _frameSize = _videoInfo.width * _videoInfo.height;
_decompBufferSize = _frameSize;
_frameBuffer1 = (uint8 *)malloc(_frameSize);
_frameBuffer2 = (uint8 *)malloc(_frameSize);
@@ -185,7 +149,7 @@ bool DXAPlayer::loadFile(const char *fileName) {
} while (tag != 0);
}
#endif
- _frameNum = 0;
+ _videoInfo.currentFrame = 0;
return true;
}
@@ -207,20 +171,6 @@ void DXAPlayer::closeFile() {
_decompBuffer = 0;
}
-void DXAPlayer::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
- uint h = _height;
- uint w = _width;
-
- byte *src = _drawBuffer;
- dst += y * pitch + x;
-
- do {
- memcpy(dst, src, w);
- dst += pitch;
- src += _width;
- } while (--h);
-}
-
void DXAPlayer::decodeZlib(byte *data, int size, int totalSize) {
#ifdef USE_ZLIB
unsigned long dstLen = totalSize;
@@ -245,10 +195,10 @@ void DXAPlayer::decode12(int size) {
memcpy(_frameBuffer2, _frameBuffer1, _frameSize);
- for (int by = 0; by < _height; by += BLOCKH) {
- for (int bx = 0; bx < _width; bx += BLOCKW) {
+ for (uint32 by = 0; by < _videoInfo.height; by += BLOCKH) {
+ for (uint32 bx = 0; bx < _videoInfo.width; bx += BLOCKW) {
byte type = *dat++;
- byte *b2 = _frameBuffer1 + bx + by * _width;
+ byte *b2 = _frameBuffer1 + bx + by * _videoInfo.width;
switch (type) {
case 0:
@@ -280,7 +230,7 @@ void DXAPlayer::decode12(int size) {
}
diffMap <<= 1;
}
- b2 += _width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -291,7 +241,7 @@ void DXAPlayer::decode12(int size) {
for (int xc = 0; xc < BLOCKW; xc++) {
b2[xc] = color;
}
- b2 += _width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -300,7 +250,7 @@ void DXAPlayer::decode12(int size) {
for (int xc = 0; xc < BLOCKW; xc++) {
b2[xc] = *dat++;
}
- b2 += _width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -312,11 +262,11 @@ void DXAPlayer::decode12(int size) {
int my = mbyte & 0x07;
if (mbyte & 0x08)
my = -my;
- byte *b1 = _frameBuffer2 + (bx+mx) + (by+my) * _width;
+ byte *b1 = _frameBuffer2 + (bx+mx) + (by+my) * _videoInfo.width;
for (int yc = 0; yc < BLOCKH; yc++) {
memcpy(b2, b1, BLOCKW);
- b1 += _width;
- b2 += _width;
+ b1 += _videoInfo.width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -345,7 +295,7 @@ void DXAPlayer::decode13(int size) {
memcpy(_frameBuffer2, _frameBuffer1, _frameSize);
- int codeSize = _width * _curHeight / 16;
+ int codeSize = _videoInfo.width * _curHeight / 16;
int dataSize, motSize, maskSize;
dataSize = READ_BE_UINT32(&_decompBuffer[0]);
@@ -357,10 +307,10 @@ void DXAPlayer::decode13(int size) {
motBuf = &dataBuf[dataSize];
maskBuf = &motBuf[motSize];
- for (int by = 0; by < _curHeight; by += BLOCKH) {
- for (int bx = 0; bx < _width; bx += BLOCKW) {
+ for (uint32 by = 0; by < _curHeight; by += BLOCKH) {
+ for (uint32 bx = 0; bx < _videoInfo.width; bx += BLOCKW) {
uint8 type = *codeBuf++;
- uint8 *b2 = (uint8*)_frameBuffer1 + bx + by * _width;
+ uint8 *b2 = (uint8*)_frameBuffer1 + bx + by * _videoInfo.width;
switch (type) {
case 0:
@@ -377,7 +327,7 @@ void DXAPlayer::decode13(int size) {
}
diffMap <<= 1;
}
- b2 += _width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -388,7 +338,7 @@ void DXAPlayer::decode13(int size) {
for (int xc = 0; xc < BLOCKW; xc++) {
b2[xc] = color;
}
- b2 += _width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -397,7 +347,7 @@ void DXAPlayer::decode13(int size) {
for (int xc = 0; xc < BLOCKW; xc++) {
b2[xc] = *dataBuf++;
}
- b2 += _width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -411,11 +361,11 @@ void DXAPlayer::decode13(int size) {
if (mbyte & 0x08)
my = -my;
- uint8 *b1 = (uint8*)_frameBuffer2 + (bx+mx) + (by+my) * _width;
+ uint8 *b1 = (uint8*)_frameBuffer2 + (bx+mx) + (by+my) * _videoInfo.width;
for (int yc = 0; yc < BLOCKH; yc++) {
memcpy(b2, b1, BLOCKW);
- b1 += _width;
- b2 += _width;
+ b1 += _videoInfo.width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -427,7 +377,7 @@ void DXAPlayer::decode13(int size) {
for (int subBlock = 0; subBlock < 4; subBlock++) {
int sx = bx + subX[subBlock], sy = by + subY[subBlock];
- b2 = (uint8*)_frameBuffer1 + sx + sy * _width;
+ b2 = (uint8*)_frameBuffer1 + sx + sy * _videoInfo.width;
switch (subMask & 0xC0) {
// 00: skip
case 0x00:
@@ -439,7 +389,7 @@ void DXAPlayer::decode13(int size) {
for (int xc = 0; xc < BLOCKW / 2; xc++) {
b2[xc] = subColor;
}
- b2 += _width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -455,11 +405,11 @@ void DXAPlayer::decode13(int size) {
if (mbyte & 0x08)
my = -my;
- uint8 *b1 = (uint8*)_frameBuffer2 + (sx+mx) + (sy+my) * _width;
+ uint8 *b1 = (uint8*)_frameBuffer2 + (sx+mx) + (sy+my) * _videoInfo.width;
for (int yc = 0; yc < BLOCKH / 2; yc++) {
memcpy(b2, b1, BLOCKW / 2);
- b1 += _width;
- b2 += _width;
+ b1 += _videoInfo.width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -469,7 +419,7 @@ void DXAPlayer::decode13(int size) {
for (int xc = 0; xc < BLOCKW / 2; xc++) {
b2[xc] = *dataBuf++;
}
- b2 += _width;
+ b2 += _videoInfo.width;
}
break;
}
@@ -494,7 +444,7 @@ void DXAPlayer::decode13(int size) {
b2[xc] = pixels[code & 1];
code >>= 1;
}
- b2 += _width;
+ b2 += _videoInfo.width;
}
} else {
uint32 code = READ_BE_UINT32(maskBuf);
@@ -504,7 +454,7 @@ void DXAPlayer::decode13(int size) {
b2[xc] = pixels[code & 3];
code >>= 2;
}
- b2 += _width;
+ b2 += _videoInfo.width;
}
}
break;
@@ -517,7 +467,7 @@ void DXAPlayer::decode13(int size) {
#endif
}
-void DXAPlayer::decodeNextFrame() {
+bool DXAPlayer::decodeNextFrame() {
uint32 tag;
tag = _fileStream->readUint32BE();
@@ -560,9 +510,9 @@ void DXAPlayer::decodeNextFrame() {
}
if (type == 3) {
- for (int j = 0; j < _curHeight; ++j) {
- for (int i = 0; i < _width; ++i) {
- const int offs = j * _width + i;
+ for (uint32 j = 0; j < _curHeight; ++j) {
+ for (uint32 i = 0; i < _videoInfo.width; ++i) {
+ const int offs = j * _videoInfo.width + i;
_frameBuffer1[offs] ^= _frameBuffer2[offs];
}
}
@@ -572,24 +522,24 @@ void DXAPlayer::decodeNextFrame() {
switch (_scaleMode) {
case S_INTERLACED:
for (int cy = 0; cy < _curHeight; cy++) {
- memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width);
- memset(&_scaledBuffer[((2 * cy) + 1) * _width], 0, _width);
+ memcpy(&_scaledBuffer[2 * cy * _videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);
+ memset(&_scaledBuffer[((2 * cy) + 1) * _videoInfo.width], 0, _videoInfo.width);
}
- _drawBuffer = _scaledBuffer;
+ _videoFrameBuffer = _scaledBuffer;
break;
case S_DOUBLE:
for (int cy = 0; cy < _curHeight; cy++) {
- memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width);
- memcpy(&_scaledBuffer[((2 * cy) + 1) * _width], &_frameBuffer1[cy * _width], _width);
+ memcpy(&_scaledBuffer[2 * cy * _videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);
+ memcpy(&_scaledBuffer[((2 * cy) + 1) * _videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);
}
- _drawBuffer = _scaledBuffer;
+ _videoFrameBuffer = _scaledBuffer;
break;
case S_NONE:
- _drawBuffer = _frameBuffer1;
+ _videoFrameBuffer = _frameBuffer1;
break;
}
- _frameNum++;
+ return ++_videoInfo.currentFrame < _videoInfo.frameCount;
}
} // End of namespace Graphics
diff --git a/graphics/video/dxa_player.h b/graphics/video/dxa_player.h
index 3239913131..1593658ae7 100644
--- a/graphics/video/dxa_player.h
+++ b/graphics/video/dxa_player.h
@@ -29,56 +29,16 @@
#include "common/scummsys.h"
#include "common/stream.h"
-namespace Graphics {
+#include "graphics/video/video_player.h"
-enum ScaleMode {
- S_NONE,
- S_INTERLACED,
- S_DOUBLE
-};
+namespace Graphics {
-class DXAPlayer {
+class DXAPlayer : public VideoPlayer {
public:
DXAPlayer();
virtual ~DXAPlayer();
/**
- * Returns the width of the video
- * @return the width of the video
- */
- int getWidth();
-
- /**
- * Returns the height of the video
- * @return the height of the video
- */
- int getHeight();
-
- /**
- * Returns the current frame number of the video
- * @return the current frame number of the video
- */
- int32 getCurFrame();
-
- /**
- * Returns the amount of frames in the video
- * @return the amount of frames in the video
- */
- int32 getFrameCount();
-
- /**
- * Returns the frame rate of the video
- * @return the frame rate of the video
- */
- int32 getFrameRate();
-
- /**
- * Returns the time to wait for each frame in 1/100 ms
- * @return the time to wait for each frame in 1/100 ms
- */
- int32 getFrameDelay();
-
- /**
* Load a DXA encoded video file
* @param filename the filename to load
*/
@@ -89,55 +49,28 @@ public:
*/
void closeFile();
- /**
- * Returns if a video file is loaded or not
- */
- bool videoIsLoaded() { return (_fileStream != NULL); }
-
-protected:
- /**
- * Set RGB palette, based on current frame
- * @param pal the RGB palette data
- */
- virtual void setPalette(byte *pal) = 0;
-
- /**
- * Copy current frame into the specified position of the destination
- * buffer.
- * @param dst the buffer
- * @param x the x position of the buffer
- * @param y the y position of the buffer
- * @param pitch the pitch of buffer
- */
- void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);
-
- /**
- * Decode the next frame
- */
- void decodeNextFrame();
+ bool decodeNextFrame();
+private:
void decodeZlib(byte *data, int size, int totalSize);
void decode12(int size);
void decode13(int size);
- Common::SeekableReadStream *_fileStream;
+ enum ScaleMode {
+ S_NONE,
+ S_INTERLACED,
+ S_DOUBLE
+ };
-private:
byte *_frameBuffer1;
byte *_frameBuffer2;
byte *_scaledBuffer;
- byte *_drawBuffer;
byte *_inBuffer;
uint32 _inBufferSize;
byte *_decompBuffer;
uint32 _decompBufferSize;
- uint16 _width;
- uint16 _height, _curHeight;
- uint16 _framesCount;
- uint32 _framesPerSec;
- uint16 _frameNum;
+ uint16 _curHeight;
uint32 _frameSize;
- uint32 _frameTicks;
ScaleMode _scaleMode;
};
diff --git a/graphics/video/smk_player.cpp b/graphics/video/smk_player.cpp
index 548ed70134..f97555bb15 100644
--- a/graphics/video/smk_player.cpp
+++ b/graphics/video/smk_player.cpp
@@ -314,59 +314,16 @@ uint32 BigHuffmanTree::getCode(BitStream &bs) {
}
SMKPlayer::SMKPlayer(Audio::Mixer *mixer)
- : _currentSMKFrame(0), _fileStream(0), _audioStarted(false), _audioStream(0), _mixer(mixer) {
+ : _audioStarted(false), _audioStream(0), _mixer(mixer) {
}
SMKPlayer::~SMKPlayer() {
- closeFile();
-}
-
-int SMKPlayer::getWidth() {
- if (!_fileStream)
- return 0;
- return _header.width;
}
int SMKPlayer::getHeight() {
if (!_fileStream)
return 0;
- return (_header.flags ? 2 : 1) * _header.height;
-}
-
-int32 SMKPlayer::getCurFrame() {
- if (!_fileStream)
- return -1;
- return _currentSMKFrame;
-}
-
-int32 SMKPlayer::getFrameCount() {
- if (!_fileStream)
- return 0;
- return _header.frames;
-}
-
-int32 SMKPlayer::getFrameRate() {
- if (!_fileStream)
- return 0;
-
- if (_header.frameRate > 0)
- return 1000 / _header.frameRate;
- else if (_header.frameRate < 0)
- return 100000 / (-_header.frameRate);
- else
- return 10;
-}
-
-int32 SMKPlayer::getFrameDelay() {
- if (!_fileStream)
- return 0;
-
- if (_header.frameRate > 0)
- return _header.frameRate * 100;
- if (_header.frameRate < 0)
- return -_header.frameRate;
-
- return 10000;
+ return (_header.flags ? 2 : 1) * _videoInfo.height;
}
int32 SMKPlayer::getAudioLag() {
@@ -374,7 +331,7 @@ int32 SMKPlayer::getAudioLag() {
return 0;
int32 frameDelay = getFrameDelay();
- int32 videoTime = _currentSMKFrame * frameDelay;
+ int32 videoTime = _videoInfo.currentFrame * frameDelay;
int32 audioTime;
if (!_audioStream) {
@@ -383,23 +340,16 @@ int32 SMKPlayer::getAudioLag() {
and how much time *should* have passed.
*/
- audioTime = (g_system->getMillis() - _startTime) * 100;
+ audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100;
} else
audioTime = (((int32) _mixer->getSoundElapsedTime(_audioHandle)) * 100);
return videoTime - audioTime;
}
-uint32 SMKPlayer::getFrameWaitTime() {
- int32 waitTime = (getFrameDelay() + getAudioLag()) / 100;
-
- if (waitTime < 0)
- return 0;
-
- return waitTime;
-}
-
bool SMKPlayer::loadFile(const char *fileName) {
+ int32 frameRate;
+
closeFile();
_fileStream = SearchMan.openFile(fileName);
@@ -407,7 +357,7 @@ bool SMKPlayer::loadFile(const char *fileName) {
return false;
// Seek to the first frame
- _currentSMKFrame = 0;
+ _videoInfo.currentFrame = 0;
_header.signature = _fileStream->readUint32BE();
// No BINK support available
@@ -419,10 +369,22 @@ bool SMKPlayer::loadFile(const char *fileName) {
assert(_header.signature == MKID_BE('SMK2') || _header.signature == MKID_BE('SMK4'));
- _header.width = _fileStream->readUint32LE();
- _header.height = _fileStream->readUint32LE();
- _header.frames = _fileStream->readUint32LE();
- _header.frameRate = (int32)_fileStream->readUint32LE();
+ _videoInfo.width = _fileStream->readUint32LE();
+ _videoInfo.height = _fileStream->readUint32LE();
+ _videoInfo.frameCount = _fileStream->readUint32LE();
+ frameRate = _fileStream->readSint32LE();
+
+ if (frameRate > 0) {
+ _videoInfo.frameRate = 1000 / frameRate;
+ _videoInfo.frameDelay = frameRate * 100;
+ } else if (frameRate < 0) {
+ _videoInfo.frameRate = 100000 / (-frameRate);
+ _videoInfo.frameDelay = -frameRate;
+ } else {
+ _videoInfo.frameRate = 10;
+ _videoInfo.frameDelay = 10000;
+ }
+
// Flags are determined by which bit is set, which can be one of the following:
// 0 - set to 1 if file contains a ring frame.
// 1 - set to 1 if file is Y-interlaced
@@ -481,12 +443,12 @@ bool SMKPlayer::loadFile(const char *fileName) {
_header.dummy = _fileStream->readUint32LE();
- _frameSizes = (uint32 *)malloc(_header.frames * sizeof(uint32));
- for (i = 0; i < _header.frames; ++i)
+ _frameSizes = (uint32 *)malloc(_videoInfo.frameCount * sizeof(uint32));
+ for (i = 0; i < _videoInfo.frameCount; ++i)
_frameSizes[i] = _fileStream->readUint32LE();
- _frameTypes = (byte *)malloc(_header.frames);
- for (i = 0; i < _header.frames; ++i)
+ _frameTypes = (byte *)malloc(_videoInfo.frameCount);
+ for (i = 0; i < _videoInfo.frameCount; ++i)
_frameTypes[i] = _fileStream->readByte();
Common::Array<byte> huffmanTrees;
@@ -502,8 +464,8 @@ bool SMKPlayer::loadFile(const char *fileName) {
_FullTree = new BigHuffmanTree(bs);
_TypeTree = new BigHuffmanTree(bs);
- _videoFrameBuffer = (byte *)malloc(2 * _header.width * _header.height);
- memset(_videoFrameBuffer, 0, 2 * _header.width * _header.height);
+ _videoFrameBuffer = (byte *)malloc(2 * _videoInfo.width * _videoInfo.height);
+ memset(_videoFrameBuffer, 0, 2 * _videoInfo.width * _videoInfo.height);
_palette = (byte *)malloc(3 * 256);
memset(_palette, 0, 3 * 256);
@@ -534,20 +496,6 @@ void SMKPlayer::closeFile() {
free(_palette);
}
-void SMKPlayer::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
- uint h = (_header.flags ? 2 : 1) * _header.height;
- uint w = _header.width;
-
- byte *src = _videoFrameBuffer;
- dst += y * pitch + x;
-
- do {
- memcpy(dst, src, w);
- dst += pitch;
- src += _header.width;
- } while (--h);
-}
-
bool SMKPlayer::decodeNextFrame() {
uint i;
uint32 chunkSize = 0;
@@ -555,20 +503,20 @@ bool SMKPlayer::decodeNextFrame() {
uint32 startPos = _fileStream->pos();
- if (_currentSMKFrame == 0)
- _startTime = g_system->getMillis();
+ if (_videoInfo.currentFrame == 0)
+ _videoInfo.startTime = g_system->getMillis();
// Check if we got a frame with palette data, and
// call back the virtual setPalette function to set
// the current palette
- if (_frameTypes[_currentSMKFrame] & 1) {
+ if (_frameTypes[_videoInfo.currentFrame] & 1) {
unpackPalette();
setPalette(_palette);
}
// Load audio tracks
for (i = 0; i < 7; ++i) {
- if (!(_frameTypes[_currentSMKFrame] & (2 << i)))
+ if (!(_frameTypes[_videoInfo.currentFrame] & (2 << i)))
continue;
chunkSize = _fileStream->readUint32LE();
@@ -612,7 +560,7 @@ bool SMKPlayer::decodeNextFrame() {
}
}
- uint32 frameSize = _frameSizes[_currentSMKFrame] & ~3;
+ uint32 frameSize = _frameSizes[_videoInfo.currentFrame] & ~3;
if (_fileStream->pos() - startPos > frameSize)
exit(1);
@@ -631,9 +579,9 @@ bool SMKPlayer::decodeNextFrame() {
_FullTree->reset();
_TypeTree->reset();
- uint bw = _header.width / 4;
- uint bh = _header.height / 4;
- uint stride = _header.width;
+ uint bw = _videoInfo.width / 4;
+ uint bh = _videoInfo.height / 4;
+ uint stride = _videoInfo.width;
uint block = 0, blocks = bw*bh;
uint doubleY = _header.flags ? 2 : 1;
@@ -767,7 +715,7 @@ bool SMKPlayer::decodeNextFrame() {
free(_frameData);
- return ++_currentSMKFrame < _header.frames;
+ return ++_videoInfo.currentFrame < _videoInfo.frameCount;
}
void SMKPlayer::queueCompressedBuffer(byte *buffer, uint32 bufferSize,
diff --git a/graphics/video/smk_player.h b/graphics/video/smk_player.h
index 93f4457f2b..3ddc12e2d6 100644
--- a/graphics/video/smk_player.h
+++ b/graphics/video/smk_player.h
@@ -35,6 +35,8 @@
#include "sound/mixer.h"
#include "sound/audiostream.h"
+#include "graphics/video/video_player.h"
+
namespace Graphics {
class BigHuffmanTree;
@@ -42,97 +44,21 @@ class BigHuffmanTree;
/**
* Implementation of a Smacker v2/v4 video decoder
*/
-class SMKPlayer {
+class SMKPlayer : public Graphics::VideoPlayer {
public:
SMKPlayer(Audio::Mixer *mixer);
virtual ~SMKPlayer();
- /**
- * Returns the width of the video
- * @return the width of the video
- */
- int getWidth();
-
- /**
- * Returns the height of the video
- * @return the height of the video
- */
int getHeight();
-
- /**
- * Returns the current frame number of the video
- * @return the current frame number of the video
- */
- int32 getCurFrame();
-
- /**
- * Returns the amount of frames in the video
- * @return the amount of frames in the video
- */
- int32 getFrameCount();
-
- /**
- * Returns the frame rate of the video
- * @return the frame rate of the video
- */
- int32 getFrameRate();
-
- /**
- * Returns the time to wait for each frame in 1/100 ms
- * @return the time to wait for each frame in 1/100 ms
- */
- int32 getFrameDelay();
-
- /**
- * Returns the current A/V lag in 1/100 ms
- * If > 0, audio lags behind
- * If < 0, video lags behind
- * @return the current A/V lag in 1/100 ms
- */
int32 getAudioLag();
/**
- * Returns the time to wait until the next frame in ms, minding any lag
- * @return the time to wait until the next frame in ms
- */
- uint32 getFrameWaitTime();
-
- /**
* Load an SMK encoded video file
* @param filename the filename to load
*/
bool loadFile(const char *filename);
-
- /**
- * Close an SMK encoded video file
- */
void closeFile();
- /**
- * Returns if a video file is loaded or not
- */
- bool videoIsLoaded() { return (_fileStream != NULL); }
-
-protected:
- /**
- * Set RGB palette, based on current frame
- * @param pal the RGB palette data
- */
- virtual void setPalette(byte *pal) = 0;
-
- /**
- * Copy current frame into the specified position of the destination
- * buffer.
- * @param dst the buffer
- * @param x the x position of the buffer
- * @param y the y position of the buffer
- * @param pitch the pitch of buffer
- */
- void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);
-
- /**
- * Decode the next frame
- */
bool decodeNextFrame();
private:
@@ -152,10 +78,6 @@ private:
struct {
uint32 signature;
- uint32 width;
- uint32 height;
- uint32 frames;
- int32 frameRate;
uint32 flags;
uint32 audioSize[7];
uint32 treesSize;
@@ -182,16 +104,10 @@ private:
Audio::AppendableAudioStream *_audioStream;
Audio::SoundHandle _audioHandle;
- uint32 _currentSMKFrame;
- uint32 _startTime;
-
BigHuffmanTree *_MMapTree;
BigHuffmanTree *_MClrTree;
BigHuffmanTree *_FullTree;
BigHuffmanTree *_TypeTree;
-
- Common::SeekableReadStream *_fileStream;
- byte *_videoFrameBuffer;
};
} // End of namespace Graphics
diff --git a/graphics/video/video_player.cpp b/graphics/video/video_player.cpp
new file mode 100644
index 0000000000..5fc2c72fbf
--- /dev/null
+++ b/graphics/video/video_player.cpp
@@ -0,0 +1,216 @@
+/* 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/archive.h"
+#include "common/events.h"
+#include "common/system.h"
+#include "common/util.h"
+#include "common/array.h"
+#include "common/endian.h"
+
+#include "graphics/video/video_player.h"
+#include "graphics/surface.h"
+
+namespace Graphics {
+
+VideoPlayer::VideoPlayer() : _fileStream(0), _skipVideo(false) {
+}
+
+VideoPlayer::~VideoPlayer() {
+ closeFile();
+}
+
+int VideoPlayer::getWidth() {
+ if (!_fileStream)
+ return 0;
+ return _videoInfo.width;
+}
+
+int VideoPlayer::getHeight() {
+ if (!_fileStream)
+ return 0;
+ return _videoInfo.height;
+}
+
+int32 VideoPlayer::getCurFrame() {
+ if (!_fileStream)
+ return -1;
+ return _videoInfo.currentFrame;
+}
+
+int32 VideoPlayer::getFrameCount() {
+ if (!_fileStream)
+ return 0;
+ return _videoInfo.frameCount;
+}
+
+int32 VideoPlayer::getFrameRate() {
+ if (!_fileStream)
+ return 0;
+ return _videoInfo.frameRate;
+}
+
+int32 VideoPlayer::getFrameDelay() {
+ if (!_fileStream)
+ return 0;
+ return _videoInfo.frameDelay;
+}
+
+int32 VideoPlayer::getAudioLag() {
+ if (!_fileStream)
+ return 0;
+
+ /* No audio.
+ Calculate the lag by how much time has gone by since the first frame
+ and how much time *should* have passed.
+ */
+ int32 audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100;
+ int32 videoTime = _videoInfo.currentFrame * getFrameDelay();
+
+ return videoTime - audioTime;
+}
+
+uint32 VideoPlayer::getFrameWaitTime() {
+ int32 waitTime = (getFrameDelay() + getAudioLag()) / 100;
+
+ if (waitTime < 0)
+ return 0;
+
+ return waitTime;
+}
+
+bool VideoPlayer::loadFile(const char *fileName) {
+ return false;
+}
+
+void VideoPlayer::closeFile() {
+}
+
+void VideoPlayer::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
+ uint h = getHeight();
+ uint w = getWidth();
+
+ byte *src = _videoFrameBuffer;
+ dst += y * pitch + x;
+
+ do {
+ memcpy(dst, src, w);
+ dst += pitch;
+ src += w;
+ } while (--h);
+}
+
+void VideoPlayer::setPalette(byte *pal) {
+ for (int i = 0; i < 256; i++) {
+ _videoPalette[i * 4 + 0] = *pal++;
+ _videoPalette[i * 4 + 1] = *pal++;
+ _videoPalette[i * 4 + 2] = *pal++;
+ _videoPalette[i * 4 + 3] = 0;
+ }
+
+ g_system->setPalette(_videoPalette, 0, 256);
+}
+
+bool VideoPlayer::decodeNextFrame() {
+ return false;
+}
+
+void VideoPlayer::performPostProcessing(byte *screen) {
+}
+
+void VideoPlayer::processVideoEvents(Common::List<Common::Event> *stopEvents) {
+ Common::Event curEvent;
+ Common::EventManager *eventMan = g_system->getEventManager();
+
+ // Process events, and skip video if esc is pressed
+ while (eventMan->pollEvent(curEvent)) {
+ if (curEvent.type == Common::EVENT_RTL || curEvent.type == Common::EVENT_QUIT) {
+ _skipVideo = true;
+ }
+
+ for (Common::List<Common::Event>::const_iterator iter = stopEvents->begin(); iter != stopEvents->end(); iter++) {
+ if (curEvent.type == iter->type) {
+ if (iter->type == Common::EVENT_KEYDOWN || iter->type == Common::EVENT_KEYUP) {
+ if (curEvent.kbd.keycode == iter->kbd.keycode) {
+ _skipVideo = true;
+ break;
+ }
+ } else {
+ _skipVideo = true;
+ break;
+ }
+ }
+ }
+ }
+}
+
+bool VideoPlayer::playVideo(const char *filename, Common::List<Common::Event> *stopEvents) {
+ _skipVideo = false;
+ debug(0, "Playing video %s", filename);
+
+ if (!loadFile(filename)) {
+ warning("Failed to load video file %s", filename);
+ return false;
+ }
+
+ while (getCurFrame() < getFrameCount() && !_skipVideo) {
+ processVideoEvents(stopEvents);
+
+ uint32 startTime = 0;
+ decodeNextFrame();
+
+ Graphics::Surface *screen = g_system->lockScreen();
+ copyFrameToBuffer((byte *)screen->pixels,
+ (g_system->getWidth() - getWidth()) / 2,
+ (g_system->getHeight() - getHeight()) / 2,
+ g_system->getWidth());
+ performPostProcessing((byte *)screen->pixels);
+ g_system->unlockScreen();
+
+ uint32 waitTime = getFrameWaitTime();
+
+ if (!waitTime) {
+ warning("dropped frame %i", getCurFrame());
+ continue;
+ }
+
+ // Update the screen
+ g_system->updateScreen();
+
+ startTime = g_system->getMillis();
+
+ // Wait before showing the next frame
+ while (g_system->getMillis() < startTime + waitTime && !_skipVideo) {
+ processVideoEvents(stopEvents);
+ g_system->delayMillis(10);
+ }
+ }
+
+ closeFile();
+
+ return true;
+}
+
+} // End of namespace Graphics
diff --git a/graphics/video/video_player.h b/graphics/video/video_player.h
new file mode 100644
index 0000000000..6d346f398d
--- /dev/null
+++ b/graphics/video/video_player.h
@@ -0,0 +1,170 @@
+/* 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_PLAYER_H
+#define GRAPHICS_VIDEO_PLAYER_H
+
+#include "common/scummsys.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "common/list.h"
+#include "sound/mixer.h"
+#include "sound/audiostream.h"
+
+namespace Graphics {
+
+/**
+ * Implementation of a generic video decoder
+ */
+class VideoPlayer {
+public:
+ VideoPlayer();
+ virtual ~VideoPlayer();
+
+ /**
+ * Returns the width of the video
+ * @return the width of the video
+ */
+ virtual int getWidth();
+
+ /**
+ * Returns the height of the video
+ * @return the height of the video
+ */
+ virtual int getHeight();
+
+ /**
+ * Returns the current frame number of the video
+ * @return the current frame number of the video
+ */
+ virtual int32 getCurFrame();
+
+ /**
+ * Returns the amount of frames in the video
+ * @return the amount of frames in the video
+ */
+ virtual int32 getFrameCount();
+
+ /**
+ * Returns the frame rate of the video
+ * @return the frame rate of the video
+ */
+ virtual int32 getFrameRate();
+
+ /**
+ * Returns the time to wait for each frame in 1/100 ms
+ * @return the time to wait for each frame in 1/100 ms
+ */
+ virtual int32 getFrameDelay();
+
+ /**
+ * Returns the current A/V lag in 1/100 ms
+ * If > 0, audio lags behind
+ * If < 0, video lags behind
+ * @return the current A/V lag in 1/100 ms
+ */
+ virtual int32 getAudioLag();
+
+ /**
+ * Returns the time to wait until the next frame in ms, minding any lag
+ * @return the time to wait until the next frame in ms
+ */
+ virtual uint32 getFrameWaitTime();
+
+ /**
+ * Load a video file
+ * @param filename the filename to load
+ */
+ virtual bool loadFile(const char *filename);
+
+ /**
+ * Close a video file
+ */
+ virtual void closeFile();
+
+ /**
+ * Returns if a video file is loaded or not
+ */
+ bool videoIsLoaded() { return (_fileStream != NULL); }
+
+ /**
+ * Set RGB palette, based on current frame
+ * @param pal the RGB palette data
+ */
+ virtual void setPalette(byte *pal);
+
+ /**
+ * Copy current frame into the specified position of the destination
+ * buffer.
+ * @param dst the buffer
+ * @param x the x position of the buffer
+ * @param y the y position of the buffer
+ * @param pitch the pitch of buffer
+ */
+ void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);
+
+ /**
+ * Decode the next frame
+ */
+ virtual bool decodeNextFrame();
+
+ /**
+ * A default implementation of a video player
+ * Plays a non-interactive full screen video till it's stopped by a
+ * specific event
+ * @param filename the name of the file to play
+ * @param stopEvents a list of events that can stop the video
+ */
+ bool playVideo(const char *filename, Common::List<Common::Event> *stopEvents);
+
+ /**
+ * Perform postprocessing once the frame data is copied to the screen,
+ * right before the frame is drawn. Called from playVideo()
+ */
+ virtual void performPostProcessing(byte *screen);
+
+protected:
+ struct {
+ uint32 width;
+ uint32 height;
+ uint32 frameCount;
+ int32 frameRate;
+ int32 frameDelay;
+ uint32 currentFrame;
+ uint32 startTime;
+ } _videoInfo;
+
+ Common::SeekableReadStream *_fileStream;
+ byte *_videoFrameBuffer;
+ byte _videoPalette[256 * 4];
+ bool _skipVideo;
+
+private:
+ void processVideoEvents(Common::List<Common::Event> *stopEvents);
+};
+
+} // End of namespace Graphics
+
+#endif