mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-17 02:24:07 +02:00
#129 implementation of @Arsunt approach for Escape-130 decoder
This commit is contained in:
116
src/video.h
116
src/video.h
@@ -176,59 +176,42 @@ struct Video {
|
|||||||
a = 255;
|
a = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetYCbCr(int32 Y, int32 Cb, int32 Cr) {
|
static void YCbCr_T871_420(int32 Y0, int32 Y1, int32 Y2, int32 Y3, int32 Cb, int32 Cr, int32 F, Color32 &C0, Color32 &C1, Color32 &C2, Color32 &C3) {
|
||||||
Y = max(0, 1191 * (Y - 16));
|
static const Color32 dither[8] = {
|
||||||
Cb -= 128;
|
0x00000600, 0x00060006, 0x00040204, 0x00020402,
|
||||||
Cr -= 128;
|
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
r = clamp((Y + 1836 * Cr) >> 10, 0, 255);
|
};
|
||||||
g = clamp((Y - 547 * Cr - 218 * Cb) >> 10, 0, 255);
|
|
||||||
b = clamp((Y + 2165 * Cb) >> 10, 0, 255);
|
|
||||||
a = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetYCbCrPSX(int32 Y, int32 Cb, int32 Cr) {
|
ASSERT(F < 5);
|
||||||
int32 R = ((91893 * Cr) >> 16);
|
|
||||||
int32 G = ((-(22525 * Cb) - (46812 * Cr)) >> 16);
|
|
||||||
int32 B = ((116224 * Cb) >> 16);
|
|
||||||
|
|
||||||
Y += 128;
|
// Y[0..3] += 128 <-> RGB += 128
|
||||||
r = clamp(Y + R, 0, 255);
|
int32 R = (( 91881 * Cr ) >> 16);
|
||||||
g = clamp(Y + G, 0, 255);
|
int32 G = -(( 22550 * Cb + 46799 * Cr ) >> 16);
|
||||||
b = clamp(Y + B, 0, 255);
|
int32 B = (( 116129 * Cb ) >> 16);
|
||||||
a = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const Color32 *d = &dither[F];
|
||||||
|
|
||||||
void SetYUV(int32 Y, int32 U, int32 V) {
|
C0.r = clamp(Y0 + R + d->r, 0, 255);
|
||||||
r = clamp(Y + (74698 * V >> 16), 0, 255);
|
C0.g = clamp(Y0 + G + d->g, 0, 255);
|
||||||
g = clamp(Y - ((25863 * U + 38049 * V) >> 16), 0, 255);
|
C0.b = clamp(Y0 + B + d->b, 0, 255);
|
||||||
b = clamp(Y + (133174 * U >> 16), 0, 255);
|
|
||||||
a = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void YCbCr_420_PSX(int32 Y0, int32 Y1, int32 Y2, int32 Y3, int32 Cb, int32 Cr, Color32 &C0, Color32 &C1, Color32 &C2, Color32 &C3) {
|
|
||||||
int32 R = ((91893 * Cr) >> 16) + 128;
|
|
||||||
int32 G = ((-(22525 * Cb) - (46812 * Cr)) >> 16) + 128;
|
|
||||||
int32 B = ((116224 * Cb) >> 16) + 128;
|
|
||||||
|
|
||||||
C0.r = clamp(Y0 + R, 0, 255);
|
|
||||||
C0.g = clamp(Y0 + G, 0, 255);
|
|
||||||
C0.b = clamp(Y0 + B, 0, 255);
|
|
||||||
C0.a = 255;
|
C0.a = 255;
|
||||||
|
d++;
|
||||||
|
|
||||||
C1.r = clamp(Y1 + R, 0, 255);
|
C1.r = clamp(Y1 + R + d->r, 0, 255);
|
||||||
C1.g = clamp(Y1 + G, 0, 255);
|
C1.g = clamp(Y1 + G + d->g, 0, 255);
|
||||||
C1.b = clamp(Y1 + B, 0, 255);
|
C1.b = clamp(Y1 + B + d->b, 0, 255);
|
||||||
C1.a = 255;
|
C1.a = 255;
|
||||||
|
d++;
|
||||||
|
|
||||||
C2.r = clamp(Y2 + R, 0, 255);
|
C2.r = clamp(Y2 + R + d->r, 0, 255);
|
||||||
C2.g = clamp(Y2 + G, 0, 255);
|
C2.g = clamp(Y2 + G + d->g, 0, 255);
|
||||||
C2.b = clamp(Y2 + B, 0, 255);
|
C2.b = clamp(Y2 + B + d->b, 0, 255);
|
||||||
C2.a = 255;
|
C2.a = 255;
|
||||||
|
d++;
|
||||||
|
|
||||||
C3.r = clamp(Y3 + R, 0, 255);
|
C3.r = clamp(Y3 + R + d->r, 0, 255);
|
||||||
C3.g = clamp(Y3 + G, 0, 255);
|
C3.g = clamp(Y3 + G + d->g, 0, 255);
|
||||||
C3.b = clamp(Y3 + B, 0, 255);
|
C3.b = clamp(Y3 + B + d->b, 0, 255);
|
||||||
C3.a = 255;
|
C3.a = 255;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -312,8 +295,9 @@ struct Video {
|
|||||||
memset(nextFrame, 0, width * height * sizeof(uint32));
|
memset(nextFrame, 0, width * height * sizeof(uint32));
|
||||||
break;
|
break;
|
||||||
case 130 :
|
case 130 :
|
||||||
prevFrame = new uint8[width * height * 3 / 2];
|
// Y[w*h], Cb[w*h/4], Cr[w*h/4], F[w*h/4]
|
||||||
nextFrame = new uint8[width * height * 3 / 2];
|
prevFrame = new uint8[width * height * 7 / 4];
|
||||||
|
nextFrame = new uint8[width * height * 7 / 4];
|
||||||
lumaFrame = new uint8[width * height / 4];
|
lumaFrame = new uint8[width * height / 4];
|
||||||
memset(prevFrame, 0, width * height);
|
memset(prevFrame, 0, width * height);
|
||||||
memset(prevFrame + width * height, 16, width * height / 2);
|
memset(prevFrame + width * height, 16, width * height / 2);
|
||||||
@@ -625,16 +609,16 @@ struct Video {
|
|||||||
uint8 *data = new uint8[chunk.videoSize];
|
uint8 *data = new uint8[chunk.videoSize];
|
||||||
stream->raw(data, chunk.videoSize);
|
stream->raw(data, chunk.videoSize);
|
||||||
BitStream bs(data, chunk.videoSize);
|
BitStream bs(data, chunk.videoSize);
|
||||||
bs.data += 16; // skip 16 bytes
|
bs.data += 16; // skip 16 bytes (frame size, version, gamma/linear chroma flags etc.)
|
||||||
|
|
||||||
uint8 *lumaPtr = lumaFrame;
|
uint8 *lumaPtr = lumaFrame;
|
||||||
|
|
||||||
int skip = -1;
|
int skip = -1;
|
||||||
int bCount = width * height / 4;
|
int bCount = width * height / 4;
|
||||||
uint32 luma = 0, Y[4] = { 0 }, U = 16, V = 16;
|
uint32 luma = 0, Y[4] = { 0 }, U = 16, V = 16, F = 0;
|
||||||
|
|
||||||
uint8 *oY = prevFrame, *oU = oY + width * height, *oV = oU + width * height / 4;
|
uint8 *oY = prevFrame, *oU = oY + width * height, *oV = oU + width * height / 4, *oF = oV + width * height / 4;
|
||||||
uint8 *nY = nextFrame, *nU = nY + width * height, *nV = nU + width * height / 4;
|
uint8 *nY = nextFrame, *nU = nY + width * height, *nV = nU + width * height / 4, *nF = nV + width * height / 4;
|
||||||
|
|
||||||
for (int bIndex = 0; bIndex < bCount; bIndex++) {
|
for (int bIndex = 0; bIndex < bCount; bIndex++) {
|
||||||
if (skip == -1)
|
if (skip == -1)
|
||||||
@@ -647,6 +631,7 @@ struct Video {
|
|||||||
Y[3] = oY[width + 1];
|
Y[3] = oY[width + 1];
|
||||||
U = oU[0];
|
U = oU[0];
|
||||||
V = oV[0];
|
V = oV[0];
|
||||||
|
F = oF[0];
|
||||||
luma = *lumaPtr;
|
luma = *lumaPtr;
|
||||||
} else {
|
} else {
|
||||||
if (bs.readBit()) {
|
if (bs.readBit()) {
|
||||||
@@ -658,6 +643,7 @@ struct Video {
|
|||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
Y[i] = clamp(luma + offsetLUT[diff] * signLUT[sign][i], 0U, 63U);
|
Y[i] = clamp(luma + offsetLUT[diff] * signLUT[sign][i], 0U, 63U);
|
||||||
|
|
||||||
|
F = 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (bs.readBit())
|
if (bs.readBit())
|
||||||
@@ -665,6 +651,8 @@ struct Video {
|
|||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
Y[i] = luma;
|
Y[i] = luma;
|
||||||
|
|
||||||
|
F = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bs.readBit()) {
|
if (bs.readBit()) {
|
||||||
@@ -686,9 +674,10 @@ struct Video {
|
|||||||
nY[width + 1] = Y[3];
|
nY[width + 1] = Y[3];
|
||||||
nU[0] = U;
|
nU[0] = U;
|
||||||
nV[0] = V;
|
nV[0] = V;
|
||||||
|
nF[0] = F;
|
||||||
|
|
||||||
nY += 2; nU++; nV++;
|
nY += 2; nU++; nV++; nF++;
|
||||||
oY += 2; oU++; oV++;
|
oY += 2; oU++; oV++; oF++;
|
||||||
|
|
||||||
if (!(((bIndex + 1) * 2) % width)) {
|
if (!(((bIndex + 1) * 2) % width)) {
|
||||||
nY += width;
|
nY += width;
|
||||||
@@ -703,19 +692,19 @@ struct Video {
|
|||||||
nY = nextFrame;
|
nY = nextFrame;
|
||||||
nU = nY + width * height;
|
nU = nY + width * height;
|
||||||
nV = nU + width * height / 4;
|
nV = nU + width * height / 4;
|
||||||
|
nF = nV + width * height / 4;
|
||||||
|
|
||||||
Color32 *p = pixels;
|
for (int y = 0; y < height / 2; y++) {
|
||||||
for (int y = 0; y < height; y++) {
|
for (int x = 0; x < width / 2; x++) {
|
||||||
for (int x = 0; x < width; x++) {
|
int i = (y * width + x) * 2;
|
||||||
int Y = nY[y * width + x] << 2;
|
|
||||||
int U = chromaValueLUT[nU[x / 2]] - 128;
|
|
||||||
int V = chromaValueLUT[nV[x / 2]] - 128;
|
|
||||||
(p++)->SetYUV(Y, U, V);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y & 1) {
|
Color32::YCbCr_T871_420(nY[i] << 2, nY[i + 1] << 2, nY[i + width] << 2, nY[i + width + 1] << 2,
|
||||||
nU += width / 2;
|
chromaValueLUT[*nU] - 128, chromaValueLUT[*nV] - 128, *nF * 4,
|
||||||
nV += width / 2;
|
pixels[i], pixels[i + 1], pixels[i + width], pixels[i + width + 1]);
|
||||||
|
|
||||||
|
nU++;
|
||||||
|
nV++;
|
||||||
|
nF++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1084,7 +1073,8 @@ struct Video {
|
|||||||
|
|
||||||
int16 *b = block[(x < 8) ? ((y < 8) ? 2 : 4) : ((y < 8) ? 3 : 5)];
|
int16 *b = block[(x < 8) ? ((y < 8) ? 2 : 4) : ((y < 8) ? 3 : 5)];
|
||||||
|
|
||||||
Color32::YCbCr_420_PSX(b[j], b[j + 1], b[j + 8], b[j + 8 + 1], block[1][i], block[0][i], c[0], c[1], c[width], c[width + 1]);
|
Color32::YCbCr_T871_420(b[j] + 128, b[j + 1] + 128, b[j + 8] + 128, b[j + 8 + 1] + 128, block[1][i], block[0][i], 4,
|
||||||
|
c[0], c[1], c[width], c[width + 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user