diff options
-rw-r--r-- | video/codecs/svq1.cpp | 333 | ||||
-rw-r--r-- | video/codecs/svq1.h | 3 |
2 files changed, 170 insertions, 166 deletions
diff --git a/video/codecs/svq1.cpp b/video/codecs/svq1.cpp index 0ccdc22fc9..e91e5b3cce 100644 --- a/video/codecs/svq1.cpp +++ b/video/codecs/svq1.cpp @@ -45,13 +45,12 @@ namespace Video { #define SVQ1_BLOCK_INTRA 3 SVQ1Decoder::SVQ1Decoder(uint16 width, uint16 height) { + debug(1, "SVQ1Decoder::SVQ1Decoder(width:%d, height:%d)", width, height); + _width = width; + _height = height; _surface = new Graphics::Surface(); _surface->create(width, height, g_system->getScreenFormat()); - _current[0] = new byte[width*height]; - _current[1] = new byte[(width/4)*(height/4)]; - _current[2] = new byte[(width/4)*(height/4)]; - _last[0] = 0; _last[1] = 0; _last[2] = 0; @@ -73,10 +72,6 @@ SVQ1Decoder::~SVQ1Decoder() { _surface->free(); delete _surface; - delete[] _current[0]; - delete[] _current[1]; - delete[] _current[2]; - delete[] _last[0]; delete[] _last[1]; delete[] _last[2]; @@ -166,6 +161,89 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st //for (int i = 0; i < length; i++) // value = checksum_table[data[i] ^ (value >> 8)] ^ ((value & 0xFF) << 8); } + + static const uint8 stringXORTable[256] = { + 0x00, 0xD5, 0x7F, 0xAA, 0xFE, 0x2B, 0x81, 0x54, + 0x29, 0xFC, 0x56, 0x83, 0xD7, 0x02, 0xA8, 0x7D, + 0x52, 0x87, 0x2D, 0xF8, 0xAC, 0x79, 0xD3, 0x06, + 0x7B, 0xAE, 0x04, 0xD1, 0x85, 0x50, 0xFA, 0x2F, + 0xA4, 0x71, 0xDB, 0x0E, 0x5A, 0x8F, 0x25, 0xF0, + 0x8D, 0x58, 0xF2, 0x27, 0x73, 0xA6, 0x0C, 0xD9, + 0xF6, 0x23, 0x89, 0x5C, 0x08, 0xDD, 0x77, 0xA2, + 0xDF, 0x0A, 0xA0, 0x75, 0x21, 0xF4, 0x5E, 0x8B, + 0x9D, 0x48, 0xE2, 0x37, 0x63, 0xB6, 0x1C, 0xC9, + 0xB4, 0x61, 0xCB, 0x1E, 0x4A, 0x9F, 0x35, 0xE0, + 0xCF, 0x1A, 0xB0, 0x65, 0x31, 0xE4, 0x4E, 0x9B, + 0xE6, 0x33, 0x99, 0x4C, 0x18, 0xCD, 0x67, 0xB2, + 0x39, 0xEC, 0x46, 0x93, 0xC7, 0x12, 0xB8, 0x6D, + 0x10, 0xC5, 0x6F, 0xBA, 0xEE, 0x3B, 0x91, 0x44, + 0x6B, 0xBE, 0x14, 0xC1, 0x95, 0x40, 0xEA, 0x3F, + 0x42, 0x97, 0x3D, 0xE8, 0xBC, 0x69, 0xC3, 0x16, + 0xEF, 0x3A, 0x90, 0x45, 0x11, 0xC4, 0x6E, 0xBB, + 0xC6, 0x13, 0xB9, 0x6C, 0x38, 0xED, 0x47, 0x92, + 0xBD, 0x68, 0xC2, 0x17, 0x43, 0x96, 0x3C, 0xE9, + 0x94, 0x41, 0xEB, 0x3E, 0x6A, 0xBF, 0x15, 0xC0, + 0x4B, 0x9E, 0x34, 0xE1, 0xB5, 0x60, 0xCA, 0x1F, + 0x62, 0xB7, 0x1D, 0xC8, 0x9C, 0x49, 0xE3, 0x36, + 0x19, 0xCC, 0x66, 0xB3, 0xE7, 0x32, 0x98, 0x4D, + 0x30, 0xE5, 0x4F, 0x9A, 0xCE, 0x1B, 0xB1, 0x64, + 0x72, 0xA7, 0x0D, 0xD8, 0x8C, 0x59, 0xF3, 0x26, + 0x5B, 0x8E, 0x24, 0xF1, 0xA5, 0x70, 0xDA, 0x0F, + 0x20, 0xF5, 0x5F, 0x8A, 0xDE, 0x0B, 0xA1, 0x74, + 0x09, 0xDC, 0x76, 0xA3, 0xF7, 0x22, 0x88, 0x5D, + 0xD6, 0x03, 0xA9, 0x7C, 0x28, 0xFD, 0x57, 0x82, + 0xFF, 0x2A, 0x80, 0x55, 0x01, 0xD4, 0x7E, 0xAB, + 0x84, 0x51, 0xFB, 0x2E, 0x7A, 0xAF, 0x05, 0xD0, + 0xAD, 0x78, 0xD2, 0x07, 0x53, 0x86, 0x2C, 0xF9 + }; + + if ((frameCode ^ 0x10) >= 0x50) { + // Decode embedded string + Common::String str; + uint8 stringLen = frameData.getBits(8); + byte xorVal = stringXORTable[stringLen]; + + for (uint16 i = 0; i < stringLen-1; i++) { + byte data = frameData.getBits(8); + str += data ^ xorVal; + xorVal = stringXORTable[data]; + } + debug(1, " Embedded String of %d Characters: \"%s\"", stringLen, str.c_str()); + } + + byte unk1 = frameData.getBits(2); // Unknown + debug(1, " unk1: %d", unk1); + byte unk2 = frameData.getBits(2); // Unknown + debug(1, " unk2: %d", unk2); + bool unk3 = frameData.getBit(); // Unknown + debug(1, " unk3: %d", unk3); + + static const struct { uint w, h; } standardFrameSizes[7] = { + { 160, 120 }, // 0 + { 128, 96 }, // 1 + { 176, 144 }, // 2 + { 352, 288 }, // 3 + { 704, 576 }, // 4 + { 240, 180 }, // 5 + { 320, 240 } // 6 + }; + + byte frameSizeCode = frameData.getBits(3); + debug(1, " frameSizeCode: %d", frameSizeCode); + uint16 frameWidth, frameHeight; + if (frameSizeCode == 7) { + frameWidth = frameData.getBits(12); + frameHeight = frameData.getBits(12); + } else { + frameWidth = standardFrameSizes[frameSizeCode].w; + frameHeight = standardFrameSizes[frameSizeCode].h; + } + debug(1, " frameWidth: %d", frameWidth); + debug(1, " frameHeight: %d", frameHeight); + if (frameWidth != _width || frameHeight != _height) { // Invalid + warning("Invalid Frame Size"); + return _surface; + } } else if (frameType == 2) { // B Frame warning("B Frames not supported by SVQ1 decoder"); return _surface; @@ -174,88 +252,6 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st return _surface; } - static const uint8 stringXORTable[256] = { - 0x00, 0xD5, 0x7F, 0xAA, 0xFE, 0x2B, 0x81, 0x54, - 0x29, 0xFC, 0x56, 0x83, 0xD7, 0x02, 0xA8, 0x7D, - 0x52, 0x87, 0x2D, 0xF8, 0xAC, 0x79, 0xD3, 0x06, - 0x7B, 0xAE, 0x04, 0xD1, 0x85, 0x50, 0xFA, 0x2F, - 0xA4, 0x71, 0xDB, 0x0E, 0x5A, 0x8F, 0x25, 0xF0, - 0x8D, 0x58, 0xF2, 0x27, 0x73, 0xA6, 0x0C, 0xD9, - 0xF6, 0x23, 0x89, 0x5C, 0x08, 0xDD, 0x77, 0xA2, - 0xDF, 0x0A, 0xA0, 0x75, 0x21, 0xF4, 0x5E, 0x8B, - 0x9D, 0x48, 0xE2, 0x37, 0x63, 0xB6, 0x1C, 0xC9, - 0xB4, 0x61, 0xCB, 0x1E, 0x4A, 0x9F, 0x35, 0xE0, - 0xCF, 0x1A, 0xB0, 0x65, 0x31, 0xE4, 0x4E, 0x9B, - 0xE6, 0x33, 0x99, 0x4C, 0x18, 0xCD, 0x67, 0xB2, - 0x39, 0xEC, 0x46, 0x93, 0xC7, 0x12, 0xB8, 0x6D, - 0x10, 0xC5, 0x6F, 0xBA, 0xEE, 0x3B, 0x91, 0x44, - 0x6B, 0xBE, 0x14, 0xC1, 0x95, 0x40, 0xEA, 0x3F, - 0x42, 0x97, 0x3D, 0xE8, 0xBC, 0x69, 0xC3, 0x16, - 0xEF, 0x3A, 0x90, 0x45, 0x11, 0xC4, 0x6E, 0xBB, - 0xC6, 0x13, 0xB9, 0x6C, 0x38, 0xED, 0x47, 0x92, - 0xBD, 0x68, 0xC2, 0x17, 0x43, 0x96, 0x3C, 0xE9, - 0x94, 0x41, 0xEB, 0x3E, 0x6A, 0xBF, 0x15, 0xC0, - 0x4B, 0x9E, 0x34, 0xE1, 0xB5, 0x60, 0xCA, 0x1F, - 0x62, 0xB7, 0x1D, 0xC8, 0x9C, 0x49, 0xE3, 0x36, - 0x19, 0xCC, 0x66, 0xB3, 0xE7, 0x32, 0x98, 0x4D, - 0x30, 0xE5, 0x4F, 0x9A, 0xCE, 0x1B, 0xB1, 0x64, - 0x72, 0xA7, 0x0D, 0xD8, 0x8C, 0x59, 0xF3, 0x26, - 0x5B, 0x8E, 0x24, 0xF1, 0xA5, 0x70, 0xDA, 0x0F, - 0x20, 0xF5, 0x5F, 0x8A, 0xDE, 0x0B, 0xA1, 0x74, - 0x09, 0xDC, 0x76, 0xA3, 0xF7, 0x22, 0x88, 0x5D, - 0xD6, 0x03, 0xA9, 0x7C, 0x28, 0xFD, 0x57, 0x82, - 0xFF, 0x2A, 0x80, 0x55, 0x01, 0xD4, 0x7E, 0xAB, - 0x84, 0x51, 0xFB, 0x2E, 0x7A, 0xAF, 0x05, 0xD0, - 0xAD, 0x78, 0xD2, 0x07, 0x53, 0x86, 0x2C, 0xF9 - }; - - if ((frameCode ^ 0x10) >= 0x50) { - // Decode embedded string - Common::String str; - uint8 stringLen = frameData.getBits(8); - byte xorVal = stringXORTable[stringLen]; - - for (uint16 i = 0; i < stringLen-1; i++) { - byte data = frameData.getBits(8); - str += data ^ xorVal; - xorVal = stringXORTable[data]; - } - debug(1, " Embedded String of %d Characters: \"%s\"", stringLen, str.c_str()); - } - - byte unk1 = frameData.getBits(2); // Unknown - debug(1, " unk1: %d", unk1); - byte unk2 = frameData.getBits(2); // Unknown - debug(1, " unk2: %d", unk2); - bool unk3 = frameData.getBit(); // Unknown - debug(1, " unk3: %d", unk3); - - static const struct { uint w, h; } standardFrameSizes[7] = { - { 160, 120 }, // 0 - { 128, 96 }, // 1 - { 176, 144 }, // 2 - { 352, 288 }, // 3 - { 704, 576 }, // 4 - { 240, 180 }, // 5 - { 320, 240 } // 6 - }; - - byte frameSizeCode = frameData.getBits(3); - debug(1, " frameSizeCode: %d", frameSizeCode); - uint16 frameWidth, frameHeight; - if (frameSizeCode == 7) { - frameWidth = frameData.getBits(12); - frameHeight = frameData.getBits(12); - } else { - frameWidth = standardFrameSizes[frameSizeCode].w; - frameHeight = standardFrameSizes[frameSizeCode].h; - } - debug(1, " frameWidth: %d", frameWidth); - debug(1, " frameHeight: %d", frameHeight); - if (frameWidth == 0 || frameHeight == 0) { // Invalid - warning("Invalid Frame Size"); - return _surface; - } bool checksumPresent = frameData.getBit(); debug(1, " checksumPresent: %d", checksumPresent); if (checksumPresent) { @@ -286,91 +282,98 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st } } - if (frameWidth == _surface->w && frameHeight == _surface->h) { - // Decode Y, U and V component planes - for (int i = 0; i < 3; i++) { - int linesize, width, height; - if (i == 0) { - // Y Size is width * height - width = frameWidth; - if (width % 16) { - width /= 16; - width++; - width *= 16; - } - assert(width % 16 == 0); - height = frameHeight; - if (height % 16) { - height /= 16; - height++; - height *= 16; - } - assert(height % 16 == 0); - linesize = width; - } else { - // U and V size is width/4 * height/4 - width = frameWidth/4; - if (width % 16) { - width /= 16; - width++; - width *= 16; - } - assert(width % 16 == 0); - height = frameHeight/4; - if (height % 16) { - height /= 16; - height++; - height *= 16; - } - assert(height % 16 == 0); - linesize = width; + byte *current[3]; + current[0] = new byte[_width*_height]; + current[1] = new byte[(_width/4)*(_height/4)]; + current[2] = new byte[(_width/4)*(_height/4)]; + + // Decode Y, U and V component planes + for (int i = 0; i < 3; i++) { + int linesize, width, height; + if (i == 0) { + // Y Size is width * height + width = _width; + if (width % 16) { + width /= 16; + width++; + width *= 16; + } + assert(width % 16 == 0); + height = _height; + if (height % 16) { + height /= 16; + height++; + height *= 16; + } + assert(height % 16 == 0); + linesize = _width; + } else { + // U and V size is width/4 * height/4 + width = _width/4; + if (width % 16) { + width /= 16; + width++; + width *= 16; } + assert(width % 16 == 0); + height = _height/4; + if (height % 16) { + height /= 16; + height++; + height *= 16; + } + assert(height % 16 == 0); + linesize = _width/4; + } - if (frameType == 0) { // I Frame - // Keyframe (I) - byte *current = _current[i]; - for (uint16 y = 0; y < height; y += 16) { - for (uint16 x = 0; x < width; x += 16) { - if (int result = svq1DecodeBlockIntra(&frameData, ¤t[x], linesize) != 0) { - warning("Error in svq1DecodeBlock %i (keyframe)", result); - return _surface; - } + if (frameType == 0) { // I Frame + // Keyframe (I) + byte *currentP = current[i]; + for (uint16 y = 0; y < height; y += 16) { + for (uint16 x = 0; x < width; x += 16) { + if (int result = svq1DecodeBlockIntra(&frameData, ¤tP[x], linesize) != 0) { + warning("Error in svq1DecodeBlock %i (keyframe)", result); + return _surface; } - current += 16 * linesize; } - } else { - // Delta frame (P or B) - - // Prediction Motion Vector - Common::Point *pmv = new Common::Point[(width/8) + 3]; - - byte *previous; - if(frameType == 2) { // B Frame - warning("B Frame not supported currently"); - //previous = _next[i]; - } else - previous = _last[i]; - - byte *current = _current[i]; - for (uint16 y = 0; y < height; y += 16) { - for (uint16 x = 0; x < width; x += 16) { - if (int result = svq1DecodeDeltaBlock(&frameData, ¤t[x], previous, linesize, pmv, x, y) != 0) { - warning("Error in svq1DecodeDeltaBlock %i", result); - return _surface; - } + currentP += 16 * linesize; + } + } else { + // Delta frame (P or B) + + // Prediction Motion Vector + Common::Point *pmv = new Common::Point[(width/8) + 3]; + + byte *previous; + if(frameType == 2) { // B Frame + warning("B Frame not supported currently"); + //previous = _next[i]; + } else + previous = _last[i]; + + byte *currentP = current[i]; + for (uint16 y = 0; y < height; y += 16) { + for (uint16 x = 0; x < width; x += 16) { + if (int result = svq1DecodeDeltaBlock(&frameData, ¤tP[x], previous, linesize, pmv, x, y) != 0) { + warning("Error in svq1DecodeDeltaBlock %i", result); + return _surface; } + } - pmv[0].x = pmv[0].y = 0; + pmv[0].x = pmv[0].y = 0; - current += 16*linesize; - } - delete[] pmv; + currentP += 16*linesize; } + delete[] pmv; } + } - convertYUV410ToRGB(_surface, _current[0], _current[1], _current[2], frameWidth, frameHeight, frameWidth, frameWidth/2); - } else - warning("FrameWidth/Height Sanity Check Failed!"); + convertYUV410ToRGB(_surface, current[0], current[1], current[2], _width, _height, _width, _width/4); + + for (int i = 0; i < 3; i++) { + delete _last[i]; + _last[i] = current[i]; + } return _surface; } diff --git a/video/codecs/svq1.h b/video/codecs/svq1.h index 2271bf4d2b..ed34439329 100644 --- a/video/codecs/svq1.h +++ b/video/codecs/svq1.h @@ -43,8 +43,9 @@ public: private: Graphics::Surface *_surface; + uint16 _width; + uint16 _height; - byte *_current[3]; byte *_last[3]; Common::Huffman *_blockType; |