[Scummvm-git-logs] scummvm master -> 5956fa4757fe303fdaeb386f637ec27590a5a5fc

sev- noreply at scummvm.org
Wed Apr 5 10:45:22 UTC 2023


This automated email contains information about 11 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
78faa2ae28 IMAGE: Defer creation of surface until decodeFrame() is called in Indeo codecs
9a6897a852 IMAGE: Allow the default pixel format to be changed for YUV codecs
8a4a5bdc55 VIDEO: Add setOutputPixelFormat() to the VideoDecoder interface
a5603ac1f4 TESTBED: Pick the best pixel format in the video player
d72fee204c VIDEO: Implement setOutputPixelFormat() for MPEGPSDecoder
adef12d993 VIDEO: Implement setOutputPixelFormat() for BinkDecoder
475354cb4c VIDEO: Implement setOutputPixelFormat() for PSXStreamDecoder
70a6159af5 VIDEO: Implement setOutputPixelFormat() for TheoraDecoder
e6260bf089 VIDEO: Implement setOutputPixelFormat() for MKVDecoder
75e8dd71b7 ASYLUM: Select the best pixel format for video playback
5956fa4757 VIDEO: Remove VideoDecoder::setDefaultHighColorFormat()


Commit: 78faa2ae2888a0b4645490b1cdb77bb27173bebb
    https://github.com/scummvm/scummvm/commit/78faa2ae2888a0b4645490b1cdb77bb27173bebb
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
IMAGE: Defer creation of surface until decodeFrame() is called in Indeo codecs

Changed paths:
    image/codecs/indeo/indeo.cpp
    image/codecs/indeo/indeo.h
    image/codecs/indeo3.cpp
    image/codecs/indeo3.h
    image/codecs/indeo4.cpp
    image/codecs/indeo5.cpp


diff --git a/image/codecs/indeo/indeo.cpp b/image/codecs/indeo/indeo.cpp
index 6dbafe0e0b5..997b16a3c13 100644
--- a/image/codecs/indeo/indeo.cpp
+++ b/image/codecs/indeo/indeo.cpp
@@ -463,7 +463,10 @@ IVI45DecContext::IVI45DecContext() : _gb(nullptr), _frameNum(0), _frameType(0),
 
 /*------------------------------------------------------------------------*/
 
-IndeoDecoderBase::IndeoDecoderBase(uint16 width, uint16 height, uint bitsPerPixel) : Codec() {
+IndeoDecoderBase::IndeoDecoderBase(uint16 width, uint16 height, uint bitsPerPixel) : Codec(), _surface(nullptr) {
+	_width = width;
+	_height = height;
+	_bitsPerPixel = bitsPerPixel;
 	_pixelFormat = g_system->getScreenFormat();
 
 	if (_pixelFormat.bytesPerPixel == 1) {
@@ -486,13 +489,15 @@ IndeoDecoderBase::IndeoDecoderBase(uint16 width, uint16 height, uint bitsPerPixe
 		}
 	}
 
-	_surface.create(width, height, _pixelFormat);
-	_surface.fillRect(Common::Rect(0, 0, width, height), (bitsPerPixel == 32) ? 0xff : 0);
 	_ctx._bRefBuf = 3; // buffer 2 is used for scalability mode
 }
 
 IndeoDecoderBase::~IndeoDecoderBase() {
-	_surface.free();
+	if (_surface) {
+		_surface->free();
+		delete _surface;
+		_surface = nullptr;
+	}
 	IVIPlaneDesc::freeBuffers(_ctx._planes);
 	if (_ctx._mbVlc._custTab._table)
 		_ctx._mbVlc._custTab.freeVlc();
@@ -507,6 +512,12 @@ int IndeoDecoderBase::decodeIndeoFrame() {
 	AVFrame frameData;
 	AVFrame *frame = &frameData;
 
+	if (!_surface) {
+		_surface = new Graphics::Surface;
+		_surface->create(_width, _height, _pixelFormat);
+		_surface->fillRect(Common::Rect(0, 0, _width, _height), (_bitsPerPixel == 32) ? 0xff : 0);
+	}
+
 	// Decode the header
 	if (decodePictureHeader() < 0)
 		return -1;
@@ -562,7 +573,7 @@ int IndeoDecoderBase::decodeIndeoFrame() {
 	if (!isNonNullFrame())
 		return 0;
 
-	assert(_ctx._planes[0]._width <= _surface.w && _ctx._planes[0]._height <= _surface.h);
+	assert(_ctx._planes[0]._width <= _surface->w && _ctx._planes[0]._height <= _surface->h);
 	result = frame->setDimensions(_ctx._planes[0]._width, _ctx._planes[0]._height);
 	if (result < 0)
 		return result;
@@ -583,7 +594,7 @@ int IndeoDecoderBase::decodeIndeoFrame() {
 	outputPlane(&_ctx._planes[1], frame->_data[2], frame->_linesize[2]);
 
 	// Merge the planes into the final surface
-	YUVToRGBMan.convert410(&_surface, Graphics::YUVToRGBManager::kScaleITU,
+	YUVToRGBMan.convert410(_surface, Graphics::YUVToRGBManager::kScaleITU,
 		frame->_data[0], frame->_data[1], frame->_data[2], frame->_width, frame->_height,
 		frame->_width, frame->_width);
 
diff --git a/image/codecs/indeo/indeo.h b/image/codecs/indeo/indeo.h
index 639d7f19023..388ea46004e 100644
--- a/image/codecs/indeo/indeo.h
+++ b/image/codecs/indeo/indeo.h
@@ -518,8 +518,11 @@ private:
 		int blkSize);
 protected:
 	IVI45DecContext _ctx;
+	uint16 _width;
+	uint16 _height;
+	uint _bitsPerPixel;
 	Graphics::PixelFormat _pixelFormat;
-	Graphics::Surface _surface;
+	Graphics::Surface *_surface;
 
 	/**
 	 *  Scan patterns shared between indeo4 and indeo5
diff --git a/image/codecs/indeo3.cpp b/image/codecs/indeo3.cpp
index f7918653d54..ca43d803cc6 100644
--- a/image/codecs/indeo3.cpp
+++ b/image/codecs/indeo3.cpp
@@ -39,10 +39,12 @@
 
 namespace Image {
 
-Indeo3Decoder::Indeo3Decoder(uint16 width, uint16 height, uint bitsPerPixel) : _ModPred(0), _corrector_type(0) {
+Indeo3Decoder::Indeo3Decoder(uint16 width, uint16 height, uint bitsPerPixel) : _surface(nullptr), _ModPred(0), _corrector_type(0) {
 	_iv_frame[0].the_buf = 0;
 	_iv_frame[1].the_buf = 0;
 
+	_width = width;
+	_height = height;
 	_pixelFormat = g_system->getScreenFormat();
 
 	if (_pixelFormat.bytesPerPixel == 1) {
@@ -65,16 +67,16 @@ Indeo3Decoder::Indeo3Decoder(uint16 width, uint16 height, uint bitsPerPixel) : _
 		}
 	}
 
-	_surface = new Graphics::Surface;
-	_surface->create(width, height, _pixelFormat);
-
 	buildModPred();
 	allocFrames();
 }
 
 Indeo3Decoder::~Indeo3Decoder() {
-	_surface->free();
-	delete _surface;
+	if (_surface) {
+		_surface->free();
+		delete _surface;
+		_surface = nullptr;
+	}
 
 	delete[] _iv_frame[0].the_buf;
 	delete[] _ModPred;
@@ -134,8 +136,8 @@ void Indeo3Decoder::buildModPred() {
 }
 
 void Indeo3Decoder::allocFrames() {
-	int32 luma_width   = (_surface->w + 3) & (~3);
-	int32 luma_height  = (_surface->h + 3) & (~3);
+	int32 luma_width   = (_width + 3) & (~3);
+	int32 luma_height  = (_height + 3) & (~3);
 
 	int32 chroma_width  = ((luma_width  >> 2) + 3) & (~3);
 	int32 chroma_height = ((luma_height >> 2) + 3) & (~3);
@@ -211,6 +213,11 @@ const Graphics::Surface *Indeo3Decoder::decodeFrame(Common::SeekableReadStream &
 		_ref_frame = _iv_frame + 1;
 	}
 
+	if (!_surface) {
+		_surface = new Graphics::Surface;
+		_surface->create(_width, _height, _pixelFormat);
+	}
+
 	if (flags3 == 0x80)
 		return _surface;
 
diff --git a/image/codecs/indeo3.h b/image/codecs/indeo3.h
index d27b007f715..2646f8fcea6 100644
--- a/image/codecs/indeo3.h
+++ b/image/codecs/indeo3.h
@@ -56,6 +56,8 @@ public:
 private:
 	Graphics::Surface *_surface;
 
+	uint16 _width;
+	uint16 _height;
 	Graphics::PixelFormat _pixelFormat;
 
 	static const int _corrector_type_0[24];
diff --git a/image/codecs/indeo4.cpp b/image/codecs/indeo4.cpp
index d8b4ba714d6..32c4583b213 100644
--- a/image/codecs/indeo4.cpp
+++ b/image/codecs/indeo4.cpp
@@ -88,7 +88,7 @@ const Graphics::Surface *Indeo4Decoder::decodeFrame(Common::SeekableReadStream &
 	_ctx._frameData = nullptr;
 	_ctx._frameSize = 0;
 
-	return (err < 0) ? nullptr : &_surface;
+	return (err < 0) ? nullptr : _surface;
 }
 
 int Indeo4Decoder::decodePictureHeader() {
@@ -111,11 +111,11 @@ int Indeo4Decoder::decodePictureHeader() {
 		_ctx._hasBFrames = true;
 
 	_ctx._hasTransp = _ctx._gb->getBit();
-	if (_ctx._hasTransp && _surface.format.aBits() == 0) {
+	if (_ctx._hasTransp && _surface->format.aBits() == 0) {
 		// Surface is 4 bytes per pixel, but only RGB. So promote the
 		// surface to full RGBA, and convert all the existing pixels
 		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
-		_surface.convertToInPlace(_pixelFormat);
+		_surface->convertToInPlace(_pixelFormat);
 	}
 
 	// unknown bit: Mac decoder ignores this bit, XANIM returns error
@@ -610,16 +610,16 @@ int Indeo4Decoder::decodeRLETransparency(VLC_TYPE (*table)[2]) {
 	bool runIsOpaque = _ctx._gb->getBit();
 	bool nextRunIsOpaque = !runIsOpaque;
 
-	uint32 *pixel = (uint32 *)_surface.getPixels();
-	const int surfacePixelPitch = _surface.pitch / _surface.format.bytesPerPixel;
-	const int surfacePadding = surfacePixelPitch - _surface.w;
-	const uint32 *endOfVisibleRow = pixel + _surface.w;
-	const uint32 *endOfVisibleArea = pixel + surfacePixelPitch * _surface.h - surfacePadding;
+	uint32 *pixel = (uint32 *)_surface->getPixels();
+	const int surfacePixelPitch = _surface->pitch / _surface->format.bytesPerPixel;
+	const int surfacePadding = surfacePixelPitch - _surface->w;
+	const uint32 *endOfVisibleRow = pixel + _surface->w;
+	const uint32 *endOfVisibleArea = pixel + surfacePixelPitch * _surface->h - surfacePadding;
 
-	const int codecAlignedWidth = (_surface.w + 31) & ~31;
-	const int codecPaddingSize = codecAlignedWidth - _surface.w;
+	const int codecAlignedWidth = (_surface->w + 31) & ~31;
+	const int codecPaddingSize = codecAlignedWidth - _surface->w;
 
-	int numPixelsToRead = codecAlignedWidth * _surface.h;
+	int numPixelsToRead = codecAlignedWidth * _surface->h;
 	int numPixelsToSkip = 0;
 	while (numPixelsToRead > 0) {
 		int value = _ctx._gb->getVLC2<1, IVI_VLC_BITS>(table);
@@ -716,7 +716,7 @@ int Indeo4Decoder::decodeTransparency() {
 
 	if (_ctx._gb->getBit()) { /* @350 */
 		/* @358 */
-		_ctx._transKeyColor = _surface.format.ARGBToColor(0, _ctx._gb->getBits<8>(), _ctx._gb->getBits<8>(), _ctx._gb->getBits<8>());
+		_ctx._transKeyColor = _surface->format.ARGBToColor(0, _ctx._gb->getBits<8>(), _ctx._gb->getBits<8>(), _ctx._gb->getBits<8>());
 		debug(4, "Indeo4: Key color is %08x", _ctx._transKeyColor);
 		/* @477 */
 	}
@@ -767,8 +767,8 @@ int Indeo4Decoder::decodeTransparency() {
 	// necessary for correct decoding of game videos.
 	assert(!_ctx._usesTiling);
 
-	assert(_surface.format.bytesPerPixel == 4);
-	assert((_surface.pitch % 4) == 0);
+	assert(_surface->format.bytesPerPixel == 4);
+	assert((_surface->pitch % 4) == 0);
 
 	const uint32 startByte = _ctx._gb->pos() / 8;
 
@@ -781,7 +781,7 @@ int Indeo4Decoder::decodeTransparency() {
 			// It should only be necessary to draw transparency here since the
 			// data from the YUV planes gets drawn to the output surface on each
 			// frame, which resets the surface pixels to be fully opaque
-			_surface.fillRect(Common::Rect(_surface.w, _surface.h), _ctx._transKeyColor);
+			_surface->fillRect(Common::Rect(_surface->w, _surface->h), _ctx._transKeyColor);
 		}
 
 		// No alignment here
diff --git a/image/codecs/indeo5.cpp b/image/codecs/indeo5.cpp
index ab45cd9d041..c845b189641 100644
--- a/image/codecs/indeo5.cpp
+++ b/image/codecs/indeo5.cpp
@@ -96,7 +96,7 @@ const Graphics::Surface *Indeo5Decoder::decodeFrame(Common::SeekableReadStream &
 	_ctx._frameData = nullptr;
 	_ctx._frameSize = 0;
 
-	return (err < 0) ? nullptr : &_surface;
+	return (err < 0) ? nullptr : _surface;
 }
 
 int Indeo5Decoder::decodePictureHeader() {


Commit: 9a6897a85273e64ae46c03e932cc771625de0b58
    https://github.com/scummvm/scummvm/commit/9a6897a85273e64ae46c03e932cc771625de0b58
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
IMAGE: Allow the default pixel format to be changed for YUV codecs

Changed paths:
    image/codecs/cinepak.cpp
    image/codecs/cinepak.h
    image/codecs/codec.h
    image/codecs/indeo/indeo.cpp
    image/codecs/indeo/indeo.h
    image/codecs/indeo3.cpp
    image/codecs/indeo3.h
    image/codecs/mjpeg.cpp
    image/codecs/mjpeg.h
    image/codecs/mpeg.cpp
    image/codecs/mpeg.h
    image/codecs/svq1.cpp
    image/codecs/svq1.h
    image/codecs/xan.h
    image/jpeg.h


diff --git a/image/codecs/cinepak.cpp b/image/codecs/cinepak.cpp
index 53d68617451..1133eccd731 100644
--- a/image/codecs/cinepak.cpp
+++ b/image/codecs/cinepak.cpp
@@ -624,6 +624,14 @@ void CinepakDecoder::decodeVectors(Common::SeekableReadStream &stream, uint16 st
 	}
 }
 
+bool CinepakDecoder::setOutputPixelFormat(const Graphics::PixelFormat &format) {
+	if (_bitsPerPixel == 8)
+		return false;
+
+	_pixelFormat = format;
+	return true;
+}
+
 bool CinepakDecoder::canDither(DitherType type) const {
 	return (type == kDitherTypeVFW || type == kDitherTypeQT) && _bitsPerPixel == 24;
 }
diff --git a/image/codecs/cinepak.h b/image/codecs/cinepak.h
index 2c67b194c5f..a537ac8c3c5 100644
--- a/image/codecs/cinepak.h
+++ b/image/codecs/cinepak.h
@@ -74,6 +74,7 @@ public:
 
 	const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream) override;
 	Graphics::PixelFormat getPixelFormat() const override { return _pixelFormat; }
+	bool setOutputPixelFormat(const Graphics::PixelFormat &format) override;
 
 	bool containsPalette() const override { return _ditherPalette != 0; }
 	const byte *getPalette() override { _dirtyPalette = false; return _ditherPalette; }
diff --git a/image/codecs/codec.h b/image/codecs/codec.h
index 7645039c7f5..8109c50766d 100644
--- a/image/codecs/codec.h
+++ b/image/codecs/codec.h
@@ -85,6 +85,12 @@ public:
 	 */
 	virtual Graphics::PixelFormat getPixelFormat() const = 0;
 
+	/**
+	 * Select the preferred format to use, for codecs where this is faster than converting
+	 * the image afterwards. Returns true if supported, and false otherwise.
+	 */
+	virtual bool setOutputPixelFormat(const Graphics::PixelFormat &format) { return false; }
+
 	/**
 	 * Can this codec's frames contain a palette?
 	 */
diff --git a/image/codecs/indeo/indeo.cpp b/image/codecs/indeo/indeo.cpp
index 997b16a3c13..aa307906fa7 100644
--- a/image/codecs/indeo/indeo.cpp
+++ b/image/codecs/indeo/indeo.cpp
@@ -469,25 +469,9 @@ IndeoDecoderBase::IndeoDecoderBase(uint16 width, uint16 height, uint bitsPerPixe
 	_bitsPerPixel = bitsPerPixel;
 	_pixelFormat = g_system->getScreenFormat();
 
-	if (_pixelFormat.bytesPerPixel == 1) {
-		switch (bitsPerPixel) {
-		case 15:
-			_pixelFormat = Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0);
-			break;
-		case 16:
-			_pixelFormat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
-			break;
-		case 24:
-			_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0);
-			break;
-		case 32:
-			_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
-			break;
-		default:
-			error("Invalid color depth");
-			break;
-		}
-	}
+	// Default to a 32bpp format, if in 8bpp mode
+	if (_pixelFormat.bytesPerPixel == 1)
+		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
 
 	_ctx._bRefBuf = 3; // buffer 2 is used for scalability mode
 }
diff --git a/image/codecs/indeo/indeo.h b/image/codecs/indeo/indeo.h
index 388ea46004e..dc543e74ad5 100644
--- a/image/codecs/indeo/indeo.h
+++ b/image/codecs/indeo/indeo.h
@@ -536,6 +536,12 @@ protected:
 	 */
 	Graphics::PixelFormat getPixelFormat() const override { return _pixelFormat; }
 
+	/**
+	 * Select the preferred format to use, for codecs where this is faster than converting
+	 * the image afterwards. Returns true if supported, and false otherwise.
+	 */
+	bool setOutputPixelFormat(const Graphics::PixelFormat &format) { _pixelFormat = format; return true; }
+
 	/**
 	 * Decode the Indeo picture header.
 	 * @returns		0 = Ok, negative number = error
diff --git a/image/codecs/indeo3.cpp b/image/codecs/indeo3.cpp
index ca43d803cc6..dc5f31886ee 100644
--- a/image/codecs/indeo3.cpp
+++ b/image/codecs/indeo3.cpp
@@ -47,25 +47,9 @@ Indeo3Decoder::Indeo3Decoder(uint16 width, uint16 height, uint bitsPerPixel) : _
 	_height = height;
 	_pixelFormat = g_system->getScreenFormat();
 
-	if (_pixelFormat.bytesPerPixel == 1) {
-		switch (bitsPerPixel) {
-		case 15:
-			_pixelFormat = Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0);
-			break;
-		case 16:
-			_pixelFormat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
-			break;
-		case 24:
-			_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0);
-			break;
-		case 32:
-			_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
-			break;
-		default:
-			error("Invalid color depth");
-			break;
-		}
-	}
+	// Default to a 32bpp format, if in 8bpp mode
+	if (_pixelFormat.bytesPerPixel == 1)
+		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
 
 	buildModPred();
 	allocFrames();
diff --git a/image/codecs/indeo3.h b/image/codecs/indeo3.h
index 2646f8fcea6..d223c1b3de6 100644
--- a/image/codecs/indeo3.h
+++ b/image/codecs/indeo3.h
@@ -50,6 +50,7 @@ public:
 
 	const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream) override;
 	Graphics::PixelFormat getPixelFormat() const override;
+	bool setOutputPixelFormat(const Graphics::PixelFormat &format) override { _pixelFormat = format; return true; }
 
 	static bool isIndeo3(Common::SeekableReadStream &stream);
 
diff --git a/image/codecs/mjpeg.cpp b/image/codecs/mjpeg.cpp
index 662bee3b8d7..397553e6366 100644
--- a/image/codecs/mjpeg.cpp
+++ b/image/codecs/mjpeg.cpp
@@ -40,6 +40,11 @@ namespace Image {
 
 MJPEGDecoder::MJPEGDecoder() : Codec() {
 	_pixelFormat = g_system->getScreenFormat();
+
+	// Default to a 32bpp format, if in 8bpp mode
+	if (_pixelFormat.bytesPerPixel == 1)
+		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
+
 	_surface = 0;
 }
 
diff --git a/image/codecs/mjpeg.h b/image/codecs/mjpeg.h
index c52b38144ec..c68ecc0d85e 100644
--- a/image/codecs/mjpeg.h
+++ b/image/codecs/mjpeg.h
@@ -47,6 +47,7 @@ public:
 
 	const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream) override;
 	Graphics::PixelFormat getPixelFormat() const override { return _pixelFormat; }
+	bool setOutputPixelFormat(const Graphics::PixelFormat &format) override { _pixelFormat = format; return true; }
 
 private:
 	Graphics::PixelFormat _pixelFormat;
diff --git a/image/codecs/mpeg.cpp b/image/codecs/mpeg.cpp
index d10eff0fd38..c708bd3ee3e 100644
--- a/image/codecs/mpeg.cpp
+++ b/image/codecs/mpeg.cpp
@@ -37,6 +37,11 @@ namespace Image {
 
 MPEGDecoder::MPEGDecoder() : Codec() {
 	_pixelFormat = g_system->getScreenFormat();
+
+	// Default to a 32bpp format, if in 8bpp mode
+	if (_pixelFormat.bytesPerPixel == 1)
+		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
+
 	_surface = 0;
 
 	_mpegDecoder = mpeg2_init();
diff --git a/image/codecs/mpeg.h b/image/codecs/mpeg.h
index eb7a64af597..5b5eaf50de4 100644
--- a/image/codecs/mpeg.h
+++ b/image/codecs/mpeg.h
@@ -53,6 +53,7 @@ public:
 	// Codec interface
 	const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream) override;
 	Graphics::PixelFormat getPixelFormat() const override { return _pixelFormat; }
+	bool setOutputPixelFormat(const Graphics::PixelFormat &format) override { _pixelFormat = format; return true; }
 
 	// MPEGPSDecoder call
 	bool decodePacket(Common::SeekableReadStream &packet, uint32 &framePeriod, Graphics::Surface *dst = 0);
diff --git a/image/codecs/svq1.cpp b/image/codecs/svq1.cpp
index c02c5f22e09..47dde72bf7c 100644
--- a/image/codecs/svq1.cpp
+++ b/image/codecs/svq1.cpp
@@ -47,6 +47,12 @@ SVQ1Decoder::SVQ1Decoder(uint16 width, uint16 height) {
 	debug(1, "SVQ1Decoder::SVQ1Decoder(width:%d, height:%d)", width, height);
 	_width = width;
 	_height = height;
+	_pixelFormat = g_system->getScreenFormat();
+
+	// Default to a 32bpp format, if in 8bpp mode
+	if (_pixelFormat.bytesPerPixel == 1)
+		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
+
 	_frameWidth = _frameHeight = 0;
 	_surface = 0;
 
@@ -251,7 +257,7 @@ const Graphics::Surface *SVQ1Decoder::decodeFrame(Common::SeekableReadStream &st
 	// Now we'll create the surface
 	if (!_surface) {
 		_surface = new Graphics::Surface();
-		_surface->create(yWidth, yHeight, g_system->getScreenFormat());
+		_surface->create(yWidth, yHeight, _pixelFormat);
 		_surface->w = _width;
 		_surface->h = _height;
 	}
diff --git a/image/codecs/svq1.h b/image/codecs/svq1.h
index e9c678f38ba..f5090c27f7b 100644
--- a/image/codecs/svq1.h
+++ b/image/codecs/svq1.h
@@ -44,9 +44,11 @@ public:
 	~SVQ1Decoder() override;
 
 	const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream) override;
-	Graphics::PixelFormat getPixelFormat() const override { return _surface->format; }
+	Graphics::PixelFormat getPixelFormat() const override { return _pixelFormat; }
+	bool setOutputPixelFormat(const Graphics::PixelFormat &format) override { _pixelFormat = format; return true; }
 
 private:
+	Graphics::PixelFormat _pixelFormat;
 	Graphics::Surface *_surface;
 	uint16 _width, _height;
 	uint16 _frameWidth, _frameHeight;
diff --git a/image/codecs/xan.h b/image/codecs/xan.h
index 8f9efcfb0c6..513fd748c1f 100644
--- a/image/codecs/xan.h
+++ b/image/codecs/xan.h
@@ -47,6 +47,7 @@ public:
 
 	const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream) override;
 	Graphics::PixelFormat getPixelFormat() const override { return _pixelFormat; }
+	bool setOutputPixelFormat(const Graphics::PixelFormat &format) override { _pixelFormat = format; return true; }
 
 private:
 	void decodeFrameType0(Common::SeekableReadStream &stream);
diff --git a/image/jpeg.h b/image/jpeg.h
index 9dcb46f899b..26b9a87a6c1 100644
--- a/image/jpeg.h
+++ b/image/jpeg.h
@@ -59,6 +59,7 @@ public:
 	// Codec API
 	const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream) override;
 	Graphics::PixelFormat getPixelFormat() const override;
+	bool setOutputPixelFormat(const Graphics::PixelFormat &format) override { _requestedPixelFormat = format; return true; }
 
 	// Special API for JPEG
 	enum ColorSpace {
@@ -95,13 +96,6 @@ public:
 	 */
 	void setOutputColorSpace(ColorSpace outSpace) { _colorSpace = outSpace; }
 
-	/**
-	 * Request the output pixel format. The JPEG decoder provides high performance
-	 * color conversion routines for some pixel formats. This setting allows to use
-	 * them and avoid costly subsequent color conversion.
-	 */
-	void setOutputPixelFormat(const Graphics::PixelFormat &format) { _requestedPixelFormat = format; }
-
 private:
 	Graphics::Surface _surface;
 	ColorSpace _colorSpace;


Commit: 8a4a5bdc55c00ffadb84e5d1d7f8bfd8d7502340
    https://github.com/scummvm/scummvm/commit/8a4a5bdc55c00ffadb84e5d1d7f8bfd8d7502340
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
VIDEO: Add setOutputPixelFormat() to the VideoDecoder interface

Changed paths:
    video/3do_decoder.cpp
    video/3do_decoder.h
    video/avi_decoder.cpp
    video/avi_decoder.h
    video/hnm_decoder.cpp
    video/hnm_decoder.h
    video/qt_decoder.cpp
    video/qt_decoder.h
    video/video_decoder.cpp
    video/video_decoder.h


diff --git a/video/3do_decoder.cpp b/video/3do_decoder.cpp
index 7cee1adf88c..8efe5786757 100644
--- a/video/3do_decoder.cpp
+++ b/video/3do_decoder.cpp
@@ -396,6 +396,10 @@ Graphics::PixelFormat ThreeDOMovieDecoder::StreamVideoTrack::getPixelFormat() co
 	return _codec->getPixelFormat();
 }
 
+bool ThreeDOMovieDecoder::StreamVideoTrack::setOutputPixelFormat(const Graphics::PixelFormat &format) {
+	return _codec->setOutputPixelFormat(format);
+}
+
 void ThreeDOMovieDecoder::StreamVideoTrack::decodeFrame(Common::SeekableReadStream *stream, uint32 videoTimeStamp) {
 	_surface = _codec->decodeFrame(*stream);
 	_curFrame++;
diff --git a/video/3do_decoder.h b/video/3do_decoder.h
index fa3034e3d17..e6936aff0b9 100644
--- a/video/3do_decoder.h
+++ b/video/3do_decoder.h
@@ -75,6 +75,7 @@ private:
 		uint16 getWidth() const override { return _width; }
 		uint16 getHeight() const override { return _height; }
 		Graphics::PixelFormat getPixelFormat() const override;
+		bool setOutputPixelFormat(const Graphics::PixelFormat &format);
 		int getCurFrame() const override { return _curFrame; }
 		int getFrameCount() const override { return _frameCount; }
 		void setNextFrameStartTime(uint32 nextFrameStartTime) { _nextFrameStartTime = nextFrameStartTime; }
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index 3a589c5fd55..872b5370414 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -985,6 +985,13 @@ Graphics::PixelFormat AVIDecoder::AVIVideoTrack::getPixelFormat() const {
 	return Graphics::PixelFormat();
 }
 
+bool AVIDecoder::AVIVideoTrack::setOutputPixelFormat(const Graphics::PixelFormat &format) {
+	if (_videoCodec)
+		return _videoCodec->setOutputPixelFormat(format);
+
+	return false;
+}
+
 void AVIDecoder::AVIVideoTrack::loadPaletteFromChunkRaw(Common::SeekableReadStream *chunk, int firstEntry, int numEntries) {
 	assert(chunk);
 	assert(firstEntry >= 0);
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index 0b6bdda7652..1e3f00693f2 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -212,6 +212,7 @@ protected:
 		uint16 getHeight() const { return _bmInfo.height; }
 		uint16 getBitCount() const { return _bmInfo.bitCount; }
 		Graphics::PixelFormat getPixelFormat() const;
+		bool setOutputPixelFormat(const Graphics::PixelFormat &format);
 		int getCurFrame() const { return _curFrame; }
 		int getFrameCount() const { return _frameCount; }
 		Common::String &getName() { return _vidsHeader.name; }
diff --git a/video/hnm_decoder.cpp b/video/hnm_decoder.cpp
index 35a2ac53ef5..ebb789da054 100644
--- a/video/hnm_decoder.cpp
+++ b/video/hnm_decoder.cpp
@@ -1064,6 +1064,10 @@ Graphics::PixelFormat HNMDecoder::HNM6VideoTrack::getPixelFormat() const {
 	return _decoder->getPixelFormat();
 }
 
+bool HNMDecoder::HNM6VideoTrack::setOutputPixelFormat(const Graphics::PixelFormat &format) {
+	return _decoder->setOutputPixelFormat(format);
+}
+
 void HNMDecoder::HNM6VideoTrack::decodeChunk(byte *data, uint32 size,
         uint16 chunkType, uint16 flags) {
 	if (chunkType == MKTAG16('I', 'X') ||
diff --git a/video/hnm_decoder.h b/video/hnm_decoder.h
index 29361fbf732..4bd7502e415 100644
--- a/video/hnm_decoder.h
+++ b/video/hnm_decoder.h
@@ -162,6 +162,7 @@ private:
 		uint16 getWidth() const override;
 		uint16 getHeight() const override;
 		Graphics::PixelFormat getPixelFormat() const override;
+		bool setOutputPixelFormat(const Graphics::PixelFormat &format) override;
 		const Graphics::Surface *decodeNextFrame() override { return _surface; }
 
 		virtual void newFrame(uint32 frameDelay) override;
diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp
index 94efc64064a..710fed87882 100644
--- a/video/qt_decoder.cpp
+++ b/video/qt_decoder.cpp
@@ -461,6 +461,13 @@ Graphics::PixelFormat QuickTimeDecoder::VideoTrackHandler::getPixelFormat() cons
 	return ((VideoSampleDesc *)_parent->sampleDescs[0])->_videoCodec->getPixelFormat();
 }
 
+bool QuickTimeDecoder::VideoTrackHandler::setOutputPixelFormat(const Graphics::PixelFormat &format) {
+	if (_forcedDitherPalette)
+		return false;
+
+	return ((VideoSampleDesc *)_parent->sampleDescs[0])->_videoCodec->setOutputPixelFormat(format);
+}
+
 int QuickTimeDecoder::VideoTrackHandler::getFrameCount() const {
 	return _parent->frameCount;
 }
diff --git a/video/qt_decoder.h b/video/qt_decoder.h
index b2364f27c6c..d6766ed8b9e 100644
--- a/video/qt_decoder.h
+++ b/video/qt_decoder.h
@@ -135,6 +135,7 @@ private:
 		uint16 getWidth() const;
 		uint16 getHeight() const;
 		Graphics::PixelFormat getPixelFormat() const;
+		bool setOutputPixelFormat(const Graphics::PixelFormat &format);
 		int getCurFrame() const { return _curFrame; }
 		int getFrameCount() const;
 		uint32 getNextFrameStartTime() const; // milliseconds
diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp
index 28ed9e1ef88..094359df7a9 100644
--- a/video/video_decoder.cpp
+++ b/video/video_decoder.cpp
@@ -48,6 +48,7 @@ VideoDecoder::VideoDecoder() {
 	_nextVideoTrack = 0;
 	_mainAudioTrack = 0;
 	_canSetDither = true;
+	_canSetDefaultFormat = true;
 
 	// Find the best format for output
 	_defaultHighColorFormat = g_system->getScreenFormat();
@@ -79,6 +80,7 @@ void VideoDecoder::close() {
 	_nextVideoTrack = 0;
 	_mainAudioTrack = 0;
 	_canSetDither = true;
+	_canSetDefaultFormat = true;
 }
 
 bool VideoDecoder::loadFile(const Common::Path &filename) {
@@ -208,6 +210,7 @@ Graphics::PixelFormat VideoDecoder::getPixelFormat() const {
 const Graphics::Surface *VideoDecoder::decodeNextFrame() {
 	_needsUpdate = false;
 	_canSetDither = false;
+	_canSetDefaultFormat = false;
 
 	readNextPacket();
 
@@ -547,6 +550,23 @@ bool VideoDecoder::setDitheringPalette(const byte *palette) {
 	return result;
 }
 
+bool VideoDecoder::setOutputPixelFormat(const Graphics::PixelFormat &format) {
+	// If a frame was already decoded, we can't set it now.
+	if (!_canSetDefaultFormat)
+		return false;
+
+	bool result = false;
+
+	for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) {
+		if ((*it)->getTrackType() == Track::kTrackTypeVideo) {
+			if (((VideoTrack *)*it)->setOutputPixelFormat(format))
+				result = true;
+		}
+	}
+
+	return result;
+}
+
 VideoDecoder::Track::Track() {
 	_paused = false;
 }
diff --git a/video/video_decoder.h b/video/video_decoder.h
index b9adb38772f..6d41dbaafd5 100644
--- a/video/video_decoder.h
+++ b/video/video_decoder.h
@@ -397,6 +397,17 @@ public:
 	 */
 	bool setDitheringPalette(const byte *palette);
 
+	/**
+	 * Set the default high color format for videos that convert from YUV.
+	 *
+	 * This should be called after loadStream(), but before a decodeNextFrame()
+	 * call. This is enforced.
+	 *
+	 * @param format The preferred output pixel format
+	 * @return true on success, false otherwise
+	 */
+	bool setOutputPixelFormat(const Graphics::PixelFormat &format);
+
 	/////////////////////////////////////////
 	// Audio Control
 	/////////////////////////////////////////
@@ -577,6 +588,11 @@ protected:
 		 */
 		virtual Graphics::PixelFormat getPixelFormat() const = 0;
 
+		/**
+		 * Set the default high color format for videos that convert from YUV.
+		 */
+		virtual bool setOutputPixelFormat(const Graphics::PixelFormat &format) { return false; }
+
 		/**
 		 * Get the current frame of this track
 		 *
@@ -954,8 +970,9 @@ private:
 	mutable bool _dirtyPalette;
 	const byte *_palette;
 
-	// Enforcement of not being able to set dither
+	// Enforcement of not being able to set dither or set the default format
 	bool _canSetDither;
+	bool _canSetDefaultFormat;
 
 	// Default PixelFormat settings
 	Graphics::PixelFormat _defaultHighColorFormat;


Commit: a5603ac1f4a26296adf4b4a162ef72378a273230
    https://github.com/scummvm/scummvm/commit/a5603ac1f4a26296adf4b4a162ef72378a273230
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
TESTBED: Pick the best pixel format in the video player

Changed paths:
    engines/testbed/video.cpp


diff --git a/engines/testbed/video.cpp b/engines/testbed/video.cpp
index f0c43447edd..da349e051c1 100644
--- a/engines/testbed/video.cpp
+++ b/engines/testbed/video.cpp
@@ -52,9 +52,6 @@ Common::Error Videotests::videoTest(const Common::FSNode &node) {
 }
 
 Common::Error Videotests::videoTest(Common::SeekableReadStream *stream, const Common::String &name) {
-	Graphics::PixelFormat pixelformat = Graphics::PixelFormat::createFormatCLUT8();
-	initGraphics(640, 480, &pixelformat);
-
 	Video::VideoDecoder *video = new Video::QuickTimeDecoder();
 	if (!video->loadStream(stream)) {
 		warning("Cannot open video %s", name.c_str());
@@ -63,12 +60,28 @@ Common::Error Videotests::videoTest(Common::SeekableReadStream *stream, const Co
 		return Common::kReadingFailed;
 	}
 
-	const byte *palette = video->getPalette();
-
-	if (!palette) {
-		palette = Video::quickTimeDefaultPalette256;
+	Common::List<Graphics::PixelFormat> supportedFormatsList = g_system->getSupportedFormats();
+	Graphics::PixelFormat pixelformat = supportedFormatsList.front();
+	warning("Best pixel format: %s", pixelformat.toString().c_str());
+	warning("Video pixel format: %s", video->getPixelFormat().toString().c_str());
+
+	if (video->getPixelFormat().isCLUT8()) {
+		pixelformat = Graphics::PixelFormat::createFormatCLUT8();
+	} else {
+		if (pixelformat.isCLUT8() && video->setDitheringPalette(Video::quickTimeDefaultPalette256)) {
+			pixelformat = Graphics::PixelFormat::createFormatCLUT8();
+		} else {
+			pixelformat = supportedFormatsList.front();
+
+			if (!video->setOutputPixelFormat(pixelformat)) {
+				// TODO: Search for the pixel format in supportedFormatsList?
+				pixelformat = video->getPixelFormat();
+			}
+		}
 	}
-	g_system->getPaletteManager()->setPalette(palette, 0, 256);
+
+	warning("Actual pixel format: %s", pixelformat.toString().c_str());
+	initGraphics(640, 480, &pixelformat);
 
 	video->start();
 
@@ -77,20 +90,31 @@ Common::Error Videotests::videoTest(Common::SeekableReadStream *stream, const Co
 			uint32 pos = video->getTime();
 			debug(5, "video time: %d", pos);
 
+			if (pixelformat.isCLUT8() && video->hasDirtyPalette()) {
+				g_system->getPaletteManager()->setPalette(video->getPalette(), 0, 256);
+			}
+
 			const Graphics::Surface *frame = video->decodeNextFrame();
 			if (frame) {
-				Graphics::Surface *conv = frame->convertTo(pixelformat, 0, 0, palette, 256);
+				const Graphics::Surface *surf = frame;
+				Graphics::Surface *conv = nullptr;
+
+				if (frame->format != pixelformat) {
+					surf = conv = frame->convertTo(pixelformat, video->getPalette());
+				}
 
 				int x = 0, y = 0;
 
-				if (conv->w < g_system->getWidth() && conv->h < g_system->getHeight()) {
-					x = (g_system->getWidth() - conv->w) >> 1;
-					y = (g_system->getHeight() - conv->h) >> 1;
+				if (surf->w < g_system->getWidth() && surf->h < g_system->getHeight()) {
+					x = (g_system->getWidth() - surf->w) >> 1;
+					y = (g_system->getHeight() - surf->h) >> 1;
 				}
-				g_system->copyRectToScreen(conv->getPixels(), conv->pitch, x, y, MIN<uint16>(conv->w, 640), MIN<uint16>(conv->h, 480));
+				g_system->copyRectToScreen(surf->getPixels(), surf->pitch, x, y, MIN<uint16>(surf->w, 640), MIN<uint16>(surf->h, 480));
 
-				conv->free();
-				delete conv;
+				if (conv) {
+					conv->free();
+					delete conv;
+				}
 			}
 
 			Common::Event event;


Commit: d72fee204cd787b63076b4479ed2b0b6bf56d6e9
    https://github.com/scummvm/scummvm/commit/d72fee204cd787b63076b4479ed2b0b6bf56d6e9
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
VIDEO: Implement setOutputPixelFormat() for MPEGPSDecoder

Changed paths:
    engines/grim/movie/mpeg.cpp
    video/mpegps_decoder.cpp
    video/mpegps_decoder.h


diff --git a/engines/grim/movie/mpeg.cpp b/engines/grim/movie/mpeg.cpp
index 9a082282106..e6e3c05b806 100644
--- a/engines/grim/movie/mpeg.cpp
+++ b/engines/grim/movie/mpeg.cpp
@@ -45,8 +45,8 @@ bool MpegPlayer::loadFile(const Common::String &filename) {
 	if (!stream)
 		return false;
 
-	_videoDecoder->setDefaultHighColorFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 8, 16, 24, 0));
 	_videoDecoder->loadStream(stream);
+	_videoDecoder->setOutputPixelFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 8, 16, 24, 0));
 	_videoDecoder->start();
 
 	return true;
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index b244594fe84..43219d6befb 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -205,7 +205,7 @@ bool MPEGPSDecoder::addFirstVideoTrack() {
 	// Video stream
 	// Can be MPEG-1/2 or MPEG-4/h.264. We'll assume the former and
 	// I hope we never need the latter.
-	MPEGVideoTrack *track = new MPEGVideoTrack(packet, getDefaultHighColorFormat());
+	MPEGVideoTrack *track = new MPEGVideoTrack(packet);
 	addTrack(track);
 	_streamMap[startCode] = track;
 
@@ -584,14 +584,14 @@ void MPEGPSDecoder::MPEGPSDemuxer::parseProgramStreamMap(int length) {
 // Video track
 // --------------------------------------------------------------------------
 
-MPEGPSDecoder::MPEGVideoTrack::MPEGVideoTrack(Common::SeekableReadStream *firstPacket, const Graphics::PixelFormat &format) {
+MPEGPSDecoder::MPEGVideoTrack::MPEGVideoTrack(Common::SeekableReadStream *firstPacket) {
 	_surface = 0;
 	_endOfTrack = false;
 	_curFrame = -1;
 	_framePts = 0xFFFFFFFF;
 	_nextFrameStartTime = Audio::Timestamp(0, 27000000); // 27 MHz timer
 
-	findDimensions(firstPacket, format);
+	findDimensions(firstPacket);
 
 #ifdef USE_MPEG2
 	_mpegDecoder = new Image::MPEGDecoder();
@@ -610,18 +610,20 @@ MPEGPSDecoder::MPEGVideoTrack::~MPEGVideoTrack() {
 }
 
 uint16 MPEGPSDecoder::MPEGVideoTrack::getWidth() const {
-	return _surface ? _surface->w : 0;
+	return _width;
 }
 
 uint16 MPEGPSDecoder::MPEGVideoTrack::getHeight() const {
-	return _surface ? _surface->h : 0;
+	return _height;
 }
 
 Graphics::PixelFormat MPEGPSDecoder::MPEGVideoTrack::getPixelFormat() const {
-	if (!_surface)
-		return Graphics::PixelFormat();
+	return _pixelFormat;
+}
 
-	return _surface->format;
+bool MPEGPSDecoder::MPEGVideoTrack::setOutputPixelFormat(const Graphics::PixelFormat &format) {
+	_pixelFormat = format;
+	return true;
 }
 
 const Graphics::Surface *MPEGPSDecoder::MPEGVideoTrack::decodeNextFrame() {
@@ -630,6 +632,11 @@ const Graphics::Surface *MPEGPSDecoder::MPEGVideoTrack::decodeNextFrame() {
 
 bool MPEGPSDecoder::MPEGVideoTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) {
 #ifdef USE_MPEG2
+	if (!_surface) {
+		_surface = new Graphics::Surface();
+		_surface->create(_width, _height, _pixelFormat);
+	}
+
 	if (pts != 0xFFFFFFFF) {
 		_framePts = pts;
 	}
@@ -663,7 +670,7 @@ bool MPEGPSDecoder::MPEGVideoTrack::sendPacket(Common::SeekableReadStream *packe
 #endif
 }
 
-void MPEGPSDecoder::MPEGVideoTrack::findDimensions(Common::SeekableReadStream *firstPacket, const Graphics::PixelFormat &format) {
+void MPEGPSDecoder::MPEGVideoTrack::findDimensions(Common::SeekableReadStream *firstPacket) {
 	// First, check for the picture start code
 	if (firstPacket->readUint32BE() != 0x1B3)
 		error("Failed to detect MPEG sequence start");
@@ -671,15 +678,15 @@ void MPEGPSDecoder::MPEGVideoTrack::findDimensions(Common::SeekableReadStream *f
 	// This is part of the bitstream, but there's really no purpose
 	// to use Common::BitStream just for this: 12 bits width, 12 bits
 	// height
-	uint16 width = firstPacket->readByte() << 4;
-	uint16 height = firstPacket->readByte();
-	width |= (height & 0xF0) >> 4;
-	height = ((height & 0x0F) << 8) | firstPacket->readByte();
-
-	debug(0, "MPEG dimensions: %dx%d", width, height);
-
-	_surface = new Graphics::Surface();
-	_surface->create(width, height, format);
+	_width = firstPacket->readByte() << 4;
+	_height = firstPacket->readByte();
+	_width |= (_height & 0xF0) >> 4;
+	_height = ((_height & 0x0F) << 8) | firstPacket->readByte();
+	_pixelFormat = g_system->getScreenFormat();
+	if (_pixelFormat.bytesPerPixel == 1)
+		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
+
+	debug(0, "MPEG dimensions: %dx%d", _width, _height);
 
 	firstPacket->seek(0);
 }
diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h
index 3863a1e29b5..12c1a20529d 100644
--- a/video/mpegps_decoder.h
+++ b/video/mpegps_decoder.h
@@ -113,13 +113,14 @@ private:
 	// An MPEG 1/2 video track
 	class MPEGVideoTrack : public VideoTrack, public MPEGStream {
 	public:
-		MPEGVideoTrack(Common::SeekableReadStream *firstPacket, const Graphics::PixelFormat &format);
+		MPEGVideoTrack(Common::SeekableReadStream *firstPacket);
 		~MPEGVideoTrack();
 
 		bool endOfTrack() const { return _endOfTrack; }
 		uint16 getWidth() const;
 		uint16 getHeight() const;
 		Graphics::PixelFormat getPixelFormat() const;
+		bool setOutputPixelFormat(const Graphics::PixelFormat &format);
 		int getCurFrame() const { return _curFrame; }
 		uint32 getNextFrameStartTime() const { return _nextFrameStartTime.msecs(); }
 		const Graphics::Surface *decodeNextFrame();
@@ -136,7 +137,11 @@ private:
 		Audio::Timestamp _nextFrameStartTime;
 		Graphics::Surface *_surface;
 
-		void findDimensions(Common::SeekableReadStream *firstPacket, const Graphics::PixelFormat &format);
+		uint16 _width;
+		uint16 _height;
+		Graphics::PixelFormat _pixelFormat;
+
+		void findDimensions(Common::SeekableReadStream *firstPacket);
 
 #ifdef USE_MPEG2
 		Image::MPEGDecoder *_mpegDecoder;


Commit: adef12d993e9b92f4dbf97b12355063619173fcb
    https://github.com/scummvm/scummvm/commit/adef12d993e9b92f4dbf97b12355063619173fcb
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
VIDEO: Implement setOutputPixelFormat() for BinkDecoder

Changed paths:
    engines/grim/movie/bink.cpp
    engines/icb/movie_pc.cpp
    engines/icb/options_manager_pc.cpp
    engines/myst3/inventory.cpp
    engines/myst3/menu.cpp
    engines/myst3/movie.cpp
    engines/myst3/puzzles.cpp
    engines/myst3/subtitles.cpp
    engines/scumm/he/animation_he.cpp
    engines/stark/ui/world/fmvscreen.cpp
    engines/stark/visual/smacker.cpp
    video/bink_decoder.cpp
    video/bink_decoder.h


diff --git a/engines/grim/movie/bink.cpp b/engines/grim/movie/bink.cpp
index 9e42b2b80e5..9279d8a1dec 100644
--- a/engines/grim/movie/bink.cpp
+++ b/engines/grim/movie/bink.cpp
@@ -44,7 +44,6 @@ MoviePlayer *CreateBinkPlayer(bool demo) {
 
 BinkPlayer::BinkPlayer(bool demo) : MoviePlayer(), _demo(demo) {
 	_videoDecoder = new Video::BinkDecoder();
-	_videoDecoder->setDefaultHighColorFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 8, 16, 24, 0));
 	_subtitleIndex = _subtitles.begin();
 }
 
@@ -205,7 +204,10 @@ bool BinkPlayer::loadFile(const Common::String &filename) {
 
 	Common::SeekableReadStream *bink = nullptr;
 	bink = new Common::SeekableSubReadStream(stream, startBinkPos, stream->size(), DisposeAfterUse::YES);
-	return _videoDecoder->loadStream(bink);
+	if (!_videoDecoder->loadStream(bink))
+		return false;
+	_videoDecoder->setOutputPixelFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 8, 16, 24, 0));
+	return true;
 }
 
 } // end of namespace Grim
diff --git a/engines/icb/movie_pc.cpp b/engines/icb/movie_pc.cpp
index 0dabe6e06d5..884de097fb0 100644
--- a/engines/icb/movie_pc.cpp
+++ b/engines/icb/movie_pc.cpp
@@ -65,7 +65,6 @@ bool MovieManager::registerMovie(const char *fileName, bool8 fade, bool8 loop) {
 		g_theMusicManager->StopMusic();
 
 	_binkDecoder = new Video::BinkDecoder();
-	_binkDecoder->setDefaultHighColorFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 24));
 
 	Common::SeekableReadStream *stream = openDiskFileForBinaryStreamRead(fileName);
 	if (!stream) {
@@ -74,6 +73,9 @@ bool MovieManager::registerMovie(const char *fileName, bool8 fade, bool8 loop) {
 	if (!_binkDecoder->loadStream(stream)) {
 		return false;
 	}
+
+	_binkDecoder->setOutputPixelFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 24));
+
 	if (_binkDecoder->getWidth() != SCREEN_WIDTH) {
 		_x = (SCREEN_WIDTH / 2) - (_binkDecoder->getWidth() / 2);
 	}
diff --git a/engines/icb/options_manager_pc.cpp b/engines/icb/options_manager_pc.cpp
index 218f37725d7..8dd845e6c76 100644
--- a/engines/icb/options_manager_pc.cpp
+++ b/engines/icb/options_manager_pc.cpp
@@ -6182,8 +6182,6 @@ void OptionsManager::DrawSlideShow() {
 
 		// This slide is bink compressed
 		Video::BinkDecoder *binkDecoder = new Video::BinkDecoder();
-		binkDecoder->setDefaultHighColorFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 24));
-
 		Common::MemoryReadStream *stream = new Common::MemoryReadStream((byte *)slideptr, slideLen);
 		if (!stream) {
 			Fatal_error("Failed open bink file");
@@ -6192,6 +6190,8 @@ void OptionsManager::DrawSlideShow() {
 			Fatal_error("Failed open bink file");
 		}
 
+		binkDecoder->setOutputPixelFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 24));
+
 		// Verify image dimensions
 		if (binkDecoder->getWidth() > SCREEN_WIDTH || binkDecoder->getHeight() > SCREEN_DEPTH)
 			Fatal_error("Slide image is too large to fit screen!");
diff --git a/engines/myst3/inventory.cpp b/engines/myst3/inventory.cpp
index 15933c6cea5..51e008bf0ef 100644
--- a/engines/myst3/inventory.cpp
+++ b/engines/myst3/inventory.cpp
@@ -338,8 +338,8 @@ DragItem::DragItem(Myst3Engine *vm, uint id):
 
 	// Load the movie
 	_movieStream = movieDesc.getData();
-	_bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
 	_bink.loadStream(_movieStream);
+	_bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
 	_bink.start();
 
 	const Graphics::Surface *frame = _bink.decodeNextFrame();
diff --git a/engines/myst3/menu.cpp b/engines/myst3/menu.cpp
index 958cc816b38..4817142ade7 100644
--- a/engines/myst3/menu.cpp
+++ b/engines/myst3/menu.cpp
@@ -57,8 +57,8 @@ Dialog::Dialog(Myst3Engine *vm, uint id):
 
 	// Load the movie
 	Common::SeekableReadStream *movieStream = movieDesc.getData();
-	_bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
 	_bink.loadStream(movieStream);
+	_bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
 	_bink.start();
 
 	const Graphics::Surface *frame = _bink.decodeNextFrame();
diff --git a/engines/myst3/movie.cpp b/engines/myst3/movie.cpp
index 78d6d8af6a3..5be07da80d8 100644
--- a/engines/myst3/movie.cpp
+++ b/engines/myst3/movie.cpp
@@ -73,9 +73,9 @@ Movie::Movie(Myst3Engine *vm, uint16 id) :
 	loadPosition(binkDesc.getVideoData());
 
 	Common::SeekableReadStream *binkStream = binkDesc.getData();
-	_bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
 	_bink.setSoundType(Audio::Mixer::kSFXSoundType);
 	_bink.loadStream(binkStream);
+	_bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
 
 	if (binkDesc.getType() == Archive::kMultitrackMovie || binkDesc.getType() == Archive::kDialogMovie) {
 		uint language = ConfMan.getInt("audio_language");
diff --git a/engines/myst3/puzzles.cpp b/engines/myst3/puzzles.cpp
index 05485522328..29e1ed18cfb 100644
--- a/engines/myst3/puzzles.cpp
+++ b/engines/myst3/puzzles.cpp
@@ -1527,8 +1527,8 @@ void Puzzles::projectorLoadBitmap(uint16 bitmap) {
 	// Rebuild the complete background image from the frames of the bink movie
 	Common::SeekableReadStream *movieStream = movieDesc.getData();
 	Video::BinkDecoder bink;
-	bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
 	bink.loadStream(movieStream);
+	bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
 	bink.start();
 
 	for (uint i = 0; i < 1024; i += 256) {
@@ -1554,8 +1554,8 @@ void Puzzles::projectorAddSpotItem(uint16 bitmap, uint16 x, uint16 y) {
 	// Rebuild the complete background image from the frames of the bink movie
 	Common::SeekableReadStream *movieStream = movieDesc.getData();
 	Video::BinkDecoder bink;
-	bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
 	bink.loadStream(movieStream);
+	bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
 	bink.start();
 
 	const Graphics::Surface *frame = bink.decodeNextFrame();
diff --git a/engines/myst3/subtitles.cpp b/engines/myst3/subtitles.cpp
index ae41f93a109..75b210b81e8 100644
--- a/engines/myst3/subtitles.cpp
+++ b/engines/myst3/subtitles.cpp
@@ -360,8 +360,8 @@ bool MovieSubtitles::loadSubtitles(int32 id) {
 
 	// Load the movie
 	Common::SeekableReadStream *movieStream = movie.getData();
-	_bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
 	_bink.loadStream(movieStream);
+	_bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
 	_bink.start();
 
 	return true;
diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp
index 59e9996fee9..a60796544cc 100644
--- a/engines/scumm/he/animation_he.cpp
+++ b/engines/scumm/he/animation_he.cpp
@@ -65,14 +65,14 @@ int MoviePlayer::load(const Common::String &filename, int flags, int image) {
 	if (_video->isVideoLoaded())
 		_video->close();
 
-	// Ensure that Bink will use our PixelFormat
-	_video->setDefaultHighColorFormat(g_system->getScreenFormat());
-
 	if (!_video->loadFile(filename)) {
 		warning("Failed to load video file %s", filename.c_str());
 		return -1;
 	}
 
+	// Ensure that Bink will use our PixelFormat
+	_video->setOutputPixelFormat(g_system->getScreenFormat());
+
 	_video->start();
 
 	debug(1, "Playing video %s", filename.c_str());
diff --git a/engines/stark/ui/world/fmvscreen.cpp b/engines/stark/ui/world/fmvscreen.cpp
index fc1a97ea210..fa4bd7fbf8f 100644
--- a/engines/stark/ui/world/fmvscreen.cpp
+++ b/engines/stark/ui/world/fmvscreen.cpp
@@ -41,7 +41,6 @@ FMVScreen::FMVScreen(Gfx::Driver *gfx, Cursor *cursor) :
 	_bitmap->setSamplingFilter(StarkSettings->getImageSamplingFilter());
 
 	_decoder = new Video::BinkDecoder();
-	_decoder->setDefaultHighColorFormat(_bitmap->getBestPixelFormat());
 	_decoder->setSoundType(Audio::Mixer::kSFXSoundType);
 
 	_surfaceRenderer = _gfx->createSurfaceRenderer();
@@ -82,6 +81,7 @@ void FMVScreen::play(const Common::String &name) {
 	if (!_decoder->isVideoLoaded()) {
 		error("Could not open %s", name.c_str());
 	}
+	_decoder->setOutputPixelFormat(_bitmap->getBestPixelFormat());
 	_decoder->start();
 }
 
diff --git a/engines/stark/visual/smacker.cpp b/engines/stark/visual/smacker.cpp
index 72db7c8f5a5..06ca3607421 100644
--- a/engines/stark/visual/smacker.cpp
+++ b/engines/stark/visual/smacker.cpp
@@ -72,9 +72,9 @@ void VisualSmacker::loadBink(Common::SeekableReadStream *stream) {
 
 	_decoder = new Video::BinkDecoder();
 	_decoder->setSoundType(Audio::Mixer::kSFXSoundType);
-	// We need a format with alpha transparency, so we can't use _bitmap->getBestPixelFormat() here.
-	_decoder->setDefaultHighColorFormat(Gfx::Driver::getRGBAPixelFormat());
 	_decoder->loadStream(stream);
+	// We need a format with alpha transparency, so we can't use _bitmap->getBestPixelFormat() here.
+	_decoder->setOutputPixelFormat(Gfx::Driver::getRGBAPixelFormat());
 
 	init();
 }
diff --git a/video/bink_decoder.cpp b/video/bink_decoder.cpp
index 30de3d478dc..0c371d6447c 100644
--- a/video/bink_decoder.cpp
+++ b/video/bink_decoder.cpp
@@ -102,7 +102,7 @@ bool BinkDecoder::loadStream(Common::SeekableReadStream *stream) {
 	uint32 videoFlags = _bink->readUint32LE();
 
 	// BIKh and BIKi swap the chroma planes
-	addTrack(new BinkVideoTrack(width, height, getDefaultHighColorFormat(), frameCount,
+	addTrack(new BinkVideoTrack(width, height, frameCount,
 			Common::Rational(frameRateNum, frameRateDen), (id == kBIKhID || id == kBIKiID), videoFlags & kVideoFlagAlpha, id));
 
 	uint32 audioTrackCount = _bink->readUint32LE();
@@ -242,8 +242,8 @@ BinkDecoder::AudioInfo::~AudioInfo() {
 	delete dct;
 }
 
-BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, const Graphics::PixelFormat &format, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id) :
-		_frameCount(frameCount), _frameRate(frameRate), _swapPlanes(swapPlanes), _hasAlpha(hasAlpha), _id(id) {
+BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id) :
+		_frameCount(frameCount), _frameRate(frameRate), _swapPlanes(swapPlanes), _hasAlpha(hasAlpha), _id(id), _surface(nullptr) {
 	_curFrame = -1;
 
 	for (int i = 0; i < 16; i++)
@@ -269,8 +269,8 @@ BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, const G
 	}
 
 	// Make the surface even-sized:
-	_surfaceHeight = height;
-	_surfaceWidth = width;
+	_surfaceHeight = _height = height;
+	_surfaceWidth = _width = width;
 
 	if (height & 1) {
 		_surfaceHeight++;
@@ -279,12 +279,11 @@ BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, const G
 		_surfaceWidth++;
 	}
 
-	_surface.create(_surfaceWidth, _surfaceHeight, format);
-	// Since we over-allocate to make surfaces even-sized
-	// we need to set the actual VIDEO size back into the
-	// surface.
-	_surface.h = height;
-	_surface.w = width;
+	_pixelFormat = g_system->getScreenFormat();
+
+	// Default to a 32bpp format, if in 8bpp mode
+	if (_pixelFormat.bytesPerPixel == 1)
+		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
 
 	// Compute the video dimensions in blocks
 	_yBlockWidth   = (width  +  7) >> 3;
@@ -323,7 +322,11 @@ BinkDecoder::BinkVideoTrack::~BinkVideoTrack() {
 		_huffman[i] = 0;
 	}
 
-	_surface.free();
+	if (_surface) {
+		_surface->free();
+		delete _surface;
+		_surface = nullptr;
+	}
 }
 
 Common::Rational BinkDecoder::getFrameRate() {
@@ -446,6 +449,16 @@ bool BinkDecoder::BinkVideoTrack::rewind() {
 void BinkDecoder::BinkVideoTrack::decodePacket(VideoFrame &frame) {
 	assert(frame.bits);
 
+	if (!_surface) {
+		_surface = new Graphics::Surface();
+		_surface->create(_surfaceWidth, _surfaceHeight, _pixelFormat);
+		// Since we over-allocate to make surfaces even-sized
+		// we need to set the actual VIDEO size back into the
+		// surface.
+		_surface->h = _height;
+		_surface->w = _width;
+	}
+
 	if (_hasAlpha) {
 		if (_id == kBIKiID)
 			frame.bits->skip(32);
@@ -470,11 +483,11 @@ void BinkDecoder::BinkVideoTrack::decodePacket(VideoFrame &frame) {
 	// to allow for odd-sized videos.
 	if (_hasAlpha) {
 		assert(_curPlanes[0] && _curPlanes[1] && _curPlanes[2] && _curPlanes[3]);
-		YUVToRGBMan.convert420Alpha(&_surface, Graphics::YUVToRGBManager::kScaleITU, _curPlanes[0], _curPlanes[1], _curPlanes[2], _curPlanes[3],
+		YUVToRGBMan.convert420Alpha(_surface, Graphics::YUVToRGBManager::kScaleITU, _curPlanes[0], _curPlanes[1], _curPlanes[2], _curPlanes[3],
 				_surfaceWidth, _surfaceHeight, _yBlockWidth * 8, _uvBlockWidth * 8);
 	} else {
 		assert(_curPlanes[0] && _curPlanes[1] && _curPlanes[2]);
-		YUVToRGBMan.convert420(&_surface, Graphics::YUVToRGBManager::kScaleITU, _curPlanes[0], _curPlanes[1], _curPlanes[2],
+		YUVToRGBMan.convert420(_surface, Graphics::YUVToRGBManager::kScaleITU, _curPlanes[0], _curPlanes[1], _curPlanes[2],
 				_surfaceWidth, _surfaceHeight, _yBlockWidth * 8, _uvBlockWidth * 8);
 	}
 
@@ -675,8 +688,8 @@ void BinkDecoder::BinkVideoTrack::mergeHuffmanSymbols(VideoFrame &video, byte *d
 }
 
 void BinkDecoder::BinkVideoTrack::initBundles() {
-	uint32 bw     = (_surface.w + 7) >> 3;
-	uint32 bh     = (_surface.h + 7) >> 3;
+	uint32 bw     = (_width + 7) >> 3;
+	uint32 bh     = (_height + 7) >> 3;
 	uint32 blocks = bw * bh;
 
 	for (int i = 0; i < kSourceMAX; i++) {
@@ -684,8 +697,8 @@ void BinkDecoder::BinkVideoTrack::initBundles() {
 		_bundles[i].dataEnd = _bundles[i].data + blocks * 64;
 	}
 
-	uint32 cbw[2] = { (uint32)((_surface.w + 7) >> 3), (uint32)((_surface.w  + 15) >> 4) };
-	uint32 cw [2] = { (uint32)( _surface.w          ), (uint32)( _surface.w        >> 1) };
+	uint32 cbw[2] = { (uint32)((_width + 7) >> 3), (uint32)((_width  + 15) >> 4) };
+	uint32 cw [2] = { (uint32)( _width          ), (uint32)( _width        >> 1) };
 
 	// Calculate the lengths of an element count in bits
 	for (int i = 0; i < 2; i++) {
diff --git a/video/bink_decoder.h b/video/bink_decoder.h
index e21d6777a7f..e71c9d2fff1 100644
--- a/video/bink_decoder.h
+++ b/video/bink_decoder.h
@@ -147,15 +147,16 @@ private:
 
 	class BinkVideoTrack : public FixedRateVideoTrack {
 	public:
-		BinkVideoTrack(uint32 width, uint32 height, const Graphics::PixelFormat &format, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id);
+		BinkVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id);
 		~BinkVideoTrack();
 
-		uint16 getWidth() const override { return _surface.w; }
-		uint16 getHeight() const  override{ return _surface.h; }
-		Graphics::PixelFormat getPixelFormat() const override { return _surface.format; }
+		uint16 getWidth() const override { return _width; }
+		uint16 getHeight() const  override{ return _height; }
+		Graphics::PixelFormat getPixelFormat() const override { return _pixelFormat; }
+		bool setOutputPixelFormat(const Graphics::PixelFormat &format) { _pixelFormat = format; return true; }
 		int getCurFrame() const override { return _curFrame; }
 		int getFrameCount() const override { return _frameCount; }
-		const Graphics::Surface *decodeNextFrame() override { return &_surface; }
+		const Graphics::Surface *decodeNextFrame() override { return _surface; }
 		bool isSeekable() const  override{ return true; }
 		bool seek(const Audio::Timestamp &time) override { return true; }
 		bool rewind() override;
@@ -243,7 +244,10 @@ private:
 		int _curFrame;
 		int _frameCount;
 
-		Graphics::Surface _surface;
+		Graphics::Surface *_surface;
+		Graphics::PixelFormat _pixelFormat;
+		uint16 _width;
+		uint16 _height;
 		int _surfaceWidth; ///< The actual surface width
 		int _surfaceHeight; ///< The actual surface height
 


Commit: 475354cb4c6dde54aff01dbe358d417db99d6617
    https://github.com/scummvm/scummvm/commit/475354cb4c6dde54aff01dbe358d417db99d6617
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
VIDEO: Implement setOutputPixelFormat() for PSXStreamDecoder

Changed paths:
    video/psx_decoder.cpp
    video/psx_decoder.h


diff --git a/video/psx_decoder.cpp b/video/psx_decoder.cpp
index 4658f0821d8..8a1b4355b1a 100644
--- a/video/psx_decoder.cpp
+++ b/video/psx_decoder.cpp
@@ -340,17 +340,21 @@ Audio::AudioStream *PSXStreamDecoder::PSXAudioTrack::getAudioStream() const {
 }
 
 
-PSXStreamDecoder::PSXVideoTrack::PSXVideoTrack(Common::SeekableReadStream *firstSector, CDSpeed speed, int frameCount) : _nextFrameStartTime(0, speed), _frameCount(frameCount) {
+PSXStreamDecoder::PSXVideoTrack::PSXVideoTrack(Common::SeekableReadStream *firstSector, CDSpeed speed, int frameCount) : _nextFrameStartTime(0, speed), _frameCount(frameCount), _surface(nullptr) {
 	assert(firstSector);
 
 	firstSector->seek(40);
-	uint16 width = firstSector->readUint16LE();
-	uint16 height = firstSector->readUint16LE();
-	_surface = new Graphics::Surface();
-	_surface->create(width, height, g_system->getScreenFormat());
+	_width = firstSector->readUint16LE();
+	_height = firstSector->readUint16LE();
 
-	_macroBlocksW = (width + 15) / 16;
-	_macroBlocksH = (height + 15) / 16;
+	_pixelFormat = g_system->getScreenFormat();
+
+	// Default to a 32bpp format, if in 8bpp mode
+	if (_pixelFormat.bytesPerPixel == 1)
+		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
+
+	_macroBlocksW = (_width + 15) / 16;
+	_macroBlocksH = (_height + 15) / 16;
 	_yBuffer = new byte[_macroBlocksW * _macroBlocksH * 16 * 16];
 	_cbBuffer = new byte[_macroBlocksW * _macroBlocksH * 8 * 8];
 	_crBuffer = new byte[_macroBlocksW * _macroBlocksH * 8 * 8];
@@ -363,8 +367,10 @@ PSXStreamDecoder::PSXVideoTrack::PSXVideoTrack(Common::SeekableReadStream *first
 }
 
 PSXStreamDecoder::PSXVideoTrack::~PSXVideoTrack() {
-	_surface->free();
-	delete _surface;
+	if (_surface) {
+		_surface->free();
+		delete _surface;
+	}
 
 	delete[] _yBuffer;
 	delete[] _cbBuffer;
@@ -383,6 +389,11 @@ const Graphics::Surface *PSXStreamDecoder::PSXVideoTrack::decodeNextFrame() {
 }
 
 void PSXStreamDecoder::PSXVideoTrack::decodeFrame(Common::BitStreamMemoryStream *frame, uint sectorCount) {
+	if (!_surface) {
+		_surface = new Graphics::Surface();
+		_surface->create(_width, _height, _pixelFormat);
+	}
+
 	// A frame is essentially an MPEG-1 intra frame
 
 	Common::BitStreamMemory16LEMSB bits(frame);
diff --git a/video/psx_decoder.h b/video/psx_decoder.h
index a9af522e17b..f4914f3c913 100644
--- a/video/psx_decoder.h
+++ b/video/psx_decoder.h
@@ -80,9 +80,10 @@ private:
 		PSXVideoTrack(Common::SeekableReadStream *firstSector, CDSpeed speed, int frameCount);
 		~PSXVideoTrack();
 
-		uint16 getWidth() const { return _surface->w; }
-		uint16 getHeight() const { return _surface->h; }
-		Graphics::PixelFormat getPixelFormat() const { return _surface->format; }
+		uint16 getWidth() const { return _width; }
+		uint16 getHeight() const { return _height; }
+		Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
+		bool setOutputPixelFormat(const Graphics::PixelFormat &format) { _pixelFormat = format; return true; }
 		bool endOfTrack() const { return _endOfTrack; }
 		int getCurFrame() const { return _curFrame; }
 		int getFrameCount() const { return _frameCount; }
@@ -94,6 +95,9 @@ private:
 
 	private:
 		Graphics::Surface *_surface;
+		Graphics::PixelFormat _pixelFormat;
+		uint16 _width;
+		uint16 _height;
 		uint32 _frameCount;
 		Audio::Timestamp _nextFrameStartTime;
 		bool _endOfTrack;


Commit: 70a6159af5ae959bc134b55c23859e6747340bc0
    https://github.com/scummvm/scummvm/commit/70a6159af5ae959bc134b55c23859e6747340bc0
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
VIDEO: Implement setOutputPixelFormat() for TheoraDecoder

Changed paths:
    video/theora_decoder.cpp
    video/theora_decoder.h


diff --git a/video/theora_decoder.cpp b/video/theora_decoder.cpp
index b759ec4bf66..dca4b82a450 100644
--- a/video/theora_decoder.cpp
+++ b/video/theora_decoder.cpp
@@ -167,7 +167,7 @@ bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) {
 
 	// And now we have it all. Initialize decoders next
 	if (_hasVideo) {
-		_videoTrack = new TheoraVideoTrack(getDefaultHighColorFormat(), theoraInfo, theoraSetup);
+		_videoTrack = new TheoraVideoTrack(theoraInfo, theoraSetup);
 		addTrack(_videoTrack);
 	}
 
@@ -254,7 +254,7 @@ Common::Rational TheoraDecoder::getFrameRate() const {
 	return Common::Rational();
 }
 
-TheoraDecoder::TheoraVideoTrack::TheoraVideoTrack(const Graphics::PixelFormat &format, th_info &theoraInfo, th_setup_info *theoraSetup) {
+TheoraDecoder::TheoraVideoTrack::TheoraVideoTrack(th_info &theoraInfo, th_setup_info *theoraSetup) {
 	_theoraDecode = th_decode_alloc(&theoraInfo, theoraSetup);
 
 	if (theoraInfo.pixel_fmt != TH_PF_420)
@@ -264,11 +264,18 @@ TheoraDecoder::TheoraVideoTrack::TheoraVideoTrack(const Graphics::PixelFormat &f
 	th_decode_ctl(_theoraDecode, TH_DECCTL_GET_PPLEVEL_MAX, &postProcessingMax, sizeof(postProcessingMax));
 	th_decode_ctl(_theoraDecode, TH_DECCTL_SET_PPLEVEL, &postProcessingMax, sizeof(postProcessingMax));
 
-	_surface.create(theoraInfo.frame_width, theoraInfo.frame_height, format);
+	_x = theoraInfo.pic_x;
+	_y = theoraInfo.pic_y;
+	_width = theoraInfo.pic_width;
+	_height = theoraInfo.pic_height;
+	_surfaceWidth = theoraInfo.frame_width;
+	_surfaceHeight = theoraInfo.frame_height;
 
-	// Set up a display surface
-	_displaySurface.init(theoraInfo.pic_width, theoraInfo.pic_height, _surface.pitch,
-	                    _surface.getBasePtr(theoraInfo.pic_x, theoraInfo.pic_y), format);
+	_pixelFormat = g_system->getScreenFormat();
+
+	// Default to a 32bpp format, if in 8bpp mode
+	if (_pixelFormat.bytesPerPixel == 1)
+		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
 
 	// Set the frame rate
 	_frameRate = Common::Rational(theoraInfo.fps_numerator, theoraInfo.fps_denominator);
@@ -276,13 +283,24 @@ TheoraDecoder::TheoraVideoTrack::TheoraVideoTrack(const Graphics::PixelFormat &f
 	_endOfVideo = false;
 	_nextFrameStartTime = 0.0;
 	_curFrame = -1;
+	_surface = nullptr;
+	_displaySurface = nullptr;
 }
 
 TheoraDecoder::TheoraVideoTrack::~TheoraVideoTrack() {
 	th_decode_free(_theoraDecode);
 
-	_surface.free();
-	_displaySurface.setPixels(0);
+	if (_surface) {
+		_surface->free();
+		delete _surface;
+		_surface = nullptr;
+	}
+
+	if (_displaySurface) {
+		_displaySurface->setPixels(0);
+		delete _displaySurface;
+		_displaySurface = nullptr;
+	}
 }
 
 bool TheoraDecoder::TheoraVideoTrack::decodePacket(ogg_packet &oggPacket) {
@@ -330,7 +348,19 @@ void TheoraDecoder::TheoraVideoTrack::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuf
 	assert(YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height >> 1);
 	assert(YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height >> 1);
 
-	YUVToRGBMan.convert420(&_surface, Graphics::YUVToRGBManager::kScaleITU, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
+	if (!_surface) {
+		_surface = new Graphics::Surface();
+		_surface->create(_surfaceWidth, _surfaceHeight, _pixelFormat);
+	}
+
+	// Set up a display surface
+	if (!_displaySurface) {
+		_displaySurface = new Graphics::Surface();
+		_displaySurface->init(_width, _height, _surface->pitch,
+		                      _surface->getBasePtr(_x, _y), _surface->format);
+	}
+
+	YUVToRGBMan.convert420(_surface, Graphics::YUVToRGBManager::kScaleITU, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
 }
 
 static vorbis_info *info = 0;
diff --git a/video/theora_decoder.h b/video/theora_decoder.h
index 8979c8670b7..6adf2123cec 100644
--- a/video/theora_decoder.h
+++ b/video/theora_decoder.h
@@ -79,17 +79,18 @@ protected:
 private:
 	class TheoraVideoTrack : public VideoTrack {
 	public:
-		TheoraVideoTrack(const Graphics::PixelFormat &format, th_info &theoraInfo, th_setup_info *theoraSetup);
+		TheoraVideoTrack(th_info &theoraInfo, th_setup_info *theoraSetup);
 		~TheoraVideoTrack();
 
 		bool endOfTrack() const { return _endOfVideo; }
-		uint16 getWidth() const { return _displaySurface.w; }
-		uint16 getHeight() const { return _displaySurface.h; }
-		Graphics::PixelFormat getPixelFormat() const { return _displaySurface.format; }
+		uint16 getWidth() const { return _width; }
+		uint16 getHeight() const { return _height; }
+		Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
+		bool setOutputPixelFormat(const Graphics::PixelFormat &format) { _pixelFormat = format; return true; }
 		int getCurFrame() const { return _curFrame; }
 		const Common::Rational &getFrameRate() const { return _frameRate; }
 		uint32 getNextFrameStartTime() const { return (uint32)(_nextFrameStartTime * 1000); }
-		const Graphics::Surface *decodeNextFrame() { return &_displaySurface; }
+		const Graphics::Surface *decodeNextFrame() { return _displaySurface; }
 
 		bool decodePacket(ogg_packet &oggPacket);
 		void setEndOfVideo() { _endOfVideo = true; }
@@ -100,8 +101,15 @@ private:
 		Common::Rational _frameRate;
 		double _nextFrameStartTime;
 
-		Graphics::Surface _surface;
-		Graphics::Surface _displaySurface;
+		Graphics::Surface *_surface;
+		Graphics::Surface *_displaySurface;
+		Graphics::PixelFormat _pixelFormat;
+		int _x;
+		int _y;
+		uint16 _width;
+		uint16 _height;
+		uint16 _surfaceWidth;
+		uint16 _surfaceHeight;
 
 		th_dec_ctx *_theoraDecode;
 


Commit: e6260bf0890bfb79133022c982a801f9eb8a0463
    https://github.com/scummvm/scummvm/commit/e6260bf0890bfb79133022c982a801f9eb8a0463
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
VIDEO: Implement setOutputPixelFormat() for MKVDecoder

Changed paths:
    video/mkv_decoder.cpp
    video/mkv_decoder.h


diff --git a/video/mkv_decoder.cpp b/video/mkv_decoder.cpp
index b6cd9ae15db..9e0efa5e421 100644
--- a/video/mkv_decoder.cpp
+++ b/video/mkv_decoder.cpp
@@ -171,7 +171,7 @@ bool MKVDecoder::loadStream(Common::SeekableReadStream *stream) {
 		if (trackType == mkvparser::Track::kVideo && _vTrack < 0) {
 			_vTrack = pTrack->GetNumber();
 
-			_videoTrack = new VPXVideoTrack(getDefaultHighColorFormat(), pTrack);
+			_videoTrack = new VPXVideoTrack(pTrack);
 
 			addTrack(_videoTrack);
 		}
@@ -310,15 +310,18 @@ void MKVDecoder::readNextPacket() {
 	}
 }
 
-MKVDecoder::VPXVideoTrack::VPXVideoTrack(const Graphics::PixelFormat &format, const mkvparser::Track *const pTrack) {
+MKVDecoder::VPXVideoTrack::VPXVideoTrack(const mkvparser::Track *const pTrack) {
 	const mkvparser::VideoTrack *const pVideoTrack = static_cast<const mkvparser::VideoTrack *>(pTrack);
 
-	const long long width = pVideoTrack->GetWidth();
-	const long long height = pVideoTrack->GetHeight();
+	_width = pVideoTrack->GetWidth();
+	_height = pVideoTrack->GetHeight();
+	_pixelFormat = g_system->getScreenFormat();
 
-	debug(1, "VideoTrack: %lld x %lld", width, height);
+	// Default to a 32bpp format, if in 8bpp mode
+	if (_pixelFormat.bytesPerPixel == 1)
+		_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
 
-	_displaySurface.create(width, height, format);
+	debug(1, "VideoTrack: %d x %d", _width, _height);
 
 	_endOfVideo = false;
 	_nextFrameStartTime = 0.0;
@@ -332,7 +335,6 @@ MKVDecoder::VPXVideoTrack::VPXVideoTrack(const Graphics::PixelFormat &format, co
 }
 
 MKVDecoder::VPXVideoTrack::~VPXVideoTrack() {
-	_displaySurface.free();
 	// The last frame is not freed in decodeNextFrame(), clear it hear instead.
 	_surface.free();
 	delete _codec;
diff --git a/video/mkv_decoder.h b/video/mkv_decoder.h
index 606129879c5..e651041baf4 100644
--- a/video/mkv_decoder.h
+++ b/video/mkv_decoder.h
@@ -88,13 +88,14 @@ protected:
 private:
 	class VPXVideoTrack : public VideoTrack {
 	public:
-		VPXVideoTrack(const Graphics::PixelFormat &format, const mkvparser::Track *const pTrack);
+		VPXVideoTrack(const mkvparser::Track *const pTrack);
 		~VPXVideoTrack();
 
 		bool endOfTrack() const;
-		uint16 getWidth() const { return _displaySurface.w; }
-		uint16 getHeight() const { return _displaySurface.h; }
-		Graphics::PixelFormat getPixelFormat() const { return _displaySurface.format; }
+		uint16 getWidth() const { return _width; }
+		uint16 getHeight() const { return _height; }
+		Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
+		bool setOutputPixelFormat(const Graphics::PixelFormat &format) { _pixelFormat = format; return true; }
 		int getCurFrame() const { return _curFrame; }
 		uint32 getNextFrameStartTime() const { return (uint32)(_nextFrameStartTime * 1000); }
 		const Graphics::Surface *decodeNextFrame();
@@ -106,8 +107,11 @@ private:
 		bool _endOfVideo;
 		double _nextFrameStartTime;
 
+		uint16 _width;
+		uint16 _height;
+		Graphics::PixelFormat _pixelFormat;
+
 		Graphics::Surface _surface;
-		Graphics::Surface _displaySurface;
 		Common::Queue<Graphics::Surface> _displayQueue;
 
 		vpx_codec_ctx_t *_codec = nullptr;


Commit: 75e8dd71b77739ee6cbdaa474a66908e33dc3e23
    https://github.com/scummvm/scummvm/commit/75e8dd71b77739ee6cbdaa474a66908e33dc3e23
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
ASYLUM: Select the best pixel format for video playback

Changed paths:
    engines/asylum/views/video.cpp


diff --git a/engines/asylum/views/video.cpp b/engines/asylum/views/video.cpp
index 6a4785a297a..1fc55147b3a 100644
--- a/engines/asylum/views/video.cpp
+++ b/engines/asylum/views/video.cpp
@@ -189,14 +189,16 @@ void VideoPlayer::play(const Common::String &filename, bool showSubtitles) {
 	int32 frameEnd = 0;
 	int32 currentSubtitle = 0;
 
-	_decoder->start();
-
 	if (_vm->checkGameVersion("Steam") || _vm->isAltDemo()) {
-		Graphics::PixelFormat decoderFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
-		_decoder->setDefaultHighColorFormat(decoderFormat);
+		Graphics::PixelFormat bestFormat = g_system->getSupportedFormats().front();
+		_decoder->setOutputPixelFormat(bestFormat);
+
+		Graphics::PixelFormat decoderFormat = _decoder->getPixelFormat();
 		initGraphics(640, 480, &decoderFormat);
 	}
 
+	_decoder->start();
+
 	while (!_done && !Engine::shouldQuit() && !_decoder->endOfVideo()) {
 		_vm->handleEvents();
 


Commit: 5956fa4757fe303fdaeb386f637ec27590a5a5fc
    https://github.com/scummvm/scummvm/commit/5956fa4757fe303fdaeb386f637ec27590a5a5fc
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-05T12:45:13+02:00

Commit Message:
VIDEO: Remove VideoDecoder::setDefaultHighColorFormat()

Changed paths:
    video/video_decoder.cpp
    video/video_decoder.h


diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp
index 094359df7a9..b1209b52848 100644
--- a/video/video_decoder.cpp
+++ b/video/video_decoder.cpp
@@ -49,12 +49,6 @@ VideoDecoder::VideoDecoder() {
 	_mainAudioTrack = 0;
 	_canSetDither = true;
 	_canSetDefaultFormat = true;
-
-	// Find the best format for output
-	_defaultHighColorFormat = g_system->getScreenFormat();
-
-	if (_defaultHighColorFormat.bytesPerPixel == 1)
-		_defaultHighColorFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
 }
 
 void VideoDecoder::close() {
diff --git a/video/video_decoder.h b/video/video_decoder.h
index 6d41dbaafd5..215a3eef6b0 100644
--- a/video/video_decoder.h
+++ b/video/video_decoder.h
@@ -356,16 +356,6 @@ public:
 	 */
 	virtual const Graphics::Surface *decodeNextFrame();
 
-	/**
-	 * Set the default high color format for videos that convert from YUV.
-	 *
-	 * By default, VideoDecoder will attempt to use the screen format
-	 * if it's >8bpp and use a 32bpp format when not.
-	 *
-	 * This must be set before calling loadStream().
-	 */
-	void setDefaultHighColorFormat(const Graphics::PixelFormat &format) { _defaultHighColorFormat = format; }
-
 	/**
 	 * Set the video to decode frames in reverse.
 	 *
@@ -382,7 +372,7 @@ public:
 	 * Tell the video to dither to a palette.
 	 *
 	 * By default, VideoDecoder will return surfaces in native, or in the case
-	 * of YUV-based videos, the format set by setDefaultHighColorFormat().
+	 * of YUV-based videos, the format set by setOutputPixelFormat().
 	 * For video formats or codecs that support it, this will start outputting
 	 * its surfaces in 8bpp with this palette.
 	 *
@@ -892,11 +882,6 @@ protected:
 	 */
 	bool endOfVideoTracks() const;
 
-	/**
-	 * Get the default high color format
-	 */
-	Graphics::PixelFormat getDefaultHighColorFormat() const { return _defaultHighColorFormat; }
-
 	/**
 	 * Set _nextVideoTrack to the video track with the lowest start time for the next frame.
 	 *
@@ -974,9 +959,6 @@ private:
 	bool _canSetDither;
 	bool _canSetDefaultFormat;
 
-	// Default PixelFormat settings
-	Graphics::PixelFormat _defaultHighColorFormat;
-
 protected:
 	// Internal helper functions
 	void stopAudio();




More information about the Scummvm-git-logs mailing list