diff options
author | Matthew Hoops | 2012-04-07 19:35:45 -0400 |
---|---|---|
committer | D G Turner | 2012-04-08 03:29:56 +0100 |
commit | 744528cb18ef6b79703a77804acf01864aaaf39e (patch) | |
tree | e4fd93e989541776cd008dfbcba27910d987053f | |
parent | 8e107f8c78e9c17fd908c205c12fbb718f868648 (diff) | |
download | scummvm-rg350-744528cb18ef6b79703a77804acf01864aaaf39e.tar.gz scummvm-rg350-744528cb18ef6b79703a77804acf01864aaaf39e.tar.bz2 scummvm-rg350-744528cb18ef6b79703a77804acf01864aaaf39e.zip |
VIDEO: Clean up the SVQ1 code
-rw-r--r-- | video/codecs/svq1.cpp | 551 | ||||
-rw-r--r-- | video/codecs/svq1.h | 22 | ||||
-rw-r--r-- | video/codecs/svq1_cb.h | 3 | ||||
-rw-r--r-- | video/codecs/svq1_vlc.h | 3 | ||||
-rw-r--r-- | video/qt_decoder.cpp | 3 |
5 files changed, 250 insertions, 332 deletions
diff --git a/video/codecs/svq1.cpp b/video/codecs/svq1.cpp index f1ee33748a..dc64429d4a 100644 --- a/video/codecs/svq1.cpp +++ b/video/codecs/svq1.cpp @@ -21,7 +21,7 @@ */ // Sorenson Video 1 Codec -// Based off ffmpeg's SVQ1 decoder (written by Mike Melanson) +// Based off FFmpeg's SVQ1 decoder (written by Arpi and Nick Kurshev) #include "video/codecs/svq1.h" #include "video/codecs/svq1_cb.h" @@ -89,7 +89,7 @@ SVQ1Decoder::~SVQ1Decoder() { } } -#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) +#define ALIGN(x, a) (((x)+(a)-1)&~((a)-1)) const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *stream) { debug(1, "SVQ1Decoder::decodeImage()"); @@ -104,81 +104,28 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st return _surface; } - // swap some header bytes (why?) - //if (frameCode != 0x20) { - // uint32 *src = stream; - // - // for (i = 4; i < 8; i++) { - // src[i] = ((src[i] << 16) | (src[i] >> 16)) ^ src[7 - i]; - // } - //} - -#if 0 - static const uint16 checksum_table[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 - }; -#endif - byte temporalReference = frameData.getBits(8); debug(1, " temporalReference: %d", temporalReference); - const char* types[4] = { "I (Key)", "P (Delta from Previous)", "B (Delta from Next)", "Invalid" }; + static const char *const types[4] = { "I (Key)", "P (Delta from Previous)", "B (Delta from Next)", "Invalid" }; byte frameType = frameData.getBits(2); debug(1, " frameType: %d = %s Frame", frameType, types[frameType]); + if (frameType == 0) { // I Frame // TODO: Validate checksum if present if (frameCode == 0x50 || frameCode == 0x60) { uint32 checksum = frameData.getBits(16); debug(1, " checksum:0x%02x", checksum); - //uint16 calculate_packet_checksum (const uint8 *data, const int length) { - // int value; - //for (int i = 0; i < length; i++) - // value = checksum_table[data[i] ^ (value >> 8)] ^ ((value & 0xFF) << 8); + // We're currently just ignoring the checksum } if ((frameCode ^ 0x10) >= 0x50) { // Skip embedded string - uint8 stringLen = frameData.getBits(8); + byte stringLen = frameData.getBits(8); for (uint16 i = 0; i < stringLen-1; i++) frameData.skip(8); } - 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); + frameData.skip(5); // Unknown static const struct { uint w, h; } standardFrameSizes[7] = { { 160, 120 }, // 0 @@ -200,22 +147,23 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st _frameWidth = standardFrameSizes[frameSizeCode].w; _frameHeight = standardFrameSizes[frameSizeCode].h; } + debug(1, " frameWidth: %d", _frameWidth); debug(1, " frameHeight: %d", _frameHeight); } else if (frameType == 2) { // B Frame - warning("B Frames not supported by SVQ1 decoder"); + warning("B Frames not supported by SVQ1 decoder (yet)"); return _surface; } else if (frameType == 3) { // Invalid warning("Invalid Frame Type"); return _surface; } - bool checksumPresent = frameData.getBit(); + bool checksumPresent = frameData.getBit() != 0; debug(1, " checksumPresent: %d", checksumPresent); if (checksumPresent) { - bool usePacketChecksum = frameData.getBit(); + bool usePacketChecksum = frameData.getBit() != 0; debug(1, " usePacketChecksum: %d", usePacketChecksum); - bool componentChecksumsAfterImageData = frameData.getBit(); + bool componentChecksumsAfterImageData = frameData.getBit() != 0; debug(1, " componentChecksumsAfterImageData: %d", componentChecksumsAfterImageData); byte unk4 = frameData.getBits(2); debug(1, " unk4: %d", unk4); @@ -223,27 +171,19 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st warning("Invalid Frame Header in SVQ1 Frame Decode"); } - bool unk5 = frameData.getBit(); - debug(1, " unk5: %d", unk5); + // Some more unknown data + bool unk5 = frameData.getBit() != 0; if (unk5) { - bool unk6 = frameData.getBit(); - debug(1, " unk6: %d", unk6); - byte unk7 = frameData.getBits(4); - debug(1, " unk7: %d", unk7); - bool unk8 = frameData.getBit(); - debug(1, " unk8: %d", unk8); - byte unk9 = frameData.getBits(2); - debug(1, " unk9: %d", unk9); - while (frameData.getBit()) { - byte unk10 = frameData.getBits(8); - debug(1, " unk10: %d", unk10); - } + frameData.skip(8); + + while (frameData.getBit() != 0) + frameData.skip(8); } - int yWidth = FFALIGN(_frameWidth, 16); - int yHeight = FFALIGN(_frameHeight, 16); - int uvWidth = FFALIGN(yWidth / 4, 16); - int uvHeight = FFALIGN(yHeight / 4, 16); + int yWidth = ALIGN(_frameWidth, 16); + int yHeight = ALIGN(_frameHeight, 16); + int uvWidth = ALIGN(yWidth / 4, 16); + int uvHeight = ALIGN(yHeight / 4, 16); byte *current[3]; @@ -276,14 +216,15 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st // Delta frame (P or B) // Prediction Motion Vector - Common::Point *pmv = new Common::Point[(width/8) + 3]; + Common::Point *pmv = new Common::Point[(width / 8) + 3]; byte *previous; - if(frameType == 2) { // B Frame + if (frameType == 2) { // B Frame warning("B Frame not supported currently"); //previous = _next[i]; - } else + } else { previous = _last[i]; + } byte *currentP = current[i]; for (uint16 y = 0; y < height; y += 16) { @@ -296,8 +237,9 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st pmv[0].x = pmv[0].y = 0; - currentP += 16*width; + currentP += 16 * width; } + delete[] pmv; } } @@ -312,6 +254,7 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st convertYUV410ToRGB(_surface, current[0], current[1], current[2], yWidth, yHeight, yWidth, uvWidth); + // Store the current surfaces for later and free the old ones for (int i = 0; i < 3; i++) { delete[] _last[i]; _last[i] = current[i]; @@ -320,21 +263,13 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st return _surface; } -bool SVQ1Decoder::svq1DecodeBlockIntra(Common::BitStream *s, uint8 *pixels, int pitch) { - uint8 *list[63]; - uint32 *dst; - int entries[6]; - int i, j, m, n; - int mean, stages; - unsigned int x, y, width, height, level; - uint32 n1, n2, n3, n4; - +bool SVQ1Decoder::svq1DecodeBlockIntra(Common::BitStream *s, byte *pixels, int pitch) { // initialize list for breadth first processing of vectors + byte *list[63]; list[0] = pixels; // recursively process vector - for (i = 0, m = 1, n = 1, level = 5; i < n; i++) { - // SVQ1_PROCESS_VECTOR() + for (int i = 0, m = 1, n = 1, level = 5; i < n; i++) { for (; level > 0; i++) { // process next depth if (i == m) { @@ -342,83 +277,86 @@ bool SVQ1Decoder::svq1DecodeBlockIntra(Common::BitStream *s, uint8 *pixels, int if (--level == 0) break; } + // divide block if next bit set if (s->getBit() == 0) break; + // add child nodes list[n++] = list[i]; list[n++] = list[i] + (((level & 1) ? pitch : 1) << ((level / 2) + 1)); } // destination address and vector size - dst = (uint32 *) list[i]; - width = 1 << ((4 + level) /2); - height = 1 << ((3 + level) /2); + uint32 *dst = (uint32 *)list[i]; + uint width = 1 << ((level + 4) / 2); + uint height = 1 << ((level + 3) / 2); // get number of stages (-1 skips vector, 0 for mean only) - stages = _intraMultistage[level]->getSymbol(*s) - 1; + int stages = _intraMultistage[level]->getSymbol(*s) - 1; if (stages == -1) { - for (y = 0; y < height; y++) { - memset (&dst[y*(pitch / 4)], 0, width); - } - continue; // skip vector + for (uint y = 0; y < height; y++) + memset(&dst[y * (pitch / 4)], 0, width); + + continue; // skip vector } - if ((stages > 0) && (level >= 4)) { - warning("Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i", stages, level); + if (stages > 0 && level >= 4) { + warning("Error (svq1_decode_block_intra): invalid vector: stages = %d, level = %d", stages, level); return false; // error - invalid vector } - mean = _intraMean->getSymbol(*s); + int mean = _intraMean->getSymbol(*s); if (stages == 0) { - for (y = 0; y < height; y++) { - memset (&dst[y*(pitch / 4)], mean, width); - } + for (uint y = 0; y < height; y++) + memset(&dst[y * (pitch / 4)], mean, width); } else { - // SVQ1_CALC_CODEBOOK_ENTRIES(svq1_intra_codebooks); const uint32 *codebook = s_svq1IntraCodebooks[level]; - uint32 bit_cache = s->getBits(4*stages); + uint32 bitCache = s->getBits(stages * 4); + // calculate codebook entries for this vector - for (j = 0; j < stages; j++) { - entries[j] = (((bit_cache >> (4*(stages - j - 1))) & 0xF) + 16*j) << (level + 1); - } - mean -= (stages * 128); - n4 = ((mean + (mean >> 31)) << 16) | (mean & 0xFFFF); - - // SVQ1_DO_CODEBOOK_INTRA() - for (y = 0; y < height; y++) { - for (x = 0; x < (width / 4); x++, codebook++) { - n1 = n4; - n2 = n4; - // SVQ1_ADD_CODEBOOK() + int entries[6]; + for (int j = 0; j < stages; j++) + entries[j] = (((bitCache >> ((stages - j - 1) * 4)) & 0xF) + j * 16) << (level + 1); + + mean -= stages * 128; + uint32 n4 = ((mean + (mean >> 31)) << 16) | (mean & 0xFFFF); + + for (uint y = 0; y < height; y++) { + for (uint x = 0; x < (width / 4); x++, codebook++) { + uint32 n1 = n4; + uint32 n2 = n4; + uint32 n3; + // add codebook entries to vector - for (j=0; j < stages; j++) { - n3 = codebook[entries[j]] ^ 0x80808080; - n1 += ((n3 & 0xFF00FF00) >> 8); - n2 += (n3 & 0x00FF00FF); + for (int j = 0; j < stages; j++) { + n3 = codebook[entries[j]] ^ 0x80808080; + n1 += (n3 & 0xFF00FF00) >> 8; + n2 += n3 & 0x00FF00FF; } // clip to [0..255] if (n1 & 0xFF00FF00) { - n3 = ((( n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; + n3 = (((n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; n1 += 0x7F007F00; n1 |= (((~n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; - n1 &= (n3 & 0x00FF00FF); + n1 &= n3 & 0x00FF00FF; } if (n2 & 0xFF00FF00) { - n3 = ((( n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; + n3 = (((n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; n2 += 0x7F007F00; n2 |= (((~n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; - n2 &= (n3 & 0x00FF00FF); + n2 &= n3 & 0x00FF00FF; } // store result dst[x] = (n1 << 8) | n2; } - dst += (pitch / 4); + + dst += pitch / 4; } } } @@ -426,21 +364,13 @@ bool SVQ1Decoder::svq1DecodeBlockIntra(Common::BitStream *s, uint8 *pixels, int return true; } -bool SVQ1Decoder::svq1DecodeBlockNonIntra(Common::BitStream *s, uint8 *pixels, int pitch) { - uint8 *list[63]; - uint32 *dst; - int entries[6]; - int i, j, m, n; - int mean, stages; - int x, y, width, height, level; - uint32 n1, n2, n3, n4; - +bool SVQ1Decoder::svq1DecodeBlockNonIntra(Common::BitStream *s, byte *pixels, int pitch) { // initialize list for breadth first processing of vectors + byte *list[63]; list[0] = pixels; // recursively process vector - for (i = 0, m = 1, n = 1, level = 5; i < n; i++) { - // SVQ1_PROCESS_VECTOR() + for (int i = 0, m = 1, n = 1, level = 5; i < n; i++) { for (; level > 0; i++) { // process next depth if (i == m) { @@ -448,93 +378,103 @@ bool SVQ1Decoder::svq1DecodeBlockNonIntra(Common::BitStream *s, uint8 *pixels, i if (--level == 0) break; } + // divide block if next bit set if (s->getBit() == 0) break; + // add child nodes list[n++] = list[i]; list[n++] = list[i] + (((level & 1) ? pitch : 1) << ((level / 2) + 1)); } // destination address and vector size - dst = (uint32 *) list[i]; - width = 1 << ((4 + level) /2); - height = 1 << ((3 + level) /2); + uint32 *dst = (uint32 *)list[i]; + int width = 1 << ((level + 4) / 2); + int height = 1 << ((level + 3) / 2); // get number of stages (-1 skips vector, 0 for mean only) - stages = _interMultistage[level]->getSymbol(*s) - 1; + int stages = _interMultistage[level]->getSymbol(*s) - 1; - if (stages == -1) continue; // skip vector + if (stages == -1) + continue; // skip vector - if ((stages > 0) && (level >= 4)) { - warning("Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i", stages, level); + if (stages > 0 && level >= 4) { + warning("Error (svq1_decode_block_non_intra): invalid vector: stages = %d, level = %d", stages, level); return false; // error - invalid vector } - mean = _interMean->getSymbol(*s) - 256; - - // SVQ1_CALC_CODEBOOK_ENTRIES(svq1_inter_codebooks); + int mean = _interMean->getSymbol(*s) - 256; const uint32 *codebook = s_svq1InterCodebooks[level]; - uint32 bit_cache = s->getBits(4*stages); + uint32 bitCache = s->getBits(stages * 4); + // calculate codebook entries for this vector - for (j=0; j < stages; j++) { - entries[j] = (((bit_cache >> (4*(stages - j - 1))) & 0xF) + 16*j) << (level + 1); - } - mean -= (stages * 128); - n4 = ((mean + (mean >> 31)) << 16) | (mean & 0xFFFF); + int entries[6]; + for (int j = 0; j < stages; j++) + entries[j] = (((bitCache >> ((stages - j - 1) * 4)) & 0xF) + j * 16) << (level + 1); + + mean -= stages * 128; + uint32 n4 = ((mean + (mean >> 31)) << 16) | (mean & 0xFFFF); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < (width / 4); x++, codebook++) { + uint32 n3 = dst[x]; - // SVQ1_DO_CODEBOOK_NONINTRA() - for (y = 0; y < height; y++) { - for (x = 0; x < (width / 4); x++, codebook++) { - n3 = dst[x]; // add mean value to vector - n1 = ((n3 & 0xFF00FF00) >> 8) + n4; - n2 = (n3 & 0x00FF00FF) + n4; - //SVQ1_ADD_CODEBOOK() + uint32 n1 = ((n3 & 0xFF00FF00) >> 8) + n4; + uint32 n2 = (n3 & 0x00FF00FF) + n4; + // add codebook entries to vector - for (j=0; j < stages; j++) { - n3 = codebook[entries[j]] ^ 0x80808080; - n1 += ((n3 & 0xFF00FF00) >> 8); - n2 += (n3 & 0x00FF00FF); + for (int j = 0; j < stages; j++) { + n3 = codebook[entries[j]] ^ 0x80808080; + n1 += (n3 & 0xFF00FF00) >> 8; + n2 += n3 & 0x00FF00FF; } // clip to [0..255] if (n1 & 0xFF00FF00) { - n3 = ((( n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; + n3 = ((( n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; n1 += 0x7F007F00; n1 |= (((~n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; - n1 &= (n3 & 0x00FF00FF); + n1 &= n3 & 0x00FF00FF; } if (n2 & 0xFF00FF00) { n3 = ((( n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; n2 += 0x7F007F00; n2 |= (((~n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001; - n2 &= (n3 & 0x00FF00FF); + n2 &= n3 & 0x00FF00FF; } // store result dst[x] = (n1 << 8) | n2; } - dst += (pitch / 4); + + dst += pitch / 4; } } + return true; } // median of 3 -static inline int mid_pred(int a, int b, int c) { +static inline int midPred(int a, int b, int c) { if (a > b) { if (c > b) { - if (c > a) b = a; - else b = c; + if (c > a) + b = a; + else + b = c; } } else { if (b > c) { - if (c > a) b = c; - else b = a; + if (c > a) + b = c; + else + b = a; } } + return b; } @@ -544,26 +484,22 @@ bool SVQ1Decoder::svq1DecodeMotionVector(Common::BitStream *s, Common::Point *mv int diff = _motionComponent->getSymbol(*s); if (diff < 0) return false; // error - invalid motion code - else if (diff) { - if (s->getBit()) diff = -diff; - } + else if (diff && s->getBit() != 0) + diff = -diff; // add median of motion vector predictors and clip result if (i == 1) - mv->y = ((diff + mid_pred(pmv[0]->y, pmv[1]->y, pmv[2]->y)) << 26) >> 26; + mv->y = ((diff + midPred(pmv[0]->y, pmv[1]->y, pmv[2]->y)) << 26) >> 26; else - mv->x = ((diff + mid_pred(pmv[0]->x, pmv[1]->x, pmv[2]->x)) << 26) >> 26; + mv->x = ((diff + midPred(pmv[0]->x, pmv[1]->x, pmv[2]->x)) << 26) >> 26; } return true; } -void SVQ1Decoder::svq1SkipBlock(uint8 *current, uint8 *previous, int pitch, int x, int y) { - uint8 *src; - uint8 *dst; - - src = &previous[x + y*pitch]; - dst = current; +void SVQ1Decoder::svq1SkipBlock(byte *current, byte *previous, int pitch, int x, int y) { + const byte *src = &previous[x + y * pitch]; + byte *dst = current; for (int i = 0; i < 16; i++) { memcpy(dst, src, 16); @@ -572,100 +508,95 @@ void SVQ1Decoder::svq1SkipBlock(uint8 *current, uint8 *previous, int pitch, int } } -static void put_pixels8_c(uint8 *block, const uint8 *pixels, int line_size, int h) { +void SVQ1Decoder::putPixels8C(byte *block, const byte *pixels, int lineSize, int h) { for (int i = 0; i < h; i++) { - *((uint32*)(block)) = READ_UINT32(pixels); - *((uint32*)(block + 4)) = READ_UINT32(pixels + 4); - pixels += line_size; - block += line_size; + *((uint32 *)block) = READ_UINT32(pixels); + *((uint32 *)(block + 4)) = READ_UINT32(pixels + 4); + pixels += lineSize; + block += lineSize; } } -static inline uint32 rnd_avg32(uint32 a, uint32 b) { - return (a | b) - (((a ^ b) & ~((0x01)*0x01010101UL)) >> 1); +static inline uint32 rndAvg32(uint32 a, uint32 b) { + return (a | b) - (((a ^ b) & ~0x01010101) >> 1); } -static inline void put_pixels8_l2(uint8 *dst, const uint8 *src1, const uint8 *src2, - int dst_stride, int src_stride1, int src_stride2, int h) { - for (int i = 0; i < h; i++){ - uint32 a, b; - a= READ_UINT32(&src1[i*src_stride1]); - b= READ_UINT32(&src2[i*src_stride2]); - *((uint32*)&dst[i*dst_stride]) = rnd_avg32(a, b); - a= READ_UINT32(&src1[i*src_stride1 + 4]); - b= READ_UINT32(&src2[i*src_stride2 + 4]); - *((uint32*)&dst[i*dst_stride + 4]) = rnd_avg32(a, b); +void SVQ1Decoder::putPixels8L2(byte *dst, const byte *src1, const byte *src2, + int dstStride, int srcStride1, int srcStride2, int h) { + for (int i = 0; i < h; i++) { + uint32 a = READ_UINT32(&src1[srcStride1 * i]); + uint32 b = READ_UINT32(&src2[srcStride2 * i]); + *((uint32 *)&dst[dstStride * i]) = rndAvg32(a, b); + a = READ_UINT32(&src1[srcStride1 * i + 4]); + b = READ_UINT32(&src2[srcStride2 * i + 4]); + *((uint32 *)&dst[dstStride * i + 4]) = rndAvg32(a, b); } } -static inline void put_pixels8_x2_c(uint8 *block, const uint8 *pixels, int line_size, int h) { - put_pixels8_l2(block, pixels, pixels+1, line_size, line_size, line_size, h); +void SVQ1Decoder::putPixels8X2C(byte *block, const byte *pixels, int lineSize, int h) { + putPixels8L2(block, pixels, pixels + 1, lineSize, lineSize, lineSize, h); } -static inline void put_pixels8_y2_c(uint8 *block, const uint8 *pixels, int line_size, int h) { - put_pixels8_l2(block, pixels, pixels+line_size, line_size, line_size, line_size, h); +void SVQ1Decoder::putPixels8Y2C(byte *block, const byte *pixels, int lineSize, int h) { + putPixels8L2(block, pixels, pixels + lineSize, lineSize, lineSize, lineSize, h); } -static inline void put_pixels8_xy2_c(uint8 *block, const uint8 *pixels, int line_size, int h) { +void SVQ1Decoder::putPixels8XY2C(byte *block, const byte *pixels, int lineSize, int h) { for (int j = 0; j < 2; j++) { uint32 a = READ_UINT32(pixels); - uint32 b = READ_UINT32(pixels+1); + uint32 b = READ_UINT32(pixels + 1); uint32 l0 = (a & 0x03030303UL) + (b & 0x03030303UL) + 0x02020202UL; uint32 h0 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2); - uint32 l1, h1; - pixels += line_size; + pixels += lineSize; + for (int i = 0; i < h; i += 2) { a = READ_UINT32(pixels); - b = READ_UINT32(pixels+1); - l1 = (a & 0x03030303UL) + (b & 0x03030303UL); - h1 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2); - *((uint32*)block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL); - pixels += line_size; - block += line_size; + b = READ_UINT32(pixels + 1); + uint32 l1 = (a & 0x03030303UL) + (b & 0x03030303UL); + uint32 h1 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2); + *((uint32 *)block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL); + pixels += lineSize; + block += lineSize; a = READ_UINT32(pixels); - b = READ_UINT32(pixels+1); + b = READ_UINT32(pixels + 1); l0 = (a & 0x03030303UL) + (b & 0x03030303UL) + 0x02020202UL; h0 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2); - *((uint32*)block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL); - pixels += line_size; - block += line_size; + *((uint32 *)block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL); + pixels += lineSize; + block += lineSize; } - pixels += 4 - line_size*(h + 1); - block += 4 - line_size*h; + + pixels += 4 - lineSize * (h + 1); + block += 4 - lineSize * h; } } -static void put_pixels16_c(uint8 *block, const uint8 *pixels, int line_size, int h) { - put_pixels8_c(block, pixels, line_size, h); - put_pixels8_c(block+8, pixels+8, line_size, h); +void SVQ1Decoder::putPixels16C(byte *block, const byte *pixels, int lineSize, int h) { + putPixels8C(block, pixels, lineSize, h); + putPixels8C(block + 8, pixels + 8, lineSize, h); } -static void put_pixels16_x2_c(uint8 *block, const uint8 *pixels, int line_size, int h) { - put_pixels8_x2_c(block, pixels, line_size, h); - put_pixels8_x2_c(block+8, pixels+8, line_size, h); +void SVQ1Decoder::putPixels16X2C(byte *block, const byte *pixels, int lineSize, int h) { + putPixels8X2C(block, pixels, lineSize, h); + putPixels8X2C(block + 8, pixels + 8, lineSize, h); } -static void put_pixels16_y2_c(uint8 *block, const uint8 *pixels, int line_size, int h) { - put_pixels8_y2_c(block, pixels, line_size, h); - put_pixels8_y2_c(block+8, pixels+8, line_size, h); +void SVQ1Decoder::putPixels16Y2C(byte *block, const byte *pixels, int lineSize, int h) { + putPixels8Y2C(block, pixels, lineSize, h); + putPixels8Y2C(block + 8, pixels + 8, lineSize, h); } -static void put_pixels16_xy2_c(uint8 *block, const uint8 *pixels, int line_size, int h) { - put_pixels8_xy2_c(block, pixels, line_size, h); - put_pixels8_xy2_c(block+8, pixels+8, line_size, h); +void SVQ1Decoder::putPixels16XY2C(byte *block, const byte *pixels, int lineSize, int h) { + putPixels8XY2C(block, pixels, lineSize, h); + putPixels8XY2C(block + 8, pixels + 8, lineSize, h); } -bool SVQ1Decoder::svq1MotionInterBlock(Common::BitStream *ss, - uint8 *current, uint8 *previous, int pitch, - Common::Point *motion, int x, int y) { - uint8 *src; - uint8 *dst; - Common::Point mv; - Common::Point *pmv[3]; - bool resultValid; +bool SVQ1Decoder::svq1MotionInterBlock(Common::BitStream *ss, byte *current, byte *previous, int pitch, + Common::Point *motion, int x, int y) { // predict and decode motion vector + Common::Point *pmv[3]; pmv[0] = &motion[0]; if (y == 0) { pmv[1] = pmv[2] = pmv[0]; @@ -674,62 +605,48 @@ bool SVQ1Decoder::svq1MotionInterBlock(Common::BitStream *ss, pmv[2] = &motion[(x / 8) + 4]; } - resultValid = svq1DecodeMotionVector(ss, &mv, pmv); + Common::Point mv; + bool resultValid = svq1DecodeMotionVector(ss, &mv, pmv); if (!resultValid) return false; motion[0].x = motion[(x / 8) + 2].x = motion[(x / 8) + 3].x = mv.x; motion[0].y = motion[(x / 8) + 2].y = motion[(x / 8) + 3].y = mv.y; - if(y + (mv.y >> 1) < 0) + if (y + (mv.y >> 1) < 0) mv.y = 0; - if(x + (mv.x >> 1) < 0) - mv.x = 0; -#if 0 - int w = (s->width + 15) & ~15; - int h = (s->height + 15) & ~15; - if(x + (mv.x >> 1) < 0 || y + (mv.y >> 1) < 0 || x + (mv.x >> 1) + 16 > w || y + (mv.y >> 1) + 16 > h) - debug(1, "%d %d %d %d", x, y, x + (mv.x >> 1), y + (mv.y >> 1)); -#endif + if (x + (mv.x >> 1) < 0) + mv.x = 0; - src = &previous[(x + (mv.x >> 1)) + (y + (mv.y >> 1))*pitch]; - dst = current; + const byte *src = &previous[(x + (mv.x >> 1)) + (y + (mv.y >> 1)) * pitch]; + byte *dst = current; - // Halfpel motion compensation with rounding (a+b+1)>>1. + // Halfpel motion compensation with rounding (a + b + 1) >> 1. // 4 motion compensation functions for the 4 halfpel positions // for 16x16 blocks - switch(((mv.y & 1)*2) + (mv.x & 1)) { + switch(((mv.y & 1) << 1) + (mv.x & 1)) { case 0: - put_pixels16_c(dst, src, pitch, 16); + putPixels16C(dst, src, pitch, 16); break; case 1: - put_pixels16_x2_c(dst, src, pitch, 16); + putPixels16X2C(dst, src, pitch, 16); break; case 2: - put_pixels16_y2_c(dst, src, pitch, 16); + putPixels16Y2C(dst, src, pitch, 16); break; case 3: - put_pixels16_xy2_c(dst, src, pitch, 16); - break; - default: - error("Motion Compensation Function Lookup Error. Should Not Happen!"); + putPixels16XY2C(dst, src, pitch, 16); break; } return true; } -bool SVQ1Decoder::svq1MotionInter4vBlock(Common::BitStream *ss, - uint8 *current, uint8 *previous, int pitch, - Common::Point *motion, int x, int y) { - uint8 *src; - uint8 *dst; - Common::Point mv; - Common::Point *pmv[4]; - bool resultValid; - +bool SVQ1Decoder::svq1MotionInter4vBlock(Common::BitStream *ss, byte *current, byte *previous, int pitch, + Common::Point *motion, int x, int y) { // predict and decode motion vector (0) + Common::Point *pmv[4]; pmv[0] = &motion[0]; if (y == 0) { pmv[1] = pmv[2] = pmv[0]; @@ -738,17 +655,17 @@ bool SVQ1Decoder::svq1MotionInter4vBlock(Common::BitStream *ss, pmv[2] = &motion[(x / 8) + 4]; } - resultValid = svq1DecodeMotionVector(ss, &mv, pmv); + Common::Point mv; + bool resultValid = svq1DecodeMotionVector(ss, &mv, pmv); if (!resultValid) return false; // predict and decode motion vector (1) pmv[0] = &mv; - if (y == 0) { + if (y == 0) pmv[1] = pmv[2] = pmv[0]; - } else { + else pmv[1] = &motion[(x / 8) + 3]; - } resultValid = svq1DecodeMotionVector(ss, &motion[0], pmv); if (!resultValid) @@ -772,80 +689,68 @@ bool SVQ1Decoder::svq1MotionInter4vBlock(Common::BitStream *ss, // form predictions for (int i = 0; i < 4; i++) { - int mvx = pmv[i]->x + (i & 1)*16; - int mvy = pmv[i]->y + (i >> 1)*16; + int mvx = pmv[i]->x + (i & 1) * 16; + int mvy = pmv[i]->y + (i >> 1) * 16; - ///XXX /FIXME clipping or padding? - if(y + (mvy >> 1) < 0) + // FIXME: clipping or padding? + if (y + (mvy >> 1) < 0) mvy = 0; - if(x + (mvx >> 1) < 0) + + if (x + (mvx >> 1) < 0) mvx = 0; -#if 0 - int w = (s->width + 15) & ~15; - int h = (s->height + 15) & ~15; - if(x + (mvx >> 1) < 0 || y + (mvy >> 1) < 0 || x + (mvx >> 1) + 8 > w || y + (mvy >> 1) + 8 > h) - debug(1, "%d %d %d %d", x, y, x + (mvx >> 1), y + (mvy >> 1)); -#endif - src = &previous[(x + (mvx >> 1)) + (y + (mvy >> 1))*pitch]; - dst = current; + const byte *src = &previous[(x + (mvx >> 1)) + (y + (mvy >> 1)) * pitch]; + byte *dst = current; - // Halfpel motion compensation with rounding (a+b+1)>>1. + // Halfpel motion compensation with rounding (a + b + 1) >> 1. // 4 motion compensation functions for the 4 halfpel positions // for 8x8 blocks - switch(((mvy & 1)*2) + (mvx & 1)) { + switch(((mvy & 1) << 1) + (mvx & 1)) { case 0: - put_pixels8_c(dst, src, pitch, 8); + putPixels8C(dst, src, pitch, 8); break; case 1: - put_pixels8_x2_c(dst, src, pitch, 8); + putPixels8X2C(dst, src, pitch, 8); break; case 2: - put_pixels8_y2_c(dst, src, pitch, 8); + putPixels8Y2C(dst, src, pitch, 8); break; case 3: - put_pixels8_xy2_c(dst, src, pitch, 8); - break; - default: - error("Motion Compensation Function Lookup Error. Should Not Happen!"); + putPixels8XY2C(dst, src, pitch, 8); break; } // select next block - if (i & 1) { - current += 8*(pitch - 1); - } else { - current += 8; - } + if (i & 1) + current += (pitch - 1) * 8; + else + current += 8; } return true; } -bool SVQ1Decoder::svq1DecodeDeltaBlock(Common::BitStream *ss, - uint8 *current, uint8 *previous, int pitch, - Common::Point *motion, int x, int y) { - uint32 block_type; - bool resultValid = true; - +bool SVQ1Decoder::svq1DecodeDeltaBlock(Common::BitStream *ss, byte *current, byte *previous, int pitch, + Common::Point *motion, int x, int y) { // get block type - block_type = _blockType->getSymbol(*ss); + uint32 blockType = _blockType->getSymbol(*ss); // reset motion vectors - if (block_type == SVQ1_BLOCK_SKIP || block_type == SVQ1_BLOCK_INTRA) { - motion[0].x = - motion[0].y = + if (blockType == SVQ1_BLOCK_SKIP || blockType == SVQ1_BLOCK_INTRA) { + motion[0].x = + motion[0].y = motion[(x / 8) + 2].x = motion[(x / 8) + 2].y = motion[(x / 8) + 3].x = motion[(x / 8) + 3].y = 0; } - switch (block_type) { + bool resultValid = true; + + switch (blockType) { case SVQ1_BLOCK_SKIP: svq1SkipBlock(current, previous, pitch, x, y); break; - case SVQ1_BLOCK_INTER: resultValid = svq1MotionInterBlock(ss, current, previous, pitch, motion, x, y); if (!resultValid) { @@ -854,7 +759,6 @@ bool SVQ1Decoder::svq1DecodeDeltaBlock(Common::BitStream *ss, } resultValid = svq1DecodeBlockNonIntra(ss, current, pitch); break; - case SVQ1_BLOCK_INTER_4V: resultValid = svq1MotionInter4vBlock(ss, current, previous, pitch, motion, x, y); if (!resultValid) { @@ -863,7 +767,6 @@ bool SVQ1Decoder::svq1DecodeDeltaBlock(Common::BitStream *ss, } resultValid = svq1DecodeBlockNonIntra(ss, current, pitch); break; - case SVQ1_BLOCK_INTRA: resultValid = svq1DecodeBlockIntra(ss, current, pitch); break; diff --git a/video/codecs/svq1.h b/video/codecs/svq1.h index 2c35f6cb46..df22d4b7de 100644 --- a/video/codecs/svq1.h +++ b/video/codecs/svq1.h @@ -55,16 +55,26 @@ private: Common::Huffman *_interMean; Common::Huffman *_motionComponent; - bool svq1DecodeBlockIntra(Common::BitStream *s, uint8 *pixels, int pitch); - bool svq1DecodeBlockNonIntra(Common::BitStream *s, uint8 *pixels, int pitch); + bool svq1DecodeBlockIntra(Common::BitStream *s, byte *pixels, int pitch); + bool svq1DecodeBlockNonIntra(Common::BitStream *s, byte *pixels, int pitch); bool svq1DecodeMotionVector(Common::BitStream *s, Common::Point *mv, Common::Point **pmv); - void svq1SkipBlock(uint8 *current, uint8 *previous, int pitch, int x, int y); - bool svq1MotionInterBlock(Common::BitStream *ss, uint8 *current, uint8 *previous, int pitch, + void svq1SkipBlock(byte *current, byte *previous, int pitch, int x, int y); + bool svq1MotionInterBlock(Common::BitStream *ss, byte *current, byte *previous, int pitch, Common::Point *motion, int x, int y); - bool svq1MotionInter4vBlock(Common::BitStream *ss, uint8 *current, uint8 *previous, int pitch, + bool svq1MotionInter4vBlock(Common::BitStream *ss, byte *current, byte *previous, int pitch, Common::Point *motion, int x, int y); - bool svq1DecodeDeltaBlock(Common::BitStream *ss, uint8 *current, uint8 *previous, int pitch, + bool svq1DecodeDeltaBlock(Common::BitStream *ss, byte *current, byte *previous, int pitch, Common::Point *motion, int x, int y); + + void putPixels8C(byte *block, const byte *pixels, int lineSize, int h); + void putPixels8L2(byte *dst, const byte *src1, const byte *src2, int dstStride, int srcStride1, int srcStride2, int h); + void putPixels8X2C(byte *block, const byte *pixels, int lineSize, int h); + void putPixels8Y2C(byte *block, const byte *pixels, int lineSize, int h); + void putPixels8XY2C(byte *block, const byte *pixels, int lineSize, int h); + void putPixels16C(byte *block, const byte *pixels, int lineSize, int h); + void putPixels16X2C(byte *block, const byte *pixels, int lineSize, int h); + void putPixels16Y2C(byte *block, const byte *pixels, int lineSize, int h); + void putPixels16XY2C(byte *block, const byte *pixels, int lineSize, int h); }; } // End of namespace Video diff --git a/video/codecs/svq1_cb.h b/video/codecs/svq1_cb.h index f764de048c..f9a8c54e40 100644 --- a/video/codecs/svq1_cb.h +++ b/video/codecs/svq1_cb.h @@ -20,6 +20,9 @@ * */ +// These tables are modified from their FFmpeg counterparts so that +// they work on both little and big endian systems. + #ifndef VIDEO_CODECS_SVQ1_CB_H #define VIDEO_CODECS_SVQ1_CB_H diff --git a/video/codecs/svq1_vlc.h b/video/codecs/svq1_vlc.h index eb70eb582e..5fb10981f7 100644 --- a/video/codecs/svq1_vlc.h +++ b/video/codecs/svq1_vlc.h @@ -20,6 +20,9 @@ * */ +// These tables are modified versions of the FFmpeg ones so that they +// will work with our BitStream class directly. + #ifndef VIDEO_CODECS_SVQ1_VLC_H #define VIDEO_CODECS_SVQ1_VLC_H diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp index 52e18064c1..df839610a1 100644 --- a/video/qt_decoder.cpp +++ b/video/qt_decoder.cpp @@ -46,9 +46,8 @@ #include "video/codecs/qtrle.h" #include "video/codecs/rpza.h" #include "video/codecs/smc.h" -#include "video/codecs/svq1.h" #include "video/codecs/cdtoons.h" - +#include "video/codecs/svq1.h" namespace Video { |