mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-17 18:36:43 +02:00
#129 TR2 & TR3 FMVs support (Escape-130)
This commit is contained in:
@@ -561,9 +561,10 @@ namespace TR {
|
|||||||
if (id == LVL_TR2_VENICE || id == LVL_TR2_CUT_2 || id == LVL_TR2_PLATFORM || id == LVL_TR2_CUT_3 || id == LVL_TR2_UNWATER ||
|
if (id == LVL_TR2_VENICE || id == LVL_TR2_CUT_2 || id == LVL_TR2_PLATFORM || id == LVL_TR2_CUT_3 || id == LVL_TR2_UNWATER ||
|
||||||
id == LVL_TR2_KEEL || id == LVL_TR2_LIVING || id == LVL_TR2_DECK || id == LVL_TR2_CATACOMB || id == LVL_TR2_ICECAVE ||
|
id == LVL_TR2_KEEL || id == LVL_TR2_LIVING || id == LVL_TR2_DECK || id == LVL_TR2_CATACOMB || id == LVL_TR2_ICECAVE ||
|
||||||
id == LVL_TR2_CUT_4 || id == LVL_TR2_XIAN || id == LVL_TR2_HOUSE) {
|
id == LVL_TR2_CUT_4 || id == LVL_TR2_XIAN || id == LVL_TR2_HOUSE) {
|
||||||
strcpy(dst, LEVEL_INFO[id].name);
|
char buf[64];
|
||||||
String::toLower(dst);
|
strcpy(buf, LEVEL_INFO[id].name);
|
||||||
sprintf(dst, "DATA/%s.TR2", dst);
|
String::toLower(buf);
|
||||||
|
sprintf(dst, "DATA/%s.TR2", buf);
|
||||||
} else if (id == LVL_TR2_TITLE) {
|
} else if (id == LVL_TR2_TITLE) {
|
||||||
sprintf(dst, "DATA/%s.tr2", LEVEL_INFO[id].name);
|
sprintf(dst, "DATA/%s.tr2", LEVEL_INFO[id].name);
|
||||||
} else if (id == LVL_TR2_EMPRTOMB) {
|
} else if (id == LVL_TR2_EMPRTOMB) {
|
||||||
@@ -912,6 +913,18 @@ namespace TR {
|
|||||||
case LVL_TR2_HOUSE :
|
case LVL_TR2_HOUSE :
|
||||||
CHECK_FILE("fmv/END.RPL");
|
CHECK_FILE("fmv/END.RPL");
|
||||||
return "video/2/END.RPL";
|
return "video/2/END.RPL";
|
||||||
|
case LVL_TR3_TITLE :
|
||||||
|
CHECK_FILE("fmv/Intr_Eng.rpl");
|
||||||
|
return "video/3/Intr_Eng.rpl";
|
||||||
|
case LVL_TR3_SHORE :
|
||||||
|
CHECK_FILE("fmv/Sail_Eng.rpl");
|
||||||
|
return "video/3/Sail_Eng.rpl";
|
||||||
|
case LVL_TR3_ANTARC :
|
||||||
|
CHECK_FILE("fmv/Crsh_Eng.rpl");
|
||||||
|
return "video/3/Crsh_Eng.rpl";
|
||||||
|
case LVL_TR3_STPAUL :
|
||||||
|
CHECK_FILE("fmv/Endgame.rpl");
|
||||||
|
return "video/3/Endgame.rpl";
|
||||||
// TR3
|
// TR3
|
||||||
default : return NULL;
|
default : return NULL;
|
||||||
}
|
}
|
||||||
|
25
src/sound.h
25
src/sound.h
@@ -314,33 +314,30 @@ namespace Sound {
|
|||||||
|
|
||||||
int16 getSample(uint8 n, State &state) {
|
int16 getSample(uint8 n, State &state) {
|
||||||
static int indexLUT[] = {
|
static int indexLUT[] = {
|
||||||
-1, -1, -1, -1, 2, 4, 6, 8
|
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int stepLUT[] = {
|
static int stepLUT[] = {
|
||||||
7, 8, 9, 10, 11, 12, 13, 14,
|
7, 8, 9, 10, 11, 12, 13, 14,
|
||||||
16, 17, 19, 21, 23, 25, 28, 31,
|
16, 17, 19, 21, 23, 25, 28, 31,
|
||||||
34, 37, 41, 45, 50, 55, 60, 66,
|
34, 37, 41, 45, 50, 55, 60, 66,
|
||||||
73, 80, 88, 97, 107, 118, 130, 143,
|
73, 80, 88, 97, 107, 118, 130, 143,
|
||||||
157, 173, 190, 209, 230, 253, 279, 307,
|
157, 173, 190, 209, 230, 253, 279, 307,
|
||||||
337, 371, 408, 449, 494, 544, 598, 658,
|
337, 371, 408, 449, 494, 544, 598, 658,
|
||||||
724, 796, 876, 963, 1060, 1166, 1282, 1411,
|
724, 796, 876, 963, 1060, 1166, 1282, 1411,
|
||||||
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
|
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
|
||||||
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
|
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
|
||||||
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
|
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
|
||||||
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
|
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
|
||||||
32767
|
32767
|
||||||
};
|
};
|
||||||
|
|
||||||
int step = stepLUT[state.idx];
|
int step = stepLUT[state.idx];
|
||||||
|
int idx = n & 7;
|
||||||
|
|
||||||
state.idx += indexLUT[n & 7];
|
state.idx = clamp(state.idx + indexLUT[idx], 0, 88);
|
||||||
state.idx = clamp(state.idx, 0, 88);
|
|
||||||
|
|
||||||
int diff = step >> 3;
|
int diff = (2 * idx + 1) * step >> 3;
|
||||||
if (n & 1) diff += step >> 2;
|
|
||||||
if (n & 2) diff += step >> 1;
|
|
||||||
if (n & 4) diff += step;
|
|
||||||
|
|
||||||
if (n & 8) {
|
if (n & 8) {
|
||||||
state.amp -= diff;
|
state.amp -= diff;
|
||||||
@@ -359,8 +356,8 @@ namespace Sound {
|
|||||||
uint8 n;
|
uint8 n;
|
||||||
stream->read(n);
|
stream->read(n);
|
||||||
|
|
||||||
int a = getSample(n & 0x0F, state[0]);
|
int a = getSample(n >> 4, state[0]);
|
||||||
int b = getSample(n >> 4, state[1 % channels]);
|
int b = getSample(n & 0x0F, state[1 % channels]);
|
||||||
|
|
||||||
Frame frame;
|
Frame frame;
|
||||||
if (channels == 2) {
|
if (channels == 2) {
|
||||||
@@ -600,7 +597,7 @@ namespace Sound {
|
|||||||
} else if (type == FOURCC("data")) {
|
} else if (type == FOURCC("data")) {
|
||||||
if (waveFmt.format == 1) decoder = new PCM(stream, waveFmt.channels, waveFmt.samplesPerSec, size, waveFmt.sampleBits);
|
if (waveFmt.format == 1) decoder = new PCM(stream, waveFmt.channels, waveFmt.samplesPerSec, size, waveFmt.sampleBits);
|
||||||
#ifdef DECODE_ADPCM
|
#ifdef DECODE_ADPCM
|
||||||
if (waveFmt.format == 2) decoder = new ADPCM(stream, waveFmt.channels, size, waveFmt.block, waveFmt.samplesPerSec);
|
if (waveFmt.format == 2) decoder = new ADPCM(stream, waveFmt.channels, waveFmt.samplesPerSec, size, waveFmt.block);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
|
262
src/video.h
262
src/video.h
@@ -7,6 +7,35 @@
|
|||||||
|
|
||||||
struct Video {
|
struct Video {
|
||||||
|
|
||||||
|
union Color32 {
|
||||||
|
uint32 value;
|
||||||
|
struct { uint8 r, g, b, a; };
|
||||||
|
|
||||||
|
void SetRGB15(uint16 v) {
|
||||||
|
r = (v & 0x7C00) >> 7;
|
||||||
|
g = (v & 0x03E0) >> 2;
|
||||||
|
b = (v & 0x001F) << 3;
|
||||||
|
a = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetYCbCr(int32 Y, int32 Cb, int32 Cr) {
|
||||||
|
Y = max(0, 1191 * (Y - 16));
|
||||||
|
Cb -= 128;
|
||||||
|
Cr -= 128;
|
||||||
|
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 SetYUV(int32 Y, int32 U, int32 V) {
|
||||||
|
r = clamp(Y + (74698 * V >> 16), 0, 255);
|
||||||
|
g = clamp(Y - ((25863 * U + 38049 * V) >> 16), 0, 255);
|
||||||
|
b = clamp(Y + (133174 * U >> 16), 0, 255);
|
||||||
|
a = 255;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Decoder : Sound::Decoder {
|
struct Decoder : Sound::Decoder {
|
||||||
int width, height, fps;
|
int width, height, fps;
|
||||||
|
|
||||||
@@ -25,7 +54,7 @@ struct Video {
|
|||||||
|
|
||||||
Sound::Decoder *audioDecoder;
|
Sound::Decoder *audioDecoder;
|
||||||
|
|
||||||
uint32 *prevFrame, *nextFrame;
|
uint8 *prevFrame, *nextFrame, *lumaFrame;
|
||||||
|
|
||||||
struct Chunk {
|
struct Chunk {
|
||||||
int offset;
|
int offset;
|
||||||
@@ -47,7 +76,7 @@ struct Video {
|
|||||||
MacroBlock *blocks;
|
MacroBlock *blocks;
|
||||||
} codebook[3];
|
} codebook[3];
|
||||||
|
|
||||||
Escape(Stream *stream) : Decoder(stream), audioDecoder(NULL), chunks(NULL) {
|
Escape(Stream *stream) : Decoder(stream), audioDecoder(NULL), prevFrame(NULL), nextFrame(NULL), lumaFrame(NULL), chunks(NULL) {
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
skipLine();
|
skipLine();
|
||||||
|
|
||||||
@@ -78,10 +107,24 @@ struct Video {
|
|||||||
chunks[i].audioSize = readValue();
|
chunks[i].audioSize = readValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
prevFrame = new uint32[width * height];
|
switch (vfmt) {
|
||||||
nextFrame = new uint32[width * height];
|
case 124 :
|
||||||
memset(prevFrame, 0, width * height * sizeof(uint32));
|
prevFrame = new uint8[width * height * 4];
|
||||||
memset(nextFrame, 0, width * height * sizeof(uint32));
|
nextFrame = new uint8[width * height * 4];
|
||||||
|
memset(prevFrame, 0, width * height * sizeof(uint32));
|
||||||
|
memset(nextFrame, 0, width * height * sizeof(uint32));
|
||||||
|
break;
|
||||||
|
case 130 :
|
||||||
|
prevFrame = new uint8[width * height * 3 / 2];
|
||||||
|
nextFrame = new uint8[width * height * 3 / 2];
|
||||||
|
lumaFrame = new uint8[width * height / 4];
|
||||||
|
memset(prevFrame, 0, width * height);
|
||||||
|
memset(prevFrame + width * height, 16, width * height / 2);
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
LOG("! unsupported Escape codec version (%d)\n", vfmt);
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
codebook[0].blocks =
|
codebook[0].blocks =
|
||||||
codebook[1].blocks =
|
codebook[1].blocks =
|
||||||
@@ -110,6 +153,7 @@ struct Video {
|
|||||||
delete[] codebook[2].blocks;
|
delete[] codebook[2].blocks;
|
||||||
delete[] prevFrame;
|
delete[] prevFrame;
|
||||||
delete[] nextFrame;
|
delete[] nextFrame;
|
||||||
|
delete[] lumaFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skipLine() {
|
void skipLine() {
|
||||||
@@ -133,6 +177,28 @@ struct Video {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getSkip124(BitStream &bs) {
|
||||||
|
int value;
|
||||||
|
|
||||||
|
if ((value = bs.read(1)) != 1 ||
|
||||||
|
(value += bs.read(3)) != 8 ||
|
||||||
|
(value += bs.read(7)) != 135)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
return value + bs.read(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getSkip130(BitStream &bs) {
|
||||||
|
int value;
|
||||||
|
|
||||||
|
if (value = bs.read(1)) return 0;
|
||||||
|
if (value = bs.read(3)) return value;
|
||||||
|
if (value = bs.read(8)) return value + 7;
|
||||||
|
if (value = bs.read(15)) return value + 262;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void copySuperBlock(uint32 *dst, int dstWidth, uint32 *src, int srcWidth) {
|
void copySuperBlock(uint32 *dst, int dstWidth, uint32 *src, int srcWidth) {
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
memcpy(dst, src, 8 * sizeof(uint32));
|
memcpy(dst, src, 8 * sizeof(uint32));
|
||||||
@@ -141,24 +207,6 @@ struct Video {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getSkipCount(BitStream &bs) {
|
|
||||||
int value;
|
|
||||||
|
|
||||||
value = bs.read(1);
|
|
||||||
if (!value)
|
|
||||||
return value;
|
|
||||||
|
|
||||||
value += bs.read(3);
|
|
||||||
if (value != (1 + ((1 << 3) - 1)))
|
|
||||||
return value;
|
|
||||||
|
|
||||||
value += bs.read(7);
|
|
||||||
if (value != (1 + ((1 << 3) - 1)) + ((1 << 7) - 1))
|
|
||||||
return value;
|
|
||||||
|
|
||||||
return value + bs.read(12);
|
|
||||||
}
|
|
||||||
|
|
||||||
void decodeMacroBlock(BitStream &bs, MacroBlock &mb, int &cbIndex, int sbIndex) {
|
void decodeMacroBlock(BitStream &bs, MacroBlock &mb, int &cbIndex, int sbIndex) {
|
||||||
int value = bs.read(1);
|
int value = bs.read(1);
|
||||||
if (value) {
|
if (value) {
|
||||||
@@ -184,20 +232,6 @@ struct Video {
|
|||||||
dst[9] = mb.pixels[3];
|
dst[9] = mb.pixels[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
union Color32 {
|
|
||||||
uint32 value;
|
|
||||||
struct { uint8 r, g, b, a; };
|
|
||||||
|
|
||||||
Color32() {}
|
|
||||||
|
|
||||||
Color32(uint16 v) {
|
|
||||||
r = (v & 0x7C00) >> 7;
|
|
||||||
g = (v & 0x03E0) >> 2;
|
|
||||||
b = (v & 0x001F) << 3;
|
|
||||||
a = 255;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool decode(uint8 *frame) {
|
bool decode(uint8 *frame) {
|
||||||
if (curVideoChunk >= chunksCount)
|
if (curVideoChunk >= chunksCount)
|
||||||
return false;
|
return false;
|
||||||
@@ -258,8 +292,9 @@ struct Video {
|
|||||||
|
|
||||||
for (uint32 j = 0; j < cb.size; j++) {
|
for (uint32 j = 0; j < cb.size; j++) {
|
||||||
uint8 mask = bs.read(4);
|
uint8 mask = bs.read(4);
|
||||||
Color32 cA = Color32(uint16(bs.read(15)));
|
Color32 cA, cB;
|
||||||
Color32 cB = Color32(uint16(bs.read(15)));
|
cA.SetRGB15(bs.read(15));
|
||||||
|
cB.SetRGB15(bs.read(15));
|
||||||
|
|
||||||
if (cA.value != cB.value && (mask == 6 || mask == 9) && // check for 0101 or 1010 mask
|
if (cA.value != cB.value && (mask == 6 || mask == 9) && // check for 0101 or 1010 mask
|
||||||
abs(int(cA.r) - int(cB.r)) <= 8 &&
|
abs(int(cA.r) - int(cB.r)) <= 8 &&
|
||||||
@@ -292,13 +327,13 @@ struct Video {
|
|||||||
for (int sbIndex = 0; sbIndex < sbCount; sbIndex++) {
|
for (int sbIndex = 0; sbIndex < sbCount; sbIndex++) {
|
||||||
int sbLine = width / 8;
|
int sbLine = width / 8;
|
||||||
int sbOffset = ((sbIndex / sbLine) * width + (sbIndex % sbLine)) * 8;
|
int sbOffset = ((sbIndex / sbLine) * width + (sbIndex % sbLine)) * 8;
|
||||||
uint32 *src = prevFrame + sbOffset;
|
uint32 *src = (uint32*)prevFrame + sbOffset;
|
||||||
uint32 *dst = nextFrame + sbOffset;
|
uint32 *dst = (uint32*)nextFrame + sbOffset;
|
||||||
|
|
||||||
uint16 multiMask = 0;
|
uint16 multiMask = 0;
|
||||||
|
|
||||||
if (skip == -1)
|
if (skip == -1)
|
||||||
skip = getSkipCount(bs);
|
skip = getSkip124(bs);
|
||||||
|
|
||||||
if (skip) {
|
if (skip) {
|
||||||
copySuperBlock(dst, width, src, width);
|
copySuperBlock(dst, width, src, width);
|
||||||
@@ -345,13 +380,152 @@ struct Video {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool decode130(uint8 *frame) {
|
bool decode130(uint8 *frame) {
|
||||||
|
|
||||||
|
static const uint8 offsetLUT[] = {
|
||||||
|
2, 4, 10, 20
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int8 signLUT[64][4] = {
|
||||||
|
{ 0, 0, 0, 0 }, { -1, 1, 0, 0 }, { 1, -1, 0, 0 }, { -1, 0, 1, 0 },
|
||||||
|
{ -1, 1, 1, 0 }, { 0, -1, 1, 0 }, { 1, -1, 1, 0 }, { -1, -1, 1, 0 },
|
||||||
|
{ 1, 0, -1, 0 }, { 0, 1, -1, 0 }, { 1, 1, -1, 0 }, { -1, 1, -1, 0 },
|
||||||
|
{ 1, -1, -1, 0 }, { -1, 0, 0, 1 }, { -1, 1, 0, 1 }, { 0, -1, 0, 1 },
|
||||||
|
{ 0, 0, 0, 0 }, { 1, -1, 0, 1 }, { -1, -1, 0, 1 }, { -1, 0, 1, 1 },
|
||||||
|
{ -1, 1, 1, 1 }, { 0, -1, 1, 1 }, { 1, -1, 1, 1 }, { -1, -1, 1, 1 },
|
||||||
|
{ 0, 0, -1, 1 }, { 1, 0, -1, 1 }, { -1, 0, -1, 1 }, { 0, 1, -1, 1 },
|
||||||
|
{ 1, 1, -1, 1 }, { -1, 1, -1, 1 }, { 0, -1, -1, 1 }, { 1, -1, -1, 1 },
|
||||||
|
{ 0, 0, 0, 0 }, { -1, -1, -1, 1 }, { 1, 0, 0, -1 }, { 0, 1, 0, -1 },
|
||||||
|
{ 1, 1, 0, -1 }, { -1, 1, 0, -1 }, { 1, -1, 0, -1 }, { 0, 0, 1, -1 },
|
||||||
|
{ 1, 0, 1, -1 }, { -1, 0, 1, -1 }, { 0, 1, 1, -1 }, { 1, 1, 1, -1 },
|
||||||
|
{ -1, 1, 1, -1 }, { 0, -1, 1, -1 }, { 1, -1, 1, -1 }, { -1, -1, 1, -1 },
|
||||||
|
{ 0, 0, 0, 0 }, { 1, 0, -1, -1 }, { 0, 1, -1, -1 }, { 1, 1, -1, -1 },
|
||||||
|
{ -1, 1, -1, -1 }, { 1, -1, -1, -1 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int8 lumaLUT[] = {
|
||||||
|
-4, -3, -2, -1, 1, 2, 3, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int8 chromaLUT[2][8] = {
|
||||||
|
{ 1, 1, 0, -1, -1, -1, 0, 1 },
|
||||||
|
{ 0, 1, 1, 1, 0, -1, -1, -1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8 chromaValueLUT[] = {
|
||||||
|
20, 28, 36, 44, 52, 60, 68, 76,
|
||||||
|
84, 92, 100, 106, 112, 116, 120, 124,
|
||||||
|
128, 132, 136, 140, 144, 150, 156, 164,
|
||||||
|
172, 180, 188, 196, 204, 212, 220, 228
|
||||||
|
};
|
||||||
|
|
||||||
|
Chunk &chunk = chunks[curVideoChunk++];
|
||||||
|
|
||||||
|
uint8 *data = new uint8[chunk.videoSize];
|
||||||
|
stream->raw(data, chunk.videoSize);
|
||||||
|
BitStream bs(data, chunk.videoSize);
|
||||||
|
bs.data += 16; // skip 16 bytes
|
||||||
|
|
||||||
|
uint8 *lumaPtr = lumaFrame;
|
||||||
|
|
||||||
|
int skip = -1;
|
||||||
|
int bCount = width * height / 4;
|
||||||
|
uint32 luma = 0, Y[4] = { 0 }, U = 16, V = 16;
|
||||||
|
|
||||||
|
uint8 *oY = prevFrame, *oU = oY + width * height, *oV = oU + width * height / 4;
|
||||||
|
uint8 *nY = nextFrame, *nU = nY + width * height, *nV = nU + width * height / 4;
|
||||||
|
|
||||||
|
for (int bIndex = 0; bIndex < bCount; bIndex++) {
|
||||||
|
if (skip == -1)
|
||||||
|
skip = getSkip130(bs);
|
||||||
|
|
||||||
|
if (skip) {
|
||||||
|
Y[0] = oY[0];
|
||||||
|
Y[1] = oY[1];
|
||||||
|
Y[2] = oY[width];
|
||||||
|
Y[3] = oY[width + 1];
|
||||||
|
U = oU[0];
|
||||||
|
V = oV[0];
|
||||||
|
luma = *lumaPtr;
|
||||||
|
} else {
|
||||||
|
if (bs.read(1)) {
|
||||||
|
uint32 sign = bs.read(6);
|
||||||
|
uint32 diff = bs.read(2);
|
||||||
|
|
||||||
|
luma = bs.read(5) * 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
Y[i] = clamp(luma + offsetLUT[diff] * signLUT[sign][i], 0U, 63U);
|
||||||
|
|
||||||
|
} else if (bs.read(1)) {
|
||||||
|
luma = bs.read(1) ? bs.read(6) : ((luma + lumaLUT[bs.read(3)]) & 63);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
Y[i] = luma;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs.read(1)) {
|
||||||
|
if (bs.read(1)) {
|
||||||
|
U = bs.read(5);
|
||||||
|
V = bs.read(5);
|
||||||
|
} else {
|
||||||
|
uint32 idx = bs.read(3);
|
||||||
|
U = (U + chromaLUT[0][idx]) & 31;
|
||||||
|
V = (V + chromaLUT[1][idx]) & 31;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*lumaPtr++ = luma;
|
||||||
|
|
||||||
|
nY[0] = Y[0];
|
||||||
|
nY[1] = Y[1];
|
||||||
|
nY[width] = Y[2];
|
||||||
|
nY[width + 1] = Y[3];
|
||||||
|
nU[0] = U;
|
||||||
|
nV[0] = V;
|
||||||
|
|
||||||
|
nY += 2; nU++; nV++;
|
||||||
|
oY += 2; oU++; oV++;
|
||||||
|
|
||||||
|
if (!(((bIndex + 1) * 2) % width)) {
|
||||||
|
nY += width;
|
||||||
|
oY += width;
|
||||||
|
}
|
||||||
|
|
||||||
|
skip--;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] data;
|
||||||
|
|
||||||
|
nY = nextFrame;
|
||||||
|
nU = nY + width * height;
|
||||||
|
nV = nU + width * height / 4;
|
||||||
|
|
||||||
|
Color32 *p = (Color32*)frame;
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
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) {
|
||||||
|
nU += width / 2;
|
||||||
|
nV += width / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(prevFrame, nextFrame);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int decode(Sound::Frame *frames, int count) {
|
virtual int decode(Sound::Frame *frames, int count) {
|
||||||
if (!audioDecoder) return 0;
|
if (!audioDecoder) return 0;
|
||||||
|
|
||||||
if (abs(curAudioChunk - curVideoChunk) > 1) { // sync with video chunk
|
if (bps != 4 && abs(curAudioChunk - curVideoChunk) > 1) { // sync with video chunk, doesn't work for IMA
|
||||||
curAudioChunk = curVideoChunk;
|
curAudioChunk = curVideoChunk;
|
||||||
curAudioPos = 0;
|
curAudioPos = 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user