From ce6eb341215b5624eac7df9f148b64fd8941288c Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@google.com>
Date: Tue, 20 Oct 2020 23:12:11 +0200
Subject: [PATCH] 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
---
 engines/sherlock/module.mk                    |  1 -
 engines/sherlock/scalpel/scalpel.cpp          |  4 +-
 engines/sherlock/scalpel/scalpel_talk.cpp     |  1 -
 .../3do_decoder.cpp                           | 56 +++++++++----------
 .../movie_decoder.h => video/3do_decoder.h    | 15 +++--
 video/module.mk                               |  1 +
 6 files changed, 42 insertions(+), 36 deletions(-)
 rename engines/sherlock/scalpel/3do/movie_decoder.cpp => video/3do_decoder.cpp (84%)
 rename engines/sherlock/scalpel/3do/movie_decoder.h => video/3do_decoder.h (93%)

diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk
index 265053a0809..e2b2e652454 100644
--- a/engines/sherlock/module.mk
+++ b/engines/sherlock/module.mk
@@ -2,7 +2,6 @@ MODULE := engines/sherlock
 
 MODULE_OBJS = \
 	scalpel/scalpel.o \
-	scalpel/3do/movie_decoder.o \
 	scalpel/3do/scalpel_3do_screen.o \
 	scalpel/drivers/adlib.o \
 	scalpel/drivers/mt32.o \
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 351d55a436d..3469372d378 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -34,7 +34,7 @@
 #include "sherlock/sherlock.h"
 #include "sherlock/music.h"
 #include "sherlock/animation.h"
-#include "sherlock/scalpel/3do/movie_decoder.h"
+#include "video/3do_decoder.h"
 
 namespace Sherlock {
 
@@ -1272,7 +1272,7 @@ void ScalpelEngine::showScummVMRestoreDialog() {
 
 bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::Point &pos, bool isPortrait) {
 	Scalpel3DOScreen &screen = *(Scalpel3DOScreen *)_screen;
-	Scalpel3DOMovieDecoder *videoDecoder = new Scalpel3DOMovieDecoder();
+	Video::ThreeDOMovieDecoder *videoDecoder = new Video::ThreeDOMovieDecoder();
 	Graphics::ManagedSurface tempSurface;
 
 	Common::Point framePos(pos.x, pos.y);
diff --git a/engines/sherlock/scalpel/scalpel_talk.cpp b/engines/sherlock/scalpel/scalpel_talk.cpp
index f1460fd01d6..55cf8207262 100644
--- a/engines/sherlock/scalpel/scalpel_talk.cpp
+++ b/engines/sherlock/scalpel/scalpel_talk.cpp
@@ -30,7 +30,6 @@
 #include "sherlock/scalpel/scalpel_user_interface.h"
 #include "sherlock/scalpel/scalpel.h"
 #include "sherlock/screen.h"
-#include "sherlock/scalpel/3do/movie_decoder.h"
 
 namespace Sherlock {
 
diff --git a/engines/sherlock/scalpel/3do/movie_decoder.cpp b/video/3do_decoder.cpp
similarity index 84%
rename from engines/sherlock/scalpel/3do/movie_decoder.cpp
rename to video/3do_decoder.cpp
index d14c46e56b2..ab6df337fd4 100644
--- a/engines/sherlock/scalpel/3do/movie_decoder.cpp
+++ b/video/3do_decoder.cpp
@@ -27,7 +27,7 @@
 #include "audio/audiostream.h"
 #include "audio/decoders/3do.h"
 
-#include "sherlock/scalpel/3do/movie_decoder.h"
+#include "video/3do_decoder.h"
 #include "image/codecs/cinepak.h"
 
 // for Test-Code
@@ -40,19 +40,19 @@
 #include "graphics/pixelformat.h"
 #include "graphics/surface.h"
 
-namespace Sherlock {
+namespace Video {
 
-Scalpel3DOMovieDecoder::Scalpel3DOMovieDecoder()
+ThreeDOMovieDecoder::ThreeDOMovieDecoder()
 	: _stream(0), _videoTrack(0), _audioTrack(0) {
 	_streamVideoOffset = 0;
 	_streamAudioOffset = 0;
 }
 
-Scalpel3DOMovieDecoder::~Scalpel3DOMovieDecoder() {
+ThreeDOMovieDecoder::~ThreeDOMovieDecoder() {
 	close();
 }
 
-bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
+bool ThreeDOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
 	uint32 videoSubType    = 0;
 	uint32 videoCodecTag   = 0;
 	uint32 videoHeight     = 0;
@@ -92,7 +92,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
 			case MKTAG('F', 'H', 'D', 'R'):
 				// FILM header found
 				if (_videoTrack) {
-					warning("Sherlock 3DO movie: Multiple FILM headers found");
+					warning("3DO movie: Multiple FILM headers found");
 					close();
 					return false;
 				}
@@ -111,7 +111,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
 				break;
 
 			default:
-				warning("Sherlock 3DO movie: Unknown subtype inside FILM packet");
+				warning("3DO movie: Unknown subtype inside FILM packet");
 				close();
 				return false;
 			}
@@ -128,7 +128,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
 
 				// Bail if we already have a track
 				if (_audioTrack) {
-					warning("Sherlock 3DO movie: Multiple SNDS headers found");
+					warning("3DO movie: Multiple SNDS headers found");
 					close();
 					return false;
 				}
@@ -154,7 +154,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
 				// Audio data
 				break;
 			default:
-				warning("Sherlock 3DO movie: Unknown subtype inside FILM packet");
+				warning("3DO movie: Unknown subtype inside FILM packet");
 				close();
 				return false;
 			}
@@ -173,7 +173,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
 			break;
 
 		default:
-			warning("Unknown chunk-tag '%s' inside Sherlock 3DO movie", tag2str(chunkTag));
+			warning("Unknown chunk-tag '%s' inside 3DO movie", tag2str(chunkTag));
 			close();
 			return false;
 		}
@@ -197,7 +197,7 @@ bool Scalpel3DOMovieDecoder::loadStream(Common::SeekableReadStream *stream) {
 	return true;
 }
 
-void Scalpel3DOMovieDecoder::close() {
+void ThreeDOMovieDecoder::close() {
 	Video::VideoDecoder::close();
 
 	delete _stream; _stream = 0;
@@ -206,7 +206,7 @@ void Scalpel3DOMovieDecoder::close() {
 
 // We try to at least decode 1 frame
 // and also try to get at least 0.5 seconds of audio queued up
-void Scalpel3DOMovieDecoder::readNextPacket() {
+void ThreeDOMovieDecoder::readNextPacket() {
 	uint32 currentMovieTime = getTime();
 	uint32 wantedAudioQueued  = currentMovieTime + 500; // always try to be 0.500 seconds in front of movie time
 
@@ -300,7 +300,7 @@ void Scalpel3DOMovieDecoder::readNextPacket() {
 				break;
 
 			default:
-				error("Sherlock 3DO movie: Unknown subtype inside FILM packet");
+				error("3DO movie: Unknown subtype inside FILM packet");
 				break;
 			}
 			break;
@@ -332,7 +332,7 @@ void Scalpel3DOMovieDecoder::readNextPacket() {
 				break;
 
 			default:
-				error("Sherlock 3DO movie: Unknown subtype inside SNDS packet");
+				error("3DO movie: Unknown subtype inside SNDS packet");
 				break;
 			}
 			break;
@@ -349,7 +349,7 @@ void Scalpel3DOMovieDecoder::readNextPacket() {
 			break;
 
 		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
@@ -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;
 	_height = height;
 	_frameCount = frameCount;
@@ -373,27 +373,27 @@ Scalpel3DOMovieDecoder::StreamVideoTrack::StreamVideoTrack(uint32 width, uint32
 	if (codecTag == MKTAG('c', 'v', 'i', 'd'))
 		_codec = new Image::CinepakDecoder();
 	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;
 }
 
-bool Scalpel3DOMovieDecoder::StreamVideoTrack::endOfTrack() const {
+bool ThreeDOMovieDecoder::StreamVideoTrack::endOfTrack() const {
 	return getCurFrame() >= getFrameCount() - 1;
 }
 
-Graphics::PixelFormat Scalpel3DOMovieDecoder::StreamVideoTrack::getPixelFormat() const {
+Graphics::PixelFormat ThreeDOMovieDecoder::StreamVideoTrack::getPixelFormat() const {
 	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);
 	_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) {
 	switch (codecTag) {
 	case MKTAG('A','D','P','4'):
@@ -402,7 +402,7 @@ Scalpel3DOMovieDecoder::StreamAudioTrack::StreamAudioTrack(uint32 codecTag, uint
 		break;
 
 	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
@@ -417,7 +417,7 @@ Scalpel3DOMovieDecoder::StreamAudioTrack::StreamAudioTrack(uint32 codecTag, uint
 		_stereo = true;
 		break;
 	default:
-		error("Unsupported Sherlock 3DO movie audio channels %d", channels);
+		error("Unsupported 3DO movie audio channels %d", channels);
 	}
 
 	_audioStream = Audio::makeQueuingAudioStream(sampleRate, _stereo);
@@ -427,13 +427,13 @@ Scalpel3DOMovieDecoder::StreamAudioTrack::StreamAudioTrack(uint32 codecTag, uint
 	memset(&_SDX2_PersistentSpace, 0, sizeof(_SDX2_PersistentSpace));
 }
 
-Scalpel3DOMovieDecoder::StreamAudioTrack::~StreamAudioTrack() {
+ThreeDOMovieDecoder::StreamAudioTrack::~StreamAudioTrack() {
 	delete _audioStream;
 //	free(_ADP4_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;
 	Audio::RewindableAudioStream *audioStream = 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;
 }
 
-} // End of namespace Sherlock
+} // End of namespace Video
diff --git a/engines/sherlock/scalpel/3do/movie_decoder.h b/video/3do_decoder.h
similarity index 93%
rename from engines/sherlock/scalpel/3do/movie_decoder.h
rename to video/3do_decoder.h
index b54c424315c..e03bd8a1ed7 100644
--- a/engines/sherlock/scalpel/3do/movie_decoder.h
+++ b/video/3do_decoder.h
@@ -39,12 +39,19 @@ namespace Image {
 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:
-	Scalpel3DOMovieDecoder();
-	~Scalpel3DOMovieDecoder() override;
+	ThreeDOMovieDecoder();
+	~ThreeDOMovieDecoder() override;
 
 	bool loadStream(Common::SeekableReadStream *stream) override;
 	void close() override;
diff --git a/video/module.mk b/video/module.mk
index c1fb79256ee..875b141672e 100644
--- a/video/module.mk
+++ b/video/module.mk
@@ -1,6 +1,7 @@
 MODULE := video
 
 MODULE_OBJS := \
+	3do_decoder.o \
 	avi_decoder.o \
 	coktel_decoder.o \
 	dxa_decoder.o \