mirror of
https://github.com/libretro/scummvm.git
synced 2025-05-13 09:36:21 +00:00
TRECISION: Refactor the video decoder classes
Change NightlongVideoDecoder to be a base class. This allows us to remove it as an intermediate class and cleanly separate the PC Smacker from the Amiga video decoder
This commit is contained in:
parent
ede8abfd5d
commit
13be0648f0
@ -66,33 +66,38 @@ AnimManager::~AnimManager() {
|
||||
}
|
||||
|
||||
void AnimManager::playMovie(const Common::String &filename, int startFrame, int endFrame, bool singleChoice) {
|
||||
NightlongVideoDecoder *smkDecoder = new NightlongVideoDecoder(_vm->isAmiga());
|
||||
NightlongVideoDecoder *videoDecoder;
|
||||
|
||||
if (!smkDecoder->loadFile(filename)) {
|
||||
if (!_vm->isAmiga())
|
||||
videoDecoder = new NightlongSmackerDecoder();
|
||||
else
|
||||
videoDecoder = new NightlongAmigaDecoder();
|
||||
|
||||
if (!videoDecoder->loadFile(filename)) {
|
||||
warning("playMovie: File %s not found", filename.c_str());
|
||||
delete smkDecoder;
|
||||
delete videoDecoder;
|
||||
_vm->_dialogMgr->afterChoice();
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Event event;
|
||||
bool skipVideo = false;
|
||||
uint16 x = (g_system->getWidth() - smkDecoder->getWidth()) / 2;
|
||||
uint16 y = (g_system->getHeight() - smkDecoder->getHeight()) / 2;
|
||||
uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2;
|
||||
uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2;
|
||||
_vm->_drawText._text.clear();
|
||||
|
||||
smkDecoder->start();
|
||||
videoDecoder->start();
|
||||
|
||||
// WORKAROUND: If the video has a single choice, and it starts from
|
||||
// the beginning, ignore the calculated end frame and play all of it
|
||||
if (singleChoice && startFrame < 10 && endFrame < (int)smkDecoder->getFrameCount() - 1)
|
||||
endFrame = smkDecoder->getFrameCount() - 1;
|
||||
if (singleChoice && startFrame < 10 && endFrame < (int)videoDecoder->getFrameCount() - 1)
|
||||
endFrame = videoDecoder->getFrameCount() - 1;
|
||||
|
||||
setVideoRange(smkDecoder, startFrame, endFrame);
|
||||
setVideoRange(videoDecoder, startFrame, endFrame);
|
||||
|
||||
while (!_vm->shouldQuit() && startFrame != endFrame && !smkDecoder->endOfVideo() && !skipVideo) {
|
||||
if (smkDecoder->needsUpdate()) {
|
||||
drawFrame(smkDecoder, x, y, true);
|
||||
while (!_vm->shouldQuit() && startFrame != endFrame && !videoDecoder->endOfVideo() && !skipVideo) {
|
||||
if (videoDecoder->needsUpdate()) {
|
||||
drawFrame(videoDecoder, x, y, true);
|
||||
}
|
||||
|
||||
while (_vm->getEventManager()->pollEvent(event)) {
|
||||
@ -103,7 +108,7 @@ void AnimManager::playMovie(const Common::String &filename, int startFrame, int
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
|
||||
delete smkDecoder;
|
||||
delete videoDecoder;
|
||||
|
||||
_vm->_mouseLeftBtn = _vm->_mouseRightBtn = false;
|
||||
_vm->freeKey();
|
||||
@ -171,7 +176,10 @@ void AnimManager::openSmkAnim(int slot, const Common::String &name) {
|
||||
}
|
||||
|
||||
void AnimManager::openSmk(int slot, Common::SeekableReadStream *stream) {
|
||||
_animations[slot] = new NightlongVideoDecoder(_vm->isAmiga());
|
||||
if (!_vm->isAmiga())
|
||||
_animations[slot] = new NightlongSmackerDecoder();
|
||||
else
|
||||
_animations[slot] = new NightlongAmigaDecoder();
|
||||
|
||||
if (!_animations[slot]->loadStream(stream)) {
|
||||
warning("Invalid SMK file");
|
||||
@ -409,33 +417,33 @@ bool AnimManager::shouldShowAnim(int animation, Common::Rect curRect) {
|
||||
}
|
||||
|
||||
void AnimManager::drawSmkBackgroundFrame(int animation) {
|
||||
NightlongVideoDecoder *smkDecoder = _animations[kSmackerBackground];
|
||||
if (smkDecoder == nullptr)
|
||||
NightlongVideoDecoder *videoDecoder = _animations[kSmackerBackground];
|
||||
if (videoDecoder == nullptr)
|
||||
return;
|
||||
const Graphics::Surface *frame = smkDecoder->decodeNextFrame();
|
||||
const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
|
||||
if (!frame)
|
||||
return;
|
||||
|
||||
const Common::Rect *lastRect = smkDecoder->getNextDirtyRect();
|
||||
const byte *palette = smkDecoder->getPalette();
|
||||
const Common::Rect *lastRect = videoDecoder->getNextDirtyRect();
|
||||
const byte *palette = videoDecoder->getPalette();
|
||||
|
||||
if (smkDecoder->getCurFrame() == 0 && shouldShowAnim(animation, *lastRect) && !_bgAnimRestarted) {
|
||||
if (videoDecoder->getCurFrame() == 0 && shouldShowAnim(animation, *lastRect) && !_bgAnimRestarted) {
|
||||
_vm->_graphicsMgr->blitToScreenBuffer(frame, 0, TOP, palette, true);
|
||||
} else {
|
||||
while (lastRect) {
|
||||
if (smkDecoder->getCurFrame() > 0 && shouldShowAnim(animation, *lastRect)) {
|
||||
if (videoDecoder->getCurFrame() > 0 && shouldShowAnim(animation, *lastRect)) {
|
||||
Graphics::Surface anim = frame->getSubArea(*lastRect);
|
||||
_vm->_graphicsMgr->blitToScreenBuffer(&anim, lastRect->left, lastRect->top + TOP, palette, true);
|
||||
}
|
||||
|
||||
lastRect = smkDecoder->getNextDirtyRect();
|
||||
lastRect = videoDecoder->getNextDirtyRect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimManager::drawSmkIconFrame(uint16 startIcon, uint16 iconNum) {
|
||||
NightlongVideoDecoder *smkDecoder = _animations[kSmackerIcon];
|
||||
if (smkDecoder == nullptr)
|
||||
NightlongVideoDecoder *videoDecoder = _animations[kSmackerIcon];
|
||||
if (videoDecoder == nullptr)
|
||||
return;
|
||||
|
||||
int stx = ICONMARGSX;
|
||||
@ -453,11 +461,14 @@ void AnimManager::drawSmkIconFrame(uint16 startIcon, uint16 iconNum) {
|
||||
if (a == ICONSHOWN)
|
||||
return;
|
||||
|
||||
const Graphics::Surface *frame = smkDecoder->decodeNextFrame();
|
||||
_vm->_graphicsMgr->copyToScreenBuffer(frame, stx, FIRSTLINE, smkDecoder->getPalette());
|
||||
const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
|
||||
if (!frame)
|
||||
return;
|
||||
|
||||
if (smkDecoder->endOfVideo())
|
||||
smkDecoder->rewind();
|
||||
_vm->_graphicsMgr->copyToScreenBuffer(frame, stx, FIRSTLINE, videoDecoder->getPalette());
|
||||
|
||||
if (videoDecoder->endOfVideo())
|
||||
videoDecoder->rewind();
|
||||
}
|
||||
|
||||
void AnimManager::drawSmkActionFrame() {
|
||||
|
@ -39,160 +39,6 @@
|
||||
|
||||
namespace Trecision {
|
||||
|
||||
NightlongVideoDecoder::NightlongVideoDecoder(bool isAmiga) {
|
||||
_isAmiga = isAmiga;
|
||||
_smkDecoder = !isAmiga ? new NightlongSmackerDecoder() : nullptr;
|
||||
_mixer = g_system->getMixer();
|
||||
}
|
||||
|
||||
NightlongVideoDecoder::~NightlongVideoDecoder() {
|
||||
delete _smkDecoder;
|
||||
|
||||
if (_mixer->isSoundHandleActive(_amigaSoundHandle))
|
||||
_mixer->stopHandle(_amigaSoundHandle);
|
||||
}
|
||||
|
||||
bool NightlongVideoDecoder::loadFile(const Common::Path &filename) {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->loadFile(filename);
|
||||
else {
|
||||
// TODO: Amiga video format
|
||||
|
||||
// Load the video's audio track
|
||||
Common::File *stream = new Common::File();
|
||||
Common::String file = filename.toString();
|
||||
stream->open("a" + file);
|
||||
|
||||
if (stream->isOpen()) {
|
||||
Audio::SeekableAudioStream *sound = Audio::makeRawStream(stream, 11025, 0, DisposeAfterUse::YES);
|
||||
|
||||
_mixer->playStream(
|
||||
Audio::Mixer::kSFXSoundType,
|
||||
&_amigaSoundHandle,
|
||||
sound);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
delete stream;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NightlongVideoDecoder::loadStream(Common::SeekableReadStream *stream) {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->loadStream(stream);
|
||||
else
|
||||
return false; // TODO: Amiga videos
|
||||
}
|
||||
|
||||
void NightlongVideoDecoder::muteTrack(uint track, bool mute) {
|
||||
if (!_isAmiga)
|
||||
_smkDecoder->muteTrack(track, mute);
|
||||
// TODO: Amiga videos
|
||||
}
|
||||
|
||||
void NightlongVideoDecoder::setMute(bool mute) {
|
||||
if (!_isAmiga)
|
||||
_smkDecoder->setMute(mute);
|
||||
// TODO: Amiga videos
|
||||
}
|
||||
|
||||
bool NightlongVideoDecoder::forceSeekToFrame(uint frame) {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->forceSeekToFrame(frame);
|
||||
else
|
||||
return false; // TODO: Amiga videos
|
||||
}
|
||||
|
||||
bool NightlongVideoDecoder::endOfFrames() const {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->endOfFrames();
|
||||
else
|
||||
return !_mixer->isSoundHandleActive(_amigaSoundHandle); // HACK, since we only play the audio for now
|
||||
}
|
||||
|
||||
int NightlongVideoDecoder::getCurFrame() const {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->getCurFrame();
|
||||
else
|
||||
return 0; // TODO: Amiga videos
|
||||
}
|
||||
|
||||
uint16 NightlongVideoDecoder::getWidth() const {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->getWidth();
|
||||
else
|
||||
return 0; // TODO: Amiga videos
|
||||
}
|
||||
|
||||
uint16 NightlongVideoDecoder::getHeight() const {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->getHeight();
|
||||
else
|
||||
return 0; // TODO: Amiga videos
|
||||
}
|
||||
|
||||
const Graphics::Surface *NightlongVideoDecoder::decodeNextFrame() {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->decodeNextFrame();
|
||||
else
|
||||
return nullptr; // TODO: Amiga videos
|
||||
}
|
||||
|
||||
uint32 NightlongVideoDecoder::getFrameCount() const {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->getFrameCount();
|
||||
else
|
||||
return 10; // TODO: Amiga videos. Anything > 1 to keep playing till the audio is done
|
||||
}
|
||||
|
||||
const byte *NightlongVideoDecoder::getPalette() {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->getPalette();
|
||||
else
|
||||
return nullptr; // TODO: Amiga videos
|
||||
}
|
||||
|
||||
void NightlongVideoDecoder::start() {
|
||||
if (!_isAmiga)
|
||||
_smkDecoder->start();
|
||||
// TODO: Amiga videos
|
||||
}
|
||||
|
||||
void NightlongVideoDecoder::rewind() {
|
||||
if (!_isAmiga)
|
||||
_smkDecoder->rewind();
|
||||
// TODO: Amiga videos
|
||||
}
|
||||
|
||||
bool NightlongVideoDecoder::needsUpdate() const {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->needsUpdate();
|
||||
else
|
||||
return false; // TODO: Amiga videos
|
||||
}
|
||||
|
||||
void NightlongVideoDecoder::setEndFrame(uint frame) {
|
||||
if (!_isAmiga)
|
||||
_smkDecoder->setEndFrame(frame);
|
||||
// TODO: Amiga videos
|
||||
}
|
||||
|
||||
bool NightlongVideoDecoder::endOfVideo() const {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->endOfVideo();
|
||||
else
|
||||
return false; // TODO: Amiga videos
|
||||
}
|
||||
|
||||
const Common::Rect *NightlongVideoDecoder::getNextDirtyRect() {
|
||||
if (!_isAmiga)
|
||||
return _smkDecoder->getNextDirtyRect();
|
||||
else
|
||||
return nullptr; // TODO: Amiga videos
|
||||
}
|
||||
|
||||
bool NightlongSmackerDecoder::loadStream(Common::SeekableReadStream *stream) {
|
||||
if (!SmackerDecoder::loadStream(stream))
|
||||
return false;
|
||||
@ -271,4 +117,107 @@ bool NightlongSmackerDecoder::endOfFrames() const {
|
||||
return getCurFrame() >= (int32)getFrameCount() - 1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
NightlongAmigaDecoder::AmigaVideoTrack::AmigaVideoTrack(const Common::String &fileName) {
|
||||
memset(_palette, 0, sizeof(_palette));
|
||||
|
||||
Common::File *stream = new Common::File();
|
||||
stream->open(fileName);
|
||||
|
||||
if (!stream->isOpen())
|
||||
return;
|
||||
|
||||
_curFrame = 0;
|
||||
_frameCount = 10; // TODO: Anything > 1 to keep playing till the audio is done
|
||||
|
||||
// TODO: some videos have more than 256 entries
|
||||
/*uint16 palEntries = stream->readUint16LE();
|
||||
stream->skip(2); // unknown
|
||||
for (uint16 i = 0; i < palEntries; i++) {
|
||||
_palette[i * 3] = stream->readByte();
|
||||
_palette[i * 3 + 1] = stream->readByte();
|
||||
_palette[i * 3 + 2] = stream->readByte();
|
||||
stream->skip(1); // unused alpha channel
|
||||
}*/
|
||||
|
||||
delete stream;
|
||||
}
|
||||
|
||||
uint16 NightlongAmigaDecoder::AmigaVideoTrack::getWidth() const {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 NightlongAmigaDecoder::AmigaVideoTrack::getHeight() const {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
Graphics::PixelFormat NightlongAmigaDecoder::AmigaVideoTrack::getPixelFormat() const {
|
||||
// TODO
|
||||
return g_system->getScreenFormat();
|
||||
}
|
||||
|
||||
uint32 NightlongAmigaDecoder::AmigaVideoTrack::getNextFrameStartTime() const {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Graphics::Surface *NightlongAmigaDecoder::AmigaVideoTrack::decodeNextFrame() {
|
||||
// TODO
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NightlongAmigaDecoder::AmigaAudioTrack::AmigaAudioTrack(const Common::String &fileName) :
|
||||
AudioTrack(Audio::Mixer::SoundType::kSFXSoundType) {
|
||||
Common::File *stream = new Common::File();
|
||||
stream->open(fileName);
|
||||
_audioStream = Audio::makeRawStream(stream, 11025, 0, DisposeAfterUse::YES);
|
||||
}
|
||||
|
||||
void NightlongAmigaDecoder::readNextPacket() {
|
||||
AmigaVideoTrack *videoTrack = (AmigaVideoTrack *)getTrack(0);
|
||||
|
||||
if (videoTrack->endOfTrack())
|
||||
return;
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
bool NightlongAmigaDecoder::loadStream(Common::SeekableReadStream *stream) {
|
||||
Common::File *file = dynamic_cast<Common::File *>(stream);
|
||||
if (!file)
|
||||
return false;
|
||||
Common::String fileName = file->getName();
|
||||
addTrack(new AmigaVideoTrack(fileName));
|
||||
if (Common::File::exists("a" + fileName))
|
||||
addTrack(new AmigaAudioTrack("a" + fileName));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NightlongAmigaDecoder::muteTrack(uint track, bool mute) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void NightlongAmigaDecoder::setMute(bool mute) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
bool NightlongAmigaDecoder::forceSeekToFrame(uint frame) {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
const Common::Rect *NightlongAmigaDecoder::getNextDirtyRect() {
|
||||
// TODO
|
||||
return &_lastDirtyRect;
|
||||
}
|
||||
|
||||
bool NightlongAmigaDecoder::endOfFrames() const {
|
||||
//return getCurFrame() >= (int32)getFrameCount() - 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Trecision
|
||||
|
@ -32,46 +32,64 @@ namespace Trecision {
|
||||
|
||||
class TrecisionEngine;
|
||||
|
||||
class NightlongSmackerDecoder : public Video::SmackerDecoder {
|
||||
class NightlongVideoDecoder : public Video::SmackerDecoder {
|
||||
public:
|
||||
bool loadStream(Common::SeekableReadStream *stream) override;
|
||||
void muteTrack(uint track, bool mute);
|
||||
void setMute(bool mute);
|
||||
bool forceSeekToFrame(uint frame);
|
||||
bool endOfFrames() const;
|
||||
virtual void muteTrack(uint track, bool mute) {}
|
||||
virtual void setMute(bool mute) {}
|
||||
virtual bool forceSeekToFrame(uint frame) { return false; }
|
||||
virtual bool endOfFrames() const { return false; }
|
||||
};
|
||||
|
||||
class NightlongVideoDecoder {
|
||||
class NightlongSmackerDecoder : public NightlongVideoDecoder {
|
||||
public:
|
||||
NightlongVideoDecoder(bool isAmiga);
|
||||
~NightlongVideoDecoder();
|
||||
bool loadStream(Common::SeekableReadStream *stream);
|
||||
void muteTrack(uint track, bool mute);
|
||||
void setMute(bool mute);
|
||||
bool forceSeekToFrame(uint frame);
|
||||
bool endOfFrames() const;
|
||||
bool loadStream(Common::SeekableReadStream *stream) override;
|
||||
void muteTrack(uint track, bool mute) override;
|
||||
void setMute(bool mute) override;
|
||||
bool forceSeekToFrame(uint frame) override;
|
||||
bool endOfFrames() const override;
|
||||
};
|
||||
|
||||
// VideoDecoder functions
|
||||
int getCurFrame() const;
|
||||
uint16 getWidth() const;
|
||||
uint16 getHeight() const;
|
||||
const Graphics::Surface *decodeNextFrame();
|
||||
uint32 getFrameCount() const;
|
||||
const byte *getPalette();
|
||||
void start();
|
||||
void rewind();
|
||||
bool needsUpdate() const;
|
||||
void setEndFrame(uint frame);
|
||||
bool endOfVideo() const;
|
||||
|
||||
bool loadFile(const Common::Path &filename);
|
||||
const Common::Rect *getNextDirtyRect();
|
||||
class NightlongAmigaDecoder : public NightlongVideoDecoder {
|
||||
public:
|
||||
bool loadStream(Common::SeekableReadStream *stream) override;
|
||||
void muteTrack(uint track, bool mute) override;
|
||||
void setMute(bool mute) override;
|
||||
bool forceSeekToFrame(uint frame) override;
|
||||
bool endOfFrames() const override;
|
||||
const Common::Rect *getNextDirtyRect() override;
|
||||
|
||||
private:
|
||||
bool _isAmiga;
|
||||
NightlongSmackerDecoder *_smkDecoder;
|
||||
Audio::SoundHandle _amigaSoundHandle;
|
||||
Audio::Mixer *_mixer;
|
||||
Common::Rect _lastDirtyRect;
|
||||
|
||||
void readNextPacket() override;
|
||||
|
||||
class AmigaVideoTrack : public VideoTrack {
|
||||
public:
|
||||
AmigaVideoTrack(const Common::String &fileName);
|
||||
|
||||
private:
|
||||
byte _palette[3 * 256];
|
||||
int _curFrame;
|
||||
uint32 _frameCount;
|
||||
|
||||
uint16 getWidth() const override;
|
||||
uint16 getHeight() const override;
|
||||
Graphics::PixelFormat getPixelFormat() const override;
|
||||
int getCurFrame() const override { return _curFrame; }
|
||||
uint32 getNextFrameStartTime() const override;
|
||||
const Graphics::Surface *decodeNextFrame() override;
|
||||
int getFrameCount() const override { return _frameCount; }
|
||||
const byte *getPalette() const override { return _palette; }
|
||||
bool hasDirtyPalette() const override { return true; }
|
||||
};
|
||||
|
||||
class AmigaAudioTrack : public AudioTrack {
|
||||
public:
|
||||
AmigaAudioTrack(const Common::String &fileName);
|
||||
private:
|
||||
Audio::AudioStream *getAudioStream() const override { return _audioStream; }
|
||||
Audio::AudioStream *_audioStream;
|
||||
};
|
||||
};
|
||||
|
||||
} // End of namespace Trecision
|
||||
|
Loading…
x
Reference in New Issue
Block a user