VIDEO: Convert DXADecoder to the AdvancedVideoDecoder API
This commit is contained in:
parent
84e0b3a167
commit
3117e4a8ff
10 changed files with 218 additions and 307 deletions
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue