diff options
-rw-r--r-- | graphics/module.mk | 2 | ||||
-rw-r--r-- | graphics/video/avi_decoder.cpp | 7 | ||||
-rw-r--r-- | graphics/video/codecs/indeo3.cpp (renamed from graphics/video/coktelvideo/indeo3.cpp) | 192 | ||||
-rw-r--r-- | graphics/video/codecs/indeo3.h (renamed from graphics/video/coktelvideo/indeo3.h) | 56 | ||||
-rw-r--r-- | graphics/video/coktelvideo/coktelvideo.cpp | 76 | ||||
-rw-r--r-- | graphics/video/coktelvideo/coktelvideo.h | 10 |
6 files changed, 122 insertions, 221 deletions
diff --git a/graphics/module.mk b/graphics/module.mk index 75e3919370..9df126afa7 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -37,7 +37,7 @@ MODULE_OBJS := \ video/codecs/qtrle.o \ video/codecs/rpza.o \ video/codecs/smc.o \ - video/coktelvideo/indeo3.o \ + video/codecs/indeo3.o \ video/coktelvideo/coktelvideo.o ifdef USE_SCALERS diff --git a/graphics/video/avi_decoder.cpp b/graphics/video/avi_decoder.cpp index 06589d99b0..4973cb3eb0 100644 --- a/graphics/video/avi_decoder.cpp +++ b/graphics/video/avi_decoder.cpp @@ -38,6 +38,7 @@ #include "graphics/video/codecs/cinepak.h" #include "graphics/video/codecs/msvideo1.h" #include "graphics/video/codecs/msrle.h" +#include "graphics/video/codecs/indeo3.h" namespace Graphics { @@ -387,10 +388,14 @@ Codec *AviDecoder::createCodec() { case ID_MSVC: case ID_WHAM: return new MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); - case ID_RLE : + case ID_RLE: return new MSRLEDecoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); case ID_CVID: return new CinepakDecoder(); +#ifdef USE_INDEO3 + case ID_IV32: + return new Indeo3Decoder(_bmInfo.width, _bmInfo.height); +#endif default: warning ("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler)); } diff --git a/graphics/video/coktelvideo/indeo3.cpp b/graphics/video/codecs/indeo3.cpp index 983705ab9c..f59ae81e81 100644 --- a/graphics/video/coktelvideo/indeo3.cpp +++ b/graphics/video/codecs/indeo3.cpp @@ -38,33 +38,38 @@ #include "common/frac.h" #include "common/file.h" -#include "graphics/dither.h" -#include "graphics/video/coktelvideo/indeo3.h" +#include "graphics/conversion.h" + +#include "graphics/video/codecs/indeo3.h" namespace Graphics { -Indeo3::Indeo3(int16 width, int16 height, Graphics::PaletteLUT *palLUT) { - assert((width > 0) && (height > 0)); +Indeo3Decoder::Indeo3Decoder(uint16 width, uint16 height) : _ModPred(0), _corrector_type(0) { + _iv_frame[0].the_buf = 0; + _iv_frame[1].the_buf = 0; - _width = width; - _height = height; - _palLUT = palLUT; + _pixelFormat = g_system->getScreenFormat(); - _ditherSL = 0; - setDither(kDitherSierraLight); + _surface = new Surface; + _surface->create(width, height, _pixelFormat.bytesPerPixel); buildModPred(); allocFrames(); } -Indeo3::~Indeo3() { +Indeo3Decoder::~Indeo3Decoder() { + delete _surface; + delete[] _iv_frame[0].the_buf; delete[] _ModPred; delete[] _corrector_type; - delete _ditherSL; } -bool Indeo3::isIndeo3(byte *data, uint32 dataLen) { +PixelFormat Indeo3Decoder::getPixelFormat() const { + return _pixelFormat; +} + +bool Indeo3Decoder::isIndeo3(byte *data, uint32 dataLen) { // No data, no Indeo 3 if (!data) return false; @@ -90,23 +95,7 @@ bool Indeo3::isIndeo3(byte *data, uint32 dataLen) { return true; } -void Indeo3::setDither(DitherAlgorithm dither) { - delete _ditherSL; - _ditherSL = 0; - - _dither = dither; - - switch (dither) { - case kDitherSierraLight: - _ditherSL = new Graphics::SierraLight(_width, _palLUT); - break; - - default: - return; - } -} - -void Indeo3::buildModPred() { +void Indeo3Decoder::buildModPred() { _ModPred = new byte[8 * 128]; for (int i = 0; i < 128; i++) { @@ -133,12 +122,12 @@ void Indeo3::buildModPred() { } } -void Indeo3::allocFrames() { - int32 luma_width = (_width + 3) & (~3); - int32 luma_height = (_height + 3) & (~3); +void Indeo3Decoder::allocFrames() { + int32 luma_width = (_surface->w + 3) & (~3); + int32 luma_height = (_surface->h + 3) & (~3); - int32 chroma_width = ((luma_width >> 2) + 3) & (~3); - int32 chroma_height = ((luma_height>> 2) + 3) & (~3); + int32 chroma_width = ((luma_width >> 2) + 3) & (~3); + int32 chroma_height = ((luma_height >> 2) + 3) & (~3); int32 luma_pixels = luma_width * luma_height; int32 chroma_pixels = chroma_width * chroma_height; @@ -184,21 +173,23 @@ void Indeo3::allocFrames() { } } -bool Indeo3::decompressFrame(byte *inData, uint32 dataLen, - byte *outData, uint16 width, uint16 height) { +Surface *Indeo3Decoder::decodeImage(Common::SeekableReadStream *stream) { + uint32 dataLen = stream->size(); + + byte *inData = new byte[dataLen]; + + if (stream->read(inData, dataLen) != dataLen) + return 0; // Not Indeo 3? Fail if (!isIndeo3(inData, dataLen)) - return false; - - assert(outData); - assert(_palLUT); + return 0; uint32 frameDataLen = READ_LE_UINT32(inData + 12); // Less data than the frame should have? Fail if (dataLen < (frameDataLen - 16)) - return false; + return 0; Common::MemoryReadStream frame(inData, dataLen); @@ -219,7 +210,7 @@ bool Indeo3::decompressFrame(byte *inData, uint32 dataLen, } if (flags3 == 0x80) - return true; + return _surface; frame.skip(3); @@ -262,85 +253,40 @@ bool Indeo3::decompressFrame(byte *inData, uint32 dataLen, decodeChunk(_cur_frame->Ubuf, _ref_frame->Ubuf, chromaWidth, chromaHeight, buf_pos + offs * 2, flags2, hdr_pos, buf_pos, MIN<int>(chromaWidth, 40)); - BlitState blitState; - - blitState.widthY = _cur_frame->y_w; - blitState.widthUV = _cur_frame->uv_w; - blitState.uwidthUV = chromaWidth; - blitState.uwidthOut = fWidth; - blitState.heightY = _cur_frame->y_h; - blitState.heightUV = _cur_frame->uv_h; - blitState.uheightUV = chromaHeight; - blitState.uheightOut = fHeight; - blitState.scaleWYUV = blitState.widthY / blitState.widthUV; - blitState.scaleHYUV = blitState.heightY / blitState.heightUV; - blitState.scaleWYOut = blitState.widthY / blitState.uwidthOut; - blitState.scaleHYOut = blitState.heightY / blitState.uheightOut; - blitState.lineWidthOut = blitState.scaleWYOut * blitState.uwidthOut; - blitState.lineHeightOut = blitState.scaleHYOut * blitState.uheightOut; - blitState.bufY = _cur_frame->Ybuf; - blitState.bufU = _cur_frame->Ubuf; - blitState.bufV = _cur_frame->Vbuf; - blitState.bufOut = outData; - - blitFrame(blitState); + // Blit the frame onto the surface + const byte *srcY = _cur_frame->Ybuf; + const byte *srcU = _cur_frame->Ubuf; + const byte *srcV = _cur_frame->Vbuf; + byte *dest = (byte *)_surface->pixels; + for (uint32 y = 0; y < fHeight; y++) { + byte *rowDest = dest; - return true; -} - -void Indeo3::blitFrame(BlitState &s) { - if (_ditherSL) - _ditherSL->newFrame(); - - for (s.curY = 0; s.curY < s.uheightOut; s.curY++) { - if (_dither == kDitherNone) - blitLine(s); - else - blitLineDither(s); - } -} + for (uint32 x = 0; x < fWidth; x++, rowDest += _surface->bytesPerPixel) { + const byte cY = srcY[x]; + const byte cU = srcU[x >> 2]; + const byte cV = srcV[x >> 2]; -void Indeo3::blitLine(BlitState &s) { - byte *lineU = s.bufU + (s.curY >> 2) * s.uwidthUV; - byte *lineV = s.bufV + (s.curY >> 2) * s.uwidthUV; + byte r = 0, g = 0, b = 0; + YUV2RGB(cY, cU, cV, r, g, b); - for (s.curX = 0; s.curX < s.uwidthOut; s.curX++) { - byte dataY = *s.bufY++; - byte dataU = lineU[s.curX >> 2]; - byte dataV = lineV[s.curX >> 2]; - - for (int n = 0; n < s.scaleWYOut; n++) - *s.bufOut++ = _palLUT->findNearest(dataY, dataU, dataV); - } + const uint32 color = _pixelFormat.RGBToColor(r, g, b); - byte *lineDest = s.bufOut - s.lineWidthOut; - for (int n = 1; n < s.scaleHYOut; n++) { - memcpy(s.bufOut, lineDest, s.lineWidthOut); - s.bufOut += s.lineWidthOut; - } -} - -void Indeo3::blitLineDither(BlitState &s) { - byte *lineU = s.bufU + (s.curY >> 2) * s.uwidthUV; - byte *lineV = s.bufV + (s.curY >> 2) * s.uwidthUV; - - for (uint16 i = 0; i < s.scaleHYOut; i++) { - byte *bufY = s.bufY; - - for (s.curX = 0; s.curX < s.uwidthOut; s.curX++) { - byte dataY = *bufY++; - byte dataU = lineU[s.curX >> 2]; - byte dataV = lineV[s.curX >> 2]; + if (_surface->bytesPerPixel == 1) + *((uint8 *)rowDest) = (uint8)color; + else if (_surface->bytesPerPixel == 2) + *((uint16 *)rowDest) = (uint16)color; + } - for (int n = 0; n < s.scaleWYOut; n++) - *s.bufOut++ = _ditherSL->dither(dataY, dataU, dataV, s.curX * s.scaleWYOut + n); + dest += _surface->pitch; + srcY += fWidth; + if ((y & 3) == 3) { + srcU += fWidth >> 2; + srcV += fWidth >> 2; } - - _ditherSL->nextLine(); } - s.bufY += s.uwidthOut; + return _surface; } typedef struct { @@ -397,7 +343,7 @@ typedef struct { } \ lp2 = 4; -void Indeo3::decodeChunk(byte *cur, byte *ref, int width, int height, +void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height, const byte *buf1, uint32 fflags2, const byte *hdr, const byte *buf2, int min_width_160) { @@ -729,7 +675,7 @@ void Indeo3::decodeChunk(byte *cur, byte *ref, int width, int height, break; case 9: - warning("Indeo3::decodeChunk: Untested (1)"); + warning("Indeo3Decoder::decodeChunk: Untested (1)"); lv1 = *buf1++; lv = (lv1 & 0x7F) << 1; lv += (lv << 8); @@ -906,7 +852,7 @@ void Indeo3::decodeChunk(byte *cur, byte *ref, int width, int height, break; case 9: - warning("Indeo3::decodeChunk: Untested (2)"); + warning("Indeo3Decoder::decodeChunk: Untested (2)"); lv1 = *buf1; lv = (lv1 & 0x7F) << 1; lv += (lv << 8); @@ -1002,7 +948,7 @@ void Indeo3::decodeChunk(byte *cur, byte *ref, int width, int height, break; case 9: - warning("Indeo3::decodeChunk: Untested (3)"); + warning("Indeo3Decoder::decodeChunk: Untested (3)"); lv1 = *buf1; lv = (lv1 & 0x7F) << 1; lv += (lv << 8); @@ -1099,7 +1045,7 @@ void Indeo3::decodeChunk(byte *cur, byte *ref, int width, int height, break; case 9: - warning("Indeo3::decodeChunk: Untested (4)"); + warning("Indeo3Decoder::decodeChunk: Untested (4)"); lv1 = *buf1++; lv = (lv1 & 0x7F) << 1; lv += (lv << 8); @@ -1127,7 +1073,7 @@ void Indeo3::decodeChunk(byte *cur, byte *ref, int width, int height, // FIXME: I've seen case 13 happen in Urban // Runner. Perhaps it uses a more recent form of // Indeo 3? There appears to have been several. - warning("Indeo3::decodeChunk: Unknown case %d", k); + warning("Indeo3Decoder::decodeChunk: Unknown case %d", k); return; } } @@ -1157,15 +1103,15 @@ void Indeo3::decodeChunk(byte *cur, byte *ref, int width, int height, // static data -const int Indeo3::_corrector_type_0[24] = { +const int Indeo3Decoder::_corrector_type_0[24] = { 195, 159, 133, 115, 101, 93, 87, 77, 195, 159, 133, 115, 101, 93, 87, 77, 128, 79, 79, 79, 79, 79, 79, 79 }; -const int Indeo3::_corrector_type_2[8] = { 9, 7, 6, 8, 5, 4, 3, 2 }; +const int Indeo3Decoder::_corrector_type_2[8] = { 9, 7, 6, 8, 5, 4, 3, 2 }; -const uint32 Indeo3::correction[] = { +const uint32 Indeo3Decoder::correction[] = { 0x00000000, 0x00000202, 0xfffffdfe, 0x000002ff, 0xfffffd01, 0xffffff03, 0x000000fd, 0x00000404, 0xfffffbfc, 0x00000501, 0xfffffaff, 0x00000105, 0xfffffefb, 0x000003fc, 0xfffffc04, 0x000005fe, 0xfffffa02, 0xfffffe06, 0x000001fa, 0x00000904, 0xfffff6fc, 0x00000409, 0xfffffbf7, 0x00000909, @@ -1937,7 +1883,7 @@ const uint32 Indeo3::correction[] = { }; -const uint32 Indeo3::correctionloworder[] = { +const uint32 Indeo3Decoder::correctionloworder[] = { 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x04040404, 0xfbfbfbfc, 0x05050101, 0xfafafeff, 0x01010505, 0xfefefafb, 0x0403fbfc, 0xfbfc0404, 0x0605fdfe, 0xf9fa0202, 0xfdfe0606, 0x0201f9fa, 0x09090404, 0xf6f6fbfc, 0x04040909, 0xfbfbf6f7, 0x09090909, @@ -2709,7 +2655,7 @@ const uint32 Indeo3::correctionloworder[] = { }; -const uint32 Indeo3::correctionhighorder[] = { +const uint32 Indeo3Decoder::correctionhighorder[] = { 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, diff --git a/graphics/video/coktelvideo/indeo3.h b/graphics/video/codecs/indeo3.h index af6ef26449..8d50b74b1e 100644 --- a/graphics/video/coktelvideo/indeo3.h +++ b/graphics/video/codecs/indeo3.h @@ -34,36 +34,28 @@ * written, produced, and directed by Alan Smithee */ -#ifndef GRAPHICS_VIDEO_INDEO3_H -#define GRAPHICS_VIDEO_INDEO3_H +#ifndef GRAPHICS_INDEO3_H +#define GRAPHICS_INDEO3_H -#include "common/stream.h" +#include "graphics/video/codecs/codec.h" namespace Graphics { - class PaletteLUT; - class SierraLight; -} -namespace Graphics { - -class Indeo3 { +class Indeo3Decoder : public Codec { public: - enum DitherAlgorithm { - kDitherNone = 0, - kDitherSierraLight - }; + Indeo3Decoder(uint16 width, uint16 height); + ~Indeo3Decoder(); - Indeo3(int16 width, int16 height, Graphics::PaletteLUT *palLUT); - ~Indeo3(); + Surface *decodeImage(Common::SeekableReadStream *stream); + PixelFormat getPixelFormat() const; static bool isIndeo3(byte *data, uint32 dataLen); - void setDither(DitherAlgorithm dither); +private: + Surface *_surface; - bool decompressFrame(byte *inData, uint32 dataLen, - byte *outData, uint16 width, uint16 height); + PixelFormat _pixelFormat; -private: static const int _corrector_type_0[24]; static const int _corrector_type_2[8]; static const uint32 correction[]; @@ -80,8 +72,6 @@ private: uint16 uv_w, uv_h; }; - int16 _width; - int16 _height; YUVBufs _iv_frame[2]; YUVBufs *_cur_frame; YUVBufs *_ref_frame; @@ -89,38 +79,16 @@ private: byte *_ModPred; uint16 *_corrector_type; - Graphics::PaletteLUT *_palLUT; - - DitherAlgorithm _dither; - Graphics::SierraLight *_ditherSL; - - struct BlitState { - uint32 curX, curY; - uint16 widthY, widthUV; - uint16 heightY, heightUV; - uint16 uwidthUV, uwidthOut; - uint16 uheightUV, uheightOut; - uint16 scaleWYUV, scaleWYOut; - uint16 scaleHYUV, scaleHYOut; - uint16 lineWidthOut, lineHeightOut; - byte *bufY, *bufU, *bufV, *bufOut; - }; - void buildModPred(); void allocFrames(); void decodeChunk(byte *cur, byte *ref, int width, int height, const byte *buf1, uint32 fflags2, const byte *hdr, const byte *buf2, int min_width_160); - - void blitFrame(BlitState &s); - - void blitLine(BlitState &s); - void blitLineDither(BlitState &s); }; } // End of namespace Graphics -#endif // GRAPHICS_VIDEO_INDEO3_H +#endif // GRAPHICS_INDEO3_H #endif // USE_INDEO3 diff --git a/graphics/video/coktelvideo/coktelvideo.cpp b/graphics/video/coktelvideo/coktelvideo.cpp index 9ee9fd68d0..280431b5d5 100644 --- a/graphics/video/coktelvideo/coktelvideo.cpp +++ b/graphics/video/coktelvideo/coktelvideo.cpp @@ -31,11 +31,13 @@ #include "common/system.h" #include "graphics/dither.h" -#include "graphics/video/coktelvideo/indeo3.h" +#include "graphics/video/codecs/indeo3.h" #include "sound/audiostream.h" #include "sound/decoders/raw.h" +static const uint32 kVideoCodecIndeo3 = MKID_BE('iv32'); + namespace Graphics { PreImd::PreImd() { @@ -1439,11 +1441,11 @@ bool Vmd::assessVideoProperties() { _externalCodec = false; if (_externalCodec) { - if (_videoCodec == MKID_BE('iv32')) { + if (_videoCodec == kVideoCodecIndeo3) { #ifdef USE_INDEO3 _features &= ~kFeaturesPalette; _features |= kFeaturesFullColor; - _codecIndeo3 = new Indeo3(_width, _height, _palLUT); + _codec = new Indeo3Decoder(_width, _height); #else warning("Vmd::assessVideoProperties(): Indeo3 decoder not compiled in"); #endif @@ -1503,11 +1505,6 @@ bool Vmd::assessVideoProperties() { } } -#ifdef USE_INDEO3 - if (_externalCodec && _codecIndeo3) - _features |= kFeaturesSupportsDouble; -#endif - return true; } @@ -1816,15 +1813,6 @@ void Vmd::setDoubleMode(bool doubleMode) { } -#ifdef USE_INDEO3 - if (_codecIndeo3) { - delete _codecIndeo3; - - _codecIndeo3 = new Indeo3(_width * (doubleMode ? 2 : 1), - _height * (doubleMode ? 2 : 1), _palLUT); - } -#endif - _doubleMode = doubleMode; } @@ -1870,10 +1858,6 @@ void Vmd::zeroData() { _hasVideo = true; _videoCodec = 0; -#ifdef USE_INDEO3 - _codecIndeo3 = 0; -#endif - _partsPerFrame = 0; _frames = 0; @@ -1886,6 +1870,8 @@ void Vmd::zeroData() { _audioFormat = kAudioFormat8bitDirect; _externalCodec = false; + _codec = 0; + _doubleMode = false; _blitMode = 0; _bytesPerPixel = 1; @@ -1898,11 +1884,10 @@ void Vmd::zeroData() { void Vmd::deleteData() { Imd::deleteData(); -#ifdef USE_INDEO3 - delete _codecIndeo3; -#endif - delete[] _frames; - delete[] _vidMemBuffer; + delete _codec; + + delete[] _frames; + delete[] _vidMemBuffer; } void Vmd::clear() { @@ -2158,38 +2143,39 @@ uint32 Vmd::renderFrame(int16 &left, int16 &top, int16 &right, int16 &bottom) { uint8 type; byte *dest = imdVidMem; -#ifdef USE_INDEO3 - uint32 dataLen = _frameDataLen; - - if (Indeo3::isIndeo3(dataPtr, dataLen)) { - if (!_codecIndeo3) + if (_externalCodec) { + if (!_codec) return 0; - if (!_codecIndeo3->decompressFrame(dataPtr, dataLen, _vidBuffer, - width * (_doubleMode ? 2 : 1), height * (_doubleMode ? 2 : 1))) + if (_videoCodec == kVideoCodecIndeo3) { +#ifndef USE_INDEO3 return 0; +#else + if (!Indeo3Decoder::isIndeo3(dataPtr, _frameDataLen)) { + warning("Indeo3 data not indeo3"); + return 0; + } +#endif + } + Common::MemoryReadStream *dataStream = new Common::MemoryReadStream(dataPtr, _frameDataLen); + _codec->decodeImage(dataStream); + + // TODO + + /* type = 2; srcPtr = _vidBuffer; width = _width * (_doubleMode ? 2 : 1); height = _height * (_doubleMode ? 2 : 1); right = left + width - 1; bottom = top + height - 1; + */ - } else { - - if (_externalCodec) { - warning("Unknown external codec"); - return 0; - } - -#else - - if (_externalCodec) { return 0; - } else { + } -#endif + if (!_externalCodec) { type = *dataPtr++; srcPtr = dataPtr; diff --git a/graphics/video/coktelvideo/coktelvideo.h b/graphics/video/coktelvideo/coktelvideo.h index f8b1965f41..91dbee99bf 100644 --- a/graphics/video/coktelvideo/coktelvideo.h +++ b/graphics/video/coktelvideo/coktelvideo.h @@ -41,9 +41,7 @@ namespace Audio { namespace Graphics { -#ifdef USE_INDEO3 -class Indeo3; -#endif +class Codec; /** Common interface for handling Coktel Vision videos and derivated formats. */ class CoktelVideo { @@ -530,7 +528,6 @@ protected: AudioFormat _audioFormat; // Video properties - bool _externalCodec; byte _blitMode; byte _bytesPerPixel; byte _preScaleX; @@ -542,9 +539,8 @@ protected: Graphics::PaletteLUT *_palLUT; -#ifdef USE_INDEO3 - Indeo3 *_codecIndeo3; -#endif + bool _externalCodec; + Codec *_codec; void clear(); void zeroData(); |