mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-01 06:14:07 +00:00
IMAGE: Defer creation of surface until decodeFrame() is called in Indeo codecs
This commit is contained in:
parent
d90d7a72b6
commit
78faa2ae28
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -56,6 +56,8 @@ public:
|
||||
private:
|
||||
Graphics::Surface *_surface;
|
||||
|
||||
uint16 _width;
|
||||
uint16 _height;
|
||||
Graphics::PixelFormat _pixelFormat;
|
||||
|
||||
static const int _corrector_type_0[24];
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user