From 0b4dd7c4593587355c1965eb0d266040c83f0382 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 11 Jan 2009 03:34:50 +0000 Subject: Committed a modified version of wjp's patch for the video player: - Split the video player from the video decoders. It's now possible to have one video player for multiple decoders - Added the palette weight calculation from the BS1 engine into VideoPlayer::setPalette. It's now possible to find the values of the white and black colors via getWhite() and getBlack() (useful for subtitle overlays) - Adapted FTA2's movie playing code to the new changes to video player - Fixed a slight bug in the DXA decoder (_videoinfo.startTime was not initialized) svn-id: r35816 --- graphics/video/dxa_player.cpp | 4 ++ graphics/video/dxa_player.h | 2 +- graphics/video/smk_player.cpp | 1 + graphics/video/smk_player.h | 2 +- graphics/video/video_player.cpp | 92 +++++++++++++++++++++++------------------ graphics/video/video_player.h | 68 +++++++++++++++++++----------- 6 files changed, 103 insertions(+), 66 deletions(-) (limited to 'graphics/video') diff --git a/graphics/video/dxa_player.cpp b/graphics/video/dxa_player.cpp index e228510e6b..397d1232da 100644 --- a/graphics/video/dxa_player.cpp +++ b/graphics/video/dxa_player.cpp @@ -25,6 +25,7 @@ #include "common/endian.h" #include "common/archive.h" +#include "common/system.h" #include "common/util.h" #include "graphics/video/dxa_player.h" @@ -476,6 +477,9 @@ void DXAPlayer::decode13(int size) { bool DXAPlayer::decodeNextFrame() { uint32 tag; + if (_videoInfo.currentFrame == 0) + _videoInfo.startTime = g_system->getMillis(); + tag = _fileStream->readUint32BE(); if (tag == MKID_BE('CMAP')) { byte rgb[768]; diff --git a/graphics/video/dxa_player.h b/graphics/video/dxa_player.h index fb5645c089..78825dc6f1 100644 --- a/graphics/video/dxa_player.h +++ b/graphics/video/dxa_player.h @@ -30,7 +30,7 @@ namespace Graphics { -class DXAPlayer : public VideoPlayer { +class DXAPlayer : public VideoDecoder { public: DXAPlayer(); virtual ~DXAPlayer(); diff --git a/graphics/video/smk_player.cpp b/graphics/video/smk_player.cpp index 81c18e94b4..143fa04621 100644 --- a/graphics/video/smk_player.cpp +++ b/graphics/video/smk_player.cpp @@ -321,6 +321,7 @@ SMKPlayer::SMKPlayer(Audio::Mixer *mixer) } SMKPlayer::~SMKPlayer() { + closeFile(); } int SMKPlayer::getHeight() { diff --git a/graphics/video/smk_player.h b/graphics/video/smk_player.h index 512eb57c20..6e7e0e88a9 100644 --- a/graphics/video/smk_player.h +++ b/graphics/video/smk_player.h @@ -44,7 +44,7 @@ class BigHuffmanTree; /** * Implementation of a Smacker v2/v4 video decoder */ -class SMKPlayer : public Graphics::VideoPlayer { +class SMKPlayer : public Graphics::VideoDecoder { public: SMKPlayer(Audio::Mixer *mixer); virtual ~SMKPlayer(); diff --git a/graphics/video/video_player.cpp b/graphics/video/video_player.cpp index 6bf7a5e39d..1f8fe78447 100644 --- a/graphics/video/video_player.cpp +++ b/graphics/video/video_player.cpp @@ -35,50 +35,51 @@ namespace Graphics { -VideoPlayer::VideoPlayer() : _fileStream(0), _skipVideo(false) { +VideoDecoder::VideoDecoder() : _fileStream(0) { + _black = 0; + _white = 255; } -VideoPlayer::~VideoPlayer() { - closeFile(); +VideoDecoder::~VideoDecoder() { } -int VideoPlayer::getWidth() { +int VideoDecoder::getWidth() { if (!_fileStream) return 0; return _videoInfo.width; } -int VideoPlayer::getHeight() { +int VideoDecoder::getHeight() { if (!_fileStream) return 0; return _videoInfo.height; } -int32 VideoPlayer::getCurFrame() { +int32 VideoDecoder::getCurFrame() { if (!_fileStream) return -1; return _videoInfo.currentFrame; } -int32 VideoPlayer::getFrameCount() { +int32 VideoDecoder::getFrameCount() { if (!_fileStream) return 0; return _videoInfo.frameCount; } -int32 VideoPlayer::getFrameRate() { +int32 VideoDecoder::getFrameRate() { if (!_fileStream) return 0; return _videoInfo.frameRate; } -int32 VideoPlayer::getFrameDelay() { +int32 VideoDecoder::getFrameDelay() { if (!_fileStream) return 0; return _videoInfo.frameDelay; } -int32 VideoPlayer::getAudioLag() { +int32 VideoDecoder::getAudioLag() { if (!_fileStream) return 0; @@ -92,7 +93,7 @@ int32 VideoPlayer::getAudioLag() { return videoTime - audioTime; } -uint32 VideoPlayer::getFrameWaitTime() { +uint32 VideoDecoder::getFrameWaitTime() { int32 waitTime = (getFrameDelay() + getAudioLag()) / 100; if (waitTime < 0) @@ -101,14 +102,7 @@ uint32 VideoPlayer::getFrameWaitTime() { return waitTime; } -bool VideoPlayer::loadFile(const char *fileName) { - return false; -} - -void VideoPlayer::closeFile() { -} - -void VideoPlayer::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) { +void VideoDecoder::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) { uint h = getHeight(); uint w = getWidth(); @@ -122,25 +116,45 @@ void VideoPlayer::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) { } while (--h); } -void VideoPlayer::setPalette(byte *pal) { +void VideoDecoder::setPalette(byte *pal) { byte videoPalette[256 * 4]; + uint32 maxWeight = 0; + uint32 minWeight = 0xFFFFFFFF; + uint32 weight = 0; + byte r, g, b; + 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; + + // Try and find the white and black colors for the current palette + r = videoPalette[i * 4 + 0]; + g = videoPalette[i * 4 + 1]; + b = videoPalette[i * 4 + 2]; + + weight = 3 * r * r + 6 * g * g + 2 * b * b; + + if (weight >= maxWeight) { + _white = i; + maxWeight = weight; + } + + if (weight <= minWeight) { + _black = i; + minWeight = i; + } } g_system->setPalette(videoPalette, 0, 256); } -bool VideoPlayer::decodeNextFrame() { - return false; -} -void VideoPlayer::performPostProcessing(byte *screen) { -} +/* + * VideoPlayer + */ void VideoPlayer::processVideoEvents(Common::List *stopEvents) { Common::Event curEvent; @@ -168,35 +182,30 @@ void VideoPlayer::processVideoEvents(Common::List *stopEvents) { } } -bool VideoPlayer::playVideo(const char *filename, Common::List *stopEvents) { +bool VideoPlayer::playVideo(Common::List *stopEvents) { _skipVideo = false; - debug(0, "Playing video %s", filename); - - if (!loadFile(filename)) { - warning("Failed to load video file %s", filename); - return false; - } + debug(0, "Playing video"); g_system->clearScreen(); - while (getCurFrame() < getFrameCount() && !_skipVideo) { + while (_decoder->getCurFrame() < _decoder->getFrameCount() && !_skipVideo) { processVideoEvents(stopEvents); uint32 startTime = 0; - decodeNextFrame(); + _decoder->decodeNextFrame(); Graphics::Surface *screen = g_system->lockScreen(); - copyFrameToBuffer((byte *)screen->pixels, - (g_system->getWidth() - getWidth()) / 2, - (g_system->getHeight() - getHeight()) / 2, + _decoder->copyFrameToBuffer((byte *)screen->pixels, + (g_system->getWidth() - _decoder->getWidth()) / 2, + (g_system->getHeight() - _decoder->getHeight()) / 2, g_system->getWidth()); performPostProcessing((byte *)screen->pixels); g_system->unlockScreen(); - uint32 waitTime = getFrameWaitTime(); + uint32 waitTime = _decoder->getFrameWaitTime(); if (!waitTime) { - warning("dropped frame %i", getCurFrame()); + warning("dropped frame %i", _decoder->getCurFrame()); continue; } @@ -212,9 +221,10 @@ bool VideoPlayer::playVideo(const char *filename, Common::List *s } } - closeFile(); + return !_skipVideo; +} - return true; +void VideoPlayer::performPostProcessing(byte *screen) { } } // End of namespace Graphics diff --git a/graphics/video/video_player.h b/graphics/video/video_player.h index 4a44349552..a32996df75 100644 --- a/graphics/video/video_player.h +++ b/graphics/video/video_player.h @@ -39,10 +39,10 @@ namespace Graphics { /** * Implementation of a generic video decoder */ -class VideoPlayer { +class VideoDecoder { public: - VideoPlayer(); - virtual ~VideoPlayer(); + VideoDecoder(); + virtual ~VideoDecoder(); /** * Returns the width of the video @@ -98,12 +98,12 @@ public: * Load a video file * @param filename the filename to load */ - virtual bool loadFile(const char *filename); + virtual bool loadFile(const char *filename) = 0; /** * Close a video file */ - virtual void closeFile(); + virtual void closeFile()=0; /** * Returns if a video file is loaded or not @@ -116,6 +116,16 @@ public: */ virtual void setPalette(byte *pal); + /** + * Return the black palette color for the current frame + */ + byte getBlack() { return _black; } + + /** + * Return the white palette color for the current frame + */ + byte getWhite() { return _white; } + /** * Copy current frame into the specified position of the destination * buffer. @@ -127,24 +137,9 @@ public: 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 + * Decode the next frame to _videoFrameBuffer */ - bool playVideo(const char *filename, Common::List *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); + virtual bool decodeNextFrame() = 0; protected: struct { @@ -157,11 +152,38 @@ protected: uint32 startTime; } _videoInfo; + byte _black, _white; + Common::SeekableReadStream *_fileStream; byte *_videoFrameBuffer; +}; + +class VideoPlayer { +public: + VideoPlayer(VideoDecoder* decoder) : _skipVideo(false), _decoder(decoder) + { } + ~VideoPlayer() { } + /** + * 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 + * + * Returns true if the video was played to the end, false if skipped + */ + bool playVideo(Common::List *stopEvents); + +protected: + /** + * Perform postprocessing once the frame data is copied to the screen, + * right before the frame is drawn. Called by playVideo() + */ + virtual void performPostProcessing(byte *screen); + bool _skipVideo; + VideoDecoder* _decoder; -private: void processVideoEvents(Common::List *stopEvents); }; -- cgit v1.2.3