diff options
| author | Matthew Hoops | 2012-01-09 14:52:06 -0500 | 
|---|---|---|
| committer | Willem Jan Palenstijn | 2012-02-23 22:48:18 +0100 | 
| commit | ee35d32a362d58891fedff9843867397f2d4497b (patch) | |
| tree | 4a7ab5d7868ab22aa515fb3c6ec7e3870d5228f5 | |
| parent | 8812f885bc95f0e4af05c333780eb77a8c2eaa19 (diff) | |
| download | scummvm-rg350-ee35d32a362d58891fedff9843867397f2d4497b.tar.gz scummvm-rg350-ee35d32a362d58891fedff9843867397f2d4497b.tar.bz2 scummvm-rg350-ee35d32a362d58891fedff9843867397f2d4497b.zip | |
VIDEO: Implement PSX stream v3 frame support
| -rw-r--r-- | video/psx_decoder.cpp | 166 | ||||
| -rw-r--r-- | video/psx_decoder.h | 17 | 
2 files changed, 127 insertions, 56 deletions
| diff --git a/video/psx_decoder.cpp b/video/psx_decoder.cpp index 4ed5a16294..a0705e8804 100644 --- a/video/psx_decoder.cpp +++ b/video/psx_decoder.cpp @@ -58,17 +58,53 @@ PSXStreamDecoder::PSXStreamDecoder(CDSpeed speed, uint32 frameCount) {  PSXStreamDecoder::~PSXStreamDecoder() {  	close();  	delete _surface; -	delete _huffman; +	delete _acHuffman; +	delete _dcHuffmanLuma; +	delete _dcHuffmanChroma;  } -#define CODE_COUNT 113 -#define HUFFVAL(z, a) ((z << 8) | a) +// Here are the codes/lengths/symbols that are used for decoding +// DC coefficients (version 3 frames only) + +#define DC_CODE_COUNT 9 +#define DC_HUFF_VAL(b, n, p) (((b) << 16) | ((n) << 8) | (p)) +#define GET_DC_BITS(x) ((x) >> 16) +#define GET_DC_NEG(x) ((int)(((x) >> 8) & 0xff)) +#define GET_DC_POS(x) ((int)((x) & 0xff)) + +static const uint32 s_huffmanDCChromaCodes[DC_CODE_COUNT] = { +	254, 126, 62, 30, 14, 6, 2, 1, 0 +}; + +static const byte s_huffmanDCChromaLengths[DC_CODE_COUNT] = { +	8, 7, 6, 5, 4, 3, 2, 2, 2 +}; + +static const uint32 s_huffmanDCLumaCodes[DC_CODE_COUNT] = { +	126, 62, 30, 14, 6, 5, 1, 0, 4 +}; + +static const byte s_huffmanDCLumaLengths[DC_CODE_COUNT] = { +	7, 6, 5, 4, 3, 3, 2, 2, 3 +}; + +static const uint32 s_huffmanDCSymbols[DC_CODE_COUNT] = { +	DC_HUFF_VAL(8, 255, 128), DC_HUFF_VAL(7, 127, 64), DC_HUFF_VAL(6, 63, 32), +	DC_HUFF_VAL(5, 31, 16), DC_HUFF_VAL(4, 15, 8), DC_HUFF_VAL(3, 7, 4), +	DC_HUFF_VAL(2, 3, 2), DC_HUFF_VAL(1, 1, 1), DC_HUFF_VAL(0, 0, 0) +}; + +// Here are the codes/lengths/symbols that are used for decoding +// DC coefficients (version 2 and 3 frames) + +#define AC_CODE_COUNT 113 +#define AC_HUFF_VAL(z, a) ((z << 8) | a)  #define ESCAPE_CODE  ((uint32)-1) // arbitrary, just so we can tell what code it is  #define END_OF_BLOCK ((uint32)-2) // arbitrary, just so we can tell what code it is -#define GET_ZEROES(code) (code >> 8) -#define GET_AC(code) ((int)(code & 0xff)) +#define GET_AC_ZERO_RUN(code) (code >> 8) +#define GET_AC_COEFFICIENT(code) ((int)(code & 0xff)) -static const uint32 s_huffmanCodes[CODE_COUNT] = { +static const uint32 s_huffmanACCodes[AC_CODE_COUNT] = {  	// Regular codes  	3, 3, 4, 5, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7,  	32, 33, 34, 35, 36, 37, 38, 39, 8, 9, 10, 11, @@ -87,7 +123,7 @@ static const uint32 s_huffmanCodes[CODE_COUNT] = {  	2  }; -static const byte s_huffmanLengths[CODE_COUNT] = { +static const byte s_huffmanACLengths[AC_CODE_COUNT] = {  	// Regular codes  	2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,  	8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, @@ -106,31 +142,31 @@ static const byte s_huffmanLengths[CODE_COUNT] = {  	2  }; -static const uint32 s_huffmanSymbols[CODE_COUNT] = { +static const uint32 s_huffmanACSymbols[AC_CODE_COUNT] = {  	// Regular codes -	HUFFVAL(0, 1), HUFFVAL(1, 1), HUFFVAL(0, 2), HUFFVAL(2, 1), HUFFVAL(0, 3), -	HUFFVAL(4, 1), HUFFVAL(3, 1), HUFFVAL(7, 1), HUFFVAL(6, 1), HUFFVAL(1, 2), -	HUFFVAL(5, 1), HUFFVAL(2, 2), HUFFVAL(9, 1), HUFFVAL(0, 4), HUFFVAL(8, 1), -	HUFFVAL(13, 1), HUFFVAL(0, 6), HUFFVAL(12, 1), HUFFVAL(11, 1), HUFFVAL(3, 2), -	HUFFVAL(1, 3), HUFFVAL(0, 5), HUFFVAL(10, 1), HUFFVAL(16, 1), HUFFVAL(5, 2), -	HUFFVAL(0, 7), HUFFVAL(2, 3), HUFFVAL(1, 4), HUFFVAL(15, 1), HUFFVAL(14, 1), -	HUFFVAL(4, 2), HUFFVAL(0, 11), HUFFVAL(8, 2), HUFFVAL(4, 3), HUFFVAL(0, 10), -	HUFFVAL(2, 4), HUFFVAL(7, 2), HUFFVAL(21, 1), HUFFVAL(20, 1), HUFFVAL(0, 9), -	HUFFVAL(19, 1), HUFFVAL(18, 1), HUFFVAL(1, 5), HUFFVAL(3, 3), HUFFVAL(0, 8), -	HUFFVAL(6, 2), HUFFVAL(17, 1), HUFFVAL(10, 2), HUFFVAL(9, 2), HUFFVAL(5, 3), -	HUFFVAL(3, 4), HUFFVAL(2, 5), HUFFVAL(1, 7), HUFFVAL(1, 6), HUFFVAL(0, 15), -	HUFFVAL(0, 14), HUFFVAL(0, 13), HUFFVAL(0, 12), HUFFVAL(26, 1), HUFFVAL(25, 1), -	HUFFVAL(24, 1), HUFFVAL(23, 1), HUFFVAL(22, 1), HUFFVAL(0, 31), HUFFVAL(0, 30), -	HUFFVAL(0, 29), HUFFVAL(0, 28), HUFFVAL(0, 27), HUFFVAL(0, 26), HUFFVAL(0, 25), -	HUFFVAL(0, 24), HUFFVAL(0, 23), HUFFVAL(0, 22), HUFFVAL(0, 21), HUFFVAL(0, 20), -	HUFFVAL(0, 19), HUFFVAL(0, 18), HUFFVAL(0, 17), HUFFVAL(0, 16), HUFFVAL(0, 40), -	HUFFVAL(0, 39), HUFFVAL(0, 38), HUFFVAL(0, 37), HUFFVAL(0, 36), HUFFVAL(0, 35), -	HUFFVAL(0, 34), HUFFVAL(0, 33), HUFFVAL(0, 32), HUFFVAL(1, 14), HUFFVAL(1, 13), -	HUFFVAL(1, 12), HUFFVAL(1, 11), HUFFVAL(1, 10), HUFFVAL(1, 9), HUFFVAL(1, 8), -	HUFFVAL(1, 18), HUFFVAL(1, 17), HUFFVAL(1, 16), HUFFVAL(1, 15), HUFFVAL(6, 3), -	HUFFVAL(16, 2), HUFFVAL(15, 2), HUFFVAL(14, 2), HUFFVAL(13, 2), HUFFVAL(12, 2), -	HUFFVAL(11, 2), HUFFVAL(31, 1), HUFFVAL(30, 1), HUFFVAL(29, 1), HUFFVAL(28, 1), -	HUFFVAL(27, 1), +	AC_HUFF_VAL(0, 1), AC_HUFF_VAL(1, 1), AC_HUFF_VAL(0, 2), AC_HUFF_VAL(2, 1), AC_HUFF_VAL(0, 3), +	AC_HUFF_VAL(4, 1), AC_HUFF_VAL(3, 1), AC_HUFF_VAL(7, 1), AC_HUFF_VAL(6, 1), AC_HUFF_VAL(1, 2), +	AC_HUFF_VAL(5, 1), AC_HUFF_VAL(2, 2), AC_HUFF_VAL(9, 1), AC_HUFF_VAL(0, 4), AC_HUFF_VAL(8, 1), +	AC_HUFF_VAL(13, 1), AC_HUFF_VAL(0, 6), AC_HUFF_VAL(12, 1), AC_HUFF_VAL(11, 1), AC_HUFF_VAL(3, 2), +	AC_HUFF_VAL(1, 3), AC_HUFF_VAL(0, 5), AC_HUFF_VAL(10, 1), AC_HUFF_VAL(16, 1), AC_HUFF_VAL(5, 2), +	AC_HUFF_VAL(0, 7), AC_HUFF_VAL(2, 3), AC_HUFF_VAL(1, 4), AC_HUFF_VAL(15, 1), AC_HUFF_VAL(14, 1), +	AC_HUFF_VAL(4, 2), AC_HUFF_VAL(0, 11), AC_HUFF_VAL(8, 2), AC_HUFF_VAL(4, 3), AC_HUFF_VAL(0, 10), +	AC_HUFF_VAL(2, 4), AC_HUFF_VAL(7, 2), AC_HUFF_VAL(21, 1), AC_HUFF_VAL(20, 1), AC_HUFF_VAL(0, 9), +	AC_HUFF_VAL(19, 1), AC_HUFF_VAL(18, 1), AC_HUFF_VAL(1, 5), AC_HUFF_VAL(3, 3), AC_HUFF_VAL(0, 8), +	AC_HUFF_VAL(6, 2), AC_HUFF_VAL(17, 1), AC_HUFF_VAL(10, 2), AC_HUFF_VAL(9, 2), AC_HUFF_VAL(5, 3), +	AC_HUFF_VAL(3, 4), AC_HUFF_VAL(2, 5), AC_HUFF_VAL(1, 7), AC_HUFF_VAL(1, 6), AC_HUFF_VAL(0, 15), +	AC_HUFF_VAL(0, 14), AC_HUFF_VAL(0, 13), AC_HUFF_VAL(0, 12), AC_HUFF_VAL(26, 1), AC_HUFF_VAL(25, 1), +	AC_HUFF_VAL(24, 1), AC_HUFF_VAL(23, 1), AC_HUFF_VAL(22, 1), AC_HUFF_VAL(0, 31), AC_HUFF_VAL(0, 30), +	AC_HUFF_VAL(0, 29), AC_HUFF_VAL(0, 28), AC_HUFF_VAL(0, 27), AC_HUFF_VAL(0, 26), AC_HUFF_VAL(0, 25), +	AC_HUFF_VAL(0, 24), AC_HUFF_VAL(0, 23), AC_HUFF_VAL(0, 22), AC_HUFF_VAL(0, 21), AC_HUFF_VAL(0, 20), +	AC_HUFF_VAL(0, 19), AC_HUFF_VAL(0, 18), AC_HUFF_VAL(0, 17), AC_HUFF_VAL(0, 16), AC_HUFF_VAL(0, 40), +	AC_HUFF_VAL(0, 39), AC_HUFF_VAL(0, 38), AC_HUFF_VAL(0, 37), AC_HUFF_VAL(0, 36), AC_HUFF_VAL(0, 35), +	AC_HUFF_VAL(0, 34), AC_HUFF_VAL(0, 33), AC_HUFF_VAL(0, 32), AC_HUFF_VAL(1, 14), AC_HUFF_VAL(1, 13), +	AC_HUFF_VAL(1, 12), AC_HUFF_VAL(1, 11), AC_HUFF_VAL(1, 10), AC_HUFF_VAL(1, 9), AC_HUFF_VAL(1, 8), +	AC_HUFF_VAL(1, 18), AC_HUFF_VAL(1, 17), AC_HUFF_VAL(1, 16), AC_HUFF_VAL(1, 15), AC_HUFF_VAL(6, 3), +	AC_HUFF_VAL(16, 2), AC_HUFF_VAL(15, 2), AC_HUFF_VAL(14, 2), AC_HUFF_VAL(13, 2), AC_HUFF_VAL(12, 2), +	AC_HUFF_VAL(11, 2), AC_HUFF_VAL(31, 1), AC_HUFF_VAL(30, 1), AC_HUFF_VAL(29, 1), AC_HUFF_VAL(28, 1), +	AC_HUFF_VAL(27, 1),  	// Escape code  	ESCAPE_CODE, @@ -143,7 +179,9 @@ void PSXStreamDecoder::initCommon() {  	_audStream = 0;  	_surface = new Graphics::Surface();  	_yBuffer = _cbBuffer = _crBuffer = 0; -	_huffman = new Common::Huffman(0, CODE_COUNT, s_huffmanCodes, s_huffmanLengths, s_huffmanSymbols); +	_acHuffman = new Common::Huffman(0, AC_CODE_COUNT, s_huffmanACCodes, s_huffmanACLengths, s_huffmanACSymbols); +	_dcHuffmanChroma = new Common::Huffman(0, DC_CODE_COUNT, s_huffmanDCChromaCodes, s_huffmanDCChromaLengths, s_huffmanDCSymbols); +	_dcHuffmanLuma = new Common::Huffman(0, DC_CODE_COUNT, s_huffmanDCLumaCodes, s_huffmanDCLumaLengths, s_huffmanDCSymbols);  }  #define RAW_CD_SECTOR_SIZE 2352 @@ -448,6 +486,9 @@ void PSXStreamDecoder::decodeFrame(Common::SeekableReadStream *frame) {  	if (version != 2 && version != 3)  		error("Unknown PSX stream frame version"); +	// Initalize default v3 DC here +	_lastDC[0] = _lastDC[1] = _lastDC[2] = 0; +  	for (int mbX = 0; mbX < _macroBlocksW; mbX++)  		for (int mbY = 0; mbY < _macroBlocksH; mbY++)  			decodeMacroBlock(&bits, mbX, mbY, scale, version); @@ -461,12 +502,12 @@ void PSXStreamDecoder::decodeMacroBlock(Common::BitStream *bits, int mbX, int mb  	int pitchC = _macroBlocksW * 8;  	// Note the strange order of red before blue -	decodeBlock(bits, _crBuffer + (mbY * pitchC + mbX) * 8, pitchC, scale, version); -	decodeBlock(bits, _cbBuffer + (mbY * pitchC + mbX) * 8, pitchC, scale, version); -	decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16, pitchY, scale, version); -	decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16 + 8, pitchY, scale, version); -	decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16 + 8 * pitchY, pitchY, scale, version); -	decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16 + 8 * pitchY + 8, pitchY, scale, version); +	decodeBlock(bits, _crBuffer + (mbY * pitchC + mbX) * 8, pitchC, scale, version, kPlaneV); +	decodeBlock(bits, _cbBuffer + (mbY * pitchC + mbX) * 8, pitchC, scale, version, kPlaneU); +	decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16, pitchY, scale, version, kPlaneY); +	decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16 + 8, pitchY, scale, version, kPlaneY); +	decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16 + 8 * pitchY, pitchY, scale, version, kPlaneY); +	decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16 + 8 * pitchY + 8, pitchY, scale, version, kPlaneY);  }  // Standard JPEG/MPEG zig zag table @@ -503,6 +544,32 @@ void PSXStreamDecoder::dequantizeBlock(int *coefficients, float *block, uint16 s  	}  } +int PSXStreamDecoder::readDC(Common::BitStream *bits, uint16 version, PlaneType plane) { +	// Version 2 just has its coefficient as 10-bits +	if (version == 2) +		return readSignedCoefficient(bits); + +	// Version 3 has it stored as huffman codes as a difference from the previous DC value + +	Common::Huffman *huffman = (plane == kPlaneY) ? _dcHuffmanLuma : _dcHuffmanChroma; + +	uint32 symbol = huffman->getSymbol(*bits); +	int dc = 0; + +	if (GET_DC_BITS(symbol) != 0) { +		bool negative = (bits->getBit() == 0); +		dc = bits->getBits(GET_DC_BITS(symbol) - 1); + +		if (negative) +			dc -= GET_DC_NEG(symbol); +		else +			dc += GET_DC_POS(symbol); +	} + +	_lastDC[plane] += dc * 4; // convert from 8-bit to 10-bit +	return _lastDC[plane]; +} +  #define BLOCK_OVERFLOW_CHECK() \  	if (count > 63) \  		error("PSXStreamDecoder::readAC(): Too many coefficients") @@ -515,7 +582,7 @@ void PSXStreamDecoder::readAC(Common::BitStream *bits, int *block) {  	int count = 0;  	while (!bits->eos()) { -		uint32 symbol = _huffman->getSymbol(*bits); +		uint32 symbol = _acHuffman->getSymbol(*bits);  		if (symbol == ESCAPE_CODE) {  			// The escape code! @@ -529,15 +596,15 @@ void PSXStreamDecoder::readAC(Common::BitStream *bits, int *block) {  			break;  		} else {  			// Normal huffman code -			int zeroes = GET_ZEROES(symbol); +			int zeroes = GET_AC_ZERO_RUN(symbol);  			count += zeroes + 1;  			BLOCK_OVERFLOW_CHECK();  			block += zeroes;  			if (bits->getBit()) -				*block++ = -GET_AC(symbol); +				*block++ = -GET_AC_COEFFICIENT(symbol);  			else -				*block++ = GET_AC(symbol); +				*block++ = GET_AC_COEFFICIENT(symbol);  		}  	}  } @@ -603,18 +670,11 @@ void PSXStreamDecoder::idct(float *dequantData, float *result) {  	}  } -void PSXStreamDecoder::decodeBlock(Common::BitStream *bits, byte *block, int pitch, uint16 scale, uint16 version) { -	int dc; - -	if (version == 2) { -		dc = readSignedCoefficient(bits); -	} else { -		// TODO -		error("Unhandled PSX stream version 3 DC"); -	} - +void PSXStreamDecoder::decodeBlock(Common::BitStream *bits, byte *block, int pitch, uint16 scale, uint16 version, PlaneType plane) { +	// Version 2 just has signed 10 bits for DC +	// Version 3 has them huffman coded  	int coefficients[8 * 8]; -	coefficients[0] = dc; // Start us off with the DC +	coefficients[0] = readDC(bits, version, plane);  	readAC(bits, &coefficients[1]); // Read in the AC  	// Dequantize diff --git a/video/psx_decoder.h b/video/psx_decoder.h index e8de507589..4223f0344e 100644 --- a/video/psx_decoder.h +++ b/video/psx_decoder.h @@ -96,15 +96,26 @@ private:  	Audio::QueuingAudioStream *_audStream;  	void queueAudioFromSector(Common::SeekableReadStream *sector); -	Common::Huffman *_huffman; +	enum PlaneType { +		kPlaneY = 0, +		kPlaneU = 1, +		kPlaneV = 2 +	}; +  	uint16 _macroBlocksW, _macroBlocksH;  	byte *_yBuffer, *_cbBuffer, *_crBuffer;  	void decodeFrame(Common::SeekableReadStream *frame);  	void decodeMacroBlock(Common::BitStream *bits, int mbX, int mbY, uint16 scale, uint16 version); -	void decodeBlock(Common::BitStream *bits, byte *block, int pitch, uint16 scale, uint16 version); +	void decodeBlock(Common::BitStream *bits, byte *block, int pitch, uint16 scale, uint16 version, PlaneType plane); -	void dequantizeBlock(int *coefficients, float *block, uint16 scale);  	void readAC(Common::BitStream *bits, int *block); +	Common::Huffman *_acHuffman; + +	int readDC(Common::BitStream *bits, uint16 version, PlaneType plane); +	Common::Huffman *_dcHuffmanLuma, *_dcHuffmanChroma; +	int _lastDC[3]; + +	void dequantizeBlock(int *coefficients, float *block, uint16 scale);  	void idct(float *dequantData, float *result);  	int readSignedCoefficient(Common::BitStream *bits); | 
