aboutsummaryrefslogtreecommitdiff
path: root/engines/titanic/support/avi_surface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/titanic/support/avi_surface.cpp')
-rw-r--r--engines/titanic/support/avi_surface.cpp145
1 files changed, 53 insertions, 92 deletions
diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp
index 7fbb05ed58..9e465c705f 100644
--- a/engines/titanic/support/avi_surface.cpp
+++ b/engines/titanic/support/avi_surface.cpp
@@ -30,28 +30,10 @@
namespace Titanic {
-Video::AVIDecoder::AVIVideoTrack &AVIDecoder::getVideoTrack() {
- for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++)
- if ((*it)->getTrackType() == Track::kTrackTypeVideo)
- return *dynamic_cast<AVIVideoTrack *>(*it);
-
- error("Could not find video track");
-}
-
-/**
- * Track filter for AVIDecoder that filters out any secondary
- * video track some videos have to hold transparency masks
- */
-static bool primaryTrackSelect(bool isVideo, int trackCounter) {
- return !isVideo || trackCounter == 0;
-}
-
-/**
- * Track filter for AVIDecoder that only accepts the secondary
- * transparency msak video track for a video, if present
- */
-static bool secondaryTrackSelect(bool isVideo, int trackCounter) {
- return isVideo && trackCounter > 0;
+Video::AVIDecoder::AVIVideoTrack &AVIDecoder::getVideoTrack(uint idx) {
+ assert(idx < _videoTracks.size());
+ AVIVideoTrack *track = static_cast<AVIVideoTrack *>(_videoTracks[idx].track);
+ return *track;
}
AVISurface::AVISurface(const CResourceKey &key) {
@@ -60,45 +42,34 @@ AVISurface::AVISurface(const CResourceKey &key) {
_movieFrameSurface[0] = _movieFrameSurface[1] = nullptr;
_framePixels = nullptr;
- // Reset current frame. We need to keep track of frames separately from the decoders,
+ // Reset current frame. We need to keep track of frames separately from the decoder,
// since it needs to be able to go beyond the frame count or to negative to allow
// correct detection of when range playbacks have finished
_currentFrame = -1;
_isReversed = false;
- // Create a decoder for the audio (if any) and primary video track
- _decoders[0] = new AVIDecoder(Audio::Mixer::kPlainSoundType, primaryTrackSelect);
- if (!_decoders[0]->loadFile(key.getString()))
+ // Create a decoder
+ _decoder = new AVIDecoder(Audio::Mixer::kPlainSoundType);
+ if (!_decoder->loadFile(key.getString()))
error("Could not open video - %s", key.getString().c_str());
- _streamCount = 1;
-
- // Create a decoder for any secondary video track
- AVIDecoder *decoder2 = new AVIDecoder(Audio::Mixer::kPlainSoundType, secondaryTrackSelect);
- if (decoder2->loadFile(key.getString())) {
- _decoders[1] = decoder2;
- ++_streamCount;
- } else {
- delete decoder2;
- _decoders[1] = nullptr;
- }
+ _streamCount = _decoder->videoTrackCount();
}
AVISurface::~AVISurface() {
if (_videoSurface)
- _videoSurface->_transBlitFlag = false;
+ _videoSurface->_flipVertically = false;
delete _framePixels;
delete _movieFrameSurface[0];
delete _movieFrameSurface[1];
- delete _decoders[0];
- delete _decoders[1];
+ delete _decoder;
}
bool AVISurface::play(uint flags, CGameObject *obj) {
if (flags & MOVIE_REVERSE)
- return play(_decoders[0]->getFrameCount() - 1, 0, flags, obj);
+ return play(_decoder->getFrameCount() - 1, 0, flags, obj);
else
- return play(0, _decoders[0]->getFrameCount() - 1, flags, obj);
+ return play(0, _decoder->getFrameCount() - 1, flags, obj);
}
bool AVISurface::play(int startFrame, int endFrame, uint flags, CGameObject *obj) {
@@ -123,26 +94,23 @@ bool AVISurface::play(int startFrame, int endFrame, int initialFrame, uint flags
me->_endFrame = endFrame;
me->_initialFrame = 0;
me->_gameObject = obj;
-
+
info->addEvent(me);
}
_movieRangeInfo.push_back(info);
-
+
if (_movieRangeInfo.size() == 1) {
// First play call, so start the movie playing
setReversed(info->_isReversed);
return startAtFrame(initialFrame);
} else {
return true;
- }
+ }
}
void AVISurface::stop() {
- _decoders[0]->stop();
- if (_decoders[1])
- _decoders[1]->stop();
-
+ _decoder->stop();
_movieRangeInfo.destroyContents();
}
@@ -160,19 +128,14 @@ bool AVISurface::startAtFrame(int frameNumber) {
renderFrame();
// Start the playback
- _decoders[0]->start();
- if (_decoders[1])
- _decoders[1]->start();
-
+ _decoder->start();
+
return true;
}
void AVISurface::seekToFrame(uint frameNumber) {
if ((int)frameNumber != getFrame()) {
- _decoders[0]->seekToFrame(frameNumber);
- if (_decoders[1])
- _decoders[1]->seekToFrame(frameNumber);
-
+ _decoder->seekToFrame(frameNumber);
_currentFrame = (int)frameNumber;
}
@@ -180,10 +143,7 @@ void AVISurface::seekToFrame(uint frameNumber) {
}
void AVISurface::setReversed(bool isReversed) {
- _decoders[0]->setReverse(isReversed);
- if (_decoders[1])
- _decoders[1]->setReverse(isReversed);
-
+ _decoder->setReverse(isReversed);
_isReversed = isReversed;
}
@@ -221,7 +181,7 @@ bool AVISurface::handleEvents(CMovieEventList &events) {
setReversed(info->_isReversed);
seekToFrame(newFrame);
}
-
+
// Get any events for the given position
info->getMovieFrame(events, newFrame);
return renderFrame();
@@ -234,8 +194,8 @@ void AVISurface::setVideoSurface(CVideoSurface *surface) {
_videoSurface = surface;
// Handling for secondary video stream
- if (_decoders[1]) {
- const Common::String &streamName = _decoders[1]->getVideoTrack().getName();
+ if (_streamCount == 2) {
+ const Common::String &streamName = _decoder->getVideoTrack(1).getName();
if (streamName == "mask0") {
_videoSurface->_transparencyMode = TRANS_MASK0;
@@ -252,21 +212,21 @@ void AVISurface::setVideoSurface(CVideoSurface *surface) {
}
void AVISurface::setupDecompressor() {
- for (int idx = 0; idx < 2; ++idx) {
- if (!_decoders[idx])
- continue;
- AVIDecoder &decoder = *_decoders[idx];
+ if (!_decoder)
+ return;
+ for (int idx = 0; idx < _streamCount; ++idx) {
// Setup frame surface
- _movieFrameSurface[idx] = new Graphics::ManagedSurface(decoder.getWidth(), decoder.getHeight(),
- decoder.getVideoTrack().getPixelFormat());
+ _movieFrameSurface[idx] = new Graphics::ManagedSurface(_decoder->getWidth(), _decoder->getHeight(),
+ _decoder->getVideoTrack(idx).getPixelFormat());
bool flag = false;
- if (idx == 0 && _videoSurface) {
- const Graphics::PixelFormat &ff = decoder.getVideoTrack().getPixelFormat();
+ if (idx == 0 && _videoSurface &&
+ _videoSurface->getPitch() == _movieFrameSurface[idx]->pitch) {
+ const uint bitCount = _decoder->getVideoTrack(0).getBitCount();
const int vDepth = _videoSurface->getPixelDepth();
- switch (ff.bpp()) {
+ switch (bitCount) {
case 15:
flag = vDepth == 1;
break;
@@ -285,20 +245,23 @@ void AVISurface::setupDecompressor() {
}
if (!flag) {
- _framePixels = new Graphics::ManagedSurface(decoder.getWidth(), decoder.getHeight(),
- decoder.getVideoTrack().getPixelFormat());
+ _framePixels = new Graphics::ManagedSurface(_decoder->getWidth(), _decoder->getHeight(),
+ _decoder->getVideoTrack(0).getPixelFormat());
} else if (idx == 0) {
- _videoSurface->_transBlitFlag = true;
+ // The original developers used a vertical flipped playback to indicate
+ // an incompatibility between source video and dest surface bit-depths,
+ // which would result in poor playback performance
+ _videoSurface->_flipVertically = true;
}
}
}
uint AVISurface::getWidth() const {
- return _decoders[0]->getWidth();
+ return _decoder->getWidth();
}
uint AVISurface::getHeight() const {
- return _decoders[0]->getHeight();
+ return _decoder->getHeight();
}
void AVISurface::setFrame(int frameNumber) {
@@ -307,25 +270,26 @@ void AVISurface::setFrame(int frameNumber) {
stop();
// Ensure the frame number is valid
- if (frameNumber >= (int)_decoders[0]->getFrameCount())
- frameNumber = _decoders[0]->getFrameCount() - 1;
+ if (frameNumber >= (int)_decoder->getFrameCount())
+ frameNumber = _decoder->getFrameCount() - 1;
seekToFrame(frameNumber);
renderFrame();
}
bool AVISurface::isNextFrame() const {
- return _decoders[0]->getTimeToNextFrame() == 0;
+ return _decoder->getTimeToNextFrame() == 0;
}
bool AVISurface::renderFrame() {
// Check there's a frame ready for display
- if (!_decoders[0]->needsUpdate())
+ if (!_decoder->needsUpdate())
return false;
// Make a copy of each decoder's video frame
for (int idx = 0; idx < _streamCount; ++idx) {
- const Graphics::Surface *frame = _decoders[idx]->decodeNextFrame();
+ const Graphics::Surface *frame = (idx == 0) ?
+ _decoder->decodeNextFrame() : _decoder->decodeNextTransparency();
assert(_movieFrameSurface[idx]->format == frame->format);
_movieFrameSurface[idx]->blitFrom(*frame);
@@ -333,17 +297,16 @@ bool AVISurface::renderFrame() {
if (!_framePixels) {
if (_videoSurface->lock()) {
- if (_streamCount == 1) {
- // Original seems to call a stubbed empty method here.
- // Likely this form of blitting to surface wasn't needed
- }
+ // Blit the frame directly to the video surface
+ assert(_streamCount == 1);
+ _videoSurface->blitFrom(Point(0, 0), &_movieFrameSurface[0]->rawSurface());
_videoSurface->unlock();
}
} else {
// Blit the primary video track's frame to the video surface
Graphics::Surface *s = _movieFrameSurface[0]->rawSurface().convertTo(
- g_system->getScreenFormat(), _decoders[0]->getPalette());
+ g_system->getScreenFormat(), _decoder->getPalette());
_videoSurface->lock();
_videoSurface->getRawSurface()->blitFrom(*s);
_videoSurface->unlock();
@@ -375,9 +338,7 @@ bool AVISurface::addEvent(int frameNumber, CGameObject *obj) {
}
void AVISurface::setFrameRate(double rate) {
- _decoders[0]->setRate(Common::Rational((int)rate));
- if (_decoders[1])
- _decoders[1]->setRate(Common::Rational((int)rate));
+ _decoder->setRate(Common::Rational((int)rate));
}
Graphics::ManagedSurface *AVISurface::getSecondarySurface() {
@@ -403,7 +364,7 @@ void AVISurface::playCutscene(const Rect &r, uint startFrame, uint endFrame) {
while (_currentFrame < (int)endFrame && !g_vm->shouldQuit()) {
if (isNextFrame()) {
renderFrame();
- _currentFrame = _decoders[0]->getCurFrame();
+ _currentFrame = _decoder->getCurFrame();
if (isDifferent) {
// Clear the destination area, and use the transBlitFrom method,