aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--video/codecs/svq1.cpp551
-rw-r--r--video/codecs/svq1.h22
-rw-r--r--video/codecs/svq1_cb.h3
-rw-r--r--video/codecs/svq1_vlc.h3
-rw-r--r--video/qt_decoder.cpp3
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 {