VIDEO: uplift 3do movie decoder from sherlock engine

The format is generic to 3DO and is also used by plumbers.
I think it's also accelerated on 3DO so probably is used by
a lot of 3DO titles
This commit is contained in:
Vladimir Serbinenko 2020-10-20 23:12:11 +02:00 committed by Eugene Sandulenko
parent f3f0d0228a
commit ce6eb34121
6 changed files with 42 additions and 36 deletions

@ -2,7 +2,6 @@ MODULE := engines/sherlock
MODULE_OBJS = \ MODULE_OBJS = \
scalpel/scalpel.o \ scalpel/scalpel.o \
scalpel/3do/movie_decoder.o \
scalpel/3do/scalpel_3do_screen.o \ scalpel/3do/scalpel_3do_screen.o \
scalpel/drivers/adlib.o \ scalpel/drivers/adlib.o \
scalpel/drivers/mt32.o \ scalpel/drivers/mt32.o \

@ -34,7 +34,7 @@
#include "sherlock/sherlock.h" #include "sherlock/sherlock.h"
#include "sherlock/music.h" #include "sherlock/music.h"
#include "sherlock/animation.h" #include "sherlock/animation.h"
#include "sherlock/scalpel/3do/movie_decoder.h" #include "video/3do_decoder.h"
namespace Sherlock { namespace Sherlock {
@ -1272,7 +1272,7 @@ void ScalpelEngine::showScummVMRestoreDialog() {
bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::Point &pos, bool isPortrait) { bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::Point &pos, bool isPortrait) {
Scalpel3DOScreen &screen = *(Scalpel3DOScreen *)_screen; Scalpel3DOScreen &screen = *(Scalpel3DOScreen *)_screen;
Scalpel3DOMovieDecoder *videoDecoder = new Scalpel3DOMovieDecoder(); Video::ThreeDOMovieDecoder *videoDecoder = new Video::ThreeDOMovieDecoder();
Graphics::ManagedSurface tempSurface; Graphics::ManagedSurface tempSurface;
Common::Point framePos(pos.x, pos.y); Common::Point framePos(pos.x, pos.y);

@ -30,7 +30,6 @@
#include "sherlock/scalpel/scalpel_user_interface.h" #include "sherlock/scalpel/scalpel_user_interface.h"
#include "sherlock/scalpel/scalpel.h" #include "sherlock/scalpel/scalpel.h"
#include "sherlock/screen.h" #include "sherlock/screen.h"
#include "sherlock/scalpel/3do/movie_decoder.h"
namespace Sherlock { namespace Sherlock {

@ -27,7 +27,7 @@
#include "audio/audiostream.h" #include "audio/audiostream.h"
#include "audio/decoders/3do.h" #include "audio/decoders/3do.h"
#include "sherlock/scalpel/3do/movie_decoder.h" #include "video/3do_decoder.h"
#include "image/codecs/cinepak.h" #include "image/codecs/cinepak.h"
// for Test-Code // for Test-Code
@ -40,19 +40,19 @@
#include "graphics/pixelformat.h" #include "graphics/pixelformat.h"
#include "graphics/surface.h" #include "graphics/surface.h"
namespace Sherlock { namespace Video {
Scalpel3DOMovieDecoder::Scalpel3DOMovieDecoder() ThreeDOMovieDecoder::ThreeDOMovieDecoder()
: _stream(0), _videoTrack(0), _audioTrack(0) { : _stream(0), _videoTrack(0), _audioTrack(0) {
_streamVideoOffset = 0; _streamVideoOffset = 0;
_streamAudioOffset = 0; _streamAudioOffset = 0;
} }
Scalpel3DOMovieDecoder::~Scalpel3DOMovieDecoder() { ThreeDOMovieDecoder::~ThreeDOMovieDecoder() {
close(); close();
} }
bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) { bool ThreeDOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
uint32 videoSubType = 0; uint32 videoSubType = 0;
uint32 videoCodecTag = 0; uint32 videoCodecTag = 0;
uint32 videoHeight = 0; uint32 videoHeight = 0;
@ -92,7 +92,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
case MKTAG('F', 'H', 'D', 'R'): case MKTAG('F', 'H', 'D', 'R'):
// FILM header found // FILM header found
if (_videoTrack) { if (_videoTrack) {
warning("Sherlock 3DO movie: Multiple FILM headers found"); warning("3DO movie: Multiple FILM headers found");
close(); close();
return false; return false;
} }
@ -111,7 +111,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
break; break;
default: default:
warning("Sherlock 3DO movie: Unknown subtype inside FILM packet"); warning("3DO movie: Unknown subtype inside FILM packet");
close(); close();
return false; return false;
} }
@ -128,7 +128,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
// Bail if we already have a track // Bail if we already have a track
if (_audioTrack) { if (_audioTrack) {
warning("Sherlock 3DO movie: Multiple SNDS headers found"); warning("3DO movie: Multiple SNDS headers found");
close(); close();
return false; return false;
} }
@ -154,7 +154,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
// Audio data // Audio data
break; break;
default: default:
warning("Sherlock 3DO movie: Unknown subtype inside FILM packet"); warning("3DO movie: Unknown subtype inside FILM packet");
close(); close();
return false; return false;
} }
@ -173,7 +173,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
break; break;
default: default:
warning("Unknown chunk-tag '%s' inside Sherlock 3DO movie", tag2str(chunkTag)); warning("Unknown chunk-tag '%s' inside 3DO movie", tag2str(chunkTag));
close(); close();
return false; return false;
} }
@ -197,7 +197,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
return true; return true;
} }
void Scalpel3DOMovieDecoder::close() { void ThreeDOMovieDecoder::close() {
Video::VideoDecoder::close(); Video::VideoDecoder::close();
delete _stream; _stream = 0; delete _stream; _stream = 0;
@ -206,7 +206,7 @@ void Scalpel3DOMovieDecoder::close() {
// We try to at least decode 1 frame // We try to at least decode 1 frame
// and also try to get at least 0.5 seconds of audio queued up // and also try to get at least 0.5 seconds of audio queued up
void Scalpel3DOMovieDecoder::readNextPacket() { void ThreeDOMovieDecoder::readNextPacket() {
uint32 currentMovieTime = getTime(); uint32 currentMovieTime = getTime();
uint32 wantedAudioQueued = currentMovieTime + 500; // always try to be 0.500 seconds in front of movie time uint32 wantedAudioQueued = currentMovieTime + 500; // always try to be 0.500 seconds in front of movie time
@ -300,7 +300,7 @@ void Scalpel3DOMovieDecoder::readNextPacket() {
break; break;
default: default:
error("Sherlock 3DO movie: Unknown subtype inside FILM packet"); error("3DO movie: Unknown subtype inside FILM packet");
break; break;
} }
break; break;
@ -332,7 +332,7 @@ void Scalpel3DOMovieDecoder::readNextPacket() {
break; break;
default: default:
error("Sherlock 3DO movie: Unknown subtype inside SNDS packet"); error("3DO movie: Unknown subtype inside SNDS packet");
break; break;
} }
break; break;
@ -349,7 +349,7 @@ void Scalpel3DOMovieDecoder::readNextPacket() {
break; break;
default: default:
error("Unknown chunk-tag '%s' inside Sherlock 3DO movie", tag2str(chunkTag)); error("Unknown chunk-tag '%s' inside 3DO movie", tag2str(chunkTag));
} }
// Always seek to end of chunk // Always seek to end of chunk
@ -362,7 +362,7 @@ void Scalpel3DOMovieDecoder::readNextPacket() {
} }
} }
Scalpel3DOMovieDecoder::StreamVideoTrack::StreamVideoTrack(uint32 width, uint32 height, uint32 codecTag, uint32 frameCount) { ThreeDOMovieDecoder::StreamVideoTrack::StreamVideoTrack(uint32 width, uint32 height, uint32 codecTag, uint32 frameCount) {
_width = width; _width = width;
_height = height; _height = height;
_frameCount = frameCount; _frameCount = frameCount;
@ -373,27 +373,27 @@ Scalpel3DOMovieDecoder::StreamVideoTrack::StreamVideoTrack(uint32 width, uint32
if (codecTag == MKTAG('c', 'v', 'i', 'd')) if (codecTag == MKTAG('c', 'v', 'i', 'd'))
_codec = new Image::CinepakDecoder(); _codec = new Image::CinepakDecoder();
else else
error("Unsupported Sherlock 3DO movie video codec tag '%s'", tag2str(codecTag)); error("Unsupported 3DO movie video codec tag '%s'", tag2str(codecTag));
} }
Scalpel3DOMovieDecoder::StreamVideoTrack::~StreamVideoTrack() { ThreeDOMovieDecoder::StreamVideoTrack::~StreamVideoTrack() {
delete _codec; delete _codec;
} }
bool Scalpel3DOMovieDecoder::StreamVideoTrack::endOfTrack() const { bool ThreeDOMovieDecoder::StreamVideoTrack::endOfTrack() const {
return getCurFrame() >= getFrameCount() - 1; return getCurFrame() >= getFrameCount() - 1;
} }
Graphics::PixelFormat Scalpel3DOMovieDecoder::StreamVideoTrack::getPixelFormat() const { Graphics::PixelFormat ThreeDOMovieDecoder::StreamVideoTrack::getPixelFormat() const {
return _codec->getPixelFormat(); return _codec->getPixelFormat();
} }
void Scalpel3DOMovieDecoder::StreamVideoTrack::decodeFrame(Common::SeekableReadStream *stream, uint32 videoTimeStamp) { void ThreeDOMovieDecoder::StreamVideoTrack::decodeFrame(Common::SeekableReadStream *stream, uint32 videoTimeStamp) {
_surface = _codec->decodeFrame(*stream); _surface = _codec->decodeFrame(*stream);
_curFrame++; _curFrame++;
} }
Scalpel3DOMovieDecoder::StreamAudioTrack::StreamAudioTrack(uint32 codecTag, uint32 sampleRate, uint32 channels, Audio::Mixer::SoundType soundType) : ThreeDOMovieDecoder::StreamAudioTrack::StreamAudioTrack(uint32 codecTag, uint32 sampleRate, uint32 channels, Audio::Mixer::SoundType soundType) :
AudioTrack(soundType) { AudioTrack(soundType) {
switch (codecTag) { switch (codecTag) {
case MKTAG('A','D','P','4'): case MKTAG('A','D','P','4'):
@ -402,7 +402,7 @@ Scalpel3DOMovieDecoder::StreamAudioTrack::StreamAudioTrack(uint32 codecTag, uint
break; break;
default: default:
error("Unsupported Sherlock 3DO movie audio codec tag '%s'", tag2str(codecTag)); error("Unsupported 3DO movie audio codec tag '%s'", tag2str(codecTag));
} }
_totalAudioQueued = 0; // currently 0 milliseconds queued _totalAudioQueued = 0; // currently 0 milliseconds queued
@ -417,7 +417,7 @@ Scalpel3DOMovieDecoder::StreamAudioTrack::StreamAudioTrack(uint32 codecTag, uint
_stereo = true; _stereo = true;
break; break;
default: default:
error("Unsupported Sherlock 3DO movie audio channels %d", channels); error("Unsupported 3DO movie audio channels %d", channels);
} }
_audioStream = Audio::makeQueuingAudioStream(sampleRate, _stereo); _audioStream = Audio::makeQueuingAudioStream(sampleRate, _stereo);
@ -427,13 +427,13 @@ Scalpel3DOMovieDecoder::StreamAudioTrack::StreamAudioTrack(uint32 codecTag, uint
memset(&_SDX2_PersistentSpace, 0, sizeof(_SDX2_PersistentSpace)); memset(&_SDX2_PersistentSpace, 0, sizeof(_SDX2_PersistentSpace));
} }
Scalpel3DOMovieDecoder::StreamAudioTrack::~StreamAudioTrack() { ThreeDOMovieDecoder::StreamAudioTrack::~StreamAudioTrack() {
delete _audioStream; delete _audioStream;
// free(_ADP4_PersistentSpace); // free(_ADP4_PersistentSpace);
// free(_SDX2_PersistentSpace); // free(_SDX2_PersistentSpace);
} }
void Scalpel3DOMovieDecoder::StreamAudioTrack::queueAudio(Common::SeekableReadStream *stream, uint32 size) { void ThreeDOMovieDecoder::StreamAudioTrack::queueAudio(Common::SeekableReadStream *stream, uint32 size) {
Common::SeekableReadStream *compressedAudioStream = 0; Common::SeekableReadStream *compressedAudioStream = 0;
Audio::RewindableAudioStream *audioStream = 0; Audio::RewindableAudioStream *audioStream = 0;
uint32 audioLengthMSecs = 0; uint32 audioLengthMSecs = 0;
@ -460,8 +460,8 @@ void Scalpel3DOMovieDecoder::StreamAudioTrack::queueAudio(Common::SeekableReadSt
} }
} }
Audio::AudioStream *Scalpel3DOMovieDecoder::StreamAudioTrack::getAudioStream() const { Audio::AudioStream *ThreeDOMovieDecoder::StreamAudioTrack::getAudioStream() const {
return _audioStream; return _audioStream;
} }
} // End of namespace Sherlock } // End of namespace Video

@ -39,12 +39,19 @@ namespace Image {
class Codec; class Codec;
} }
namespace Sherlock { namespace Video {
class Scalpel3DOMovieDecoder : public Video::VideoDecoder { /**
* Decoder for 3DO videos.
*
* Video decoder used in engines:
* - sherlock
* - plumbers
*/
class ThreeDOMovieDecoder : public Video::VideoDecoder {
public: public:
Scalpel3DOMovieDecoder(); ThreeDOMovieDecoder();
~Scalpel3DOMovieDecoder() override; ~ThreeDOMovieDecoder() override;
bool loadStream(Common::SeekableReadStream *stream) override; bool loadStream(Common::SeekableReadStream *stream) override;
void close() override; void close() override;

@ -1,6 +1,7 @@
MODULE := video MODULE := video
MODULE_OBJS := \ MODULE_OBJS := \
3do_decoder.o \
avi_decoder.o \ avi_decoder.o \
coktel_decoder.o \ coktel_decoder.o \
dxa_decoder.o \ dxa_decoder.o \