aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Hoops2012-04-07 00:36:19 -0400
committerD G Turner2012-04-08 03:29:48 +0100
commit8bf8a08048f20ad7a831564aaa384b8bcc1beb24 (patch)
tree952661a4c9fe1fc5b93dddaa83936d26e04e7ef4
parent95d7c012d6635ac8124d74aeacfb6d52fc2d7ea0 (diff)
downloadscummvm-rg350-8bf8a08048f20ad7a831564aaa384b8bcc1beb24.tar.gz
scummvm-rg350-8bf8a08048f20ad7a831564aaa384b8bcc1beb24.tar.bz2
scummvm-rg350-8bf8a08048f20ad7a831564aaa384b8bcc1beb24.zip
VIDEO: Fix SVQ1 plane pitch
All the Myst intro videos now decode correctly
-rw-r--r--video/codecs/svq1.cpp78
1 files changed, 27 insertions, 51 deletions
diff --git a/video/codecs/svq1.cpp b/video/codecs/svq1.cpp
index 9d2faaa243..3844213797 100644
--- a/video/codecs/svq1.cpp
+++ b/video/codecs/svq1.cpp
@@ -89,6 +89,8 @@ SVQ1Decoder::~SVQ1Decoder() {
}
}
+#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1))
+
const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *stream) {
debug(1, "SVQ1Decoder::decodeImage()");
@@ -200,14 +202,6 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st
}
debug(1, " frameWidth: %d", _frameWidth);
debug(1, " frameHeight: %d", _frameHeight);
-
- // Now we'll create the surface
- if (!_surface) {
- _surface = new Graphics::Surface();
- _surface->create(_frameWidth, _frameHeight, g_system->getScreenFormat());
- _surface->w = _width;
- _surface->h = _height;
- }
} else if (frameType == 2) { // B Frame
warning("B Frames not supported by SVQ1 decoder");
return _surface;
@@ -246,63 +240,37 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st
}
}
+ int yWidth = FFALIGN(_frameWidth, 16);
+ int yHeight = FFALIGN(_frameHeight, 16);
+ int uvWidth = FFALIGN(yWidth / 4, 16);
+ int uvHeight = FFALIGN(yHeight / 4, 16);
+
byte *current[3];
- // FIXME - Added extra _width of 16px blocks to stop out of
- // range access causing crashes. Need to correct code...
- current[0] = new byte[_frameWidth * _frameHeight + (_frameWidth * 16)];
- current[1] = new byte[(_frameWidth / 4) * (_frameHeight / 4) + (_frameWidth / 4 * 16)];
- current[2] = new byte[(_frameWidth / 4) * (_frameHeight / 4) + (_frameWidth / 4 * 16)];
// Decode Y, U and V component planes
for (int i = 0; i < 3; i++) {
- int linesize, width, height;
+ int 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 = _frameWidth;
+ width = yWidth;
+ height = yHeight;
} 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 = _frameWidth / 4;
+ width = uvWidth;
+ height = uvHeight;
}
+ current[i] = new byte[width * height];
+
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 (svq1DecodeBlockIntra(&frameData, &currentP[x], linesize)) {
+ if (svq1DecodeBlockIntra(&frameData, &currentP[x], width)) {
warning("svq1DecodeBlockIntra decode failure");
return _surface;
}
}
- currentP += 16 * linesize;
+ currentP += 16 * width;
}
} else {
// Delta frame (P or B)
@@ -320,7 +288,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, &currentP[x], previous, linesize, pmv, x, y)) {
+ if (svq1DecodeDeltaBlock(&frameData, &currentP[x], previous, width, pmv, x, y)) {
warning("svq1DecodeDeltaBlock decode failure");
return _surface;
}
@@ -328,13 +296,21 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st
pmv[0].x = pmv[0].y = 0;
- currentP += 16*linesize;
+ currentP += 16*width;
}
delete[] pmv;
}
}
- convertYUV410ToRGB(_surface, current[0], current[1], current[2], _frameWidth, _frameHeight, _frameWidth, _frameWidth / 4);
+ // Now we'll create the surface
+ if (!_surface) {
+ _surface = new Graphics::Surface();
+ _surface->create(yWidth, yHeight, g_system->getScreenFormat());
+ _surface->w = _width;
+ _surface->h = _height;
+ }
+
+ convertYUV410ToRGB(_surface, current[0], current[1], current[2], yWidth, yHeight, yWidth, uvWidth);
for (int i = 0; i < 3; i++) {
delete[] _last[i];