VIDEO: Convert DXADecoder to the AdvancedVideoDecoder API

This commit is contained in:
Matthew Hoops 2012-07-24 13:24:01 -04:00
parent 84e0b3a167
commit 3117e4a8ff
10 changed files with 218 additions and 307 deletions

View file

@ -260,9 +260,6 @@ bool MoviePlayerDXA::load() {
debug(0, "Playing video %s", videoName.c_str());
CursorMan.showMouse(false);
_firstFrameOffset = _fileStream->pos();
return true;
}
@ -302,35 +299,6 @@ void MoviePlayerDXA::stopVideo() {
}
void MoviePlayerDXA::startSound() {
uint32 offset, size;
if (getSoundTag() == MKTAG('W','A','V','E')) {
size = _fileStream->readUint32BE();
if (_sequenceNum) {
Common::File in;
_fileStream->seek(size, SEEK_CUR);
in.open("audio.wav");
if (!in.isOpen()) {
error("Can't read offset file 'audio.wav'");
}
in.seek(_sequenceNum * 8, SEEK_SET);
offset = in.readUint32LE();
size = in.readUint32LE();
in.seek(offset, SEEK_SET);
_bgSoundStream = Audio::makeWAVStream(in.readStream(size), DisposeAfterUse::YES);
in.close();
} else {
_bgSoundStream = Audio::makeWAVStream(_fileStream->readStream(size), DisposeAfterUse::YES);
}
} else {
_bgSoundStream = Audio::SeekableAudioStream::openStreamFile(baseName);
}
if (_bgSoundStream != NULL) {
_vm->_mixer->stopHandle(_bgSound);
_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_bgSound, _bgSoundStream, -1, getVolume(), getBalance());
@ -344,8 +312,7 @@ void MoviePlayerDXA::nextFrame() {
}
if (_vm->_interactiveVideo == TYPE_LOOPING && endOfVideo()) {
_fileStream->seek(_firstFrameOffset);
_curFrame = -1;
rewind();
startSound();
}
@ -374,13 +341,15 @@ bool MoviePlayerDXA::processFrame() {
copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
_vm->_system->unlockScreen();
Common::Rational soundTime(_mixer->getSoundElapsedTime(_bgSound), 1000);
if ((_bgSoundStream == NULL) || ((soundTime * getFrameRate()).toInt() / 1000 < getCurFrame() + 1)) {
uint32 soundTime = _mixer->getSoundElapsedTime(_bgSound);
uint32 nextFrameStartTime = ((Video::AdvancedVideoDecoder::VideoTrack *)getTrack(0))->getNextFrameStartTime();
if ((_bgSoundStream == NULL) || soundTime < nextFrameStartTime) {
if (_bgSoundStream && _mixer->isSoundHandleActive(_bgSound)) {
while (_mixer->isSoundHandleActive(_bgSound) && (soundTime * getFrameRate()).toInt() < getCurFrame()) {
while (_mixer->isSoundHandleActive(_bgSound) && soundTime < nextFrameStartTime) {
_vm->_system->delayMillis(10);
soundTime = Common::Rational(_mixer->getSoundElapsedTime(_bgSound), 1000);
soundTime = _mixer->getSoundElapsedTime(_bgSound);
}
// In case the background sound ends prematurely, update
// _ticks so that we can still fall back on the no-sound
@ -399,14 +368,35 @@ bool MoviePlayerDXA::processFrame() {
return false;
}
void MoviePlayerDXA::updateVolume() {
if (g_system->getMixer()->isSoundHandleActive(_bgSound))
g_system->getMixer()->setChannelVolume(_bgSound, getVolume());
void MoviePlayerDXA::readSoundData(Common::SeekableReadStream *stream) {
uint32 tag = stream->readUint32BE();
if (tag == MKTAG('W','A','V','E')) {
uint32 size = stream->readUint32BE();
if (_sequenceNum) {
Common::File in;
stream->skip(size);
in.open("audio.wav");
if (!in.isOpen()) {
error("Can't read offset file 'audio.wav'");
}
void MoviePlayerDXA::updateBalance() {
if (g_system->getMixer()->isSoundHandleActive(_bgSound))
g_system->getMixer()->setChannelBalance(_bgSound, getBalance());
in.seek(_sequenceNum * 8, SEEK_SET);
uint32 offset = in.readUint32LE();
size = in.readUint32LE();
in.seek(offset, SEEK_SET);
_bgSoundStream = Audio::makeWAVStream(in.readStream(size), DisposeAfterUse::YES);
in.close();
} else {
_bgSoundStream = Audio::makeWAVStream(stream->readStream(size), DisposeAfterUse::YES);
}
} else {
_bgSoundStream = Audio::SeekableAudioStream::openStreamFile(baseName);
}
}
///////////////////////////////////////////////////////////////////////////////

View file

@ -81,16 +81,13 @@ public:
virtual void stopVideo();
protected:
// VideoDecoder API
void updateVolume();
void updateBalance();
void readSoundData(Common::SeekableReadStream *stream);
private:
void handleNextFrame();
bool processFrame();
void startSound();
void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);
uint32 _firstFrameOffset;
};
class MoviePlayerSMK : public MoviePlayer, Video::SmackerDecoder {

View file

@ -37,6 +37,7 @@
#include "gui/message.h"
#include "video/dxa_decoder.h"
#include "video/psx_decoder.h"
#include "video/smk_decoder.h"
@ -96,9 +97,8 @@ static const char *const sequenceListPSX[20] = {
// Basic movie player
///////////////////////////////////////////////////////////////////////////////
MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType)
: _vm(vm), _textMan(textMan), _resMan(resMan), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system) {
_bgSoundStream = NULL;
MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType)
: _vm(vm), _textMan(textMan), _resMan(resMan), _system(system) {
_decoderType = decoderType;
_decoder = decoder;
@ -107,7 +107,6 @@ MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::
}
MoviePlayer::~MoviePlayer() {
delete _bgSoundHandle;
delete _decoder;
}
@ -116,16 +115,12 @@ MoviePlayer::~MoviePlayer() {
* @param id the id of the file
*/
bool MoviePlayer::load(uint32 id) {
Common::File f;
Common::String filename;
if (_decoderType == kVideoDecoderDXA)
_bgSoundStream = Audio::SeekableAudioStream::openStreamFile(sequenceList[id]);
else
_bgSoundStream = NULL;
if (SwordEngine::_systemVars.showText) {
Common::File f;
filename = Common::String::format("%s.txt", sequenceList[id]);
if (f.open(filename)) {
Common::String line;
int lineNo = 0;
@ -169,7 +164,6 @@ bool MoviePlayer::load(uint32 id) {
_movieTexts.push_back(MovieText(startFrame, endFrame, ptr, color));
lastEnd = endFrame;
}
f.close();
}
}
@ -179,13 +173,6 @@ bool MoviePlayer::load(uint32 id) {
break;
case kVideoDecoderSMK:
filename = Common::String::format("%s.smk", sequenceList[id]);
if (_decoder->loadFile(filename)) {
((Video::AdvancedVideoDecoder *)_decoder)->start(); // TODO: Remove after new API is complete
return true;
} else {
return false;
}
break;
case kVideoDecoderPSX:
filename = Common::String::format("%s.str", (_vm->_systemVars.isDemo) ? sequenceList[id] : sequenceListPSX[id]);
@ -205,30 +192,27 @@ bool MoviePlayer::load(uint32 id) {
break;
}
return _decoder->loadFile(filename.c_str());
if (!_decoder->loadFile(filename))
return false;
// For DXA, also add the external sound file
if (_decoderType == kVideoDecoderDXA)
((Video::AdvancedVideoDecoder *)_decoder)->addStreamFileTrack(sequenceList[id]);
((Video::AdvancedVideoDecoder *)_decoder)->start(); // TODO: Remove after new API is complete
return true;
}
void MoviePlayer::play() {
if (_bgSoundStream)
_snd->playStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream);
bool terminated = false;
_textX = 0;
_textY = 0;
terminated = !playVideo();
if (terminated)
_snd->stopHandle(*_bgSoundHandle);
playVideo();
_textMan->releaseText(2, false);
_movieTexts.clear();
while (_snd->isSoundHandleActive(*_bgSoundHandle))
_system->delayMillis(100);
// It's tempting to call _screen->fullRefresh() here to restore the old
// palette. However, that causes glitches with DXA movies, where the
// previous location would be momentarily drawn, before switching to
@ -514,24 +498,12 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
scaledFrame.free();
}
DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
: _mixer(mixer), _bgSoundHandle(bgSoundHandle) {
}
uint32 DXADecoderWithSound::getTime() const {
if (_mixer->isSoundHandleActive(*_bgSoundHandle))
return _mixer->getSoundElapsedTime(*_bgSoundHandle);
return DXADecoder::getTime();
}
///////////////////////////////////////////////////////////////////////////////
// Factory function for creating the appropriate cutscene player
///////////////////////////////////////////////////////////////////////////////
MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system) {
MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system) {
Common::String filename;
Audio::SoundHandle *bgSoundHandle = new Audio::SoundHandle;
// For the PSX version, we'll try the PlayStation stream files
if (vm->isPsx()) {
@ -542,7 +514,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
#ifdef USE_RGB_COLOR
// All BS1 PSX videos run the videos at 2x speed
Video::VideoDecoder *psxDecoder = new Video::PSXStreamDecoder(Video::PSXStreamDecoder::kCD2x);
return new MoviePlayer(vm, textMan, resMan, snd, system, bgSoundHandle, psxDecoder, kVideoDecoderPSX);
return new MoviePlayer(vm, textMan, resMan, system, psxDecoder, kVideoDecoderPSX);
#else
GUI::MessageDialog dialog(Common::String::format(_("PSX stream cutscene '%s' cannot be played in paletted mode"), filename.c_str()), _("OK"));
dialog.runModal();
@ -555,19 +527,19 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
if (Common::File::exists(filename)) {
Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder();
return new MoviePlayer(vm, textMan, resMan, snd, system, bgSoundHandle, smkDecoder, kVideoDecoderSMK);
return new MoviePlayer(vm, textMan, resMan, system, smkDecoder, kVideoDecoderSMK);
}
filename = Common::String::format("%s.dxa", sequenceList[id]);
if (Common::File::exists(filename)) {
#ifdef USE_ZLIB
DXADecoderWithSound *dxaDecoder = new DXADecoderWithSound(snd, bgSoundHandle);
return new MoviePlayer(vm, textMan, resMan, snd, system, bgSoundHandle, dxaDecoder, kVideoDecoderDXA);
Video::VideoDecoder *dxaDecoder = new Video::DXADecoder();
return new MoviePlayer(vm, textMan, resMan, system, dxaDecoder, kVideoDecoderDXA);
#else
GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK"));
dialog.runModal();
return NULL;
return 0;
#endif
}
@ -577,7 +549,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
if (Common::File::exists(filename)) {
GUI::MessageDialog dialog(_("MPEG2 cutscenes are no longer supported"), _("OK"));
dialog.runModal();
return NULL;
return 0;
}
if (!vm->isPsx() || scumm_stricmp(sequenceList[id], "enddemo") != 0) {
@ -586,7 +558,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
dialog.runModal();
}
return NULL;
return 0;
}
} // End of namespace Sword1

View file

@ -23,16 +23,19 @@
#ifndef SWORD1_ANIMATION_H
#define SWORD1_ANIMATION_H
#include "video/dxa_decoder.h"
#include "video/video_decoder.h"
#include "common/list.h"
#include "audio/audiostream.h"
#include "sword1/screen.h"
#include "sword1/sound.h"
namespace Graphics {
struct Surface;
}
namespace Video {
class VideoDecoder;
}
namespace Sword1 {
enum DecoderType {
@ -55,21 +58,9 @@ public:
}
};
class DXADecoderWithSound : public Video::DXADecoder {
public:
DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle);
~DXADecoderWithSound() {}
uint32 getTime() const;
private:
Audio::Mixer *_mixer;
Audio::SoundHandle *_bgSoundHandle;
};
class MoviePlayer {
public:
MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType);
MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType);
virtual ~MoviePlayer();
bool load(uint32 id);
void play();
@ -78,7 +69,6 @@ protected:
SwordEngine *_vm;
Text *_textMan;
ResMan *_resMan;
Audio::Mixer *_snd;
OSystem *_system;
Common::List<MovieText> _movieTexts;
int _textX, _textY, _textWidth, _textHeight;
@ -88,8 +78,6 @@ protected:
DecoderType _decoderType;
Video::VideoDecoder *_decoder;
Audio::SoundHandle *_bgSoundHandle;
Audio::AudioStream *_bgSoundStream;
bool playVideo();
void performPostProcessing(byte *screen);
@ -100,7 +88,7 @@ protected:
void convertColor(byte r, byte g, byte b, float &h, float &s, float &v);
};
MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system);
MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system);
} // End of namespace Sword1

View file

@ -959,7 +959,7 @@ int Logic::fnPlaySequence(Object *cpt, int32 id, int32 sequenceId, int32 d, int3
// meantime, we don't want any looping sound effects still playing.
_sound->quitScreen();
MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _mixer, _system);
MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _system);
if (player) {
_screen->clearScreen();
if (player->load(sequenceId))

View file

@ -40,6 +40,7 @@
#include "gui/message.h"
#include "video/dxa_decoder.h"
#include "video/smk_decoder.h"
#include "video/psx_decoder.h"
@ -51,9 +52,8 @@ namespace Sword2 {
// Basic movie player
///////////////////////////////////////////////////////////////////////////////
MoviePlayer::MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType)
: _vm(vm), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system) {
_bgSoundStream = NULL;
MoviePlayer::MoviePlayer(Sword2Engine *vm, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType)
: _vm(vm), _system(system) {
_decoderType = decoderType;
_decoder = decoder;
@ -62,7 +62,6 @@ MoviePlayer::MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, A
}
MoviePlayer::~MoviePlayer() {
delete _bgSoundHandle;
delete _decoder;
}
@ -75,11 +74,6 @@ bool MoviePlayer::load(const char *name) {
if (_vm->shouldQuit())
return false;
if (_decoderType == kVideoDecoderDXA)
_bgSoundStream = Audio::SeekableAudioStream::openStreamFile(name);
else
_bgSoundStream = NULL;
_textSurface = NULL;
Common::String filename;
@ -89,13 +83,6 @@ bool MoviePlayer::load(const char *name) {
break;
case kVideoDecoderSMK:
filename = Common::String::format("%s.smk", name);
if (_decoder->loadFile(filename)) {
((Video::AdvancedVideoDecoder *)_decoder)->start(); // TODO: Remove after new API is complete
return true;
} else {
return false;
}
break;
case kVideoDecoderPSX:
filename = Common::String::format("%s.str", name);
@ -114,7 +101,15 @@ bool MoviePlayer::load(const char *name) {
}
}
return _decoder->loadFile(filename.c_str());
if (!_decoder->loadFile(filename))
return false;
// For DXA, also add the external sound file
if (_decoderType == kVideoDecoderDXA)
((Video::AdvancedVideoDecoder *)_decoder)->addStreamFileTrack(name);
((Video::AdvancedVideoDecoder *)_decoder)->start(); // TODO: Remove after new API is complete
return true;
}
void MoviePlayer::play(MovieText *movieTexts, uint32 numMovieTexts, uint32 leadIn, uint32 leadOut) {
@ -130,24 +125,15 @@ void MoviePlayer::play(MovieText *movieTexts, uint32 numMovieTexts, uint32 leadI
if (leadIn)
_vm->_sound->playMovieSound(leadIn, kLeadInSound);
if (_bgSoundStream)
_snd->playStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream);
bool terminated = false;
terminated = !playVideo();
bool terminated = !playVideo();
closeTextObject(_currentMovieText, NULL, 0);
if (terminated) {
_snd->stopHandle(*_bgSoundHandle);
_vm->_sound->stopMovieSounds();
_vm->_sound->stopSpeech();
}
while (_snd->isSoundHandleActive(*_bgSoundHandle))
_system->delayMillis(100);
if (_decoderType == kVideoDecoderPSX) {
// Need to jump back to paletted color
initGraphics(640, 480, true);
@ -414,31 +400,19 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
scaledFrame.free();
}
DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
: _mixer(mixer), _bgSoundHandle(bgSoundHandle) {
}
uint32 DXADecoderWithSound::getTime() const {
if (_mixer->isSoundHandleActive(*_bgSoundHandle))
return _mixer->getSoundElapsedTime(*_bgSoundHandle);
return DXADecoder::getTime();
}
///////////////////////////////////////////////////////////////////////////////
// Factory function for creating the appropriate cutscene player
///////////////////////////////////////////////////////////////////////////////
MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, uint32 frameCount) {
MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system, uint32 frameCount) {
Common::String filename;
Audio::SoundHandle *bgSoundHandle = new Audio::SoundHandle;
filename = Common::String::format("%s.str", name);
if (Common::File::exists(filename)) {
#ifdef USE_RGB_COLOR
Video::VideoDecoder *psxDecoder = new Video::PSXStreamDecoder(Video::PSXStreamDecoder::kCD2x, frameCount);
return new MoviePlayer(vm, snd, system, bgSoundHandle, psxDecoder, kVideoDecoderPSX);
return new MoviePlayer(vm, system, psxDecoder, kVideoDecoderPSX);
#else
GUI::MessageDialog dialog(_("PSX cutscenes found but ScummVM has been built without RGB color support"), _("OK"));
dialog.runModal();
@ -450,15 +424,15 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *s
if (Common::File::exists(filename)) {
Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder();
return new MoviePlayer(vm, snd, system, bgSoundHandle, smkDecoder, kVideoDecoderSMK);
return new MoviePlayer(vm, system, smkDecoder, kVideoDecoderSMK);
}
filename = Common::String::format("%s.dxa", name);
if (Common::File::exists(filename)) {
#ifdef USE_ZLIB
DXADecoderWithSound *dxaDecoder = new DXADecoderWithSound(snd, bgSoundHandle);
return new MoviePlayer(vm, snd, system, bgSoundHandle, dxaDecoder, kVideoDecoderDXA);
Video::DXADecoder *dxaDecoder = new Video::DXADecoder();
return new MoviePlayer(vm, system, dxaDecoder, kVideoDecoderDXA);
#else
GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK"));
dialog.runModal();

View file

@ -25,12 +25,16 @@
#ifndef SWORD2_ANIMATION_H
#define SWORD2_ANIMATION_H
#include "video/dxa_decoder.h"
#include "video/video_decoder.h"
#include "audio/mixer.h"
#include "sword2/screen.h"
namespace Graphics {
struct Surface;
}
namespace Video {
class VideoDecoder;
}
namespace Sword2 {
enum DecoderType {
@ -55,20 +59,9 @@ struct MovieText {
}
};
class DXADecoderWithSound : public Video::DXADecoder {
public:
DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle);
~DXADecoderWithSound() {}
uint32 getTime() const;
private:
Audio::Mixer *_mixer;
Audio::SoundHandle *_bgSoundHandle;
};
class MoviePlayer {
public:
MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType);
MoviePlayer(Sword2Engine *vm, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType);
virtual ~MoviePlayer();
bool load(const char *name);
@ -76,7 +69,6 @@ public:
protected:
Sword2Engine *_vm;
Audio::Mixer *_snd;
OSystem *_system;
MovieText *_movieTexts;
uint32 _numMovieTexts;
@ -87,8 +79,6 @@ protected:
DecoderType _decoderType;
Video::VideoDecoder *_decoder;
Audio::SoundHandle *_bgSoundHandle;
Audio::AudioStream *_bgSoundStream;
uint32 _leadOut;
int _leadOutFrame;
@ -105,7 +95,7 @@ protected:
uint32 getWhiteColor();
};
MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, uint32 frameCount);
MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system, uint32 frameCount);
} // End of namespace Sword2

View file

@ -2139,7 +2139,7 @@ int32 Logic::fnPlaySequence(int32 *params) {
uint32 frameCount = Sword2Engine::isPsx() ? params[1] : 0;
_moviePlayer = makeMoviePlayer(filename, _vm, _vm->_mixer, _vm->_system, frameCount);
_moviePlayer = makeMoviePlayer(filename, _vm, _vm->_system, frameCount);
if (_moviePlayer && _moviePlayer->load(filename)) {
_moviePlayer->play(_sequenceTextList, _sequenceTextLines, _smackerLeadIn, _smackerLeadOut);

View file

@ -37,28 +37,6 @@
namespace Video {
DXADecoder::DXADecoder() {
_fileStream = 0;
_surface = 0;
_dirtyPalette = false;
_frameBuffer1 = 0;
_frameBuffer2 = 0;
_scaledBuffer = 0;
_inBuffer = 0;
_inBufferSize = 0;
_decompBuffer = 0;
_decompBufferSize = 0;
_width = 0;
_height = 0;
_frameSize = 0;
_frameCount = 0;
_frameRate = 0;
_scaleMode = S_NONE;
}
DXADecoder::~DXADecoder() {
@ -68,10 +46,34 @@ DXADecoder::~DXADecoder() {
bool DXADecoder::loadStream(Common::SeekableReadStream *stream) {
close();
_fileStream = stream;
uint32 tag = stream->readUint32BE();
uint32 tag = _fileStream->readUint32BE();
assert(tag == MKTAG('D','E','X','A'));
if (tag != MKTAG('D','E','X','A')) {
close();
return false;
}
DXAVideoTrack *track = new DXAVideoTrack(stream);
addTrack(track);
readSoundData(stream);
track->setFrameStartPos();
return true;
}
void DXADecoder::readSoundData(Common::SeekableReadStream *stream) {
// Skip over the tag by default
stream->readUint32BE();
}
DXADecoder::DXAVideoTrack::DXAVideoTrack(Common::SeekableReadStream *stream) {
_fileStream = stream;
_curFrame = -1;
_frameStartOffset = 0;
_decompBuffer = 0;
_inBuffer = 0;
memset(_palette, 0, 256 * 3);
uint8 flags = _fileStream->readByte();
_frameCount = _fileStream->readUint16BE();
@ -105,18 +107,14 @@ bool DXADecoder::loadStream(Common::SeekableReadStream *stream) {
_frameSize = _width * _height;
_decompBufferSize = _frameSize;
_frameBuffer1 = (uint8 *)malloc(_frameSize);
_frameBuffer1 = new byte[_frameSize];
memset(_frameBuffer1, 0, _frameSize);
_frameBuffer2 = (uint8 *)malloc(_frameSize);
_frameBuffer2 = new byte[_frameSize];
memset(_frameBuffer2, 0, _frameSize);
if (!_frameBuffer1 || !_frameBuffer2)
error("DXADecoder: Error allocating frame buffers (size %u)", _frameSize);
_scaledBuffer = 0;
if (_scaleMode != S_NONE) {
_scaledBuffer = (uint8 *)malloc(_frameSize);
if (!_scaledBuffer)
error("Error allocating scale buffer (size %u)", _frameSize);
_scaledBuffer = new byte[_frameSize];
memset(_scaledBuffer, 0, _frameSize);
}
@ -148,36 +146,33 @@ bool DXADecoder::loadStream(Common::SeekableReadStream *stream) {
} while (tag != 0);
}
#endif
}
// Read the sound header
_soundTag = _fileStream->readUint32BE();
DXADecoder::DXAVideoTrack::~DXAVideoTrack() {
delete _fileStream;
delete _surface;
delete[] _frameBuffer1;
delete[] _frameBuffer2;
delete[] _scaledBuffer;
delete[] _inBuffer;
delete[] _decompBuffer;
}
bool DXADecoder::DXAVideoTrack::rewind() {
_curFrame = -1;
_fileStream->seek(_frameStartOffset);
return true;
}
void DXADecoder::close() {
if (!_fileStream)
return;
delete _fileStream;
_fileStream = 0;
delete _surface;
_surface = 0;
free(_frameBuffer1);
free(_frameBuffer2);
free(_scaledBuffer);
free(_inBuffer);
free(_decompBuffer);
_inBuffer = 0;
_decompBuffer = 0;
reset();
Graphics::PixelFormat DXADecoder::DXAVideoTrack::getPixelFormat() const {
return _surface->format;
}
void DXADecoder::decodeZlib(byte *data, int size, int totalSize) {
void DXADecoder::DXAVideoTrack::setFrameStartPos() {
_frameStartOffset = _fileStream->pos();
}
void DXADecoder::DXAVideoTrack::decodeZlib(byte *data, int size, int totalSize) {
#ifdef USE_ZLIB
unsigned long dstLen = totalSize;
Common::uncompress(data, &dstLen, _inBuffer, size);
@ -187,14 +182,13 @@ void DXADecoder::decodeZlib(byte *data, int size, int totalSize) {
#define BLOCKW 4
#define BLOCKH 4
void DXADecoder::decode12(int size) {
void DXADecoder::DXAVideoTrack::decode12(int size) {
#ifdef USE_ZLIB
if (_decompBuffer == NULL) {
_decompBuffer = (byte *)malloc(_decompBufferSize);
if (!_decompBuffer) {
_decompBuffer = new byte[_decompBufferSize];
memset(_decompBuffer, 0, _decompBufferSize);
if (_decompBuffer == NULL)
error("Error allocating decomp buffer (size %u)", _decompBufferSize);
}
/* decompress the input data */
decodeZlib(_decompBuffer, size, _decompBufferSize);
@ -287,15 +281,13 @@ void DXADecoder::decode12(int size) {
#endif
}
void DXADecoder::decode13(int size) {
void DXADecoder::DXAVideoTrack::decode13(int size) {
#ifdef USE_ZLIB
uint8 *codeBuf, *dataBuf, *motBuf, *maskBuf;
if (_decompBuffer == NULL) {
_decompBuffer = (byte *)malloc(_decompBufferSize);
if (!_decompBuffer) {
_decompBuffer = new byte[_decompBufferSize];
memset(_decompBuffer, 0, _decompBufferSize);
if (_decompBuffer == NULL)
error("Error allocating decomp buffer (size %u)", _decompBufferSize);
}
/* decompress the input data */
@ -475,7 +467,7 @@ void DXADecoder::decode13(int size) {
#endif
}
const Graphics::Surface *DXADecoder::decodeNextFrame() {
const Graphics::Surface *DXADecoder::DXAVideoTrack::decodeNextFrame() {
uint32 tag = _fileStream->readUint32BE();
if (tag == MKTAG('C','M','A','P')) {
_fileStream->read(_palette, 256 * 3);
@ -486,11 +478,10 @@ const Graphics::Surface *DXADecoder::decodeNextFrame() {
if (tag == MKTAG('F','R','A','M')) {
byte type = _fileStream->readByte();
uint32 size = _fileStream->readUint32BE();
if ((_inBuffer == NULL) || (_inBufferSize < size)) {
free(_inBuffer);
_inBuffer = (byte *)malloc(size);
if (_inBuffer == NULL)
error("Error allocating input buffer (size %u)", size);
if (!_inBuffer || _inBufferSize < size) {
delete[] _inBuffer;
_inBuffer = new byte[size];
memset(_inBuffer, 0, size);
_inBufferSize = size;
}
@ -551,9 +542,6 @@ const Graphics::Surface *DXADecoder::decodeNextFrame() {
_curFrame++;
if (_curFrame == 0)
_startTime = g_system->getMillis();
return _surface;
}

View file

@ -41,33 +41,42 @@ namespace Video {
* - sword1
* - sword2
*/
class DXADecoder : public FixedRateVideoDecoder {
class DXADecoder : public AdvancedVideoDecoder {
public:
DXADecoder();
virtual ~DXADecoder();
bool loadStream(Common::SeekableReadStream *stream);
void close();
bool isVideoLoaded() const { return _fileStream != 0; }
protected:
/**
* Read the sound data out of the given DXA stream
*/
virtual void readSoundData(Common::SeekableReadStream *stream);
private:
class DXAVideoTrack : public FixedRateVideoTrack {
public:
DXAVideoTrack(Common::SeekableReadStream *stream);
~DXAVideoTrack();
bool isRewindable() const { return true; }
bool rewind();
uint16 getWidth() const { return _width; }
uint16 getHeight() const { return _height; }
uint32 getFrameCount() const { return _frameCount; }
Graphics::PixelFormat getPixelFormat() const;
int getCurFrame() const { return _curFrame; }
int getFrameCount() const { return _frameCount; }
const Graphics::Surface *decodeNextFrame();
Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }
const byte *getPalette() { _dirtyPalette = false; return _palette; }
const byte *getPalette() const { _dirtyPalette = false; return _palette; }
bool hasDirtyPalette() const { return _dirtyPalette; }
/**
* Get the sound chunk tag of the loaded DXA file
*/
uint32 getSoundTag() { return _soundTag; }
void setFrameStartPos();
protected:
Common::Rational getFrameRate() const { return _frameRate; }
Common::SeekableReadStream *_fileStream;
private:
void decodeZlib(byte *data, int size, int totalSize);
void decode12(int size);
@ -79,9 +88,8 @@ private:
S_DOUBLE
};
Common::SeekableReadStream *_fileStream;
Graphics::Surface *_surface;
byte _palette[256 * 3];
bool _dirtyPalette;
byte *_frameBuffer1;
byte *_frameBuffer2;
@ -93,10 +101,14 @@ private:
uint16 _curHeight;
uint32 _frameSize;
ScaleMode _scaleMode;
uint32 _soundTag;
uint16 _width, _height;
uint32 _frameRate;
uint32 _frameCount;
byte _palette[256 * 3];
mutable bool _dirtyPalette;
int _curFrame;
uint32 _frameStartOffset;
};
};
} // End of namespace Video