diff options
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/module.mk | 3 | ||||
-rw-r--r-- | graphics/video/dxa_player.cpp | 186 | ||||
-rw-r--r-- | graphics/video/dxa_player.h | 89 | ||||
-rw-r--r-- | graphics/video/smk_player.cpp | 128 | ||||
-rw-r--r-- | graphics/video/smk_player.h | 90 | ||||
-rw-r--r-- | graphics/video/video_player.cpp | 216 | ||||
-rw-r--r-- | graphics/video/video_player.h | 170 |
7 files changed, 508 insertions, 374 deletions
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 |