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

View file

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

View file

@ -23,16 +23,19 @@
#ifndef SWORD1_ANIMATION_H #ifndef SWORD1_ANIMATION_H
#define SWORD1_ANIMATION_H #define SWORD1_ANIMATION_H
#include "video/dxa_decoder.h"
#include "video/video_decoder.h"
#include "common/list.h" #include "common/list.h"
#include "audio/audiostream.h"
#include "sword1/screen.h" #include "sword1/screen.h"
#include "sword1/sound.h" #include "sword1/sound.h"
namespace Graphics {
struct Surface;
}
namespace Video {
class VideoDecoder;
}
namespace Sword1 { namespace Sword1 {
enum DecoderType { 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 { class MoviePlayer {
public: 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(); virtual ~MoviePlayer();
bool load(uint32 id); bool load(uint32 id);
void play(); void play();
@ -78,7 +69,6 @@ protected:
SwordEngine *_vm; SwordEngine *_vm;
Text *_textMan; Text *_textMan;
ResMan *_resMan; ResMan *_resMan;
Audio::Mixer *_snd;
OSystem *_system; OSystem *_system;
Common::List<MovieText> _movieTexts; Common::List<MovieText> _movieTexts;
int _textX, _textY, _textWidth, _textHeight; int _textX, _textY, _textWidth, _textHeight;
@ -88,8 +78,6 @@ protected:
DecoderType _decoderType; DecoderType _decoderType;
Video::VideoDecoder *_decoder; Video::VideoDecoder *_decoder;
Audio::SoundHandle *_bgSoundHandle;
Audio::AudioStream *_bgSoundStream;
bool playVideo(); bool playVideo();
void performPostProcessing(byte *screen); void performPostProcessing(byte *screen);
@ -100,7 +88,7 @@ protected:
void convertColor(byte r, byte g, byte b, float &h, float &s, float &v); 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 } // 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. // meantime, we don't want any looping sound effects still playing.
_sound->quitScreen(); _sound->quitScreen();
MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _mixer, _system); MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _system);
if (player) { if (player) {
_screen->clearScreen(); _screen->clearScreen();
if (player->load(sequenceId)) if (player->load(sequenceId))

View file

@ -40,6 +40,7 @@
#include "gui/message.h" #include "gui/message.h"
#include "video/dxa_decoder.h"
#include "video/smk_decoder.h" #include "video/smk_decoder.h"
#include "video/psx_decoder.h" #include "video/psx_decoder.h"
@ -51,9 +52,8 @@ namespace Sword2 {
// Basic movie player // Basic movie player
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
MoviePlayer::MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType) MoviePlayer::MoviePlayer(Sword2Engine *vm, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType)
: _vm(vm), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system) { : _vm(vm), _system(system) {
_bgSoundStream = NULL;
_decoderType = decoderType; _decoderType = decoderType;
_decoder = decoder; _decoder = decoder;
@ -62,7 +62,6 @@ MoviePlayer::MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, A
} }
MoviePlayer::~MoviePlayer() { MoviePlayer::~MoviePlayer() {
delete _bgSoundHandle;
delete _decoder; delete _decoder;
} }
@ -75,11 +74,6 @@ bool MoviePlayer::load(const char *name) {
if (_vm->shouldQuit()) if (_vm->shouldQuit())
return false; return false;
if (_decoderType == kVideoDecoderDXA)
_bgSoundStream = Audio::SeekableAudioStream::openStreamFile(name);
else
_bgSoundStream = NULL;
_textSurface = NULL; _textSurface = NULL;
Common::String filename; Common::String filename;
@ -89,13 +83,6 @@ bool MoviePlayer::load(const char *name) {
break; break;
case kVideoDecoderSMK: case kVideoDecoderSMK:
filename = Common::String::format("%s.smk", name); 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; break;
case kVideoDecoderPSX: case kVideoDecoderPSX:
filename = Common::String::format("%s.str", name); 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) { 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) if (leadIn)
_vm->_sound->playMovieSound(leadIn, kLeadInSound); _vm->_sound->playMovieSound(leadIn, kLeadInSound);
if (_bgSoundStream) bool terminated = !playVideo();
_snd->playStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream);
bool terminated = false;
terminated = !playVideo();
closeTextObject(_currentMovieText, NULL, 0); closeTextObject(_currentMovieText, NULL, 0);
if (terminated) { if (terminated) {
_snd->stopHandle(*_bgSoundHandle);
_vm->_sound->stopMovieSounds(); _vm->_sound->stopMovieSounds();
_vm->_sound->stopSpeech(); _vm->_sound->stopSpeech();
} }
while (_snd->isSoundHandleActive(*_bgSoundHandle))
_system->delayMillis(100);
if (_decoderType == kVideoDecoderPSX) { if (_decoderType == kVideoDecoderPSX) {
// Need to jump back to paletted color // Need to jump back to paletted color
initGraphics(640, 480, true); initGraphics(640, 480, true);
@ -414,31 +400,19 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
scaledFrame.free(); 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 // 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; Common::String filename;
Audio::SoundHandle *bgSoundHandle = new Audio::SoundHandle;
filename = Common::String::format("%s.str", name); filename = Common::String::format("%s.str", name);
if (Common::File::exists(filename)) { if (Common::File::exists(filename)) {
#ifdef USE_RGB_COLOR #ifdef USE_RGB_COLOR
Video::VideoDecoder *psxDecoder = new Video::PSXStreamDecoder(Video::PSXStreamDecoder::kCD2x, frameCount); 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 #else
GUI::MessageDialog dialog(_("PSX cutscenes found but ScummVM has been built without RGB color support"), _("OK")); GUI::MessageDialog dialog(_("PSX cutscenes found but ScummVM has been built without RGB color support"), _("OK"));
dialog.runModal(); dialog.runModal();
@ -450,15 +424,15 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *s
if (Common::File::exists(filename)) { if (Common::File::exists(filename)) {
Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder(); 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); filename = Common::String::format("%s.dxa", name);
if (Common::File::exists(filename)) { if (Common::File::exists(filename)) {
#ifdef USE_ZLIB #ifdef USE_ZLIB
DXADecoderWithSound *dxaDecoder = new DXADecoderWithSound(snd, bgSoundHandle); Video::DXADecoder *dxaDecoder = new Video::DXADecoder();
return new MoviePlayer(vm, snd, system, bgSoundHandle, dxaDecoder, kVideoDecoderDXA); return new MoviePlayer(vm, system, dxaDecoder, kVideoDecoderDXA);
#else #else
GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK")); GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK"));
dialog.runModal(); dialog.runModal();

View file

@ -25,12 +25,16 @@
#ifndef SWORD2_ANIMATION_H #ifndef SWORD2_ANIMATION_H
#define 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" #include "sword2/screen.h"
namespace Graphics {
struct Surface;
}
namespace Video {
class VideoDecoder;
}
namespace Sword2 { namespace Sword2 {
enum DecoderType { 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 { class MoviePlayer {
public: 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(); virtual ~MoviePlayer();
bool load(const char *name); bool load(const char *name);
@ -76,7 +69,6 @@ public:
protected: protected:
Sword2Engine *_vm; Sword2Engine *_vm;
Audio::Mixer *_snd;
OSystem *_system; OSystem *_system;
MovieText *_movieTexts; MovieText *_movieTexts;
uint32 _numMovieTexts; uint32 _numMovieTexts;
@ -87,8 +79,6 @@ protected:
DecoderType _decoderType; DecoderType _decoderType;
Video::VideoDecoder *_decoder; Video::VideoDecoder *_decoder;
Audio::SoundHandle *_bgSoundHandle;
Audio::AudioStream *_bgSoundStream;
uint32 _leadOut; uint32 _leadOut;
int _leadOutFrame; int _leadOutFrame;
@ -105,7 +95,7 @@ protected:
uint32 getWhiteColor(); 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 } // End of namespace Sword2

View file

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

View file

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

View file

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