diff options
Diffstat (limited to 'video/codecs/svq1.cpp')
-rw-r--r-- | video/codecs/svq1.cpp | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/video/codecs/svq1.cpp b/video/codecs/svq1.cpp index eba0c90305..57e84968a3 100644 --- a/video/codecs/svq1.cpp +++ b/video/codecs/svq1.cpp @@ -180,28 +180,29 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st frameData.skip(8); } - int yWidth = ALIGN(_frameWidth, 16); - int yHeight = ALIGN(_frameHeight, 16); - int uvWidth = ALIGN(yWidth / 4, 16); - int uvHeight = ALIGN(yHeight / 4, 16); + uint yWidth = ALIGN(_frameWidth, 16); + uint yHeight = ALIGN(_frameHeight, 16); + uint uvWidth = ALIGN(yWidth / 4, 16); + uint uvHeight = ALIGN(yHeight / 4, 16); + uint uvPitch = uvWidth + 4; // we need at least one extra column and pitch must be divisible by 4 byte *current[3]; // Decode Y, U and V component planes for (int i = 0; i < 3; i++) { - int width, height; + uint width, height, pitch; if (i == 0) { width = yWidth; height = yHeight; + pitch = width; current[i] = new byte[width * height]; } else { width = uvWidth; height = uvHeight; + pitch = uvPitch; - // Add an extra row's worth of data to not go out-of-bounds in the - // color conversion. Then fill that with "empty" data. - current[i] = new byte[width * (height + 1)]; - memset(current[i] + width * height, 0x80, width); + // Add an extra row here. See below for more information. + current[i] = new byte[pitch * (height + 1)]; } if (frameType == 0) { // I Frame @@ -209,12 +210,12 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st byte *currentP = current[i]; for (uint16 y = 0; y < height; y += 16) { for (uint16 x = 0; x < width; x += 16) { - if (!svq1DecodeBlockIntra(&frameData, ¤tP[x], width)) { + if (!svq1DecodeBlockIntra(&frameData, ¤tP[x], pitch)) { warning("svq1DecodeBlockIntra decode failure"); return _surface; } } - currentP += 16 * width; + currentP += 16 * pitch; } } else { // Delta frame (P or B) @@ -222,9 +223,9 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st // Prediction Motion Vector Common::Point *pmv = new Common::Point[(width / 8) + 3]; - byte *previous; + byte *previous = 0; if (frameType == 2) { // B Frame - warning("B Frame not supported currently"); + error("SVQ1 Video: B Frames not supported"); //previous = _next[i]; } else { previous = _last[i]; @@ -233,7 +234,7 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st byte *currentP = current[i]; for (uint16 y = 0; y < height; y += 16) { for (uint16 x = 0; x < width; x += 16) { - if (!svq1DecodeDeltaBlock(&frameData, ¤tP[x], previous, width, pmv, x, y)) { + if (!svq1DecodeDeltaBlock(&frameData, ¤tP[x], previous, pitch, pmv, x, y)) { warning("svq1DecodeDeltaBlock decode failure"); return _surface; } @@ -241,7 +242,7 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st pmv[0].x = pmv[0].y = 0; - currentP += 16 * width; + currentP += 16 * pitch; } delete[] pmv; @@ -256,7 +257,21 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st _surface->h = _height; } - convertYUV410ToRGB(_surface, current[0], current[1], current[2], yWidth, yHeight, yWidth, uvWidth); + // We need to massage the chrominance data a bit to be able to be used by the converter + // Since the thing peeks at values one column and one row beyond the data, we need to fill it in + + // First, fill in the column-after-last with the last column's value + for (uint i = 0; i < uvHeight; i++) { + current[1][i * uvPitch + uvWidth] = current[1][i * uvPitch + uvWidth - 1]; + current[2][i * uvPitch + uvWidth] = current[2][i * uvPitch + uvWidth - 1]; + } + + // Then, copy the last row to the one after the last row + memcpy(current[1] + uvHeight * uvPitch, current[1] + (uvHeight - 1) * uvPitch, uvWidth + 1); + memcpy(current[2] + uvHeight * uvPitch, current[2] + (uvHeight - 1) * uvPitch, uvWidth + 1); + + // Finally, actually do the conversion ;) + YUVToRGBMan.convert410(_surface, Graphics::YUVToRGBManager::kScaleFull, current[0], current[1], current[2], yWidth, yHeight, yWidth, uvPitch); // Store the current surfaces for later and free the old ones for (int i = 0; i < 3; i++) { @@ -317,7 +332,7 @@ bool SVQ1Decoder::svq1DecodeBlockIntra(Common::BitStream *s, byte *pixels, int p for (uint y = 0; y < height; y++) memset(&dst[y * (pitch / 4)], mean, width); } else { - const uint32 *codebook = s_svq1IntraCodebooks[level]; + const uint32 *codebook = (const uint32 *)s_svq1IntraCodebooks[level]; uint32 bitCache = s->getBits(stages * 4); // calculate codebook entries for this vector @@ -336,7 +351,7 @@ bool SVQ1Decoder::svq1DecodeBlockIntra(Common::BitStream *s, byte *pixels, int p // add codebook entries to vector for (int j = 0; j < stages; j++) { - n3 = codebook[entries[j]] ^ 0x80808080; + n3 = READ_UINT32(&codebook[entries[j]]) ^ 0x80808080; n1 += (n3 & 0xFF00FF00) >> 8; n2 += n3 & 0x00FF00FF; } @@ -409,7 +424,7 @@ bool SVQ1Decoder::svq1DecodeBlockNonIntra(Common::BitStream *s, byte *pixels, in } int mean = _interMean->getSymbol(*s) - 256; - const uint32 *codebook = s_svq1InterCodebooks[level]; + const uint32 *codebook = (const uint32 *)s_svq1InterCodebooks[level]; uint32 bitCache = s->getBits(stages * 4); // calculate codebook entries for this vector @@ -430,7 +445,7 @@ bool SVQ1Decoder::svq1DecodeBlockNonIntra(Common::BitStream *s, byte *pixels, in // add codebook entries to vector for (int j = 0; j < stages; j++) { - n3 = codebook[entries[j]] ^ 0x80808080; + n3 = READ_UINT32(&codebook[entries[j]]) ^ 0x80808080; n1 += (n3 & 0xFF00FF00) >> 8; n2 += n3 & 0x00FF00FF; } |