diff options
Diffstat (limited to 'video')
-rw-r--r-- | video/avi_decoder.cpp | 559 | ||||
-rw-r--r-- | video/avi_decoder.h | 312 | ||||
-rw-r--r-- | video/bink_decoder.cpp | 1022 | ||||
-rw-r--r-- | video/bink_decoder.h | 419 | ||||
-rw-r--r-- | video/codecs/qtrle.cpp | 135 | ||||
-rw-r--r-- | video/codecs/qtrle.h | 3 | ||||
-rw-r--r-- | video/codecs/rpza.cpp | 22 | ||||
-rw-r--r-- | video/codecs/rpza.h | 3 | ||||
-rw-r--r-- | video/codecs/svq1.cpp | 8 | ||||
-rw-r--r-- | video/codecs/svq1_cb.h | 2900 | ||||
-rw-r--r-- | video/coktel_decoder.cpp | 205 | ||||
-rw-r--r-- | video/coktel_decoder.h | 124 | ||||
-rw-r--r-- | video/dxa_decoder.cpp | 130 | ||||
-rw-r--r-- | video/dxa_decoder.h | 102 | ||||
-rw-r--r-- | video/flic_decoder.cpp | 302 | ||||
-rw-r--r-- | video/flic_decoder.h | 101 | ||||
-rw-r--r-- | video/module.mk | 5 | ||||
-rw-r--r-- | video/psx_decoder.cpp | 248 | ||||
-rw-r--r-- | video/psx_decoder.h | 107 | ||||
-rw-r--r-- | video/qt_decoder.cpp | 638 | ||||
-rw-r--r-- | video/qt_decoder.h | 179 | ||||
-rw-r--r-- | video/smk_decoder.cpp | 388 | ||||
-rw-r--r-- | video/smk_decoder.h | 118 | ||||
-rw-r--r-- | video/theora_decoder.cpp | 487 | ||||
-rw-r--r-- | video/theora_decoder.h | 157 | ||||
-rw-r--r-- | video/video_decoder.cpp | 628 | ||||
-rw-r--r-- | video/video_decoder.h | 708 |
27 files changed, 5927 insertions, 4083 deletions
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 9685952304..0d51f5b130 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -42,106 +42,128 @@ namespace Video { -/* +#define UNKNOWN_HEADER(a) error("Unknown header found -- \'%s\'", tag2str(a)) + +// IDs used throughout the AVI files +// that will be handled by this player +#define ID_RIFF MKTAG('R','I','F','F') +#define ID_AVI MKTAG('A','V','I',' ') +#define ID_LIST MKTAG('L','I','S','T') +#define ID_HDRL MKTAG('h','d','r','l') +#define ID_AVIH MKTAG('a','v','i','h') +#define ID_STRL MKTAG('s','t','r','l') +#define ID_STRH MKTAG('s','t','r','h') +#define ID_VIDS MKTAG('v','i','d','s') +#define ID_AUDS MKTAG('a','u','d','s') +#define ID_MIDS MKTAG('m','i','d','s') +#define ID_TXTS MKTAG('t','x','t','s') +#define ID_JUNK MKTAG('J','U','N','K') +#define ID_STRF MKTAG('s','t','r','f') +#define ID_MOVI MKTAG('m','o','v','i') +#define ID_REC MKTAG('r','e','c',' ') +#define ID_VEDT MKTAG('v','e','d','t') +#define ID_IDX1 MKTAG('i','d','x','1') +#define ID_STRD MKTAG('s','t','r','d') +#define ID_00AM MKTAG('0','0','A','M') +//#define ID_INFO MKTAG('I','N','F','O') + +// Codec tags +#define ID_RLE MKTAG('R','L','E',' ') +#define ID_CRAM MKTAG('C','R','A','M') +#define ID_MSVC MKTAG('m','s','v','c') +#define ID_WHAM MKTAG('W','H','A','M') +#define ID_CVID MKTAG('c','v','i','d') +#define ID_IV32 MKTAG('i','v','3','2') +#define ID_DUCK MKTAG('D','U','C','K') + static byte char2num(char c) { - return (c >= 48 && c <= 57) ? c - 48 : 0; + c = tolower((byte)c); + return (c >= 'a' && c <= 'f') ? c - 'a' + 10 : c - '0'; } -static byte getStreamNum(uint32 tag) { - return char2num((char)(tag >> 24)) * 16 + char2num((char)(tag >> 16)); +static byte getStreamIndex(uint32 tag) { + return char2num((tag >> 24) & 0xFF) << 4 | char2num((tag >> 16) & 0xFF); } -*/ static uint16 getStreamType(uint32 tag) { return tag & 0xffff; } -AviDecoder::AviDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : _mixer(mixer) { - _soundType = soundType; - - _videoCodec = NULL; +AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _soundType(soundType) { _decodedHeader = false; - _audStream = NULL; - _fileStream = NULL; - _audHandle = new Audio::SoundHandle(); - _dirtyPalette = false; - memset(_palette, 0, sizeof(_palette)); - memset(&_wvInfo, 0, sizeof(PCMWAVEFORMAT)); - memset(&_bmInfo, 0, sizeof(BITMAPINFOHEADER)); - memset(&_vidsHeader, 0, sizeof(AVIStreamHeader)); - memset(&_audsHeader, 0, sizeof(AVIStreamHeader)); - memset(&_ixInfo, 0, sizeof(AVIOLDINDEX)); + _fileStream = 0; + memset(&_ixInfo, 0, sizeof(_ixInfo)); + memset(&_header, 0, sizeof(_header)); } -AviDecoder::~AviDecoder() { +AVIDecoder::~AVIDecoder() { close(); - delete _audHandle; } -void AviDecoder::runHandle(uint32 tag) { - assert (_fileStream); +void AVIDecoder::runHandle(uint32 tag) { + assert(_fileStream); if (_fileStream->eos()) return; - debug (3, "Decoding tag %s", tag2str(tag)); + debug(3, "Decoding tag %s", tag2str(tag)); switch (tag) { - case ID_RIFF: - /*_filesize = */_fileStream->readUint32LE(); - if (_fileStream->readUint32BE() != ID_AVI) - error("RIFF file is not an AVI video"); - break; - case ID_LIST: - handleList(); - break; - case ID_AVIH: - _header.size = _fileStream->readUint32LE(); - _header.microSecondsPerFrame = _fileStream->readUint32LE(); - _header.maxBytesPerSecond = _fileStream->readUint32LE(); - _header.padding = _fileStream->readUint32LE(); - _header.flags = _fileStream->readUint32LE(); - _header.totalFrames = _fileStream->readUint32LE(); - _header.initialFrames = _fileStream->readUint32LE(); - _header.streams = _fileStream->readUint32LE(); - _header.bufferSize = _fileStream->readUint32LE(); - _header.width = _fileStream->readUint32LE(); - _header.height = _fileStream->readUint32LE(); - //Ignore 16 bytes of reserved data - _fileStream->skip(16); - break; - case ID_STRH: - handleStreamHeader(); - break; - case ID_STRD: // Extra stream info, safe to ignore - case ID_VEDT: // Unknown, safe to ignore - case ID_JUNK: // Alignment bytes, should be ignored - { - uint32 junkSize = _fileStream->readUint32LE(); - _fileStream->skip(junkSize + (junkSize & 1)); // Alignment - } break; - case ID_IDX1: - _ixInfo.size = _fileStream->readUint32LE(); - _ixInfo.indices = new AVIOLDINDEX::Index[_ixInfo.size / 16]; - debug (0, "%d Indices", (_ixInfo.size / 16)); - for (uint32 i = 0; i < (_ixInfo.size / 16); i++) { - _ixInfo.indices[i].id = _fileStream->readUint32BE(); - _ixInfo.indices[i].flags = _fileStream->readUint32LE(); - _ixInfo.indices[i].offset = _fileStream->readUint32LE(); - _ixInfo.indices[i].size = _fileStream->readUint32LE(); - debug (0, "Index %d == Tag \'%s\', Offset = %d, Size = %d", i, tag2str(_ixInfo.indices[i].id), _ixInfo.indices[i].offset, _ixInfo.indices[i].size); - } - break; - default: - error ("Unknown tag \'%s\' found", tag2str(tag)); + case ID_RIFF: + /*_filesize = */_fileStream->readUint32LE(); + if (_fileStream->readUint32BE() != ID_AVI) + error("RIFF file is not an AVI video"); + break; + case ID_LIST: + handleList(); + break; + case ID_AVIH: + _header.size = _fileStream->readUint32LE(); + _header.microSecondsPerFrame = _fileStream->readUint32LE(); + _header.maxBytesPerSecond = _fileStream->readUint32LE(); + _header.padding = _fileStream->readUint32LE(); + _header.flags = _fileStream->readUint32LE(); + _header.totalFrames = _fileStream->readUint32LE(); + _header.initialFrames = _fileStream->readUint32LE(); + _header.streams = _fileStream->readUint32LE(); + _header.bufferSize = _fileStream->readUint32LE(); + _header.width = _fileStream->readUint32LE(); + _header.height = _fileStream->readUint32LE(); + // Ignore 16 bytes of reserved data + _fileStream->skip(16); + break; + case ID_STRH: + handleStreamHeader(); + break; + case ID_STRD: // Extra stream info, safe to ignore + case ID_VEDT: // Unknown, safe to ignore + case ID_JUNK: // Alignment bytes, should be ignored + { + uint32 junkSize = _fileStream->readUint32LE(); + _fileStream->skip(junkSize + (junkSize & 1)); // Alignment + } break; + case ID_IDX1: + _ixInfo.size = _fileStream->readUint32LE(); + _ixInfo.indices = new OldIndex::Index[_ixInfo.size / 16]; + debug(0, "%d Indices", (_ixInfo.size / 16)); + for (uint32 i = 0; i < (_ixInfo.size / 16); i++) { + _ixInfo.indices[i].id = _fileStream->readUint32BE(); + _ixInfo.indices[i].flags = _fileStream->readUint32LE(); + _ixInfo.indices[i].offset = _fileStream->readUint32LE(); + _ixInfo.indices[i].size = _fileStream->readUint32LE(); + debug(0, "Index %d == Tag \'%s\', Offset = %d, Size = %d", i, tag2str(_ixInfo.indices[i].id), _ixInfo.indices[i].offset, _ixInfo.indices[i].size); + } + break; + default: + error("Unknown tag \'%s\' found", tag2str(tag)); } } -void AviDecoder::handleList() { +void AVIDecoder::handleList() { uint32 listSize = _fileStream->readUint32LE() - 4; // Subtract away listType's 4 bytes uint32 listType = _fileStream->readUint32BE(); uint32 curPos = _fileStream->pos(); - debug (0, "Found LIST of type %s", tag2str(listType)); + debug(0, "Found LIST of type %s", tag2str(listType)); while ((_fileStream->pos() - curPos) < listSize) runHandle(_fileStream->readUint32BE()); @@ -151,12 +173,14 @@ void AviDecoder::handleList() { _decodedHeader = true; } -void AviDecoder::handleStreamHeader() { +void AVIDecoder::handleStreamHeader() { AVIStreamHeader sHeader; sHeader.size = _fileStream->readUint32LE(); sHeader.streamType = _fileStream->readUint32BE(); + if (sHeader.streamType == ID_MIDS || sHeader.streamType == ID_TXTS) - error ("Unhandled MIDI/Text stream"); + error("Unhandled MIDI/Text stream"); + sHeader.streamHandler = _fileStream->readUint32BE(); sHeader.flags = _fileStream->readUint32LE(); sHeader.priority = _fileStream->readUint16LE(); @@ -174,63 +198,67 @@ void AviDecoder::handleStreamHeader() { if (_fileStream->readUint32BE() != ID_STRF) error("Could not find STRF tag"); + uint32 strfSize = _fileStream->readUint32LE(); uint32 startPos = _fileStream->pos(); if (sHeader.streamType == ID_VIDS) { - _vidsHeader = sHeader; - - _bmInfo.size = _fileStream->readUint32LE(); - _bmInfo.width = _fileStream->readUint32LE(); - assert (_header.width == _bmInfo.width); - _bmInfo.height = _fileStream->readUint32LE(); - assert (_header.height == _bmInfo.height); - _bmInfo.planes = _fileStream->readUint16LE(); - _bmInfo.bitCount = _fileStream->readUint16LE(); - _bmInfo.compression = _fileStream->readUint32BE(); - _bmInfo.sizeImage = _fileStream->readUint32LE(); - _bmInfo.xPelsPerMeter = _fileStream->readUint32LE(); - _bmInfo.yPelsPerMeter = _fileStream->readUint32LE(); - _bmInfo.clrUsed = _fileStream->readUint32LE(); - _bmInfo.clrImportant = _fileStream->readUint32LE(); - - if (_bmInfo.bitCount == 8) { - if (_bmInfo.clrUsed == 0) - _bmInfo.clrUsed = 256; - - for (uint32 i = 0; i < _bmInfo.clrUsed; i++) { - _palette[i * 3 + 2] = _fileStream->readByte(); - _palette[i * 3 + 1] = _fileStream->readByte(); - _palette[i * 3] = _fileStream->readByte(); + BitmapInfoHeader bmInfo; + bmInfo.size = _fileStream->readUint32LE(); + bmInfo.width = _fileStream->readUint32LE(); + bmInfo.height = _fileStream->readUint32LE(); + bmInfo.planes = _fileStream->readUint16LE(); + bmInfo.bitCount = _fileStream->readUint16LE(); + bmInfo.compression = _fileStream->readUint32BE(); + bmInfo.sizeImage = _fileStream->readUint32LE(); + bmInfo.xPelsPerMeter = _fileStream->readUint32LE(); + bmInfo.yPelsPerMeter = _fileStream->readUint32LE(); + bmInfo.clrUsed = _fileStream->readUint32LE(); + bmInfo.clrImportant = _fileStream->readUint32LE(); + + if (bmInfo.clrUsed == 0) + bmInfo.clrUsed = 256; + + if (sHeader.streamHandler == 0) + sHeader.streamHandler = bmInfo.compression; + + AVIVideoTrack *track = new AVIVideoTrack(_header.totalFrames, sHeader, bmInfo); + + if (bmInfo.bitCount == 8) { + byte *palette = const_cast<byte *>(track->getPalette()); + for (uint32 i = 0; i < bmInfo.clrUsed; i++) { + palette[i * 3 + 2] = _fileStream->readByte(); + palette[i * 3 + 1] = _fileStream->readByte(); + palette[i * 3] = _fileStream->readByte(); _fileStream->readByte(); } - _dirtyPalette = true; + track->markPaletteDirty(); } - if (!_vidsHeader.streamHandler) - _vidsHeader.streamHandler = _bmInfo.compression; + addTrack(track); } else if (sHeader.streamType == ID_AUDS) { - _audsHeader = sHeader; - - _wvInfo.tag = _fileStream->readUint16LE(); - _wvInfo.channels = _fileStream->readUint16LE(); - _wvInfo.samplesPerSec = _fileStream->readUint32LE(); - _wvInfo.avgBytesPerSec = _fileStream->readUint32LE(); - _wvInfo.blockAlign = _fileStream->readUint16LE(); - _wvInfo.size = _fileStream->readUint16LE(); + PCMWaveFormat wvInfo; + wvInfo.tag = _fileStream->readUint16LE(); + wvInfo.channels = _fileStream->readUint16LE(); + wvInfo.samplesPerSec = _fileStream->readUint32LE(); + wvInfo.avgBytesPerSec = _fileStream->readUint32LE(); + wvInfo.blockAlign = _fileStream->readUint16LE(); + wvInfo.size = _fileStream->readUint16LE(); // AVI seems to treat the sampleSize as including the second // channel as well, so divide for our sake. - if (_wvInfo.channels == 2) - _audsHeader.sampleSize /= 2; + if (wvInfo.channels == 2) + sHeader.sampleSize /= 2; + + addTrack(new AVIAudioTrack(sHeader, wvInfo, _soundType)); } // Ensure that we're at the end of the chunk _fileStream->seek(startPos + strfSize); } -bool AviDecoder::loadStream(Common::SeekableReadStream *stream) { +bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) { close(); _fileStream = stream; @@ -252,74 +280,31 @@ bool AviDecoder::loadStream(Common::SeekableReadStream *stream) { if (nextTag == ID_LIST) { _fileStream->readUint32BE(); // Skip size if (_fileStream->readUint32BE() != ID_MOVI) - error ("Expected 'movi' LIST"); - } else - error ("Expected 'movi' LIST"); - - // Now, create the codec - _videoCodec = createCodec(); - - // Initialize the video stuff too - _audStream = createAudioStream(); - if (_audStream) - _mixer->playStream(_soundType, _audHandle, _audStream); - - debug (0, "Frames = %d, Dimensions = %d x %d", _header.totalFrames, _header.width, _header.height); - debug (0, "Frame Rate = %d", _vidsHeader.rate / _vidsHeader.scale); - if (_wvInfo.samplesPerSec != 0) - debug (0, "Sound Rate = %d", _wvInfo.samplesPerSec); - debug (0, "Video Codec = \'%s\'", tag2str(_vidsHeader.streamHandler)); - - if (!_videoCodec) - return false; + error("Expected 'movi' LIST"); + } else { + error("Expected 'movi' LIST"); + } return true; } -void AviDecoder::close() { - if (!_fileStream) - return; +void AVIDecoder::close() { + VideoDecoder::close(); delete _fileStream; _fileStream = 0; - - // Deinitialize sound - _mixer->stopHandle(*_audHandle); - _audStream = 0; - _decodedHeader = false; - delete _videoCodec; - _videoCodec = 0; - delete[] _ixInfo.indices; - _ixInfo.indices = 0; - - memset(_palette, 0, sizeof(_palette)); - memset(&_wvInfo, 0, sizeof(PCMWAVEFORMAT)); - memset(&_bmInfo, 0, sizeof(BITMAPINFOHEADER)); - memset(&_vidsHeader, 0, sizeof(AVIStreamHeader)); - memset(&_audsHeader, 0, sizeof(AVIStreamHeader)); - memset(&_ixInfo, 0, sizeof(AVIOLDINDEX)); - - reset(); + memset(&_ixInfo, 0, sizeof(_ixInfo)); + memset(&_header, 0, sizeof(_header)); } -uint32 AviDecoder::getElapsedTime() const { - if (_audStream) - return _mixer->getSoundElapsedTime(*_audHandle); - - return FixedRateVideoDecoder::getElapsedTime(); -} - -const Graphics::Surface *AviDecoder::decodeNextFrame() { +void AVIDecoder::readNextPacket() { uint32 nextTag = _fileStream->readUint32BE(); if (_fileStream->eos()) - return NULL; - - if (_curFrame == -1) - _startTime = g_system->getMillis(); + return; if (nextTag == ID_LIST) { // A list of audio/video chunks @@ -327,128 +312,170 @@ const Graphics::Surface *AviDecoder::decodeNextFrame() { int32 startPos = _fileStream->pos(); if (_fileStream->readUint32BE() != ID_REC) - error ("Expected 'rec ' LIST"); - - // Decode chunks in the list and see if we get a frame - const Graphics::Surface *frame = NULL; - while (_fileStream->pos() < startPos + (int32)listSize) { - const Graphics::Surface *temp = decodeNextFrame(); - if (temp) - frame = temp; - } + error("Expected 'rec ' LIST"); + + // Decode chunks in the list + while (_fileStream->pos() < startPos + (int32)listSize) + readNextPacket(); + + return; + } else if (nextTag == ID_JUNK || nextTag == ID_IDX1) { + runHandle(nextTag); + return; + } - return frame; - } else if (getStreamType(nextTag) == 'wb') { - // Audio Chunk - uint32 chunkSize = _fileStream->readUint32LE(); - queueAudioBuffer(chunkSize); - _fileStream->skip(chunkSize & 1); // Alignment - } else if (getStreamType(nextTag) == 'dc' || getStreamType(nextTag) == 'id' || - getStreamType(nextTag) == 'AM' || getStreamType(nextTag) == '32' || - getStreamType(nextTag) == 'iv') { - // Compressed Frame - _curFrame++; - uint32 chunkSize = _fileStream->readUint32LE(); - - if (chunkSize == 0) // Keep last frame on screen - return NULL; - - Common::SeekableReadStream *frameData = _fileStream->readStream(chunkSize); - const Graphics::Surface *surface = _videoCodec->decodeImage(frameData); - delete frameData; - _fileStream->skip(chunkSize & 1); // Alignment - return surface; - } else if (getStreamType(nextTag) == 'pc') { - // Palette Change - _fileStream->readUint32LE(); // Chunk size, not needed here - byte firstEntry = _fileStream->readByte(); - uint16 numEntries = _fileStream->readByte(); - _fileStream->readUint16LE(); // Reserved - - // 0 entries means all colors are going to be changed - if (numEntries == 0) - numEntries = 256; - - for (uint16 i = firstEntry; i < numEntries + firstEntry; i++) { - _palette[i * 3] = _fileStream->readByte(); - _palette[i * 3 + 1] = _fileStream->readByte(); - _palette[i * 3 + 2] = _fileStream->readByte(); - _fileStream->readByte(); // Flags that don't serve us any purpose + Track *track = getTrack(getStreamIndex(nextTag)); + + if (!track) + error("Cannot get track from tag '%s'", tag2str(nextTag)); + + uint32 chunkSize = _fileStream->readUint32LE(); + Common::SeekableReadStream *chunk = 0; + + if (chunkSize != 0) { + chunk = _fileStream->readStream(chunkSize); + _fileStream->skip(chunkSize & 1); + } + + if (track->getTrackType() == Track::kTrackTypeAudio) { + if (getStreamType(nextTag) != MKTAG16('w', 'b')) + error("Invalid audio track tag '%s'", tag2str(nextTag)); + + assert(chunk); + ((AVIAudioTrack *)track)->queueSound(chunk); + } else { + AVIVideoTrack *videoTrack = (AVIVideoTrack *)track; + + if (getStreamType(nextTag) == MKTAG16('p', 'c')) { + // Palette Change + assert(chunk); + byte firstEntry = chunk->readByte(); + uint16 numEntries = chunk->readByte(); + chunk->readUint16LE(); // Reserved + + // 0 entries means all colors are going to be changed + if (numEntries == 0) + numEntries = 256; + + byte *palette = const_cast<byte *>(videoTrack->getPalette()); + + for (uint16 i = firstEntry; i < numEntries + firstEntry; i++) { + palette[i * 3] = chunk->readByte(); + palette[i * 3 + 1] = chunk->readByte(); + palette[i * 3 + 2] = chunk->readByte(); + chunk->readByte(); // Flags that don't serve us any purpose + } + + delete chunk; + videoTrack->markPaletteDirty(); + } else if (getStreamType(nextTag) == MKTAG16('d', 'b')) { + // TODO: Check if this really is uncompressed. Many videos + // falsely put compressed data in here. + error("Uncompressed AVI frame found"); + } else { + // Otherwise, assume it's a compressed frame + videoTrack->decodeFrame(chunk); } + } +} - _dirtyPalette = true; +AVIDecoder::AVIVideoTrack::AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader) + : _frameCount(frameCount), _vidsHeader(streamHeader), _bmInfo(bitmapInfoHeader) { + memset(_palette, 0, sizeof(_palette)); + _videoCodec = createCodec(); + _dirtyPalette = false; + _lastFrame = 0; + _curFrame = -1; +} - // No alignment necessary. It's always even. - } else if (nextTag == ID_JUNK) { - runHandle(ID_JUNK); - } else if (nextTag == ID_IDX1) { - runHandle(ID_IDX1); - } else - error("Tag = \'%s\', %d", tag2str(nextTag), _fileStream->pos()); +AVIDecoder::AVIVideoTrack::~AVIVideoTrack() { + delete _videoCodec; +} + +void AVIDecoder::AVIVideoTrack::decodeFrame(Common::SeekableReadStream *stream) { + if (stream) { + if (_videoCodec) + _lastFrame = _videoCodec->decodeImage(stream); + } else { + // Empty frame + _lastFrame = 0; + } - return NULL; + delete stream; + _curFrame++; } -Codec *AviDecoder::createCodec() { +Graphics::PixelFormat AVIDecoder::AVIVideoTrack::getPixelFormat() const { + if (_videoCodec) + return _videoCodec->getPixelFormat(); + + return Graphics::PixelFormat(); +} + +Codec *AVIDecoder::AVIVideoTrack::createCodec() { switch (_vidsHeader.streamHandler) { - case ID_CRAM: - case ID_MSVC: - case ID_WHAM: - return new MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); - case ID_RLE: - return new MSRLEDecoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); - case ID_CVID: - return new CinepakDecoder(_bmInfo.bitCount); - case ID_IV32: - return new Indeo3Decoder(_bmInfo.width, _bmInfo.height); + case ID_CRAM: + case ID_MSVC: + case ID_WHAM: + return new MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); + case ID_RLE: + return new MSRLEDecoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); + case ID_CVID: + return new CinepakDecoder(_bmInfo.bitCount); + case ID_IV32: + return new Indeo3Decoder(_bmInfo.width, _bmInfo.height); #ifdef VIDEO_CODECS_TRUEMOTION1_H - case ID_DUCK: - return new TrueMotion1Decoder(_bmInfo.width, _bmInfo.height); + case ID_DUCK: + return new TrueMotion1Decoder(_bmInfo.width, _bmInfo.height); #endif - default: - warning ("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler)); + default: + warning("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler)); } - return NULL; + return 0; } -Graphics::PixelFormat AviDecoder::getPixelFormat() const { - assert(_videoCodec); - return _videoCodec->getPixelFormat(); +AVIDecoder::AVIAudioTrack::AVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType) + : _audsHeader(streamHeader), _wvInfo(waveFormat), _soundType(soundType) { + _audStream = createAudioStream(); } -Audio::QueuingAudioStream *AviDecoder::createAudioStream() { - if (_wvInfo.tag == kWaveFormatPCM || _wvInfo.tag == kWaveFormatDK3) - return Audio::makeQueuingAudioStream(_wvInfo.samplesPerSec, _wvInfo.channels == 2); - else if (_wvInfo.tag != kWaveFormatNone) // No sound - warning("Unsupported AVI audio format %d", _wvInfo.tag); - - return NULL; +AVIDecoder::AVIAudioTrack::~AVIAudioTrack() { + delete _audStream; } -void AviDecoder::queueAudioBuffer(uint32 chunkSize) { - // Return if we haven't created the queue (unsupported audio format) - if (!_audStream) { - _fileStream->skip(chunkSize); - return; +void AVIDecoder::AVIAudioTrack::queueSound(Common::SeekableReadStream *stream) { + if (_audStream) { + if (_wvInfo.tag == kWaveFormatPCM) { + byte flags = 0; + if (_audsHeader.sampleSize == 2) + flags |= Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN; + else + flags |= Audio::FLAG_UNSIGNED; + + if (_wvInfo.channels == 2) + flags |= Audio::FLAG_STEREO; + + _audStream->queueAudioStream(Audio::makeRawStream(stream, _wvInfo.samplesPerSec, flags, DisposeAfterUse::YES), DisposeAfterUse::YES); + } else if (_wvInfo.tag == kWaveFormatDK3) { + _audStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMDK3, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES); + } + } else { + delete stream; } +} - Common::SeekableReadStream *stream = _fileStream->readStream(chunkSize); - - if (_wvInfo.tag == kWaveFormatPCM) { - byte flags = 0; - if (_audsHeader.sampleSize == 2) - flags |= Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN; - else - flags |= Audio::FLAG_UNSIGNED; +Audio::AudioStream *AVIDecoder::AVIAudioTrack::getAudioStream() const { + return _audStream; +} - if (_wvInfo.channels == 2) - flags |= Audio::FLAG_STEREO; +Audio::QueuingAudioStream *AVIDecoder::AVIAudioTrack::createAudioStream() { + if (_wvInfo.tag == kWaveFormatPCM || _wvInfo.tag == kWaveFormatDK3) + return Audio::makeQueuingAudioStream(_wvInfo.samplesPerSec, _wvInfo.channels == 2); + else if (_wvInfo.tag != kWaveFormatNone) // No sound + warning("Unsupported AVI audio format %d", _wvInfo.tag); - _audStream->queueAudioStream(Audio::makeRawStream(stream, _wvInfo.samplesPerSec, flags, DisposeAfterUse::YES), DisposeAfterUse::YES); - } else if (_wvInfo.tag == kWaveFormatDK3) { - _audStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, chunkSize, Audio::kADPCMDK3, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES); - } + return 0; } } // End of namespace Video diff --git a/video/avi_decoder.h b/video/avi_decoder.h index 508760ec89..a3a262db36 100644 --- a/video/avi_decoder.h +++ b/video/avi_decoder.h @@ -47,191 +47,183 @@ namespace Video { class Codec; -#define UNKNOWN_HEADER(a) error("Unknown header found -- \'%s\'", tag2str(a)) - -// IDs used throughout the AVI files -// that will be handled by this player -#define ID_RIFF MKTAG('R','I','F','F') -#define ID_AVI MKTAG('A','V','I',' ') -#define ID_LIST MKTAG('L','I','S','T') -#define ID_HDRL MKTAG('h','d','r','l') -#define ID_AVIH MKTAG('a','v','i','h') -#define ID_STRL MKTAG('s','t','r','l') -#define ID_STRH MKTAG('s','t','r','h') -#define ID_VIDS MKTAG('v','i','d','s') -#define ID_AUDS MKTAG('a','u','d','s') -#define ID_MIDS MKTAG('m','i','d','s') -#define ID_TXTS MKTAG('t','x','t','s') -#define ID_JUNK MKTAG('J','U','N','K') -#define ID_STRF MKTAG('s','t','r','f') -#define ID_MOVI MKTAG('m','o','v','i') -#define ID_REC MKTAG('r','e','c',' ') -#define ID_VEDT MKTAG('v','e','d','t') -#define ID_IDX1 MKTAG('i','d','x','1') -#define ID_STRD MKTAG('s','t','r','d') -#define ID_00AM MKTAG('0','0','A','M') -//#define ID_INFO MKTAG('I','N','F','O') - -// Codec tags -#define ID_RLE MKTAG('R','L','E',' ') -#define ID_CRAM MKTAG('C','R','A','M') -#define ID_MSVC MKTAG('m','s','v','c') -#define ID_WHAM MKTAG('W','H','A','M') -#define ID_CVID MKTAG('c','v','i','d') -#define ID_IV32 MKTAG('i','v','3','2') -#define ID_DUCK MKTAG('D','U','C','K') - -struct BITMAPINFOHEADER { - uint32 size; - uint32 width; - uint32 height; - uint16 planes; - uint16 bitCount; - uint32 compression; - uint32 sizeImage; - uint32 xPelsPerMeter; - uint32 yPelsPerMeter; - uint32 clrUsed; - uint32 clrImportant; -}; - -struct WAVEFORMAT { - uint16 tag; - uint16 channels; - uint32 samplesPerSec; - uint32 avgBytesPerSec; - uint16 blockAlign; -}; - -struct PCMWAVEFORMAT : public WAVEFORMAT { - uint16 size; -}; - -struct WAVEFORMATEX : public WAVEFORMAT { - uint16 bitsPerSample; - uint16 size; -}; - -struct AVIOLDINDEX { - uint32 size; - struct Index { - uint32 id; - uint32 flags; - uint32 offset; - uint32 size; - } *indices; -}; - -// Index Flags -enum IndexFlags { - AVIIF_INDEX = 0x10 -}; - -// Audio Codecs -enum { - kWaveFormatNone = 0, - kWaveFormatPCM = 1, - kWaveFormatDK3 = 98 -}; - -struct AVIHeader { - uint32 size; - uint32 microSecondsPerFrame; - uint32 maxBytesPerSecond; - uint32 padding; - uint32 flags; - uint32 totalFrames; - uint32 initialFrames; - uint32 streams; - uint32 bufferSize; - uint32 width; - uint32 height; -}; - -// Flags from the AVIHeader -enum AviFlags { - AVIF_HASINDEX = 0x00000010, - AVIF_MUSTUSEINDEX = 0x00000020, - AVIF_ISINTERLEAVED = 0x00000100, - AVIF_TRUSTCKTYPE = 0x00000800, - AVIF_WASCAPTUREFILE = 0x00010000, - AVIF_WASCOPYRIGHTED = 0x00020000 -}; - -struct AVIStreamHeader { - uint32 size; - uint32 streamType; - uint32 streamHandler; - uint32 flags; - uint16 priority; - uint16 language; - uint32 initialFrames; - uint32 scale; - uint32 rate; - uint32 start; - uint32 length; - uint32 bufferSize; - uint32 quality; - uint32 sampleSize; - Common::Rect frame; -}; - /** * Decoder for AVI videos. * * Video decoder used in engines: * - sci */ -class AviDecoder : public FixedRateVideoDecoder { +class AVIDecoder : public VideoDecoder { public: - AviDecoder(Audio::Mixer *mixer, - Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); - virtual ~AviDecoder(); + AVIDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); + virtual ~AVIDecoder(); bool loadStream(Common::SeekableReadStream *stream); void close(); - - bool isVideoLoaded() const { return _fileStream != 0; } uint16 getWidth() const { return _header.width; } uint16 getHeight() const { return _header.height; } - uint32 getFrameCount() const { return _header.totalFrames; } - uint32 getElapsedTime() const; - const Graphics::Surface *decodeNextFrame(); - Graphics::PixelFormat getPixelFormat() const; - const byte *getPalette() { _dirtyPalette = false; return _palette; } - bool hasDirtyPalette() const { return _dirtyPalette; } protected: - Common::Rational getFrameRate() const { return Common::Rational(_vidsHeader.rate, _vidsHeader.scale); } + void readNextPacket(); private: - Audio::Mixer *_mixer; - BITMAPINFOHEADER _bmInfo; - PCMWAVEFORMAT _wvInfo; - AVIOLDINDEX _ixInfo; - AVIHeader _header; - AVIStreamHeader _vidsHeader; - AVIStreamHeader _audsHeader; - byte _palette[3 * 256]; - bool _dirtyPalette; + struct BitmapInfoHeader { + uint32 size; + uint32 width; + uint32 height; + uint16 planes; + uint16 bitCount; + uint32 compression; + uint32 sizeImage; + uint32 xPelsPerMeter; + uint32 yPelsPerMeter; + uint32 clrUsed; + uint32 clrImportant; + }; + + struct WaveFormat { + uint16 tag; + uint16 channels; + uint32 samplesPerSec; + uint32 avgBytesPerSec; + uint16 blockAlign; + }; + + struct PCMWaveFormat : public WaveFormat { + uint16 size; + }; + + struct WaveFormatEX : public WaveFormat { + uint16 bitsPerSample; + uint16 size; + }; + + struct OldIndex { + uint32 size; + struct Index { + uint32 id; + uint32 flags; + uint32 offset; + uint32 size; + } *indices; + }; + + // Index Flags + enum IndexFlags { + AVIIF_INDEX = 0x10 + }; + + struct AVIHeader { + uint32 size; + uint32 microSecondsPerFrame; + uint32 maxBytesPerSecond; + uint32 padding; + uint32 flags; + uint32 totalFrames; + uint32 initialFrames; + uint32 streams; + uint32 bufferSize; + uint32 width; + uint32 height; + }; + + // Flags from the AVIHeader + enum AVIFlags { + AVIF_HASINDEX = 0x00000010, + AVIF_MUSTUSEINDEX = 0x00000020, + AVIF_ISINTERLEAVED = 0x00000100, + AVIF_TRUSTCKTYPE = 0x00000800, + AVIF_WASCAPTUREFILE = 0x00010000, + AVIF_WASCOPYRIGHTED = 0x00020000 + }; + + struct AVIStreamHeader { + uint32 size; + uint32 streamType; + uint32 streamHandler; + uint32 flags; + uint16 priority; + uint16 language; + uint32 initialFrames; + uint32 scale; + uint32 rate; + uint32 start; + uint32 length; + uint32 bufferSize; + uint32 quality; + uint32 sampleSize; + Common::Rect frame; + }; + + class AVIVideoTrack : public FixedRateVideoTrack { + public: + AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader); + ~AVIVideoTrack(); + + void decodeFrame(Common::SeekableReadStream *stream); + + uint16 getWidth() const { return _bmInfo.width; } + uint16 getHeight() const { return _bmInfo.height; } + Graphics::PixelFormat getPixelFormat() const; + int getCurFrame() const { return _curFrame; } + int getFrameCount() const { return _frameCount; } + const Graphics::Surface *decodeNextFrame() { return _lastFrame; } + const byte *getPalette() const { _dirtyPalette = false; return _palette; } + bool hasDirtyPalette() const { return _dirtyPalette; } + void markPaletteDirty() { _dirtyPalette = true; } + + protected: + Common::Rational getFrameRate() const { return Common::Rational(_vidsHeader.rate, _vidsHeader.scale); } + + private: + AVIStreamHeader _vidsHeader; + BitmapInfoHeader _bmInfo; + byte _palette[3 * 256]; + mutable bool _dirtyPalette; + int _frameCount, _curFrame; + + Codec *_videoCodec; + const Graphics::Surface *_lastFrame; + Codec *createCodec(); + }; + + class AVIAudioTrack : public AudioTrack { + public: + AVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType); + ~AVIAudioTrack(); + + void queueSound(Common::SeekableReadStream *stream); + Audio::Mixer::SoundType getSoundType() const { return _soundType; } + + protected: + Audio::AudioStream *getAudioStream() const; + + private: + // Audio Codecs + enum { + kWaveFormatNone = 0, + kWaveFormatPCM = 1, + kWaveFormatDK3 = 98 + }; + + AVIStreamHeader _audsHeader; + PCMWaveFormat _wvInfo; + Audio::Mixer::SoundType _soundType; + Audio::QueuingAudioStream *_audStream; + Audio::QueuingAudioStream *createAudioStream(); + }; + + OldIndex _ixInfo; + AVIHeader _header; Common::SeekableReadStream *_fileStream; bool _decodedHeader; - Codec *_videoCodec; - Codec *createCodec(); - Audio::Mixer::SoundType _soundType; void runHandle(uint32 tag); void handleList(); void handleStreamHeader(); - void handlePalChange(); - - Audio::SoundHandle *_audHandle; - Audio::QueuingAudioStream *_audStream; - Audio::QueuingAudioStream *createAudioStream(); - void queueAudioBuffer(uint32 chunkSize); }; } // End of namespace Video diff --git a/video/bink_decoder.cpp b/video/bink_decoder.cpp index 884ca69f17..620316806f 100644 --- a/video/bink_decoder.cpp +++ b/video/bink_decoder.cpp @@ -24,6 +24,7 @@ // based quite heavily on the Bink decoder found in FFmpeg. // Many thanks to Kostya Shishkov for doing the hard work. +#include "audio/audiostream.h" #include "audio/decoders/raw.h" #include "common/util.h" @@ -60,139 +61,108 @@ static const uint32 kDCStartBits = 11; namespace Video { -BinkDecoder::VideoFrame::VideoFrame() : bits(0) { -} - -BinkDecoder::VideoFrame::~VideoFrame() { - delete bits; +BinkDecoder::BinkDecoder() { + _bink = 0; } - -BinkDecoder::AudioTrack::AudioTrack() : bits(0), bands(0), rdft(0), dct(0) { +BinkDecoder::~BinkDecoder() { + close(); } -BinkDecoder::AudioTrack::~AudioTrack() { - delete bits; - - delete[] bands; - - delete rdft; - delete dct; -} +bool BinkDecoder::loadStream(Common::SeekableReadStream *stream) { + close(); + uint32 id = stream->readUint32BE(); + if ((id != kBIKfID) && (id != kBIKgID) && (id != kBIKhID) && (id != kBIKiID)) + return false; -BinkDecoder::BinkDecoder() { - _bink = 0; - _audioTrack = 0; + uint32 fileSize = stream->readUint32LE() + 8; + uint32 frameCount = stream->readUint32LE(); + uint32 largestFrameSize = stream->readUint32LE(); - for (int i = 0; i < 16; i++) - _huffman[i] = 0; + if (largestFrameSize > fileSize) { + warning("Largest frame size greater than file size"); + return false; + } - for (int i = 0; i < kSourceMAX; i++) { - _bundles[i].countLength = 0; + stream->skip(4); - _bundles[i].huffman.index = 0; - for (int j = 0; j < 16; j++) - _bundles[i].huffman.symbols[j] = j; + uint32 width = stream->readUint32LE(); + uint32 height = stream->readUint32LE(); - _bundles[i].data = 0; - _bundles[i].dataEnd = 0; - _bundles[i].curDec = 0; - _bundles[i].curPtr = 0; + uint32 frameRateNum = stream->readUint32LE(); + uint32 frameRateDen = stream->readUint32LE(); + if (frameRateNum == 0 || frameRateDen == 0) { + warning("Invalid frame rate (%d/%d)", frameRateNum, frameRateDen); + return false; } - for (int i = 0; i < 16; i++) { - _colHighHuffman[i].index = 0; - for (int j = 0; j < 16; j++) - _colHighHuffman[i].symbols[j] = j; - } + _bink = stream; - for (int i = 0; i < 4; i++) { - _curPlanes[i] = 0; - _oldPlanes[i] = 0; - } + uint32 videoFlags = _bink->readUint32LE(); - _audioStream = 0; -} + // BIKh and BIKi swap the chroma planes + addTrack(new BinkVideoTrack(width, height, getDefaultHighColorFormat(), frameCount, + Common::Rational(frameRateNum, frameRateDen), (id == kBIKhID || id == kBIKiID), videoFlags & kVideoFlagAlpha, id)); -void BinkDecoder::startAudio() { - if (_audioTrack < _audioTracks.size()) { - const AudioTrack &audio = _audioTracks[_audioTrack]; + uint32 audioTrackCount = _bink->readUint32LE(); - _audioStream = Audio::makeQueuingAudioStream(audio.outSampleRate, audio.outChannels == 2); - g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audioHandle, _audioStream); - } // else no audio -} + if (audioTrackCount > 0) { + _audioTracks.reserve(audioTrackCount); -void BinkDecoder::stopAudio() { - if (_audioStream) { - g_system->getMixer()->stopHandle(_audioHandle); - _audioStream = 0; - } -} + _bink->skip(4 * audioTrackCount); -BinkDecoder::~BinkDecoder() { - close(); -} + // Reading audio track properties + for (uint32 i = 0; i < audioTrackCount; i++) { + AudioInfo track; -void BinkDecoder::close() { - reset(); + track.sampleRate = _bink->readUint16LE(); + track.flags = _bink->readUint16LE(); - // Stop audio - stopAudio(); + _audioTracks.push_back(track); - for (int i = 0; i < 4; i++) { - delete[] _curPlanes[i]; _curPlanes[i] = 0; - delete[] _oldPlanes[i]; _oldPlanes[i] = 0; + initAudioTrack(_audioTracks[i]); + } + + _bink->skip(4 * audioTrackCount); } - deinitBundles(); + // Reading video frame properties + _frames.resize(frameCount); + for (uint32 i = 0; i < frameCount; i++) { + _frames[i].offset = _bink->readUint32LE(); + _frames[i].keyFrame = _frames[i].offset & 1; - for (int i = 0; i < 16; i++) { - delete _huffman[i]; - _huffman[i] = 0; - } + _frames[i].offset &= ~1; - delete _bink; _bink = 0; - _surface.free(); + if (i != 0) + _frames[i - 1].size = _frames[i].offset - _frames[i - 1].offset; - _audioTrack = 0; + _frames[i].bits = 0; + } - for (int i = 0; i < kSourceMAX; i++) { - _bundles[i].countLength = 0; + _frames[frameCount - 1].size = _bink->size() - _frames[frameCount - 1].offset; - _bundles[i].huffman.index = 0; - for (int j = 0; j < 16; j++) - _bundles[i].huffman.symbols[j] = j; + return true; +} - _bundles[i].data = 0; - _bundles[i].dataEnd = 0; - _bundles[i].curDec = 0; - _bundles[i].curPtr = 0; - } +void BinkDecoder::close() { + VideoDecoder::close(); - for (int i = 0; i < 16; i++) { - _colHighHuffman[i].index = 0; - for (int j = 0; j < 16; j++) - _colHighHuffman[i].symbols[j] = j; - } + delete _bink; + _bink = 0; _audioTracks.clear(); _frames.clear(); } -uint32 BinkDecoder::getElapsedTime() const { - if (_audioStream && g_system->getMixer()->isSoundHandleActive(_audioHandle)) - return g_system->getMixer()->getSoundElapsedTime(_audioHandle) + _audioStartOffset; +void BinkDecoder::readNextPacket() { + BinkVideoTrack *videoTrack = (BinkVideoTrack *)getTrack(0); - return g_system->getMillis() - _startTime; -} - -const Graphics::Surface *BinkDecoder::decodeNextFrame() { - if (endOfVideo()) - return 0; + if (videoTrack->endOfTrack()) + return; - VideoFrame &frame = _frames[_curFrame + 1]; + VideoFrame &frame = _frames[videoTrack->getCurFrame() + 1]; if (!_bink->seek(frame.offset)) error("Bad bink seek"); @@ -200,7 +170,7 @@ const Graphics::Surface *BinkDecoder::decodeNextFrame() { uint32 frameSize = frame.size; for (uint32 i = 0; i < _audioTracks.size(); i++) { - AudioTrack &audio = _audioTracks[i]; + AudioInfo &audio = _audioTracks[i]; uint32 audioPacketLength = _bink->readUint32LE(); @@ -210,24 +180,21 @@ const Graphics::Surface *BinkDecoder::decodeNextFrame() { error("Audio packet too big for the frame"); if (audioPacketLength >= 4) { + // Get our track - audio index plus one as the first track is video + BinkAudioTrack *audioTrack = (BinkAudioTrack *)getTrack(i + 1); uint32 audioPacketStart = _bink->pos(); uint32 audioPacketEnd = _bink->pos() + audioPacketLength; - if (i == _audioTrack) { - // Only play one audio track - - // Number of samples in bytes - audio.sampleCount = _bink->readUint32LE() / (2 * audio.channels); + // Number of samples in bytes + audio.sampleCount = _bink->readUint32LE() / (2 * audio.channels); - audio.bits = - new Common::BitStream32LELSB(new Common::SeekableSubReadStream(_bink, - audioPacketStart + 4, audioPacketEnd), true); + audio.bits = new Common::BitStream32LELSB(new Common::SeekableSubReadStream(_bink, + audioPacketStart + 4, audioPacketEnd), true); - audioPacket(audio); + audioTrack->decodePacket(); - delete audio.bits; - audio.bits = 0; - } + delete audio.bits; + audio.bits = 0; _bink->seek(audioPacketEnd); @@ -238,67 +205,125 @@ const Graphics::Surface *BinkDecoder::decodeNextFrame() { uint32 videoPacketStart = _bink->pos(); uint32 videoPacketEnd = _bink->pos() + frameSize; - frame.bits = - new Common::BitStream32LELSB(new Common::SeekableSubReadStream(_bink, - videoPacketStart, videoPacketEnd), true); + frame.bits = new Common::BitStream32LELSB(new Common::SeekableSubReadStream(_bink, + videoPacketStart, videoPacketEnd), true); - videoPacket(frame); + videoTrack->decodePacket(frame); delete frame.bits; frame.bits = 0; +} - _curFrame++; - if (_curFrame == 0) - _startTime = g_system->getMillis(); +BinkDecoder::VideoFrame::VideoFrame() : bits(0) { +} - return &_surface; +BinkDecoder::VideoFrame::~VideoFrame() { + delete bits; } -void BinkDecoder::audioPacket(AudioTrack &audio) { - if (!_audioStream) - return; - int outSize = audio.frameLen * audio.channels; - while (audio.bits->pos() < audio.bits->size()) { - int16 *out = (int16 *)malloc(outSize * 2); - memset(out, 0, outSize * 2); +BinkDecoder::AudioInfo::AudioInfo() : bits(0), bands(0), rdft(0), dct(0) { +} - audioBlock(audio, out); +BinkDecoder::AudioInfo::~AudioInfo() { + delete bits; - byte flags = Audio::FLAG_16BITS; - if (audio.outChannels == 2) - flags |= Audio::FLAG_STEREO; + delete[] bands; -#ifdef SCUMM_LITTLE_ENDIAN - flags |= Audio::FLAG_LITTLE_ENDIAN; -#endif + delete rdft; + delete dct; +} + +BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, const Graphics::PixelFormat &format, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id) : + _frameCount(frameCount), _frameRate(frameRate), _swapPlanes(swapPlanes), _hasAlpha(hasAlpha), _id(id) { + _curFrame = -1; + + for (int i = 0; i < 16; i++) + _huffman[i] = 0; + + for (int i = 0; i < kSourceMAX; i++) { + _bundles[i].countLength = 0; + + _bundles[i].huffman.index = 0; + for (int j = 0; j < 16; j++) + _bundles[i].huffman.symbols[j] = j; + + _bundles[i].data = 0; + _bundles[i].dataEnd = 0; + _bundles[i].curDec = 0; + _bundles[i].curPtr = 0; + } + + for (int i = 0; i < 16; i++) { + _colHighHuffman[i].index = 0; + for (int j = 0; j < 16; j++) + _colHighHuffman[i].symbols[j] = j; + } + + _surface.create(width, height, format); + + // Give the planes a bit extra space + width = _surface.w + 32; + height = _surface.h + 32; + + _curPlanes[0] = new byte[ width * height ]; // Y + _curPlanes[1] = new byte[(width >> 1) * (height >> 1)]; // U, 1/4 resolution + _curPlanes[2] = new byte[(width >> 1) * (height >> 1)]; // V, 1/4 resolution + _curPlanes[3] = new byte[ width * height ]; // A + _oldPlanes[0] = new byte[ width * height ]; // Y + _oldPlanes[1] = new byte[(width >> 1) * (height >> 1)]; // U, 1/4 resolution + _oldPlanes[2] = new byte[(width >> 1) * (height >> 1)]; // V, 1/4 resolution + _oldPlanes[3] = new byte[ width * height ]; // A + + // Initialize the video with solid black + memset(_curPlanes[0], 0, width * height ); + memset(_curPlanes[1], 0, (width >> 1) * (height >> 1)); + memset(_curPlanes[2], 0, (width >> 1) * (height >> 1)); + memset(_curPlanes[3], 255, width * height ); + memset(_oldPlanes[0], 0, width * height ); + memset(_oldPlanes[1], 0, (width >> 1) * (height >> 1)); + memset(_oldPlanes[2], 0, (width >> 1) * (height >> 1)); + memset(_oldPlanes[3], 255, width * height ); - _audioStream->queueBuffer((byte *)out, audio.blockSize * 2, DisposeAfterUse::YES, flags); + initBundles(); + initHuffman(); +} - if (audio.bits->pos() & 0x1F) // next data block starts at a 32-byte boundary - audio.bits->skip(32 - (audio.bits->pos() & 0x1F)); +BinkDecoder::BinkVideoTrack::~BinkVideoTrack() { + for (int i = 0; i < 4; i++) { + delete[] _curPlanes[i]; _curPlanes[i] = 0; + delete[] _oldPlanes[i]; _oldPlanes[i] = 0; } + + deinitBundles(); + + for (int i = 0; i < 16; i++) { + delete _huffman[i]; + _huffman[i] = 0; + } + + _surface.free(); } -void BinkDecoder::videoPacket(VideoFrame &video) { - assert(video.bits); +void BinkDecoder::BinkVideoTrack::decodePacket(VideoFrame &frame) { + assert(frame.bits); if (_hasAlpha) { if (_id == kBIKiID) - video.bits->skip(32); + frame.bits->skip(32); - decodePlane(video, 3, false); + decodePlane(frame, 3, false); } if (_id == kBIKiID) - video.bits->skip(32); + frame.bits->skip(32); for (int i = 0; i < 3; i++) { int planeIdx = ((i == 0) || !_swapPlanes) ? i : (i ^ 3); - decodePlane(video, planeIdx, i != 0); + decodePlane(frame, planeIdx, i != 0); - if (video.bits->pos() >= video.bits->size()) + if (frame.bits->pos() >= frame.bits->size()) break; } @@ -311,10 +336,11 @@ void BinkDecoder::videoPacket(VideoFrame &video) { // And swap the planes with the reference planes for (int i = 0; i < 4; i++) SWAP(_curPlanes[i], _oldPlanes[i]); -} -void BinkDecoder::decodePlane(VideoFrame &video, int planeIdx, bool isChroma) { + _curFrame++; +} +void BinkDecoder::BinkVideoTrack::decodePlane(VideoFrame &video, int planeIdx, bool isChroma) { uint32 blockWidth = isChroma ? ((_surface.w + 15) >> 4) : ((_surface.w + 7) >> 3); uint32 blockHeight = isChroma ? ((_surface.h + 15) >> 4) : ((_surface.h + 7) >> 3); uint32 width = isChroma ? (_surface.w >> 1) : _surface.w; @@ -371,48 +397,38 @@ void BinkDecoder::decodePlane(VideoFrame &video, int planeIdx, bool isChroma) { } switch (blockType) { - case kBlockSkip: - blockSkip(ctx); - break; - - case kBlockScaled: - blockScaled(ctx); - break; - - case kBlockMotion: - blockMotion(ctx); - break; - - case kBlockRun: - blockRun(ctx); - break; - - case kBlockResidue: - blockResidue(ctx); - break; - - case kBlockIntra: - blockIntra(ctx); - break; - - case kBlockFill: - blockFill(ctx); - break; - - case kBlockInter: - blockInter(ctx); - break; - - case kBlockPattern: - blockPattern(ctx); - break; - - case kBlockRaw: - blockRaw(ctx); - break; - - default: - error("Unknown block type: %d", blockType); + case kBlockSkip: + blockSkip(ctx); + break; + case kBlockScaled: + blockScaled(ctx); + break; + case kBlockMotion: + blockMotion(ctx); + break; + case kBlockRun: + blockRun(ctx); + break; + case kBlockResidue: + blockResidue(ctx); + break; + case kBlockIntra: + blockIntra(ctx); + break; + case kBlockFill: + blockFill(ctx); + break; + case kBlockInter: + blockInter(ctx); + break; + case kBlockPattern: + blockPattern(ctx); + break; + case kBlockRaw: + blockRaw(ctx); + break; + default: + error("Unknown block type: %d", blockType); } } @@ -424,7 +440,7 @@ void BinkDecoder::decodePlane(VideoFrame &video, int planeIdx, bool isChroma) { } -void BinkDecoder::readBundle(VideoFrame &video, Source source) { +void BinkDecoder::BinkVideoTrack::readBundle(VideoFrame &video, Source source) { if (source == kSourceColors) { for (int i = 0; i < 16; i++) readHuffman(video, _colHighHuffman[i]); @@ -439,12 +455,11 @@ void BinkDecoder::readBundle(VideoFrame &video, Source source) { _bundles[source].curPtr = _bundles[source].data; } -void BinkDecoder::readHuffman(VideoFrame &video, Huffman &huffman) { +void BinkDecoder::BinkVideoTrack::readHuffman(VideoFrame &video, Huffman &huffman) { huffman.index = video.bits->getBits(4); if (huffman.index == 0) { // The first tree always gives raw nibbles - for (int i = 0; i < 16; i++) huffman.symbols[i] = i; @@ -455,7 +470,6 @@ void BinkDecoder::readHuffman(VideoFrame &video, Huffman &huffman) { if (video.bits->getBit()) { // Symbol selection - memset(hasSymbol, 0, 16); uint8 length = video.bits->getBits(3); @@ -493,9 +507,9 @@ void BinkDecoder::readHuffman(VideoFrame &video, Huffman &huffman) { memcpy(huffman.symbols, in, 16); } -void BinkDecoder::mergeHuffmanSymbols(VideoFrame &video, byte *dst, const byte *src, int size) { +void BinkDecoder::BinkVideoTrack::mergeHuffmanSymbols(VideoFrame &video, byte *dst, const byte *src, int size) { const byte *src2 = src + size; - int size2 = size; + int size2 = size; do { if (!video.bits->getBit()) { @@ -510,197 +524,12 @@ void BinkDecoder::mergeHuffmanSymbols(VideoFrame &video, byte *dst, const byte * while (size--) *dst++ = *src++; + while (size2--) *dst++ = *src2++; } -bool BinkDecoder::loadStream(Common::SeekableReadStream *stream) { - Graphics::PixelFormat format = g_system->getScreenFormat(); - return loadStream(stream, format); -} - -bool BinkDecoder::loadStream(Common::SeekableReadStream *stream, const Graphics::PixelFormat &format) { - close(); - - _id = stream->readUint32BE(); - if ((_id != kBIKfID) && (_id != kBIKgID) && (_id != kBIKhID) && (_id != kBIKiID)) - return false; - - uint32 fileSize = stream->readUint32LE() + 8; - uint32 frameCount = stream->readUint32LE(); - uint32 largestFrameSize = stream->readUint32LE(); - - if (largestFrameSize > fileSize) { - warning("Largest frame size greater than file size"); - return false; - } - - stream->skip(4); - - uint32 width = stream->readUint32LE(); - uint32 height = stream->readUint32LE(); - - uint32 frameRateNum = stream->readUint32LE(); - uint32 frameRateDen = stream->readUint32LE(); - if (frameRateNum == 0 || frameRateDen == 0) { - warning("Invalid frame rate (%d/%d)", frameRateNum, frameRateDen); - return false; - } - - _frameRate = Common::Rational(frameRateNum, frameRateDen); - _bink = stream; - - _videoFlags = _bink->readUint32LE(); - - uint32 audioTrackCount = _bink->readUint32LE(); - - if (audioTrackCount > 1) { - warning("More than one audio track found. Using the first one"); - - _audioTrack = 0; - } - - if (audioTrackCount > 0) { - _audioTracks.reserve(audioTrackCount); - - _bink->skip(4 * audioTrackCount); - - // Reading audio track properties - for (uint32 i = 0; i < audioTrackCount; i++) { - AudioTrack track; - - track.sampleRate = _bink->readUint16LE(); - track.flags = _bink->readUint16LE(); - - _audioTracks.push_back(track); - - initAudioTrack(_audioTracks[i]); - } - - _bink->skip(4 * audioTrackCount); - } - - // Reading video frame properties - _frames.resize(frameCount); - for (uint32 i = 0; i < frameCount; i++) { - _frames[i].offset = _bink->readUint32LE(); - _frames[i].keyFrame = _frames[i].offset & 1; - - _frames[i].offset &= ~1; - - if (i != 0) - _frames[i - 1].size = _frames[i].offset - _frames[i - 1].offset; - - _frames[i].bits = 0; - } - - _frames[frameCount - 1].size = _bink->size() - _frames[frameCount - 1].offset; - - _hasAlpha = _videoFlags & kVideoFlagAlpha; - _swapPlanes = (_id == kBIKhID) || (_id == kBIKiID); // BIKh and BIKi swap the chroma planes - - _surface.create(width, height, format); - - // Give the planes a bit extra space - width = _surface.w + 32; - height = _surface.h + 32; - - _curPlanes[0] = new byte[ width * height ]; // Y - _curPlanes[1] = new byte[(width >> 1) * (height >> 1)]; // U, 1/4 resolution - _curPlanes[2] = new byte[(width >> 1) * (height >> 1)]; // V, 1/4 resolution - _curPlanes[3] = new byte[ width * height ]; // A - _oldPlanes[0] = new byte[ width * height ]; // Y - _oldPlanes[1] = new byte[(width >> 1) * (height >> 1)]; // U, 1/4 resolution - _oldPlanes[2] = new byte[(width >> 1) * (height >> 1)]; // V, 1/4 resolution - _oldPlanes[3] = new byte[ width * height ]; // A - - // Initialize the video with solid black - memset(_curPlanes[0], 0, width * height ); - memset(_curPlanes[1], 0, (width >> 1) * (height >> 1)); - memset(_curPlanes[2], 0, (width >> 1) * (height >> 1)); - memset(_curPlanes[3], 255, width * height ); - memset(_oldPlanes[0], 0, width * height ); - memset(_oldPlanes[1], 0, (width >> 1) * (height >> 1)); - memset(_oldPlanes[2], 0, (width >> 1) * (height >> 1)); - memset(_oldPlanes[3], 255, width * height ); - - initBundles(); - initHuffman(); - - startAudio(); - _audioStartOffset = 0; - - return true; -} - -void BinkDecoder::initAudioTrack(AudioTrack &audio) { - audio.sampleCount = 0; - audio.bits = 0; - - audio.channels = ((audio.flags & kAudioFlagStereo) != 0) ? 2 : 1; - audio.codec = ((audio.flags & kAudioFlagDCT ) != 0) ? kAudioCodecDCT : kAudioCodecRDFT; - - if (audio.channels > kAudioChannelsMax) - error("Too many audio channels: %d", audio.channels); - - uint32 frameLenBits; - // Calculate frame length - if (audio.sampleRate < 22050) - frameLenBits = 9; - else if(audio.sampleRate < 44100) - frameLenBits = 10; - else - frameLenBits = 11; - - audio.frameLen = 1 << frameLenBits; - - audio.outSampleRate = audio.sampleRate; - audio.outChannels = audio.channels; - - if (audio.codec == kAudioCodecRDFT) { - // RDFT audio already interleaves the samples correctly - - if (audio.channels == 2) - frameLenBits++; - - audio.sampleRate *= audio.channels; - audio.frameLen *= audio.channels; - audio.channels = 1; - } - - audio.overlapLen = audio.frameLen / 16; - audio.blockSize = (audio.frameLen - audio.overlapLen) * audio.channels; - audio.root = 2.0 / sqrt((double)audio.frameLen); - - uint32 sampleRateHalf = (audio.sampleRate + 1) / 2; - - // Calculate number of bands - for (audio.bandCount = 1; audio.bandCount < 25; audio.bandCount++) - if (sampleRateHalf <= binkCriticalFreqs[audio.bandCount - 1]) - break; - - audio.bands = new uint32[audio.bandCount + 1]; - - // Populate bands - audio.bands[0] = 1; - for (uint32 i = 1; i < audio.bandCount; i++) - audio.bands[i] = binkCriticalFreqs[i - 1] * (audio.frameLen / 2) / sampleRateHalf; - audio.bands[audio.bandCount] = audio.frameLen / 2; - - audio.first = true; - - for (uint8 i = 0; i < audio.channels; i++) - audio.coeffsPtr[i] = audio.coeffs + i * audio.frameLen; - - audio.codec = ((audio.flags & kAudioFlagDCT) != 0) ? kAudioCodecDCT : kAudioCodecRDFT; - - if (audio.codec == kAudioCodecRDFT) - audio.rdft = new Common::RDFT(frameLenBits, Common::RDFT::DFT_C2R); - else if (audio.codec == kAudioCodecDCT) - audio.dct = new Common::DCT(frameLenBits, Common::DCT::DCT_III); -} - -void BinkDecoder::initBundles() { +void BinkDecoder::BinkVideoTrack::initBundles() { uint32 bw = (_surface.w + 7) >> 3; uint32 bh = (_surface.h + 7) >> 3; uint32 blocks = bw * bh; @@ -729,21 +558,21 @@ void BinkDecoder::initBundles() { } } -void BinkDecoder::deinitBundles() { +void BinkDecoder::BinkVideoTrack::deinitBundles() { for (int i = 0; i < kSourceMAX; i++) delete[] _bundles[i].data; } -void BinkDecoder::initHuffman() { +void BinkDecoder::BinkVideoTrack::initHuffman() { for (int i = 0; i < 16; i++) _huffman[i] = new Common::Huffman(binkHuffmanLengths[i][15], 16, binkHuffmanCodes[i], binkHuffmanLengths[i]); } -byte BinkDecoder::getHuffmanSymbol(VideoFrame &video, Huffman &huffman) { +byte BinkDecoder::BinkVideoTrack::getHuffmanSymbol(VideoFrame &video, Huffman &huffman) { return huffman.symbols[_huffman[huffman.index]->getSymbol(*video.bits)]; } -int32 BinkDecoder::getBundleValue(Source source) { +int32 BinkDecoder::BinkVideoTrack::getBundleValue(Source source) { if ((source < kSourceXOff) || (source == kSourceRun)) return *_bundles[source].curPtr++; @@ -757,7 +586,7 @@ int32 BinkDecoder::getBundleValue(Source source) { return ret; } -uint32 BinkDecoder::readBundleCount(VideoFrame &video, Bundle &bundle) { +uint32 BinkDecoder::BinkVideoTrack::readBundleCount(VideoFrame &video, Bundle &bundle) { if (!bundle.curDec || (bundle.curDec > bundle.curPtr)) return 0; @@ -768,7 +597,7 @@ uint32 BinkDecoder::readBundleCount(VideoFrame &video, Bundle &bundle) { return n; } -void BinkDecoder::blockSkip(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockSkip(DecodeContext &ctx) { byte *dest = ctx.dest; byte *prev = ctx.prev; @@ -776,7 +605,7 @@ void BinkDecoder::blockSkip(DecodeContext &ctx) { memcpy(dest, prev, 8); } -void BinkDecoder::blockScaledSkip(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockScaledSkip(DecodeContext &ctx) { byte *dest = ctx.dest; byte *prev = ctx.prev; @@ -784,7 +613,7 @@ void BinkDecoder::blockScaledSkip(DecodeContext &ctx) { memcpy(dest, prev, 16); } -void BinkDecoder::blockScaledRun(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockScaledRun(DecodeContext &ctx) { const uint8 *scan = binkPatterns[ctx.video->bits->getBits(4)]; int i = 0; @@ -820,7 +649,7 @@ void BinkDecoder::blockScaledRun(DecodeContext &ctx) { ctx.dest[ctx.coordScaledMap4[*scan]] = getBundleValue(kSourceColors); } -void BinkDecoder::blockScaledIntra(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockScaledIntra(DecodeContext &ctx) { int16 block[64]; memset(block, 0, 64 * sizeof(int16)); @@ -841,7 +670,7 @@ void BinkDecoder::blockScaledIntra(DecodeContext &ctx) { } } -void BinkDecoder::blockScaledFill(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockScaledFill(DecodeContext &ctx) { byte v = getBundleValue(kSourceColors); byte *dest = ctx.dest; @@ -849,7 +678,7 @@ void BinkDecoder::blockScaledFill(DecodeContext &ctx) { memset(dest, v, 16); } -void BinkDecoder::blockScaledPattern(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockScaledPattern(DecodeContext &ctx) { byte col[2]; for (int i = 0; i < 2; i++) @@ -865,7 +694,7 @@ void BinkDecoder::blockScaledPattern(DecodeContext &ctx) { } } -void BinkDecoder::blockScaledRaw(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockScaledRaw(DecodeContext &ctx) { byte row[8]; byte *dest1 = ctx.dest; @@ -880,32 +709,27 @@ void BinkDecoder::blockScaledRaw(DecodeContext &ctx) { } } -void BinkDecoder::blockScaled(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockScaled(DecodeContext &ctx) { BlockType blockType = (BlockType) getBundleValue(kSourceSubBlockTypes); switch (blockType) { - case kBlockRun: - blockScaledRun(ctx); - break; - - case kBlockIntra: - blockScaledIntra(ctx); - break; - - case kBlockFill: - blockScaledFill(ctx); - break; - - case kBlockPattern: - blockScaledPattern(ctx); - break; - - case kBlockRaw: - blockScaledRaw(ctx); - break; - - default: - error("Invalid 16x16 block type: %d", blockType); + case kBlockRun: + blockScaledRun(ctx); + break; + case kBlockIntra: + blockScaledIntra(ctx); + break; + case kBlockFill: + blockScaledFill(ctx); + break; + case kBlockPattern: + blockScaledPattern(ctx); + break; + case kBlockRaw: + blockScaledRaw(ctx); + break; + default: + error("Invalid 16x16 block type: %d", blockType); } ctx.blockX += 1; @@ -913,7 +737,7 @@ void BinkDecoder::blockScaled(DecodeContext &ctx) { ctx.prev += 8; } -void BinkDecoder::blockMotion(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockMotion(DecodeContext &ctx) { int8 xOff = getBundleValue(kSourceXOff); int8 yOff = getBundleValue(kSourceYOff); @@ -926,7 +750,7 @@ void BinkDecoder::blockMotion(DecodeContext &ctx) { memcpy(dest, prev, 8); } -void BinkDecoder::blockRun(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockRun(DecodeContext &ctx) { const uint8 *scan = binkPatterns[ctx.video->bits->getBits(4)]; int i = 0; @@ -953,7 +777,7 @@ void BinkDecoder::blockRun(DecodeContext &ctx) { ctx.dest[ctx.coordMap[*scan++]] = getBundleValue(kSourceColors); } -void BinkDecoder::blockResidue(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockResidue(DecodeContext &ctx) { blockMotion(ctx); byte v = ctx.video->bits->getBits(7); @@ -970,7 +794,7 @@ void BinkDecoder::blockResidue(DecodeContext &ctx) { dst[j] += src[j]; } -void BinkDecoder::blockIntra(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockIntra(DecodeContext &ctx) { int16 block[64]; memset(block, 0, 64 * sizeof(int16)); @@ -981,7 +805,7 @@ void BinkDecoder::blockIntra(DecodeContext &ctx) { IDCTPut(ctx, block); } -void BinkDecoder::blockFill(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockFill(DecodeContext &ctx) { byte v = getBundleValue(kSourceColors); byte *dest = ctx.dest; @@ -989,7 +813,7 @@ void BinkDecoder::blockFill(DecodeContext &ctx) { memset(dest, v, 8); } -void BinkDecoder::blockInter(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockInter(DecodeContext &ctx) { blockMotion(ctx); int16 block[64]; @@ -1002,7 +826,7 @@ void BinkDecoder::blockInter(DecodeContext &ctx) { IDCTAdd(ctx, block); } -void BinkDecoder::blockPattern(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockPattern(DecodeContext &ctx) { byte col[2]; for (int i = 0; i < 2; i++) @@ -1017,7 +841,7 @@ void BinkDecoder::blockPattern(DecodeContext &ctx) { } } -void BinkDecoder::blockRaw(DecodeContext &ctx) { +void BinkDecoder::BinkVideoTrack::blockRaw(DecodeContext &ctx) { byte *dest = ctx.dest; byte *data = _bundles[kSourceColors].curPtr; for (int i = 0; i < 8; i++, dest += ctx.pitch, data += 8) @@ -1026,7 +850,7 @@ void BinkDecoder::blockRaw(DecodeContext &ctx) { _bundles[kSourceColors].curPtr += 64; } -void BinkDecoder::readRuns(VideoFrame &video, Bundle &bundle) { +void BinkDecoder::BinkVideoTrack::readRuns(VideoFrame &video, Bundle &bundle) { uint32 n = readBundleCount(video, bundle); if (n == 0) return; @@ -1046,7 +870,7 @@ void BinkDecoder::readRuns(VideoFrame &video, Bundle &bundle) { *bundle.curDec++ = getHuffmanSymbol(video, bundle.huffman); } -void BinkDecoder::readMotionValues(VideoFrame &video, Bundle &bundle) { +void BinkDecoder::BinkVideoTrack::readMotionValues(VideoFrame &video, Bundle &bundle) { uint32 n = readBundleCount(video, bundle); if (n == 0) return; @@ -1083,7 +907,7 @@ void BinkDecoder::readMotionValues(VideoFrame &video, Bundle &bundle) { } const uint8 rleLens[4] = { 4, 8, 12, 32 }; -void BinkDecoder::readBlockTypes(VideoFrame &video, Bundle &bundle) { +void BinkDecoder::BinkVideoTrack::readBlockTypes(VideoFrame &video, Bundle &bundle) { uint32 n = readBundleCount(video, bundle); if (n == 0) return; @@ -1120,7 +944,7 @@ void BinkDecoder::readBlockTypes(VideoFrame &video, Bundle &bundle) { } while (bundle.curDec < decEnd); } -void BinkDecoder::readPatterns(VideoFrame &video, Bundle &bundle) { +void BinkDecoder::BinkVideoTrack::readPatterns(VideoFrame &video, Bundle &bundle) { uint32 n = readBundleCount(video, bundle); if (n == 0) return; @@ -1138,7 +962,7 @@ void BinkDecoder::readPatterns(VideoFrame &video, Bundle &bundle) { } -void BinkDecoder::readColors(VideoFrame &video, Bundle &bundle) { +void BinkDecoder::BinkVideoTrack::readColors(VideoFrame &video, Bundle &bundle) { uint32 n = readBundleCount(video, bundle); if (n == 0) return; @@ -1182,7 +1006,7 @@ void BinkDecoder::readColors(VideoFrame &video, Bundle &bundle) { } } -void BinkDecoder::readDCS(VideoFrame &video, Bundle &bundle, int startBits, bool hasSign) { +void BinkDecoder::BinkVideoTrack::readDCS(VideoFrame &video, Bundle &bundle, int startBits, bool hasSign) { uint32 length = readBundleCount(video, bundle); if (length == 0) return; @@ -1228,7 +1052,7 @@ void BinkDecoder::readDCS(VideoFrame &video, Bundle &bundle, int startBits, bool } /** Reads 8x8 block of DCT coefficients. */ -void BinkDecoder::readDCTCoeffs(VideoFrame &video, int16 *block, bool isIntra) { +void BinkDecoder::BinkVideoTrack::readDCTCoeffs(VideoFrame &video, int16 *block, bool isIntra) { int coefCount = 0; int coefIdx[64]; @@ -1326,7 +1150,7 @@ void BinkDecoder::readDCTCoeffs(VideoFrame &video, int16 *block, bool isIntra) { } /** Reads 8x8 block with residue after motion compensation. */ -void BinkDecoder::readResidue(VideoFrame &video, int16 *block, int masksCount) { +void BinkDecoder::BinkVideoTrack::readResidue(VideoFrame &video, int16 *block, int masksCount) { int nzCoeff[64]; int nzCoeffCount = 0; @@ -1417,63 +1241,170 @@ void BinkDecoder::readResidue(VideoFrame &video, int16 *block, int masksCount) { } } -float BinkDecoder::getFloat(AudioTrack &audio) { - int power = audio.bits->getBits(5); +#define A1 2896 /* (1/sqrt(2))<<12 */ +#define A2 2217 +#define A3 3784 +#define A4 -5352 - float f = ldexp((float)audio.bits->getBits(23), power - 23); +#define IDCT_TRANSFORM(dest,s0,s1,s2,s3,s4,s5,s6,s7,d0,d1,d2,d3,d4,d5,d6,d7,munge,src) {\ + const int a0 = (src)[s0] + (src)[s4]; \ + const int a1 = (src)[s0] - (src)[s4]; \ + const int a2 = (src)[s2] + (src)[s6]; \ + const int a3 = (A1*((src)[s2] - (src)[s6])) >> 11; \ + const int a4 = (src)[s5] + (src)[s3]; \ + const int a5 = (src)[s5] - (src)[s3]; \ + const int a6 = (src)[s1] + (src)[s7]; \ + const int a7 = (src)[s1] - (src)[s7]; \ + const int b0 = a4 + a6; \ + const int b1 = (A3*(a5 + a7)) >> 11; \ + const int b2 = ((A4*a5) >> 11) - b0 + b1; \ + const int b3 = (A1*(a6 - a4) >> 11) - b2; \ + const int b4 = ((A2*a7) >> 11) + b3 - b1; \ + (dest)[d0] = munge(a0+a2 +b0); \ + (dest)[d1] = munge(a1+a3-a2+b2); \ + (dest)[d2] = munge(a1-a3+a2+b3); \ + (dest)[d3] = munge(a0-a2 -b4); \ + (dest)[d4] = munge(a0-a2 +b4); \ + (dest)[d5] = munge(a1-a3+a2-b3); \ + (dest)[d6] = munge(a1+a3-a2-b2); \ + (dest)[d7] = munge(a0+a2 -b0); \ +} +/* end IDCT_TRANSFORM macro */ - if (audio.bits->getBit()) - f = -f; +#define MUNGE_NONE(x) (x) +#define IDCT_COL(dest,src) IDCT_TRANSFORM(dest,0,8,16,24,32,40,48,56,0,8,16,24,32,40,48,56,MUNGE_NONE,src) - return f; +#define MUNGE_ROW(x) (((x) + 0x7F)>>8) +#define IDCT_ROW(dest,src) IDCT_TRANSFORM(dest,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,MUNGE_ROW,src) + +static inline void IDCTCol(int16 *dest, const int16 *src) { + if ((src[8] | src[16] | src[24] | src[32] | src[40] | src[48] | src[56]) == 0) { + dest[ 0] = + dest[ 8] = + dest[16] = + dest[24] = + dest[32] = + dest[40] = + dest[48] = + dest[56] = src[0]; + } else { + IDCT_COL(dest, src); + } +} + +void BinkDecoder::BinkVideoTrack::IDCT(int16 *block) { + int i; + int16 temp[64]; + + for (i = 0; i < 8; i++) + IDCTCol(&temp[i], &block[i]); + for (i = 0; i < 8; i++) { + IDCT_ROW( (&block[8*i]), (&temp[8*i]) ); + } +} + +void BinkDecoder::BinkVideoTrack::IDCTAdd(DecodeContext &ctx, int16 *block) { + int i, j; + + IDCT(block); + byte *dest = ctx.dest; + for (i = 0; i < 8; i++, dest += ctx.pitch, block += 8) + for (j = 0; j < 8; j++) + dest[j] += block[j]; +} + +void BinkDecoder::BinkVideoTrack::IDCTPut(DecodeContext &ctx, int16 *block) { + int i; + int16 temp[64]; + for (i = 0; i < 8; i++) + IDCTCol(&temp[i], &block[i]); + for (i = 0; i < 8; i++) { + IDCT_ROW( (&ctx.dest[i*ctx.pitch]), (&temp[8*i]) ); + } +} + +BinkDecoder::BinkAudioTrack::BinkAudioTrack(BinkDecoder::AudioInfo &audio) : _audioInfo(&audio) { + _audioStream = Audio::makeQueuingAudioStream(_audioInfo->outSampleRate, _audioInfo->outChannels == 2); +} + +BinkDecoder::BinkAudioTrack::~BinkAudioTrack() { + delete _audioStream; +} + +Audio::AudioStream *BinkDecoder::BinkAudioTrack::getAudioStream() const { + return _audioStream; +} + +void BinkDecoder::BinkAudioTrack::decodePacket() { + int outSize = _audioInfo->frameLen * _audioInfo->channels; + + while (_audioInfo->bits->pos() < _audioInfo->bits->size()) { + int16 *out = (int16 *)malloc(outSize * 2); + memset(out, 0, outSize * 2); + + audioBlock(out); + + byte flags = Audio::FLAG_16BITS; + if (_audioInfo->outChannels == 2) + flags |= Audio::FLAG_STEREO; + +#ifdef SCUMM_LITTLE_ENDIAN + flags |= Audio::FLAG_LITTLE_ENDIAN; +#endif + + _audioStream->queueBuffer((byte *)out, _audioInfo->blockSize * 2, DisposeAfterUse::YES, flags); + + if (_audioInfo->bits->pos() & 0x1F) // next data block starts at a 32-byte boundary + _audioInfo->bits->skip(32 - (_audioInfo->bits->pos() & 0x1F)); + } } -void BinkDecoder::audioBlock(AudioTrack &audio, int16 *out) { - if (audio.codec == kAudioCodecDCT) - audioBlockDCT (audio); - else if (audio.codec == kAudioCodecRDFT) - audioBlockRDFT(audio); +void BinkDecoder::BinkAudioTrack::audioBlock(int16 *out) { + if (_audioInfo->codec == kAudioCodecDCT) + audioBlockDCT (); + else if (_audioInfo->codec == kAudioCodecRDFT) + audioBlockRDFT(); - floatToInt16Interleave(out, const_cast<const float **>(audio.coeffsPtr), audio.frameLen, audio.channels); + floatToInt16Interleave(out, const_cast<const float **>(_audioInfo->coeffsPtr), _audioInfo->frameLen, _audioInfo->channels); - if (!audio.first) { - int count = audio.overlapLen * audio.channels; + if (!_audioInfo->first) { + int count = _audioInfo->overlapLen * _audioInfo->channels; int shift = Common::intLog2(count); for (int i = 0; i < count; i++) { - out[i] = (audio.prevCoeffs[i] * (count - i) + out[i] * i) >> shift; + out[i] = (_audioInfo->prevCoeffs[i] * (count - i) + out[i] * i) >> shift; } } - memcpy(audio.prevCoeffs, out + audio.blockSize, audio.overlapLen * audio.channels * sizeof(*out)); + memcpy(_audioInfo->prevCoeffs, out + _audioInfo->blockSize, _audioInfo->overlapLen * _audioInfo->channels * sizeof(*out)); - audio.first = false; + _audioInfo->first = false; } -void BinkDecoder::audioBlockDCT(AudioTrack &audio) { - audio.bits->skip(2); +void BinkDecoder::BinkAudioTrack::audioBlockDCT() { + _audioInfo->bits->skip(2); - for (uint8 i = 0; i < audio.channels; i++) { - float *coeffs = audio.coeffsPtr[i]; + for (uint8 i = 0; i < _audioInfo->channels; i++) { + float *coeffs = _audioInfo->coeffsPtr[i]; - readAudioCoeffs(audio, coeffs); + readAudioCoeffs(coeffs); coeffs[0] /= 0.5; - audio.dct->calc(coeffs); + _audioInfo->dct->calc(coeffs); - for (uint32 j = 0; j < audio.frameLen; j++) - coeffs[j] *= (audio.frameLen / 2.0); + for (uint32 j = 0; j < _audioInfo->frameLen; j++) + coeffs[j] *= (_audioInfo->frameLen / 2.0); } } -void BinkDecoder::audioBlockRDFT(AudioTrack &audio) { - for (uint8 i = 0; i < audio.channels; i++) { - float *coeffs = audio.coeffsPtr[i]; +void BinkDecoder::BinkAudioTrack::audioBlockRDFT() { + for (uint8 i = 0; i < _audioInfo->channels; i++) { + float *coeffs = _audioInfo->coeffsPtr[i]; - readAudioCoeffs(audio, coeffs); + readAudioCoeffs(coeffs); - audio.rdft->calc(coeffs); + _audioInfo->rdft->calc(coeffs); } } @@ -1481,56 +1412,56 @@ static const uint8 rleLengthTab[16] = { 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64 }; -void BinkDecoder::readAudioCoeffs(AudioTrack &audio, float *coeffs) { - coeffs[0] = getFloat(audio) * audio.root; - coeffs[1] = getFloat(audio) * audio.root; +void BinkDecoder::BinkAudioTrack::readAudioCoeffs(float *coeffs) { + coeffs[0] = getFloat() * _audioInfo->root; + coeffs[1] = getFloat() * _audioInfo->root; float quant[25]; - for (uint32 i = 0; i < audio.bandCount; i++) { - int value = audio.bits->getBits(8); + for (uint32 i = 0; i < _audioInfo->bandCount; i++) { + int value = _audioInfo->bits->getBits(8); // 0.066399999 / log10(M_E) - quant[i] = exp(MIN(value, 95) * 0.15289164787221953823f) * audio.root; + quant[i] = exp(MIN(value, 95) * 0.15289164787221953823f) * _audioInfo->root; } float q = 0.0; // Find band (k) int k; - for (k = 0; audio.bands[k] < 1; k++) + for (k = 0; _audioInfo->bands[k] < 1; k++) q = quant[k]; // Parse coefficients uint32 i = 2; - while (i < audio.frameLen) { + while (i < _audioInfo->frameLen) { uint32 j = 0; - if (audio.bits->getBit()) - j = i + rleLengthTab[audio.bits->getBits(4)] * 8; + if (_audioInfo->bits->getBit()) + j = i + rleLengthTab[_audioInfo->bits->getBits(4)] * 8; else j = i + 8; - j = MIN(j, audio.frameLen); + j = MIN(j, _audioInfo->frameLen); - int width = audio.bits->getBits(4); + int width = _audioInfo->bits->getBits(4); if (width == 0) { memset(coeffs + i, 0, (j - i) * sizeof(*coeffs)); i = j; - while (audio.bands[k] * 2 < i) + while (_audioInfo->bands[k] * 2 < i) q = quant[k++]; } else { while (i < j) { - if (audio.bands[k] * 2 == i) + if (_audioInfo->bands[k] * 2 == i) q = quant[k++]; - int coeff = audio.bits->getBits(width); + int coeff = _audioInfo->bits->getBits(width); if (coeff) { - if (audio.bits->getBit()) + if (_audioInfo->bits->getBit()) coeffs[i] = -q * coeff; else coeffs[i] = q * coeff; @@ -1548,10 +1479,10 @@ void BinkDecoder::readAudioCoeffs(AudioTrack &audio, float *coeffs) { } static inline int floatToInt16One(float src) { - return (int16) CLIP<int>((int) floor(src + 0.5), -32768, 32767); + return (int16)CLIP<int>((int)floor(src + 0.5), -32768, 32767); } -void BinkDecoder::floatToInt16Interleave(int16 *dst, const float **src, uint32 length, uint8 channels) { +void BinkDecoder::BinkAudioTrack::floatToInt16Interleave(int16 *dst, const float **src, uint32 length, uint8 channels) { if (channels == 2) { for (uint32 i = 0; i < length; i++) { dst[2 * i ] = floatToInt16One(src[0][i]); @@ -1564,87 +1495,84 @@ void BinkDecoder::floatToInt16Interleave(int16 *dst, const float **src, uint32 l } } -#define A1 2896 /* (1/sqrt(2))<<12 */ -#define A2 2217 -#define A3 3784 -#define A4 -5352 +float BinkDecoder::BinkAudioTrack::getFloat() { + int power = _audioInfo->bits->getBits(5); -#define IDCT_TRANSFORM(dest,s0,s1,s2,s3,s4,s5,s6,s7,d0,d1,d2,d3,d4,d5,d6,d7,munge,src) {\ - const int a0 = (src)[s0] + (src)[s4]; \ - const int a1 = (src)[s0] - (src)[s4]; \ - const int a2 = (src)[s2] + (src)[s6]; \ - const int a3 = (A1*((src)[s2] - (src)[s6])) >> 11; \ - const int a4 = (src)[s5] + (src)[s3]; \ - const int a5 = (src)[s5] - (src)[s3]; \ - const int a6 = (src)[s1] + (src)[s7]; \ - const int a7 = (src)[s1] - (src)[s7]; \ - const int b0 = a4 + a6; \ - const int b1 = (A3*(a5 + a7)) >> 11; \ - const int b2 = ((A4*a5) >> 11) - b0 + b1; \ - const int b3 = (A1*(a6 - a4) >> 11) - b2; \ - const int b4 = ((A2*a7) >> 11) + b3 - b1; \ - (dest)[d0] = munge(a0+a2 +b0); \ - (dest)[d1] = munge(a1+a3-a2+b2); \ - (dest)[d2] = munge(a1-a3+a2+b3); \ - (dest)[d3] = munge(a0-a2 -b4); \ - (dest)[d4] = munge(a0-a2 +b4); \ - (dest)[d5] = munge(a1-a3+a2-b3); \ - (dest)[d6] = munge(a1+a3-a2-b2); \ - (dest)[d7] = munge(a0+a2 -b0); \ + float f = ldexp((float)_audioInfo->bits->getBits(23), power - 23); + + if (_audioInfo->bits->getBit()) + f = -f; + + return f; } -/* end IDCT_TRANSFORM macro */ -#define MUNGE_NONE(x) (x) -#define IDCT_COL(dest,src) IDCT_TRANSFORM(dest,0,8,16,24,32,40,48,56,0,8,16,24,32,40,48,56,MUNGE_NONE,src) +void BinkDecoder::initAudioTrack(AudioInfo &audio) { + audio.sampleCount = 0; + audio.bits = 0; -#define MUNGE_ROW(x) (((x) + 0x7F)>>8) -#define IDCT_ROW(dest,src) IDCT_TRANSFORM(dest,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,MUNGE_ROW,src) + audio.channels = ((audio.flags & kAudioFlagStereo) != 0) ? 2 : 1; + audio.codec = ((audio.flags & kAudioFlagDCT ) != 0) ? kAudioCodecDCT : kAudioCodecRDFT; -static inline void IDCTCol(int16 *dest, const int16 *src) -{ - if ((src[8] | src[16] | src[24] | src[32] | src[40] | src[48] | src[56]) == 0) { - dest[ 0] = - dest[ 8] = - dest[16] = - dest[24] = - dest[32] = - dest[40] = - dest[48] = - dest[56] = src[0]; - } else { - IDCT_COL(dest, src); - } -} + if (audio.channels > kAudioChannelsMax) + error("Too many audio channels: %d", audio.channels); -void BinkDecoder::IDCT(int16 *block) { - int i; - int16 temp[64]; + uint32 frameLenBits; + // Calculate frame length + if (audio.sampleRate < 22050) + frameLenBits = 9; + else if(audio.sampleRate < 44100) + frameLenBits = 10; + else + frameLenBits = 11; - for (i = 0; i < 8; i++) - IDCTCol(&temp[i], &block[i]); - for (i = 0; i < 8; i++) { - IDCT_ROW( (&block[8*i]), (&temp[8*i]) ); - } -} + audio.frameLen = 1 << frameLenBits; -void BinkDecoder::IDCTAdd(DecodeContext &ctx, int16 *block) { - int i, j; + audio.outSampleRate = audio.sampleRate; + audio.outChannels = audio.channels; - IDCT(block); - byte *dest = ctx.dest; - for (i = 0; i < 8; i++, dest += ctx.pitch, block += 8) - for (j = 0; j < 8; j++) - dest[j] += block[j]; -} + if (audio.codec == kAudioCodecRDFT) { + // RDFT audio already interleaves the samples correctly -void BinkDecoder::IDCTPut(DecodeContext &ctx, int16 *block) { - int i; - int16 temp[64]; - for (i = 0; i < 8; i++) - IDCTCol(&temp[i], &block[i]); - for (i = 0; i < 8; i++) { - IDCT_ROW( (&ctx.dest[i*ctx.pitch]), (&temp[8*i]) ); + if (audio.channels == 2) + frameLenBits++; + + audio.sampleRate *= audio.channels; + audio.frameLen *= audio.channels; + audio.channels = 1; } + + audio.overlapLen = audio.frameLen / 16; + audio.blockSize = (audio.frameLen - audio.overlapLen) * audio.channels; + audio.root = 2.0 / sqrt((double)audio.frameLen); + + uint32 sampleRateHalf = (audio.sampleRate + 1) / 2; + + // Calculate number of bands + for (audio.bandCount = 1; audio.bandCount < 25; audio.bandCount++) + if (sampleRateHalf <= binkCriticalFreqs[audio.bandCount - 1]) + break; + + audio.bands = new uint32[audio.bandCount + 1]; + + // Populate bands + audio.bands[0] = 1; + for (uint32 i = 1; i < audio.bandCount; i++) + audio.bands[i] = binkCriticalFreqs[i - 1] * (audio.frameLen / 2) / sampleRateHalf; + audio.bands[audio.bandCount] = audio.frameLen / 2; + + audio.first = true; + + for (uint8 i = 0; i < audio.channels; i++) + audio.coeffsPtr[i] = audio.coeffs + i * audio.frameLen; + + audio.codec = ((audio.flags & kAudioFlagDCT) != 0) ? kAudioCodecDCT : kAudioCodecRDFT; + + if (audio.codec == kAudioCodecRDFT) + audio.rdft = new Common::RDFT(frameLenBits, Common::RDFT::DFT_C2R); + else if (audio.codec == kAudioCodecDCT) + audio.dct = new Common::DCT(frameLenBits, Common::DCT::DCT_III); + + addTrack(new BinkAudioTrack(audio)); } } // End of namespace Video diff --git a/video/bink_decoder.h b/video/bink_decoder.h index 3d5e882dd7..150e91aab7 100644 --- a/video/bink_decoder.h +++ b/video/bink_decoder.h @@ -31,22 +31,27 @@ #ifndef VIDEO_BINK_DECODER_H #define VIDEO_BINK_DECODER_H -#include "audio/audiostream.h" -#include "audio/mixer.h" #include "common/array.h" #include "common/rational.h" -#include "graphics/surface.h" - #include "video/video_decoder.h" +namespace Audio { +class AudioStream; +class QueuingAudioStream; +} + namespace Common { - class SeekableReadStream; - class BitStream; - class Huffman; +class SeekableReadStream; +class BitStream; +class Huffman; - class RDFT; - class DCT; +class RDFT; +class DCT; +} + +namespace Graphics { +struct Surface; } namespace Video { @@ -57,87 +62,28 @@ namespace Video { * Video decoder used in engines: * - scumm (he) */ -class BinkDecoder : public FixedRateVideoDecoder { +class BinkDecoder : public VideoDecoder { public: BinkDecoder(); ~BinkDecoder(); - // VideoDecoder API bool loadStream(Common::SeekableReadStream *stream); void close(); - bool isVideoLoaded() const { return _bink != 0; } - uint16 getWidth() const { return _surface.w; } - uint16 getHeight() const { return _surface.h; } - Graphics::PixelFormat getPixelFormat() const { return _surface.format; } - uint32 getFrameCount() const { return _frames.size(); } - uint32 getElapsedTime() const; - const Graphics::Surface *decodeNextFrame(); - - // FixedRateVideoDecoder - Common::Rational getFrameRate() const { return _frameRate; } - - // Bink specific - bool loadStream(Common::SeekableReadStream *stream, const Graphics::PixelFormat &format); + protected: + void readNextPacket(); + +private: static const int kAudioChannelsMax = 2; static const int kAudioBlockSizeMax = (kAudioChannelsMax << 11); - /** IDs for different data types used in Bink video codec. */ - enum Source { - kSourceBlockTypes = 0, ///< 8x8 block types. - kSourceSubBlockTypes , ///< 16x16 block types (a subset of 8x8 block types). - kSourceColors , ///< Pixel values used for different block types. - kSourcePattern , ///< 8-bit values for 2-color pattern fill. - kSourceXOff , ///< X components of motion value. - kSourceYOff , ///< Y components of motion value. - kSourceIntraDC , ///< DC values for intrablocks with DCT. - kSourceInterDC , ///< DC values for interblocks with DCT. - kSourceRun , ///< Run lengths for special fill block. - - kSourceMAX - }; - - /** Bink video block types. */ - enum BlockType { - kBlockSkip = 0, ///< Skipped block. - kBlockScaled , ///< Block has size 16x16. - kBlockMotion , ///< Block is copied from previous frame with some offset. - kBlockRun , ///< Block is composed from runs of colors with custom scan order. - kBlockResidue , ///< Motion block with some difference added. - kBlockIntra , ///< Intra DCT block. - kBlockFill , ///< Block is filled with single color. - kBlockInter , ///< Motion block with DCT applied to the difference. - kBlockPattern , ///< Block is filled with two colors following custom pattern. - kBlockRaw ///< Uncoded 8x8 block. - }; - - /** Data structure for decoding and tranlating Huffman'd data. */ - struct Huffman { - int index; ///< Index of the Huffman codebook to use. - byte symbols[16]; ///< Huffman symbol => Bink symbol tranlation list. - }; - - /** Data structure used for decoding a single Bink data type. */ - struct Bundle { - int countLengths[2]; ///< Lengths of number of entries to decode (in bits). - int countLength; ///< Length of number of entries to decode (in bits) for the current plane. - - Huffman huffman; ///< Huffman codebook. - - byte *data; ///< Buffer for decoded symbols. - byte *dataEnd; ///< Buffer end. - - byte *curDec; ///< Pointer to the data that wasn't yet decoded. - byte *curPtr; ///< Pointer to the data that wasn't yet read. - }; - enum AudioCodec { kAudioCodecDCT, kAudioCodecRDFT }; /** An audio track. */ - struct AudioTrack { + struct AudioInfo { uint16 flags; uint32 sampleRate; @@ -172,8 +118,8 @@ protected: Common::RDFT *rdft; Common::DCT *dct; - AudioTrack(); - ~AudioTrack(); + AudioInfo(); + ~AudioInfo(); }; /** A video frame. */ @@ -189,149 +135,218 @@ protected: ~VideoFrame(); }; - /** A decoder state. */ - struct DecodeContext { - VideoFrame *video; + class BinkVideoTrack : public FixedRateVideoTrack { + public: + BinkVideoTrack(uint32 width, uint32 height, const Graphics::PixelFormat &format, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id); + ~BinkVideoTrack(); + + uint16 getWidth() const { return _surface.w; } + uint16 getHeight() const { return _surface.h; } + Graphics::PixelFormat getPixelFormat() const { return _surface.format; } + int getCurFrame() const { return _curFrame; } + int getFrameCount() const { return _frameCount; } + const Graphics::Surface *decodeNextFrame() { return &_surface; } + + /** Decode a video packet. */ + void decodePacket(VideoFrame &frame); + + protected: + Common::Rational getFrameRate() const { return _frameRate; } - uint32 planeIdx; + private: + /** A decoder state. */ + struct DecodeContext { + VideoFrame *video; + + uint32 planeIdx; - uint32 blockX; - uint32 blockY; + uint32 blockX; + uint32 blockY; - byte *dest; - byte *prev; + byte *dest; + byte *prev; - byte *destStart, *destEnd; - byte *prevStart, *prevEnd; + byte *destStart, *destEnd; + byte *prevStart, *prevEnd; - uint32 pitch; + uint32 pitch; - int coordMap[64]; - int coordScaledMap1[64]; - int coordScaledMap2[64]; - int coordScaledMap3[64]; - int coordScaledMap4[64]; + int coordMap[64]; + int coordScaledMap1[64]; + int coordScaledMap2[64]; + int coordScaledMap3[64]; + int coordScaledMap4[64]; + }; + + /** IDs for different data types used in Bink video codec. */ + enum Source { + kSourceBlockTypes = 0, ///< 8x8 block types. + kSourceSubBlockTypes , ///< 16x16 block types (a subset of 8x8 block types). + kSourceColors , ///< Pixel values used for different block types. + kSourcePattern , ///< 8-bit values for 2-color pattern fill. + kSourceXOff , ///< X components of motion value. + kSourceYOff , ///< Y components of motion value. + kSourceIntraDC , ///< DC values for intrablocks with DCT. + kSourceInterDC , ///< DC values for interblocks with DCT. + kSourceRun , ///< Run lengths for special fill block. + + kSourceMAX + }; + + /** Bink video block types. */ + enum BlockType { + kBlockSkip = 0, ///< Skipped block. + kBlockScaled , ///< Block has size 16x16. + kBlockMotion , ///< Block is copied from previous frame with some offset. + kBlockRun , ///< Block is composed from runs of colors with custom scan order. + kBlockResidue , ///< Motion block with some difference added. + kBlockIntra , ///< Intra DCT block. + kBlockFill , ///< Block is filled with single color. + kBlockInter , ///< Motion block with DCT applied to the difference. + kBlockPattern , ///< Block is filled with two colors following custom pattern. + kBlockRaw ///< Uncoded 8x8 block. + }; + + /** Data structure for decoding and tranlating Huffman'd data. */ + struct Huffman { + int index; ///< Index of the Huffman codebook to use. + byte symbols[16]; ///< Huffman symbol => Bink symbol tranlation list. + }; + + /** Data structure used for decoding a single Bink data type. */ + struct Bundle { + int countLengths[2]; ///< Lengths of number of entries to decode (in bits). + int countLength; ///< Length of number of entries to decode (in bits) for the current plane. + + Huffman huffman; ///< Huffman codebook. + + byte *data; ///< Buffer for decoded symbols. + byte *dataEnd; ///< Buffer end. + + byte *curDec; ///< Pointer to the data that wasn't yet decoded. + byte *curPtr; ///< Pointer to the data that wasn't yet read. + }; + + int _curFrame; + int _frameCount; + + Graphics::Surface _surface; + + uint32 _id; ///< The BIK FourCC. + + bool _hasAlpha; ///< Do video frames have alpha? + bool _swapPlanes; ///< Are the planes ordered (A)YVU instead of (A)YUV? + + Common::Rational _frameRate; + + Bundle _bundles[kSourceMAX]; ///< Bundles for decoding all data types. + + Common::Huffman *_huffman[16]; ///< The 16 Huffman codebooks used in Bink decoding. + + /** Huffman codebooks to use for decoding high nibbles in color data types. */ + Huffman _colHighHuffman[16]; + /** Value of the last decoded high nibble in color data types. */ + int _colLastVal; + + byte *_curPlanes[4]; ///< The 4 color planes, YUVA, current frame. + byte *_oldPlanes[4]; ///< The 4 color planes, YUVA, last frame. + + /** Initialize the bundles. */ + void initBundles(); + /** Deinitialize the bundles. */ + void deinitBundles(); + + /** Initialize the Huffman decoders. */ + void initHuffman(); + + /** Decode a plane. */ + void decodePlane(VideoFrame &video, int planeIdx, bool isChroma); + + /** Read/Initialize a bundle for decoding a plane. */ + void readBundle(VideoFrame &video, Source source); + + /** Read the symbols for a Huffman code. */ + void readHuffman(VideoFrame &video, Huffman &huffman); + /** Merge two Huffman symbol lists. */ + void mergeHuffmanSymbols(VideoFrame &video, byte *dst, const byte *src, int size); + + /** Read and translate a symbol out of a Huffman code. */ + byte getHuffmanSymbol(VideoFrame &video, Huffman &huffman); + + /** Get a direct value out of a bundle. */ + int32 getBundleValue(Source source); + /** Read a count value out of a bundle. */ + uint32 readBundleCount(VideoFrame &video, Bundle &bundle); + + // Handle the block types + void blockSkip (DecodeContext &ctx); + void blockScaledSkip (DecodeContext &ctx); + void blockScaledRun (DecodeContext &ctx); + void blockScaledIntra (DecodeContext &ctx); + void blockScaledFill (DecodeContext &ctx); + void blockScaledPattern(DecodeContext &ctx); + void blockScaledRaw (DecodeContext &ctx); + void blockScaled (DecodeContext &ctx); + void blockMotion (DecodeContext &ctx); + void blockRun (DecodeContext &ctx); + void blockResidue (DecodeContext &ctx); + void blockIntra (DecodeContext &ctx); + void blockFill (DecodeContext &ctx); + void blockInter (DecodeContext &ctx); + void blockPattern (DecodeContext &ctx); + void blockRaw (DecodeContext &ctx); + + // Read the bundles + void readRuns (VideoFrame &video, Bundle &bundle); + void readMotionValues(VideoFrame &video, Bundle &bundle); + void readBlockTypes (VideoFrame &video, Bundle &bundle); + void readPatterns (VideoFrame &video, Bundle &bundle); + void readColors (VideoFrame &video, Bundle &bundle); + void readDCS (VideoFrame &video, Bundle &bundle, int startBits, bool hasSign); + void readDCTCoeffs (VideoFrame &video, int16 *block, bool isIntra); + void readResidue (VideoFrame &video, int16 *block, int masksCount); + + // Bink video IDCT + void IDCT(int16 *block); + void IDCTPut(DecodeContext &ctx, int16 *block); + void IDCTAdd(DecodeContext &ctx, int16 *block); }; - Common::SeekableReadStream *_bink; + class BinkAudioTrack : public AudioTrack { + public: + BinkAudioTrack(AudioInfo &audio); + ~BinkAudioTrack(); + + /** Decode an audio packet. */ + void decodePacket(); - uint32 _id; ///< The BIK FourCC. + protected: + Audio::AudioStream *getAudioStream() const; - Common::Rational _frameRate; + private: + AudioInfo *_audioInfo; + Audio::QueuingAudioStream *_audioStream; - Graphics::Surface _surface; + float getFloat(); - Audio::SoundHandle _audioHandle; - Audio::QueuingAudioStream *_audioStream; - int32 _audioStartOffset; + /** Decode an audio block. */ + void audioBlock(int16 *out); + /** Decode a DCT'd audio block. */ + void audioBlockDCT(); + /** Decode a RDFT'd audio block. */ + void audioBlockRDFT(); - uint32 _videoFlags; ///< Video frame features. + void readAudioCoeffs(float *coeffs); - bool _hasAlpha; ///< Do video frames have alpha? - bool _swapPlanes; ///< Are the planes ordered (A)YVU instead of (A)YUV? + static void floatToInt16Interleave(int16 *dst, const float **src, uint32 length, uint8 channels); + }; + + Common::SeekableReadStream *_bink; - Common::Array<AudioTrack> _audioTracks; ///< All audio tracks. + Common::Array<AudioInfo> _audioTracks; ///< All audio tracks. Common::Array<VideoFrame> _frames; ///< All video frames. - uint32 _audioTrack; ///< Audio track to use. - - Common::Huffman *_huffman[16]; ///< The 16 Huffman codebooks used in Bink decoding. - - Bundle _bundles[kSourceMAX]; ///< Bundles for decoding all data types. - - /** Huffman codebooks to use for decoding high nibbles in color data types. */ - Huffman _colHighHuffman[16]; - /** Value of the last decoded high nibble in color data types. */ - int _colLastVal; - - byte *_curPlanes[4]; ///< The 4 color planes, YUVA, current frame. - byte *_oldPlanes[4]; ///< The 4 color planes, YUVA, last frame. - - - /** Initialize the bundles. */ - void initBundles(); - /** Deinitialize the bundles. */ - void deinitBundles(); - - /** Initialize the Huffman decoders. */ - void initHuffman(); - - /** Decode an audio packet. */ - void audioPacket(AudioTrack &audio); - /** Decode a video packet. */ - virtual void videoPacket(VideoFrame &video); - - /** Decode a plane. */ - void decodePlane(VideoFrame &video, int planeIdx, bool isChroma); - - /** Read/Initialize a bundle for decoding a plane. */ - void readBundle(VideoFrame &video, Source source); - - /** Read the symbols for a Huffman code. */ - void readHuffman(VideoFrame &video, Huffman &huffman); - /** Merge two Huffman symbol lists. */ - void mergeHuffmanSymbols(VideoFrame &video, byte *dst, const byte *src, int size); - - /** Read and translate a symbol out of a Huffman code. */ - byte getHuffmanSymbol(VideoFrame &video, Huffman &huffman); - - /** Get a direct value out of a bundle. */ - int32 getBundleValue(Source source); - /** Read a count value out of a bundle. */ - uint32 readBundleCount(VideoFrame &video, Bundle &bundle); - - // Handle the block types - void blockSkip (DecodeContext &ctx); - void blockScaledSkip (DecodeContext &ctx); - void blockScaledRun (DecodeContext &ctx); - void blockScaledIntra (DecodeContext &ctx); - void blockScaledFill (DecodeContext &ctx); - void blockScaledPattern(DecodeContext &ctx); - void blockScaledRaw (DecodeContext &ctx); - void blockScaled (DecodeContext &ctx); - void blockMotion (DecodeContext &ctx); - void blockRun (DecodeContext &ctx); - void blockResidue (DecodeContext &ctx); - void blockIntra (DecodeContext &ctx); - void blockFill (DecodeContext &ctx); - void blockInter (DecodeContext &ctx); - void blockPattern (DecodeContext &ctx); - void blockRaw (DecodeContext &ctx); - - // Read the bundles - void readRuns (VideoFrame &video, Bundle &bundle); - void readMotionValues(VideoFrame &video, Bundle &bundle); - void readBlockTypes (VideoFrame &video, Bundle &bundle); - void readPatterns (VideoFrame &video, Bundle &bundle); - void readColors (VideoFrame &video, Bundle &bundle); - void readDCS (VideoFrame &video, Bundle &bundle, int startBits, bool hasSign); - void readDCTCoeffs (VideoFrame &video, int16 *block, bool isIntra); - void readResidue (VideoFrame &video, int16 *block, int masksCount); - - void initAudioTrack(AudioTrack &audio); - - float getFloat(AudioTrack &audio); - - /** Decode an audio block. */ - void audioBlock (AudioTrack &audio, int16 *out); - /** Decode a DCT'd audio block. */ - void audioBlockDCT (AudioTrack &audio); - /** Decode a RDFT'd audio block. */ - void audioBlockRDFT(AudioTrack &audio); - - void readAudioCoeffs(AudioTrack &audio, float *coeffs); - - void floatToInt16Interleave(int16 *dst, const float **src, uint32 length, uint8 channels); - - // Bink video IDCT - void IDCT(int16 *block); - void IDCTPut(DecodeContext &ctx, int16 *block); - void IDCTAdd(DecodeContext &ctx, int16 *block); - - /** Start playing the audio track */ - void startAudio(); - /** Stop playing the audio track */ - void stopAudio(); + void initAudioTrack(AudioInfo &audio); }; } // End of namespace Video diff --git a/video/codecs/qtrle.cpp b/video/codecs/qtrle.cpp index f01720ec86..d2cdea27de 100644 --- a/video/codecs/qtrle.cpp +++ b/video/codecs/qtrle.cpp @@ -37,28 +37,25 @@ namespace Video { QTRLEDecoder::QTRLEDecoder(uint16 width, uint16 height, byte bitsPerPixel) : Codec() { _bitsPerPixel = bitsPerPixel; - _pixelFormat = g_system->getScreenFormat(); - // We need to increase the surface size to a multiple of 4 + // We need to ensure the width is a multiple of 4 uint16 wMod = width % 4; - if(wMod != 0) + if (wMod != 0) width += 4 - wMod; - debug(2, "QTRLE corrected width: %d", width); - _surface = new Graphics::Surface(); - _surface->create(width, height, _bitsPerPixel <= 8 ? Graphics::PixelFormat::createFormatCLUT8() : _pixelFormat); + _surface->create(width, height, getPixelFormat()); } #define CHECK_STREAM_PTR(n) \ if ((stream->pos() + n) > stream->size()) { \ - warning ("Problem: stream out of bounds (%d >= %d)", stream->pos() + n, stream->size()); \ + warning("QTRLE Problem: stream out of bounds (%d > %d)", stream->pos() + n, stream->size()); \ return; \ } #define CHECK_PIXEL_PTR(n) \ if ((int32)pixelPtr + n > _surface->w * _surface->h) { \ - warning ("Problem: pixel ptr = %d, pixel limit = %d", pixelPtr + n, _surface->w * _surface->h); \ + warning("QTRLE Problem: pixel ptr = %d, pixel limit = %d", pixelPtr + n, _surface->w * _surface->h); \ return; \ } \ @@ -132,8 +129,6 @@ void QTRLEDecoder::decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr, for (int8 i = numPixels - 1; i >= 0; i--) { pi[numPixels - 1 - i] = (stream->readByte() >> ((i * bpp) & 0x07)) & ((1 << bpp) - 1); - // FIXME: Is this right? - //stream_ptr += ((i & ((num_pixels>>2)-1)) == 0); if ((i & ((numPixels >> 2) - 1)) == 0) stream->readByte(); } @@ -215,7 +210,7 @@ void QTRLEDecoder::decode8(Common::SeekableReadStream *stream, uint32 rowPtr, ui void QTRLEDecoder::decode16(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) { uint32 pixelPtr = 0; - OverlayColor *rgb = (OverlayColor *)_surface->pixels; + uint16 *rgb = (uint16 *)_surface->pixels; while (linesToChange--) { CHECK_STREAM_PTR(2); @@ -235,25 +230,15 @@ void QTRLEDecoder::decode16(Common::SeekableReadStream *stream, uint32 rowPtr, u CHECK_PIXEL_PTR(rleCode); - while (rleCode--) { - // Convert from RGB555 to the format specified by the Overlay - byte r = 0, g = 0, b = 0; - Graphics::colorToRGB<Graphics::ColorMasks<555> >(rgb16, r, g, b); - rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b); - } + while (rleCode--) + rgb[pixelPtr++] = rgb16; } else { CHECK_STREAM_PTR(rleCode * 2); CHECK_PIXEL_PTR(rleCode); // copy pixels directly to output - while (rleCode--) { - uint16 rgb16 = stream->readUint16BE(); - - // Convert from RGB555 to the format specified by the Overlay - byte r = 0, g = 0, b = 0; - Graphics::colorToRGB<Graphics::ColorMasks<555> >(rgb16, r, g, b); - rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b); - } + while (rleCode--) + rgb[pixelPtr++] = stream->readUint16BE(); } } @@ -263,7 +248,7 @@ void QTRLEDecoder::decode16(Common::SeekableReadStream *stream, uint32 rowPtr, u void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) { uint32 pixelPtr = 0; - OverlayColor *rgb = (OverlayColor *)_surface->pixels; + uint32 *rgb = (uint32 *)_surface->pixels; while (linesToChange--) { CHECK_STREAM_PTR(2); @@ -283,11 +268,12 @@ void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, u byte r = stream->readByte(); byte g = stream->readByte(); byte b = stream->readByte(); + uint32 color = _surface->format.RGBToColor(r, g, b); CHECK_PIXEL_PTR(rleCode); while (rleCode--) - rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b); + rgb[pixelPtr++] = color; } else { CHECK_STREAM_PTR(rleCode * 3); CHECK_PIXEL_PTR(rleCode); @@ -297,7 +283,7 @@ void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, u byte r = stream->readByte(); byte g = stream->readByte(); byte b = stream->readByte(); - rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b); + rgb[pixelPtr++] = _surface->format.RGBToColor(r, g, b); } } } @@ -308,7 +294,7 @@ void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, u void QTRLEDecoder::decode32(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) { uint32 pixelPtr = 0; - OverlayColor *rgb = (OverlayColor *)_surface->pixels; + uint32 *rgb = (uint32 *)_surface->pixels; while (linesToChange--) { CHECK_STREAM_PTR(2); @@ -329,11 +315,12 @@ void QTRLEDecoder::decode32(Common::SeekableReadStream *stream, uint32 rowPtr, u byte r = stream->readByte(); byte g = stream->readByte(); byte b = stream->readByte(); + uint32 color = _surface->format.ARGBToColor(a, r, g, b); CHECK_PIXEL_PTR(rleCode); while (rleCode--) - rgb[pixelPtr++] = _pixelFormat.ARGBToColor(a, r, g, b); + rgb[pixelPtr++] = color; } else { CHECK_STREAM_PTR(rleCode * 4); CHECK_PIXEL_PTR(rleCode); @@ -344,7 +331,7 @@ void QTRLEDecoder::decode32(Common::SeekableReadStream *stream, uint32 rowPtr, u byte r = stream->readByte(); byte g = stream->readByte(); byte b = stream->readByte(); - rgb[pixelPtr++] = _pixelFormat.ARGBToColor(a, r, g, b); + rgb[pixelPtr++] = _surface->format.ARGBToColor(a, r, g, b); } } } @@ -354,7 +341,7 @@ void QTRLEDecoder::decode32(Common::SeekableReadStream *stream, uint32 rowPtr, u } const Graphics::Surface *QTRLEDecoder::decodeImage(Common::SeekableReadStream *stream) { - uint16 start_line = 0; + uint16 startLine = 0; uint16 height = _surface->h; // check if this frame is even supposed to change @@ -369,44 +356,45 @@ const Graphics::Surface *QTRLEDecoder::decodeImage(Common::SeekableReadStream *s // if a header is present, fetch additional decoding parameters if (header & 8) { - if(stream->size() < 14) + if (stream->size() < 14) return _surface; - start_line = stream->readUint16BE(); + + startLine = stream->readUint16BE(); stream->readUint16BE(); // Unknown height = stream->readUint16BE(); stream->readUint16BE(); // Unknown } - uint32 row_ptr = _surface->w * start_line; + uint32 rowPtr = _surface->w * startLine; switch (_bitsPerPixel) { - case 1: - case 33: - decode1(stream, row_ptr, height); - break; - case 2: - case 34: - decode2_4(stream, row_ptr, height, 2); - break; - case 4: - case 36: - decode2_4(stream, row_ptr, height, 4); - break; - case 8: - case 40: - decode8(stream, row_ptr, height); - break; - case 16: - decode16(stream, row_ptr, height); - break; - case 24: - decode24(stream, row_ptr, height); - break; - case 32: - decode32(stream, row_ptr, height); - break; - default: - error ("Unsupported bits per pixel %d", _bitsPerPixel); + case 1: + case 33: + decode1(stream, rowPtr, height); + break; + case 2: + case 34: + decode2_4(stream, rowPtr, height, 2); + break; + case 4: + case 36: + decode2_4(stream, rowPtr, height, 4); + break; + case 8: + case 40: + decode8(stream, rowPtr, height); + break; + case 16: + decode16(stream, rowPtr, height); + break; + case 24: + decode24(stream, rowPtr, height); + break; + case 32: + decode32(stream, rowPtr, height); + break; + default: + error("Unsupported QTRLE bits per pixel %d", _bitsPerPixel); } return _surface; @@ -417,4 +405,27 @@ QTRLEDecoder::~QTRLEDecoder() { delete _surface; } +Graphics::PixelFormat QTRLEDecoder::getPixelFormat() const { + switch (_bitsPerPixel) { + case 1: + case 33: + case 2: + case 34: + case 4: + case 36: + case 8: + case 40: + return Graphics::PixelFormat::createFormatCLUT8(); + case 16: + return Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); + case 24: + case 32: + return Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); + default: + error("Unsupported QTRLE bits per pixel %d", _bitsPerPixel); + } + + return Graphics::PixelFormat(); +} + } // End of namespace Video diff --git a/video/codecs/qtrle.h b/video/codecs/qtrle.h index 6f8e113ca5..d9db58ab23 100644 --- a/video/codecs/qtrle.h +++ b/video/codecs/qtrle.h @@ -34,13 +34,12 @@ public: ~QTRLEDecoder(); const Graphics::Surface *decodeImage(Common::SeekableReadStream *stream); - Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; } + Graphics::PixelFormat getPixelFormat() const; private: byte _bitsPerPixel; Graphics::Surface *_surface; - Graphics::PixelFormat _pixelFormat; void decode1(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange); void decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange, byte bpp); diff --git a/video/codecs/rpza.cpp b/video/codecs/rpza.cpp index df5738202e..acc1b7f358 100644 --- a/video/codecs/rpza.cpp +++ b/video/codecs/rpza.cpp @@ -28,22 +28,17 @@ #include "common/system.h" #include "common/stream.h" #include "common/textconsole.h" -#include "graphics/colormasks.h" namespace Video { RPZADecoder::RPZADecoder(uint16 width, uint16 height) : Codec() { - _pixelFormat = g_system->getScreenFormat(); - // We need to increase the surface size to a multiple of 4 uint16 wMod = width % 4; - if(wMod != 0) + if (wMod != 0) width += 4 - wMod; - debug(2, "RPZA corrected width: %d", width); - _surface = new Graphics::Surface(); - _surface->create(width, height, _pixelFormat); + _surface->create(width, height, getPixelFormat()); } RPZADecoder::~RPZADecoder() { @@ -59,18 +54,11 @@ RPZADecoder::~RPZADecoder() { } \ totalBlocks--; \ if (totalBlocks < 0) \ - error("block counter just went negative (this should not happen)") \ + error("rpza block counter just went negative (this should not happen)") \ -// Convert from RGB555 to the format specified by the screen #define PUT_PIXEL(color) \ - if ((int32)blockPtr < _surface->w * _surface->h) { \ - byte r = 0, g = 0, b = 0; \ - Graphics::colorToRGB<Graphics::ColorMasks<555> >(color, r, g, b); \ - if (_pixelFormat.bytesPerPixel == 2) \ - *((uint16 *)_surface->pixels + blockPtr) = _pixelFormat.RGBToColor(r, g, b); \ - else \ - *((uint32 *)_surface->pixels + blockPtr) = _pixelFormat.RGBToColor(r, g, b); \ - } \ + if ((int32)blockPtr < _surface->w * _surface->h) \ + WRITE_UINT16((uint16 *)_surface->pixels + blockPtr, color); \ blockPtr++ const Graphics::Surface *RPZADecoder::decodeImage(Common::SeekableReadStream *stream) { diff --git a/video/codecs/rpza.h b/video/codecs/rpza.h index 809a69f444..f082d25549 100644 --- a/video/codecs/rpza.h +++ b/video/codecs/rpza.h @@ -34,11 +34,10 @@ public: ~RPZADecoder(); const Graphics::Surface *decodeImage(Common::SeekableReadStream *stream); - Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; } + Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); } private: Graphics::Surface *_surface; - Graphics::PixelFormat _pixelFormat; }; } // End of namespace Video diff --git a/video/codecs/svq1.cpp b/video/codecs/svq1.cpp index eba0c90305..14452ab15b 100644 --- a/video/codecs/svq1.cpp +++ b/video/codecs/svq1.cpp @@ -317,7 +317,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 +336,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 +409,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 +430,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; } diff --git a/video/codecs/svq1_cb.h b/video/codecs/svq1_cb.h index f9a8c54e40..8281b3fc28 100644 --- a/video/codecs/svq1_cb.h +++ b/video/codecs/svq1_cb.h @@ -30,1477 +30,1477 @@ namespace Video { -static const uint32 s_svq1InterCodebook4x2[192] = { - 0xf9fa0207, 0xfcfd0307, 0x0807fef9, 0x0403fcf8, - 0x03091113, 0xf8f4f0f2, 0xfdf8f0ee, 0x080c0e0b, - 0x14f6f007, 0x14f6ef07, 0xeb0812fa, 0xec0912f9, - 0xf2ec0319, 0xf3ee071d, 0x0e15fce3, 0x0e14fae1, - 0xe8e4e6ed, 0x0a16201f, 0x1c1f180f, 0xf3eae0e0, - 0xe6e9f802, 0x231b03f7, 0x15150b03, 0xdee5fc08, - 0x2f0ce1e2, 0x2f0de2e3, 0xd2ef1e26, 0xd2ed1a22, - 0xd5cdced6, 0x30373022, 0x2a333630, 0xd1cbccd4, - 0xfa000504, 0x0100fefe, 0xfefffaf5, 0x01090801, - 0x05fa0100, 0x02f40108, 0x08f9f207, 0x0800f805, - 0x080b0401, 0xfb00f8f4, 0x040001ff, 0x1003f8f1, - 0xfafc0811, 0xf8f3fc09, 0xee010602, 0xf40b0bff, - 0x00020006, 0xebf9060e, 0xecf3ff01, 0x150a0101, - 0x0d07fbea, 0x0c04fff5, 0x130e00f9, 0xedfb03fc, - 0x0f0af2e6, 0xfefa0412, 0xeefb1319, 0x0204f9ec, - 0xfcfffaf3, 0xddfe2519, 0x01010405, 0x2b02dceb, - 0x03fffe02, 0xfffafe08, 0x0c02fdfe, 0xfffefefb, - 0xfbfffffd, 0xfe0807ff, 0xfd050702, 0xf8fd0101, - 0xfefdfffd, 0x0d02fdfe, 0xfaf5000f, 0x00000003, - 0xfcfbf7fa, 0x03010412, 0x0400030c, 0xfd03fdf0, - 0x021203ef, 0xfffffdff, 0x00f810fa, 0x00f90ef7, - 0xfb0ef303, 0xfc0ef303, 0xe90e14f9, 0x04f8f908, - 0x10edf108, 0xfd0b0df6, 0x1a01ff09, 0x02e5f105, - 0xfc1007ec, 0x011f09d8, 0xf9e2f41a, 0x04edfe28, - 0x00000006, 0x0201fefa, 0xfa00ff00, 0xfffe0009, - 0xfd0208f9, 0x02fd02ff, 0x04fefc07, 0xfa000002, - 0x0209fefd, 0xfc00fffe, 0xfd00fdfd, 0x040a02fa, - 0x08f60003, 0x04fc0000, 0x020401ff, 0x07f7f903, - 0xfcf70102, 0x00000cff, 0xfc07ff03, 0x0204f203, - 0x0b01f7f4, 0x00010502, 0x02000103, 0xed060800, - 0xfcf9f6fa, 0x07050709, 0xfd031506, 0xfefbf7f5, - 0xfff0f7fc, 0x2401fbfe, 0x00130b08, 0xd7fc0502, - 0xfffeffff, 0x0601fefe, 0xf8010400, 0x00010101, - 0x0004fdfe, 0xfd03ff02, 0x01fc0301, 0xfb0003ff, - 0x03020403, 0xfffafdfe, 0x02fefdfe, 0x000108fc, - 0x060204f9, 0x0001fff9, 0x01fc02fe, 0xff02fa08, - 0x020002fa, 0xfff80405, 0x0900f5ff, 0x0202fe00, - 0xfffcfb11, 0xfefefcff, 0xfd09f300, 0x02f90cff, - 0x02fbfe00, 0xfd14fbf9, 0xe2ff0707, 0x01080503, - 0xfcff03fa, 0x12f5fe02, 0x0e03f900, 0xf7eefd14, - 0xff00fe07, 0xff0000fe, 0x0001fffc, 0x040002fe, - 0x0102fd01, 0x01fb0103, 0xfeff00fd, 0xfd000107, - 0xfe000502, 0x01fffb02, 0xff04feff, 0x0005fd00, - 0xfeff0300, 0xff0501fc, 0x09ff00ff, 0xfffffeff, - 0xff0505fe, 0xfefd02fe, 0x01f50201, 0x02030102, - 0xfefff602, 0x01040204, 0x01fb0504, 0x01f50600, - 0x06060001, 0xf1010200, 0x09050307, 0x020202e2, - 0x020901de, 0x02080805, 0x06060207, 0x0401e502 +static const int8 s_svq1InterCodebook4x2[768] = { + 7, 2, -6, -7, 7, 3, -3, -4, -7, -2, 7, 8, -8, -4, 3, 4, + 19, 17, 9, 3,-14,-16,-12, -8,-18,-16, -8, -3, 11, 14, 12, 8, + 7,-16,-10, 20, 7,-17,-10, 20, -6, 18, 8,-21, -7, 18, 9,-20, + 25, 3,-20,-14, 29, 7,-18,-13,-29, -4, 21, 14,-31, -6, 20, 14, + -19,-26,-28,-24, 31, 32, 22, 10, 15, 24, 31, 28,-32,-32,-22,-13, + 2, -8,-23,-26, -9, 3, 27, 35, 3, 11, 21, 21, 8, -4,-27,-34, + -30,-31, 12, 47,-29,-30, 13, 47, 38, 30,-17,-46, 34, 26,-19,-46, + -42,-50,-51,-43, 34, 48, 55, 48, 48, 54, 51, 42,-44,-52,-53,-47, + 4, 5, 0, -6, -2, -2, 0, 1,-11, -6, -1, -2, 1, 8, 9, 1, + 0, 1, -6, 5, 8, 1,-12, 2, 7,-14, -7, 8, 5, -8, 0, 8, + 1, 4, 11, 8,-12, -8, 0, -5, -1, 1, 0, 4,-15, -8, 3, 16, + 17, 8, -4, -6, 9, -4,-13, -8, 2, 6, 1,-18, -1, 11, 11,-12, + 6, 0, 2, 0, 14, 6, -7,-21, 1, -1,-13,-20, 1, 1, 10, 21, + -22, -5, 7, 13,-11, -1, 4, 12, -7, 0, 14, 19, -4, 3, -5,-19, + -26,-14, 10, 15, 18, 4, -6, -2, 25, 19, -5,-18,-20, -7, 4, 2, + -13, -6, -1, -4, 25, 37, -2,-35, 5, 4, 1, 1,-21,-36, 2, 43, + 2, -2, -1, 3, 8, -2, -6, -1, -2, -3, 2, 12, -5, -2, -2, -1, + -3, -1, -1, -5, -1, 7, 8, -2, 2, 7, 5, -3, 1, 1, -3, -8, + -3, -1, -3, -2, -2, -3, 2, 13, 15, 0,-11, -6, 3, 0, 0, 0, + -6, -9, -5, -4, 18, 4, 1, 3, 12, 3, 0, 4,-16, -3, 3, -3, + -17, 3, 18, 2, -1, -3, -1, -1, -6, 16, -8, 0, -9, 14, -7, 0, + 3,-13, 14, -5, 3,-13, 14, -4, -7, 20, 14,-23, 8, -7, -8, 4, + 8,-15,-19, 16,-10, 13, 11, -3, 9, -1, 1, 26, 5,-15,-27, 2, + -20, 7, 16, -4,-40, 9, 31, 1, 26,-12,-30, -7, 40, -2,-19, 4, + 6, 0, 0, 0, -6, -2, 1, 2, 0, -1, 0, -6, 9, 0, -2, -1, + -7, 8, 2, -3, -1, 2, -3, 2, 7, -4, -2, 4, 2, 0, 0, -6, + -3, -2, 9, 2, -2, -1, 0, -4, -3, -3, 0, -3, -6, 2, 10, 4, + 3, 0,-10, 8, 0, 0, -4, 4, -1, 1, 4, 2, 3, -7, -9, 7, + 2, 1, -9, -4, -1, 12, 0, 0, 3, -1, 7, -4, 3,-14, 4, 2, + -12, -9, 1, 11, 2, 5, 1, 0, 3, 1, 0, 2, 0, 8, 6,-19, + -6,-10, -7, -4, 9, 7, 5, 7, 6, 21, 3, -3,-11, -9, -5, -2, + -4, -9,-16, -1, -2, -5, 1, 36, 8, 11, 19, 0, 2, 5, -4,-41, + -1, -1, -2, -1, -2, -2, 1, 6, 0, 4, 1, -8, 1, 1, 1, 0, + -2, -3, 4, 0, 2, -1, 3, -3, 1, 3, -4, 1, -1, 3, 0, -5, + 3, 4, 2, 3, -2, -3, -6, -1, -2, -3, -2, 2, -4, 8, 1, 0, + -7, 4, 2, 6, -7, -1, 1, 0, -2, 2, -4, 1, 8, -6, 2, -1, + -6, 2, 0, 2, 5, 4, -8, -1, -1,-11, 0, 9, 0, -2, 2, 2, + 17, -5, -4, -1, -1, -4, -2, -2, 0,-13, 9, -3, -1, 12, -7, 2, + 0, -2, -5, 2, -7, -5, 20, -3, 7, 7, -1,-30, 3, 5, 8, 1, + -6, 3, -1, -4, 2, -2,-11, 18, 0, -7, 3, 14, 20, -3,-18, -9, + 7, -2, 0, -1, -2, 0, 0, -1, -4, -1, 1, 0, -2, 2, 0, 4, + 1, -3, 2, 1, 3, 1, -5, 1, -3, 0, -1, -2, 7, 1, 0, -3, + 2, 5, 0, -2, 2, -5, -1, 1, -1, -2, 4, -1, 0, -3, 5, 0, + 0, 3, -1, -2, -4, 1, 5, -1, -1, 0, -1, 9, -1, -2, -1, -1, + -2, 5, 5, -1, -2, 2, -3, -2, 1, 2,-11, 1, 2, 1, 3, 2, + 2,-10, -1, -2, 4, 2, 4, 1, 4, 5, -5, 1, 0, 6,-11, 1, + 1, 0, 6, 6, 0, 2, 1,-15, 7, 3, 5, 9,-30, 2, 2, 2, + -34, 1, 9, 2, 5, 8, 8, 2, 7, 2, 6, 6, 2,-27, 1, 4 }; -static const uint32 s_svq1InterCodebook4x4[384] = { - 0xf9fa0004, 0xf7f3f8fc, 0x06fff8f8, 0x1b1605fe, - 0x0a0bf9f0, 0x0a0df9ee, 0x080cfcf1, 0x0509fff7, - 0xf00f02fe, 0xed1302fd, 0xed1302fd, 0xf20f03fe, - 0x10161611, 0xfefbf9fa, 0xf4f0f0f4, 0xfdff0101, - 0x0800ef0b, 0x09ffeb0e, 0x08feeb0e, 0x06fef00b, - 0x0bf0fe07, 0x0eebfe09, 0x0eeaff0a, 0x0aeeff08, - 0xf70310f6, 0xf50414f3, 0xf60415f2, 0xf80310f5, - 0xf7f7040b, 0xf2f4060f, 0xf2f40811, 0xf5f90a10, - 0x0d0e0a04, 0x100f07ff, 0x0803f9f4, 0xf6eee9ec, - 0xe7e6eef6, 0xf5fa0104, 0x030b0f0d, 0x080d0f0c, - 0xf5f0edf0, 0x0b0f0c07, 0x0b10100b, 0xf6f5f7fa, - 0x050c1312, 0xfc051012, 0xf1f60006, 0xeae9eff7, - 0x15fff2f6, 0x1d00eff5, 0x1e01f0f5, 0x1700f2f6, - 0xfaf4eff0, 0xf9f2eded, 0x0201fffd, 0x131d231b, - 0x1717f8db, 0x1d1cf7d6, 0x1c1af6d5, 0x1613f5da, - 0xdff01020, 0xdbee1427, 0xdaed1326, 0xdeef0f20, - 0xfcfa0918, 0x03faf6ff, 0x03fff7f8, 0xfa020703, - 0x00fffdff, 0xf90204ff, 0xf0030bfd, 0xee091401, - 0x0c06f8fd, 0x0d07f6fb, 0x0705f7fa, 0xff02fbfb, - 0xfffd0cf8, 0x01fd0ff6, 0x01fc0df5, 0x02fd08f5, - 0xf4fb0609, 0xf3f80003, 0xfffffcfc, 0x120f01fc, - 0x0c0e0d09, 0xfeff0304, 0xfbf8fbfe, 0xfcf7f5f9, - 0xfcf9fb07, 0xfcf9fe0e, 0xfbf80011, 0xfbf9010f, - 0x0406fff6, 0x0402f7f1, 0x00fdff02, 0xf6f80d19, - 0xf0fd0b07, 0xf1fd0b07, 0xf7fe0706, 0xfbfd0204, - 0x00fffff9, 0x0602fef7, 0x0e06fcf4, 0x1308faf3, - 0xfbf5eeee, 0x040300fd, 0x06060806, 0x06060606, - 0xf60d03fb, 0xf70f01fa, 0xfa0ffdfa, 0xfd0afafa, - 0xf7f70109, 0x0506090b, 0x07080300, 0xfbfaf2f1, - 0x130bfaf5, 0xf8f7fbfe, 0xf6f70206, 0x05040506, - 0x0f08fdf9, 0x0f0a03ff, 0xfeff0505, 0xe7ebfe04, - 0x05fafa06, 0x09f9f708, 0x0df9f408, 0x0ef9f204, - 0x0101fdfc, 0xfdfefbfd, 0xfcfe0007, 0xfcfc0714, - 0x0afaecfd, 0x01000006, 0xff050805, 0xfe0000fd, - 0x02ff060d, 0x03020305, 0x000300fd, 0xfbfef8f0, - 0x00faf9fe, 0x01fdfafd, 0xff02fffb, 0x05100cff, - 0x080901f9, 0x0305fef6, 0x030702fa, 0xf9ff00fc, - 0xe8f70403, 0x03060200, 0x0704ffff, 0xfeff0305, - 0x02f70603, 0x01f30601, 0x02f60801, 0x01f90801, - 0x1602fdfd, 0x0cfbfdfe, 0x02f6fdfe, 0x02fcfffd, - 0x02080c0b, 0xf8fbfbfb, 0xfd00fcfa, 0x0303fffe, - 0xfffefa0c, 0xfefef80c, 0xfd00f909, 0xfe02fa04, - 0xfd0c01ed, 0xfc0504fc, 0xfffe0106, 0x07fefc04, - 0xf8f9fcfd, 0x00fefcfc, 0x100e02ff, 0x0404fefc, - 0xfb0207ff, 0x01ff00fe, 0x0dfffd04, 0x08f2f406, - 0xfb0405ff, 0xf70305fe, 0xf40407fe, 0xf70407ff, - 0x0101fdfa, 0xfa000b0b, 0xf9fe0406, 0x0a03f6f4, - 0xfefdfdfe, 0x0a0e0b06, 0xf6f6f5f7, 0x02030202, - 0xfff9fbf9, 0x070002ff, 0x090001ff, 0xfffb0403, - 0xfff1ff0a, 0x02fb0104, 0x01ff01fd, 0x040401fd, - 0x0a04ff02, 0x00ff0206, 0xf4f90202, 0xfd0002fc, - 0xf8fffcff, 0xf702ff03, 0xfb050004, 0x03080002, - 0x01010203, 0x0300fe04, 0x0104ff02, 0xe7ff0600, - 0xfcfefeff, 0xfcff00fd, 0x02fcffff, 0x1902fa00, - 0x0005fff5, 0x02fe0007, 0x04fdff0a, 0xfffefbfb, - 0xff030600, 0x01fffffe, 0xfbf4f9ff, 0x04020608, - 0xfaff0602, 0xfcff0a09, 0x00fc0001, 0xfbf7fe03, - 0x000403fc, 0x000303fc, 0x020300f5, 0x020703f5, - 0x0307fc02, 0x0107f801, 0x0104f4ff, 0x0202f703, - 0x09fefe02, 0x0103fdef, 0xfa0107fc, 0x03ff0405, - 0xfc0002ff, 0xff0c08f9, 0xfb0405fe, 0xfef8fb03, - 0xfefb0000, 0x1b03f8fe, 0x06fdfcff, 0xf9fe01fd, - 0xff010404, 0xfdf9f6f9, 0x03050a0a, 0xfdfcfefe, - 0x07050100, 0xecf0fe04, 0x08070400, 0xfffe0002, - 0x110301fe, 0xfffe01fd, 0xfefffeff, 0x00fffbff, - 0x0001fd05, 0x0000fe06, 0xfd00feff, 0xff0801f5, - 0x00000003, 0x01040200, 0x01060002, 0x02fdeefe, - 0x010600f2, 0x01fffefb, 0x010001ff, 0x00040701, - 0xfc0100ff, 0xfc030801, 0x030104fd, 0x01fc01fa, - 0x0303f401, 0xff00f6ff, 0x01020002, 0x04020203, - 0x03000003, 0x01fe0002, 0x00fb0205, 0xfff2ff06, - 0xfdfdfafe, 0x0504ff02, 0x00feff06, 0xfbff0404, - 0x00f501fc, 0x01fc02ff, 0xff03fd02, 0x000ffe01, - 0xfe00ff01, 0x01f9fc01, 0x15fffafe, 0x01ff02fe, - 0x00feff15, 0xfe01fdff, 0xff02fef7, 0xfffc0102, - 0xfa020801, 0x0004fff6, 0x0303fdfc, 0xffff0005, - 0xfe010203, 0x0304fefe, 0xeffc0205, 0x0304fe00, - 0x0300fcf9, 0xff020909, 0xff00faf5, 0x01000105, - 0xf5051100, 0x00fafe03, 0x01fcfe02, 0xff0201fc, - 0xfdfbfffb, 0xfefd05fd, 0xfb021004, 0xffff05fe, - 0x01fc0000, 0x0b0502ff, 0x01feffff, 0xfffdfefc, - 0x000afffb, 0xfd000106, 0x0001fc00, 0xff03fcfe, - 0x00030906, 0x00fe01fe, 0xfefefdfe, 0xfa010001, - 0x01020001, 0x01fe03ff, 0x00f1ff00, 0x060205ff, - 0x02020002, 0x06fcf400, 0xff040100, 0xfc010201, - 0x00f9fe01, 0xff000000, 0x030b02fb, 0xfa000301, - 0xfcf7fd00, 0x00ff0301, 0x00fe0104, 0x06fffd07, - 0x0206fe01, 0xfe03ff00, 0x020004fe, 0x02f202ff, - 0xff000202, 0xf2fd03fe, 0xfd030200, 0x02030105, - 0xf204fd01, 0xff0bfe01, 0x0003ff00, 0x020001ff, - 0x02fd03fe, 0x03fcfffc, 0x030102ff, 0x0702fefa, - 0x000201fe, 0xff0000fe, 0x02ff050c, 0xf901fff8, - 0x02fcfe02, 0xfef5000b, 0xfffd0103, 0xff010300, - 0xfe000300, 0xfdfffa00, 0x00fef90c, 0x0101fe07, - 0x02020201, 0x020002ff, 0x000400e9, 0x03010203, - 0x05fffbfc, 0xff0a05fd, 0xfc030000, 0xfb02ff01 +static const int8 s_svq1InterCodebook4x4[1536] = { + 4, 0, -6, -7, -4, -8,-13, -9, -8, -8, -1, 6, -2, 5, 22, 27, + -16, -7, 11, 10,-18, -7, 13, 10,-15, -4, 12, 8, -9, -1, 9, 5, + -2, 2, 15,-16, -3, 2, 19,-19, -3, 2, 19,-19, -2, 3, 15,-14, + 17, 22, 22, 16, -6, -7, -5, -2,-12,-16,-16,-12, 1, 1, -1, -3, + 11,-17, 0, 8, 14,-21, -1, 9, 14,-21, -2, 8, 11,-16, -2, 6, + 7, -2,-16, 11, 9, -2,-21, 14, 10, -1,-22, 14, 8, -1,-18, 10, + -10, 16, 3, -9,-13, 20, 4,-11,-14, 21, 4,-10,-11, 16, 3, -8, + 11, 4, -9, -9, 15, 6,-12,-14, 17, 8,-12,-14, 16, 10, -7,-11, + 4, 10, 14, 13, -1, 7, 15, 16,-12, -7, 3, 8,-20,-23,-18,-10, + -10,-18,-26,-25, 4, 1, -6,-11, 13, 15, 11, 3, 12, 15, 13, 8, + -16,-19,-16,-11, 7, 12, 15, 11, 11, 16, 16, 11, -6, -9,-11,-10, + 18, 19, 12, 5, 18, 16, 5, -4, 6, 0,-10,-15, -9,-17,-23,-22, + -10,-14, -1, 21,-11,-17, 0, 29,-11,-16, 1, 30,-10,-14, 0, 23, + -16,-17,-12, -6,-19,-19,-14, -7, -3, -1, 1, 2, 27, 35, 29, 19, + -37, -8, 23, 23,-42, -9, 28, 29,-43,-10, 26, 28,-38,-11, 19, 22, + 32, 16,-16,-33, 39, 20,-18,-37, 38, 19,-19,-38, 32, 15,-17,-34, + 24, 9, -6, -4, -1,-10, -6, 3, -8, -9, -1, 3, 3, 7, 2, -6, + -1, -3, -1, 0, -1, 4, 2, -7, -3, 11, 3,-16, 1, 20, 9,-18, + -3, -8, 6, 12, -5,-10, 7, 13, -6, -9, 5, 7, -5, -5, 2, -1, + -8, 12, -3, -1,-10, 15, -3, 1,-11, 13, -4, 1,-11, 8, -3, 2, + 9, 6, -5,-12, 3, 0, -8,-13, -4, -4, -1, -1, -4, 1, 15, 18, + 9, 13, 14, 12, 4, 3, -1, -2, -2, -5, -8, -5, -7,-11, -9, -4, + 7, -5, -7, -4, 14, -2, -7, -4, 17, 0, -8, -5, 15, 1, -7, -5, + -10, -1, 6, 4,-15, -9, 2, 4, 2, -1, -3, 0, 25, 13, -8,-10, + 7, 11, -3,-16, 7, 11, -3,-15, 6, 7, -2, -9, 4, 2, -3, -5, + -7, -1, -1, 0, -9, -2, 2, 6,-12, -4, 6, 14,-13, -6, 8, 19, + -18,-18,-11, -5, -3, 0, 3, 4, 6, 8, 6, 6, 6, 6, 6, 6, + -5, 3, 13,-10, -6, 1, 15, -9, -6, -3, 15, -6, -6, -6, 10, -3, + 9, 1, -9, -9, 11, 9, 6, 5, 0, 3, 8, 7,-15,-14, -6, -5, + -11, -6, 11, 19, -2, -5, -9, -8, 6, 2, -9,-10, 6, 5, 4, 5, + -7, -3, 8, 15, -1, 3, 10, 15, 5, 5, -1, -2, 4, -2,-21,-25, + 6, -6, -6, 5, 8, -9, -7, 9, 8,-12, -7, 13, 4,-14, -7, 14, + -4, -3, 1, 1, -3, -5, -2, -3, 7, 0, -2, -4, 20, 7, -4, -4, + -3,-20, -6, 10, 6, 0, 0, 1, 5, 8, 5, -1, -3, 0, 0, -2, + 13, 6, -1, 2, 5, 3, 2, 3, -3, 0, 3, 0,-16, -8, -2, -5, + -2, -7, -6, 0, -3, -6, -3, 1, -5, -1, 2, -1, -1, 12, 16, 5, + -7, 1, 9, 8,-10, -2, 5, 3, -6, 2, 7, 3, -4, 0, -1, -7, + 3, 4, -9,-24, 0, 2, 6, 3, -1, -1, 4, 7, 5, 3, -1, -2, + 3, 6, -9, 2, 1, 6,-13, 1, 1, 8,-10, 2, 1, 8, -7, 1, + -3, -3, 2, 22, -2, -3, -5, 12, -2, -3,-10, 2, -3, -1, -4, 2, + 11, 12, 8, 2, -5, -5, -5, -8, -6, -4, 0, -3, -2, -1, 3, 3, + 12, -6, -2, -1, 12, -8, -2, -2, 9, -7, 0, -3, 4, -6, 2, -2, + -19, 1, 12, -3, -4, 4, 5, -4, 6, 1, -2, -1, 4, -4, -2, 7, + -3, -4, -7, -8, -4, -4, -2, 0, -1, 2, 14, 16, -4, -2, 4, 4, + -1, 7, 2, -5, -2, 0, -1, 1, 4, -3, -1, 13, 6,-12,-14, 8, + -1, 5, 4, -5, -2, 5, 3, -9, -2, 7, 4,-12, -1, 7, 4, -9, + -6, -3, 1, 1, 11, 11, 0, -6, 6, 4, -2, -7,-12,-10, 3, 10, + -2, -3, -3, -2, 6, 11, 14, 10, -9,-11,-10,-10, 2, 2, 3, 2, + -7, -5, -7, -1, -1, 2, 0, 7, -1, 1, 0, 9, 3, 4, -5, -1, + 10, -1,-15, -1, 4, 1, -5, 2, -3, 1, -1, 1, -3, 1, 4, 4, + 2, -1, 4, 10, 6, 2, -1, 0, 2, 2, -7,-12, -4, 2, 0, -3, + -1, -4, -1, -8, 3, -1, 2, -9, 4, 0, 5, -5, 2, 0, 8, 3, + 3, 2, 1, 1, 4, -2, 0, 3, 2, -1, 4, 1, 0, 6, -1,-25, + -1, -2, -2, -4, -3, 0, -1, -4, -1, -1, -4, 2, 0, -6, 2, 25, + -11, -1, 5, 0, 7, 0, -2, 2, 10, -1, -3, 4, -5, -5, -2, -1, + 0, 6, 3, -1, -2, -1, -1, 1, -1, -7,-12, -5, 8, 6, 2, 4, + 2, 6, -1, -6, 9, 10, -1, -4, 1, 0, -4, 0, 3, -2, -9, -5, + -4, 3, 4, 0, -4, 3, 3, 0,-11, 0, 3, 2,-11, 3, 7, 2, + 2, -4, 7, 3, 1, -8, 7, 1, -1,-12, 4, 1, 3, -9, 2, 2, + 2, -2, -2, 9,-17, -3, 3, 1, -4, 7, 1, -6, 5, 4, -1, 3, + -1, 2, 0, -4, -7, 8, 12, -1, -2, 5, 4, -5, 3, -5, -8, -2, + 0, 0, -5, -2, -2, -8, 3, 27, -1, -4, -3, 6, -3, 1, -2, -7, + 4, 4, 1, -1, -7,-10, -7, -3, 10, 10, 5, 3, -2, -2, -4, -3, + 0, 1, 5, 7, 4, -2,-16,-20, 0, 4, 7, 8, 2, 0, -2, -1, + -2, 1, 3, 17, -3, 1, -2, -1, -1, -2, -1, -2, -1, -5, -1, 0, + 5, -3, 1, 0, 6, -2, 0, 0, -1, -2, 0, -3,-11, 1, 8, -1, + 3, 0, 0, 0, 0, 2, 4, 1, 2, 0, 6, 1, -2,-18, -3, 2, + -14, 0, 6, 1, -5, -2, -1, 1, -1, 1, 0, 1, 1, 7, 4, 0, + -1, 0, 1, -4, 1, 8, 3, -4, -3, 4, 1, 3, -6, 1, -4, 1, + 1,-12, 3, 3, -1,-10, 0, -1, 2, 0, 2, 1, 3, 2, 2, 4, + 3, 0, 0, 3, 2, 0, -2, 1, 5, 2, -5, 0, 6, -1,-14, -1, + -2, -6, -3, -3, 2, -1, 4, 5, 6, -1, -2, 0, 4, 4, -1, -5, + -4, 1,-11, 0, -1, 2, -4, 1, 2, -3, 3, -1, 1, -2, 15, 0, + 1, -1, 0, -2, 1, -4, -7, 1, -2, -6, -1, 21, -2, 2, -1, 1, + 21, -1, -2, 0, -1, -3, 1, -2, -9, -2, 2, -1, 2, 1, -4, -1, + 1, 8, 2, -6,-10, -1, 4, 0, -4, -3, 3, 3, 5, 0, -1, -1, + 3, 2, 1, -2, -2, -2, 4, 3, 5, 2, -4,-17, 0, -2, 4, 3, + -7, -4, 0, 3, 9, 9, 2, -1,-11, -6, 0, -1, 5, 1, 0, 1, + 0, 17, 5,-11, 3, -2, -6, 0, 2, -2, -4, 1, -4, 1, 2, -1, + -5, -1, -5, -3, -3, 5, -3, -2, 4, 16, 2, -5, -2, 5, -1, -1, + 0, 0, -4, 1, -1, 2, 5, 11, -1, -1, -2, 1, -4, -2, -3, -1, + -5, -1, 10, 0, 6, 1, 0, -3, 0, -4, 1, 0, -2, -4, 3, -1, + 6, 9, 3, 0, -2, 1, -2, 0, -2, -3, -2, -2, 1, 0, 1, -6, + 1, 0, 2, 1, -1, 3, -2, 1, 0, -1,-15, 0, -1, 5, 2, 6, + 2, 0, 2, 2, 0,-12, -4, 6, 0, 1, 4, -1, 1, 2, 1, -4, + 1, -2, -7, 0, 0, 0, 0, -1, -5, 2, 11, 3, 1, 3, 0, -6, + 0, -3, -9, -4, 1, 3, -1, 0, 4, 1, -2, 0, 7, -3, -1, 6, + 1, -2, 6, 2, 0, -1, 3, -2, -2, 4, 0, 2, -1, 2,-14, 2, + 2, 2, 0, -1, -2, 3, -3,-14, 0, 2, 3, -3, 5, 1, 3, 2, + 1, -3, 4,-14, 1, -2, 11, -1, 0, -1, 3, 0, -1, 1, 0, 2, + -2, 3, -3, 2, -4, -1, -4, 3, -1, 2, 1, 3, -6, -2, 2, 7, + -2, 1, 2, 0, -2, 0, 0, -1, 12, 5, -1, 2, -8, -1, 1, -7, + 2, -2, -4, 2, 11, 0,-11, -2, 3, 1, -3, -1, 0, 3, 1, -1, + 0, 3, 0, -2, 0, -6, -1, -3, 12, -7, -2, 0, 7, -2, 1, 1, + 1, 2, 2, 2, -1, 2, 0, 2,-23, 0, 4, 0, 3, 2, 1, 3, + -4, -5, -1, 5, -3, 5, 10, -1, 0, 0, 3, -4, 1, -1, 2, -5 }; -static const uint32 s_svq1InterCodebook8x4[768] = { - 0x00040809, 0xfdfcfcfd, 0xff040809, 0xfdfbfbfc, - 0xfe030708, 0xfcfbfbfb, 0xfe010406, 0xfdfcfbfc, - 0xfcf5f2f4, 0x06060501, 0xfbf9f6f8, 0x010101fe, - 0x01030405, 0xffff0000, 0x06090d0d, 0xfeff0003, - 0xfffdfcfc, 0x0b080401, 0xfefcfafb, 0x0c080300, - 0xfcfaf9f9, 0x0a0702fe, 0xfcfbf9f9, 0x080501fe, - 0x01fffefd, 0x06070603, 0x07050302, 0x04060808, - 0x03040504, 0xf9fafe01, 0xf9fe0001, 0xf0eff2f6, - 0x0801fcfb, 0xf9fd0309, 0x0b01faf9, 0xf8fd050c, - 0x0900f9f8, 0xf9fd050b, 0x05fffaf8, 0xfafe0408, - 0xf8f9fbfc, 0xfaf8f7f7, 0xf9fafbfc, 0xfefcfaf9, - 0x03020100, 0x090a0805, 0x06030201, 0x0d0e0c09, - 0x05060605, 0x01020304, 0x07070605, 0x04060606, - 0x010100ff, 0x05050503, 0xefeff0f3, 0xfcfaf6f2, - 0x100d0b09, 0x0a0c0d0f, 0xf9fafbfc, 0xfbfaf9f9, - 0xf9f9fafa, 0xfbfaf9f9, 0x0000fffe, 0xff000000, - 0xf0f1f3f5, 0xf6f4f2f0, 0x05040302, 0x03030304, - 0x08080706, 0x05060708, 0x03030403, 0x03030303, - 0x01040403, 0xeff3f9fe, 0x05070705, 0xedf3fb01, - 0x08090806, 0xf0f7ff05, 0x0a0a0806, 0xf5fc0207, - 0xf6ff0912, 0x00fcf7f3, 0xf4ff0c16, 0x02fcf6f1, - 0xf6000d17, 0x02fdf7f3, 0xfa020c14, 0x02fefaf7, - 0xf9fafafa, 0xfaf9f9f9, 0xf8f8f9fa, 0xf8f7f7f7, - 0xfdfdfdfd, 0xfdfdfdfd, 0x15120f0c, 0x0e111315, - 0x1212100e, 0x0d0f1012, 0x05060605, 0x03040405, - 0xf6f7f9fa, 0xf9f7f6f6, 0xf2f3f5f6, 0xf6f4f3f2, - 0x05fcefe5, 0x070a0a09, 0x07fdede0, 0x080b0c0b, - 0x08fef0e2, 0x070a0c0c, 0x0700f4e9, 0x06090b0a, - 0x0c101110, 0xf4f8ff06, 0x0a0f1211, 0xeef1f801, - 0x040a0e0f, 0xe9ecf2fb, 0xff04080a, 0xeaebf0f7, - 0xf5f4f4f6, 0x140e04fb, 0xf4f1f3f5, 0x1b1307fc, - 0xf5f2f3f5, 0x1c1508fd, 0xf7f4f5f6, 0x191208fe, - 0x01ffffff, 0x05060604, 0x02000000, 0xfe010304, - 0x04020000, 0xf6f9ff04, 0x05030000, 0xf1f5fd03, - 0xfff8f3f2, 0xfcff0303, 0x04fffcfb, 0x00030808, - 0x03020203, 0x01030504, 0xfe000305, 0xfffffffe, - 0xfafa0109, 0xfffefdfb, 0xfafa010c, 0x00fffefc, - 0xfcfc040e, 0xfffffefe, 0xffff060e, 0xffffffff, - 0x0a080604, 0x0507090b, 0x00ffffff, 0xfeffff00, - 0xfbfcfcfe, 0xfcfbfbfb, 0xfcfdfdfe, 0xfffefdfc, - 0x04040302, 0x00000103, 0x050401ff, 0x03040506, - 0x02fefaf8, 0x03040403, 0xfbf7f3f2, 0x0000fffe, - 0xfcfbfcfd, 0x0d0c0700, 0xfbfbfcfd, 0x0a0904fe, - 0xfbfcfdfe, 0x0403fffc, 0xfdfeffff, 0x0100fefd, - 0xf8fe0509, 0xfcf9f6f5, 0x02060a0c, 0x0000ff00, - 0x04030202, 0x01010103, 0x00fcf8f7, 0x00010201, - 0x05080806, 0xf3f5fb01, 0x02020100, 0xf5f8fcff, - 0x0301fefd, 0xfcff0103, 0x0502fffe, 0x01040606, - 0x05050403, 0xfafd0104, 0x02040605, 0xfd000202, - 0xfb000506, 0xfefffefb, 0xf5fd0407, 0xfefdf9f4, - 0xffff0001, 0x000000ff, 0x04040302, 0x03040505, - 0xf6f7f7f9, 0xfaf9f7f6, 0x06050403, 0x05050505, - 0xf9f9f9f9, 0xfcfbfafa, 0xfffdfcfb, 0x0000ffff, - 0x0401fefd, 0x05050505, 0x0603fffe, 0x090a0a09, - 0x030a01f2, 0x010100fe, 0x030d02f0, 0x0001fffd, - 0x030c02f1, 0x0101fefc, 0x020a03f6, 0x0101fffd, - 0x02040100, 0x0bfdf6fb, 0x020401ff, 0x0ffef3fa, - 0x010300ff, 0x0ffff4fa, 0x010201ff, 0x0b00f8fc, - 0xfefe050a, 0xfc010502, 0xfaf80007, 0xfc020501, - 0xf9f4fb02, 0xff040702, 0xfcf6f9ff, 0x02070904, - 0xfafcfbfb, 0xfdfbfbfa, 0xfcfefeff, 0xfcfbfafb, - 0x04070706, 0xfdfdfe00, 0x0a0d0e0d, 0xfeff0105, - 0x02020101, 0x02020202, 0xf7f8fafb, 0xfaf9f8f7, - 0x0b0a0907, 0x0507090b, 0xfdfdfeff, 0xfdfcfcfc, - 0x0000ffff, 0xffff0000, 0xfbfcfdfd, 0xfefdfdfc, - 0xfdff0102, 0x00fffefd, 0x03080c0c, 0x01000001, - 0xfaf8f8fa, 0x080602fe, 0xfeff0101, 0x07050300, - 0xff010303, 0x020000ff, 0xff000100, 0xfffeffff, - 0x00000001, 0x04020000, 0x04030102, 0x02000103, - 0x00000102, 0x0300ffff, 0xf4fa0105, 0x04fff8f3, - 0xfeff00fe, 0x030200ff, 0x00fefdfa, 0x01010101, - 0x0400fbf7, 0x00010305, 0x0703fdf8, 0x00010408, - 0x03020201, 0xfdff0103, 0x06050504, 0x00020506, - 0x00000000, 0xfcfe0001, 0xfdfcfdfd, 0xf8f9fcfd, - 0xff060c0e, 0x0000fdfd, 0xfd010507, 0xfffefcfb, - 0xfefefefe, 0xfffffefe, 0x01fffcfa, 0xff000101, - 0xfd010202, 0xfdfaf9fa, 0xfdff0001, 0x060401fe, - 0x02010000, 0x07080704, 0x00000000, 0xf8f9fcff, - 0xfe010200, 0xfffefdfd, 0xfd0001ff, 0x0200fefb, - 0xfbfefffe, 0x090601fc, 0xfcfdfefd, 0x0d0b05fe, - 0x0602fefc, 0xf2f6fd04, 0x0401fffe, 0xfeff0104, - 0xfeff0000, 0x060400fe, 0xfd000202, 0x090500fd, - 0x01fefcfc, 0xf9030906, 0xfffefefe, 0xf5000804, - 0x00000101, 0xf6ff0602, 0x00010202, 0xf9000402, - 0xfafdfeff, 0xf8f8f8f9, 0x01030302, 0xfcfdfeff, - 0x04050505, 0xff000203, 0x03030303, 0x01010202, - 0xfe020303, 0x0a0700fd, 0xfe020201, 0x0300fcfb, - 0x02040300, 0xfcfafbfd, 0x04040200, 0xf9f9fc01, - 0x05050402, 0x06060505, 0xfbfdfcfc, 0xfefdfdfb, - 0xfbfcfcfd, 0xfefefefc, 0x00000101, 0x04050402, - 0x040300fe, 0x02020304, 0x00fcf9f7, 0x06060603, - 0xfefdfbfb, 0x04030100, 0xfe020505, 0xfdfbfafc, - 0x07fcfa01, 0x01fefe05, 0x06fcfb05, 0x01fcfb04, - 0x06fcfb05, 0x01fdfb04, 0x08fdf901, 0x01fdff07, - 0x00fcf9f8, 0x05050402, 0x02050605, 0xf9f9fbff, - 0x01040605, 0xfbfafbfd, 0xfefbf9f9, 0x0a090601, - 0x01000306, 0xf2f80003, 0x01ff0003, 0xfc000304, - 0x01000001, 0x01010102, 0x0201ffff, 0x00ffff01, - 0x01010101, 0x00fdfe00, 0x00010201, 0xfcf7f8fe, - 0x02030301, 0x01fdfd01, 0x01010100, 0x08040101, - 0x07090502, 0x01ffff02, 0x0001fffc, 0x02fffcfd, - 0x030300fd, 0x0200ff00, 0x0101fffc, 0xfcfbfcfe, - 0xfefeff01, 0x050402ff, 0x00010102, 0x0000ffff, - 0x05040302, 0x00010204, 0xfdfaf7f7, 0xffffffff, - 0x0704fafa, 0xfefffe00, 0x0605feff, 0xff00feff, - 0x0001ff04, 0xfe00fefc, 0xfeff0107, 0x010301fd, - 0x03010204, 0x02010103, 0x00fcfe02, 0x00000103, - 0xfcf8fc01, 0x00010201, 0xfaf7fd02, 0x02030300, - 0xff00ffff, 0x020100ff, 0xf8fc0103, 0x0201fdf9, - 0xfefdff02, 0x000100ff, 0x0b0500ff, 0xfdff0309, - 0xfffefeff, 0x01010101, 0x0300ff00, 0x05050606, - 0xffff0102, 0xfcfafbfe, 0x01020202, 0xfbfbfcff, - 0xf9fafdff, 0x01fffcfa, 0x04030505, 0x05040304, - 0xfefdfeff, 0x0100fefe, 0x00000000, 0x03020100, - 0xfffcfafa, 0x02020202, 0xfefbf9fa, 0x00ffff00, - 0x04020202, 0x04030304, 0xff000102, 0x04020000, - 0xf8fb050c, 0x020200fb, 0xfdfafd02, 0xfeff0000, - 0x03fffdfe, 0xfdfe0104, 0x04030202, 0xffff0103, - 0x00010203, 0x00030401, 0xfb000304, 0x030300fa, - 0xf9010302, 0x0301faf4, 0xff040301, 0x0100fcfa, - 0x0602fcf7, 0x00010407, 0x0604fff9, 0xfdfd0004, - 0x040400fa, 0xfefdfe01, 0x020301fc, 0x00fffe00, - 0xfb020500, 0xfc0103fd, 0xfa0204fe, 0xfd0406fd, - 0xfb0305ff, 0xfc0307ff, 0xfa0002ff, 0xfd0305fd, - 0x0503fdf8, 0xfefe0103, 0xfe040402, 0x0301fdfc, - 0xfbfd0102, 0x030403fd, 0x03fbfafb, 0xfbff080a, - 0xfc020300, 0x0600f9f7, 0x0705fffb, 0xfdfdff04, - 0x03fefbfb, 0xfcff0506, 0xfc000609, 0xff0101fe, - 0x01ffffff, 0x00ff0001, 0x000000ff, 0x00ffff00, - 0xfffe0102, 0x00000101, 0xff02080c, 0xf9f9fcff, - 0x06030102, 0x00020407, 0x00ff0001, 0xf8f9fcff, - 0x00ff0000, 0xfdff0000, 0x00000000, 0xfe000101, - 0x010100ff, 0xfeff0000, 0xfdff0000, 0x01fffdfc, - 0x000000ff, 0x0c0a0401, 0xfefe00ff, 0x01fffdfd, - 0xfcfefffd, 0x07090902, 0xfdff00fd, 0x01ff0200, - 0xfdfe01ff, 0x00fdff00, 0xfefd0000, 0x01ffff00, - 0xfffffeff, 0xfefffffe, 0xfffeff02, 0xfe000100, - 0x02feff03, 0xfdff0305, 0x01fbfb01, 0x00020606, - 0xff000201, 0xfe000100, 0x00fffdfb, 0xfe010201, - 0xfefefbf9, 0x0100fefe, 0x010100ff, 0x0c090300, - 0x01050600, 0x0300fdfe, 0x01050600, 0x03020101, - 0xfdfefefb, 0x00000000, 0xfefdfdfa, 0xfeff0000, - 0x01020404, 0x00ffff00, 0x0100fefe, 0x00010102, - 0xff010202, 0xf6f7fbfd, 0xffff0102, 0x01040401, - 0xfefe0004, 0x00fffefe, 0xfdfc0107, 0x010100fe, - 0xfeff050a, 0x00010100, 0xfcfd0105, 0xfefffffd, - 0xfdff0102, 0xff0101fd, 0x0003fffe, 0x000101ff, - 0x020701fd, 0x00fffefd, 0xff0804fe, 0x0200fbf8, - 0x0201fffc, 0xfefcfd01, 0x01fefdfb, 0x06040404, - 0xfdfcfefd, 0x02010100, 0x01020202, 0xffff0102, - 0xff00fffc, 0xfffffdfd, 0x02040401, 0xfdfeff00, - 0x03050604, 0xfcfe0102, 0x01010100, 0xfafcff01, - 0xff020201, 0x02fffbfa, 0x0101fefd, 0x0502fdfc, - 0x0202fffe, 0x0300fcfd, 0x0602fefe, 0x02010205, - 0x00fdfd02, 0x01030200, 0x0301ff03, 0xfbff0201, - 0xfefcf9fb, 0x01080801, 0x000200ff, 0xfd0100fd, - 0xfefbfbfe, 0xfe00fffd, 0x0400fcff, 0x00040200, - 0x0a080000, 0xff030102, 0x0302fdfc, 0xff01fdfd, - 0x02fcfe01, 0xfffe0307, 0xfffe0406, 0x03ff0002, - 0xfefe0101, 0x04fdfbfe, 0x0101fefa, 0x04fefcff, - 0xfefefffe, 0xfe000100, 0xff0001ff, 0xfdff0000, - 0xfcfe0100, 0x0000fffd, 0x00050806, 0x03020100, - 0x0502fefe, 0x01000002, 0xfffefe02, 0x040201ff, - 0x0100ff02, 0x01000000, 0x01fff9f8, 0x0301ffff, - 0x02060300, 0x000201fe, 0x00fff9f6, 0x0102fffd, - 0x02020000, 0xff010101, 0xfefe0003, 0x00010200, - 0x00000108, 0x00fffdfe, 0x0502fe02, 0x01fffe01, - 0xfffdfafd, 0x02fffdfd, 0x02010002, 0x00000102, - 0xfeffff01, 0x000100ff, 0xff02090f, 0xfdfdfdfe, - 0x00fefd00, 0xffffff00, 0x00010001, 0xffffff00, - 0xfe020200, 0xf8f9fdfd, 0x00020200, 0x01010201, - 0x02020201, 0x03000103, 0xfeff0001, 0x0500feff, - 0x01fffaf5, 0xfd010302, 0xff030401, 0xff0201fe, - 0xff010202, 0xff0100fe, 0xffff0000, 0x02030200, - 0x01020101, 0xfc0001ff, 0xfe000000, 0xfe0402fe, - 0x0000fdfe, 0xfa0102ff, 0x05050200, 0xf9ff0203, - 0x00000204, 0xff010303, 0x03ffff00, 0xff010406, - 0x0200fefe, 0xfefe0002, 0xfbff00ff, 0x01fffbf9, - 0x00feff05, 0xfb020402, 0x02fefb00, 0xfa000201, - 0x01000106, 0x0204fffe, 0x00fdfd02, 0x0000feff, - 0x0200ff01, 0x0b060000, 0x00ffff02, 0x0503fefd, - 0x00fffe00, 0xfd0000ff, 0xffffff01, 0xf9fdfffe, - 0xfefe0101, 0xfe010301, 0xff0002ff, 0x000001ff, - 0xff0302fc, 0x0100fefe, 0x0504fef5, 0xfeff0206, - 0xff01fefa, 0x0901fcfd, 0x030300fd, 0x03fdfd02, - 0x00000101, 0x03feff01, 0xfdfd0002, 0x03ffff00, - 0x01fdff01, 0x06fcfa02, 0xfefbfe00, 0x03fefd00, - 0xfe010202, 0xff0201fe, 0xfe0101ff, 0xff0706ff, - 0xfefc0001, 0x01fdfe01, 0xfefd00fc, 0x00fd0002, - 0x010304fd, 0xff000708, 0xfc0104fd, 0xfdfe0302, - 0xfc0106fd, 0xffff0101, 0xfdfd04fe, 0xffff0003, - 0x02fc0201, 0x02fffd04, 0x05fcff03, 0x02fdfa04 +static const int8 s_svq1InterCodebook8x4[3072] = { + 9, 8, 4, 0, -3, -4, -4, -3, 9, 8, 4, -1, -4, -5, -5, -3, + 8, 7, 3, -2, -5, -5, -5, -4, 6, 4, 1, -2, -4, -5, -4, -3, + -12,-14,-11, -4, 1, 5, 6, 6, -8,-10, -7, -5, -2, 1, 1, 1, + 5, 4, 3, 1, 0, 0, -1, -1, 13, 13, 9, 6, 3, 0, -1, -2, + -4, -4, -3, -1, 1, 4, 8, 11, -5, -6, -4, -2, 0, 3, 8, 12, + -7, -7, -6, -4, -2, 2, 7, 10, -7, -7, -5, -4, -2, 1, 5, 8, + -3, -2, -1, 1, 3, 6, 7, 6, 2, 3, 5, 7, 8, 8, 6, 4, + 4, 5, 4, 3, 1, -2, -6, -7, 1, 0, -2, -7,-10,-14,-17,-16, + -5, -4, 1, 8, 9, 3, -3, -7, -7, -6, 1, 11, 12, 5, -3, -8, + -8, -7, 0, 9, 11, 5, -3, -7, -8, -6, -1, 5, 8, 4, -2, -6, + -4, -5, -7, -8, -9, -9, -8, -6, -4, -5, -6, -7, -7, -6, -4, -2, + 0, 1, 2, 3, 5, 8, 10, 9, 1, 2, 3, 6, 9, 12, 14, 13, + 5, 6, 6, 5, 4, 3, 2, 1, 5, 6, 7, 7, 6, 6, 6, 4, + -1, 0, 1, 1, 3, 5, 5, 5,-13,-16,-17,-17,-14,-10, -6, -4, + 9, 11, 13, 16, 15, 13, 12, 10, -4, -5, -6, -7, -7, -7, -6, -5, + -6, -6, -7, -7, -7, -7, -6, -5, -2, -1, 0, 0, 0, 0, 0, -1, + -11,-13,-15,-16,-16,-14,-12,-10, 2, 3, 4, 5, 4, 3, 3, 3, + 6, 7, 8, 8, 8, 7, 6, 5, 3, 4, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 1, -2, -7,-13,-17, 5, 7, 7, 5, 1, -5,-13,-19, + 6, 8, 9, 8, 5, -1, -9,-16, 6, 8, 10, 10, 7, 2, -4,-11, + 18, 9, -1,-10,-13, -9, -4, 0, 22, 12, -1,-12,-15,-10, -4, 2, + 23, 13, 0,-10,-13, -9, -3, 2, 20, 12, 2, -6, -9, -6, -2, 2, + -6, -6, -6, -7, -7, -7, -7, -6, -6, -7, -8, -8, -9, -9, -9, -8, + -3, -3, -3, -3, -3, -3, -3, -3, 12, 15, 18, 21, 21, 19, 17, 14, + 14, 16, 18, 18, 18, 16, 15, 13, 5, 6, 6, 5, 5, 4, 4, 3, + -6, -7, -9,-10,-10,-10, -9, -7,-10,-11,-13,-14,-14,-13,-12,-10, + -27,-17, -4, 5, 9, 10, 10, 7,-32,-19, -3, 7, 11, 12, 11, 8, + -30,-16, -2, 8, 12, 12, 10, 7,-23,-12, 0, 7, 10, 11, 9, 6, + 16, 17, 16, 12, 6, -1, -8,-12, 17, 18, 15, 10, 1, -8,-15,-18, + 15, 14, 10, 4, -5,-14,-20,-23, 10, 8, 4, -1, -9,-16,-21,-22, + -10,-12,-12,-11, -5, 4, 14, 20,-11,-13,-15,-12, -4, 7, 19, 27, + -11,-13,-14,-11, -3, 8, 21, 28,-10,-11,-12, -9, -2, 8, 18, 25, + -1, -1, -1, 1, 4, 6, 6, 5, 0, 0, 0, 2, 4, 3, 1, -2, + 0, 0, 2, 4, 4, -1, -7,-10, 0, 0, 3, 5, 3, -3,-11,-15, + -14,-13, -8, -1, 3, 3, -1, -4, -5, -4, -1, 4, 8, 8, 3, 0, + 3, 2, 2, 3, 4, 5, 3, 1, 5, 3, 0, -2, -2, -1, -1, -1, + 9, 1, -6, -6, -5, -3, -2, -1, 12, 1, -6, -6, -4, -2, -1, 0, + 14, 4, -4, -4, -2, -2, -1, -1, 14, 6, -1, -1, -1, -1, -1, -1, + 4, 6, 8, 10, 11, 9, 7, 5, -1, -1, -1, 0, 0, -1, -1, -2, + -2, -4, -4, -5, -5, -5, -5, -4, -2, -3, -3, -4, -4, -3, -2, -1, + 2, 3, 4, 4, 3, 1, 0, 0, -1, 1, 4, 5, 6, 5, 4, 3, + -8, -6, -2, 2, 3, 4, 4, 3,-14,-13, -9, -5, -2, -1, 0, 0, + -3, -4, -5, -4, 0, 7, 12, 13, -3, -4, -5, -5, -2, 4, 9, 10, + -2, -3, -4, -5, -4, -1, 3, 4, -1, -1, -2, -3, -3, -2, 0, 1, + 9, 5, -2, -8,-11,-10, -7, -4, 12, 10, 6, 2, 0, -1, 0, 0, + 2, 2, 3, 4, 3, 1, 1, 1, -9, -8, -4, 0, 1, 2, 1, 0, + 6, 8, 8, 5, 1, -5,-11,-13, 0, 1, 2, 2, -1, -4, -8,-11, + -3, -2, 1, 3, 3, 1, -1, -4, -2, -1, 2, 5, 6, 6, 4, 1, + 3, 4, 5, 5, 4, 1, -3, -6, 5, 6, 4, 2, 2, 2, 0, -3, + 6, 5, 0, -5, -5, -2, -1, -2, 7, 4, -3,-11,-12, -7, -3, -2, + 1, 0, -1, -1, -1, 0, 0, 0, 2, 3, 4, 4, 5, 5, 4, 3, + -7, -9, -9,-10,-10, -9, -7, -6, 3, 4, 5, 6, 5, 5, 5, 5, + -7, -7, -7, -7, -6, -6, -5, -4, -5, -4, -3, -1, -1, -1, 0, 0, + -3, -2, 1, 4, 5, 5, 5, 5, -2, -1, 3, 6, 9, 10, 10, 9, + -14, 1, 10, 3, -2, 0, 1, 1,-16, 2, 13, 3, -3, -1, 1, 0, + -15, 2, 12, 3, -4, -2, 1, 1,-10, 3, 10, 2, -3, -1, 1, 1, + 0, 1, 4, 2, -5,-10, -3, 11, -1, 1, 4, 2, -6,-13, -2, 15, + -1, 0, 3, 1, -6,-12, -1, 15, -1, 1, 2, 1, -4, -8, 0, 11, + 10, 5, -2, -2, 2, 5, 1, -4, 7, 0, -8, -6, 1, 5, 2, -4, + 2, -5,-12, -7, 2, 7, 4, -1, -1, -7,-10, -4, 4, 9, 7, 2, + -5, -5, -4, -6, -6, -5, -5, -3, -1, -2, -2, -4, -5, -6, -5, -4, + 6, 7, 7, 4, 0, -2, -3, -3, 13, 14, 13, 10, 5, 1, -1, -2, + 1, 1, 2, 2, 2, 2, 2, 2, -5, -6, -8, -9, -9, -8, -7, -6, + 7, 9, 10, 11, 11, 9, 7, 5, -1, -2, -3, -3, -4, -4, -4, -3, + -1, -1, 0, 0, 0, 0, -1, -1, -3, -3, -4, -5, -4, -3, -3, -2, + 2, 1, -1, -3, -3, -2, -1, 0, 12, 12, 8, 3, 1, 0, 0, 1, + -6, -8, -8, -6, -2, 2, 6, 8, 1, 1, -1, -2, 0, 3, 5, 7, + 3, 3, 1, -1, -1, 0, 0, 2, 0, 1, 0, -1, -1, -1, -2, -1, + 1, 0, 0, 0, 0, 0, 2, 4, 2, 1, 3, 4, 3, 1, 0, 2, + 2, 1, 0, 0, -1, -1, 0, 3, 5, 1, -6,-12,-13, -8, -1, 4, + -2, 0, -1, -2, -1, 0, 2, 3, -6, -3, -2, 0, 1, 1, 1, 1, + -9, -5, 0, 4, 5, 3, 1, 0, -8, -3, 3, 7, 8, 4, 1, 0, + 1, 2, 2, 3, 3, 1, -1, -3, 4, 5, 5, 6, 6, 5, 2, 0, + 0, 0, 0, 0, 1, 0, -2, -4, -3, -3, -4, -3, -3, -4, -7, -8, + 14, 12, 6, -1, -3, -3, 0, 0, 7, 5, 1, -3, -5, -4, -2, -1, + -2, -2, -2, -2, -2, -2, -1, -1, -6, -4, -1, 1, 1, 1, 0, -1, + 2, 2, 1, -3, -6, -7, -6, -3, 1, 0, -1, -3, -2, 1, 4, 6, + 0, 0, 1, 2, 4, 7, 8, 7, 0, 0, 0, 0, -1, -4, -7, -8, + 0, 2, 1, -2, -3, -3, -2, -1, -1, 1, 0, -3, -5, -2, 0, 2, + -2, -1, -2, -5, -4, 1, 6, 9, -3, -2, -3, -4, -2, 5, 11, 13, + -4, -2, 2, 6, 4, -3,-10,-14, -2, -1, 1, 4, 4, 1, -1, -2, + 0, 0, -1, -2, -2, 0, 4, 6, 2, 2, 0, -3, -3, 0, 5, 9, + -4, -4, -2, 1, 6, 9, 3, -7, -2, -2, -2, -1, 4, 8, 0,-11, + 1, 1, 0, 0, 2, 6, -1,-10, 2, 2, 1, 0, 2, 4, 0, -7, + -1, -2, -3, -6, -7, -8, -8, -8, 2, 3, 3, 1, -1, -2, -3, -4, + 5, 5, 5, 4, 3, 2, 0, -1, 3, 3, 3, 3, 2, 2, 1, 1, + 3, 3, 2, -2, -3, 0, 7, 10, 1, 2, 2, -2, -5, -4, 0, 3, + 0, 3, 4, 2, -3, -5, -6, -4, 0, 2, 4, 4, 1, -4, -7, -7, + 2, 4, 5, 5, 5, 5, 6, 6, -4, -4, -3, -5, -5, -3, -3, -2, + -3, -4, -4, -5, -4, -2, -2, -2, 1, 1, 0, 0, 2, 4, 5, 4, + -2, 0, 3, 4, 4, 3, 2, 2, -9, -7, -4, 0, 3, 6, 6, 6, + -5, -5, -3, -2, 0, 1, 3, 4, 5, 5, 2, -2, -4, -6, -5, -3, + 1, -6, -4, 7, 5, -2, -2, 1, 5, -5, -4, 6, 4, -5, -4, 1, + 5, -5, -4, 6, 4, -5, -3, 1, 1, -7, -3, 8, 7, -1, -3, 1, + -8, -7, -4, 0, 2, 4, 5, 5, 5, 6, 5, 2, -1, -5, -7, -7, + 5, 6, 4, 1, -3, -5, -6, -5, -7, -7, -5, -2, 1, 6, 9, 10, + 6, 3, 0, 1, 3, 0, -8,-14, 3, 0, -1, 1, 4, 3, 0, -4, + 1, 0, 0, 1, 2, 1, 1, 1, -1, -1, 1, 2, 1, -1, -1, 0, + 1, 1, 1, 1, 0, -2, -3, 0, 1, 2, 1, 0, -2, -8, -9, -4, + 1, 3, 3, 2, 1, -3, -3, 1, 0, 1, 1, 1, 1, 1, 4, 8, + 2, 5, 9, 7, 2, -1, -1, 1, -4, -1, 1, 0, -3, -4, -1, 2, + -3, 0, 3, 3, 0, -1, 0, 2, -4, -1, 1, 1, -2, -4, -5, -4, + 1, -1, -2, -2, -1, 2, 4, 5, 2, 1, 1, 0, -1, -1, 0, 0, + 2, 3, 4, 5, 4, 2, 1, 0, -9, -9, -6, -3, -1, -1, -1, -1, + -6, -6, 4, 7, 0, -2, -1, -2, -1, -2, 5, 6, -1, -2, 0, -1, + 4, -1, 1, 0, -4, -2, 0, -2, 7, 1, -1, -2, -3, 1, 3, 1, + 4, 2, 1, 3, 3, 1, 1, 2, 2, -2, -4, 0, 3, 1, 0, 0, + 1, -4, -8, -4, 1, 2, 1, 0, 2, -3, -9, -6, 0, 3, 3, 2, + -1, -1, 0, -1, -1, 0, 1, 2, 3, 1, -4, -8, -7, -3, 1, 2, + 2, -1, -3, -2, -1, 0, 1, 0, -1, 0, 5, 11, 9, 3, -1, -3, + -1, -2, -2, -1, 1, 1, 1, 1, 0, -1, 0, 3, 6, 6, 5, 5, + 2, 1, -1, -1, -2, -5, -6, -4, 2, 2, 2, 1, -1, -4, -5, -5, + -1, -3, -6, -7, -6, -4, -1, 1, 5, 5, 3, 4, 4, 3, 4, 5, + -1, -2, -3, -2, -2, -2, 0, 1, 0, 0, 0, 0, 0, 1, 2, 3, + -6, -6, -4, -1, 2, 2, 2, 2, -6, -7, -5, -2, 0, -1, -1, 0, + 2, 2, 2, 4, 4, 3, 3, 4, 2, 1, 0, -1, 0, 0, 2, 4, + 12, 5, -5, -8, -5, 0, 2, 2, 2, -3, -6, -3, 0, 0, -1, -2, + -2, -3, -1, 3, 4, 1, -2, -3, 2, 2, 3, 4, 3, 1, -1, -1, + 3, 2, 1, 0, 1, 4, 3, 0, 4, 3, 0, -5, -6, 0, 3, 3, + 2, 3, 1, -7,-12, -6, 1, 3, 1, 3, 4, -1, -6, -4, 0, 1, + -9, -4, 2, 6, 7, 4, 1, 0, -7, -1, 4, 6, 4, 0, -3, -3, + -6, 0, 4, 4, 1, -2, -3, -2, -4, 1, 3, 2, 0, -2, -1, 0, + 0, 5, 2, -5, -3, 3, 1, -4, -2, 4, 2, -6, -3, 6, 4, -3, + -1, 5, 3, -5, -1, 7, 3, -4, -1, 2, 0, -6, -3, 5, 3, -3, + -8, -3, 3, 5, 3, 1, -2, -2, 2, 4, 4, -2, -4, -3, 1, 3, + 2, 1, -3, -5, -3, 3, 4, 3, -5, -6, -5, 3, 10, 8, -1, -5, + 0, 3, 2, -4, -9, -7, 0, 6, -5, -1, 5, 7, 4, -1, -3, -3, + -5, -5, -2, 3, 6, 5, -1, -4, 9, 6, 0, -4, -2, 1, 1, -1, + -1, -1, -1, 1, 1, 0, -1, 0, -1, 0, 0, 0, 0, -1, -1, 0, + 2, 1, -2, -1, 1, 1, 0, 0, 12, 8, 2, -1, -1, -4, -7, -7, + 2, 1, 3, 6, 7, 4, 2, 0, 1, 0, -1, 0, -1, -4, -7, -8, + 0, 0, -1, 0, 0, 0, -1, -3, 0, 0, 0, 0, 1, 1, 0, -2, + -1, 0, 1, 1, 0, 0, -1, -2, 0, 0, -1, -3, -4, -3, -1, 1, + -1, 0, 0, 0, 1, 4, 10, 12, -1, 0, -2, -2, -3, -3, -1, 1, + -3, -1, -2, -4, 2, 9, 9, 7, -3, 0, -1, -3, 0, 2, -1, 1, + -1, 1, -2, -3, 0, -1, -3, 0, 0, 0, -3, -2, 0, -1, -1, 1, + -1, -2, -1, -1, -2, -1, -1, -2, 2, -1, -2, -1, 0, 1, 0, -2, + 3, -1, -2, 2, 5, 3, -1, -3, 1, -5, -5, 1, 6, 6, 2, 0, + 1, 2, 0, -1, 0, 1, 0, -2, -5, -3, -1, 0, 1, 2, 1, -2, + -7, -5, -2, -2, -2, -2, 0, 1, -1, 0, 1, 1, 0, 3, 9, 12, + 0, 6, 5, 1, -2, -3, 0, 3, 0, 6, 5, 1, 1, 1, 2, 3, + -5, -2, -2, -3, 0, 0, 0, 0, -6, -3, -3, -2, 0, 0, -1, -2, + 4, 4, 2, 1, 0, -1, -1, 0, -2, -2, 0, 1, 2, 1, 1, 0, + 2, 2, 1, -1, -3, -5, -9,-10, 2, 1, -1, -1, 1, 4, 4, 1, + 4, 0, -2, -2, -2, -2, -1, 0, 7, 1, -4, -3, -2, 0, 1, 1, + 10, 5, -1, -2, 0, 1, 1, 0, 5, 1, -3, -4, -3, -1, -1, -2, + 2, 1, -1, -3, -3, 1, 1, -1, -2, -1, 3, 0, -1, 1, 1, 0, + -3, 1, 7, 2, -3, -2, -1, 0, -2, 4, 8, -1, -8, -5, 0, 2, + -4, -1, 1, 2, 1, -3, -4, -2, -5, -3, -2, 1, 4, 4, 4, 6, + -3, -2, -4, -3, 0, 1, 1, 2, 2, 2, 2, 1, 2, 1, -1, -1, + -4, -1, 0, -1, -3, -3, -1, -1, 1, 4, 4, 2, 0, -1, -2, -3, + 4, 6, 5, 3, 2, 1, -2, -4, 0, 1, 1, 1, 1, -1, -4, -6, + 1, 2, 2, -1, -6, -5, -1, 2, -3, -2, 1, 1, -4, -3, 2, 5, + -2, -1, 2, 2, -3, -4, 0, 3, -2, -2, 2, 6, 5, 2, 1, 2, + 2, -3, -3, 0, 0, 2, 3, 1, 3, -1, 1, 3, 1, 2, -1, -5, + -5, -7, -4, -2, 1, 8, 8, 1, -1, 0, 2, 0, -3, 0, 1, -3, + -2, -5, -5, -2, -3, -1, 0, -2, -1, -4, 0, 4, 0, 2, 4, 0, + 0, 0, 8, 10, 2, 1, 3, -1, -4, -3, 2, 3, -3, -3, 1, -1, + 1, -2, -4, 2, 7, 3, -2, -1, 6, 4, -2, -1, 2, 0, -1, 3, + 1, 1, -2, -2, -2, -5, -3, 4, -6, -2, 1, 1, -1, -4, -2, 4, + -2, -1, -2, -2, 0, 1, 0, -2, -1, 1, 0, -1, 0, 0, -1, -3, + 0, 1, -2, -4, -3, -1, 0, 0, 6, 8, 5, 0, 0, 1, 2, 3, + -2, -2, 2, 5, 2, 0, 0, 1, 2, -2, -2, -1, -1, 1, 2, 4, + 2, -1, 0, 1, 0, 0, 0, 1, -8, -7, -1, 1, -1, -1, 1, 3, + 0, 3, 6, 2, -2, 1, 2, 0,-10, -7, -1, 0, -3, -1, 2, 1, + 0, 0, 2, 2, 1, 1, 1, -1, 3, 0, -2, -2, 0, 2, 1, 0, + 8, 1, 0, 0, -2, -3, -1, 0, 2, -2, 2, 5, 1, -2, -1, 1, + -3, -6, -3, -1, -3, -3, -1, 2, 2, 0, 1, 2, 2, 1, 0, 0, + 1, -1, -1, -2, -1, 0, 1, 0, 15, 9, 2, -1, -2, -3, -3, -3, + 0, -3, -2, 0, 0, -1, -1, -1, 1, 0, 1, 0, 0, -1, -1, -1, + 0, 2, 2, -2, -3, -3, -7, -8, 0, 2, 2, 0, 1, 2, 1, 1, + 1, 2, 2, 2, 3, 1, 0, 3, 1, 0, -1, -2, -1, -2, 0, 5, + -11, -6, -1, 1, 2, 3, 1, -3, 1, 4, 3, -1, -2, 1, 2, -1, + 2, 2, 1, -1, -2, 0, 1, -1, 0, 0, -1, -1, 0, 2, 3, 2, + 1, 1, 2, 1, -1, 1, 0, -4, 0, 0, 0, -2, -2, 2, 4, -2, + -2, -3, 0, 0, -1, 2, 1, -6, 0, 2, 5, 5, 3, 2, -1, -7, + 4, 2, 0, 0, 3, 3, 1, -1, 0, -1, -1, 3, 6, 4, 1, -1, + -2, -2, 0, 2, 2, 0, -2, -2, -1, 0, -1, -5, -7, -5, -1, 1, + 5, -1, -2, 0, 2, 4, 2, -5, 0, -5, -2, 2, 1, 2, 0, -6, + 6, 1, 0, 1, -2, -1, 4, 2, 2, -3, -3, 0, -1, -2, 0, 0, + 1, -1, 0, 2, 0, 0, 6, 11, 2, -1, -1, 0, -3, -2, 3, 5, + 0, -2, -1, 0, -1, 0, 0, -3, 1, -1, -1, -1, -2, -1, -3, -7, + 1, 1, -2, -2, 1, 3, 1, -2, -1, 2, 0, -1, -1, 1, 0, 0, + -4, 2, 3, -1, -2, -2, 0, 1,-11, -2, 4, 5, 6, 2, -1, -2, + -6, -2, 1, -1, -3, -4, 1, 9, -3, 0, 3, 3, 2, -3, -3, 3, + 1, 1, 0, 0, 1, -1, -2, 3, 2, 0, -3, -3, 0, -1, -1, 3, + 1, -1, -3, 1, 2, -6, -4, 6, 0, -2, -5, -2, 0, -3, -2, 3, + 2, 2, 1, -2, -2, 1, 2, -1, -1, 1, 1, -2, -1, 6, 7, -1, + 1, 0, -4, -2, 1, -2, -3, 1, -4, 0, -3, -2, 2, 0, -3, 0, + -3, 4, 3, 1, 8, 7, 0, -1, -3, 4, 1, -4, 2, 3, -2, -3, + -3, 6, 1, -4, 1, 1, -1, -1, -2, 4, -3, -3, 3, 0, -1, -1, + 1, 2, -4, 2, 4, -3, -1, 2, 3, -1, -4, 5, 4, -6, -3, 2 }; -static const uint32 s_svq1InterCodebook8x8[1536] = { - 0x0504fdfc, 0x00010102, 0x0505fdfb, 0x00000102, - 0x0505fcfa, 0x00000102, 0x0504fcf9, 0x00000102, - 0x0403fbf8, 0x00000102, 0x0403faf8, 0x00010101, - 0x0402faf8, 0x00010102, 0x0402faf8, 0x01010101, - 0xffffffff, 0xffffffff, 0xfefefeff, 0xfefefefe, - 0xfdfdfdfe, 0xfdfdfdfd, 0xfdfdfdfe, 0xfdfcfdfd, - 0xfefefefe, 0xfefdfdfe, 0x01010101, 0xffff0001, - 0x05050504, 0x02030304, 0x08080707, 0x05060708, - 0x04020102, 0xfafc0004, 0x05020101, 0xf9fb0105, - 0x04010201, 0xf8fb0105, 0x05010101, 0xf8fa0005, - 0x05010100, 0xf7fa0106, 0x04010000, 0xf8fb0005, - 0x04010000, 0xf9fb0005, 0x04010000, 0xf9fc0104, - 0x00030201, 0xfffdfcfd, 0x00040301, 0xfffdfcfd, - 0x01050402, 0xfefdfcfd, 0x01060502, 0xfefcfbfd, - 0x01060603, 0xfefcfbfd, 0x01060603, 0xfefcfbfd, - 0x01060603, 0xfefcfbfd, 0x01050503, 0xfefcfcfd, - 0x02020202, 0xff000001, 0x03040404, 0x00010102, - 0x04040504, 0x01020303, 0x04040404, 0x02020304, - 0x03030302, 0x01020303, 0xffffffff, 0x00000000, - 0xfbfafafb, 0xfdfdfcfb, 0xf8f7f7f9, 0xfbfafaf9, - 0x06060606, 0x04050506, 0x03040404, 0x02030303, - 0xffffff00, 0xfffffefe, 0xfafafbfd, 0xfcfbfafa, - 0xf9fafbfd, 0xfcfbfafa, 0xfefefeff, 0xfffffefe, - 0x01010100, 0x01010101, 0x03030303, 0x03030303, - 0xfbfe0102, 0x050200fc, 0xfafe0102, 0x050300fb, - 0xfafe0102, 0x0603fffa, 0xf9fe0203, 0x070400fa, - 0xf9fe0102, 0x070500fb, 0xfafe0102, 0x070400fb, - 0xfafe0102, 0x060400fc, 0xfbfe0101, 0x060300fc, - 0xfcfaf7f6, 0x020302ff, 0xfdfbf7f6, 0x03040400, - 0xfffdf9f7, 0x03050502, 0x00fefbf9, 0x03050503, - 0x0100fdfa, 0x03050604, 0x0201fefc, 0x02040503, - 0x020100fe, 0x01030402, 0x020201ff, 0x01030302, - 0xfafbfbfc, 0xfbfafafa, 0xfcfcfdfd, 0xfcfcfcfc, - 0x00000000, 0xffffffff, 0x05060505, 0x02030405, - 0x07070605, 0x04050607, 0x04040303, 0x02030404, - 0x0000ff00, 0xff00ffff, 0xfcfcfdfd, 0xfdfdfcfc, - 0x01fbfe01, 0x00020405, 0x01fafd01, 0x00020506, - 0x00f9fc00, 0x01020606, 0xfff7fbff, 0x01030606, - 0xfef6faff, 0x01030606, 0xfef7faff, 0x01030605, - 0xfef7fafe, 0x01030505, 0xfef9fafe, 0x01020404, - 0xf7f8f9fb, 0xfaf9f8f7, 0xf9fafafb, 0xfbfafaf9, - 0xfcfdfdfd, 0xfcfcfbfb, 0xff0000ff, 0xffffffff, - 0x02020100, 0x01020202, 0x05040302, 0x04050505, - 0x06050403, 0x07080808, 0x06050403, 0x06070707, - 0x08070605, 0x090a0a09, 0x07060403, 0x08090908, - 0x03020100, 0x05050504, 0xfffffeff, 0x02020100, - 0xfdfdfdfe, 0x00fffefd, 0xfbfbfcfd, 0xfcfbfbfb, - 0xfafbfbfc, 0xfbfaf9f9, 0xfafbfcfd, 0xfafaf9f9, - 0xfd00070d, 0xfbfcfcfd, 0xfd00070e, 0xfcfcfcfd, - 0xfcff080f, 0xfcfbfcfc, 0xfcff080f, 0xfdfcfbfc, - 0xfcff070f, 0xfcfbfbfb, 0xfcff070e, 0xfdfcfcfc, - 0xfcff060c, 0xfdfcfcfc, 0xfcff050b, 0xfdfcfcfc, - 0x0405fcef, 0x03030404, 0x0405fbee, 0x03030404, - 0x0406fbed, 0x02030404, 0x0406fbec, 0x03030404, - 0x0406fcec, 0x03030504, 0x0406fbed, 0x03030504, - 0x0405fcee, 0x02030404, 0x0304fbef, 0x03030404, - 0xfcfafafa, 0x0b0601fe, 0xfcf9f9fa, 0x0d0802fe, - 0xfcf9f8f8, 0x0e0903fe, 0xfbf9f8f8, 0x100a04ff, - 0xfbf9f8f8, 0x110a04ff, 0xfcf9f8f8, 0x100a0500, - 0xfdfaf8f8, 0x0f090400, 0xfdfbf9f9, 0x0c080400, - 0x05070708, 0xf2f8fe02, 0x05070808, 0xf1f8fe02, - 0x05070808, 0xf0f7fd01, 0x05070808, 0xeff6fd01, - 0x05080908, 0xeff6fd01, 0x04070808, 0xf0f6fc01, - 0x04070707, 0xf2f7fd01, 0x03060706, 0xf3f7fd00, - 0xfcfc0105, 0x0000fffd, 0xfdfd0207, 0x0001fffe, - 0xfdfd0107, 0x010100ff, 0xfefd0106, 0x000101ff, - 0xfefc0006, 0x000100ff, 0xfdfc0005, 0xff0000ff, - 0xfffd0005, 0xfe000000, 0xfffe0104, 0xff000100, - 0x01010202, 0xf8f8fafe, 0x01010101, 0xf8f8fbfe, - 0x00010101, 0xfbfbfdff, 0x00000000, 0xfeffffff, - 0x0000ff00, 0x00010000, 0x00000001, 0x02030201, - 0x01010102, 0x03040302, 0x03030303, 0x04050404, - 0xfefdfcfc, 0x01010000, 0xfefdfcfc, 0x010000ff, - 0xfffefefe, 0x0000ffff, 0x00000100, 0xff000000, - 0x02020202, 0x01010202, 0x04040403, 0x03040404, - 0x03010101, 0x03030403, 0xfcfbfafb, 0xfefefdfd, - 0xfffffefc, 0x0100ffff, 0xfffffefc, 0x0100ffff, - 0xfffffefd, 0x020100ff, 0xfffefdfc, 0x030301ff, - 0xfffdfdfc, 0x050401ff, 0xfefefdfc, 0x070401ff, - 0xfffffefe, 0x08060200, 0x010000ff, 0x08070401, - 0xfefdfdfd, 0x00fffffe, 0x0100ffff, 0x03030202, - 0x04020100, 0x05060605, 0x030200ff, 0x03050605, - 0x0200ffff, 0x01020303, 0x00fffefe, 0xfcfcfdff, - 0xffff0000, 0xf9f8fcfe, 0x00010201, 0xf9fafcff, - 0xfa0104fe, 0x00000300, 0xf90105fe, 0x00000300, - 0xf80105fd, 0xffff0300, 0xf70106fe, 0xff000300, - 0xf80206fe, 0xff000400, 0xf90105fd, 0x00000401, - 0xf90104fe, 0x00010400, 0xfa0104ff, 0x00010300, - 0x03000000, 0x01040504, 0x02010101, 0x00020303, - 0x02010202, 0xfeff0102, 0x01010304, 0xfbfdff00, - 0xff010305, 0xfafcfdfe, 0xfe000305, 0xf9fafbfd, - 0xfe000304, 0xfbfbfcfd, 0xff000304, 0xfdfdfefe, - 0x00000000, 0x06fefbff, 0x01000000, 0x08fefaff, - 0x02000000, 0x09fdfa00, 0x0200ff00, 0x0afef900, - 0x0200ff00, 0x0afdf8ff, 0x02ffff00, 0x09fdf9ff, - 0x0100ff00, 0x08fdfaff, 0x01000000, 0x07fefb00, - 0x02030302, 0xffff0001, 0x02030403, 0xfeff0001, - 0x02040403, 0xfdfeff01, 0x02030302, 0xfdfeff00, - 0x010100ff, 0xfefeff00, 0xfffdfcfb, 0x01010100, - 0xfffbf8f8, 0x03040301, 0x00fbf7f6, 0x05060503, - 0x0504fffb, 0x00000103, 0x0504fffa, 0xfeff0002, - 0x0405fffa, 0xfefeff02, 0x0404fff9, 0xfdfdfe01, - 0x0405fffa, 0xfdfdfe01, 0x040400fb, 0xfefeff01, - 0x040500fc, 0xfeffff01, 0x030401fd, 0xfeffff01, - 0x01fefdfe, 0x03050604, 0x00fcfcfd, 0x02040503, - 0xfffbfbfd, 0x01030402, 0xfffcfafc, 0xff020402, - 0x01fdfcfe, 0xff020402, 0x01fefcfe, 0xfe010303, - 0x01fefdfe, 0xfe010303, 0x01fffefe, 0xfe000303, - 0xfefdfcfc, 0x070502ff, 0xfdfdfcfc, 0x070501fe, - 0xfdfefdfe, 0x0503fffd, 0xfe00ffff, 0x0402fefd, - 0xff010101, 0x0301fdfc, 0xff020304, 0x01fffdfc, - 0x00030406, 0x00fefdfd, 0x01030506, 0xfffefdfe, - 0x04080b0c, 0xfffefe00, 0x0206090a, 0x00fffeff, - 0x00020304, 0x0100ffff, 0xffffffff, 0x020100fe, - 0xfefcfbfd, 0x030200fe, 0xfefcfbfb, 0x020100ff, - 0xfefcfbfb, 0x010100ff, 0xfefdfcfc, 0x0000fffe, - 0xff020303, 0xfefdfcfd, 0xfe000203, 0xfefdfcfc, - 0xff010202, 0xfdfcfbfd, 0x01030303, 0xfdfdfdfe, - 0x03040404, 0xfefefe00, 0x03050505, 0xfefeff00, - 0x02040505, 0xfefdfeff, 0x00030303, 0xfcfcfcfe, - 0xfe04ffff, 0xfb0206fe, 0xfe0400ff, 0xfa0206fd, - 0xfe0400ff, 0xf90307fd, 0xfd04ffff, 0xf90308fc, - 0xfd04ff00, 0xfa0307fc, 0xfd04ffff, 0xfa0307fc, - 0xfd03ffff, 0xfa0306fc, 0xfe0300ff, 0xfb0306fd, - 0x02f9fe01, 0x01fffe05, 0x03f8fe01, 0x02fffd06, - 0x04f7fe02, 0x02fefc07, 0x05f7ff03, 0x03fffc07, - 0x04f7ff03, 0x02fefc07, 0x04f9ff03, 0x01fefc06, - 0x04fa0002, 0x01fffc06, 0x03fb0002, 0x01fffd04, - 0x000202fe, 0xfcfdff00, 0x010202fe, 0xfcfe0001, - 0x020202fe, 0xfeff0102, 0x030302fd, 0xfe000204, - 0x020302fd, 0xfd000204, 0x010201fc, 0xfdff0102, - 0x000100fb, 0xfdfe0101, 0x000000fc, 0xfdfe0001, - 0xfeff0000, 0x080702fe, 0xfdff0000, 0x070601fe, - 0xfdff0100, 0x050400fd, 0xff000100, 0x030100ff, - 0x01010200, 0x0100ff00, 0x020100fe, 0xffff0001, - 0x0100fefb, 0xfdfd0001, 0x01fffcfa, 0xfcfdff01, - 0x0502fefc, 0x02030406, 0x0401fdfb, 0x00000204, - 0x0200fefc, 0xfefeff01, 0x0100fffe, 0xfefdfe00, - 0x000000fe, 0xfffeffff, 0x00fffffe, 0x02010000, - 0xfffffefe, 0x04030100, 0xfffefdfe, 0x05040200, - 0xfefe0102, 0x000100ff, 0xfdfd0001, 0x000100ff, - 0xfdfdff00, 0x010101ff, 0xfffd0000, 0x03030201, - 0xfffdff00, 0x03030301, 0xfefcfefe, 0x04040301, - 0xfefcfdfd, 0x04030301, 0xfefbfdfe, 0x03030201, - 0x04030504, 0x05040404, 0x00010303, 0x01000000, - 0xfeff0101, 0xfefdfcfd, 0xfe000202, 0xfefdfcfe, - 0xff010302, 0xfefdfdff, 0x00000201, 0xfffefeff, - 0xff000100, 0xfffefdff, 0xff000101, 0xfefefeff, - 0x00fffffe, 0x00010201, 0x05030201, 0x03050506, - 0x04030201, 0x03040505, 0xfdfdfefe, 0x0000fffe, - 0xfbfcfdfd, 0xfffefdfc, 0xfefeffff, 0x0000fffe, - 0xff000100, 0x010000ff, 0xfeff00ff, 0xfffefefd, - 0x05060707, 0xfeff0204, 0x02020303, 0xfdfe0001, - 0xffffff00, 0xfefeff00, 0xfffefdff, 0x01000000, - 0xfffefe00, 0x020201ff, 0xffff0103, 0x020201ff, - 0xfdfe0103, 0x0201fffe, 0xfafbfe01, 0x00fefdfb, - 0xfdfeff00, 0xfefe00ff, 0xffff0000, 0xfeff0100, - 0xfffe0000, 0xfe000000, 0xfdfdfeff, 0xfdfdfffe, - 0xfdfdfeff, 0xfcfdfefe, 0x00000202, 0xfeff0000, - 0x02030505, 0xff000202, 0x05060808, 0x01020404, - 0xfdfaf8f9, 0xfffeffff, 0x00fdfbfb, 0x00000102, - 0x0300ffff, 0x01010304, 0x03010102, 0x02020304, - 0x02000203, 0x02010203, 0xffff0204, 0x01010100, - 0xfdfe0203, 0x0100fffe, 0xfcfd0103, 0x0100fefd, - 0x02fffefc, 0x00010303, 0xfefcfbf9, 0xfeff0000, - 0xfcfbfbfa, 0xfdfefefe, 0xffff00ff, 0xff000000, - 0x02020302, 0x00010202, 0x03040503, 0x00010001, - 0x02030403, 0xffffff00, 0x01030505, 0xffffff00, - 0xff000101, 0xfcfafbfd, 0x00000101, 0xfffdfd00, - 0x00ffff00, 0x03010001, 0xfffdfefe, 0x07040202, - 0x00fefefe, 0x06030202, 0x010000ff, 0x03000001, - 0x03030300, 0xfffdfe01, 0x03040301, 0xfcfbfd00, - 0xff000200, 0xfefefcfd, 0x00020401, 0xfffefdfe, - 0x01030603, 0xff00fefe, 0x01040704, 0x00fffdfe, - 0x00030603, 0x00fffdfd, 0xff000301, 0x0101fefd, - 0xfeff0100, 0x0202fffd, 0xfdfdfffe, 0x0201fffd, - 0x00ff0103, 0x00000001, 0xfffeff02, 0xffff0001, - 0x00feff01, 0xfdfe0001, 0x01fffe00, 0xfbfd0103, - 0x02fffe00, 0xfbfd0205, 0x04fffe00, 0xfbfe0306, - 0x0400fe00, 0xfcfe0407, 0x0400fe00, 0xfcfe0406, - 0xfcfdfefe, 0x00fffefd, 0xff000101, 0x0100ffff, - 0x02020303, 0x01010101, 0x02020202, 0x01000001, - 0x00000000, 0xffffffff, 0xfcfcfcfc, 0xfdfcfcfc, - 0xfdfefdfd, 0x00fffffe, 0x05040403, 0x07060605, - 0xfe07feff, 0x00fffffc, 0xff09feff, 0x00fffffc, - 0xff0afdff, 0x01fffffc, 0xfe0afdff, 0x02fffffd, - 0xfe0afeff, 0x02fffffc, 0xfe09feff, 0x02fffffc, - 0xfe08feff, 0x01ff00fc, 0xfe07fe00, 0x0200fffd, - 0x0301fc03, 0x0001fefd, 0x0401fb03, 0x0001fefd, - 0x0502fa03, 0x0003fffd, 0x0502fa03, 0x0002fffd, - 0x0501fa03, 0x0003fefc, 0x0501fa03, 0x0002fefd, - 0x0401fa02, 0x0001fffd, 0x0401fa02, 0x0001fffe, - 0x01010000, 0x02000001, 0x0101ff00, 0x02000001, - 0x0000ff00, 0x02000000, 0x0000ff00, 0x00ff0000, - 0x00010001, 0xfffeff00, 0x00010103, 0xfdfcfe00, - 0x01020305, 0xfcfbfd00, 0x00020405, 0xfbfbfcff, - 0xfeff0001, 0xf7fafdfe, 0xffff0002, 0xfafd0000, - 0xff000001, 0xfbfe0000, 0x01010102, 0xfdff0201, - 0x01020101, 0xff010202, 0x01020101, 0x01010101, - 0x01020000, 0x02020000, 0x02020100, 0x02020000, - 0x0100fdfc, 0x03040604, 0x0000fefd, 0x00010402, - 0x0000ffff, 0xfdfe0101, 0x00010101, 0xfbfd0101, - 0x00010101, 0xfbfd0101, 0xff0000ff, 0xfcfe0101, - 0xff0000ff, 0xfe000201, 0x000000ff, 0x00010302, - 0x040300ff, 0xfbfbfc00, 0x05040000, 0xfefdfe02, - 0x0402ff00, 0x00ffff02, 0x01fffe00, 0x0100fe00, - 0x00fefe01, 0x01ffff00, 0x00fdfe01, 0x00ff0001, - 0x01fefe01, 0x00000103, 0x02fffe01, 0x00000204, - 0x02030201, 0x01020200, 0x000100ff, 0x010101fd, - 0xfe0000ff, 0x010200fc, 0xff0202ff, 0x010200fb, - 0xff0403ff, 0x010200fb, 0x000402fe, 0x0000fffc, - 0x000200fc, 0x0000fefc, 0x0102fffb, 0x020301fe, - 0x00010001, 0xfeff0201, 0xfeff0002, 0xff000301, - 0xfcfe0003, 0x00010300, 0xfbfd0105, 0x010102fe, - 0xfbfe0106, 0x010001fe, 0xfbff0105, 0x00ff00fe, - 0xfcfe0003, 0x00ff00fe, 0xfe00ff01, 0x01000100, - 0x03020101, 0x02010102, 0x0100ffff, 0x01010001, - 0x0000fdfc, 0x02010101, 0x0200fdfc, 0x02030202, - 0x0100fcfb, 0x02010101, 0xfffffcfb, 0x00fffefe, - 0x0000fefd, 0xfffefdfe, 0x04040302, 0x00000002, - 0x0100fefc, 0x00000000, 0x0101fffd, 0x00000000, - 0x020200fe, 0x02000000, 0x010201ff, 0x050300ff, - 0xff010200, 0x060500fe, 0xfd000100, 0x060400fd, - 0xfcfe0101, 0x0201fdfc, 0xfcfe0001, 0x00fefcfb, - 0xfdfdfdff, 0xfffffefd, 0x00010203, 0x01010100, - 0x02030405, 0x02020101, 0xfe000102, 0xfffffefe, - 0xff000000, 0xfefefefe, 0x03030100, 0xffff0102, - 0x04030100, 0xff010203, 0x01fffdfc, 0xfdfdfe00, - 0xf8f9fcfd, 0x02fffcf9, 0xfcfdff00, 0x0200fefc, - 0xff000001, 0x0200fefd, 0x00010102, 0x0200ffff, - 0x01010101, 0x01000000, 0x01010101, 0x01010101, - 0x02010000, 0x02020303, 0x03010000, 0x02030404, - 0x00030303, 0x020100ff, 0xff010101, 0x01fffffe, - 0xfdfffefe, 0x00fefefd, 0xfefefcfc, 0x00fdfefe, - 0x01fffcfc, 0x02ff0001, 0x0302fffd, 0x05030304, - 0x030200fe, 0x03030303, 0x0000fefe, 0x01000000, - 0xff010200, 0xfe03fffd, 0xffff00ff, 0xfe0400fd, - 0xfefefefe, 0xfe0501fe, 0xfffdfefd, 0xfd0401fe, - 0x00ff00fe, 0xfb0300ff, 0x02010201, 0xfb020000, - 0x03020402, 0xfd030101, 0x01010201, 0xfe040100, - 0xfffcfd04, 0x03010303, 0xfffcfc04, 0x02000203, - 0x00fcfd04, 0x01ff0202, 0x01fefd04, 0x00fe0102, - 0x01fefc02, 0x00fd0002, 0x00fefd02, 0x02fe0001, - 0x00ffff03, 0x03000000, 0xfefefe02, 0x02ffffff, - 0x04030202, 0xff000103, 0x02010001, 0xfefeff01, - 0x01020102, 0xffff0001, 0x03040304, 0x01010102, - 0x02020203, 0x01010101, 0x00fffeff, 0xffffffff, - 0xfffefdfd, 0xfefefefe, 0xfdfdfcfc, 0xfdfdfcfc, - 0xfdff0102, 0x0403fefc, 0xff010202, 0x0201fefd, - 0x03030201, 0xfefffe00, 0x040200ff, 0xfdff0002, - 0x0300fefe, 0xfd000203, 0xfffdfe00, 0xff020201, - 0xfbfcff03, 0x000200fd, 0xfafe0306, 0x010300fb, - 0x00fe03fe, 0x01fefe03, 0x00fd04fd, 0x02fffe03, - 0x00fd05fd, 0x02fffe04, 0xfffc04fe, 0x02fefd03, - 0x00fd04fd, 0x02fffd03, 0x00fe05fe, 0x02fffd03, - 0x01fd04fe, 0x02fffe03, 0x01fe03fe, 0x0200fe03, - 0xff000001, 0xfffc0201, 0xff000002, 0xfefc0201, - 0xff010101, 0x00fe0402, 0xff01ff00, 0x01ff0502, - 0xfe00ff00, 0x01ff0501, 0xfeffff00, 0xfffd0300, - 0xfe000101, 0xfffd0300, 0xfd000101, 0x00fe0300, - 0x01ff0001, 0x05040201, 0x01ff0001, 0x07050101, - 0xfffe0000, 0x050300ff, 0xfffeff00, 0x0302ffff, - 0xfffdff00, 0x0201ffff, 0xfefcfeff, 0x0000fefe, - 0xfffefeff, 0x0000fefe, 0x00ffff00, 0x0000ffff, - 0xff000303, 0x040401ff, 0xfe000302, 0x010100fe, - 0xff010302, 0x000100ff, 0xff000201, 0xfe00ffff, - 0xff000100, 0xfe00fffe, 0xff000100, 0x0001fffe, - 0xfdff0101, 0x0301fdfc, 0xfdff0201, 0x0301fcfb, - 0x0100fefd, 0xfe000101, 0x01010100, 0xfdff0000, - 0x01010201, 0xfeffff00, 0xfffdff00, 0xff00ffff, - 0xfdfafd00, 0x0101fffe, 0xfdfcff02, 0x020200fe, - 0x01010405, 0x02030100, 0x01020405, 0x0100ff00, - 0xfbfe00fe, 0x0000fdfa, 0x000100fe, 0x020201ff, - 0x030100fe, 0x01020202, 0x040200fe, 0x01010203, - 0x030200fe, 0x00ff0002, 0x0101fffd, 0x01ffff00, - 0x0001fffc, 0x0200feff, 0xff00fffc, 0x0401feff, - 0xff0000fd, 0x00010101, 0xff0001fd, 0xffff0000, - 0x000303ff, 0x01000001, 0xfe0202fd, 0x010000ff, - 0xfe0000fb, 0x020001ff, 0x0001fef9, 0x02020201, - 0x020300fb, 0x02020303, 0x010402fd, 0xfdfe0000, - 0xfefe0205, 0xffffff00, 0xfdfcff02, 0xfffffeff, - 0x01fefe00, 0x0100ff02, 0x03fffeff, 0x0200ff03, - 0x03000001, 0x02fffe03, 0x03010102, 0x00fefe02, - 0x01ff0001, 0xfefdfd01, 0x02010001, 0x00000003, - 0x00fdfbfc, 0xfffeff01, 0x01fffdfe, 0x00000002, - 0x01020101, 0x01010102, 0x01030403, 0xfffffe00, - 0x00020303, 0xfefdfdfe, 0xff000101, 0xfefefcfe, - 0x00000102, 0x0100ff00, 0x01010102, 0x03010101, - 0xff000000, 0x0001fffe, 0xfefffffe, 0x0000fefd, - 0xff0000ff, 0x010100fe, 0xff000101, 0x010301ff, - 0xfe000202, 0x000302ff, 0xffff0103, 0xfe020401, - 0xfffd0002, 0xfb000503, 0x00feff01, 0xfaff0303, - 0x040300ff, 0x02010002, 0x0100fffe, 0x0100feff, - 0xfdfefdfe, 0xfdfaf9fa, 0x01030202, 0xfefdfeff, - 0x01030202, 0x00000000, 0x00010102, 0x01000101, - 0x00000001, 0x02010100, 0x00ff0001, 0x01020200, - 0x01030101, 0x01ffffff, 0x0000fffe, 0x02fffefe, - 0x0101fefe, 0x03010001, 0xff00fefe, 0x0200ff00, - 0x00010000, 0x01feffff, 0x01020203, 0x01fefe00, - 0x02030305, 0x04010101, 0xfbfcfd00, 0x01fffdfc, - 0x02fffcfa, 0xff000002, 0x0301fefc, 0x00020203, - 0x02fffefd, 0x00020303, 0x01fefefd, 0xff010102, - 0x00fefefe, 0xff010202, 0x01ffffff, 0x00020302, - 0x01feffff, 0xff020202, 0x00feff00, 0xff000102, - 0x01020406, 0x01000000, 0xfeff0204, 0xfffffefe, - 0xfeff0102, 0xfffefefe, 0xfe000202, 0x00fffefe, - 0xfeff0000, 0x0100fffe, 0xfffefdfd, 0x00fffeff, - 0x0302fefd, 0xfeff0002, 0x050400fe, 0xff000205, - 0x00020405, 0xfffffeff, 0x01020304, 0xff00ff00, - 0x01000101, 0xff010001, 0x00fffffe, 0xfdfefe00, - 0x000000ff, 0xfbfdfdff, 0xff010100, 0xfdfefeff, - 0xfeffffff, 0x010301ff, 0xfffefeff, 0x05060502, - 0x01fefdfd, 0xfffffe01, 0x04030201, 0xfdfffd01, - 0x01000203, 0xfdfffdff, 0x00ff0001, 0x0001ffff, - 0x01000101, 0x03050202, 0x02010101, 0x00030202, - 0xfefefffd, 0xfdfffdfd, 0x000101ff, 0xfe00ffff, - 0xfefe0002, 0xfe010402, 0xfffe0001, 0xff020503, - 0xfefdfeff, 0xfe010301, 0xfffffeff, 0xff010200, - 0x01010000, 0x00020201, 0x04040100, 0x01030202, - 0x0102fffe, 0xfdfefdfe, 0x000100ff, 0xfbfcfcfd, - 0xfcfd0004, 0xfffefcfc, 0x00ff0005, 0xfffefdff, - 0x01000004, 0x00000001, 0xfffefd00, 0x00010000, - 0x0000fe00, 0x01020101, 0x00000002, 0x00010101, - 0xffff0002, 0x00010101, 0xfefeff01, 0x02020200, - 0x00fefbfd, 0x00fdfdff, 0x0200fe00, 0x03000002, - 0x00feff02, 0x02ffff00, 0xffff0205, 0x02ffffff, - 0xff000205, 0x02ff00ff, 0x00000102, 0x02000100, - 0x0101ffff, 0x02010202, 0x0000fefd, 0xfffe0000, - 0x00020300, 0xfdfdfdfe, 0x01030300, 0x02010000, - 0xfeff00ff, 0x0301ffff, 0xfeff00ff, 0x0200ffff, - 0xfeff00ff, 0x02ff0000, 0xfeff00ff, 0x01feffff, - 0xfd000100, 0x02ffffff, 0xff020505, 0x0301ffff, - 0xff010000, 0x0200fefd, 0x00030101, 0x0100fefe, - 0x01030101, 0xffff0000, 0x0102ff00, 0xfdff0001, - 0x0101feff, 0xfcfe0001, 0x010200ff, 0xfdff0001, - 0x02030101, 0xfdfe0001, 0x02040202, 0xfcfeff01, - 0x02020201, 0x0200fe00, 0xfdfeffff, 0x01fdfbfc, - 0x00010100, 0x01ffffff, 0x01010100, 0x02000000, - 0x02010100, 0x02010101, 0x0200ffff, 0x03020202, - 0xfffcfcfe, 0x00fefefe, 0x01000001, 0x01000000, - 0xfefdff00, 0x01020200, 0xfdfeff00, 0x02010100, - 0xfdfe0001, 0x010000ff, 0xfeff00ff, 0x00ff0000, - 0x000101ff, 0x00000202, 0x01030200, 0x02030503, - 0xfe0101ff, 0x01010300, 0xfc0000ff, 0xfffffffc, - 0x000101ff, 0x02010201, 0x000100fd, 0x02000101, - 0xfffffdfb, 0x01000100, 0xfdfefdfc, 0x00fffffe, - 0xfeff0000, 0x00fefefe, 0x00020403, 0x01000000, - 0x00000102, 0x00ff0000, 0x03020100, 0x02030404, - 0x040704ff, 0x00000000, 0x030604ff, 0x01010100, - 0x00040300, 0x010000ff, 0xfe010100, 0xffff00ff, - 0xffff00ff, 0x000000ff, 0x00ffffff, 0x00000000, - 0x00fdfdff, 0xfffeff01, 0xfefcfcfd, 0xfffefeff, - 0x00010202, 0xfd000101, 0x0000fffe, 0xfd000101, - 0x0100fffe, 0xfe010102, 0x02020201, 0xff020303, - 0x00010201, 0xff020101, 0xfcfe0100, 0xff0100fe, - 0xfdff0101, 0xfdff00fe, 0xff000201, 0xfcff0100, - 0xfefeffff, 0x03040300, 0xfdff0101, 0x000000fe, - 0x02020202, 0xffff0102, 0x03010101, 0xfefe0003, - 0xffffff00, 0xfffffe00, 0xfdfcfdff, 0x0200fefe, - 0x0100ffff, 0x05030202, 0x00fffffe, 0x01000000, - 0x0002fdfe, 0xff010100, 0xfe01fcff, 0x000202ff, - 0xfe00fc01, 0xff0101fe, 0xff01fd02, 0xff0101ff, - 0x0103fe03, 0xff010100, 0x0102fd01, 0xff000100, - 0x0001fbff, 0x010100ff, 0x0303fd00, 0x03030201, - 0x01feff00, 0xff020505, 0xfffeff01, 0xfbfe0101, - 0xfeff0101, 0xfdffffff, 0xffff0101, 0x030402ff, - 0xffffffff, 0x030400ff, 0x0100ffff, 0xfffffdff, - 0x02000000, 0xff000002, 0x00fdfe00, 0x02030101, - 0x01020302, 0xfefe0000, 0x01000302, 0x02030301, - 0xfffd0000, 0x030202ff, 0x01fdfefe, 0x01010201, - 0x02fefffe, 0xfeff0101, 0x02000100, 0xfefe0000, - 0x02000100, 0xfefe0000, 0x00fefefd, 0xfdfefeff, - 0x03ff0100, 0xff0301ff, 0x03ff0100, 0xfd02ffff, - 0x03fe0101, 0xfd00fdff, 0x03fe0202, 0xfe01fe00, - 0x03fd0101, 0xfd01feff, 0x03fd0101, 0xfe01ff00, - 0x04ff0201, 0xfe01ff00, 0x03ff0100, 0xfd00fdff, - 0x01fffdfd, 0xfeff0102, 0x0200fefe, 0xfefe0001, - 0x0201fefd, 0xfffeff01, 0x0402fefd, 0x01fefe00, - 0x0402fffd, 0x02fefe00, 0x030401ff, 0x02fefdff, - 0x02040200, 0x02fffeff, 0x00020100, 0x030100ff, - 0x01fb0003, 0x01000004, 0x02fbfe01, 0x01feff05, - 0x030000ff, 0xff000103, 0xfe0403fe, 0xfe00fffd, - 0xfd0503fd, 0xfe0000fd, 0xfe0203ff, 0xff0202fe, - 0xff000002, 0x00000000, 0x01fefd00, 0xfefe0003 +static const int8 s_svq1InterCodebook8x8[6144] = { + -4, -3, 4, 5, 2, 1, 1, 0, -5, -3, 5, 5, 2, 1, 0, 0, + -6, -4, 5, 5, 2, 1, 0, 0, -7, -4, 4, 5, 2, 1, 0, 0, + -8, -5, 3, 4, 2, 1, 0, 0, -8, -6, 3, 4, 1, 1, 1, 0, + -8, -6, 2, 4, 2, 1, 1, 0, -8, -6, 2, 4, 1, 1, 1, 1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, + -2, -3, -3, -3, -3, -3, -3, -3, -2, -3, -3, -3, -3, -3, -4, -3, + -2, -2, -2, -2, -2, -3, -3, -2, 1, 1, 1, 1, 1, 0, -1, -1, + 4, 5, 5, 5, 4, 3, 3, 2, 7, 7, 8, 8, 8, 7, 6, 5, + 2, 1, 2, 4, 4, 0, -4, -6, 1, 1, 2, 5, 5, 1, -5, -7, + 1, 2, 1, 4, 5, 1, -5, -8, 1, 1, 1, 5, 5, 0, -6, -8, + 0, 1, 1, 5, 6, 1, -6, -9, 0, 0, 1, 4, 5, 0, -5, -8, + 0, 0, 1, 4, 5, 0, -5, -7, 0, 0, 1, 4, 4, 1, -4, -7, + 1, 2, 3, 0, -3, -4, -3, -1, 1, 3, 4, 0, -3, -4, -3, -1, + 2, 4, 5, 1, -3, -4, -3, -2, 2, 5, 6, 1, -3, -5, -4, -2, + 3, 6, 6, 1, -3, -5, -4, -2, 3, 6, 6, 1, -3, -5, -4, -2, + 3, 6, 6, 1, -3, -5, -4, -2, 3, 5, 5, 1, -3, -4, -4, -2, + 2, 2, 2, 2, 1, 0, 0, -1, 4, 4, 4, 3, 2, 1, 1, 0, + 4, 5, 4, 4, 3, 3, 2, 1, 4, 4, 4, 4, 4, 3, 2, 2, + 2, 3, 3, 3, 3, 3, 2, 1, -1, -1, -1, -1, 0, 0, 0, 0, + -5, -6, -6, -5, -5, -4, -3, -3, -7, -9, -9, -8, -7, -6, -6, -5, + 6, 6, 6, 6, 6, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, + 0, -1, -1, -1, -2, -2, -1, -1, -3, -5, -6, -6, -6, -6, -5, -4, + -3, -5, -6, -7, -6, -6, -5, -4, -1, -2, -2, -2, -2, -2, -1, -1, + 0, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 1, -2, -5, -4, 0, 2, 5, 2, 1, -2, -6, -5, 0, 3, 5, + 2, 1, -2, -6, -6, -1, 3, 6, 3, 2, -2, -7, -6, 0, 4, 7, + 2, 1, -2, -7, -5, 0, 5, 7, 2, 1, -2, -6, -5, 0, 4, 7, + 2, 1, -2, -6, -4, 0, 4, 6, 1, 1, -2, -5, -4, 0, 3, 6, + -10, -9, -6, -4, -1, 2, 3, 2,-10, -9, -5, -3, 0, 4, 4, 3, + -9, -7, -3, -1, 2, 5, 5, 3, -7, -5, -2, 0, 3, 5, 5, 3, + -6, -3, 0, 1, 4, 6, 5, 3, -4, -2, 1, 2, 3, 5, 4, 2, + -2, 0, 1, 2, 2, 4, 3, 1, -1, 1, 2, 2, 2, 3, 3, 1, + -4, -5, -5, -6, -6, -6, -6, -5, -3, -3, -4, -4, -4, -4, -4, -4, + 0, 0, 0, 0, -1, -1, -1, -1, 5, 5, 6, 5, 5, 4, 3, 2, + 5, 6, 7, 7, 7, 6, 5, 4, 3, 3, 4, 4, 4, 4, 3, 2, + 0, -1, 0, 0, -1, -1, 0, -1, -3, -3, -4, -4, -4, -4, -3, -3, + 1, -2, -5, 1, 5, 4, 2, 0, 1, -3, -6, 1, 6, 5, 2, 0, + 0, -4, -7, 0, 6, 6, 2, 1, -1, -5, -9, -1, 6, 6, 3, 1, + -1, -6,-10, -2, 6, 6, 3, 1, -1, -6, -9, -2, 5, 6, 3, 1, + -2, -6, -9, -2, 5, 5, 3, 1, -2, -6, -7, -2, 4, 4, 2, 1, + -5, -7, -8, -9, -9, -8, -7, -6, -5, -6, -6, -7, -7, -6, -6, -5, + -3, -3, -3, -4, -5, -5, -4, -4, -1, 0, 0, -1, -1, -1, -1, -1, + 0, 1, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 5, 5, 5, 4, + 3, 4, 5, 6, 8, 8, 8, 7, 3, 4, 5, 6, 7, 7, 7, 6, + 5, 6, 7, 8, 9, 10, 10, 9, 3, 4, 6, 7, 8, 9, 9, 8, + 0, 1, 2, 3, 4, 5, 5, 5, -1, -2, -1, -1, 0, 1, 2, 2, + -2, -3, -3, -3, -3, -2, -1, 0, -3, -4, -5, -5, -5, -5, -5, -4, + -4, -5, -5, -6, -7, -7, -6, -5, -3, -4, -5, -6, -7, -7, -6, -6, + 13, 7, 0, -3, -3, -4, -4, -5, 14, 7, 0, -3, -3, -4, -4, -4, + 15, 8, -1, -4, -4, -4, -5, -4, 15, 8, -1, -4, -4, -5, -4, -3, + 15, 7, -1, -4, -5, -5, -5, -4, 14, 7, -1, -4, -4, -4, -4, -3, + 12, 6, -1, -4, -4, -4, -4, -3, 11, 5, -1, -4, -4, -4, -4, -3, + -17, -4, 5, 4, 4, 4, 3, 3,-18, -5, 5, 4, 4, 4, 3, 3, + -19, -5, 6, 4, 4, 4, 3, 2,-20, -5, 6, 4, 4, 4, 3, 3, + -20, -4, 6, 4, 4, 5, 3, 3,-19, -5, 6, 4, 4, 5, 3, 3, + -18, -4, 5, 4, 4, 4, 3, 2,-17, -5, 4, 3, 4, 4, 3, 3, + -6, -6, -6, -4, -2, 1, 6, 11, -6, -7, -7, -4, -2, 2, 8, 13, + -8, -8, -7, -4, -2, 3, 9, 14, -8, -8, -7, -5, -1, 4, 10, 16, + -8, -8, -7, -5, -1, 4, 10, 17, -8, -8, -7, -4, 0, 5, 10, 16, + -8, -8, -6, -3, 0, 4, 9, 15, -7, -7, -5, -3, 0, 4, 8, 12, + 8, 7, 7, 5, 2, -2, -8,-14, 8, 8, 7, 5, 2, -2, -8,-15, + 8, 8, 7, 5, 1, -3, -9,-16, 8, 8, 7, 5, 1, -3,-10,-17, + 8, 9, 8, 5, 1, -3,-10,-17, 8, 8, 7, 4, 1, -4,-10,-16, + 7, 7, 7, 4, 1, -3, -9,-14, 6, 7, 6, 3, 0, -3, -9,-13, + 5, 1, -4, -4, -3, -1, 0, 0, 7, 2, -3, -3, -2, -1, 1, 0, + 7, 1, -3, -3, -1, 0, 1, 1, 6, 1, -3, -2, -1, 1, 1, 0, + 6, 0, -4, -2, -1, 0, 1, 0, 5, 0, -4, -3, -1, 0, 0, -1, + 5, 0, -3, -1, 0, 0, 0, -2, 4, 1, -2, -1, 0, 1, 0, -1, + 2, 2, 1, 1, -2, -6, -8, -8, 1, 1, 1, 1, -2, -5, -8, -8, + 1, 1, 1, 0, -1, -3, -5, -5, 0, 0, 0, 0, -1, -1, -1, -2, + 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 2, 3, 2, + 2, 1, 1, 1, 2, 3, 4, 3, 3, 3, 3, 3, 4, 4, 5, 4, + -4, -4, -3, -2, 0, 0, 1, 1, -4, -4, -3, -2, -1, 0, 0, 1, + -2, -2, -2, -1, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, + 2, 2, 2, 2, 2, 2, 1, 1, 3, 4, 4, 4, 4, 4, 4, 3, + 1, 1, 1, 3, 3, 4, 3, 3, -5, -6, -5, -4, -3, -3, -2, -2, + -4, -2, -1, -1, -1, -1, 0, 1, -4, -2, -1, -1, -1, -1, 0, 1, + -3, -2, -1, -1, -1, 0, 1, 2, -4, -3, -2, -1, -1, 1, 3, 3, + -4, -3, -3, -1, -1, 1, 4, 5, -4, -3, -2, -2, -1, 1, 4, 7, + -2, -2, -1, -1, 0, 2, 6, 8, -1, 0, 0, 1, 1, 4, 7, 8, + -3, -3, -3, -2, -2, -1, -1, 0, -1, -1, 0, 1, 2, 2, 3, 3, + 0, 1, 2, 4, 5, 6, 6, 5, -1, 0, 2, 3, 5, 6, 5, 3, + -1, -1, 0, 2, 3, 3, 2, 1, -2, -2, -1, 0, -1, -3, -4, -4, + 0, 0, -1, -1, -2, -4, -8, -7, 1, 2, 1, 0, -1, -4, -6, -7, + -2, 4, 1, -6, 0, 3, 0, 0, -2, 5, 1, -7, 0, 3, 0, 0, + -3, 5, 1, -8, 0, 3, -1, -1, -2, 6, 1, -9, 0, 3, 0, -1, + -2, 6, 2, -8, 0, 4, 0, -1, -3, 5, 1, -7, 1, 4, 0, 0, + -2, 4, 1, -7, 0, 4, 1, 0, -1, 4, 1, -6, 0, 3, 1, 0, + 0, 0, 0, 3, 4, 5, 4, 1, 1, 1, 1, 2, 3, 3, 2, 0, + 2, 2, 1, 2, 2, 1, -1, -2, 4, 3, 1, 1, 0, -1, -3, -5, + 5, 3, 1, -1, -2, -3, -4, -6, 5, 3, 0, -2, -3, -5, -6, -7, + 4, 3, 0, -2, -3, -4, -5, -5, 4, 3, 0, -1, -2, -2, -3, -3, + 0, 0, 0, 0, -1, -5, -2, 6, 0, 0, 0, 1, -1, -6, -2, 8, + 0, 0, 0, 2, 0, -6, -3, 9, 0, -1, 0, 2, 0, -7, -2, 10, + 0, -1, 0, 2, -1, -8, -3, 10, 0, -1, -1, 2, -1, -7, -3, 9, + 0, -1, 0, 1, -1, -6, -3, 8, 0, 0, 0, 1, 0, -5, -2, 7, + 2, 3, 3, 2, 1, 0, -1, -1, 3, 4, 3, 2, 1, 0, -1, -2, + 3, 4, 4, 2, 1, -1, -2, -3, 2, 3, 3, 2, 0, -1, -2, -3, + -1, 0, 1, 1, 0, -1, -2, -2, -5, -4, -3, -1, 0, 1, 1, 1, + -8, -8, -5, -1, 1, 3, 4, 3,-10, -9, -5, 0, 3, 5, 6, 5, + -5, -1, 4, 5, 3, 1, 0, 0, -6, -1, 4, 5, 2, 0, -1, -2, + -6, -1, 5, 4, 2, -1, -2, -2, -7, -1, 4, 4, 1, -2, -3, -3, + -6, -1, 5, 4, 1, -2, -3, -3, -5, 0, 4, 4, 1, -1, -2, -2, + -4, 0, 5, 4, 1, -1, -1, -2, -3, 1, 4, 3, 1, -1, -1, -2, + -2, -3, -2, 1, 4, 6, 5, 3, -3, -4, -4, 0, 3, 5, 4, 2, + -3, -5, -5, -1, 2, 4, 3, 1, -4, -6, -4, -1, 2, 4, 2, -1, + -2, -4, -3, 1, 2, 4, 2, -1, -2, -4, -2, 1, 3, 3, 1, -2, + -2, -3, -2, 1, 3, 3, 1, -2, -2, -2, -1, 1, 3, 3, 0, -2, + -4, -4, -3, -2, -1, 2, 5, 7, -4, -4, -3, -3, -2, 1, 5, 7, + -2, -3, -2, -3, -3, -1, 3, 5, -1, -1, 0, -2, -3, -2, 2, 4, + 1, 1, 1, -1, -4, -3, 1, 3, 4, 3, 2, -1, -4, -3, -1, 1, + 6, 4, 3, 0, -3, -3, -2, 0, 6, 5, 3, 1, -2, -3, -2, -1, + 12, 11, 8, 4, 0, -2, -2, -1, 10, 9, 6, 2, -1, -2, -1, 0, + 4, 3, 2, 0, -1, -1, 0, 1, -1, -1, -1, -1, -2, 0, 1, 2, + -3, -5, -4, -2, -2, 0, 2, 3, -5, -5, -4, -2, -1, 0, 1, 2, + -5, -5, -4, -2, -1, 0, 1, 1, -4, -4, -3, -2, -2, -1, 0, 0, + 3, 3, 2, -1, -3, -4, -3, -2, 3, 2, 0, -2, -4, -4, -3, -2, + 2, 2, 1, -1, -3, -5, -4, -3, 3, 3, 3, 1, -2, -3, -3, -3, + 4, 4, 4, 3, 0, -2, -2, -2, 5, 5, 5, 3, 0, -1, -2, -2, + 5, 5, 4, 2, -1, -2, -3, -2, 3, 3, 3, 0, -2, -4, -4, -4, + -1, -1, 4, -2, -2, 6, 2, -5, -1, 0, 4, -2, -3, 6, 2, -6, + -1, 0, 4, -2, -3, 7, 3, -7, -1, -1, 4, -3, -4, 8, 3, -7, + 0, -1, 4, -3, -4, 7, 3, -6, -1, -1, 4, -3, -4, 7, 3, -6, + -1, -1, 3, -3, -4, 6, 3, -6, -1, 0, 3, -2, -3, 6, 3, -5, + 1, -2, -7, 2, 5, -2, -1, 1, 1, -2, -8, 3, 6, -3, -1, 2, + 2, -2, -9, 4, 7, -4, -2, 2, 3, -1, -9, 5, 7, -4, -1, 3, + 3, -1, -9, 4, 7, -4, -2, 2, 3, -1, -7, 4, 6, -4, -2, 1, + 2, 0, -6, 4, 6, -4, -1, 1, 2, 0, -5, 3, 4, -3, -1, 1, + -2, 2, 2, 0, 0, -1, -3, -4, -2, 2, 2, 1, 1, 0, -2, -4, + -2, 2, 2, 2, 2, 1, -1, -2, -3, 2, 3, 3, 4, 2, 0, -2, + -3, 2, 3, 2, 4, 2, 0, -3, -4, 1, 2, 1, 2, 1, -1, -3, + -5, 0, 1, 0, 1, 1, -2, -3, -4, 0, 0, 0, 1, 0, -2, -3, + 0, 0, -1, -2, -2, 2, 7, 8, 0, 0, -1, -3, -2, 1, 6, 7, + 0, 1, -1, -3, -3, 0, 4, 5, 0, 1, 0, -1, -1, 0, 1, 3, + 0, 2, 1, 1, 0, -1, 0, 1, -2, 0, 1, 2, 1, 0, -1, -1, + -5, -2, 0, 1, 1, 0, -3, -3, -6, -4, -1, 1, 1, -1, -3, -4, + -4, -2, 2, 5, 6, 4, 3, 2, -5, -3, 1, 4, 4, 2, 0, 0, + -4, -2, 0, 2, 1, -1, -2, -2, -2, -1, 0, 1, 0, -2, -3, -2, + -2, 0, 0, 0, -1, -1, -2, -1, -2, -1, -1, 0, 0, 0, 1, 2, + -2, -2, -1, -1, 0, 1, 3, 4, -2, -3, -2, -1, 0, 2, 4, 5, + 2, 1, -2, -2, -1, 0, 1, 0, 1, 0, -3, -3, -1, 0, 1, 0, + 0, -1, -3, -3, -1, 1, 1, 1, 0, 0, -3, -1, 1, 2, 3, 3, + 0, -1, -3, -1, 1, 3, 3, 3, -2, -2, -4, -2, 1, 3, 4, 4, + -3, -3, -4, -2, 1, 3, 3, 4, -2, -3, -5, -2, 1, 2, 3, 3, + 4, 5, 3, 4, 4, 4, 4, 5, 3, 3, 1, 0, 0, 0, 0, 1, + 1, 1, -1, -2, -3, -4, -3, -2, 2, 2, 0, -2, -2, -4, -3, -2, + 2, 3, 1, -1, -1, -3, -3, -2, 1, 2, 0, 0, -1, -2, -2, -1, + 0, 1, 0, -1, -1, -3, -2, -1, 1, 1, 0, -1, -1, -2, -2, -2, + -2, -1, -1, 0, 1, 2, 1, 0, 1, 2, 3, 5, 6, 5, 5, 3, + 1, 2, 3, 4, 5, 5, 4, 3, -2, -2, -3, -3, -2, -1, 0, 0, + -3, -3, -4, -5, -4, -3, -2, -1, -1, -1, -2, -2, -2, -1, 0, 0, + 0, 1, 0, -1, -1, 0, 0, 1, -1, 0, -1, -2, -3, -2, -2, -1, + 7, 7, 6, 5, 4, 2, -1, -2, 3, 3, 2, 2, 1, 0, -2, -3, + 0, -1, -1, -1, 0, -1, -2, -2, -1, -3, -2, -1, 0, 0, 0, 1, + 0, -2, -2, -1, -1, 1, 2, 2, 3, 1, -1, -1, -1, 1, 2, 2, + 3, 1, -2, -3, -2, -1, 1, 2, 1, -2, -5, -6, -5, -3, -2, 0, + 0, -1, -2, -3, -1, 0, -2, -2, 0, 0, -1, -1, 0, 1, -1, -2, + 0, 0, -2, -1, 0, 0, 0, -2, -1, -2, -3, -3, -2, -1, -3, -3, + -1, -2, -3, -3, -2, -2, -3, -4, 2, 2, 0, 0, 0, 0, -1, -2, + 5, 5, 3, 2, 2, 2, 0, -1, 8, 8, 6, 5, 4, 4, 2, 1, + -7, -8, -6, -3, -1, -1, -2, -1, -5, -5, -3, 0, 2, 1, 0, 0, + -1, -1, 0, 3, 4, 3, 1, 1, 2, 1, 1, 3, 4, 3, 2, 2, + 3, 2, 0, 2, 3, 2, 1, 2, 4, 2, -1, -1, 0, 1, 1, 1, + 3, 2, -2, -3, -2, -1, 0, 1, 3, 1, -3, -4, -3, -2, 0, 1, + -4, -2, -1, 2, 3, 3, 1, 0, -7, -5, -4, -2, 0, 0, -1, -2, + -6, -5, -5, -4, -2, -2, -2, -3, -1, 0, -1, -1, 0, 0, 0, -1, + 2, 3, 2, 2, 2, 2, 1, 0, 3, 5, 4, 3, 1, 0, 1, 0, + 3, 4, 3, 2, 0, -1, -1, -1, 5, 5, 3, 1, 0, -1, -1, -1, + 1, 1, 0, -1, -3, -5, -6, -4, 1, 1, 0, 0, 0, -3, -3, -1, + 0, -1, -1, 0, 1, 0, 1, 3, -2, -2, -3, -1, 2, 2, 4, 7, + -2, -2, -2, 0, 2, 2, 3, 6, -1, 0, 0, 1, 1, 0, 0, 3, + 0, 3, 3, 3, 1, -2, -3, -1, 1, 3, 4, 3, 0, -3, -5, -4, + 0, 2, 0, -1, -3, -4, -2, -2, 1, 4, 2, 0, -2, -3, -2, -1, + 3, 6, 3, 1, -2, -2, 0, -1, 4, 7, 4, 1, -2, -3, -1, 0, + 3, 6, 3, 0, -3, -3, -1, 0, 1, 3, 0, -1, -3, -2, 1, 1, + 0, 1, -1, -2, -3, -1, 2, 2, -2, -1, -3, -3, -3, -1, 1, 2, + 3, 1, -1, 0, 1, 0, 0, 0, 2, -1, -2, -1, 1, 0, -1, -1, + 1, -1, -2, 0, 1, 0, -2, -3, 0, -2, -1, 1, 3, 1, -3, -5, + 0, -2, -1, 2, 5, 2, -3, -5, 0, -2, -1, 4, 6, 3, -2, -5, + 0, -2, 0, 4, 7, 4, -2, -4, 0, -2, 0, 4, 6, 4, -2, -4, + -2, -2, -3, -4, -3, -2, -1, 0, 1, 1, 0, -1, -1, -1, 0, 1, + 3, 3, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 0, 0, 1, + 0, 0, 0, 0, -1, -1, -1, -1, -4, -4, -4, -4, -4, -4, -4, -3, + -3, -3, -2, -3, -2, -1, -1, 0, 3, 4, 4, 5, 5, 6, 6, 7, + -1, -2, 7, -2, -4, -1, -1, 0, -1, -2, 9, -1, -4, -1, -1, 0, + -1, -3, 10, -1, -4, -1, -1, 1, -1, -3, 10, -2, -3, -1, -1, 2, + -1, -2, 10, -2, -4, -1, -1, 2, -1, -2, 9, -2, -4, -1, -1, 2, + -1, -2, 8, -2, -4, 0, -1, 1, 0, -2, 7, -2, -3, -1, 0, 2, + 3, -4, 1, 3, -3, -2, 1, 0, 3, -5, 1, 4, -3, -2, 1, 0, + 3, -6, 2, 5, -3, -1, 3, 0, 3, -6, 2, 5, -3, -1, 2, 0, + 3, -6, 1, 5, -4, -2, 3, 0, 3, -6, 1, 5, -3, -2, 2, 0, + 2, -6, 1, 4, -3, -1, 1, 0, 2, -6, 1, 4, -2, -1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, 2, 0, -1, 1, 1, 1, 0, 0, 2, + 0, -1, 0, 0, 0, 0, 0, 2, 0, -1, 0, 0, 0, 0, -1, 0, + 1, 0, 1, 0, 0, -1, -2, -1, 3, 1, 1, 0, 0, -2, -4, -3, + 5, 3, 2, 1, 0, -3, -5, -4, 5, 4, 2, 0, -1, -4, -5, -5, + 1, 0, -1, -2, -2, -3, -6, -9, 2, 0, -1, -1, 0, 0, -3, -6, + 1, 0, 0, -1, 0, 0, -2, -5, 2, 1, 1, 1, 1, 2, -1, -3, + 1, 1, 2, 1, 2, 2, 1, -1, 1, 1, 2, 1, 1, 1, 1, 1, + 0, 0, 2, 1, 0, 0, 2, 2, 0, 1, 2, 2, 0, 0, 2, 2, + -4, -3, 0, 1, 4, 6, 4, 3, -3, -2, 0, 0, 2, 4, 1, 0, + -1, -1, 0, 0, 1, 1, -2, -3, 1, 1, 1, 0, 1, 1, -3, -5, + 1, 1, 1, 0, 1, 1, -3, -5, -1, 0, 0, -1, 1, 1, -2, -4, + -1, 0, 0, -1, 1, 2, 0, -2, -1, 0, 0, 0, 2, 3, 1, 0, + -1, 0, 3, 4, 0, -4, -5, -5, 0, 0, 4, 5, 2, -2, -3, -2, + 0, -1, 2, 4, 2, -1, -1, 0, 0, -2, -1, 1, 0, -2, 0, 1, + 1, -2, -2, 0, 0, -1, -1, 1, 1, -2, -3, 0, 1, 0, -1, 0, + 1, -2, -2, 1, 3, 1, 0, 0, 1, -2, -1, 2, 4, 2, 0, 0, + 1, 2, 3, 2, 0, 2, 2, 1, -1, 0, 1, 0, -3, 1, 1, 1, + -1, 0, 0, -2, -4, 0, 2, 1, -1, 2, 2, -1, -5, 0, 2, 1, + -1, 3, 4, -1, -5, 0, 2, 1, -2, 2, 4, 0, -4, -1, 0, 0, + -4, 0, 2, 0, -4, -2, 0, 0, -5, -1, 2, 1, -2, 1, 3, 2, + 1, 0, 1, 0, 1, 2, -1, -2, 2, 0, -1, -2, 1, 3, 0, -1, + 3, 0, -2, -4, 0, 3, 1, 0, 5, 1, -3, -5, -2, 2, 1, 1, + 6, 1, -2, -5, -2, 1, 0, 1, 5, 1, -1, -5, -2, 0, -1, 0, + 3, 0, -2, -4, -2, 0, -1, 0, 1, -1, 0, -2, 0, 1, 0, 1, + 1, 1, 2, 3, 2, 1, 1, 2, -1, -1, 0, 1, 1, 0, 1, 1, + -4, -3, 0, 0, 1, 1, 1, 2, -4, -3, 0, 2, 2, 2, 3, 2, + -5, -4, 0, 1, 1, 1, 1, 2, -5, -4, -1, -1, -2, -2, -1, 0, + -3, -2, 0, 0, -2, -3, -2, -1, 2, 3, 4, 4, 2, 0, 0, 0, + -4, -2, 0, 1, 0, 0, 0, 0, -3, -1, 1, 1, 0, 0, 0, 0, + -2, 0, 2, 2, 0, 0, 0, 2, -1, 1, 2, 1, -1, 0, 3, 5, + 0, 2, 1, -1, -2, 0, 5, 6, 0, 1, 0, -3, -3, 0, 4, 6, + 1, 1, -2, -4, -4, -3, 1, 2, 1, 0, -2, -4, -5, -4, -2, 0, + -1, -3, -3, -3, -3, -2, -1, -1, 3, 2, 1, 0, 0, 1, 1, 1, + 5, 4, 3, 2, 1, 1, 2, 2, 2, 1, 0, -2, -2, -2, -1, -1, + 0, 0, 0, -1, -2, -2, -2, -2, 0, 1, 3, 3, 2, 1, -1, -1, + 0, 1, 3, 4, 3, 2, 1, -1, -4, -3, -1, 1, 0, -2, -3, -3, + -3, -4, -7, -8, -7, -4, -1, 2, 0, -1, -3, -4, -4, -2, 0, 2, + 1, 0, 0, -1, -3, -2, 0, 2, 2, 1, 1, 0, -1, -1, 0, 2, + 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 2, 3, 3, 2, 2, 0, 0, 1, 3, 4, 4, 3, 2, + 3, 3, 3, 0, -1, 0, 1, 2, 1, 1, 1, -1, -2, -1, -1, 1, + -2, -2, -1, -3, -3, -2, -2, 0, -4, -4, -2, -2, -2, -2, -3, 0, + -4, -4, -1, 1, 1, 0, -1, 2, -3, -1, 2, 3, 4, 3, 3, 5, + -2, 0, 2, 3, 3, 3, 3, 3, -2, -2, 0, 0, 0, 0, 0, 1, + 0, 2, 1, -1, -3, -1, 3, -2, -1, 0, -1, -1, -3, 0, 4, -2, + -2, -2, -2, -2, -2, 1, 5, -2, -3, -2, -3, -1, -2, 1, 4, -3, + -2, 0, -1, 0, -1, 0, 3, -5, 1, 2, 1, 2, 0, 0, 2, -5, + 2, 4, 2, 3, 1, 1, 3, -3, 1, 2, 1, 1, 0, 1, 4, -2, + 4, -3, -4, -1, 3, 3, 1, 3, 4, -4, -4, -1, 3, 2, 0, 2, + 4, -3, -4, 0, 2, 2, -1, 1, 4, -3, -2, 1, 2, 1, -2, 0, + 2, -4, -2, 1, 2, 0, -3, 0, 2, -3, -2, 0, 1, 0, -2, 2, + 3, -1, -1, 0, 0, 0, 0, 3, 2, -2, -2, -2, -1, -1, -1, 2, + 2, 2, 3, 4, 3, 1, 0, -1, 1, 0, 1, 2, 1, -1, -2, -2, + 2, 1, 2, 1, 1, 0, -1, -1, 4, 3, 4, 3, 2, 1, 1, 1, + 3, 2, 2, 2, 1, 1, 1, 1, -1, -2, -1, 0, -1, -1, -1, -1, + -3, -3, -2, -1, -2, -2, -2, -2, -4, -4, -3, -3, -4, -4, -3, -3, + 2, 1, -1, -3, -4, -2, 3, 4, 2, 2, 1, -1, -3, -2, 1, 2, + 1, 2, 3, 3, 0, -2, -1, -2, -1, 0, 2, 4, 2, 0, -1, -3, + -2, -2, 0, 3, 3, 2, 0, -3, 0, -2, -3, -1, 1, 2, 2, -1, + 3, -1, -4, -5, -3, 0, 2, 0, 6, 3, -2, -6, -5, 0, 3, 1, + -2, 3, -2, 0, 3, -2, -2, 1, -3, 4, -3, 0, 3, -2, -1, 2, + -3, 5, -3, 0, 4, -2, -1, 2, -2, 4, -4, -1, 3, -3, -2, 2, + -3, 4, -3, 0, 3, -3, -1, 2, -2, 5, -2, 0, 3, -3, -1, 2, + -2, 4, -3, 1, 3, -2, -1, 2, -2, 3, -2, 1, 3, -2, 0, 2, + 1, 0, 0, -1, 1, 2, -4, -1, 2, 0, 0, -1, 1, 2, -4, -2, + 1, 1, 1, -1, 2, 4, -2, 0, 0, -1, 1, -1, 2, 5, -1, 1, + 0, -1, 0, -2, 1, 5, -1, 1, 0, -1, -1, -2, 0, 3, -3, -1, + 1, 1, 0, -2, 0, 3, -3, -1, 1, 1, 0, -3, 0, 3, -2, 0, + 1, 0, -1, 1, 1, 2, 4, 5, 1, 0, -1, 1, 1, 1, 5, 7, + 0, 0, -2, -1, -1, 0, 3, 5, 0, -1, -2, -1, -1, -1, 2, 3, + 0, -1, -3, -1, -1, -1, 1, 2, -1, -2, -4, -2, -2, -2, 0, 0, + -1, -2, -2, -1, -2, -2, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, + 3, 3, 0, -1, -1, 1, 4, 4, 2, 3, 0, -2, -2, 0, 1, 1, + 2, 3, 1, -1, -1, 0, 1, 0, 1, 2, 0, -1, -1, -1, 0, -2, + 0, 1, 0, -1, -2, -1, 0, -2, 0, 1, 0, -1, -2, -1, 1, 0, + 1, 1, -1, -3, -4, -3, 1, 3, 1, 2, -1, -3, -5, -4, 1, 3, + -3, -2, 0, 1, 1, 1, 0, -2, 0, 1, 1, 1, 0, 0, -1, -3, + 1, 2, 1, 1, 0, -1, -1, -2, 0, -1, -3, -1, -1, -1, 0, -1, + 0, -3, -6, -3, -2, -1, 1, 1, 2, -1, -4, -3, -2, 0, 2, 2, + 5, 4, 1, 1, 0, 1, 3, 2, 5, 4, 2, 1, 0, -1, 0, 1, + -2, 0, -2, -5, -6, -3, 0, 0, -2, 0, 1, 0, -1, 1, 2, 2, + -2, 0, 1, 3, 2, 2, 2, 1, -2, 0, 2, 4, 3, 2, 1, 1, + -2, 0, 2, 3, 2, 0, -1, 0, -3, -1, 1, 1, 0, -1, -1, 1, + -4, -1, 1, 0, -1, -2, 0, 2, -4, -1, 0, -1, -1, -2, 1, 4, + -3, 0, 0, -1, 1, 1, 1, 0, -3, 1, 0, -1, 0, 0, -1, -1, + -1, 3, 3, 0, 1, 0, 0, 1, -3, 2, 2, -2, -1, 0, 0, 1, + -5, 0, 0, -2, -1, 1, 0, 2, -7, -2, 1, 0, 1, 2, 2, 2, + -5, 0, 3, 2, 3, 3, 2, 2, -3, 2, 4, 1, 0, 0, -2, -3, + 5, 2, -2, -2, 0, -1, -1, -1, 2, -1, -4, -3, -1, -2, -1, -1, + 0, -2, -2, 1, 2, -1, 0, 1, -1, -2, -1, 3, 3, -1, 0, 2, + 1, 0, 0, 3, 3, -2, -1, 2, 2, 1, 1, 3, 2, -2, -2, 0, + 1, 0, -1, 1, 1, -3, -3, -2, 1, 0, 1, 2, 3, 0, 0, 0, + -4, -5, -3, 0, 1, -1, -2, -1, -2, -3, -1, 1, 2, 0, 0, 0, + 1, 1, 2, 1, 2, 1, 1, 1, 3, 4, 3, 1, 0, -2, -1, -1, + 3, 3, 2, 0, -2, -3, -3, -2, 1, 1, 0, -1, -2, -4, -2, -2, + 2, 1, 0, 0, 0, -1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 3, + 0, 0, 0, -1, -2, -1, 1, 0, -2, -1, -1, -2, -3, -2, 0, 0, + -1, 0, 0, -1, -2, 0, 1, 1, 1, 1, 0, -1, -1, 1, 3, 1, + 2, 2, 0, -2, -1, 2, 3, 0, 3, 1, -1, -1, 1, 4, 2, -2, + 2, 0, -3, -1, 3, 5, 0, -5, 1, -1, -2, 0, 3, 3, -1, -6, + -1, 0, 3, 4, 2, 0, 1, 2, -2, -1, 0, 1, -1, -2, 0, 1, + -2, -3, -2, -3, -6, -7, -6, -3, 2, 2, 3, 1, -1, -2, -3, -2, + 2, 2, 3, 1, 0, 0, 0, 0, 2, 1, 1, 0, 1, 1, 0, 1, + 1, 0, 0, 0, 0, 1, 1, 2, 1, 0, -1, 0, 0, 2, 2, 1, + 1, 1, 3, 1, -1, -1, -1, 1, -2, -1, 0, 0, -2, -2, -1, 2, + -2, -2, 1, 1, 1, 0, 1, 3, -2, -2, 0, -1, 0, -1, 0, 2, + 0, 0, 1, 0, -1, -1, -2, 1, 3, 2, 2, 1, 0, -2, -2, 1, + 5, 3, 3, 2, 1, 1, 1, 4, 0, -3, -4, -5, -4, -3, -1, 1, + -6, -4, -1, 2, 2, 0, 0, -1, -4, -2, 1, 3, 3, 2, 2, 0, + -3, -2, -1, 2, 3, 3, 2, 0, -3, -2, -2, 1, 2, 1, 1, -1, + -2, -2, -2, 0, 2, 2, 1, -1, -1, -1, -1, 1, 2, 3, 2, 0, + -1, -1, -2, 1, 2, 2, 2, -1, 0, -1, -2, 0, 2, 1, 0, -1, + 6, 4, 2, 1, 0, 0, 0, 1, 4, 2, -1, -2, -2, -2, -1, -1, + 2, 1, -1, -2, -2, -2, -2, -1, 2, 2, 0, -2, -2, -2, -1, 0, + 0, 0, -1, -2, -2, -1, 0, 1, -3, -3, -2, -1, -1, -2, -1, 0, + -3, -2, 2, 3, 2, 0, -1, -2, -2, 0, 4, 5, 5, 2, 0, -1, + 5, 4, 2, 0, -1, -2, -1, -1, 4, 3, 2, 1, 0, -1, 0, -1, + 1, 1, 0, 1, 1, 0, 1, -1, -2, -1, -1, 0, 0, -2, -2, -3, + -1, 0, 0, 0, -1, -3, -3, -5, 0, 1, 1, -1, -1, -2, -2, -3, + -1, -1, -1, -2, -1, 1, 3, 1, -1, -2, -2, -1, 2, 5, 6, 5, + -3, -3, -2, 1, 1, -2, -1, -1, 1, 2, 3, 4, 1, -3, -1, -3, + 3, 2, 0, 1, -1, -3, -1, -3, 1, 0, -1, 0, -1, -1, 1, 0, + 1, 1, 0, 1, 2, 2, 5, 3, 1, 1, 1, 2, 2, 2, 3, 0, + -3, -1, -2, -2, -3, -3, -1, -3, -1, 1, 1, 0, -1, -1, 0, -2, + 2, 0, -2, -2, 2, 4, 1, -2, 1, 0, -2, -1, 3, 5, 2, -1, + -1, -2, -3, -2, 1, 3, 1, -2, -1, -2, -1, -1, 0, 2, 1, -1, + 0, 0, 1, 1, 1, 2, 2, 0, 0, 1, 4, 4, 2, 2, 3, 1, + -2, -1, 2, 1, -2, -3, -2, -3, -1, 0, 1, 0, -3, -4, -4, -5, + 4, 0, -3, -4, -4, -4, -2, -1, 5, 0, -1, 0, -1, -3, -2, -1, + 4, 0, 0, 1, 1, 0, 0, 0, 0, -3, -2, -1, 0, 0, 1, 0, + 0, -2, 0, 0, 1, 1, 2, 1, 2, 0, 0, 0, 1, 1, 1, 0, + 2, 0, -1, -1, 1, 1, 1, 0, 1, -1, -2, -2, 0, 2, 2, 2, + -3, -5, -2, 0, -1, -3, -3, 0, 0, -2, 0, 2, 2, 0, 0, 3, + 2, -1, -2, 0, 0, -1, -1, 2, 5, 2, -1, -1, -1, -1, -1, 2, + 5, 2, 0, -1, -1, 0, -1, 2, 2, 1, 0, 0, 0, 1, 0, 2, + -1, -1, 1, 1, 2, 2, 1, 2, -3, -2, 0, 0, 0, 0, -2, -1, + 0, 3, 2, 0, -2, -3, -3, -3, 0, 3, 3, 1, 0, 0, 1, 2, + -1, 0, -1, -2, -1, -1, 1, 3, -1, 0, -1, -2, -1, -1, 0, 2, + -1, 0, -1, -2, 0, 0, -1, 2, -1, 0, -1, -2, -1, -1, -2, 1, + 0, 1, 0, -3, -1, -1, -1, 2, 5, 5, 2, -1, -1, -1, 1, 3, + 0, 0, 1, -1, -3, -2, 0, 2, 1, 1, 3, 0, -2, -2, 0, 1, + 1, 1, 3, 1, 0, 0, -1, -1, 0, -1, 2, 1, 1, 0, -1, -3, + -1, -2, 1, 1, 1, 0, -2, -4, -1, 0, 2, 1, 1, 0, -1, -3, + 1, 1, 3, 2, 1, 0, -2, -3, 2, 2, 4, 2, 1, -1, -2, -4, + 1, 2, 2, 2, 0, -2, 0, 2, -1, -1, -2, -3, -4, -5, -3, 1, + 0, 1, 1, 0, -1, -1, -1, 1, 0, 1, 1, 1, 0, 0, 0, 2, + 0, 1, 1, 2, 1, 1, 1, 2, -1, -1, 0, 2, 2, 2, 2, 3, + -2, -4, -4, -1, -2, -2, -2, 0, 1, 0, 0, 1, 0, 0, 0, 1, + 0, -1, -3, -2, 0, 2, 2, 1, 0, -1, -2, -3, 0, 1, 1, 2, + 1, 0, -2, -3, -1, 0, 0, 1, -1, 0, -1, -2, 0, 0, -1, 0, + -1, 1, 1, 0, 2, 2, 0, 0, 0, 2, 3, 1, 3, 5, 3, 2, + -1, 1, 1, -2, 0, 3, 1, 1, -1, 0, 0, -4, -4, -1, -1, -1, + -1, 1, 1, 0, 1, 2, 1, 2, -3, 0, 1, 0, 1, 1, 0, 2, + -5, -3, -1, -1, 0, 1, 0, 1, -4, -3, -2, -3, -2, -1, -1, 0, + 0, 0, -1, -2, -2, -2, -2, 0, 3, 4, 2, 0, 0, 0, 0, 1, + 2, 1, 0, 0, 0, 0, -1, 0, 0, 1, 2, 3, 4, 4, 3, 2, + -1, 4, 7, 4, 0, 0, 0, 0, -1, 4, 6, 3, 0, 1, 1, 1, + 0, 3, 4, 0, -1, 0, 0, 1, 0, 1, 1, -2, -1, 0, -1, -1, + -1, 0, -1, -1, -1, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, + -1, -3, -3, 0, 1, -1, -2, -1, -3, -4, -4, -2, -1, -2, -2, -1, + 2, 2, 1, 0, 1, 1, 0, -3, -2, -1, 0, 0, 1, 1, 0, -3, + -2, -1, 0, 1, 2, 1, 1, -2, 1, 2, 2, 2, 3, 3, 2, -1, + 1, 2, 1, 0, 1, 1, 2, -1, 0, 1, -2, -4, -2, 0, 1, -1, + 1, 1, -1, -3, -2, 0, -1, -3, 1, 2, 0, -1, 0, 1, -1, -4, + -1, -1, -2, -2, 0, 3, 4, 3, 1, 1, -1, -3, -2, 0, 0, 0, + 2, 2, 2, 2, 2, 1, -1, -1, 1, 1, 1, 3, 3, 0, -2, -2, + 0, -1, -1, -1, 0, -2, -1, -1, -1, -3, -4, -3, -2, -2, 0, 2, + -1, -1, 0, 1, 2, 2, 3, 5, -2, -1, -1, 0, 0, 0, 0, 1, + -2, -3, 2, 0, 0, 1, 1, -1, -1, -4, 1, -2, -1, 2, 2, 0, + 1, -4, 0, -2, -2, 1, 1, -1, 2, -3, 1, -1, -1, 1, 1, -1, + 3, -2, 3, 1, 0, 1, 1, -1, 1, -3, 2, 1, 0, 1, 0, -1, + -1, -5, 1, 0, -1, 0, 1, 1, 0, -3, 3, 3, 1, 2, 3, 3, + 0, -1, -2, 1, 5, 5, 2, -1, 1, -1, -2, -1, 1, 1, -2, -5, + 1, 1, -1, -2, -1, -1, -1, -3, 1, 1, -1, -1, -1, 2, 4, 3, + -1, -1, -1, -1, -1, 0, 4, 3, -1, -1, 0, 1, -1, -3, -1, -1, + 0, 0, 0, 2, 2, 0, 0, -1, 0, -2, -3, 0, 1, 1, 3, 2, + 2, 3, 2, 1, 0, 0, -2, -2, 2, 3, 0, 1, 1, 3, 3, 2, + 0, 0, -3, -1, -1, 2, 2, 3, -2, -2, -3, 1, 1, 2, 1, 1, + -2, -1, -2, 2, 1, 1, -1, -2, 0, 1, 0, 2, 0, 0, -2, -2, + 0, 1, 0, 2, 0, 0, -2, -2, -3, -2, -2, 0, -1, -2, -2, -3, + 0, 1, -1, 3, -1, 1, 3, -1, 0, 1, -1, 3, -1, -1, 2, -3, + 1, 1, -2, 3, -1, -3, 0, -3, 2, 2, -2, 3, 0, -2, 1, -2, + 1, 1, -3, 3, -1, -2, 1, -3, 1, 1, -3, 3, 0, -1, 1, -2, + 1, 2, -1, 4, 0, -1, 1, -2, 0, 1, -1, 3, -1, -3, 0, -3, + -3, -3, -1, 1, 2, 1, -1, -2, -2, -2, 0, 2, 1, 0, -2, -2, + -3, -2, 1, 2, 1, -1, -2, -1, -3, -2, 2, 4, 0, -2, -2, 1, + -3, -1, 2, 4, 0, -2, -2, 2, -1, 1, 4, 3, -1, -3, -2, 2, + 0, 2, 4, 2, -1, -2, -1, 2, 0, 1, 2, 0, -1, 0, 1, 3, + 3, 0, -5, 1, 4, 0, 0, 1, 1, -2, -5, 2, 5, -1, -2, 1, + -1, 0, 0, 3, 3, 1, 0, -1, -2, 3, 4, -2, -3, -1, 0, -2, + -3, 3, 5, -3, -3, 0, 0, -2, -1, 3, 2, -2, -2, 2, 2, -1, + 2, 0, 0, -1, 0, 0, 0, 0, 0, -3, -2, 1, 3, 0, -2, -2 }; -const uint32 *const s_svq1InterCodebooks[6] = { +static const int8 *const s_svq1InterCodebooks[6] = { s_svq1InterCodebook4x2, s_svq1InterCodebook4x4, s_svq1InterCodebook8x4, s_svq1InterCodebook8x8, 0, 0 }; -static const uint32 s_svq1IntraCodebook4x2[192] = { - 0x0b0d0d0c, 0xeff1f6f9, 0xf6f4f1f0, 0x0c0f0f0b, - 0x0f141102, 0x0d02e8d3, 0xdcfa1415, 0xe5ff100c, - 0x2d0aebee, 0x15f9ecf5, 0x00e4f82b, 0x03e4f021, - 0xfaeeeef4, 0x371cf6ec, 0xeeebeefb, 0xecfa1e38, - 0xea1d1bde, 0xe71a1de2, 0x1a21221e, 0xdfdde1e7, - 0xe0dcdde1, 0x1f25241d, 0x2226f4b9, 0x212affc1, - 0xc4e1253a, 0xc3df2237, 0x5d16c7c7, 0x5d15c6c7, - 0x3e46453b, 0xc4bcbcc1, 0xc0b9b9c0, 0x3e48493f, - 0x0f0700fe, 0x05fdf6f5, 0xf6f6f8fb, 0x090e0901, - 0xf5fc080f, 0xf4f5020c, 0x1c1300f8, 0xe6f1ff04, - 0xf2021bf1, 0xf70116f2, 0xf6f3fafc, 0x2f06f2fa, - 0x1706ecdd, 0x04060906, 0xea1702fa, 0xeb1c04f9, - 0x06feea14, 0x08fbe416, 0xf4f0eef6, 0xff021324, - 0x080400fd, 0x1717f6d3, 0xddec0f28, 0x0104fffc, - 0x18dffb09, 0x13e60308, 0xfd0604ff, 0xcff31920, - 0x070f1818, 0xf9ede5ef, 0x182700d1, 0x0407faeb, - 0xf3f600ff, 0x10050101, 0xf7fd0514, 0xfafefcff, - 0x0401f9ef, 0x0000070c, 0x0b0c0003, 0xe90001fd, - 0x00fa1104, 0x00e70306, 0x05080aef, 0x040104f2, - 0x02040a0d, 0x0201f7e9, 0x0701fd03, 0x14f9e901, - 0x0c02eef9, 0x090afcfb, 0xe8070a04, 0xf6040306, - 0x06eaf216, 0xff050500, 0xfcf503fc, 0xf2071ff9, - 0x2afff0fb, 0xfbf7fefc, 0xfdfaf805, 0xfbebfc2a, - 0xf4140cee, 0x07f6f30d, 0xeefef7f8, 0x082806f0, - 0x0400ff0a, 0xf3ff04fd, 0xf10106fe, 0x02010305, - 0x0301fefc, 0xfcf7000f, 0xfcfcfcfd, 0xfd1005fd, - 0x04030d02, 0x00f6f8fd, 0xfffcfefa, 0x17fafdfe, - 0x0107fa06, 0x0105ee04, 0x0ef101ff, 0x04fc06fb, - 0x06020202, 0x030702e8, 0x030300e6, 0x06010705, - 0xfdeefe0e, 0x02fc0507, 0x012003fa, 0xf4fafafa, - 0x0607dc05, 0x000bff09, 0x03050404, 0xda030f04, - 0xd6fb170a, 0x04040400, 0xf3fa1117, 0x1d01dbf3, - 0x01fff205, 0x01030005, 0x02fb0400, 0xf6000008, - 0xfdfe0704, 0x010103f6, 0x030dfff4, 0xfd01ff00, - 0x0103ff00, 0x0903f7fa, 0xfafc01fa, 0x0800ff08, - 0x1200fdfd, 0xfffcfffb, 0xfc03fef8, 0xfbff1100, - 0xf609fe05, 0xfb06fb01, 0x03020204, 0x01f8f20a, - 0xffeefeff, 0x020114ff, 0x01f701ff, 0xfc16f7ff, - 0xfd08fc06, 0x05ed07ff, 0xfcfc1ff9, 0xfbfb00fa, - 0xfcedf8f9, 0x20040101, 0x04f8ff26, 0xf4faf8f9, - 0x01f900ff, 0x00ff09ff, 0x00ffff09, 0xfd01fa02, - 0x010200f4, 0x00080101, 0x02000109, 0x00f501fe, - 0xf6020800, 0x00ff02ff, 0xfb00fcfe, 0x0efffffe, - 0x05ff07fd, 0x0101f600, 0xff0efbff, 0xfefd01fe, - 0x060000fa, 0x04f70302, 0xfffffb04, 0xff0803f9, - 0xf5fffc02, 0x0001020b, 0x090302ff, 0xf1000200, - 0x03ec0503, 0x0303ff03, 0x0110ff01, 0x0209e302, - 0xfdfffaf3, 0xfdf8ff24, 0x02040502, 0x030b09db +static const int8 s_svq1IntraCodebook4x2[768] = { + 12, 13, 13, 11, -7,-10,-15,-17,-16,-15,-12,-10, 11, 15, 15, 12, + 2, 17, 20, 15,-45,-24, 2, 13, 21, 20, -6,-36, 12, 16, -1,-27, + -18,-21, 10, 45,-11,-20, -7, 21, 43, -8,-28, 0, 33,-16,-28, 3, + -12,-18,-18, -6,-20,-10, 28, 55, -5,-18,-21,-18, 56, 30, -6,-20, + -34, 27, 29,-22,-30, 29, 26,-25, 30, 34, 33, 26,-25,-31,-35,-33, + -31,-35,-36,-32, 29, 36, 37, 31,-71,-12, 38, 34,-63, -1, 42, 33, + 58, 37,-31,-60, 55, 34,-33,-61,-57,-57, 22, 93,-57,-58, 21, 93, + 59, 69, 70, 62,-63,-68,-68,-60,-64,-71,-71,-64, 63, 73, 72, 62, + -2, 0, 7, 15,-11,-10, -3, 5, -5, -8,-10,-10, 1, 9, 14, 9, + 15, 8, -4,-11, 12, 2,-11,-12, -8, 0, 19, 28, 4, -1,-15,-26, + -15, 27, 2,-14,-14, 22, 1, -9, -4, -6,-13,-10, -6,-14, 6, 47, + -35,-20, 6, 23, 6, 9, 6, 4, -6, 2, 23,-22, -7, 4, 28,-21, + 20,-22, -2, 6, 22,-28, -5, 8,-10,-18,-16,-12, 36, 19, 2, -1, + -3, 0, 4, 8,-45,-10, 23, 23, 40, 15,-20,-35, -4, -1, 4, 1, + 9, -5,-33, 24, 8, 3,-26, 19, -1, 4, 6, -3, 32, 25,-13,-49, + 24, 24, 15, 7,-17,-27,-19, -7,-47, 0, 39, 24,-21, -6, 7, 4, + -1, 0,-10,-13, 1, 1, 5, 16, 20, 5, -3, -9, -1, -4, -2, -6, + -17, -7, 1, 4, 12, 7, 0, 0, 3, 0, 12, 11, -3, 1, 0,-23, + 4, 17, -6, 0, 6, 3,-25, 0,-17, 10, 8, 5,-14, 4, 1, 4, + 13, 10, 4, 2,-23, -9, 1, 2, 3, -3, 1, 7, 1,-23, -7, 20, + -7,-18, 2, 12, -5, -4, 10, 9, 4, 10, 7,-24, 6, 3, 4,-10, + 22,-14,-22, 6, 0, 5, 5, -1, -4, 3,-11, -4, -7, 31, 7,-14, + -5,-16, -1, 42, -4, -2, -9, -5, 5, -8, -6, -3, 42, -4,-21, -5, + -18, 12, 20,-12, 13,-13,-10, 7, -8, -9, -2,-18,-16, 6, 40, 8, + 10, -1, 0, 4, -3, 4, -1,-13, -2, 6, 1,-15, 5, 3, 1, 2, + -4, -2, 1, 3, 15, 0, -9, -4, -3, -4, -4, -4, -3, 5, 16, -3, + 2, 13, 3, 4, -3, -8,-10, 0, -6, -2, -4, -1, -2, -3, -6, 23, + 6, -6, 7, 1, 4,-18, 5, 1, -1, 1,-15, 14, -5, 6, -4, 4, + 2, 2, 2, 6,-24, 2, 7, 3,-26, 0, 3, 3, 5, 7, 1, 6, + 14, -2,-18, -3, 7, 5, -4, 2, -6, 3, 32, 1, -6, -6, -6,-12, + 5,-36, 7, 6, 9, -1, 11, 0, 4, 4, 5, 3, 4, 15, 3,-38, + 10, 23, -5,-42, 0, 4, 4, 4, 23, 17, -6,-13,-13,-37, 1, 29, + 5,-14, -1, 1, 5, 0, 3, 1, 0, 4, -5, 2, 8, 0, 0,-10, + 4, 7, -2, -3,-10, 3, 1, 1,-12, -1, 13, 3, 0, -1, 1, -3, + 0, -1, 3, 1, -6, -9, 3, 9, -6, 1, -4, -6, 8, -1, 0, 8, + -3, -3, 0, 18, -5, -1, -4, -1, -8, -2, 3, -4, 0, 17, -1, -5, + 5, -2, 9,-10, 1, -5, 6, -5, 4, 2, 2, 3, 10,-14, -8, 1, + -1, -2,-18, -1, -1, 20, 1, 2, -1, 1, -9, 1, -1, -9, 22, -4, + 6, -4, 8, -3, -1, 7,-19, 5, -7, 31, -4, -4, -6, 0, -5, -5, + -7, -8,-19, -4, 1, 1, 4, 32, 38, -1, -8, 4, -7, -8, -6,-12, + -1, 0, -7, 1, -1, 9, -1, 0, 9, -1, -1, 0, 2, -6, 1, -3, + -12, 0, 2, 1, 1, 1, 8, 0, 9, 1, 0, 2, -2, 1,-11, 0, + 0, 8, 2,-10, -1, 2, -1, 0, -2, -4, 0, -5, -2, -1, -1, 14, + -3, 7, -1, 5, 0,-10, 1, 1, -1, -5, 14, -1, -2, 1, -3, -2, + -6, 0, 0, 6, 2, 3, -9, 4, 4, -5, -1, -1, -7, 3, 8, -1, + 2, -4, -1,-11, 11, 2, 1, 0, -1, 2, 3, 9, 0, 2, 0,-15, + 3, 5,-20, 3, 3, -1, 3, 3, 1, -1, 16, 1, 2,-29, 9, 2, + -13, -6, -1, -3, 36, -1, -8, -3, 2, 5, 4, 2,-37, 9, 11, 3 }; -static const uint32 s_svq1IntraCodebook4x4[384] = { - 0x0603fdf5, 0x0705fff6, 0x0706fff7, 0x0604fff7, - 0xf2000705, 0xf1020906, 0xf1020906, 0xf2000604, - 0xfafb0310, 0xf8f80110, 0xf7f7ff0e, 0xf8f8000c, - 0x11100c08, 0x090602fe, 0x00fcf8f6, 0xf9f5f2f1, - 0x10fef6f9, 0x12fdf5f9, 0x14fff5f9, 0x1301f8fa, - 0xeff0f3f7, 0xf7f9fe02, 0xff04080b, 0x070b0f10, - 0x0f0dfeea, 0x100efee8, 0x0f0dfce7, 0x0d0afae7, - 0x10161a1a, 0x03090f11, 0xf2f5fafe, 0xe4e4e7ec, - 0xebe7e5e5, 0xf9f5f1f0, 0x0d0c0803, 0x1e1f1c17, - 0xdff91014, 0xddfa1316, 0xdefa1316, 0xe0fa1114, - 0x2602ecec, 0x2802eaeb, 0x2802eaeb, 0x2603ecec, - 0x1a18fcd1, 0x1b1afdce, 0x1b1afdce, 0x1a18fcd1, - 0xe5e9062d, 0xe4e70530, 0xe4e60530, 0xe5e8062c, - 0x4cf6dce2, 0x4ef5dbe1, 0x4ef5dbe1, 0x4df6dce1, - 0x3423e0cb, 0x3424deca, 0x3424deca, 0x3322dfcb, - 0x413edea3, 0x423edea3, 0x413edea3, 0x403cdea3, - 0x020200f9, 0x0303fff8, 0x050400f8, 0x050501fa, - 0x0b0b0703, 0x03030202, 0xf9fafe01, 0xf3f5fb01, - 0xfdfcfe03, 0xfbfb0007, 0xf9fb040c, 0xf9fc060e, - 0xfe030e12, 0xfd000406, 0x00fefbf8, 0x02fef5f0, - 0x1207faf8, 0x0d02f8f9, 0x06fefafc, 0x01fdfc00, - 0xeef3fd01, 0xf9fbff00, 0x070601ff, 0x110f04fe, - 0xfef9f2f1, 0x00fffbfa, 0x01030606, 0x01060d0f, - 0x0af5fe02, 0x0bf4ff02, 0x0bf4ff03, 0x0bf5fe02, - 0xfbff0ef7, 0xfbfe0ff7, 0xfbfe10f8, 0xfcff0ff9, - 0x08080602, 0x0c0903fe, 0x0a04fbf5, 0x00f8f0ed, - 0xf1f9080e, 0xf2f9070c, 0xf7fc0508, 0xfcff0305, - 0x02fef20c, 0x03fff10d, 0x03fff10e, 0x03fff20d, - 0xf30a0600, 0xf10a0600, 0xef090700, 0xf0080601, - 0xfe0ffbf8, 0xfe11faf8, 0xfd10faf8, 0xfe0ffbf8, - 0xf6f5f5f7, 0x08090a09, 0x090a0a08, 0xf9f8f7f8, - 0x07090a09, 0xf6f6f6f8, 0xf5f5f6f9, 0x080b0c0b, - 0x00070a00, 0xfa000700, 0xfafb0200, 0xfffcfffe, - 0xf7fa0005, 0x01020202, 0x070500fe, 0x0401fbfa, - 0xff02f803, 0x0003f704, 0x0003f905, 0x0003fb07, - 0x0902fdfb, 0x0801fdfa, 0x0701fdfa, 0x0400fefb, - 0x0103080d, 0xfffcfbfd, 0x00fdf9f8, 0x020301ff, - 0xf4fb0203, 0xf7fe0304, 0xfc010403, 0xff040503, - 0x00fcf8f7, 0x00020608, 0x0003080a, 0xfffdfbfa, - 0xfbf4f7fd, 0x00fbfd00, 0x04020302, 0x06070805, - 0x0c05feff, 0x0905ffff, 0xfeff0102, 0xeff5ff02, - 0xff0303f9, 0xff0403f7, 0xff0604f6, 0x000705f7, - 0x0202f9ee, 0x030501f8, 0x00010403, 0xfdfe0509, - 0x080600fe, 0xfdfbfbfc, 0xf8fafe01, 0xff03090a, - 0x00fefe00, 0x00fbfc00, 0x08fcf8fe, 0x1806f9fb, - 0x01f90109, 0x01f80109, 0x01f60008, 0xfff5ff08, - 0x03060808, 0x02030405, 0x00fffdfe, 0xfcf8f3f6, - 0xfd020400, 0xfb030600, 0xf4020a03, 0xeafc0a05, - 0x03fffc00, 0x05fffc01, 0x0800fb01, 0x07fefaff, - 0xfcfeffff, 0xfafcfeff, 0xfeffffff, 0x090a0501, - 0xfe00030a, 0xfbfeff06, 0xfafeff03, 0xfb000002, - 0x00000306, 0x01010306, 0x01fefe04, 0xfef7f700, - 0x0201fdf5, 0x050402fa, 0x040302fd, 0x020101fe, - 0xfefffcfa, 0xfeffff02, 0xfefe020a, 0xfffc020b, - 0x02fe0006, 0x00000303, 0x000303fa, 0x0005ffef, - 0x0b0a04ff, 0x0100fefd, 0xfdfbfcfd, 0xfffefeff, - 0xf4f7fd02, 0x02030303, 0x04040202, 0xfeff0102, - 0xf60509fe, 0xfb0505fd, 0x000201fe, 0x01fefeff, - 0xfe07fdfe, 0xfd07fdff, 0xfc08feff, 0xfd07fefe, - 0x0cfdf801, 0x04fefe02, 0xfb000301, 0xf90205ff, - 0xfb0103ff, 0x0103fef9, 0x02fef9fe, 0xfffb0314, - 0xfefd0005, 0x0600f9f9, 0x060700fa, 0xf9000602, - 0x01f906fe, 0x03f807fe, 0x03f907fe, 0x02fa07ff, - 0x0705fefb, 0xf8fc0104, 0xfbfe0306, 0x0703fbf9, - 0x0506ffff, 0xfc01ff00, 0xf9000102, 0xfc000001, - 0x010300f8, 0xffff01fe, 0x01fdff01, 0x0901fe01, - 0xfcfd0205, 0xfdff00ff, 0x010301fd, 0x020400fc, - 0x0cfefe02, 0x03fbfe00, 0x01fd00ff, 0x01fefffd, - 0x00030501, 0x01fefcfa, 0x02fefe00, 0xfffc0106, - 0xfffbfbfd, 0x04050503, 0xff010300, 0xfdfe01fe, - 0xfdfbfc02, 0xfefdfe04, 0xffff0006, 0x00000107, - 0x00fefefd, 0xfffbfdfe, 0xff0002fe, 0xff090bff, - 0xf6ff0100, 0xfa0001ff, 0x04010001, 0x0dfffb02, - 0x000504fe, 0x030601fb, 0x0203fefa, 0xfe00fefb, - 0xfe0101ff, 0x0200feff, 0x07050505, 0xf9f8fc00, - 0xfbff0200, 0xfd0202ff, 0xfb030500, 0xf4020803, - 0xfe000408, 0xfffcff0a, 0x00fdfa03, 0x0000fbfc, - 0x02fcf600, 0x0503faff, 0x0406fdff, 0x0204fe00, - 0xff010800, 0xfd010b00, 0xfcfe06ff, 0xfcf9fefd, - 0xffffff00, 0x05060504, 0xfbf8f7fb, 0x02030202, - 0x01060200, 0x00030002, 0xfefffe01, 0xfafdff00, - 0x00020000, 0x01020004, 0x0000fe05, 0x02fff7fe, - 0xf6000100, 0x000801ff, 0x0004feff, 0xff02ff01, - 0xff02fefd, 0xfd02fffd, 0x0001ff00, 0x03ff0108, - 0x02010100, 0x00fefc00, 0xff01fbff, 0x020bfffe, - 0xfefe0501, 0x00fc0200, 0x01fb01fe, 0x01000500, - 0x0600fdfb, 0x000002fc, 0x000105fd, 0x000003fd, - 0x01fdfe03, 0x0800fc01, 0x03fefdfe, 0xffff0201, - 0x02000101, 0x06010002, 0x0102ff01, 0xed000300, - 0x02fefd01, 0xf9fe0506, 0x010301fd, 0x0200ffff, - 0xfcfffff8, 0x02ff0101, 0x03020304, 0x000301fb, - 0x01ff0200, 0x050000fd, 0x0800fefb, 0x06fcfcfc, - 0x02010201, 0x02fd0202, 0x00f70004, 0x01f50007, - 0xfe000000, 0xfaff0303, 0xf6fd0304, 0x020602ff, - 0x05fdfe07, 0xff0300fc, 0xf90102fc, 0x03ffff02, - 0x02020203, 0xfbf9f9fb, 0x02040605, 0x0100fffe +static const int8 s_svq1IntraCodebook4x4[1536] = { + -11, -3, 3, 6,-10, -1, 5, 7, -9, -1, 6, 7, -9, -1, 4, 6, + 5, 7, 0,-14, 6, 9, 2,-15, 6, 9, 2,-15, 4, 6, 0,-14, + 16, 3, -5, -6, 16, 1, -8, -8, 14, -1, -9, -9, 12, 0, -8, -8, + 8, 12, 16, 17, -2, 2, 6, 9,-10, -8, -4, 0,-15,-14,-11, -7, + -7,-10, -2, 16, -7,-11, -3, 18, -7,-11, -1, 20, -6, -8, 1, 19, + -9,-13,-16,-17, 2, -2, -7, -9, 11, 8, 4, -1, 16, 15, 11, 7, + -22, -2, 13, 15,-24, -2, 14, 16,-25, -4, 13, 15,-25, -6, 10, 13, + 26, 26, 22, 16, 17, 15, 9, 3, -2, -6,-11,-14,-20,-25,-28,-28, + -27,-27,-25,-21,-16,-15,-11, -7, 3, 8, 12, 13, 23, 28, 31, 30, + 20, 16, -7,-33, 22, 19, -6,-35, 22, 19, -6,-34, 20, 17, -6,-32, + -20,-20, 2, 38,-21,-22, 2, 40,-21,-22, 2, 40,-20,-20, 3, 38, + -47, -4, 24, 26,-50, -3, 26, 27,-50, -3, 26, 27,-47, -4, 24, 26, + 45, 6,-23,-27, 48, 5,-25,-28, 48, 5,-26,-28, 44, 6,-24,-27, + -30,-36,-10, 76,-31,-37,-11, 78,-31,-37,-11, 78,-31,-36,-10, 77, + -53,-32, 35, 52,-54,-34, 36, 52,-54,-34, 36, 52,-53,-33, 34, 51, + -93,-34, 62, 65,-93,-34, 62, 66,-93,-34, 62, 65,-93,-34, 60, 64, + -7, 0, 2, 2, -8, -1, 3, 3, -8, 0, 4, 5, -6, 1, 5, 5, + 3, 7, 11, 11, 2, 2, 3, 3, 1, -2, -6, -7, 1, -5,-11,-13, + 3, -2, -4, -3, 7, 0, -5, -5, 12, 4, -5, -7, 14, 6, -4, -7, + 18, 14, 3, -2, 6, 4, 0, -3, -8, -5, -2, 0,-16,-11, -2, 2, + -8, -6, 7, 18, -7, -8, 2, 13, -4, -6, -2, 6, 0, -4, -3, 1, + 1, -3,-13,-18, 0, -1, -5, -7, -1, 1, 6, 7, -2, 4, 15, 17, + -15,-14, -7, -2, -6, -5, -1, 0, 6, 6, 3, 1, 15, 13, 6, 1, + 2, -2,-11, 10, 2, -1,-12, 11, 3, -1,-12, 11, 2, -2,-11, 11, + -9, 14, -1, -5, -9, 15, -2, -5, -8, 16, -2, -5, -7, 15, -1, -4, + 2, 6, 8, 8, -2, 3, 9, 12,-11, -5, 4, 10,-19,-16, -8, 0, + 14, 8, -7,-15, 12, 7, -7,-14, 8, 5, -4, -9, 5, 3, -1, -4, + 12,-14, -2, 2, 13,-15, -1, 3, 14,-15, -1, 3, 13,-14, -1, 3, + 0, 6, 10,-13, 0, 6, 10,-15, 0, 7, 9,-17, 1, 6, 8,-16, + -8, -5, 15, -2, -8, -6, 17, -2, -8, -6, 16, -3, -8, -5, 15, -2, + -9,-11,-11,-10, 9, 10, 9, 8, 8, 10, 10, 9, -8, -9, -8, -7, + 9, 10, 9, 7, -8,-10,-10,-10, -7,-10,-11,-11, 11, 12, 11, 8, + 0, 10, 7, 0, 0, 7, 0, -6, 0, 2, -5, -6, -2, -1, -4, -1, + 5, 0, -6, -9, 2, 2, 2, 1, -2, 0, 5, 7, -6, -5, 1, 4, + 3, -8, 2, -1, 4, -9, 3, 0, 5, -7, 3, 0, 7, -5, 3, 0, + -5, -3, 2, 9, -6, -3, 1, 8, -6, -3, 1, 7, -5, -2, 0, 4, + 13, 8, 3, 1, -3, -5, -4, -1, -8, -7, -3, 0, -1, 1, 3, 2, + 3, 2, -5,-12, 4, 3, -2, -9, 3, 4, 1, -4, 3, 5, 4, -1, + -9, -8, -4, 0, 8, 6, 2, 0, 10, 8, 3, 0, -6, -5, -3, -1, + -3, -9,-12, -5, 0, -3, -5, 0, 2, 3, 2, 4, 5, 8, 7, 6, + -1, -2, 5, 12, -1, -1, 5, 9, 2, 1, -1, -2, 2, -1,-11,-17, + -7, 3, 3, -1, -9, 3, 4, -1,-10, 4, 6, -1, -9, 5, 7, 0, + -18, -7, 2, 2, -8, 1, 5, 3, 3, 4, 1, 0, 9, 5, -2, -3, + -2, 0, 6, 8, -4, -5, -5, -3, 1, -2, -6, -8, 10, 9, 3, -1, + 0, -2, -2, 0, 0, -4, -5, 0, -2, -8, -4, 8, -5, -7, 6, 24, + 9, 1, -7, 1, 9, 1, -8, 1, 8, 0,-10, 1, 8, -1,-11, -1, + 8, 8, 6, 3, 5, 4, 3, 2, -2, -3, -1, 0,-10,-13, -8, -4, + 0, 4, 2, -3, 0, 6, 3, -5, 3, 10, 2,-12, 5, 10, -4,-22, + 0, -4, -1, 3, 1, -4, -1, 5, 1, -5, 0, 8, -1, -6, -2, 7, + -1, -1, -2, -4, -1, -2, -4, -6, -1, -1, -1, -2, 1, 5, 10, 9, + 10, 3, 0, -2, 6, -1, -2, -5, 3, -1, -2, -6, 2, 0, 0, -5, + 6, 3, 0, 0, 6, 3, 1, 1, 4, -2, -2, 1, 0, -9, -9, -2, + -11, -3, 1, 2, -6, 2, 4, 5, -3, 2, 3, 4, -2, 1, 1, 2, + -6, -4, -1, -2, 2, -1, -1, -2, 10, 2, -2, -2, 11, 2, -4, -1, + 6, 0, -2, 2, 3, 3, 0, 0, -6, 3, 3, 0,-17, -1, 5, 0, + -1, 4, 10, 11, -3, -2, 0, 1, -3, -4, -5, -3, -1, -2, -2, -1, + 2, -3, -9,-12, 3, 3, 3, 2, 2, 2, 4, 4, 2, 1, -1, -2, + -2, 9, 5,-10, -3, 5, 5, -5, -2, 1, 2, 0, -1, -2, -2, 1, + -2, -3, 7, -2, -1, -3, 7, -3, -1, -2, 8, -4, -2, -2, 7, -3, + 1, -8, -3, 12, 2, -2, -2, 4, 1, 3, 0, -5, -1, 5, 2, -7, + -1, 3, 1, -5, -7, -2, 3, 1, -2, -7, -2, 2, 20, 3, -5, -1, + 5, 0, -3, -2, -7, -7, 0, 6, -6, 0, 7, 6, 2, 6, 0, -7, + -2, 6, -7, 1, -2, 7, -8, 3, -2, 7, -7, 3, -1, 7, -6, 2, + -5, -2, 5, 7, 4, 1, -4, -8, 6, 3, -2, -5, -7, -5, 3, 7, + -1, -1, 6, 5, 0, -1, 1, -4, 2, 1, 0, -7, 1, 0, 0, -4, + -8, 0, 3, 1, -2, 1, -1, -1, 1, -1, -3, 1, 1, -2, 1, 9, + 5, 2, -3, -4, -1, 0, -1, -3, -3, 1, 3, 1, -4, 0, 4, 2, + 2, -2, -2, 12, 0, -2, -5, 3, -1, 0, -3, 1, -3, -1, -2, 1, + 1, 5, 3, 0, -6, -4, -2, 1, 0, -2, -2, 2, 6, 1, -4, -1, + -3, -5, -5, -1, 3, 5, 5, 4, 0, 3, 1, -1, -2, 1, -2, -3, + 2, -4, -5, -3, 4, -2, -3, -2, 6, 0, -1, -1, 7, 1, 0, 0, + -3, -2, -2, 0, -2, -3, -5, -1, -2, 2, 0, -1, -1, 11, 9, -1, + 0, 1, -1,-10, -1, 1, 0, -6, 1, 0, 1, 4, 2, -5, -1, 13, + -2, 4, 5, 0, -5, 1, 6, 3, -6, -2, 3, 2, -5, -2, 0, -2, + -1, 1, 1, -2, -1, -2, 0, 2, 5, 5, 5, 7, 0, -4, -8, -7, + 0, 2, -1, -5, -1, 2, 2, -3, 0, 5, 3, -5, 3, 8, 2,-12, + 8, 4, 0, -2, 10, -1, -4, -1, 3, -6, -3, 0, -4, -5, 0, 0, + 0,-10, -4, 2, -1, -6, 3, 5, -1, -3, 6, 4, 0, -2, 4, 2, + 0, 8, 1, -1, 0, 11, 1, -3, -1, 6, -2, -4, -3, -2, -7, -4, + 0, -1, -1, -1, 4, 5, 6, 5, -5, -9, -8, -5, 2, 2, 3, 2, + 0, 2, 6, 1, 2, 0, 3, 0, 1, -2, -1, -2, 0, -1, -3, -6, + 0, 0, 2, 0, 4, 0, 2, 1, 5, -2, 0, 0, -2, -9, -1, 2, + 0, 1, 0,-10, -1, 1, 8, 0, -1, -2, 4, 0, 1, -1, 2, -1, + -3, -2, 2, -1, -3, -1, 2, -3, 0, -1, 1, 0, 8, 1, -1, 3, + 0, 1, 1, 2, 0, -4, -2, 0, -1, -5, 1, -1, -2, -1, 11, 2, + 1, 5, -2, -2, 0, 2, -4, 0, -2, 1, -5, 1, 0, 5, 0, 1, + -5, -3, 0, 6, -4, 2, 0, 0, -3, 5, 1, 0, -3, 3, 0, 0, + 3, -2, -3, 1, 1, -4, 0, 8, -2, -3, -2, 3, 1, 2, -1, -1, + 1, 1, 0, 2, 2, 0, 1, 6, 1, -1, 2, 1, 0, 3, 0,-19, + 1, -3, -2, 2, 6, 5, -2, -7, -3, 1, 3, 1, -1, -1, 0, 2, + -8, -1, -1, -4, 1, 1, -1, 2, 4, 3, 2, 3, -5, 1, 3, 0, + 0, 2, -1, 1, -3, 0, 0, 5, -5, -2, 0, 8, -4, -4, -4, 6, + 1, 2, 1, 2, 2, 2, -3, 2, 4, 0, -9, 0, 7, 0,-11, 1, + 0, 0, 0, -2, 3, 3, -1, -6, 4, 3, -3,-10, -1, 2, 6, 2, + 7, -2, -3, 5, -4, 0, 3, -1, -4, 2, 1, -7, 2, -1, -1, 3, + 3, 2, 2, 2, -5, -7, -7, -5, 5, 6, 4, 2, -2, -1, 0, 1 }; -static const uint32 s_svq1IntraCodebook8x4[768] = { - 0x06060605, 0x08080707, 0x00000000, 0x03020100, - 0xfbfcfcfd, 0xfefdfcfb, 0xfbfcfcfc, 0xfdfdfcfc, - 0x02020201, 0x03030302, 0x04030302, 0x05050504, - 0x010100ff, 0x04040302, 0xf7f7f6f7, 0xfbfaf9f8, - 0xfafbfcfc, 0xf9f9f9fa, 0xfefeff00, 0xfcfcfdfd, - 0x03030404, 0x00010102, 0x06070707, 0x04040506, - 0x06050402, 0xfafd0104, 0x05050403, 0xf8fb0004, - 0x04040302, 0xf6f9fe02, 0x01020202, 0xf4f7fc00, - 0x01fdf9f7, 0x03030404, 0x03fef9f6, 0x03030505, - 0x03fefaf7, 0x03040506, 0x03fffaf8, 0x02030404, - 0xfbfbfbfb, 0x070401fd, 0xfcfbfbfb, 0x080601fe, - 0xfdfcfbfc, 0x0a0803ff, 0xfefdfcfd, 0x0b090501, - 0xfefefefe, 0xfefefefe, 0xfbfbfbfc, 0xfcfbfbfb, - 0xfcfcfcfd, 0xfdfcfcfc, 0x0b0a0a09, 0x0a0a0b0b, - 0xfe010407, 0xf6f7fafc, 0x00030709, 0xf7f8fcfe, - 0x0204080b, 0xf8fafd00, 0x0305090b, 0xf9fbfe01, - 0xf4f3f3f3, 0xf8f8f6f5, 0x03020100, 0x03040404, - 0x06050403, 0x04050606, 0x04040403, 0x02030303, - 0x0a0b0a0a, 0x07080909, 0x06060606, 0x02030405, - 0xff000000, 0xfcfcfdfe, 0xf4f5f6f6, 0xf2f2f2f3, - 0x10111010, 0x0b0c0d0f, 0xfcfdfeff, 0xfdfcfcfc, - 0xfafafbfc, 0xfafafafa, 0xfafafafb, 0xfbfbfafa, - 0xf4f3f3f3, 0xfaf8f6f5, 0xfaf9f8f7, 0x0100fefc, - 0x0301fffe, 0x09080705, 0x0b090705, 0x0f0f0e0d, - 0x070b0e10, 0xf7f9fd02, 0x03080c0e, 0xf5f7faff, - 0x0004090b, 0xf3f5f8fc, 0xfd010508, 0xf2f4f6fa, - 0xfdf7f1ee, 0x0b090601, 0xfff9f3ef, 0x0c0b0703, - 0x01fbf5f1, 0x0d0c0905, 0x02fdf7f3, 0x0d0b0905, - 0x0f131516, 0xf7fc030a, 0x090f1214, 0xeff4fb02, - 0x01080d10, 0xe8ecf2f9, 0xf8ff060a, 0xe5e7ebf1, - 0xf2ece9e7, 0x0e0901f9, 0xf7f0ebe9, 0x15100900, - 0xfff6f0ec, 0x19161008, 0x06fdf5f1, 0x1b19140e, - 0x0100fefc, 0x02020202, 0x0200fefb, 0x03030303, - 0x01fffcfa, 0x03030302, 0x00fefbf9, 0x02020101, - 0x01010102, 0xfdfe0001, 0x01020303, 0xfcfdff00, - 0x01020304, 0xfafcfe00, 0x01030405, 0xfafbfdff, - 0x04060605, 0xfdfe0002, 0x04040403, 0xff000103, - 0xfffffefe, 0xfefeffff, 0xfefdfcfb, 0xfdfdfefe, - 0xffffffff, 0xffffffff, 0xfcfcfcfd, 0xfdfdfdfd, - 0xffffffff, 0xfeffffff, 0x06060605, 0x03040506, - 0x04040404, 0x07060504, 0xffffff00, 0x020100ff, - 0xfdfdfdfe, 0x00fffefd, 0xfcfcfdfd, 0xfffefdfc, - 0xfcfcfe00, 0x030200fe, 0xfdfdfe00, 0x050402ff, - 0xfdfcfeff, 0x06050300, 0xfdfcfdfe, 0x050402ff, - 0xfd000409, 0x0100fffd, 0xfcff0408, 0x0201fffd, - 0xfbfd0206, 0x0100fefc, 0xfcfd0105, 0x0100fefc, - 0xff010305, 0xf6f6f8fc, 0x01020303, 0xfcfdfe00, - 0x02010101, 0x00010203, 0x020100ff, 0x02030403, - 0x02020100, 0xfdfdff01, 0x01010100, 0xfdfcfeff, - 0xfdfdfdfd, 0x02fffdfd, 0x00fdfcfc, 0x0e0c0703, - 0xfafafbfb, 0xfbfafafa, 0x01020202, 0x00000000, - 0x02030404, 0x00000001, 0x04050606, 0x01010202, - 0xfdfaf9f9, 0x08070400, 0xfdfdfeff, 0x0201fffe, - 0xff010303, 0xfffefefe, 0x02040606, 0xfefefe00, - 0x02fefbfa, 0x0c0b0905, 0x00fefcfc, 0x06050402, - 0xfefefefd, 0x0100fffe, 0xfdfefefe, 0xfefdfdfd, - 0x0301fdf9, 0xfbfd0003, 0x0503fefa, 0xfbfd0104, - 0x0604fffb, 0xfcfd0205, 0x070500fc, 0xfdff0306, - 0x00000000, 0x00000000, 0xfdfdfefe, 0xfffefdfd, - 0x09080706, 0x06070809, 0xfbfbfcfc, 0xfcfbfafa, - 0xfcfaf8f7, 0x06060300, 0x03fffcfb, 0x03050605, - 0x06060301, 0xfbfe0104, 0x01050706, 0xf5f6f9fd, - 0x0105090a, 0xfcfafafd, 0xfbff0305, 0x02fefbfa, - 0xfafafcfe, 0x0a0601fc, 0xfcf9f9fa, 0x0c0b0701, - 0x02030506, 0x00000000, 0xfeff0102, 0xfffffefd, - 0xfcfeff00, 0x01fffefc, 0xfeff0000, 0x030200ff, - 0xfefeff00, 0xfffffefe, 0x01020405, 0x00000000, - 0x01030506, 0x00000000, 0xfcfe0002, 0xfefefdfc, - 0x0200fcf9, 0x01020202, 0x0000fdf9, 0x00000000, - 0x0101fffc, 0x01000000, 0x020201ff, 0x03030202, - 0x020200fe, 0x01010101, 0x020201ff, 0xff000001, - 0x02040200, 0xfdfeff00, 0x01030201, 0xfafafcfe, - 0x04020201, 0x01040605, 0xffffff00, 0xfcfe0000, - 0xfeff0000, 0xfafcfefe, 0x00000102, 0xfdff0101, - 0x01010101, 0x03030201, 0x00010000, 0x04040201, - 0xffffffff, 0x03020100, 0xfbfbfcfc, 0x00fffdfb, - 0xfcfbfbfa, 0xfffffefd, 0x010000ff, 0x03030201, - 0x01010100, 0x04030202, 0xffff0000, 0x03020100, - 0x01010100, 0xffff0000, 0x02030301, 0xfefeff01, - 0x020200fe, 0x01010202, 0xfefcf8f7, 0x03030301, - 0xfeffffff, 0xfcfdfdfd, 0xff000000, 0xfdfdfefe, - 0x00020202, 0xffffffff, 0x03040505, 0x02020202, - 0xfcff0306, 0x0101fffd, 0xfcfdff02, 0x000202ff, - 0x01fefeff, 0xfd010404, 0x0401fffe, 0xf8fd0306, - 0x01020303, 0xfefefeff, 0xfffefcfc, 0x04040301, - 0xfcfbfbfc, 0x020200fe, 0x01040707, 0xfefdfeff, - 0x000301ff, 0x0600fafc, 0x010401fe, 0x07fffafc, - 0x020401fd, 0x06fffafd, 0x020300fe, 0x04fffbfe, - 0x01feff01, 0xf9ff0404, 0xfffcff01, 0xfa000605, - 0xfdfc0003, 0xfc020603, 0xfcfb0003, 0xfd010401, - 0x03030202, 0x02020303, 0xf9fafbfc, 0xfaf9f9f9, - 0x03030201, 0x02020303, 0x01010000, 0x01020201, - 0x03fdfd03, 0x02fefe04, 0x04fcfc03, 0x02fcfc04, - 0x04fcfc04, 0x03fdfc04, 0x03fcfd03, 0x03fdfd03, - 0xfefefefe, 0xfffffefe, 0x08080706, 0x05060708, - 0xf9f9fafb, 0xfbfaf9f8, 0x02020101, 0x01010202, - 0x00000000, 0x0000ff00, 0x000000ff, 0x0000ff00, - 0xfefefdfe, 0xfdfdfdfe, 0x06050302, 0x00010204, - 0x00020608, 0x00000000, 0x00000104, 0xffffff00, - 0x0000ff01, 0xfdfeff00, 0x00fffefe, 0xfbfcfe00, - 0xfeff0103, 0xfbfbfcfd, 0x00000102, 0x00000101, - 0x00ffff00, 0x02020202, 0x01fffeff, 0x02020202, - 0xfffeff00, 0x00ffffff, 0xfffefeff, 0x010000ff, - 0x02010102, 0x00010102, 0x01030506, 0xfcfcfe00, - 0x00fffefd, 0xff000101, 0x04030100, 0x01030505, - 0x00ffffff, 0xfeff0001, 0xfffefefe, 0xfdfeff00, - 0xfefeff00, 0x0200ffff, 0xfffeff01, 0x0200ffff, - 0xfefe0001, 0x0501fefe, 0xfefeff01, 0x0a0500fe, - 0x00000000, 0xffffff00, 0x00ffffff, 0x02010000, - 0x03020201, 0x05060404, 0xfefdfdfd, 0xfdfdfdfe, - 0xfefeff01, 0x07050300, 0xfdfe0002, 0x030200fe, - 0xfdfe0103, 0xfffffefd, 0xff000103, 0xffffffff, - 0x04050301, 0xfcfdff02, 0x0201fefd, 0xfeff0001, - 0x0200fdfb, 0x00000102, 0x0201fffd, 0x00000102, - 0xffffff00, 0x04030201, 0xfdfcfcfd, 0x010000ff, - 0xfffefdfe, 0x01010101, 0x0300fefe, 0x02030404, - 0xfefdfcfc, 0x030201ff, 0x01010100, 0xfdfdfeff, - 0x04050403, 0xfdfdff02, 0x0200fefe, 0x00010202, - 0x070500fc, 0xfcfcff04, 0x030402ff, 0xfefdfd00, - 0xff000102, 0x0100fefe, 0xfeff0000, 0x0201fffe, - 0xfffefdfc, 0x02020100, 0x0005090a, 0xfefdfcfd, - 0xfefeff01, 0x000000ff, 0x01fffefe, 0xff000101, - 0x0300fdfb, 0xfe000204, 0x0100fffe, 0xffff0001, - 0xfeff0203, 0x0101fffe, 0xfbff0507, 0x0402fefa, - 0xfd0303fe, 0xfe0201fc, 0xfd0403fd, 0xfe0302fc, - 0xfd0403fd, 0xfe0302fc, 0xfe0402fc, 0xff0201fd, - 0xfdff0304, 0x0201fffd, 0x00fcfafc, 0x01040504, - 0x06050200, 0xfcfbfd02, 0xfdff0101, 0x0402fefb, - 0x020100ff, 0x04030302, 0x010100ff, 0xffffff00, - 0x020100ff, 0xfeff0102, 0x00fffefd, 0xfdfeff00, - 0x01010101, 0x02010000, 0x00ff0001, 0x00010100, - 0xfffcfe01, 0x00010201, 0xfdf9fc01, 0x01020301, - 0x01010101, 0xff000101, 0x00010101, 0x00020201, - 0x00000101, 0xfd000200, 0xff000203, 0xf7fafeff, - 0x01000000, 0x02010000, 0x00000001, 0x0200ffff, - 0x01010100, 0x00fefdff, 0x0601fbf9, 0xffff0206, - 0xfdff0103, 0x0401fefc, 0xfdfe0002, 0x02fffdfc, - 0x01010202, 0x01000001, 0x00000101, 0x01000000, - 0xfe0101ff, 0xfffcfafb, 0x030401ff, 0x02010002, - 0x030200ff, 0x01000001, 0x000100ff, 0x00ffff00, - 0x02020100, 0x01fffe00, 0xfefffffe, 0x080602ff, - 0xfdfeffff, 0x020100fe, 0xff0000ff, 0xffff00ff, - 0x01010102, 0x00000001, 0x01010000, 0x01ffff01, - 0x020200ff, 0x03fefdff, 0x00030200, 0x04fef9fb, - 0x000000ff, 0xfdfdfeff, 0xfeff00ff, 0xfefefefe, - 0x00000101, 0xff000201, 0x02010201, 0x00020605, - 0x00fdfcfe, 0xfd000202, 0x01000103, 0xfdfe0102, - 0x00000103, 0xff000000, 0xfefeff01, 0x030301ff, - 0x02010203, 0xfe010304, 0xfdfcfcfe, 0xfdfe00ff, - 0xffff0001, 0xff000100, 0x00000203, 0x00010100, - 0x00000101, 0x00000000, 0x02030302, 0x01010202, - 0xfdfeff00, 0xfcfbfbfb, 0xff000101, 0x03030100, - 0x00fefaf7, 0x02020101, 0x0201fefa, 0x01000101, - 0x020201fe, 0x01010101, 0x01020200, 0x01010100, - 0x00000001, 0x00ff0000, 0x00000000, 0x00fefdff, - 0xfefdfdfd, 0x090703ff, 0x02020201, 0xfdfcfe00, - 0xfffe0002, 0xfaff0403, 0xfdfe0001, 0x000303ff, - 0x00030300, 0x0101fffe, 0x0203fffa, 0x0100feff, - 0xfe000305, 0x010200fd, 0x02020101, 0xf9fcfe00, - 0x0201fefd, 0xfcff0102, 0xfe000202, 0x020200fe, - 0xfdfe0000, 0x0000fffe, 0x00000000, 0x02020000, - 0x0100fffe, 0x03020100, 0x0000fefc, 0x030200ff, - 0xfffefefe, 0x040200ff, 0x00000000, 0x0100ffff, - 0xffffff00, 0x0000ffff, 0x00020406, 0xfffffeff, - 0x01010100, 0xf6fbff01, 0x01010101, 0xfc000101, - 0x01010001, 0xff010101, 0x01010102, 0x00000000, - 0x030401fd, 0x00ff0103, 0x000100fc, 0x000000ff, - 0x010200fb, 0xff000101, 0xfe0102ff, 0xff00fffe, - 0x03050402, 0x0201ff00, 0x00010000, 0xfffffefe, - 0xfefefefe, 0x00fffefd, 0x00010000, 0x02010000, - 0xfdfefe00, 0xff0202ff, 0x00000001, 0xfe030501, - 0xff00ffff, 0xfb000200, 0x000100ff, 0xfe020200, - 0xffff0103, 0x02010100, 0x01000001, 0x01010101, - 0x01fef8f6, 0x01010102, 0x010201ff, 0x00000000, - 0x0100ffff, 0x01020202, 0x00ffffff, 0xfcfbfdff, - 0x01020101, 0x02000001, 0xfffffeff, 0x040200ff, - 0x00fbf9fd, 0x00000002, 0x01feff03, 0x02010102, - 0x01fffe01, 0x01000102, 0x0300ff00, 0xffffff02, - 0x00010102, 0x00000000, 0x03fef9f7, 0x01010203, - 0xfe000203, 0x0101fffe, 0x0000ff00, 0x00000101, - 0x0101fffe, 0x00000001, 0xfe010201, 0x0201fdfc, - 0xfe010201, 0x010300fd, 0x0000ffff, 0xfc000301, - 0x01ff0002, 0x03fefe02, 0x02ff0002, 0x01fcfe03, - 0x01010100, 0xfefafe02, 0x000000ff, 0xfffe0002, - 0x0201ffff, 0xfefdfe01, 0xfffeff03, 0x020100ff, - 0x0000040a, 0xfffefeff, 0xfffeff03, 0x00ffff00, - 0x010702fb, 0x0001fefc, 0xff0302fe, 0x000200fd, - 0x00000102, 0xfeff0101, 0xfffefe01, 0x0000feff, - 0xf9fe0300, 0x000003ff, 0xfbfd0301, 0x00ff0302, - 0xfefe0200, 0x00fe0204, 0x00ff01ff, 0x01feff02, - 0xfcfd0004, 0x010201fe, 0x05030000, 0xfeff0103, - 0xff010101, 0x0101fffd, 0xfefeff01, 0xfeff0000 +static const int8 s_svq1IntraCodebook8x4[3072] = { + 5, 6, 6, 6, 7, 7, 8, 8, 0, 0, 0, 0, 0, 1, 2, 3, + -3, -4, -4, -5, -5, -4, -3, -2, -4, -4, -4, -5, -4, -4, -3, -3, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 4, 4, 5, 5, 5, + -1, 0, 1, 1, 2, 3, 4, 4, -9,-10, -9, -9, -8, -7, -6, -5, + -4, -4, -5, -6, -6, -7, -7, -7, 0, -1, -2, -2, -3, -3, -4, -4, + 4, 4, 3, 3, 2, 1, 1, 0, 7, 7, 7, 6, 6, 5, 4, 4, + 2, 4, 5, 6, 4, 1, -3, -6, 3, 4, 5, 5, 4, 0, -5, -8, + 2, 3, 4, 4, 2, -2, -7,-10, 2, 2, 2, 1, 0, -4, -9,-12, + -9, -7, -3, 1, 4, 4, 3, 3,-10, -7, -2, 3, 5, 5, 3, 3, + -9, -6, -2, 3, 6, 5, 4, 3, -8, -6, -1, 3, 4, 4, 3, 2, + -5, -5, -5, -5, -3, 1, 4, 7, -5, -5, -5, -4, -2, 1, 6, 8, + -4, -5, -4, -3, -1, 3, 8, 10, -3, -4, -3, -2, 1, 5, 9, 11, + -2, -2, -2, -2, -2, -2, -2, -2, -4, -5, -5, -5, -5, -5, -5, -4, + -3, -4, -4, -4, -4, -4, -4, -3, 9, 10, 10, 11, 11, 11, 10, 10, + 7, 4, 1, -2, -4, -6, -9,-10, 9, 7, 3, 0, -2, -4, -8, -9, + 11, 8, 4, 2, 0, -3, -6, -8, 11, 9, 5, 3, 1, -2, -5, -7, + -13,-13,-13,-12,-11,-10, -8, -8, 0, 1, 2, 3, 4, 4, 4, 3, + 3, 4, 5, 6, 6, 6, 5, 4, 3, 4, 4, 4, 3, 3, 3, 2, + 10, 10, 11, 10, 9, 9, 8, 7, 6, 6, 6, 6, 5, 4, 3, 2, + 0, 0, 0, -1, -2, -3, -4, -4,-10,-10,-11,-12,-13,-14,-14,-14, + 16, 16, 17, 16, 15, 13, 12, 11, -1, -2, -3, -4, -4, -4, -4, -3, + -4, -5, -6, -6, -6, -6, -6, -6, -5, -6, -6, -6, -6, -6, -5, -5, + -13,-13,-13,-12,-11,-10, -8, -6, -9, -8, -7, -6, -4, -2, 0, 1, + -2, -1, 1, 3, 5, 7, 8, 9, 5, 7, 9, 11, 13, 14, 15, 15, + 16, 14, 11, 7, 2, -3, -7, -9, 14, 12, 8, 3, -1, -6, -9,-11, + 11, 9, 4, 0, -4, -8,-11,-13, 8, 5, 1, -3, -6,-10,-12,-14, + -18,-15, -9, -3, 1, 6, 9, 11,-17,-13, -7, -1, 3, 7, 11, 12, + -15,-11, -5, 1, 5, 9, 12, 13,-13, -9, -3, 2, 5, 9, 11, 13, + 22, 21, 19, 15, 10, 3, -4, -9, 20, 18, 15, 9, 2, -5,-12,-17, + 16, 13, 8, 1, -7,-14,-20,-24, 10, 6, -1, -8,-15,-21,-25,-27, + -25,-23,-20,-14, -7, 1, 9, 14,-23,-21,-16, -9, 0, 9, 16, 21, + -20,-16,-10, -1, 8, 16, 22, 25,-15,-11, -3, 6, 14, 20, 25, 27, + -4, -2, 0, 1, 2, 2, 2, 2, -5, -2, 0, 2, 3, 3, 3, 3, + -6, -4, -1, 1, 2, 3, 3, 3, -7, -5, -2, 0, 1, 1, 2, 2, + 2, 1, 1, 1, 1, 0, -2, -3, 3, 3, 2, 1, 0, -1, -3, -4, + 4, 3, 2, 1, 0, -2, -4, -6, 5, 4, 3, 1, -1, -3, -5, -6, + 5, 6, 6, 4, 2, 0, -2, -3, 3, 4, 4, 4, 3, 1, 0, -1, + -2, -2, -1, -1, -1, -1, -2, -2, -5, -4, -3, -2, -2, -2, -3, -3, + -1, -1, -1, -1, -1, -1, -1, -1, -3, -4, -4, -4, -3, -3, -3, -3, + -1, -1, -1, -1, -1, -1, -1, -2, 5, 6, 6, 6, 6, 5, 4, 3, + 4, 4, 4, 4, 4, 5, 6, 7, 0, -1, -1, -1, -1, 0, 1, 2, + -2, -3, -3, -3, -3, -2, -1, 0, -3, -3, -4, -4, -4, -3, -2, -1, + 0, -2, -4, -4, -2, 0, 2, 3, 0, -2, -3, -3, -1, 2, 4, 5, + -1, -2, -4, -3, 0, 3, 5, 6, -2, -3, -4, -3, -1, 2, 4, 5, + 9, 4, 0, -3, -3, -1, 0, 1, 8, 4, -1, -4, -3, -1, 1, 2, + 6, 2, -3, -5, -4, -2, 0, 1, 5, 1, -3, -4, -4, -2, 0, 1, + 5, 3, 1, -1, -4, -8,-10,-10, 3, 3, 2, 1, 0, -2, -3, -4, + 1, 1, 1, 2, 3, 2, 1, 0, -1, 0, 1, 2, 3, 4, 3, 2, + 0, 1, 2, 2, 1, -1, -3, -3, 0, 1, 1, 1, -1, -2, -4, -3, + -3, -3, -3, -3, -3, -3, -1, 2, -4, -4, -3, 0, 3, 7, 12, 14, + -5, -5, -6, -6, -6, -6, -6, -5, 2, 2, 2, 1, 0, 0, 0, 0, + 4, 4, 3, 2, 1, 0, 0, 0, 6, 6, 5, 4, 2, 2, 1, 1, + -7, -7, -6, -3, 0, 4, 7, 8, -1, -2, -3, -3, -2, -1, 1, 2, + 3, 3, 1, -1, -2, -2, -2, -1, 6, 6, 4, 2, 0, -2, -2, -2, + -6, -5, -2, 2, 5, 9, 11, 12, -4, -4, -2, 0, 2, 4, 5, 6, + -3, -2, -2, -2, -2, -1, 0, 1, -2, -2, -2, -3, -3, -3, -3, -2, + -7, -3, 1, 3, 3, 0, -3, -5, -6, -2, 3, 5, 4, 1, -3, -5, + -5, -1, 4, 6, 5, 2, -3, -4, -4, 0, 5, 7, 6, 3, -1, -3, + 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -3, -3, -3, -3, -2, -1, + 6, 7, 8, 9, 9, 8, 7, 6, -4, -4, -5, -5, -6, -6, -5, -4, + -9, -8, -6, -4, 0, 3, 6, 6, -5, -4, -1, 3, 5, 6, 5, 3, + 1, 3, 6, 6, 4, 1, -2, -5, 6, 7, 5, 1, -3, -7,-10,-11, + 10, 9, 5, 1, -3, -6, -6, -4, 5, 3, -1, -5, -6, -5, -2, 2, + -2, -4, -6, -6, -4, 1, 6, 10, -6, -7, -7, -4, 1, 7, 11, 12, + 6, 5, 3, 2, 0, 0, 0, 0, 2, 1, -1, -2, -3, -2, -1, -1, + 0, -1, -2, -4, -4, -2, -1, 1, 0, 0, -1, -2, -1, 0, 2, 3, + 0, -1, -2, -2, -2, -2, -1, -1, 5, 4, 2, 1, 0, 0, 0, 0, + 6, 5, 3, 1, 0, 0, 0, 0, 2, 0, -2, -4, -4, -3, -2, -2, + -7, -4, 0, 2, 2, 2, 2, 1, -7, -3, 0, 0, 0, 0, 0, 0, + -4, -1, 1, 1, 0, 0, 0, 1, -1, 1, 2, 2, 2, 2, 3, 3, + -2, 0, 2, 2, 1, 1, 1, 1, -1, 1, 2, 2, 1, 0, 0, -1, + 0, 2, 4, 2, 0, -1, -2, -3, 1, 2, 3, 1, -2, -4, -6, -6, + 1, 2, 2, 4, 5, 6, 4, 1, 0, -1, -1, -1, 0, 0, -2, -4, + 0, 0, -1, -2, -2, -2, -4, -6, 2, 1, 0, 0, 1, 1, -1, -3, + 1, 1, 1, 1, 1, 2, 3, 3, 0, 0, 1, 0, 1, 2, 4, 4, + -1, -1, -1, -1, 0, 1, 2, 3, -4, -4, -5, -5, -5, -3, -1, 0, + -6, -5, -5, -4, -3, -2, -1, -1, -1, 0, 0, 1, 1, 2, 3, 3, + 0, 1, 1, 1, 2, 2, 3, 4, 0, 0, -1, -1, 0, 1, 2, 3, + 0, 1, 1, 1, 0, 0, -1, -1, 1, 3, 3, 2, 1, -1, -2, -2, + -2, 0, 2, 2, 2, 2, 1, 1, -9, -8, -4, -2, 1, 3, 3, 3, + -1, -1, -1, -2, -3, -3, -3, -4, 0, 0, 0, -1, -2, -2, -3, -3, + 2, 2, 2, 0, -1, -1, -1, -1, 5, 5, 4, 3, 2, 2, 2, 2, + 6, 3, -1, -4, -3, -1, 1, 1, 2, -1, -3, -4, -1, 2, 2, 0, + -1, -2, -2, 1, 4, 4, 1, -3, -2, -1, 1, 4, 6, 3, -3, -8, + 3, 3, 2, 1, -1, -2, -2, -2, -4, -4, -2, -1, 1, 3, 4, 4, + -4, -5, -5, -4, -2, 0, 2, 2, 7, 7, 4, 1, -1, -2, -3, -2, + -1, 1, 3, 0, -4, -6, 0, 6, -2, 1, 4, 1, -4, -6, -1, 7, + -3, 1, 4, 2, -3, -6, -1, 6, -2, 0, 3, 2, -2, -5, -1, 4, + 1, -1, -2, 1, 4, 4, -1, -7, 1, -1, -4, -1, 5, 6, 0, -6, + 3, 0, -4, -3, 3, 6, 2, -4, 3, 0, -5, -4, 1, 4, 1, -3, + 2, 2, 3, 3, 3, 3, 2, 2, -4, -5, -6, -7, -7, -7, -7, -6, + 1, 2, 3, 3, 3, 3, 2, 2, 0, 0, 1, 1, 1, 2, 2, 1, + 3, -3, -3, 3, 4, -2, -2, 2, 3, -4, -4, 4, 4, -4, -4, 2, + 4, -4, -4, 4, 4, -4, -3, 3, 3, -3, -4, 3, 3, -3, -3, 3, + -2, -2, -2, -2, -2, -2, -1, -1, 6, 7, 8, 8, 8, 7, 6, 5, + -5, -6, -7, -7, -8, -7, -6, -5, 1, 1, 2, 2, 2, 2, 1, 1, + 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, + -2, -3, -2, -2, -2, -3, -3, -3, 2, 3, 5, 6, 4, 2, 1, 0, + 8, 6, 2, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, -1, -1, -1, + 1, -1, 0, 0, 0, -1, -2, -3, -2, -2, -1, 0, 0, -2, -4, -5, + 3, 1, -1, -2, -3, -4, -5, -5, 2, 1, 0, 0, 1, 1, 0, 0, + 0, -1, -1, 0, 2, 2, 2, 2, -1, -2, -1, 1, 2, 2, 2, 2, + 0, -1, -2, -1, -1, -1, -1, 0, -1, -2, -2, -1, -1, 0, 0, 1, + 2, 1, 1, 2, 2, 1, 1, 0, 6, 5, 3, 1, 0, -2, -4, -4, + -3, -2, -1, 0, 1, 1, 0, -1, 0, 1, 3, 4, 5, 5, 3, 1, + -1, -1, -1, 0, 1, 0, -1, -2, -2, -2, -2, -1, 0, -1, -2, -3, + 0, -1, -2, -2, -1, -1, 0, 2, 1, -1, -2, -1, -1, -1, 0, 2, + 1, 0, -2, -2, -2, -2, 1, 5, 1, -1, -2, -2, -2, 0, 5, 10, + 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, 0, 0, 0, 1, 2, + 1, 2, 2, 3, 4, 4, 6, 5, -3, -3, -3, -2, -2, -3, -3, -3, + 1, -1, -2, -2, 0, 3, 5, 7, 2, 0, -2, -3, -2, 0, 2, 3, + 3, 1, -2, -3, -3, -2, -1, -1, 3, 1, 0, -1, -1, -1, -1, -1, + 1, 3, 5, 4, 2, -1, -3, -4, -3, -2, 1, 2, 1, 0, -1, -2, + -5, -3, 0, 2, 2, 1, 0, 0, -3, -1, 1, 2, 2, 1, 0, 0, + 0, -1, -1, -1, 1, 2, 3, 4, -3, -4, -4, -3, -1, 0, 0, 1, + -2, -3, -2, -1, 1, 1, 1, 1, -2, -2, 0, 3, 4, 4, 3, 2, + -4, -4, -3, -2, -1, 1, 2, 3, 0, 1, 1, 1, -1, -2, -3, -3, + 3, 4, 5, 4, 2, -1, -3, -3, -2, -2, 0, 2, 2, 2, 1, 0, + -4, 0, 5, 7, 4, -1, -4, -4, -1, 2, 4, 3, 0, -3, -3, -2, + 2, 1, 0, -1, -2, -2, 0, 1, 0, 0, -1, -2, -2, -1, 1, 2, + -4, -3, -2, -1, 0, 1, 2, 2, 10, 9, 5, 0, -3, -4, -3, -2, + 1, -1, -2, -2, -1, 0, 0, 0, -2, -2, -1, 1, 1, 1, 0, -1, + -5, -3, 0, 3, 4, 2, 0, -2, -2, -1, 0, 1, 1, 0, -1, -1, + 3, 2, -1, -2, -2, -1, 1, 1, 7, 5, -1, -5, -6, -2, 2, 4, + -2, 3, 3, -3, -4, 1, 2, -2, -3, 3, 4, -3, -4, 2, 3, -2, + -3, 3, 4, -3, -4, 2, 3, -2, -4, 2, 4, -2, -3, 1, 2, -1, + 4, 3, -1, -3, -3, -1, 1, 2, -4, -6, -4, 0, 4, 5, 4, 1, + 0, 2, 5, 6, 2, -3, -5, -4, 1, 1, -1, -3, -5, -2, 2, 4, + -1, 0, 1, 2, 2, 3, 3, 4, -1, 0, 1, 1, 0, -1, -1, -1, + -1, 0, 1, 2, 2, 1, -1, -2, -3, -2, -1, 0, 0, -1, -2, -3, + 1, 1, 1, 1, 0, 0, 1, 2, 1, 0, -1, 0, 0, 1, 1, 0, + 1, -2, -4, -1, 1, 2, 1, 0, 1, -4, -7, -3, 1, 3, 2, 1, + 1, 1, 1, 1, 1, 1, 0, -1, 1, 1, 1, 0, 1, 2, 2, 0, + 1, 1, 0, 0, 0, 2, 0, -3, 3, 2, 0, -1, -1, -2, -6, -9, + 0, 0, 0, 1, 0, 0, 1, 2, 1, 0, 0, 0, -1, -1, 0, 2, + 0, 1, 1, 1, -1, -3, -2, 0, -7, -5, 1, 6, 6, 2, -1, -1, + 3, 1, -1, -3, -4, -2, 1, 4, 2, 0, -2, -3, -4, -3, -1, 2, + 2, 2, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, + -1, 1, 1, -2, -5, -6, -4, -1, -1, 1, 4, 3, 2, 0, 1, 2, + -1, 0, 2, 3, 1, 0, 0, 1, -1, 0, 1, 0, 0, -1, -1, 0, + 0, 1, 2, 2, 0, -2, -1, 1, -2, -1, -1, -2, -1, 2, 6, 8, + -1, -1, -2, -3, -2, 0, 1, 2, -1, 0, 0, -1, -1, 0, -1, -1, + 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, -1, -1, 1, + -1, 0, 2, 2, -1, -3, -2, 3, 0, 2, 3, 0, -5, -7, -2, 4, + -1, 0, 0, 0, -1, -2, -3, -3, -1, 0, -1, -2, -2, -2, -2, -2, + 1, 1, 0, 0, 1, 2, 0, -1, 1, 2, 1, 2, 5, 6, 2, 0, + -2, -4, -3, 0, 2, 2, 0, -3, 3, 1, 0, 1, 2, 1, -2, -3, + 3, 1, 0, 0, 0, 0, 0, -1, 1, -1, -2, -2, -1, 1, 3, 3, + 3, 2, 1, 2, 4, 3, 1, -2, -2, -4, -4, -3, -1, 0, -2, -3, + 1, 0, -1, -1, 0, 1, 0, -1, 3, 2, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 2, 3, 3, 2, 2, 2, 1, 1, + 0, -1, -2, -3, -5, -5, -5, -4, 1, 1, 0, -1, 0, 1, 3, 3, + -9, -6, -2, 0, 1, 1, 2, 2, -6, -2, 1, 2, 1, 1, 0, 1, + -2, 1, 2, 2, 1, 1, 1, 1, 0, 2, 2, 1, 0, 1, 1, 1, + 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -3, -2, 0, + -3, -3, -3, -2, -1, 3, 7, 9, 1, 2, 2, 2, 0, -2, -4, -3, + 2, 0, -2, -1, 3, 4, -1, -6, 1, 0, -2, -3, -1, 3, 3, 0, + 0, 3, 3, 0, -2, -1, 1, 1, -6, -1, 3, 2, -1, -2, 0, 1, + 5, 3, 0, -2, -3, 0, 2, 1, 1, 1, 2, 2, 0, -2, -4, -7, + -3, -2, 1, 2, 2, 1, -1, -4, 2, 2, 0, -2, -2, 0, 2, 2, + 0, 0, -2, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + -2, -1, 0, 1, 0, 1, 2, 3, -4, -2, 0, 0, -1, 0, 2, 3, + -2, -2, -2, -1, -1, 0, 2, 4, 0, 0, 0, 0, -1, -1, 0, 1, + 0, -1, -1, -1, -1, -1, 0, 0, 6, 4, 2, 0, -1, -2, -1, -1, + 0, 1, 1, 1, 1, -1, -5,-10, 1, 1, 1, 1, 1, 1, 0, -4, + 1, 0, 1, 1, 1, 1, 1, -1, 2, 1, 1, 1, 0, 0, 0, 0, + -3, 1, 4, 3, 3, 1, -1, 0, -4, 0, 1, 0, -1, 0, 0, 0, + -5, 0, 2, 1, 1, 1, 0, -1, -1, 2, 1, -2, -2, -1, 0, -1, + 2, 4, 5, 3, 0, -1, 1, 2, 0, 0, 1, 0, -2, -2, -1, -1, + -2, -2, -2, -2, -3, -2, -1, 0, 0, 0, 1, 0, 0, 0, 1, 2, + 0, -2, -2, -3, -1, 2, 2, -1, 1, 0, 0, 0, 1, 5, 3, -2, + -1, -1, 0, -1, 0, 2, 0, -5, -1, 0, 1, 0, 0, 2, 2, -2, + 3, 1, -1, -1, 0, 1, 1, 2, 1, 0, 0, 1, 1, 1, 1, 1, + -10, -8, -2, 1, 2, 1, 1, 1, -1, 1, 2, 1, 0, 0, 0, 0, + -1, -1, 0, 1, 2, 2, 2, 1, -1, -1, -1, 0, -1, -3, -5, -4, + 1, 1, 2, 1, 1, 0, 0, 2, -1, -2, -1, -1, -1, 0, 2, 4, + -3, -7, -5, 0, 2, 0, 0, 0, 3, -1, -2, 1, 2, 1, 1, 2, + 1, -2, -1, 1, 2, 1, 0, 1, 0, -1, 0, 3, 2, -1, -1, -1, + 2, 1, 1, 0, 0, 0, 0, 0, -9, -7, -2, 3, 3, 2, 1, 1, + 3, 2, 0, -2, -2, -1, 1, 1, 0, -1, 0, 0, 1, 1, 0, 0, + -2, -1, 1, 1, 1, 0, 0, 0, 1, 2, 1, -2, -4, -3, 1, 2, + 1, 2, 1, -2, -3, 0, 3, 1, -1, -1, 0, 0, 1, 3, 0, -4, + 2, 0, -1, 1, 2, -2, -2, 3, 2, 0, -1, 2, 3, -2, -4, 1, + 0, 1, 1, 1, 2, -2, -6, -2, -1, 0, 0, 0, 2, 0, -2, -1, + -1, -1, 1, 2, 1, -2, -3, -2, 3, -1, -2, -1, -1, 0, 1, 2, + 10, 4, 0, 0, -1, -2, -2, -1, 3, -1, -2, -1, 0, -1, -1, 0, + -5, 2, 7, 1, -4, -2, 1, 0, -2, 2, 3, -1, -3, 0, 2, 0, + 2, 1, 0, 0, 1, 1, -1, -2, 1, -2, -2, -1, -1, -2, 0, 0, + 0, 3, -2, -7, -1, 3, 0, 0, 1, 3, -3, -5, 2, 3, -1, 0, + 0, 2, -2, -2, 4, 2, -2, 0, -1, 1, -1, 0, 2, -1, -2, 1, + 4, 0, -3, -4, -2, 1, 2, 1, 0, 0, 3, 5, 3, 1, -1, -2, + 1, 1, 1, -1, -3, -1, 1, 1, 1, -1, -2, -2, 0, 0, -1, -2 }; -static const uint32 s_svq1IntraCodebook8x8[1536] = { - 0x02030404, 0xff000102, 0x02030304, 0xffff0001, - 0x02020303, 0xfeff0001, 0x01020203, 0xfdfeff00, - 0x00010202, 0xfdfeffff, 0x00000102, 0xfcfdfeff, - 0xff000001, 0xfcfcfdfe, 0xfeff0000, 0xfcfcfdfe, - 0x03030302, 0x03030303, 0x02020202, 0x03030202, - 0x02020201, 0x02020202, 0x01010100, 0x01010101, - 0x000000ff, 0x01010000, 0xfffffefe, 0xffffffff, - 0xfdfdfdfd, 0xfefefdfd, 0xfcfcfcfb, 0xfdfcfcfc, - 0x00fffefc, 0x03020201, 0x00fffefc, 0x03030201, - 0x00fffdfc, 0x03030201, 0x00fffdfc, 0x03030201, - 0x00fffdfb, 0x03030201, 0x00fffdfb, 0x03030201, - 0x00fffdfb, 0x03020101, 0xfffefdfb, 0x03020100, - 0x05050404, 0x07070606, 0x03020202, 0x04040403, - 0x00000000, 0x02010101, 0xfefefefe, 0x00ffffff, - 0xfefefefe, 0xfefefefe, 0xfefefefe, 0xfefefefe, - 0xfefefeff, 0xfefefefe, 0xffffffff, 0xfefefefe, - 0xff010305, 0xfdfdfdfe, 0xff010305, 0xfdfdfdfe, - 0xff010305, 0xfdfdfdfe, 0xff010305, 0xfdfdfdfe, - 0x00010405, 0xfdfdfdfe, 0x00020406, 0xfdfdfefe, - 0x00020406, 0xfdfefeff, 0x01020406, 0xfefefeff, - 0x030301ff, 0xfafd0002, 0x040301ff, 0xfafd0003, - 0x040401ff, 0xfafd0103, 0x040301ff, 0xfafd0103, - 0x040301fe, 0xfafd0103, 0x040301fe, 0xf9fd0103, - 0x030301fe, 0xf9fd0002, 0x030200fe, 0xfafd0002, - 0x0608090a, 0x04040506, 0x03040506, 0x01020202, - 0xff000102, 0xfffefefe, 0xfcfdfeff, 0xfdfcfcfc, - 0xfcfcfdfe, 0xfdfcfcfb, 0xfdfdfefe, 0xfefefdfd, - 0xffffffff, 0x00ffffff, 0x01010101, 0x02010101, - 0x0201fffe, 0x08070504, 0x0100fefd, 0x08070503, - 0x00fffdfc, 0x07060402, 0xfffefcfb, 0x07050301, - 0xfefdfbfa, 0x06040200, 0xfefcfbfa, 0x050301ff, - 0xfdfbfaf9, 0x030200fe, 0xfcfbf9f8, 0x0201fffd, - 0x0507090b, 0xffff0103, 0x0306080a, 0xfefe0001, - 0x02050709, 0xfcfdfe00, 0x01030608, 0xfcfcfdff, - 0xff020406, 0xfbfbfcfd, 0xfe000305, 0xfafafbfc, - 0xfdff0103, 0xf9f9fafb, 0xfcfe0002, 0xf9f9fafa, - 0x07070605, 0x08080807, 0x05050403, 0x06060606, - 0x03020200, 0x05040404, 0x0100fffe, 0x03030202, - 0xfffefdfc, 0x02010100, 0xfdfcfbfa, 0x00fffefe, - 0xfafaf9f8, 0xfdfdfcfb, 0xf8f8f7f6, 0xfbfafaf9, - 0x01030506, 0xf8fafdff, 0x02040506, 0xf8fafdff, - 0x02040506, 0xf8fafd00, 0x02040506, 0xf8fafd00, - 0x02040606, 0xf8fafd00, 0x02040506, 0xf8fafd00, - 0x02040506, 0xf8fafd00, 0x02040506, 0xf8fbfdff, - 0x08090a0b, 0x04050607, 0x06070808, 0x02030405, - 0x04040506, 0x00010202, 0x01020303, 0xfeff0000, - 0xff000101, 0xfdfdfefe, 0xfdfeffff, 0xfbfbfcfc, - 0xfbfcfcfd, 0xf9f9fafa, 0xf9fafbfb, 0xf8f8f8f8, - 0xf5f4f3f2, 0xfcfaf9f7, 0xf7f6f5f4, 0xfffdfbf9, - 0xfaf9f7f6, 0x0200fefd, 0xfefcfaf8, 0x05040200, - 0x0200fdfb, 0x08070504, 0x040200fe, 0x0a090806, - 0x07050300, 0x0c0b0a08, 0x08070503, 0x0c0c0b0a, - 0xeeeeeded, 0xf2f1f0ef, 0xf3f2f1f1, 0xf7f6f5f4, - 0xf8f7f6f5, 0xfdfcfbfa, 0xfefdfbfa, 0x020100ff, - 0x030200ff, 0x06060504, 0x08070604, 0x0a0a0a09, - 0x0c0b0a09, 0x0e0e0e0d, 0x0f0e0e0c, 0x10101010, - 0x11131516, 0x05090b0e, 0x0e111314, 0x0104080b, - 0x0a0d0f11, 0xfc000306, 0x05080b0d, 0xf7fbfe01, - 0xff030609, 0xf3f5f9fc, 0xfafd0004, 0xeff1f4f7, - 0xf5f8fbfe, 0xeceef0f2, 0xf0f3f6f8, 0xeaebedef, - 0x12121211, 0x0e101011, 0x0f0f1010, 0x0b0c0d0e, - 0x0a0b0c0c, 0x05070809, 0x04060607, 0xff010203, - 0xfeff0001, 0xfafbfcfd, 0xf8f9fafb, 0xf4f5f6f7, - 0xf2f3f4f5, 0xeff0f0f1, 0xeeefeff0, 0xecececed, - 0x00000000, 0xfdfeffff, 0x00000001, 0xfdfeff00, - 0x00000101, 0xfefeffff, 0x00010101, 0xfeffff00, - 0x01010102, 0xfeffff00, 0x01010202, 0xfeff0000, - 0x01010202, 0xffff0001, 0x01010202, 0xfe000001, - 0x00ffff00, 0x03020100, 0x00ffff00, 0x02020101, - 0xffffffff, 0x02020100, 0xfffeffff, 0x02010100, - 0xfffefeff, 0x02010000, 0xfefefeff, 0x020100ff, - 0xfffeffff, 0x02010000, 0xffffffff, 0x02010100, - 0x02020203, 0x00000101, 0x02020203, 0x00000102, - 0x01020202, 0x00000101, 0x01010202, 0xff000001, - 0x00010101, 0xffff0000, 0xffff0000, 0xffffffff, - 0xfefefefe, 0xfefefefe, 0xfdfdfdfe, 0xfefefefe, - 0x00000205, 0x000000ff, 0xff000204, 0xff00ffff, - 0xffff0104, 0xfffffffe, 0xffff0104, 0xfffffffe, - 0xfeff0104, 0xfffffffe, 0xfeff0104, 0xfffffffe, - 0xffff0104, 0xffffffff, 0xff000204, 0xff000000, - 0x0100fffe, 0x01010101, 0x0100fffd, 0x01010101, - 0x0100fffd, 0x01010101, 0x0100fffd, 0x01010101, - 0x0100fefd, 0x01010202, 0x0100fefc, 0x02020202, - 0x01fffdfb, 0x02010201, 0x00fefdfb, 0x01010101, - 0x00010303, 0xfbfcfcfe, 0x00020303, 0xfcfdfeff, - 0x01010202, 0xfefeff00, 0x01010101, 0x00000001, - 0x01000000, 0x01010101, 0x00fffffe, 0x02020100, - 0xfffefefd, 0x03020100, 0xfffefdfd, 0x03020100, - 0xfdfdfdfd, 0xfefefefd, 0xfefefdfd, 0xfffffffe, - 0xfffefefe, 0xffffffff, 0x00ffffff, 0x00000000, - 0x00000000, 0x01010101, 0x01010000, 0x02020202, - 0x02010101, 0x03030302, 0x02020202, 0x03030303, - 0xfdfbf9f8, 0xff00fffe, 0x00fffdfc, 0x01010201, - 0x030201ff, 0x01020203, 0x03030201, 0x00010202, - 0x02030302, 0xff000001, 0x00010201, 0xffffffff, - 0xff000101, 0xfffefeff, 0x00000101, 0xff00ffff, - 0x00fefdfc, 0x03030201, 0x00fefdfc, 0x02020201, - 0xfffefdfd, 0x01010100, 0xfffefefe, 0x000000ff, - 0xffffff00, 0xffffffff, 0x00010102, 0xfeffff00, - 0x01030303, 0xfefeff00, 0x02040405, 0xfeff0001, - 0x00000000, 0x03030201, 0x0000ff00, 0x03030201, - 0x0000ff00, 0x02030201, 0x01000000, 0x02020201, - 0x01010102, 0x00010101, 0x01020202, 0xfeff0000, - 0x00000102, 0xfafbfdfe, 0xfdffff00, 0xf7f8fafb, - 0x020100fe, 0xfcff0102, 0x020200fe, 0xfcff0102, - 0x020200fe, 0xfdff0102, 0x020200fe, 0xfdff0102, - 0x0202fffe, 0xfdff0102, 0x0201fffe, 0xfdff0102, - 0x0201fffd, 0xfdff0102, 0x0201fffe, 0xfdff0102, - 0xff0101ff, 0x0400fdfd, 0xff0101ff, 0x0400fdfd, - 0x000101ff, 0x0400fdfd, 0x000201ff, 0x0500fdfd, - 0x00020100, 0x0400fcfd, 0x00020100, 0x0500fcfd, - 0x00020100, 0x0400fdfd, 0xff020100, 0x0400fefe, - 0x06050606, 0x05050505, 0x02020202, 0x02020202, - 0x00000000, 0x00000000, 0xffffffff, 0xfefefefe, - 0xfefefefe, 0xfefefefe, 0xfefefefe, 0xfefefefe, - 0xfffeffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x02020202, 0x02020202, 0x00010100, 0x00000000, - 0xfefefeff, 0xfffefefe, 0xfdfdfdfd, 0xfefdfdfd, - 0xfdfcfcfd, 0xfefefdfd, 0xfefefefe, 0x0000ffff, - 0x01010100, 0x03030202, 0x05040403, 0x06060605, - 0xfdfe0104, 0x0301fffd, 0xfcfe0104, 0x0301fffd, - 0xfcfe0105, 0x0401fffd, 0xfdfe0105, 0x0402fffd, - 0xfdfe0105, 0x0402fffd, 0xfcfd0004, 0x0402fffd, - 0xfdfd0004, 0x0301fffd, 0xfdfe0003, 0x0301fffe, - 0xfcfcfcfd, 0xfcfcfcfc, 0xffffffff, 0xfefeffff, - 0x02010102, 0x01010102, 0x04030303, 0x03030304, - 0x04030303, 0x03030404, 0x02010201, 0x02020202, - 0xfffefefe, 0x0000ffff, 0xfcfcfcfc, 0xfdfdfdfd, - 0xfdfdfeff, 0x00fffefe, 0xfefeff00, 0x0100fffe, - 0xffff0102, 0x0100ffff, 0xff000103, 0x010000ff, - 0xff000203, 0x01000000, 0xff000103, 0x01000000, - 0xff000103, 0x01000000, 0x00000102, 0x01000000, - 0x01000000, 0x04030201, 0x00ff0000, 0x03020000, - 0xffffff00, 0x0100ffff, 0xffffff00, 0x00ffffff, - 0xffff0000, 0xfffefeff, 0xff000001, 0xfffefeff, - 0x00010202, 0xffffffff, 0x01020303, 0x00ffff00, - 0x00010001, 0xfffeff00, 0x00000000, 0xfffeffff, - 0x0000ff00, 0xffffffff, 0x00ffffff, 0x00000000, - 0x00ffffff, 0x01010000, 0x00ffffff, 0x03020101, - 0x00fffefe, 0x04030201, 0x00fffefe, 0x05040201, - 0x0001fffd, 0x0100ff00, 0x000100fd, 0x0200ffff, - 0x000100fd, 0x0200ffff, 0x000201fe, 0x0200ffff, - 0x000201fe, 0x0200ffff, 0x000201fe, 0x0200ffff, - 0x000202ff, 0x0200ffff, 0x000101ff, 0x01ffffff, - 0x01fffefe, 0x01030403, 0x00fffefe, 0x00020302, - 0x00fffefe, 0xff010201, 0x00ffffff, 0xff010201, - 0x00ffffff, 0xfe000101, 0x00ffff00, 0xff000101, - 0x00ffff00, 0xff010101, 0x00ffff00, 0xff000100, - 0x0100fffe, 0x01010101, 0x0000fffe, 0x00000000, - 0x00fffffe, 0xfefeffff, 0xfffffffe, 0xfdfefeff, - 0x010100ff, 0xfefeff00, 0x03030201, 0x00000102, - 0x03030201, 0x00010203, 0x01010000, 0x00000101, - 0xffffff00, 0x00000000, 0x00000001, 0x01010000, - 0x01010101, 0x01010101, 0x02020101, 0x01010101, - 0x01010101, 0x01010101, 0x010000ff, 0x00000001, - 0xfffffefd, 0xff00ffff, 0xfdfcfbfb, 0xfffefefe, - 0x01010101, 0xff000102, 0x02010101, 0xff000101, - 0x01010101, 0xfe000101, 0x01010102, 0xfe000101, - 0x00000101, 0xfdff0000, 0x00000101, 0xfdfeff00, - 0x00000101, 0xfcfeffff, 0xff000001, 0xfcfdfefe, - 0x03050708, 0x01010102, 0x00000102, 0xfffeffff, - 0xfeffffff, 0xfffefefe, 0xffffffff, 0x00ffff00, - 0x01000000, 0x00000001, 0x01010000, 0x00000001, - 0x000000ff, 0xffff0000, 0xfffffefe, 0xfffefeff, - 0xfe000409, 0xfffffefe, 0xfeff0207, 0x0000fffe, - 0xfefe0004, 0x010100ff, 0xfefefe01, 0x010100ff, - 0xfffefeff, 0x01010100, 0x00fffeff, 0x00010101, - 0x0100ffff, 0xff000101, 0x0100ff00, 0xffff0000, - 0x01010100, 0x00000101, 0x02020201, 0x00000001, - 0x02020202, 0xffff0001, 0x00010101, 0xfefefeff, - 0xff000000, 0xfefefdfe, 0xfeffffff, 0x00fffefe, - 0xffffffff, 0x02010000, 0x00ffffff, 0x04030201, - 0x0000ffff, 0xfdfdfeff, 0x0000ffff, 0xffffff00, - 0x00fffefe, 0x01010101, 0x00fefefe, 0x03030201, - 0x00ffffff, 0x03030301, 0x00000001, 0x02020101, - 0x00010202, 0xffffff00, 0x00010203, 0xfdfdfeff, - 0xfeffffff, 0xfbfcfdfe, 0xff000000, 0xfcfdfdff, - 0x00010101, 0xfdfeff00, 0x01020202, 0xffff0001, - 0x02020202, 0xff000101, 0x02020202, 0x00000102, - 0x01020101, 0x00000101, 0x01010000, 0xff000000, - 0x010302fe, 0xff0101ff, 0x000302fd, 0xff0101ff, - 0x000302fd, 0xff0101ff, 0x000302fc, 0xfe0101ff, - 0x000301fc, 0xfe0101ff, 0xff0301fc, 0xfe0101fe, - 0x000201fd, 0xfe0101ff, 0x000201fd, 0xff0101ff, - 0xfeffffff, 0xfefefefe, 0x01010101, 0x00000000, - 0x02020201, 0x02020202, 0x01010000, 0x02020201, - 0xfffffefe, 0x000000ff, 0xfdfdfdfd, 0xfefdfdfd, - 0xffffffff, 0xfefefefe, 0x04040404, 0x02030304, - 0xfffefdfd, 0x05020100, 0xfefdfdfd, 0x060301ff, - 0xfefefdfd, 0x05030200, 0xfefefefd, 0x05030100, - 0xfffefefe, 0x050301ff, 0xfffffefe, 0x04020100, - 0xffffffff, 0x04010100, 0xffffffff, 0x03020100, - 0x0100ff00, 0xffff0001, 0x01000000, 0xffff0002, - 0x00ff0001, 0x00000001, 0xfffeff01, 0x00000000, - 0xfffdfe01, 0x01000000, 0xfefdff01, 0x02010100, - 0xfffeff01, 0x02010100, 0x00ff0002, 0x02020101, - 0x01010101, 0x02010000, 0xff0000ff, 0x01000000, - 0xfffffefd, 0x010100ff, 0x00fffefc, 0x01010100, - 0x0000fefd, 0x01010101, 0x0100fffd, 0x00000101, - 0x010100ff, 0xff000001, 0x02020100, 0xff000001, - 0xfdfcfcfc, 0xfffffffe, 0xfffefefe, 0x00000000, - 0x000000ff, 0x01010101, 0x01010000, 0x01010101, - 0x01010000, 0x00010202, 0x01010000, 0x00010101, - 0x01000000, 0x00010101, 0x010000ff, 0x00000101, - 0x02020201, 0xfcfeff01, 0x02020101, 0xfcfe0001, - 0x01010100, 0xfdff0001, 0x010100ff, 0xfeff0000, - 0x010100ff, 0xff000001, 0x0000fffe, 0xff000000, - 0x0100ffff, 0x00000001, 0x010100ff, 0x00010101, - 0xff000202, 0xfefffffe, 0xfeff0101, 0xfefffffe, - 0xfeff0101, 0xff0000fe, 0xfe000101, 0x000101ff, - 0xff000101, 0x010201ff, 0xff000101, 0x010201ff, - 0xff000101, 0x010101ff, 0xff000101, 0x01010100, - 0xfeff0000, 0xfcfcfcfc, 0x02030303, 0x00000001, - 0x03030303, 0x02020202, 0x00000000, 0x01000000, - 0xffffffff, 0x00ffffff, 0x0000ff00, 0x000000ff, - 0x00000000, 0x00000000, 0x00000000, 0x00ffff00, - 0xff00ffff, 0xff0201ff, 0x00000101, 0xff030200, - 0xff000101, 0xff0301ff, 0xfe000101, 0xfe0100fe, - 0xfe000001, 0xfd0100fe, 0x00000000, 0xfd0101ff, - 0x00010100, 0xfd010201, 0x010100ff, 0xfc010201, - 0x0100fdfc, 0x00000101, 0x0100fefc, 0xff000101, - 0x0101fffd, 0xffff0001, 0x010101ff, 0x00ff0001, - 0x01020201, 0x0000ff00, 0x00010202, 0x0100ffff, - 0xff000102, 0x0100fffe, 0xff000202, 0x0101fffe, - 0x00000101, 0xffffffff, 0xffffff00, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffff0000, 0xffffffff, - 0xff000001, 0xffffffff, 0x00000102, 0xffffffff, - 0x01020305, 0x00000000, 0x02030506, 0x00000001, - 0x01030404, 0x01000000, 0x01020303, 0x01000000, - 0x00010202, 0x0100ffff, 0xff000000, 0x0100ffff, - 0xffff0000, 0x0200fffe, 0xfeffff00, 0x0100fefe, - 0xfeffff00, 0x00fffefe, 0xfeff0000, 0x00fffefe, - 0xffff0000, 0x030200ff, 0xfefeff00, 0x0201ffff, - 0xffff0001, 0x000000ff, 0x00010101, 0xffff0000, - 0x00010201, 0xffffff00, 0x000000ff, 0xffffffff, - 0xfffffefd, 0x02010100, 0x01fffdfc, 0x05050302, - 0x00000000, 0x00000000, 0x01010101, 0x01010101, - 0xff000000, 0x01000000, 0xfefeffff, 0x00fffffe, - 0x00000000, 0x01010100, 0x02020202, 0x03030302, - 0x01010101, 0x01010202, 0xfcfcfdfc, 0xfdfdfcfc, - 0x020100ff, 0x03030302, 0xffffffff, 0x00000000, - 0xfeff0000, 0xfefdfdfe, 0x00010203, 0xfefefeff, - 0x01020304, 0x00000001, 0x01010202, 0x01010100, - 0xffffff00, 0x010000ff, 0xfefefefe, 0x0000fffe, - 0x0200ff01, 0x01fffe01, 0x0200ff01, 0x01fefe01, - 0x0300ff01, 0x01fffe02, 0x0300fe00, 0x01fefe02, - 0x0300fe00, 0x01fefe02, 0x0300fe00, 0x01fffe01, - 0x0200fe00, 0x01fefe01, 0x0200ff00, 0x01fffe01, - 0x02020100, 0x02020303, 0x02010100, 0x01020303, - 0x02010000, 0x01020202, 0x010000ff, 0x01010101, - 0x0000ffff, 0x00000000, 0xffffffff, 0xffffffff, - 0xfefefefe, 0xfffefefe, 0xfefefefe, 0xfffefefe, - 0xfeff0000, 0x050300ff, 0xffff0000, 0x040200ff, - 0x00000101, 0x0201ffff, 0x01010201, 0x00ffff00, - 0x01020100, 0xfefeff00, 0x020100ff, 0xfdfd0001, - 0x0201fffe, 0xfcfe0002, 0x0200fffe, 0xfdff0102, - 0x00000000, 0xffff0000, 0x00ff0000, 0x00000000, - 0xffffffff, 0x00000000, 0xffffffff, 0x00ffffff, - 0xffffffff, 0x00ffffff, 0x000000ff, 0x00ffff00, - 0x01010000, 0x01000000, 0x04030303, 0x03030303, - 0xfefe0105, 0xff000000, 0xfffdff04, 0xff000000, - 0x00ffff03, 0xff000101, 0x01000002, 0xfe000101, - 0x01000001, 0xfe000101, 0xffffff00, 0xff000000, - 0xffffff00, 0xff0000ff, 0x00000102, 0x00000100, - 0x01010001, 0x00000101, 0x01000001, 0x00000001, - 0x00ffff01, 0x00000000, 0xffff0002, 0x00ffffff, - 0xffff0103, 0xfffefefe, 0x00010204, 0xfffefeff, - 0x00000102, 0x0000ffff, 0xffffff00, 0x010100ff, - 0x02020100, 0xfdff0102, 0x01010000, 0xfeff0001, - 0x00000000, 0xffff0000, 0x00ff0000, 0x00010100, - 0x00ff0000, 0x01010101, 0x00000000, 0x00010101, - 0x01010000, 0xfdff0102, 0x01000000, 0xfbfcff01, - 0xfffefefe, 0x02020200, 0x00000000, 0x00010101, - 0x01010101, 0xfdfe0001, 0x01010000, 0xfcfdff00, - 0x0100ffff, 0xfdfe0000, 0x0100ffff, 0xff000101, - 0x01000000, 0x00010101, 0x01010101, 0x00000000, - 0x00000100, 0x02010101, 0x00000201, 0x01ff0000, - 0xff000200, 0x00ff0001, 0x00000100, 0x01000102, - 0x00ff0100, 0x01000202, 0xffff00ff, 0x02010102, - 0xfefdfefe, 0x01010100, 0xfdfdfefe, 0x00ffffff, - 0x0100fffd, 0x00010102, 0x0100fffd, 0x01010102, - 0x010000fe, 0x01010101, 0x000000ff, 0x00000000, - 0x000000fe, 0x00ffff00, 0x000000fe, 0xffff0000, - 0x010100fd, 0x01000101, 0x0100fefb, 0x02010202, - 0x00fffffe, 0x03020100, 0x01010000, 0x02010000, - 0x00010000, 0x0100ffff, 0xffffffff, 0x00fffefe, - 0xfefefefe, 0x0100fffe, 0xff000000, 0x02020100, - 0x00000102, 0x02020100, 0xff000102, 0x0000ffff, - 0x01010100, 0xfcff0101, 0x0100ffff, 0xfd000101, - 0x0000fffe, 0xfe020201, 0x000000ff, 0xff030200, - 0x000000ff, 0x00020100, 0xfeff0000, 0x000101ff, - 0xfeff0000, 0x010200fe, 0xfeff0000, 0x020201ff, - 0x00000001, 0xfdfefdfe, 0x00010000, 0xfffffefe, - 0x0101ff00, 0x0000ffff, 0x0101ff00, 0x0000ffff, - 0x01020100, 0x0100ffff, 0x02030201, 0x02010000, - 0x010200ff, 0x03020000, 0x0000fffe, 0x020100ff, - 0xff000101, 0x01fffefe, 0xff010101, 0x0200fefe, - 0xff010101, 0x0200ffff, 0x00000000, 0x02010000, - 0x00ffffff, 0x02010000, 0x01fffeff, 0x00000101, - 0x01fffeff, 0xff000202, 0x02fffeff, 0xff000202, - 0xfeffffff, 0x0100ffff, 0xffff0000, 0x020100ff, - 0x00000001, 0x02010100, 0x00000101, 0x01010101, - 0x01000101, 0x01010001, 0x01010101, 0xffffff00, - 0x00010201, 0xfdfefeff, 0x00010202, 0xfcfcfdfe, - 0x0101fefc, 0x00000101, 0x000100fe, 0x00000000, - 0xfe010100, 0x0100fffe, 0xfe010202, 0x0201fffe, - 0xfe010201, 0x0201fffe, 0xff0101ff, 0x0100ffff, - 0x010100fe, 0x00ffff00, 0x020200fe, 0x00ffff01, - 0x00000101, 0x00000100, 0xfefdfdfe, 0x0000fffe, - 0xfefdfcfd, 0x000000ff, 0x0100ffff, 0x01020302, - 0x03020100, 0x01020303, 0x02010101, 0xff000001, - 0x00000000, 0xffffffff, 0x00ffff00, 0x00000000, - 0x00000101, 0x0200ffff, 0x00010000, 0x0101ffff, - 0x0100fffe, 0x01010101, 0x0200fdfd, 0x00010102, - 0x0100fefe, 0x00000101, 0x00000001, 0xffff0000, - 0xfdff0103, 0x0100fffe, 0xfdff0204, 0x0201fffd, - 0xff000000, 0xffffffff, 0x00010201, 0xffff0000, - 0x02030302, 0xffff0001, 0x02040403, 0xfeff0001, - 0x01020303, 0xfefeff00, 0xff000101, 0xfdfefeff, - 0xff000000, 0xfefefeff, 0xffffffff, 0xfffefeff, - 0x02020201, 0x02020102, 0x01010100, 0x00000001, - 0x01000000, 0xfeff0001, 0x00000000, 0xfcff0001, - 0x00000001, 0xfbfe0000, 0x00000001, 0xfcff0000, - 0x00ff0001, 0xfdff0000, 0x00ffff00, 0xff010101, - 0x0000fffe, 0xfeffffff, 0x000000ff, 0xfefeffff, - 0x00010100, 0xfeffffff, 0x00010100, 0xffff0000, - 0x00000100, 0x00010101, 0x00000101, 0x01020201, - 0x00000101, 0x01020201, 0xff000101, 0x00010100, - 0x00010204, 0x01010100, 0x00010204, 0x01000000, - 0x00000103, 0x00ffffff, 0xff000001, 0x00fffeff, - 0x00000000, 0x00ffffff, 0x0000ffff, 0x0100ffff, - 0xff00fffe, 0x010000ff, 0xfefffefe, 0x010000ff, - 0x01010100, 0xff000102, 0x00ffffff, 0xfefeff00, - 0x00ff00ff, 0xfffeff00, 0x00000000, 0x02010000, - 0x00000000, 0x03020000, 0xffff00ff, 0x0300ffff, - 0xff0000ff, 0x0300feff, 0x00000000, 0x0401ffff, - 0x00000202, 0x01000000, 0xfeff0101, 0x01fffeff, - 0xfefeffff, 0x00fefdfe, 0xffff00ff, 0x01fffeff, - 0x00000101, 0x01000001, 0x00000202, 0x01000001, - 0x00000202, 0xffff0000, 0x00000202, 0xffff0001, - 0x010100ff, 0xffffff00, 0x02030201, 0x00000001, - 0x01010100, 0x0000ff00, 0x00fffefe, 0x00000001, - 0x02fffefe, 0x00010202, 0x0100fffe, 0xff000001, - 0x0000ffff, 0xfefffeff, 0x01010100, 0x01010000, - 0xfefdfdfd, 0xfefeffff, 0x0100ffff, 0x00000102, - 0x02010101, 0x00000102, 0x01010101, 0x01ff0001, - 0xffff0001, 0x01ff0000, 0xffffff00, 0x01ffff00, - 0x00ff0001, 0x0200ff00, 0x00ff0002, 0x02000000, - 0xfffe0001, 0x00010100, 0xffff0002, 0x00010100, - 0xfffe0001, 0xff000100, 0xffff0001, 0xff000100, - 0x00010100, 0x00000101, 0x010201fe, 0x01000000, - 0x010200fb, 0x0100ff00, 0x0102fffa, 0x0000ff00, - 0xff000305, 0xfffffffe, 0xff000101, 0xffff00ff, - 0x010100ff, 0x00010202, 0x0100fffe, 0x01010102, - 0xfffffffe, 0x0100ff00, 0x00000100, 0x0000ffff, - 0x01010100, 0x00000001, 0x0100fefd, 0xff000001, - 0x000100ff, 0x030200ff, 0xfe0000ff, 0x00fffefc, - 0x00010100, 0xff00fffe, 0x01030201, 0x00010100, - 0x010100ff, 0x00010101, 0x00fefdfe, 0x00010000, - 0x00fefeff, 0xff000001, 0x00000103, 0xffff0001, - 0x0000fffe, 0x0000ffff, 0x000000ff, 0x01010100, - 0x00ffffff, 0x01010101, 0xfffdfe00, 0x00000001, - 0xfffdff01, 0xff000101, 0x01ff0103, 0xff000202, - 0x01000103, 0x00010102, 0xfffefe00, 0x000000ff, - 0xffff0001, 0x00010201, 0xfffeff00, 0x01020201, - 0x00ffffff, 0x00020100, 0x000000fe, 0xff010000, - 0x000100ff, 0xffffffff, 0x02010100, 0x00fffe00, - 0x02020201, 0x00ffff01, 0x01010100, 0xfffefe00, - 0xffff0000, 0xfefeffff, 0x00ff0000, 0x01020201, - 0xffff0000, 0x02020100, 0xfeff0101, 0xffffffff, - 0x00010202, 0xfefeff00, 0x01020201, 0xfefe0000, - 0x00000000, 0xff000101, 0xffffff00, 0x01020302, - 0x0201fe00, 0x010000ff, 0x0302feff, 0x000000ff, - 0x0302fe00, 0x0000ffff, 0x0203ff00, 0x000100fe, - 0x0103ff00, 0x000100fe, 0x0102ff00, 0xff0001ff, - 0xff010000, 0xff0000fe, 0xfe000001, 0xfffffffe, - 0x01010101, 0xfeffff01, 0x01000000, 0x01010101, - 0x01000000, 0x03020101, 0xff000001, 0x02010000, - 0xfeffff00, 0x020100ff, 0xfefefefe, 0x010100ff, - 0xffffffff, 0xff000000, 0x00020202, 0xfcfeffff, - 0xfffffeff, 0x03020100, 0xffffffff, 0x03020100, - 0x00ff0001, 0x020100ff, 0x00000001, 0x020200ff, - 0xffff0001, 0x020100fe, 0xfefefe00, 0x0100fffd, - 0xfefefe00, 0x0101fffe, 0x00000000, 0x02020100 +static const int8 s_svq1IntraCodebook8x8[6144] = { + 4, 4, 3, 2, 2, 1, 0, -1, 4, 3, 3, 2, 1, 0, -1, -1, + 3, 3, 2, 2, 1, 0, -1, -2, 3, 2, 2, 1, 0, -1, -2, -3, + 2, 2, 1, 0, -1, -1, -2, -3, 2, 1, 0, 0, -1, -2, -3, -4, + 1, 0, 0, -1, -2, -3, -4, -4, 0, 0, -1, -2, -2, -3, -4, -4, + 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, + 1, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, + -1, 0, 0, 0, 0, 0, 1, 1, -2, -2, -1, -1, -1, -1, -1, -1, + -3, -3, -3, -3, -3, -3, -2, -2, -5, -4, -4, -4, -4, -4, -4, -3, + -4, -2, -1, 0, 1, 2, 2, 3, -4, -2, -1, 0, 1, 2, 3, 3, + -4, -3, -1, 0, 1, 2, 3, 3, -4, -3, -1, 0, 1, 2, 3, 3, + -5, -3, -1, 0, 1, 2, 3, 3, -5, -3, -1, 0, 1, 2, 3, 3, + -5, -3, -1, 0, 1, 1, 2, 3, -5, -3, -2, -1, 0, 1, 2, 3, + 4, 4, 5, 5, 6, 6, 7, 7, 2, 2, 2, 3, 3, 4, 4, 4, + 0, 0, 0, 0, 1, 1, 1, 2, -2, -2, -2, -2, -1, -1, -1, 0, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -1, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -2, -2, -2, -2, + 5, 3, 1, -1, -2, -3, -3, -3, 5, 3, 1, -1, -2, -3, -3, -3, + 5, 3, 1, -1, -2, -3, -3, -3, 5, 3, 1, -1, -2, -3, -3, -3, + 5, 4, 1, 0, -2, -3, -3, -3, 6, 4, 2, 0, -2, -2, -3, -3, + 6, 4, 2, 0, -1, -2, -2, -3, 6, 4, 2, 1, -1, -2, -2, -2, + -1, 1, 3, 3, 2, 0, -3, -6, -1, 1, 3, 4, 3, 0, -3, -6, + -1, 1, 4, 4, 3, 1, -3, -6, -1, 1, 3, 4, 3, 1, -3, -6, + -2, 1, 3, 4, 3, 1, -3, -6, -2, 1, 3, 4, 3, 1, -3, -7, + -2, 1, 3, 3, 2, 0, -3, -7, -2, 0, 2, 3, 2, 0, -3, -6, + 10, 9, 8, 6, 6, 5, 4, 4, 6, 5, 4, 3, 2, 2, 2, 1, + 2, 1, 0, -1, -2, -2, -2, -1, -1, -2, -3, -4, -4, -4, -4, -3, + -2, -3, -4, -4, -5, -4, -4, -3, -2, -2, -3, -3, -3, -3, -2, -2, + -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1, 2, + -2, -1, 1, 2, 4, 5, 7, 8, -3, -2, 0, 1, 3, 5, 7, 8, + -4, -3, -1, 0, 2, 4, 6, 7, -5, -4, -2, -1, 1, 3, 5, 7, + -6, -5, -3, -2, 0, 2, 4, 6, -6, -5, -4, -2, -1, 1, 3, 5, + -7, -6, -5, -3, -2, 0, 2, 3, -8, -7, -5, -4, -3, -1, 1, 2, + 11, 9, 7, 5, 3, 1, -1, -1, 10, 8, 6, 3, 1, 0, -2, -2, + 9, 7, 5, 2, 0, -2, -3, -4, 8, 6, 3, 1, -1, -3, -4, -4, + 6, 4, 2, -1, -3, -4, -5, -5, 5, 3, 0, -2, -4, -5, -6, -6, + 3, 1, -1, -3, -5, -6, -7, -7, 2, 0, -2, -4, -6, -6, -7, -7, + 5, 6, 7, 7, 7, 8, 8, 8, 3, 4, 5, 5, 6, 6, 6, 6, + 0, 2, 2, 3, 4, 4, 4, 5, -2, -1, 0, 1, 2, 2, 3, 3, + -4, -3, -2, -1, 0, 1, 1, 2, -6, -5, -4, -3, -2, -2, -1, 0, + -8, -7, -6, -6, -5, -4, -3, -3,-10, -9, -8, -8, -7, -6, -6, -5, + 6, 5, 3, 1, -1, -3, -6, -8, 6, 5, 4, 2, -1, -3, -6, -8, + 6, 5, 4, 2, 0, -3, -6, -8, 6, 5, 4, 2, 0, -3, -6, -8, + 6, 6, 4, 2, 0, -3, -6, -8, 6, 5, 4, 2, 0, -3, -6, -8, + 6, 5, 4, 2, 0, -3, -6, -8, 6, 5, 4, 2, -1, -3, -5, -8, + 11, 10, 9, 8, 7, 6, 5, 4, 8, 8, 7, 6, 5, 4, 3, 2, + 6, 5, 4, 4, 2, 2, 1, 0, 3, 3, 2, 1, 0, 0, -1, -2, + 1, 1, 0, -1, -2, -2, -3, -3, -1, -1, -2, -3, -4, -4, -5, -5, + -3, -4, -4, -5, -6, -6, -7, -7, -5, -5, -6, -7, -8, -8, -8, -8, + -14,-13,-12,-11, -9, -7, -6, -4,-12,-11,-10, -9, -7, -5, -3, -1, + -10, -9, -7, -6, -3, -2, 0, 2, -8, -6, -4, -2, 0, 2, 4, 5, + -5, -3, 0, 2, 4, 5, 7, 8, -2, 0, 2, 4, 6, 8, 9, 10, + 0, 3, 5, 7, 8, 10, 11, 12, 3, 5, 7, 8, 10, 11, 12, 12, + -19,-19,-18,-18,-17,-16,-15,-14,-15,-15,-14,-13,-12,-11,-10, -9, + -11,-10, -9, -8, -6, -5, -4, -3, -6, -5, -3, -2, -1, 0, 1, 2, + -1, 0, 2, 3, 4, 5, 6, 6, 4, 6, 7, 8, 9, 10, 10, 10, + 9, 10, 11, 12, 13, 14, 14, 14, 12, 14, 14, 15, 16, 16, 16, 16, + 22, 21, 19, 17, 14, 11, 9, 5, 20, 19, 17, 14, 11, 8, 4, 1, + 17, 15, 13, 10, 6, 3, 0, -4, 13, 11, 8, 5, 1, -2, -5, -9, + 9, 6, 3, -1, -4, -7,-11,-13, 4, 0, -3, -6, -9,-12,-15,-17, + -2, -5, -8,-11,-14,-16,-18,-20, -8,-10,-13,-16,-17,-19,-21,-22, + 17, 18, 18, 18, 17, 16, 16, 14, 16, 16, 15, 15, 14, 13, 12, 11, + 12, 12, 11, 10, 9, 8, 7, 5, 7, 6, 6, 4, 3, 2, 1, -1, + 1, 0, -1, -2, -3, -4, -5, -6, -5, -6, -7, -8, -9,-10,-11,-12, + -11,-12,-13,-14,-15,-16,-16,-17,-16,-17,-17,-18,-19,-20,-20,-20, + 0, 0, 0, 0, -1, -1, -2, -3, 1, 0, 0, 0, 0, -1, -2, -3, + 1, 1, 0, 0, -1, -1, -2, -2, 1, 1, 1, 0, 0, -1, -1, -2, + 2, 1, 1, 1, 0, -1, -1, -2, 2, 2, 1, 1, 0, 0, -1, -2, + 2, 2, 1, 1, 1, 0, -1, -1, 2, 2, 1, 1, 1, 0, 0, -2, + 0, -1, -1, 0, 0, 1, 2, 3, 0, -1, -1, 0, 1, 1, 2, 2, + -1, -1, -1, -1, 0, 1, 2, 2, -1, -1, -2, -1, 0, 1, 1, 2, + -1, -2, -2, -1, 0, 0, 1, 2, -1, -2, -2, -2, -1, 0, 1, 2, + -1, -1, -2, -1, 0, 0, 1, 2, -1, -1, -1, -1, 0, 1, 1, 2, + 3, 2, 2, 2, 1, 1, 0, 0, 3, 2, 2, 2, 2, 1, 0, 0, + 2, 2, 2, 1, 1, 1, 0, 0, 2, 2, 1, 1, 1, 0, 0, -1, + 1, 1, 1, 0, 0, 0, -1, -1, 0, 0, -1, -1, -1, -1, -1, -1, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -2, -2, -2, -2, + 5, 2, 0, 0, -1, 0, 0, 0, 4, 2, 0, -1, -1, -1, 0, -1, + 4, 1, -1, -1, -2, -1, -1, -1, 4, 1, -1, -1, -2, -1, -1, -1, + 4, 1, -1, -2, -2, -1, -1, -1, 4, 1, -1, -2, -2, -1, -1, -1, + 4, 1, -1, -1, -1, -1, -1, -1, 4, 2, 0, -1, 0, 0, 0, -1, + -2, -1, 0, 1, 1, 1, 1, 1, -3, -1, 0, 1, 1, 1, 1, 1, + -3, -1, 0, 1, 1, 1, 1, 1, -3, -1, 0, 1, 1, 1, 1, 1, + -3, -2, 0, 1, 2, 2, 1, 1, -4, -2, 0, 1, 2, 2, 2, 2, + -5, -3, -1, 1, 1, 2, 1, 2, -5, -3, -2, 0, 1, 1, 1, 1, + 3, 3, 1, 0, -2, -4, -4, -5, 3, 3, 2, 0, -1, -2, -3, -4, + 2, 2, 1, 1, 0, -1, -2, -2, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, -2, -1, -1, 0, 0, 1, 2, 2, + -3, -2, -2, -1, 0, 1, 2, 3, -3, -3, -2, -1, 0, 1, 2, 3, + -3, -3, -3, -3, -3, -2, -2, -2, -3, -3, -2, -2, -2, -1, -1, -1, + -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 2, 2, 2, 2, + 1, 1, 1, 2, 2, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + -8, -7, -5, -3, -2, -1, 0, -1, -4, -3, -1, 0, 1, 2, 1, 1, + -1, 1, 2, 3, 3, 2, 2, 1, 1, 2, 3, 3, 2, 2, 1, 0, + 2, 3, 3, 2, 1, 0, 0, -1, 1, 2, 1, 0, -1, -1, -1, -1, + 1, 1, 0, -1, -1, -2, -2, -1, 1, 1, 0, 0, -1, -1, 0, -1, + -4, -3, -2, 0, 1, 2, 3, 3, -4, -3, -2, 0, 1, 2, 2, 2, + -3, -3, -2, -1, 0, 1, 1, 1, -2, -2, -2, -1, -1, 0, 0, 0, + 0, -1, -1, -1, -1, -1, -1, -1, 2, 1, 1, 0, 0, -1, -1, -2, + 3, 3, 3, 1, 0, -1, -2, -2, 5, 4, 4, 2, 1, 0, -1, -2, + 0, 0, 0, 0, 1, 2, 3, 3, 0, -1, 0, 0, 1, 2, 3, 3, + 0, -1, 0, 0, 1, 2, 3, 2, 0, 0, 0, 1, 1, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 1, 0, 0, -1, -2, + 2, 1, 0, 0, -2, -3, -5, -6, 0, -1, -1, -3, -5, -6, -8, -9, + -2, 0, 1, 2, 2, 1, -1, -4, -2, 0, 2, 2, 2, 1, -1, -4, + -2, 0, 2, 2, 2, 1, -1, -3, -2, 0, 2, 2, 2, 1, -1, -3, + -2, -1, 2, 2, 2, 1, -1, -3, -2, -1, 1, 2, 2, 1, -1, -3, + -3, -1, 1, 2, 2, 1, -1, -3, -2, -1, 1, 2, 2, 1, -1, -3, + -1, 1, 1, -1, -3, -3, 0, 4, -1, 1, 1, -1, -3, -3, 0, 4, + -1, 1, 1, 0, -3, -3, 0, 4, -1, 1, 2, 0, -3, -3, 0, 5, + 0, 1, 2, 0, -3, -4, 0, 4, 0, 1, 2, 0, -3, -4, 0, 5, + 0, 1, 2, 0, -3, -3, 0, 4, 0, 1, 2, -1, -2, -2, 0, 4, + 6, 6, 5, 6, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 0, 0, 0, 0, 0, + -1, -2, -2, -2, -2, -2, -2, -1, -3, -3, -3, -3, -3, -3, -3, -2, + -3, -4, -4, -3, -3, -3, -2, -2, -2, -2, -2, -2, -1, -1, 0, 0, + 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, + 4, 1, -2, -3, -3, -1, 1, 3, 4, 1, -2, -4, -3, -1, 1, 3, + 5, 1, -2, -4, -3, -1, 1, 4, 5, 1, -2, -3, -3, -1, 2, 4, + 5, 1, -2, -3, -3, -1, 2, 4, 4, 0, -3, -4, -3, -1, 2, 4, + 4, 0, -3, -3, -3, -1, 1, 3, 3, 0, -2, -3, -2, -1, 1, 3, + -3, -4, -4, -4, -4, -4, -4, -4, -1, -1, -1, -1, -1, -1, -2, -2, + 2, 1, 1, 2, 2, 1, 1, 1, 3, 3, 3, 4, 4, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 3, 3, 1, 2, 1, 2, 2, 2, 2, 2, + -2, -2, -2, -1, -1, -1, 0, 0, -4, -4, -4, -4, -3, -3, -3, -3, + -1, -2, -3, -3, -2, -2, -1, 0, 0, -1, -2, -2, -2, -1, 0, 1, + 2, 1, -1, -1, -1, -1, 0, 1, 3, 1, 0, -1, -1, 0, 0, 1, + 3, 2, 0, -1, 0, 0, 0, 1, 3, 1, 0, -1, 0, 0, 0, 1, + 3, 1, 0, -1, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 1, 1, 2, 3, 4, 0, 0, -1, 0, 0, 0, 2, 3, + 0, -1, -1, -1, -1, -1, 0, 1, 0, -1, -1, -1, -1, -1, -1, 0, + 0, 0, -1, -1, -1, -2, -2, -1, 1, 0, 0, -1, -1, -2, -2, -1, + 2, 2, 1, 0, -1, -1, -1, -1, 3, 3, 2, 1, 0, -1, -1, 0, + 1, 0, 1, 0, 0, -1, -2, -1, 0, 0, 0, 0, -1, -1, -2, -1, + 0, -1, 0, 0, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, + -1, -1, -1, 0, 0, 0, 1, 1, -1, -1, -1, 0, 1, 1, 2, 3, + -2, -2, -1, 0, 1, 2, 3, 4, -2, -2, -1, 0, 1, 2, 4, 5, + -3, -1, 1, 0, 0, -1, 0, 1, -3, 0, 1, 0, -1, -1, 0, 2, + -3, 0, 1, 0, -1, -1, 0, 2, -2, 1, 2, 0, -1, -1, 0, 2, + -2, 1, 2, 0, -1, -1, 0, 2, -2, 1, 2, 0, -1, -1, 0, 2, + -1, 2, 2, 0, -1, -1, 0, 2, -1, 1, 1, 0, -1, -1, -1, 1, + -2, -2, -1, 1, 3, 4, 3, 1, -2, -2, -1, 0, 2, 3, 2, 0, + -2, -2, -1, 0, 1, 2, 1, -1, -1, -1, -1, 0, 1, 2, 1, -1, + -1, -1, -1, 0, 1, 1, 0, -2, 0, -1, -1, 0, 1, 1, 0, -1, + 0, -1, -1, 0, 1, 1, 1, -1, 0, -1, -1, 0, 0, 1, 0, -1, + -2, -1, 0, 1, 1, 1, 1, 1, -2, -1, 0, 0, 0, 0, 0, 0, + -2, -1, -1, 0, -1, -1, -2, -2, -2, -1, -1, -1, -1, -2, -2, -3, + -1, 0, 1, 1, 0, -1, -2, -2, 1, 2, 3, 3, 2, 1, 0, 0, + 1, 2, 3, 3, 3, 2, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, -1, -1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, 0, 0, 1, 1, 0, 0, 0, + -3, -2, -1, -1, -1, -1, 0, -1, -5, -5, -4, -3, -2, -2, -2, -1, + 1, 1, 1, 1, 2, 1, 0, -1, 1, 1, 1, 2, 1, 1, 0, -1, + 1, 1, 1, 1, 1, 1, 0, -2, 2, 1, 1, 1, 1, 1, 0, -2, + 1, 1, 0, 0, 0, 0, -1, -3, 1, 1, 0, 0, 0, -1, -2, -3, + 1, 1, 0, 0, -1, -1, -2, -4, 1, 0, 0, -1, -2, -2, -3, -4, + 8, 7, 5, 3, 2, 1, 1, 1, 2, 1, 0, 0, -1, -1, -2, -1, + -1, -1, -1, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, -1, -1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + -1, 0, 0, 0, 0, 0, -1, -1, -2, -2, -1, -1, -1, -2, -2, -1, + 9, 4, 0, -2, -2, -2, -1, -1, 7, 2, -1, -2, -2, -1, 0, 0, + 4, 0, -2, -2, -1, 0, 1, 1, 1, -2, -2, -2, -1, 0, 1, 1, + -1, -2, -2, -1, 0, 1, 1, 1, -1, -2, -1, 0, 1, 1, 1, 0, + -1, -1, 0, 1, 1, 1, 0, -1, 0, -1, 0, 1, 0, 0, -1, -1, + 0, 1, 1, 1, 1, 1, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, + 2, 2, 2, 2, 1, 0, -1, -1, 1, 1, 1, 0, -1, -2, -2, -2, + 0, 0, 0, -1, -2, -3, -2, -2, -1, -1, -1, -2, -2, -2, -1, 0, + -1, -1, -1, -1, 0, 0, 1, 2, -1, -1, -1, 0, 1, 2, 3, 4, + -1, -1, 0, 0, -1, -2, -3, -3, -1, -1, 0, 0, 0, -1, -1, -1, + -2, -2, -1, 0, 1, 1, 1, 1, -2, -2, -2, 0, 1, 2, 3, 3, + -1, -1, -1, 0, 1, 3, 3, 3, 1, 0, 0, 0, 1, 1, 2, 2, + 2, 2, 1, 0, 0, -1, -1, -1, 3, 2, 1, 0, -1, -2, -3, -3, + -1, -1, -1, -2, -2, -3, -4, -5, 0, 0, 0, -1, -1, -3, -3, -4, + 1, 1, 1, 0, 0, -1, -2, -3, 2, 2, 2, 1, 1, 0, -1, -1, + 2, 2, 2, 2, 1, 1, 0, -1, 2, 2, 2, 2, 2, 1, 0, 0, + 1, 1, 2, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, -1, + -2, 2, 3, 1, -1, 1, 1, -1, -3, 2, 3, 0, -1, 1, 1, -1, + -3, 2, 3, 0, -1, 1, 1, -1, -4, 2, 3, 0, -1, 1, 1, -2, + -4, 1, 3, 0, -1, 1, 1, -2, -4, 1, 3, -1, -2, 1, 1, -2, + -3, 1, 2, 0, -1, 1, 1, -2, -3, 1, 2, 0, -1, 1, 1, -1, + -1, -1, -1, -2, -2, -2, -2, -2, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 1, 2, 2, 2, + -2, -2, -1, -1, -1, 0, 0, 0, -3, -3, -3, -3, -3, -3, -3, -2, + -1, -1, -1, -1, -2, -2, -2, -2, 4, 4, 4, 4, 4, 3, 3, 2, + -3, -3, -2, -1, 0, 1, 2, 5, -3, -3, -3, -2, -1, 1, 3, 6, + -3, -3, -2, -2, 0, 2, 3, 5, -3, -2, -2, -2, 0, 1, 3, 5, + -2, -2, -2, -1, -1, 1, 3, 5, -2, -2, -1, -1, 0, 1, 2, 4, + -1, -1, -1, -1, 0, 1, 1, 4, -1, -1, -1, -1, 0, 1, 2, 3, + 0, -1, 0, 1, 1, 0, -1, -1, 0, 0, 0, 1, 2, 0, -1, -1, + 1, 0, -1, 0, 1, 0, 0, 0, 1, -1, -2, -1, 0, 0, 0, 0, + 1, -2, -3, -1, 0, 0, 0, 1, 1, -1, -3, -2, 0, 1, 1, 2, + 1, -1, -2, -1, 0, 1, 1, 2, 2, 0, -1, 0, 1, 1, 2, 2, + 1, 1, 1, 1, 0, 0, 1, 2, -1, 0, 0, -1, 0, 0, 0, 1, + -3, -2, -1, -1, -1, 0, 1, 1, -4, -2, -1, 0, 0, 1, 1, 1, + -3, -2, 0, 0, 1, 1, 1, 1, -3, -1, 0, 1, 1, 1, 0, 0, + -1, 0, 1, 1, 1, 0, 0, -1, 0, 1, 2, 2, 1, 0, 0, -1, + -4, -4, -4, -3, -2, -1, -1, -1, -2, -2, -2, -1, 0, 0, 0, 0, + -1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 2, 2, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 0, -1, 0, 0, 1, 1, 1, 0, 0, + 1, 2, 2, 2, 1, -1, -2, -4, 1, 1, 2, 2, 1, 0, -2, -4, + 0, 1, 1, 1, 1, 0, -1, -3, -1, 0, 1, 1, 0, 0, -1, -2, + -1, 0, 1, 1, 1, 0, 0, -1, -2, -1, 0, 0, 0, 0, 0, -1, + -1, -1, 0, 1, 1, 0, 0, 0, -1, 0, 1, 1, 1, 1, 1, 0, + 2, 2, 0, -1, -2, -1, -1, -2, 1, 1, -1, -2, -2, -1, -1, -2, + 1, 1, -1, -2, -2, 0, 0, -1, 1, 1, 0, -2, -1, 1, 1, 0, + 1, 1, 0, -1, -1, 1, 2, 1, 1, 1, 0, -1, -1, 1, 2, 1, + 1, 1, 0, -1, -1, 1, 1, 1, 1, 1, 0, -1, 0, 1, 1, 1, + 0, 0, -1, -2, -4, -4, -4, -4, 3, 3, 3, 2, 1, 0, 0, 0, + 3, 3, 3, 3, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, + -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, + -1, -1, 0, -1, -1, 1, 2, -1, 1, 1, 0, 0, 0, 2, 3, -1, + 1, 1, 0, -1, -1, 1, 3, -1, 1, 1, 0, -2, -2, 0, 1, -2, + 1, 0, 0, -2, -2, 0, 1, -3, 0, 0, 0, 0, -1, 1, 1, -3, + 0, 1, 1, 0, 1, 2, 1, -3, -1, 0, 1, 1, 1, 2, 1, -4, + -4, -3, 0, 1, 1, 1, 0, 0, -4, -2, 0, 1, 1, 1, 0, -1, + -3, -1, 1, 1, 1, 0, -1, -1, -1, 1, 1, 1, 1, 0, -1, 0, + 1, 2, 2, 1, 0, -1, 0, 0, 2, 2, 1, 0, -1, -1, 0, 1, + 2, 1, 0, -1, -2, -1, 0, 1, 2, 2, 0, -1, -2, -1, 1, 1, + 1, 1, 0, 0, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, -1, -1, -1, -1, -1, + 1, 0, 0, -1, -1, -1, -1, -1, 2, 1, 0, 0, -1, -1, -1, -1, + 5, 3, 2, 1, 0, 0, 0, 0, 6, 5, 3, 2, 1, 0, 0, 0, + 4, 4, 3, 1, 0, 0, 0, 1, 3, 3, 2, 1, 0, 0, 0, 1, + 2, 2, 1, 0, -1, -1, 0, 1, 0, 0, 0, -1, -1, -1, 0, 1, + 0, 0, -1, -1, -2, -1, 0, 2, 0, -1, -1, -2, -2, -2, 0, 1, + 0, -1, -1, -2, -2, -2, -1, 0, 0, 0, -1, -2, -2, -2, -1, 0, + 0, 0, -1, -1, -1, 0, 2, 3, 0, -1, -2, -2, -1, -1, 1, 2, + 1, 0, -1, -1, -1, 0, 0, 0, 1, 1, 1, 0, 0, 0, -1, -1, + 1, 2, 1, 0, 0, -1, -1, -1, -1, 0, 0, 0, -1, -1, -1, -1, + -3, -2, -1, -1, 0, 1, 1, 2, -4, -3, -1, 1, 2, 3, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, -1, 0, 0, 0, 1, -1, -1, -2, -2, -2, -1, -1, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, + 1, 1, 1, 1, 2, 2, 1, 1, -4, -3, -4, -4, -4, -4, -3, -3, + -1, 0, 1, 2, 2, 3, 3, 3, -1, -1, -1, -1, 0, 0, 0, 0, + 0, 0, -1, -2, -2, -3, -3, -2, 3, 2, 1, 0, -1, -2, -2, -2, + 4, 3, 2, 1, 1, 0, 0, 0, 2, 2, 1, 1, 0, 1, 1, 1, + 0, -1, -1, -1, -1, 0, 0, 1, -2, -2, -2, -2, -2, -1, 0, 0, + 1, -1, 0, 2, 1, -2, -1, 1, 1, -1, 0, 2, 1, -2, -2, 1, + 1, -1, 0, 3, 2, -2, -1, 1, 0, -2, 0, 3, 2, -2, -2, 1, + 0, -2, 0, 3, 2, -2, -2, 1, 0, -2, 0, 3, 1, -2, -1, 1, + 0, -2, 0, 2, 1, -2, -2, 1, 0, -1, 0, 2, 1, -2, -1, 1, + 0, 1, 2, 2, 3, 3, 2, 2, 0, 1, 1, 2, 3, 3, 2, 1, + 0, 0, 1, 2, 2, 2, 2, 1, -1, 0, 0, 1, 1, 1, 1, 1, + -1, -1, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -2, -2, -2, -2, -2, -2, -2, -1, -2, -2, -2, -2, -2, -2, -2, -1, + 0, 0, -1, -2, -1, 0, 3, 5, 0, 0, -1, -1, -1, 0, 2, 4, + 1, 1, 0, 0, -1, -1, 1, 2, 1, 2, 1, 1, 0, -1, -1, 0, + 0, 1, 2, 1, 0, -1, -2, -2, -1, 0, 1, 2, 1, 0, -3, -3, + -2, -1, 1, 2, 2, 0, -2, -4, -2, -1, 0, 2, 2, 1, -1, -3, + 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, -1, 0, 0, 0, 0, 0, + -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, -1, -1, 0, + 0, 0, 1, 1, 0, 0, 0, 1, 3, 3, 3, 4, 3, 3, 3, 3, + 5, 1, -2, -2, 0, 0, 0, -1, 4, -1, -3, -1, 0, 0, 0, -1, + 3, -1, -1, 0, 1, 1, 0, -1, 2, 0, 0, 1, 1, 1, 0, -2, + 1, 0, 0, 1, 1, 1, 0, -2, 0, -1, -1, -1, 0, 0, 0, -1, + 0, -1, -1, -1, -1, 0, 0, -1, 2, 1, 0, 0, 0, 1, 0, 0, + 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, + 1, -1, -1, 0, 0, 0, 0, 0, 2, 0, -1, -1, -1, -1, -1, 0, + 3, 1, -1, -1, -2, -2, -2, -1, 4, 2, 1, 0, -1, -2, -2, -1, + 2, 1, 0, 0, -1, -1, 0, 0, 0, -1, -1, -1, -1, 0, 1, 1, + 0, 1, 2, 2, 2, 1, -1, -3, 0, 0, 1, 1, 1, 0, -1, -2, + 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, -1, 0, 0, 1, 1, 0, + 0, 0, -1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 2, 1, -1, -3, 0, 0, 0, 1, 1, -1, -4, -5, + -2, -2, -2, -1, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, -2, -3, 0, 0, 1, 1, 0, -1, -3, -4, + -1, -1, 0, 1, 0, 0, -2, -3, -1, -1, 0, 1, 1, 1, 0, -1, + 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 1, 2, 1, 2, 0, 0, 0, 0, -1, 1, + 0, 2, 0, -1, 1, 0, -1, 0, 0, 1, 0, 0, 2, 1, 0, 1, + 0, 1, -1, 0, 2, 2, 0, 1, -1, 0, -1, -1, 2, 1, 1, 2, + -2, -2, -3, -2, 0, 1, 1, 1, -2, -2, -3, -3, -1, -1, -1, 0, + -3, -1, 0, 1, 2, 1, 1, 0, -3, -1, 0, 1, 2, 1, 1, 1, + -2, 0, 0, 1, 1, 1, 1, 1, -1, 0, 0, 0, 0, 0, 0, 0, + -2, 0, 0, 0, 0, -1, -1, 0, -2, 0, 0, 0, 0, 0, -1, -1, + -3, 0, 1, 1, 1, 1, 0, 1, -5, -2, 0, 1, 2, 2, 1, 2, + -2, -1, -1, 0, 0, 1, 2, 3, 0, 0, 1, 1, 0, 0, 1, 2, + 0, 0, 1, 0, -1, -1, 0, 1, -1, -1, -1, -1, -2, -2, -1, 0, + -2, -2, -2, -2, -2, -1, 0, 1, 0, 0, 0, -1, 0, 1, 2, 2, + 2, 1, 0, 0, 0, 1, 2, 2, 2, 1, 0, -1, -1, -1, 0, 0, + 0, 1, 1, 1, 1, 1, -1, -4, -1, -1, 0, 1, 1, 1, 0, -3, + -2, -1, 0, 0, 1, 2, 2, -2, -1, 0, 0, 0, 0, 2, 3, -1, + -1, 0, 0, 0, 0, 1, 2, 0, 0, 0, -1, -2, -1, 1, 1, 0, + 0, 0, -1, -2, -2, 0, 2, 1, 0, 0, -1, -2, -1, 1, 2, 2, + 1, 0, 0, 0, -2, -3, -2, -3, 0, 0, 1, 0, -2, -2, -1, -1, + 0, -1, 1, 1, -1, -1, 0, 0, 0, -1, 1, 1, -1, -1, 0, 0, + 0, 1, 2, 1, -1, -1, 0, 1, 1, 2, 3, 2, 0, 0, 1, 2, + -1, 0, 2, 1, 0, 0, 2, 3, -2, -1, 0, 0, -1, 0, 1, 2, + 1, 1, 0, -1, -2, -2, -1, 1, 1, 1, 1, -1, -2, -2, 0, 2, + 1, 1, 1, -1, -1, -1, 0, 2, 0, 0, 0, 0, 0, 0, 1, 2, + -1, -1, -1, 0, 0, 0, 1, 2, -1, -2, -1, 1, 1, 1, 0, 0, + -1, -2, -1, 1, 2, 2, 0, -1, -1, -2, -1, 2, 2, 2, 0, -1, + -1, -1, -1, -2, -1, -1, 0, 1, 0, 0, -1, -1, -1, 0, 1, 2, + 1, 0, 0, 0, 0, 1, 1, 2, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, + 1, 2, 1, 0, -1, -2, -2, -3, 2, 2, 1, 0, -2, -3, -4, -4, + -4, -2, 1, 1, 1, 1, 0, 0, -2, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 1, -2, -2, -1, 0, 1, 2, 2, 1, -2, -2, -1, 1, 2, + 1, 2, 1, -2, -2, -1, 1, 2, -1, 1, 1, -1, -1, -1, 0, 1, + -2, 0, 1, 1, 0, -1, -1, 0, -2, 0, 2, 2, 1, -1, -1, 0, + 1, 1, 0, 0, 0, 1, 0, 0, -2, -3, -3, -2, -2, -1, 0, 0, + -3, -4, -3, -2, -1, 0, 0, 0, -1, -1, 0, 1, 2, 3, 2, 1, + 0, 1, 2, 3, 3, 3, 2, 1, 1, 1, 1, 2, 1, 0, 0, -1, + 0, 0, 0, 0, -1, -1, -1, -1, 0, -1, -1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, -1, -1, 0, 2, 0, 0, 1, 0, -1, -1, 1, 1, + -2, -1, 0, 1, 1, 1, 1, 1, -3, -3, 0, 2, 2, 1, 1, 0, + -2, -2, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, -1, + 3, 1, -1, -3, -2, -1, 0, 1, 4, 2, -1, -3, -3, -1, 1, 2, + 0, 0, 0, -1, -1, -1, -1, -1, 1, 2, 1, 0, 0, 0, -1, -1, + 2, 3, 3, 2, 1, 0, -1, -1, 3, 4, 4, 2, 1, 0, -1, -2, + 3, 3, 2, 1, 0, -1, -2, -2, 1, 1, 0, -1, -1, -2, -2, -3, + 0, 0, 0, -1, -1, -2, -2, -2, -1, -1, -1, -1, -1, -2, -2, -1, + 1, 2, 2, 2, 2, 1, 2, 2, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, -1, -2, 0, 0, 0, 0, 1, 0, -1, -4, + 1, 0, 0, 0, 0, 0, -2, -5, 1, 0, 0, 0, 0, 0, -1, -4, + 1, 0, -1, 0, 0, 0, -1, -3, 0, -1, -1, 0, 1, 1, 1, -1, + -2, -1, 0, 0, -1, -1, -1, -2, -1, 0, 0, 0, -1, -1, -2, -2, + 0, 1, 1, 0, -1, -1, -1, -2, 0, 1, 1, 0, 0, 0, -1, -1, + 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 2, 2, 1, + 1, 1, 0, 0, 1, 2, 2, 1, 1, 1, 0, -1, 0, 1, 1, 0, + 4, 2, 1, 0, 0, 1, 1, 1, 4, 2, 1, 0, 0, 0, 0, 1, + 3, 1, 0, 0, -1, -1, -1, 0, 1, 0, 0, -1, -1, -2, -1, 0, + 0, 0, 0, 0, -1, -1, -1, 0, -1, -1, 0, 0, -1, -1, 0, 1, + -2, -1, 0, -1, -1, 0, 0, 1, -2, -2, -1, -2, -1, 0, 0, 1, + 0, 1, 1, 1, 2, 1, 0, -1, -1, -1, -1, 0, 0, -1, -2, -2, + -1, 0, -1, 0, 0, -1, -2, -1, 0, 0, 0, 0, 0, 0, 1, 2, + 0, 0, 0, 0, 0, 0, 2, 3, -1, 0, -1, -1, -1, -1, 0, 3, + -1, 0, 0, -1, -1, -2, 0, 3, 0, 0, 0, 0, -1, -1, 1, 4, + 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, -1, -2, -1, -2, -1, 1, + -1, -1, -2, -2, -2, -3, -2, 0, -1, 0, -1, -1, -1, -2, -1, 1, + 1, 1, 0, 0, 1, 0, 0, 1, 2, 2, 0, 0, 1, 0, 0, 1, + 2, 2, 0, 0, 0, 0, -1, -1, 2, 2, 0, 0, 1, 0, -1, -1, + -1, 0, 1, 1, 0, -1, -1, -1, 1, 2, 3, 2, 1, 0, 0, 0, + 0, 1, 1, 1, 0, -1, 0, 0, -2, -2, -1, 0, 1, 0, 0, 0, + -2, -2, -1, 2, 2, 2, 1, 0, -2, -1, 0, 1, 1, 0, 0, -1, + -1, -1, 0, 0, -1, -2, -1, -2, 0, 1, 1, 1, 0, 0, 1, 1, + -3, -3, -3, -2, -1, -1, -2, -2, -1, -1, 0, 1, 2, 1, 0, 0, + 1, 1, 1, 2, 2, 1, 0, 0, 1, 1, 1, 1, 1, 0, -1, 1, + 1, 0, -1, -1, 0, 0, -1, 1, 0, -1, -1, -1, 0, -1, -1, 1, + 1, 0, -1, 0, 0, -1, 0, 2, 2, 0, -1, 0, 0, 0, 0, 2, + 1, 0, -2, -1, 0, 1, 1, 0, 2, 0, -1, -1, 0, 1, 1, 0, + 1, 0, -2, -1, 0, 1, 0, -1, 1, 0, -1, -1, 0, 1, 0, -1, + 0, 1, 1, 0, 1, 1, 0, 0, -2, 1, 2, 1, 0, 0, 0, 1, + -5, 0, 2, 1, 0, -1, 0, 1, -6, -1, 2, 1, 0, -1, 0, 0, + 5, 3, 0, -1, -2, -1, -1, -1, 1, 1, 0, -1, -1, 0, -1, -1, + -1, 0, 1, 1, 2, 2, 1, 0, -2, -1, 0, 1, 2, 1, 1, 1, + -2, -1, -1, -1, 0, -1, 0, 1, 0, 1, 0, 0, -1, -1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, -3, -2, 0, 1, 1, 0, 0, -1, + -1, 0, 1, 0, -1, 0, 2, 3, -1, 0, 0, -2, -4, -2, -1, 0, + 0, 1, 1, 0, -2, -1, 0, -1, 1, 2, 3, 1, 0, 1, 1, 0, + -1, 0, 1, 1, 1, 1, 1, 0, -2, -3, -2, 0, 0, 0, 1, 0, + -1, -2, -2, 0, 1, 0, 0, -1, 3, 1, 0, 0, 1, 0, -1, -1, + -2, -1, 0, 0, -1, -1, 0, 0, -1, 0, 0, 0, 0, 1, 1, 1, + -1, -1, -1, 0, 1, 1, 1, 1, 0, -2, -3, -1, 1, 0, 0, 0, + 1, -1, -3, -1, 1, 1, 0, -1, 3, 1, -1, 1, 2, 2, 0, -1, + 3, 1, 0, 1, 2, 1, 1, 0, 0, -2, -2, -1, -1, 0, 0, 0, + 1, 0, -1, -1, 1, 2, 1, 0, 0, -1, -2, -1, 1, 2, 2, 1, + -1, -1, -1, 0, 0, 1, 2, 0, -2, 0, 0, 0, 0, 0, 1, -1, + -1, 0, 1, 0, -1, -1, -1, -1, 0, 1, 1, 2, 0, -2, -1, 0, + 1, 2, 2, 2, 1, -1, -1, 0, 0, 1, 1, 1, 0, -2, -2, -1, + 0, 0, -1, -1, -1, -1, -2, -2, 0, 0, -1, 0, 1, 2, 2, 1, + 0, 0, -1, -1, 0, 1, 2, 2, 1, 1, -1, -2, -1, -1, -1, -1, + 2, 2, 1, 0, 0, -1, -2, -2, 1, 2, 2, 1, 0, 0, -2, -2, + 0, 0, 0, 0, 1, 1, 0, -1, 0, -1, -1, -1, 2, 3, 2, 1, + 0, -2, 1, 2, -1, 0, 0, 1, -1, -2, 2, 3, -1, 0, 0, 0, + 0, -2, 2, 3, -1, -1, 0, 0, 0, -1, 3, 2, -2, 0, 1, 0, + 0, -1, 3, 1, -2, 0, 1, 0, 0, -1, 2, 1, -1, 1, 0, -1, + 0, 0, 1, -1, -2, 0, 0, -1, 1, 0, 0, -2, -2, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -2, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 2, 3, 1, 0, 0, -1, 0, 0, 1, 2, + 0, -1, -1, -2, -1, 0, 1, 2, -2, -2, -2, -2, -1, 0, 1, 1, + -1, -1, -1, -1, 0, 0, 0, -1, 2, 2, 2, 0, -1, -1, -2, -4, + -1, -2, -1, -1, 0, 1, 2, 3, -1, -1, -1, -1, 0, 1, 2, 3, + 1, 0, -1, 0, -1, 0, 1, 2, 1, 0, 0, 0, -1, 0, 2, 2, + 1, 0, -1, -1, -2, 0, 1, 2, 0, -2, -2, -2, -3, -1, 0, 1, + 0, -2, -2, -2, -2, -1, 1, 1, 0, 0, 0, 0, 0, 1, 2, 2 }; -const uint32 *const s_svq1IntraCodebooks[6] = { +static const int8 *const s_svq1IntraCodebooks[6] = { s_svq1IntraCodebook4x2, s_svq1IntraCodebook4x4, s_svq1IntraCodebook8x4, s_svq1IntraCodebook8x8, 0, 0 diff --git a/video/coktel_decoder.cpp b/video/coktel_decoder.cpp index ae0c35cd76..5d7efe87af 100644 --- a/video/coktel_decoder.cpp +++ b/video/coktel_decoder.cpp @@ -53,7 +53,8 @@ CoktelDecoder::CoktelDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundT _mixer(mixer), _soundType(soundType), _width(0), _height(0), _x(0), _y(0), _defaultX(0), _defaultY(0), _features(0), _frameCount(0), _paletteDirty(false), _ownSurface(true), _frameRate(12), _hasSound(false), _soundEnabled(false), - _soundStage(kSoundNone), _audioStream(0) { + _soundStage(kSoundNone), _audioStream(0), _startTime(0), _pauseStartTime(0), + _isPaused(false) { assert(_mixer); @@ -261,6 +262,10 @@ bool CoktelDecoder::isPaletted() const { return true; } +int CoktelDecoder::getCurFrame() const { + return _curFrame; +} + void CoktelDecoder::close() { disableSound(); freeSurface(); @@ -273,9 +278,22 @@ void CoktelDecoder::close() { _features = 0; - _frameCount = 0; + _curFrame = -1; + _frameCount = 0; + + _startTime = 0; _hasSound = false; + + _isPaused = false; +} + +Audio::Mixer::SoundType CoktelDecoder::getSoundType() const { + return _soundType; +} + +Audio::AudioStream *CoktelDecoder::getAudioStream() const { + return _audioStream; } uint16 CoktelDecoder::getWidth() const { @@ -291,6 +309,7 @@ uint32 CoktelDecoder::getFrameCount() const { } const byte *CoktelDecoder::getPalette() { + _paletteDirty = false; return _palette; } @@ -625,14 +644,45 @@ Common::Rational CoktelDecoder::getFrameRate() const { return _frameRate; } +uint32 CoktelDecoder::getTimeToNextFrame() const { + if (endOfVideo() || _curFrame < 0) + return 0; + + uint32 elapsedTime = g_system->getMillis() - _startTime; + uint32 nextFrameStartTime = (Common::Rational((_curFrame + 1) * 1000) / getFrameRate()).toInt(); + + if (nextFrameStartTime <= elapsedTime) + return 0; + + return nextFrameStartTime - elapsedTime; +} + uint32 CoktelDecoder::getStaticTimeToNextFrame() const { return (1000 / _frameRate).toInt(); } +void CoktelDecoder::pauseVideo(bool pause) { + if (_isPaused != pause) { + if (_isPaused) { + // Add the time we were paused to the initial starting time + _startTime += g_system->getMillis() - _pauseStartTime; + } else { + // Store the time we paused for use later + _pauseStartTime = g_system->getMillis(); + } + + _isPaused = pause; + } +} + inline void CoktelDecoder::unsignedToSigned(byte *buffer, int length) { while (length-- > 0) *buffer++ ^= 0x80; } +bool CoktelDecoder::endOfVideo() const { + return !isVideoLoaded() || (getCurFrame() >= (int32)getFrameCount() - 1); +} + PreIMDDecoder::PreIMDDecoder(uint16 width, uint16 height, Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : CoktelDecoder(mixer, soundType), @@ -646,6 +696,21 @@ PreIMDDecoder::~PreIMDDecoder() { close(); } +bool PreIMDDecoder::reloadStream(Common::SeekableReadStream *stream) { + if (!_stream) + return false; + + if (!stream->seek(_stream->pos())) { + close(); + return false; + } + + delete _stream; + _stream = stream; + + return true; +} + bool PreIMDDecoder::seek(int32 frame, int whence, bool restart) { if (!evaluateSeekFrame(frame, whence)) return false; @@ -690,8 +755,6 @@ bool PreIMDDecoder::loadStream(Common::SeekableReadStream *stream) { } void PreIMDDecoder::close() { - reset(); - CoktelDecoder::close(); delete _stream; @@ -840,6 +903,21 @@ IMDDecoder::~IMDDecoder() { close(); } +bool IMDDecoder::reloadStream(Common::SeekableReadStream *stream) { + if (!_stream) + return false; + + if (!stream->seek(_stream->pos())) { + close(); + return false; + } + + delete _stream; + _stream = stream; + + return true; +} + bool IMDDecoder::seek(int32 frame, int whence, bool restart) { if (!evaluateSeekFrame(frame, whence)) return false; @@ -1129,8 +1207,6 @@ bool IMDDecoder::loadFrameTables(uint32 framePosPos, uint32 frameCoordsPos) { } void IMDDecoder::close() { - reset(); - CoktelDecoder::close(); delete _stream; @@ -1195,8 +1271,6 @@ void IMDDecoder::processFrame() { _dirtyRects.clear(); - _paletteDirty = false; - uint32 cmd = 0; bool hasNextCmd = false; bool startSound = false; @@ -1243,7 +1317,7 @@ void IMDDecoder::processFrame() { // Set palette if (cmd == kCommandPalette) { _stream->skip(2); - + _paletteDirty = true; for (int i = 0; i < 768; i++) @@ -1512,7 +1586,7 @@ VMDDecoder::VMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : _soundLastFilledFrame(0), _audioFormat(kAudioFormat8bitRaw), _hasVideo(false), _videoCodec(0), _blitMode(0), _bytesPerPixel(0), _firstFramePos(0), _videoBufferSize(0), _externalCodec(false), _codec(0), - _subtitle(-1), _isPaletted(true) { + _subtitle(-1), _isPaletted(true), _autoStartSound(true) { _videoBuffer [0] = 0; _videoBuffer [1] = 0; @@ -1526,6 +1600,21 @@ VMDDecoder::~VMDDecoder() { close(); } +bool VMDDecoder::reloadStream(Common::SeekableReadStream *stream) { + if (!_stream) + return false; + + if (!stream->seek(_stream->pos())) { + close(); + return false; + } + + delete _stream; + _stream = stream; + + return true; +} + bool VMDDecoder::seek(int32 frame, int whence, bool restart) { if (!evaluateSeekFrame(frame, whence)) return false; @@ -1959,8 +2048,6 @@ bool VMDDecoder::readFiles() { } void VMDDecoder::close() { - reset(); - CoktelDecoder::close(); delete _stream; @@ -2040,7 +2127,6 @@ void VMDDecoder::processFrame() { _dirtyRects.clear(); - _paletteDirty = false; _subtitle = -1; bool startSound = false; @@ -2160,8 +2246,9 @@ void VMDDecoder::processFrame() { if (startSound && _soundEnabled) { if (_hasSound && _audioStream) { - _mixer->playStream(_soundType, &_audioHandle, _audioStream, - -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); + if (_autoStartSound) + _mixer->playStream(_soundType, &_audioHandle, _audioStream, + -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); _soundStage = kSoundPlaying; } else _soundStage = kSoundNone; @@ -2687,6 +2774,94 @@ bool VMDDecoder::isPaletted() const { return _isPaletted; } +void VMDDecoder::setAutoStartSound(bool autoStartSound) { + _autoStartSound = autoStartSound; +} + +AdvancedVMDDecoder::AdvancedVMDDecoder(Audio::Mixer::SoundType soundType) { + _decoder = new VMDDecoder(g_system->getMixer(), soundType); + _decoder->setAutoStartSound(false); +} + +AdvancedVMDDecoder::~AdvancedVMDDecoder() { + close(); + delete _decoder; +} + +bool AdvancedVMDDecoder::loadStream(Common::SeekableReadStream *stream) { + close(); + + if (!_decoder->loadStream(stream)) + return false; + + if (_decoder->hasVideo()) { + _videoTrack = new VMDVideoTrack(_decoder); + addTrack(_videoTrack); + } + + if (_decoder->hasSound()) { + _audioTrack = new VMDAudioTrack(_decoder); + addTrack(_audioTrack); + } + + return true; +} + +void AdvancedVMDDecoder::close() { + VideoDecoder::close(); + _decoder->close(); +} + +AdvancedVMDDecoder::VMDVideoTrack::VMDVideoTrack(VMDDecoder *decoder) : _decoder(decoder) { +} + +uint16 AdvancedVMDDecoder::VMDVideoTrack::getWidth() const { + return _decoder->getWidth(); +} + +uint16 AdvancedVMDDecoder::VMDVideoTrack::getHeight() const { + return _decoder->getHeight(); +} + +Graphics::PixelFormat AdvancedVMDDecoder::VMDVideoTrack::getPixelFormat() const { + return _decoder->getPixelFormat(); +} + +int AdvancedVMDDecoder::VMDVideoTrack::getCurFrame() const { + return _decoder->getCurFrame(); +} + +int AdvancedVMDDecoder::VMDVideoTrack::getFrameCount() const { + return _decoder->getFrameCount(); +} + +const Graphics::Surface *AdvancedVMDDecoder::VMDVideoTrack::decodeNextFrame() { + return _decoder->decodeNextFrame(); +} + +const byte *AdvancedVMDDecoder::VMDVideoTrack::getPalette() const { + return _decoder->getPalette(); +} + +bool AdvancedVMDDecoder::VMDVideoTrack::hasDirtyPalette() const { + return _decoder->hasDirtyPalette(); +} + +Common::Rational AdvancedVMDDecoder::VMDVideoTrack::getFrameRate() const { + return _decoder->getFrameRate(); +} + +AdvancedVMDDecoder::VMDAudioTrack::VMDAudioTrack(VMDDecoder *decoder) : _decoder(decoder) { +} + +Audio::Mixer::SoundType AdvancedVMDDecoder::VMDAudioTrack::getSoundType() const { + return _decoder->getSoundType(); +} + +Audio::AudioStream *AdvancedVMDDecoder::VMDAudioTrack::getAudioStream() const { + return _decoder->getAudioStream(); +} + } // End of namespace Video #endif // VIDEO_COKTELDECODER_H diff --git a/video/coktel_decoder.h b/video/coktel_decoder.h index b99a44f332..91d52b65e6 100644 --- a/video/coktel_decoder.h +++ b/video/coktel_decoder.h @@ -64,7 +64,7 @@ class Codec; * - gob * - sci */ -class CoktelDecoder : public FixedRateVideoDecoder { +class CoktelDecoder { public: struct State { /** Set accordingly to what was done. */ @@ -77,7 +77,10 @@ public: CoktelDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); - ~CoktelDecoder(); + virtual ~CoktelDecoder(); + + /** Replace the current video stream with this identical one. */ + virtual bool reloadStream(Common::SeekableReadStream *stream) = 0; virtual bool seek(int32 frame, int whence = SEEK_SET, bool restart = false) = 0; @@ -95,6 +98,8 @@ public: /** Override the video's frame rate. */ void setFrameRate(Common::Rational frameRate); + /** Get the video's frame rate. */ + Common::Rational getFrameRate() const; /** Get the video's default X position. */ uint16 getDefaultX() const; @@ -135,21 +140,52 @@ public: /** Is the video paletted or true color? */ virtual bool isPaletted() const; + /** + * Get the current frame + * @see VideoDecoder::getCurFrame() + */ + int getCurFrame() const; + + /** + * Decode the next frame + * @see VideoDecoder::decodeNextFrame() + */ + virtual const Graphics::Surface *decodeNextFrame() = 0; - // VideoDecoder interface + /** + * Load a video from a stream + * @see VideoDecoder::loadStream() + */ + virtual bool loadStream(Common::SeekableReadStream *stream) = 0; + /** Has a video been loaded? */ + virtual bool isVideoLoaded() const = 0; + + /** Has the end of the video been reached? */ + bool endOfVideo() const; + + /** Close the video. */ void close(); + /** Get the Mixer SoundType audio is being played with. */ + Audio::Mixer::SoundType getSoundType() const; + /** Get the AudioStream for the audio. */ + Audio::AudioStream *getAudioStream() const; + uint16 getWidth() const; uint16 getHeight() const; + virtual Graphics::PixelFormat getPixelFormat() const = 0; uint32 getFrameCount() const; const byte *getPalette(); bool hasDirtyPalette() const; + uint32 getTimeToNextFrame() const; uint32 getStaticTimeToNextFrame() const; + void pauseVideo(bool pause); + protected: enum SoundStage { kSoundNone = 0, ///< No sound. @@ -183,8 +219,11 @@ protected: uint32 _features; + int32 _curFrame; uint32 _frameCount; + uint32 _startTime; + byte _palette[768]; bool _paletteDirty; @@ -225,10 +264,9 @@ protected: // Sound helper functions inline void unsignedToSigned(byte *buffer, int length); - - // FixedRateVideoDecoder interface - - Common::Rational getFrameRate() const; +private: + uint32 _pauseStartTime; + bool _isPaused; }; class PreIMDDecoder : public CoktelDecoder { @@ -237,10 +275,9 @@ public: Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); ~PreIMDDecoder(); - bool seek(int32 frame, int whence = SEEK_SET, bool restart = false); - + bool reloadStream(Common::SeekableReadStream *stream); - // VideoDecoder interface + bool seek(int32 frame, int whence = SEEK_SET, bool restart = false); bool loadStream(Common::SeekableReadStream *stream); void close(); @@ -268,13 +305,12 @@ public: IMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); ~IMDDecoder(); + bool reloadStream(Common::SeekableReadStream *stream); + bool seek(int32 frame, int whence = SEEK_SET, bool restart = false); void setXY(uint16 x, uint16 y); - - // VideoDecoder interface - bool loadStream(Common::SeekableReadStream *stream); void close(); @@ -355,10 +391,14 @@ private: }; class VMDDecoder : public CoktelDecoder { +friend class AdvancedVMDDecoder; + public: VMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); ~VMDDecoder(); + bool reloadStream(Common::SeekableReadStream *stream); + bool seek(int32 frame, int whence = SEEK_SET, bool restart = false); void setXY(uint16 x, uint16 y); @@ -376,9 +416,6 @@ public: bool hasVideo() const; bool isPaletted() const; - - // VideoDecoder interface - bool loadStream(Common::SeekableReadStream *stream); void close(); @@ -388,6 +425,9 @@ public: Graphics::PixelFormat getPixelFormat() const; +protected: + void setAutoStartSound(bool autoStartSound); + private: enum PartType { kPartTypeSeparator = 0, @@ -459,6 +499,7 @@ private: uint32 _soundDataSize; uint32 _soundLastFilledFrame; AudioFormat _audioFormat; + bool _autoStartSound; // Video properties bool _hasVideo; @@ -513,6 +554,57 @@ private: bool getPartCoords(int16 frame, PartType type, int16 &x, int16 &y, int16 &width, int16 &height); }; +/** + * A wrapper around the VMD code that implements the VideoDecoder + * API. + */ +class AdvancedVMDDecoder : public VideoDecoder { +public: + AdvancedVMDDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); + ~AdvancedVMDDecoder(); + + bool loadStream(Common::SeekableReadStream *stream); + void close(); + +private: + class VMDVideoTrack : public FixedRateVideoTrack { + public: + VMDVideoTrack(VMDDecoder *decoder); + + uint16 getWidth() const; + uint16 getHeight() const; + Graphics::PixelFormat getPixelFormat() const; + int getCurFrame() const; + int getFrameCount() const; + const Graphics::Surface *decodeNextFrame(); + const byte *getPalette() const; + bool hasDirtyPalette() const; + + protected: + Common::Rational getFrameRate() const; + + private: + VMDDecoder *_decoder; + }; + + class VMDAudioTrack : public AudioTrack { + public: + VMDAudioTrack(VMDDecoder *decoder); + + Audio::Mixer::SoundType getSoundType() const; + + protected: + virtual Audio::AudioStream *getAudioStream() const; + + private: + VMDDecoder *_decoder; + }; + + VMDDecoder *_decoder; + VMDVideoTrack *_videoTrack; + VMDAudioTrack *_audioTrack; +}; + } // End of namespace Video #endif // VIDEO_COKTELDECODER_H diff --git a/video/dxa_decoder.cpp b/video/dxa_decoder.cpp index 7d1112a59c..5ac9bd2088 100644 --- a/video/dxa_decoder.cpp +++ b/video/dxa_decoder.cpp @@ -37,41 +37,43 @@ namespace Video { DXADecoder::DXADecoder() { - _fileStream = 0; - _surface = 0; - _dirtyPalette = false; +} - _frameBuffer1 = 0; - _frameBuffer2 = 0; - _scaledBuffer = 0; +DXADecoder::~DXADecoder() { + close(); +} - _inBuffer = 0; - _inBufferSize = 0; +bool DXADecoder::loadStream(Common::SeekableReadStream *stream) { + close(); - _decompBuffer = 0; - _decompBufferSize = 0; + uint32 tag = stream->readUint32BE(); - _width = 0; - _height = 0; + if (tag != MKTAG('D','E','X','A')) { + close(); + return false; + } - _frameSize = 0; - _frameCount = 0; - _frameRate = 0; + DXAVideoTrack *track = new DXAVideoTrack(stream); + addTrack(track); - _scaleMode = S_NONE; -} + readSoundData(stream); -DXADecoder::~DXADecoder() { - close(); + track->setFrameStartPos(); + return true; } -bool DXADecoder::loadStream(Common::SeekableReadStream *stream) { - close(); +void DXADecoder::readSoundData(Common::SeekableReadStream *stream) { + // Skip over the tag by default + stream->readUint32BE(); +} +DXADecoder::DXAVideoTrack::DXAVideoTrack(Common::SeekableReadStream *stream) { _fileStream = stream; - - uint32 tag = _fileStream->readUint32BE(); - assert(tag == MKTAG('D','E','X','A')); + _curFrame = -1; + _frameStartOffset = 0; + _decompBuffer = 0; + _inBuffer = 0; + memset(_palette, 0, 256 * 3); uint8 flags = _fileStream->readByte(); _frameCount = _fileStream->readUint16BE(); @@ -105,18 +107,14 @@ bool DXADecoder::loadStream(Common::SeekableReadStream *stream) { _frameSize = _width * _height; _decompBufferSize = _frameSize; - _frameBuffer1 = (uint8 *)malloc(_frameSize); + _frameBuffer1 = new byte[_frameSize]; memset(_frameBuffer1, 0, _frameSize); - _frameBuffer2 = (uint8 *)malloc(_frameSize); + _frameBuffer2 = new byte[_frameSize]; memset(_frameBuffer2, 0, _frameSize); - if (!_frameBuffer1 || !_frameBuffer2) - error("DXADecoder: Error allocating frame buffers (size %u)", _frameSize); _scaledBuffer = 0; if (_scaleMode != S_NONE) { - _scaledBuffer = (uint8 *)malloc(_frameSize); - if (!_scaledBuffer) - error("Error allocating scale buffer (size %u)", _frameSize); + _scaledBuffer = new byte[_frameSize]; memset(_scaledBuffer, 0, _frameSize); } @@ -148,36 +146,33 @@ bool DXADecoder::loadStream(Common::SeekableReadStream *stream) { } while (tag != 0); } #endif - - // Read the sound header - _soundTag = _fileStream->readUint32BE(); - - return true; } -void DXADecoder::close() { - if (!_fileStream) - return; - +DXADecoder::DXAVideoTrack::~DXAVideoTrack() { delete _fileStream; - _fileStream = 0; - delete _surface; - _surface = 0; + delete[] _frameBuffer1; + delete[] _frameBuffer2; + delete[] _scaledBuffer; + delete[] _inBuffer; + delete[] _decompBuffer; +} - free(_frameBuffer1); - free(_frameBuffer2); - free(_scaledBuffer); - free(_inBuffer); - free(_decompBuffer); +bool DXADecoder::DXAVideoTrack::rewind() { + _curFrame = -1; + _fileStream->seek(_frameStartOffset); + return true; +} - _inBuffer = 0; - _decompBuffer = 0; +Graphics::PixelFormat DXADecoder::DXAVideoTrack::getPixelFormat() const { + return _surface->format; +} - reset(); +void DXADecoder::DXAVideoTrack::setFrameStartPos() { + _frameStartOffset = _fileStream->pos(); } -void DXADecoder::decodeZlib(byte *data, int size, int totalSize) { +void DXADecoder::DXAVideoTrack::decodeZlib(byte *data, int size, int totalSize) { #ifdef USE_ZLIB unsigned long dstLen = totalSize; Common::uncompress(data, &dstLen, _inBuffer, size); @@ -187,14 +182,13 @@ void DXADecoder::decodeZlib(byte *data, int size, int totalSize) { #define BLOCKW 4 #define BLOCKH 4 -void DXADecoder::decode12(int size) { +void DXADecoder::DXAVideoTrack::decode12(int size) { #ifdef USE_ZLIB - if (_decompBuffer == NULL) { - _decompBuffer = (byte *)malloc(_decompBufferSize); + if (!_decompBuffer) { + _decompBuffer = new byte[_decompBufferSize]; memset(_decompBuffer, 0, _decompBufferSize); - if (_decompBuffer == NULL) - error("Error allocating decomp buffer (size %u)", _decompBufferSize); } + /* decompress the input data */ decodeZlib(_decompBuffer, size, _decompBufferSize); @@ -287,15 +281,13 @@ void DXADecoder::decode12(int size) { #endif } -void DXADecoder::decode13(int size) { +void DXADecoder::DXAVideoTrack::decode13(int size) { #ifdef USE_ZLIB uint8 *codeBuf, *dataBuf, *motBuf, *maskBuf; - if (_decompBuffer == NULL) { - _decompBuffer = (byte *)malloc(_decompBufferSize); + if (!_decompBuffer) { + _decompBuffer = new byte[_decompBufferSize]; memset(_decompBuffer, 0, _decompBufferSize); - if (_decompBuffer == NULL) - error("Error allocating decomp buffer (size %u)", _decompBufferSize); } /* decompress the input data */ @@ -475,7 +467,7 @@ void DXADecoder::decode13(int size) { #endif } -const Graphics::Surface *DXADecoder::decodeNextFrame() { +const Graphics::Surface *DXADecoder::DXAVideoTrack::decodeNextFrame() { uint32 tag = _fileStream->readUint32BE(); if (tag == MKTAG('C','M','A','P')) { _fileStream->read(_palette, 256 * 3); @@ -486,11 +478,10 @@ const Graphics::Surface *DXADecoder::decodeNextFrame() { if (tag == MKTAG('F','R','A','M')) { byte type = _fileStream->readByte(); uint32 size = _fileStream->readUint32BE(); - if ((_inBuffer == NULL) || (_inBufferSize < size)) { - free(_inBuffer); - _inBuffer = (byte *)malloc(size); - if (_inBuffer == NULL) - error("Error allocating input buffer (size %u)", size); + + if (!_inBuffer || _inBufferSize < size) { + delete[] _inBuffer; + _inBuffer = new byte[size]; memset(_inBuffer, 0, size); _inBufferSize = size; } @@ -551,9 +542,6 @@ const Graphics::Surface *DXADecoder::decodeNextFrame() { _curFrame++; - if (_curFrame == 0) - _startTime = g_system->getMillis(); - return _surface; } diff --git a/video/dxa_decoder.h b/video/dxa_decoder.h index d13cd3076c..b3f2eca5e2 100644 --- a/video/dxa_decoder.h +++ b/video/dxa_decoder.h @@ -41,62 +41,74 @@ namespace Video { * - sword1 * - sword2 */ -class DXADecoder : public FixedRateVideoDecoder { +class DXADecoder : public VideoDecoder { public: DXADecoder(); virtual ~DXADecoder(); bool loadStream(Common::SeekableReadStream *stream); - void close(); - - bool isVideoLoaded() const { return _fileStream != 0; } - uint16 getWidth() const { return _width; } - uint16 getHeight() const { return _height; } - uint32 getFrameCount() const { return _frameCount; } - const Graphics::Surface *decodeNextFrame(); - Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } - const byte *getPalette() { _dirtyPalette = false; return _palette; } - bool hasDirtyPalette() const { return _dirtyPalette; } +protected: /** - * Get the sound chunk tag of the loaded DXA file + * Read the sound data out of the given DXA stream */ - uint32 getSoundTag() { return _soundTag; } - -protected: - Common::Rational getFrameRate() const { return _frameRate; } - - Common::SeekableReadStream *_fileStream; + virtual void readSoundData(Common::SeekableReadStream *stream); private: - void decodeZlib(byte *data, int size, int totalSize); - void decode12(int size); - void decode13(int size); - - enum ScaleMode { - S_NONE, - S_INTERLACED, - S_DOUBLE + class DXAVideoTrack : public FixedRateVideoTrack { + public: + DXAVideoTrack(Common::SeekableReadStream *stream); + ~DXAVideoTrack(); + + bool isRewindable() const { return true; } + bool rewind(); + + uint16 getWidth() const { return _width; } + uint16 getHeight() const { return _height; } + Graphics::PixelFormat getPixelFormat() const; + int getCurFrame() const { return _curFrame; } + int getFrameCount() const { return _frameCount; } + const Graphics::Surface *decodeNextFrame(); + const byte *getPalette() const { _dirtyPalette = false; return _palette; } + bool hasDirtyPalette() const { return _dirtyPalette; } + + void setFrameStartPos(); + + protected: + Common::Rational getFrameRate() const { return _frameRate; } + + private: + void decodeZlib(byte *data, int size, int totalSize); + void decode12(int size); + void decode13(int size); + + enum ScaleMode { + S_NONE, + S_INTERLACED, + S_DOUBLE + }; + + Common::SeekableReadStream *_fileStream; + Graphics::Surface *_surface; + + byte *_frameBuffer1; + byte *_frameBuffer2; + byte *_scaledBuffer; + byte *_inBuffer; + uint32 _inBufferSize; + byte *_decompBuffer; + uint32 _decompBufferSize; + uint16 _curHeight; + uint32 _frameSize; + ScaleMode _scaleMode; + uint16 _width, _height; + uint32 _frameRate; + uint32 _frameCount; + byte _palette[256 * 3]; + mutable bool _dirtyPalette; + int _curFrame; + uint32 _frameStartOffset; }; - - Graphics::Surface *_surface; - byte _palette[256 * 3]; - bool _dirtyPalette; - - byte *_frameBuffer1; - byte *_frameBuffer2; - byte *_scaledBuffer; - byte *_inBuffer; - uint32 _inBufferSize; - byte *_decompBuffer; - uint32 _decompBufferSize; - uint16 _curHeight; - uint32 _frameSize; - ScaleMode _scaleMode; - uint32 _soundTag; - uint16 _width, _height; - uint32 _frameRate; - uint32 _frameCount; }; } // End of namespace Video diff --git a/video/flic_decoder.cpp b/video/flic_decoder.cpp index bdcdedc142..1a0627615b 100644 --- a/video/flic_decoder.cpp +++ b/video/flic_decoder.cpp @@ -26,13 +26,11 @@ #include "common/stream.h" #include "common/system.h" #include "common/textconsole.h" +#include "graphics/surface.h" namespace Video { FlicDecoder::FlicDecoder() { - _paletteChanged = false; - _fileStream = 0; - _surface = 0; } FlicDecoder::~FlicDecoder() { @@ -42,35 +40,59 @@ FlicDecoder::~FlicDecoder() { bool FlicDecoder::loadStream(Common::SeekableReadStream *stream) { close(); - _fileStream = stream; - - /* uint32 frameSize = */ _fileStream->readUint32LE(); - uint16 frameType = _fileStream->readUint16LE(); + /* uint32 frameSize = */ stream->readUint32LE(); + uint16 frameType = stream->readUint16LE(); // Check FLC magic number if (frameType != 0xAF12) { - warning("FlicDecoder::FlicDecoder(): attempted to load non-FLC data (type = 0x%04X)", frameType); - delete _fileStream; - _fileStream = 0; + warning("FlicDecoder::loadStream(): attempted to load non-FLC data (type = 0x%04X)", frameType); return false; } - - _frameCount = _fileStream->readUint16LE(); - uint16 width = _fileStream->readUint16LE(); - uint16 height = _fileStream->readUint16LE(); - uint16 colorDepth = _fileStream->readUint16LE(); + uint16 frameCount = stream->readUint16LE(); + uint16 width = stream->readUint16LE(); + uint16 height = stream->readUint16LE(); + uint16 colorDepth = stream->readUint16LE(); if (colorDepth != 8) { - warning("FlicDecoder::FlicDecoder(): attempted to load an FLC with a palette of color depth %d. Only 8-bit color palettes are supported", frameType); - delete _fileStream; - _fileStream = 0; + warning("FlicDecoder::loadStream(): attempted to load an FLC with a palette of color depth %d. Only 8-bit color palettes are supported", colorDepth); return false; } + addTrack(new FlicVideoTrack(stream, frameCount, width, height)); + return true; +} + +const Common::List<Common::Rect> *FlicDecoder::getDirtyRects() const { + const Track *track = getTrack(0); + + if (track) + return ((const FlicVideoTrack *)track)->getDirtyRects(); + + return 0; +} + +void FlicDecoder::clearDirtyRects() { + Track *track = getTrack(0); + + if (track) + ((FlicVideoTrack *)track)->clearDirtyRects(); +} + +void FlicDecoder::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) { + Track *track = getTrack(0); + + if (track) + ((FlicVideoTrack *)track)->copyDirtyRectsToBuffer(dst, pitch); +} + +FlicDecoder::FlicVideoTrack::FlicVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height) { + _fileStream = stream; + _frameCount = frameCount; + _fileStream->readUint16LE(); // flags // Note: The normal delay is a 32-bit integer (dword), whereas the overridden delay is a 16-bit integer (word) // the frame delay is the FLIC "speed", in milliseconds. - _frameRate = Common::Rational(1000, _fileStream->readUint32LE()); + _frameDelay = _startFrameDelay = _fileStream->readUint32LE(); _fileStream->seek(80); _offsetFrame1 = _fileStream->readUint32LE(); @@ -78,112 +100,53 @@ bool FlicDecoder::loadStream(Common::SeekableReadStream *stream) { _surface = new Graphics::Surface(); _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); - _palette = (byte *)malloc(3 * 256); + _palette = new byte[3 * 256]; memset(_palette, 0, 3 * 256); - _paletteChanged = false; + _dirtyPalette = false; + + _curFrame = -1; + _nextFrameStartTime = 0; + _atRingFrame = false; // Seek to the first frame _fileStream->seek(_offsetFrame1); - return true; } -void FlicDecoder::close() { - if (!_fileStream) - return; - +FlicDecoder::FlicVideoTrack::~FlicVideoTrack() { delete _fileStream; - _fileStream = 0; + delete[] _palette; _surface->free(); delete _surface; - _surface = 0; - - free(_palette); - _dirtyRects.clear(); - - reset(); } -void FlicDecoder::decodeByteRun(uint8 *data) { - byte *ptr = (byte *)_surface->pixels; - while ((int32)(ptr - (byte *)_surface->pixels) < (getWidth() * getHeight())) { - int chunks = *data++; - while (chunks--) { - int count = (int8)*data++; - if (count > 0) { - memset(ptr, *data++, count); - } else { - count = -count; - memcpy(ptr, data, count); - data += count; - } - ptr += count; - } - } - - // Redraw - _dirtyRects.clear(); - _dirtyRects.push_back(Common::Rect(0, 0, getWidth(), getHeight())); +bool FlicDecoder::FlicVideoTrack::endOfTrack() const { + return getCurFrame() >= getFrameCount() - 1; } -#define OP_PACKETCOUNT 0 -#define OP_UNDEFINED 1 -#define OP_LASTPIXEL 2 -#define OP_LINESKIPCOUNT 3 - -void FlicDecoder::decodeDeltaFLC(uint8 *data) { - uint16 linesInChunk = READ_LE_UINT16(data); data += 2; - uint16 currentLine = 0; - uint16 packetCount = 0; - - while (linesInChunk--) { - uint16 opcode; +bool FlicDecoder::FlicVideoTrack::rewind() { + _curFrame = -1; + _nextFrameStartTime = 0; - // First process all the opcodes. - do { - opcode = READ_LE_UINT16(data); data += 2; + if (endOfTrack() && _fileStream->pos() < _fileStream->size()) + _atRingFrame = true; + else + _fileStream->seek(_offsetFrame1); - switch ((opcode >> 14) & 3) { - case OP_PACKETCOUNT: - packetCount = opcode; - break; - case OP_UNDEFINED: - break; - case OP_LASTPIXEL: - *((byte *)_surface->pixels + currentLine * getWidth() + getWidth() - 1) = (opcode & 0xFF); - _dirtyRects.push_back(Common::Rect(getWidth() - 1, currentLine, getWidth(), currentLine + 1)); - break; - case OP_LINESKIPCOUNT: - currentLine += -(int16)opcode; - break; - } - } while (((opcode >> 14) & 3) != OP_PACKETCOUNT); + _frameDelay = _startFrameDelay; + return true; +} - uint16 column = 0; +uint16 FlicDecoder::FlicVideoTrack::getWidth() const { + return _surface->w; +} - // Now interpret the RLE data - while (packetCount--) { - column += *data++; - int rleCount = (int8)*data++; - if (rleCount > 0) { - memcpy((byte *)_surface->pixels + (currentLine * getWidth()) + column, data, rleCount * 2); - data += rleCount * 2; - _dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1)); - } else if (rleCount < 0) { - rleCount = -rleCount; - uint16 dataWord = READ_UINT16(data); data += 2; - for (int i = 0; i < rleCount; ++i) { - WRITE_UINT16((byte *)_surface->pixels + currentLine * getWidth() + column + i * 2, dataWord); - } - _dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1)); - } else { // End of cutscene ? - return; - } - column += rleCount * 2; - } +uint16 FlicDecoder::FlicVideoTrack::getHeight() const { + return _surface->h; +} - currentLine++; - } +Graphics::PixelFormat FlicDecoder::FlicVideoTrack::getPixelFormat() const { + return _surface->format; } #define FLI_SETPAL 4 @@ -192,7 +155,7 @@ void FlicDecoder::decodeDeltaFLC(uint8 *data) { #define PSTAMP 18 #define FRAME_TYPE 0xF1FA -const Graphics::Surface *FlicDecoder::decodeNextFrame() { +const Graphics::Surface *FlicDecoder::FlicVideoTrack::decodeNextFrame() { // Read chunk uint32 frameSize = _fileStream->readUint32LE(); uint16 frameType = _fileStream->readUint16LE(); @@ -201,15 +164,12 @@ const Graphics::Surface *FlicDecoder::decodeNextFrame() { switch (frameType) { case FRAME_TYPE: { - // FIXME: FLIC should be switched over to a variable frame rate VideoDecoder to handle - // this properly. - chunkCount = _fileStream->readUint16LE(); // Note: The overridden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword) // the frame delay is the FLIC "speed", in milliseconds. uint16 newFrameDelay = _fileStream->readUint16LE(); // "speed", in milliseconds if (newFrameDelay > 0) - _frameRate = Common::Rational(1000, newFrameDelay); + _frameDelay = newFrameDelay; _fileStream->readUint16LE(); // reserved, always 0 uint16 newWidth = _fileStream->readUint16LE(); @@ -240,10 +200,11 @@ const Graphics::Surface *FlicDecoder::decodeNextFrame() { frameType = _fileStream->readUint16LE(); uint8 *data = new uint8[frameSize - 6]; _fileStream->read(data, frameSize - 6); + switch (frameType) { case FLI_SETPAL: unpackPalette(data); - _paletteChanged = true; + _dirtyPalette = true; break; case FLI_SS2: decodeDeltaFLC(data); @@ -264,26 +225,111 @@ const Graphics::Surface *FlicDecoder::decodeNextFrame() { } _curFrame++; + _nextFrameStartTime += _frameDelay; - // If we just processed the ring frame, set the next frame - if (_curFrame == (int32)_frameCount) { - _curFrame = 0; + if (_atRingFrame) { + // If we decoded the ring frame, seek to the second frame + _atRingFrame = false; _fileStream->seek(_offsetFrame2); } - if (_curFrame == 0) - _startTime = g_system->getMillis(); - return _surface; } -void FlicDecoder::reset() { - FixedRateVideoDecoder::reset(); - if (_fileStream) - _fileStream->seek(_offsetFrame1); +void FlicDecoder::FlicVideoTrack::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) { + for (Common::List<Common::Rect>::const_iterator it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { + for (int y = (*it).top; y < (*it).bottom; ++y) { + const int x = (*it).left; + memcpy(dst + y * pitch + x, (byte *)_surface->pixels + y * getWidth() + x, (*it).right - x); + } + } + + clearDirtyRects(); } -void FlicDecoder::unpackPalette(uint8 *data) { +void FlicDecoder::FlicVideoTrack::decodeByteRun(uint8 *data) { + byte *ptr = (byte *)_surface->pixels; + while ((int32)(ptr - (byte *)_surface->pixels) < (getWidth() * getHeight())) { + int chunks = *data++; + while (chunks--) { + int count = (int8)*data++; + if (count > 0) { + memset(ptr, *data++, count); + } else { + count = -count; + memcpy(ptr, data, count); + data += count; + } + ptr += count; + } + } + + // Redraw + _dirtyRects.clear(); + _dirtyRects.push_back(Common::Rect(0, 0, getWidth(), getHeight())); +} + +#define OP_PACKETCOUNT 0 +#define OP_UNDEFINED 1 +#define OP_LASTPIXEL 2 +#define OP_LINESKIPCOUNT 3 + +void FlicDecoder::FlicVideoTrack::decodeDeltaFLC(uint8 *data) { + uint16 linesInChunk = READ_LE_UINT16(data); data += 2; + uint16 currentLine = 0; + uint16 packetCount = 0; + + while (linesInChunk--) { + uint16 opcode; + + // First process all the opcodes. + do { + opcode = READ_LE_UINT16(data); data += 2; + + switch ((opcode >> 14) & 3) { + case OP_PACKETCOUNT: + packetCount = opcode; + break; + case OP_UNDEFINED: + break; + case OP_LASTPIXEL: + *((byte *)_surface->pixels + currentLine * getWidth() + getWidth() - 1) = (opcode & 0xFF); + _dirtyRects.push_back(Common::Rect(getWidth() - 1, currentLine, getWidth(), currentLine + 1)); + break; + case OP_LINESKIPCOUNT: + currentLine += -(int16)opcode; + break; + } + } while (((opcode >> 14) & 3) != OP_PACKETCOUNT); + + uint16 column = 0; + + // Now interpret the RLE data + while (packetCount--) { + column += *data++; + int rleCount = (int8)*data++; + if (rleCount > 0) { + memcpy((byte *)_surface->pixels + (currentLine * getWidth()) + column, data, rleCount * 2); + data += rleCount * 2; + _dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1)); + } else if (rleCount < 0) { + rleCount = -rleCount; + uint16 dataWord = READ_UINT16(data); data += 2; + for (int i = 0; i < rleCount; ++i) { + WRITE_UINT16((byte *)_surface->pixels + currentLine * getWidth() + column + i * 2, dataWord); + } + _dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1)); + } else { // End of cutscene ? + return; + } + column += rleCount * 2; + } + + currentLine++; + } +} + +void FlicDecoder::FlicVideoTrack::unpackPalette(uint8 *data) { uint16 numPackets = READ_LE_UINT16(data); data += 2; if (0 == READ_LE_UINT16(data)) { //special case @@ -308,14 +354,4 @@ void FlicDecoder::unpackPalette(uint8 *data) { } } -void FlicDecoder::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) { - for (Common::List<Common::Rect>::const_iterator it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { - for (int y = (*it).top; y < (*it).bottom; ++y) { - const int x = (*it).left; - memcpy(dst + y * pitch + x, (byte *)_surface->pixels + y * getWidth() + x, (*it).right - x); - } - } - _dirtyRects.clear(); -} - } // End of namespace Video diff --git a/video/flic_decoder.h b/video/flic_decoder.h index 9badc3da2e..9037af05d6 100644 --- a/video/flic_decoder.h +++ b/video/flic_decoder.h @@ -25,15 +25,17 @@ #include "video/video_decoder.h" #include "common/list.h" -#include "common/rational.h" #include "common/rect.h" -#include "graphics/pixelformat.h" -#include "graphics/surface.h" namespace Common { class SeekableReadStream; } +namespace Graphics { +struct PixelFormat; +struct Surface; +} + namespace Video { /** @@ -42,58 +44,63 @@ namespace Video { * Video decoder used in engines: * - tucker */ -class FlicDecoder : public FixedRateVideoDecoder { +class FlicDecoder : public VideoDecoder { public: FlicDecoder(); virtual ~FlicDecoder(); - /** - * Load a video file - * @param stream the stream to load - */ bool loadStream(Common::SeekableReadStream *stream); - void close(); - - /** - * Decode the next frame and return the frame's surface - * @note the return surface should *not* be freed - * @note this may return 0, in which case the last frame should be kept on screen - */ - const Graphics::Surface *decodeNextFrame(); - - bool isVideoLoaded() const { return _fileStream != 0; } - uint16 getWidth() const { return _surface->w; } - uint16 getHeight() const { return _surface->h; } - uint32 getFrameCount() const { return _frameCount; } - Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } - - const Common::List<Common::Rect> *getDirtyRects() const { return &_dirtyRects; } - void clearDirtyRects() { _dirtyRects.clear(); } - void copyDirtyRectsToBuffer(uint8 *dst, uint pitch); - - const byte *getPalette() { _paletteChanged = false; return _palette; } - bool hasDirtyPalette() const { return _paletteChanged; } - void reset(); -protected: - Common::Rational getFrameRate() const { return _frameRate; } + const Common::List<Common::Rect> *getDirtyRects() const; + void clearDirtyRects(); + void copyDirtyRectsToBuffer(uint8 *dst, uint pitch); private: - uint16 _offsetFrame1; - uint16 _offsetFrame2; - byte *_palette; - bool _paletteChanged; - - void decodeByteRun(uint8 *data); - void decodeDeltaFLC(uint8 *data); - void unpackPalette(uint8 *mem); - - Common::SeekableReadStream *_fileStream; - Graphics::Surface *_surface; - uint32 _frameCount; - Common::Rational _frameRate; - - Common::List<Common::Rect> _dirtyRects; + class FlicVideoTrack : public VideoTrack { + public: + FlicVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height); + ~FlicVideoTrack(); + + bool endOfTrack() const; + bool isRewindable() const { return true; } + bool rewind(); + + uint16 getWidth() const; + uint16 getHeight() const; + Graphics::PixelFormat getPixelFormat() const; + int getCurFrame() const { return _curFrame; } + int getFrameCount() const { return _frameCount; } + uint32 getNextFrameStartTime() const { return _nextFrameStartTime; } + const Graphics::Surface *decodeNextFrame(); + const byte *getPalette() const { _dirtyPalette = false; return _palette; } + bool hasDirtyPalette() const { return _dirtyPalette; } + + const Common::List<Common::Rect> *getDirtyRects() const { return &_dirtyRects; } + void clearDirtyRects() { _dirtyRects.clear(); } + void copyDirtyRectsToBuffer(uint8 *dst, uint pitch); + + private: + Common::SeekableReadStream *_fileStream; + Graphics::Surface *_surface; + + int _curFrame; + bool _atRingFrame; + + uint16 _offsetFrame1; + uint16 _offsetFrame2; + byte *_palette; + mutable bool _dirtyPalette; + + uint32 _frameCount; + uint32 _frameDelay, _startFrameDelay; + uint32 _nextFrameStartTime; + + Common::List<Common::Rect> _dirtyRects; + + void decodeByteRun(uint8 *data); + void decodeDeltaFLC(uint8 *data); + void unpackPalette(uint8 *mem); + }; }; } // End of namespace Video diff --git a/video/module.mk b/video/module.mk index cebd403ca2..287e14ce18 100644 --- a/video/module.mk +++ b/video/module.mk @@ -26,5 +26,10 @@ MODULE_OBJS += \ bink_decoder.o endif +ifdef USE_THEORADEC +MODULE_OBJS += \ + theora_decoder.o +endif + # Include common rules include $(srcdir)/rules.mk diff --git a/video/psx_decoder.cpp b/video/psx_decoder.cpp index 7c04b7f041..fa7f1e8cfe 100644 --- a/video/psx_decoder.cpp +++ b/video/psx_decoder.cpp @@ -149,22 +149,12 @@ static const uint32 s_huffmanACSymbols[AC_CODE_COUNT] = { END_OF_BLOCK }; -PSXStreamDecoder::PSXStreamDecoder(CDSpeed speed, uint32 frameCount) : _nextFrameStartTime(0, speed), _frameCount(frameCount) { +PSXStreamDecoder::PSXStreamDecoder(CDSpeed speed, uint32 frameCount) : _speed(speed), _frameCount(frameCount) { _stream = 0; - _audStream = 0; - _surface = new Graphics::Surface(); - _yBuffer = _cbBuffer = _crBuffer = 0; - _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); } PSXStreamDecoder::~PSXStreamDecoder() { close(); - delete _surface; - delete _acHuffman; - delete _dcHuffmanLuma; - delete _dcHuffmanChroma; } #define RAW_CD_SECTOR_SIZE 2352 @@ -178,95 +168,30 @@ bool PSXStreamDecoder::loadStream(Common::SeekableReadStream *stream) { close(); _stream = stream; - - Common::SeekableReadStream *sector = readSector(); - - if (!sector) { - close(); - return false; - } - - // Rip out video info from the first frame - sector->seek(18); - byte sectorType = sector->readByte() & CDXA_TYPE_MASK; - - if (sectorType != CDXA_TYPE_VIDEO && sectorType != CDXA_TYPE_DATA) { - close(); - return false; - } - - sector->seek(40); - - uint16 width = sector->readUint16LE(); - uint16 height = sector->readUint16LE(); - _surface->create(width, height, g_system->getScreenFormat()); - - _macroBlocksW = (width + 15) / 16; - _macroBlocksH = (height + 15) / 16; - _yBuffer = new byte[_macroBlocksW * _macroBlocksH * 16 * 16]; - _cbBuffer = new byte[_macroBlocksW * _macroBlocksH * 8 * 8]; - _crBuffer = new byte[_macroBlocksW * _macroBlocksH * 8 * 8]; - - delete sector; - _stream->seek(0); + readNextPacket(); return true; } void PSXStreamDecoder::close() { - if (!_stream) - return; + VideoDecoder::close(); + _audioTrack = 0; + _videoTrack = 0; + _frameCount = 0; delete _stream; _stream = 0; - - // Deinitialize sound - g_system->getMixer()->stopHandle(_audHandle); - _audStream = 0; - - _surface->free(); - - memset(&_adpcmStatus, 0, sizeof(_adpcmStatus)); - - _macroBlocksW = _macroBlocksH = 0; - delete[] _yBuffer; _yBuffer = 0; - delete[] _cbBuffer; _cbBuffer = 0; - delete[] _crBuffer; _crBuffer = 0; - - reset(); -} - -uint32 PSXStreamDecoder::getElapsedTime() const { - // TODO: Currently, the audio is always after the video so using this - // can often lead to gaps in the audio... - //if (_audStream) - // return _mixer->getSoundElapsedTime(_audHandle); - - return VideoDecoder::getElapsedTime(); -} - -uint32 PSXStreamDecoder::getTimeToNextFrame() const { - if (!isVideoLoaded() || endOfVideo()) - return 0; - - uint32 nextTimeMillis = _nextFrameStartTime.msecs(); - uint32 elapsedTime = getElapsedTime(); - - if (elapsedTime > nextTimeMillis) - return 0; - - return nextTimeMillis - elapsedTime; } #define VIDEO_DATA_CHUNK_SIZE 2016 #define VIDEO_DATA_HEADER_SIZE 56 -const Graphics::Surface *PSXStreamDecoder::decodeNextFrame() { +void PSXStreamDecoder::readNextPacket() { Common::SeekableReadStream *sector = 0; byte *partialFrame = 0; int sectorsRead = 0; - while (!endOfVideo()) { + while (_stream->pos() < _stream->size()) { sector = readSector(); sectorsRead++; @@ -284,6 +209,11 @@ const Graphics::Surface *PSXStreamDecoder::decodeNextFrame() { case CDXA_TYPE_DATA: case CDXA_TYPE_VIDEO: if (track == 1) { + if (!_videoTrack) { + _videoTrack = new PSXVideoTrack(sector, _speed, _frameCount); + addTrack(_videoTrack); + } + sector->seek(28); uint16 curSector = sector->readUint16LE(); uint16 sectorCount = sector->readUint16LE(); @@ -303,35 +233,27 @@ const Graphics::Surface *PSXStreamDecoder::decodeNextFrame() { // Done assembling the frame Common::SeekableReadStream *frame = new Common::MemoryReadStream(partialFrame, frameSize, DisposeAfterUse::YES); - decodeFrame(frame); + _videoTrack->decodeFrame(frame, sectorsRead); delete frame; delete sector; - - _curFrame++; - if (_curFrame == 0) - _startTime = g_system->getMillis(); - - // Increase the time by the amount of sectors we read - // One may notice that this is still not the most precise - // method since a frame takes up the time its sectors took - // up instead of the amount of time it takes the next frame - // to be read from the sectors. The actual frame rate should - // be constant instead of variable, so the slight difference - // in a frame's showing time is negligible (1/150 of a second). - _nextFrameStartTime = _nextFrameStartTime.addFrames(sectorsRead); - - return _surface; + return; } } else error("Unhandled multi-track video"); break; case CDXA_TYPE_AUDIO: // We only handle one audio channel so far - if (track == 1) - queueAudioFromSector(sector); - else + if (track == 1) { + if (!_audioTrack) { + _audioTrack = new PSXAudioTrack(sector); + addTrack(_audioTrack); + } + + _audioTrack->queueAudioFromSector(sector); + } else { warning("Unhandled multi-track audio"); + } break; default: // This shows up way too often, but the other sectors @@ -343,7 +265,19 @@ const Graphics::Surface *PSXStreamDecoder::decodeNextFrame() { delete sector; } - return 0; + if (_stream->pos() >= _stream->size()) { + if (_videoTrack) + _videoTrack->setEndOfTrack(); + + if (_audioTrack) + _audioTrack->setEndOfTrack(); + } +} + +bool PSXStreamDecoder::useAudioSync() const { + // Audio sync is disabled since most audio data comes after video + // data. + return false; } static const byte s_syncHeader[12] = { 0x00, 0xff ,0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; @@ -373,20 +307,29 @@ static const int s_xaTable[5][2] = { { 122, -60 } }; -void PSXStreamDecoder::queueAudioFromSector(Common::SeekableReadStream *sector) { +PSXStreamDecoder::PSXAudioTrack::PSXAudioTrack(Common::SeekableReadStream *sector) { assert(sector); + _endOfTrack = false; + + sector->seek(19); + byte format = sector->readByte(); + bool stereo = (format & (1 << 0)) != 0; + uint rate = (format & (1 << 2)) ? 18900 : 37800; + _audStream = Audio::makeQueuingAudioStream(rate, stereo); - if (!_audStream) { - // Initialize audio stream - sector->seek(19); - byte format = sector->readByte(); + memset(&_adpcmStatus, 0, sizeof(_adpcmStatus)); +} - bool stereo = (format & (1 << 0)) != 0; - uint rate = (format & (1 << 2)) ? 18900 : 37800; +PSXStreamDecoder::PSXAudioTrack::~PSXAudioTrack() { + delete _audStream; +} - _audStream = Audio::makeQueuingAudioStream(rate, stereo); - g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audHandle, _audStream); - } +bool PSXStreamDecoder::PSXAudioTrack::endOfTrack() const { + return AudioTrack::endOfTrack() && _endOfTrack; +} + +void PSXStreamDecoder::PSXAudioTrack::queueAudioFromSector(Common::SeekableReadStream *sector) { + assert(sector); sector->seek(24); @@ -472,7 +415,54 @@ void PSXStreamDecoder::queueAudioFromSector(Common::SeekableReadStream *sector) delete[] buf; } -void PSXStreamDecoder::decodeFrame(Common::SeekableReadStream *frame) { +Audio::AudioStream *PSXStreamDecoder::PSXAudioTrack::getAudioStream() const { + return _audStream; +} + + +PSXStreamDecoder::PSXVideoTrack::PSXVideoTrack(Common::SeekableReadStream *firstSector, CDSpeed speed, int frameCount) : _nextFrameStartTime(0, speed), _frameCount(frameCount) { + assert(firstSector); + + firstSector->seek(40); + uint16 width = firstSector->readUint16LE(); + uint16 height = firstSector->readUint16LE(); + _surface = new Graphics::Surface(); + _surface->create(width, height, g_system->getScreenFormat()); + + _macroBlocksW = (width + 15) / 16; + _macroBlocksH = (height + 15) / 16; + _yBuffer = new byte[_macroBlocksW * _macroBlocksH * 16 * 16]; + _cbBuffer = new byte[_macroBlocksW * _macroBlocksH * 8 * 8]; + _crBuffer = new byte[_macroBlocksW * _macroBlocksH * 8 * 8]; + + _endOfTrack = false; + _curFrame = -1; + _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); +} + +PSXStreamDecoder::PSXVideoTrack::~PSXVideoTrack() { + _surface->free(); + delete _surface; + + delete[] _yBuffer; + delete[] _cbBuffer; + delete[] _crBuffer; + delete _acHuffman; + delete _dcHuffmanChroma; + delete _dcHuffmanLuma; +} + +uint32 PSXStreamDecoder::PSXVideoTrack::getNextFrameStartTime() const { + return _nextFrameStartTime.msecs(); +} + +const Graphics::Surface *PSXStreamDecoder::PSXVideoTrack::decodeNextFrame() { + return _surface; +} + +void PSXStreamDecoder::PSXVideoTrack::decodeFrame(Common::SeekableReadStream *frame, uint sectorCount) { // A frame is essentially an MPEG-1 intra frame Common::BitStream16LEMSB bits(frame); @@ -494,9 +484,20 @@ void PSXStreamDecoder::decodeFrame(Common::SeekableReadStream *frame) { // Output data onto the frame Graphics::convertYUV420ToRGB(_surface, _yBuffer, _cbBuffer, _crBuffer, _surface->w, _surface->h, _macroBlocksW * 16, _macroBlocksW * 8); + + _curFrame++; + + // Increase the time by the amount of sectors we read + // One may notice that this is still not the most precise + // method since a frame takes up the time its sectors took + // up instead of the amount of time it takes the next frame + // to be read from the sectors. The actual frame rate should + // be constant instead of variable, so the slight difference + // in a frame's showing time is negligible (1/150 of a second). + _nextFrameStartTime = _nextFrameStartTime.addFrames(sectorCount); } -void PSXStreamDecoder::decodeMacroBlock(Common::BitStream *bits, int mbX, int mbY, uint16 scale, uint16 version) { +void PSXStreamDecoder::PSXVideoTrack::decodeMacroBlock(Common::BitStream *bits, int mbX, int mbY, uint16 scale, uint16 version) { int pitchY = _macroBlocksW * 16; int pitchC = _macroBlocksW * 8; @@ -533,7 +534,7 @@ static const byte s_quantizationTable[8 * 8] = { 27, 29, 35, 38, 46, 56, 69, 83 }; -void PSXStreamDecoder::dequantizeBlock(int *coefficients, float *block, uint16 scale) { +void PSXStreamDecoder::PSXVideoTrack::dequantizeBlock(int *coefficients, float *block, uint16 scale) { // Dequantize the data, un-zig-zagging as we go along for (int i = 0; i < 8 * 8; i++) { if (i == 0) // Special case for the DC coefficient @@ -543,7 +544,7 @@ void PSXStreamDecoder::dequantizeBlock(int *coefficients, float *block, uint16 s } } -int PSXStreamDecoder::readDC(Common::BitStream *bits, uint16 version, PlaneType plane) { +int PSXStreamDecoder::PSXVideoTrack::readDC(Common::BitStream *bits, uint16 version, PlaneType plane) { // Version 2 just has its coefficient as 10-bits if (version == 2) return readSignedCoefficient(bits); @@ -573,7 +574,7 @@ int PSXStreamDecoder::readDC(Common::BitStream *bits, uint16 version, PlaneType if (count > 63) \ error("PSXStreamDecoder::readAC(): Too many coefficients") -void PSXStreamDecoder::readAC(Common::BitStream *bits, int *block) { +void PSXStreamDecoder::PSXVideoTrack::readAC(Common::BitStream *bits, int *block) { // Clear the block first for (int i = 0; i < 63; i++) block[i] = 0; @@ -608,7 +609,7 @@ void PSXStreamDecoder::readAC(Common::BitStream *bits, int *block) { } } -int PSXStreamDecoder::readSignedCoefficient(Common::BitStream *bits) { +int PSXStreamDecoder::PSXVideoTrack::readSignedCoefficient(Common::BitStream *bits) { uint val = bits->getBits(10); // extend the sign @@ -630,7 +631,7 @@ static const double s_idct8x8[8][8] = { { 0.353553390593274, -0.490392640201615, 0.461939766255643, -0.415734806151273, 0.353553390593273, -0.277785116509801, 0.191341716182545, -0.097545161008064 } }; -void PSXStreamDecoder::idct(float *dequantData, float *result) { +void PSXStreamDecoder::PSXVideoTrack::idct(float *dequantData, float *result) { // IDCT code based on JPEG's IDCT code // TODO: Switch to the integer-based one mentioned in the docs // This is by far the costliest operation here @@ -669,7 +670,7 @@ void PSXStreamDecoder::idct(float *dequantData, float *result) { } } -void PSXStreamDecoder::decodeBlock(Common::BitStream *bits, byte *block, int pitch, uint16 scale, uint16 version, PlaneType plane) { +void PSXStreamDecoder::PSXVideoTrack::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]; @@ -686,12 +687,13 @@ void PSXStreamDecoder::decodeBlock(Common::BitStream *bits, byte *block, int pit // Now output the data for (int y = 0; y < 8; y++) { - byte *start = block + pitch * y; + byte *dst = block + pitch * y; // Convert the result to be in the range [0, 255] for (int x = 0; x < 8; x++) - *start++ = (int)CLIP<float>(idctData[y * 8 + x], -128.0f, 127.0f) + 128; + *dst++ = (int)CLIP<float>(idctData[y * 8 + x], -128.0f, 127.0f) + 128; } } + } // End of namespace Video diff --git a/video/psx_decoder.h b/video/psx_decoder.h index c8ad92c45a..11f311594d 100644 --- a/video/psx_decoder.h +++ b/video/psx_decoder.h @@ -71,54 +71,85 @@ public: bool loadStream(Common::SeekableReadStream *stream); void close(); - bool isVideoLoaded() const { return _stream != 0; } - uint16 getWidth() const { return _surface->w; } - uint16 getHeight() const { return _surface->h; } - uint32 getFrameCount() const { return _frameCount; } - uint32 getElapsedTime() const; - uint32 getTimeToNextFrame() const; - const Graphics::Surface *decodeNextFrame(); - Graphics::PixelFormat getPixelFormat() const { return _surface->format; } - bool endOfVideo() const { return _stream->pos() >= _stream->size(); } +protected: + void readNextPacket(); + bool useAudioSync() const; private: - void initCommon(); - Common::SeekableReadStream *_stream; - Graphics::Surface *_surface; + class PSXVideoTrack : public VideoTrack { + public: + PSXVideoTrack(Common::SeekableReadStream *firstSector, CDSpeed speed, int frameCount); + ~PSXVideoTrack(); + + uint16 getWidth() const { return _surface->w; } + uint16 getHeight() const { return _surface->h; } + Graphics::PixelFormat getPixelFormat() const { return _surface->format; } + bool endOfTrack() const { return _endOfTrack; } + int getCurFrame() const { return _curFrame; } + int getFrameCount() const { return _frameCount; } + uint32 getNextFrameStartTime() const; + const Graphics::Surface *decodeNextFrame(); + + void setEndOfTrack() { _endOfTrack = true; } + void decodeFrame(Common::SeekableReadStream *frame, uint sectorCount); + + private: + Graphics::Surface *_surface; + uint32 _frameCount; + Audio::Timestamp _nextFrameStartTime; + bool _endOfTrack; + int _curFrame; + + enum PlaneType { + kPlaneY = 0, + kPlaneU = 1, + kPlaneV = 2 + }; + + uint16 _macroBlocksW, _macroBlocksH; + byte *_yBuffer, *_cbBuffer, *_crBuffer; + 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, PlaneType plane); + + 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); + }; - uint32 _frameCount; - Audio::Timestamp _nextFrameStartTime; + class PSXAudioTrack : public AudioTrack { + public: + PSXAudioTrack(Common::SeekableReadStream *sector); + ~PSXAudioTrack(); - Audio::SoundHandle _audHandle; - Audio::QueuingAudioStream *_audStream; - void queueAudioFromSector(Common::SeekableReadStream *sector); + bool endOfTrack() const; - enum PlaneType { - kPlaneY = 0, - kPlaneU = 1, - kPlaneV = 2 - }; + void setEndOfTrack() { _endOfTrack = true; } + void queueAudioFromSector(Common::SeekableReadStream *sector); - 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, PlaneType plane); + private: + Audio::AudioStream *getAudioStream() const; - void readAC(Common::BitStream *bits, int *block); - Common::Huffman *_acHuffman; + Audio::QueuingAudioStream *_audStream; - int readDC(Common::BitStream *bits, uint16 version, PlaneType plane); - Common::Huffman *_dcHuffmanLuma, *_dcHuffmanChroma; - int _lastDC[3]; + struct ADPCMStatus { + int16 sample[2]; + } _adpcmStatus[2]; - void dequantizeBlock(int *coefficients, float *block, uint16 scale); - void idct(float *dequantData, float *result); - int readSignedCoefficient(Common::BitStream *bits); + bool _endOfTrack; + }; - struct ADPCMStatus { - int16 sample[2]; - } _adpcmStatus[2]; + CDSpeed _speed; + uint32 _frameCount; + Common::SeekableReadStream *_stream; + PSXVideoTrack *_videoTrack; + PSXAudioTrack *_audioTrack; Common::SeekableReadStream *readSector(); }; diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp index 0d80c93a1f..87c530dba0 100644 --- a/video/qt_decoder.cpp +++ b/video/qt_decoder.cpp @@ -33,14 +33,12 @@ #include "audio/audiostream.h" #include "common/debug.h" -#include "common/endian.h" #include "common/memstream.h" #include "common/system.h" #include "common/textconsole.h" #include "common/util.h" // Video codecs -#include "video/codecs/codec.h" #include "video/codecs/cinepak.h" #include "video/codecs/mjpeg.h" #include "video/codecs/qtrle.h" @@ -56,97 +54,43 @@ namespace Video { //////////////////////////////////////////// QuickTimeDecoder::QuickTimeDecoder() { - _setStartTime = false; _scaledSurface = 0; - _dirtyPalette = false; - _palette = 0; _width = _height = 0; - _needUpdate = false; } QuickTimeDecoder::~QuickTimeDecoder() { close(); } -int32 QuickTimeDecoder::getCurFrame() const { - // TODO: This is rather simplistic and doesn't take edits that - // repeat sections of the media into account. Doing that - // over-complicates things and shouldn't be necessary, but - // it would be nice to have in the future. - - int32 frame = -1; - - for (uint32 i = 0; i < _handlers.size(); i++) - if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeVideo) - frame += ((VideoTrackHandler *)_handlers[i])->getCurFrame() + 1; - - return frame; -} - -uint32 QuickTimeDecoder::getFrameCount() const { - uint32 count = 0; - - for (uint32 i = 0; i < _handlers.size(); i++) - if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeVideo) - count += ((VideoTrackHandler *)_handlers[i])->getFrameCount(); - - return count; -} - -void QuickTimeDecoder::startAudio() { - updateAudioBuffer(); - - for (uint32 i = 0; i < _audioTracks.size(); i++) { - g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audioHandles[i], _audioTracks[i], -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); +bool QuickTimeDecoder::loadFile(const Common::String &filename) { + if (!Common::QuickTimeParser::parseFile(filename)) + return false; - // Pause the audio again if we're still paused - if (isPaused()) - g_system->getMixer()->pauseHandle(_audioHandles[i], true); - } + init(); + return true; } -void QuickTimeDecoder::stopAudio() { - for (uint32 i = 0; i < _audioHandles.size(); i++) - g_system->getMixer()->stopHandle(_audioHandles[i]); -} +bool QuickTimeDecoder::loadStream(Common::SeekableReadStream *stream) { + if (!Common::QuickTimeParser::parseStream(stream)) + return false; -void QuickTimeDecoder::pauseVideoIntern(bool pause) { - for (uint32 i = 0; i < _audioHandles.size(); i++) - g_system->getMixer()->pauseHandle(_audioHandles[i], pause); + init(); + return true; } -QuickTimeDecoder::VideoTrackHandler *QuickTimeDecoder::findNextVideoTrack() const { - VideoTrackHandler *bestTrack = 0; - uint32 bestTime = 0xffffffff; - - for (uint32 i = 0; i < _handlers.size(); i++) { - if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeVideo && !_handlers[i]->endOfTrack()) { - VideoTrackHandler *track = (VideoTrackHandler *)_handlers[i]; - uint32 time = track->getNextFrameStartTime(); +void QuickTimeDecoder::close() { + VideoDecoder::close(); + Common::QuickTimeParser::close(); - if (time < bestTime) { - bestTime = time; - bestTrack = track; - } - } + if (_scaledSurface) { + _scaledSurface->free(); + delete _scaledSurface; + _scaledSurface = 0; } - - return bestTrack; } const Graphics::Surface *QuickTimeDecoder::decodeNextFrame() { - if (!_nextVideoTrack) - return 0; - - const Graphics::Surface *frame = _nextVideoTrack->decodeNextFrame(); - - if (!_setStartTime) { - _startTime = g_system->getMillis(); - _setStartTime = true; - } - - _nextVideoTrack = findNextVideoTrack(); - _needUpdate = false; + const Graphics::Surface *frame = VideoDecoder::decodeNextFrame(); // Update audio buffers too // (needs to be done after we find the next track) @@ -166,126 +110,7 @@ const Graphics::Surface *QuickTimeDecoder::decodeNextFrame() { return frame; } -void QuickTimeDecoder::scaleSurface(const Graphics::Surface *src, Graphics::Surface *dst, Common::Rational scaleFactorX, Common::Rational scaleFactorY) { - assert(src && dst); - - for (int32 j = 0; j < dst->h; j++) - for (int32 k = 0; k < dst->w; k++) - memcpy(dst->getBasePtr(k, j), src->getBasePtr((k * scaleFactorX).toInt() , (j * scaleFactorY).toInt()), src->format.bytesPerPixel); -} - -bool QuickTimeDecoder::endOfVideo() const { - if (!isVideoLoaded()) - return true; - - for (uint32 i = 0; i < _handlers.size(); i++) - if (!_handlers[i]->endOfTrack()) - return false; - - return true; -} - -uint32 QuickTimeDecoder::getElapsedTime() const { - // Try to base sync off an active audio track - for (uint32 i = 0; i < _audioHandles.size(); i++) { - if (g_system->getMixer()->isSoundHandleActive(_audioHandles[i])) { - uint32 time = g_system->getMixer()->getSoundElapsedTime(_audioHandles[i]) + _audioStartOffset.msecs(); - if (Audio::Timestamp(time, 1000) < _audioTracks[i]->getLength()) - return time; - } - } - - // Just use time elapsed since the beginning - return SeekableVideoDecoder::getElapsedTime(); -} - -uint32 QuickTimeDecoder::getTimeToNextFrame() const { - if (_needUpdate) - return 0; - - if (_nextVideoTrack) { - uint32 nextFrameStartTime = _nextVideoTrack->getNextFrameStartTime(); - - if (nextFrameStartTime == 0) - return 0; - - // TODO: Add support for rate modification - - uint32 elapsedTime = getElapsedTime(); - - if (elapsedTime < nextFrameStartTime) - return nextFrameStartTime - elapsedTime; - } - - return 0; -} - -bool QuickTimeDecoder::loadFile(const Common::String &filename) { - if (!Common::QuickTimeParser::parseFile(filename)) - return false; - - init(); - return true; -} - -bool QuickTimeDecoder::loadStream(Common::SeekableReadStream *stream) { - if (!Common::QuickTimeParser::parseStream(stream)) - return false; - - init(); - return true; -} - -void QuickTimeDecoder::init() { - Audio::QuickTimeAudioDecoder::init(); - - _startTime = 0; - _setStartTime = false; - - // Initialize all the audio tracks - if (!_audioTracks.empty()) { - _audioHandles.resize(_audioTracks.size()); - - for (uint32 i = 0; i < _audioTracks.size(); i++) - _handlers.push_back(new AudioTrackHandler(this, _audioTracks[i])); - } - - // Initialize all the video tracks - for (uint32 i = 0; i < _tracks.size(); i++) { - if (_tracks[i]->codecType == CODEC_TYPE_VIDEO) { - for (uint32 j = 0; j < _tracks[i]->sampleDescs.size(); j++) - ((VideoSampleDesc *)_tracks[i]->sampleDescs[j])->initCodec(); - - _handlers.push_back(new VideoTrackHandler(this, _tracks[i])); - } - } - - // Prepare the first video track - _nextVideoTrack = findNextVideoTrack(); - - if (_nextVideoTrack) { - if (_scaleFactorX != 1 || _scaleFactorY != 1) { - // We have to take the scale into consideration when setting width/height - _width = (_nextVideoTrack->getWidth() / _scaleFactorX).toInt(); - _height = (_nextVideoTrack->getHeight() / _scaleFactorY).toInt(); - } else { - _width = _nextVideoTrack->getWidth().toInt(); - _height = _nextVideoTrack->getHeight().toInt(); - } - - _needUpdate = true; - } else { - _needUpdate = false; - } - - // Now start any audio - if (!_audioTracks.empty()) { - startAudio(); - _audioStartOffset = Audio::Timestamp(0); - } -} - -Common::QuickTimeParser::SampleDesc *QuickTimeDecoder::readSampleDesc(Track *track, uint32 format) { +Common::QuickTimeParser::SampleDesc *QuickTimeDecoder::readSampleDesc(Common::QuickTimeParser::Track *track, uint32 format) { if (track->codecType == CODEC_TYPE_VIDEO) { debug(0, "Video Codec FourCC: \'%s\'", tag2str(format)); @@ -383,61 +208,52 @@ Common::QuickTimeParser::SampleDesc *QuickTimeDecoder::readSampleDesc(Track *tra return Audio::QuickTimeAudioDecoder::readSampleDesc(track, format); } -void QuickTimeDecoder::close() { - stopAudio(); - freeAllTrackHandlers(); - - if (_scaledSurface) { - _scaledSurface->free(); - delete _scaledSurface; - _scaledSurface = 0; - } - - _width = _height = 0; - - Common::QuickTimeParser::close(); - SeekableVideoDecoder::reset(); -} - -void QuickTimeDecoder::freeAllTrackHandlers() { - for (uint32 i = 0; i < _handlers.size(); i++) - delete _handlers[i]; - - _handlers.clear(); -} +void QuickTimeDecoder::init() { + Audio::QuickTimeAudioDecoder::init(); -void QuickTimeDecoder::seekToTime(Audio::Timestamp time) { - stopAudio(); - _audioStartOffset = time; + // Initialize all the audio tracks + for (uint32 i = 0; i < _audioTracks.size(); i++) + addTrack(new AudioTrackHandler(this, _audioTracks[i])); - // Sets all tracks to this time - for (uint32 i = 0; i < _handlers.size(); i++) - _handlers[i]->seekToTime(time); + // Initialize all the video tracks + Common::Array<Common::QuickTimeParser::Track *> &tracks = Common::QuickTimeParser::_tracks; + for (uint32 i = 0; i < tracks.size(); i++) { + if (tracks[i]->codecType == CODEC_TYPE_VIDEO) { + for (uint32 j = 0; j < tracks[i]->sampleDescs.size(); j++) + ((VideoSampleDesc *)tracks[i]->sampleDescs[j])->initCodec(); - startAudio(); + addTrack(new VideoTrackHandler(this, tracks[i])); + } + } - // Reset our start time - _startTime = g_system->getMillis() - time.msecs(); - _setStartTime = true; - resetPauseStartTime(); + // Prepare the first video track + VideoTrackHandler *nextVideoTrack = (VideoTrackHandler *)findNextVideoTrack(); - // Reset the next video track too - _nextVideoTrack = findNextVideoTrack(); - _needUpdate = _nextVideoTrack != 0; + if (nextVideoTrack) { + if (_scaleFactorX != 1 || _scaleFactorY != 1) { + // We have to take the scale into consideration when setting width/height + _width = (nextVideoTrack->getScaledWidth() / _scaleFactorX).toInt(); + _height = (nextVideoTrack->getScaledHeight() / _scaleFactorY).toInt(); + } else { + _width = nextVideoTrack->getWidth(); + _height = nextVideoTrack->getHeight(); + } + } } void QuickTimeDecoder::updateAudioBuffer() { // Updates the audio buffers for all audio tracks - for (uint32 i = 0; i < _handlers.size(); i++) - if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeAudio) - ((AudioTrackHandler *)_handlers[i])->updateBuffer(); + for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++) + if ((*it)->getTrackType() == VideoDecoder::Track::kTrackTypeAudio) + ((AudioTrackHandler *)*it)->updateBuffer(); } -Graphics::PixelFormat QuickTimeDecoder::getPixelFormat() const { - if (_nextVideoTrack) - return _nextVideoTrack->getPixelFormat(); +void QuickTimeDecoder::scaleSurface(const Graphics::Surface *src, Graphics::Surface *dst, const Common::Rational &scaleFactorX, const Common::Rational &scaleFactorY) { + assert(src && dst); - return Graphics::PixelFormat(); + for (int32 j = 0; j < dst->h; j++) + for (int32 k = 0; k < dst->w; k++) + memcpy(dst->getBasePtr(k, j), src->getBasePtr((k * scaleFactorX).toInt() , (j * scaleFactorY).toInt()), src->format.bytesPerPixel); } QuickTimeDecoder::VideoSampleDesc::VideoSampleDesc(Common::QuickTimeParser::Track *parentTrack, uint32 codecTag) : Common::QuickTimeParser::SampleDesc(parentTrack, codecTag) { @@ -492,25 +308,8 @@ void QuickTimeDecoder::VideoSampleDesc::initCodec() { } } -bool QuickTimeDecoder::endOfVideoTracks() const { - for (uint32 i = 0; i < _handlers.size(); i++) - if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeVideo && !_handlers[i]->endOfTrack()) - return false; - - return true; -} - -QuickTimeDecoder::TrackHandler::TrackHandler(QuickTimeDecoder *decoder, Track *parent) : _decoder(decoder), _parent(parent), _fd(_decoder->_fd) { - _curEdit = 0; -} - -bool QuickTimeDecoder::TrackHandler::endOfTrack() { - // A track is over when we've finished going through all edits - return _curEdit == _parent->editCount; -} - QuickTimeDecoder::AudioTrackHandler::AudioTrackHandler(QuickTimeDecoder *decoder, QuickTimeAudioTrack *audioTrack) - : TrackHandler(decoder, audioTrack->getParent()), _audioTrack(audioTrack) { + : _decoder(decoder), _audioTrack(audioTrack) { } void QuickTimeDecoder::AudioTrackHandler::updateBuffer() { @@ -520,21 +319,20 @@ void QuickTimeDecoder::AudioTrackHandler::updateBuffer() { _audioTrack->queueAudio(Audio::Timestamp(_decoder->getTimeToNextFrame() + 500, 1000)); } -bool QuickTimeDecoder::AudioTrackHandler::endOfTrack() { - return _audioTrack->endOfData(); +Audio::SeekableAudioStream *QuickTimeDecoder::AudioTrackHandler::getSeekableAudioStream() const { + return _audioTrack; } -void QuickTimeDecoder::AudioTrackHandler::seekToTime(Audio::Timestamp time) { - _audioTrack->seek(time); -} - -QuickTimeDecoder::VideoTrackHandler::VideoTrackHandler(QuickTimeDecoder *decoder, Common::QuickTimeParser::Track *parent) : TrackHandler(decoder, parent) { +QuickTimeDecoder::VideoTrackHandler::VideoTrackHandler(QuickTimeDecoder *decoder, Common::QuickTimeParser::Track *parent) : _decoder(decoder), _parent(parent) { + _curEdit = 0; enterNewEditList(false); _holdNextFrameStartTime = false; _curFrame = -1; _durationOverride = -1; _scaledSurface = 0; + _curPalette = 0; + _dirtyPalette = false; } QuickTimeDecoder::VideoTrackHandler::~VideoTrackHandler() { @@ -544,6 +342,88 @@ QuickTimeDecoder::VideoTrackHandler::~VideoTrackHandler() { } } +bool QuickTimeDecoder::VideoTrackHandler::endOfTrack() const { + // A track is over when we've finished going through all edits + return _curEdit == _parent->editCount; +} + +bool QuickTimeDecoder::VideoTrackHandler::seek(const Audio::Timestamp &requestedTime) { + // First, figure out what edit we're in + Audio::Timestamp time = requestedTime.convertToFramerate(_parent->timeScale); + + // Continue until we get to where we need to be + for (_curEdit = 0; !endOfTrack(); _curEdit++) + if ((uint32)time.totalNumberOfFrames() >= getCurEditTimeOffset() && (uint32)time.totalNumberOfFrames() < getCurEditTimeOffset() + getCurEditTrackDuration()) + break; + + // This track is done + if (endOfTrack()) + return true; + + enterNewEditList(false); + + // One extra check for the end of a track + if (endOfTrack()) + return true; + + // Now we're in the edit and need to figure out what frame we need + while (getRateAdjustedFrameTime() < (uint32)time.totalNumberOfFrames()) { + _curFrame++; + if (_durationOverride >= 0) { + _nextFrameStartTime += _durationOverride; + _durationOverride = -1; + } else { + _nextFrameStartTime += getFrameDuration(); + } + } + + // All that's left is to figure out what our starting time is going to be + // Compare the starting point for the frame to where we need to be + _holdNextFrameStartTime = getRateAdjustedFrameTime() != (uint32)time.totalNumberOfFrames(); + + // If we went past the time, go back a frame + if (_holdNextFrameStartTime) + _curFrame--; + + // Handle the keyframe here + int32 destinationFrame = _curFrame + 1; + + assert(destinationFrame < (int32)_parent->frameCount); + _curFrame = findKeyFrame(destinationFrame) - 1; + while (_curFrame < destinationFrame - 1) + bufferNextFrame(); + + return true; +} + +Audio::Timestamp QuickTimeDecoder::VideoTrackHandler::getDuration() const { + return Audio::Timestamp(0, _parent->duration, _decoder->_timeScale); +} + +uint16 QuickTimeDecoder::VideoTrackHandler::getWidth() const { + return getScaledWidth().toInt(); +} + +uint16 QuickTimeDecoder::VideoTrackHandler::getHeight() const { + return getScaledHeight().toInt(); +} + +Graphics::PixelFormat QuickTimeDecoder::VideoTrackHandler::getPixelFormat() const { + return ((VideoSampleDesc *)_parent->sampleDescs[0])->_videoCodec->getPixelFormat(); +} + +int QuickTimeDecoder::VideoTrackHandler::getFrameCount() const { + return _parent->frameCount; +} + +uint32 QuickTimeDecoder::VideoTrackHandler::getNextFrameStartTime() const { + if (endOfTrack()) + return 0; + + // Convert to milliseconds so the tracks can be compared + return getRateAdjustedFrameTime() * 1000 / _parent->timeScale; +} + const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::decodeNextFrame() { if (endOfTrack()) return 0; @@ -574,7 +454,7 @@ const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::decodeNextFrame() if (frame && (_parent->scaleFactorX != 1 || _parent->scaleFactorY != 1)) { if (!_scaledSurface) { _scaledSurface = new Graphics::Surface(); - _scaledSurface->create(getWidth().toInt(), getHeight().toInt(), getPixelFormat()); + _scaledSurface->create(getScaledWidth().toInt(), getScaledHeight().toInt(), getPixelFormat()); } _decoder->scaleSurface(frame, _scaledSurface, _parent->scaleFactorX, _parent->scaleFactorY); @@ -584,6 +464,85 @@ const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::decodeNextFrame() return frame; } +Common::Rational QuickTimeDecoder::VideoTrackHandler::getScaledWidth() const { + return Common::Rational(_parent->width) / _parent->scaleFactorX; +} + +Common::Rational QuickTimeDecoder::VideoTrackHandler::getScaledHeight() const { + return Common::Rational(_parent->height) / _parent->scaleFactorY; +} + +Common::SeekableReadStream *QuickTimeDecoder::VideoTrackHandler::getNextFramePacket(uint32 &descId) { + // First, we have to track down which chunk holds the sample and which sample in the chunk contains the frame we are looking for. + int32 totalSampleCount = 0; + int32 sampleInChunk = 0; + int32 actualChunk = -1; + uint32 sampleToChunkIndex = 0; + + for (uint32 i = 0; i < _parent->chunkCount; i++) { + if (sampleToChunkIndex < _parent->sampleToChunkCount && i >= _parent->sampleToChunk[sampleToChunkIndex].first) + sampleToChunkIndex++; + + totalSampleCount += _parent->sampleToChunk[sampleToChunkIndex - 1].count; + + if (totalSampleCount > _curFrame) { + actualChunk = i; + descId = _parent->sampleToChunk[sampleToChunkIndex - 1].id; + sampleInChunk = _parent->sampleToChunk[sampleToChunkIndex - 1].count - totalSampleCount + _curFrame; + break; + } + } + + if (actualChunk < 0) { + warning("Could not find data for frame %d", _curFrame); + return 0; + } + + // Next seek to that frame + Common::SeekableReadStream *stream = _decoder->_fd; + stream->seek(_parent->chunkOffsets[actualChunk]); + + // Then, if the chunk holds more than one frame, seek to where the frame we want is located + for (int32 i = _curFrame - sampleInChunk; i < _curFrame; i++) { + if (_parent->sampleSize != 0) + stream->skip(_parent->sampleSize); + else + stream->skip(_parent->sampleSizes[i]); + } + + // Finally, read in the raw data for the frame + //debug("Frame Data[%d]: Offset = %d, Size = %d", _curFrame, stream->pos(), _parent->sampleSizes[_curFrame]); + + if (_parent->sampleSize != 0) + return stream->readStream(_parent->sampleSize); + + return stream->readStream(_parent->sampleSizes[_curFrame]); +} + +uint32 QuickTimeDecoder::VideoTrackHandler::getFrameDuration() { + uint32 curFrameIndex = 0; + for (int32 i = 0; i < _parent->timeToSampleCount; i++) { + curFrameIndex += _parent->timeToSample[i].count; + if ((uint32)_curFrame < curFrameIndex) { + // Ok, now we have what duration this frame has. + return _parent->timeToSample[i].duration; + } + } + + // This should never occur + error("Cannot find duration for frame %d", _curFrame); + return 0; +} + +uint32 QuickTimeDecoder::VideoTrackHandler::findKeyFrame(uint32 frame) const { + for (int i = _parent->keyframeCount - 1; i >= 0; i--) + if (_parent->keyframes[i] <= frame) + return _parent->keyframes[i]; + + // If none found, we'll assume the requested frame is a key frame + return frame; +} + void QuickTimeDecoder::VideoTrackHandler::enterNewEditList(bool bufferFrames) { // Bypass all empty edit lists first while (!endOfTrack() && _parent->editList[_curEdit].mediaTime == -1) @@ -655,166 +614,25 @@ const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::bufferNextFrame() if (entry->_videoCodec->containsPalette()) { // The codec itself contains a palette if (entry->_videoCodec->hasDirtyPalette()) { - _decoder->_palette = entry->_videoCodec->getPalette(); - _decoder->_dirtyPalette = true; + _curPalette = entry->_videoCodec->getPalette(); + _dirtyPalette = true; } } else { // Check if the video description has been updated byte *palette = entry->_palette; - if (palette !=_decoder-> _palette) { - _decoder->_palette = palette; - _decoder->_dirtyPalette = true; - } - } - - return frame; -} - -uint32 QuickTimeDecoder::VideoTrackHandler::getNextFrameStartTime() { - if (endOfTrack()) - return 0; - - // Convert to milliseconds so the tracks can be compared - return getRateAdjustedFrameTime() * 1000 / _parent->timeScale; -} - -uint32 QuickTimeDecoder::VideoTrackHandler::getFrameCount() { - return _parent->frameCount; -} - -uint32 QuickTimeDecoder::VideoTrackHandler::getFrameDuration() { - uint32 curFrameIndex = 0; - for (int32 i = 0; i < _parent->timeToSampleCount; i++) { - curFrameIndex += _parent->timeToSample[i].count; - if ((uint32)_curFrame < curFrameIndex) { - // Ok, now we have what duration this frame has. - return _parent->timeToSample[i].duration; - } - } - - // This should never occur - error("Cannot find duration for frame %d", _curFrame); - return 0; -} - -Common::SeekableReadStream *QuickTimeDecoder::VideoTrackHandler::getNextFramePacket(uint32 &descId) { - // First, we have to track down which chunk holds the sample and which sample in the chunk contains the frame we are looking for. - int32 totalSampleCount = 0; - int32 sampleInChunk = 0; - int32 actualChunk = -1; - uint32 sampleToChunkIndex = 0; - - for (uint32 i = 0; i < _parent->chunkCount; i++) { - if (sampleToChunkIndex < _parent->sampleToChunkCount && i >= _parent->sampleToChunk[sampleToChunkIndex].first) - sampleToChunkIndex++; - - totalSampleCount += _parent->sampleToChunk[sampleToChunkIndex - 1].count; - - if (totalSampleCount > _curFrame) { - actualChunk = i; - descId = _parent->sampleToChunk[sampleToChunkIndex - 1].id; - sampleInChunk = _parent->sampleToChunk[sampleToChunkIndex - 1].count - totalSampleCount + _curFrame; - break; + if (palette != _curPalette) { + _curPalette = palette; + _dirtyPalette = true; } } - if (actualChunk < 0) { - warning("Could not find data for frame %d", _curFrame); - return 0; - } - - // Next seek to that frame - _fd->seek(_parent->chunkOffsets[actualChunk]); - - // Then, if the chunk holds more than one frame, seek to where the frame we want is located - for (int32 i = _curFrame - sampleInChunk; i < _curFrame; i++) { - if (_parent->sampleSize != 0) - _fd->skip(_parent->sampleSize); - else - _fd->skip(_parent->sampleSizes[i]); - } - - // Finally, read in the raw data for the frame - //debug("Frame Data[%d]: Offset = %d, Size = %d", _curFrame, _fd->pos(), _parent->sampleSizes[_curFrame]); - - if (_parent->sampleSize != 0) - return _fd->readStream(_parent->sampleSize); - - return _fd->readStream(_parent->sampleSizes[_curFrame]); -} - -uint32 QuickTimeDecoder::VideoTrackHandler::findKeyFrame(uint32 frame) const { - for (int i = _parent->keyframeCount - 1; i >= 0; i--) - if (_parent->keyframes[i] <= frame) - return _parent->keyframes[i]; - - // If none found, we'll assume the requested frame is a key frame return frame; } -void QuickTimeDecoder::VideoTrackHandler::seekToTime(Audio::Timestamp time) { - // First, figure out what edit we're in - time = time.convertToFramerate(_parent->timeScale); - - // Continue until we get to where we need to be - for (_curEdit = 0; !endOfTrack(); _curEdit++) - if ((uint32)time.totalNumberOfFrames() >= getCurEditTimeOffset() && (uint32)time.totalNumberOfFrames() < getCurEditTimeOffset() + getCurEditTrackDuration()) - break; - - // This track is done - if (endOfTrack()) - return; - - enterNewEditList(false); - - // One extra check for the end of a track - if (endOfTrack()) - return; - - // Now we're in the edit and need to figure out what frame we need - while (getRateAdjustedFrameTime() < (uint32)time.totalNumberOfFrames()) { - _curFrame++; - if (_durationOverride >= 0) { - _nextFrameStartTime += _durationOverride; - _durationOverride = -1; - } else { - _nextFrameStartTime += getFrameDuration(); - } - } - - // All that's left is to figure out what our starting time is going to be - // Compare the starting point for the frame to where we need to be - _holdNextFrameStartTime = getRateAdjustedFrameTime() != (uint32)time.totalNumberOfFrames(); - - // If we went past the time, go back a frame - if (_holdNextFrameStartTime) - _curFrame--; - - // Handle the keyframe here - int32 destinationFrame = _curFrame + 1; - - assert(destinationFrame < (int32)_parent->frameCount); - _curFrame = findKeyFrame(destinationFrame) - 1; - while (_curFrame < destinationFrame - 1) - bufferNextFrame(); -} - -Common::Rational QuickTimeDecoder::VideoTrackHandler::getWidth() const { - return Common::Rational(_parent->width) / _parent->scaleFactorX; -} - -Common::Rational QuickTimeDecoder::VideoTrackHandler::getHeight() const { - return Common::Rational(_parent->height) / _parent->scaleFactorY; -} - -Graphics::PixelFormat QuickTimeDecoder::VideoTrackHandler::getPixelFormat() const { - return ((VideoSampleDesc *)_parent->sampleDescs[0])->_videoCodec->getPixelFormat(); -} - uint32 QuickTimeDecoder::VideoTrackHandler::getRateAdjustedFrameTime() const { // Figure out what time the next frame is at taking the edit list rate into account - uint32 convertedTime = (Common::Rational(_nextFrameStartTime - getCurEditTimeOffset()) / _parent->editList[_curEdit].mediaRate).toInt(); + uint32 convertedTime = (Common::Rational(_nextFrameStartTime - getCurEditTimeOffset()) / _parent->editList[_curEdit].mediaRate).toInt(); return convertedTime + getCurEditTimeOffset(); } diff --git a/video/qt_decoder.h b/video/qt_decoder.h index 583b4b44b5..71d33711a6 100644 --- a/video/qt_decoder.h +++ b/video/qt_decoder.h @@ -31,16 +31,17 @@ #ifndef VIDEO_QT_DECODER_H #define VIDEO_QT_DECODER_H -#include "audio/mixer.h" #include "audio/decoders/quicktime_intern.h" #include "common/scummsys.h" -#include "common/rational.h" -#include "graphics/pixelformat.h" #include "video/video_decoder.h" namespace Common { - class Rational; +class Rational; +} + +namespace Graphics { +struct PixelFormat; } namespace Video { @@ -54,68 +55,33 @@ class Codec; * - mohawk * - sci */ -class QuickTimeDecoder : public SeekableVideoDecoder, public Audio::QuickTimeAudioDecoder { +class QuickTimeDecoder : public VideoDecoder, public Audio::QuickTimeAudioDecoder { public: QuickTimeDecoder(); virtual ~QuickTimeDecoder(); - /** - * Returns the width of the video - * @return the width of the video - */ - uint16 getWidth() const { return _width; } - - /** - * Returns the height of the video - * @return the height of the video - */ - uint16 getHeight() const { return _height; } - - /** - * Returns the amount of frames in the video - * @return the amount of frames in the video - */ - uint32 getFrameCount() const; - - /** - * Load a video file - * @param filename the filename to load - */ bool loadFile(const Common::String &filename); - - /** - * Load a QuickTime video file from a SeekableReadStream - * @param stream the stream to load - */ bool loadStream(Common::SeekableReadStream *stream); - - /** - * Close a QuickTime encoded video file - */ void close(); + uint16 getWidth() const { return _width; } + uint16 getHeight() const { return _height; } + const Graphics::Surface *decodeNextFrame(); + Audio::Timestamp getDuration() const { return Audio::Timestamp(0, _duration, _timeScale); } - /** - * Returns the palette of the video - * @return the palette of the video - */ - const byte *getPalette() { _dirtyPalette = false; return _palette; } - bool hasDirtyPalette() const { return _dirtyPalette; } +protected: + Common::QuickTimeParser::SampleDesc *readSampleDesc(Common::QuickTimeParser::Track *track, uint32 format); - int32 getCurFrame() const; +private: + void init(); - bool isVideoLoaded() const { return isOpen(); } - const Graphics::Surface *decodeNextFrame(); - bool endOfVideo() const; - uint32 getElapsedTime() const; - uint32 getTimeToNextFrame() const; - Graphics::PixelFormat getPixelFormat() const; + void updateAudioBuffer(); - // SeekableVideoDecoder API - void seekToFrame(uint32 frame); - void seekToTime(Audio::Timestamp time); - uint32 getDuration() const { return _duration * 1000 / _timeScale; } + uint16 _width, _height; + + Graphics::Surface *_scaledSurface; + void scaleSurface(const Graphics::Surface *src, Graphics::Surface *dst, + const Common::Rational &scaleFactorX, const Common::Rational &scaleFactorY); -protected: class VideoSampleDesc : public Common::QuickTimeParser::SampleDesc { public: VideoSampleDesc(Common::QuickTimeParser::Track *parentTrack, uint32 codecTag); @@ -131,106 +97,59 @@ protected: Codec *_videoCodec; }; - Common::QuickTimeParser::SampleDesc *readSampleDesc(Track *track, uint32 format); - -private: - void init(); - - void startAudio(); - void stopAudio(); - void updateAudioBuffer(); - void readNextAudioChunk(); - Common::Array<Audio::SoundHandle> _audioHandles; - Audio::Timestamp _audioStartOffset; - - Codec *createCodec(uint32 codecTag, byte bitsPerPixel); - uint32 findKeyFrame(uint32 frame) const; - - bool _dirtyPalette; - const byte *_palette; - bool _setStartTime; - bool _needUpdate; - - uint16 _width, _height; - - Graphics::Surface *_scaledSurface; - void scaleSurface(const Graphics::Surface *src, Graphics::Surface *dst, - Common::Rational scaleFactorX, Common::Rational scaleFactorY); - - void pauseVideoIntern(bool pause); - bool endOfVideoTracks() const; - - // The TrackHandler is a class that wraps around a QuickTime Track - // and handles playback in this decoder class. - class TrackHandler { - public: - TrackHandler(QuickTimeDecoder *decoder, Track *parent); - virtual ~TrackHandler() {} - - enum TrackType { - kTrackTypeAudio, - kTrackTypeVideo - }; - - virtual TrackType getTrackType() const = 0; - - virtual void seekToTime(Audio::Timestamp time) = 0; - - virtual bool endOfTrack(); - - protected: - uint32 _curEdit; - QuickTimeDecoder *_decoder; - Common::SeekableReadStream *_fd; - Track *_parent; - }; - // The AudioTrackHandler is currently just a wrapper around some // QuickTimeDecoder functions. - class AudioTrackHandler : public TrackHandler { + class AudioTrackHandler : public SeekableAudioTrack { public: AudioTrackHandler(QuickTimeDecoder *decoder, QuickTimeAudioTrack *audioTrack); - TrackType getTrackType() const { return kTrackTypeAudio; } void updateBuffer(); - void seekToTime(Audio::Timestamp time); - bool endOfTrack(); + + protected: + Audio::SeekableAudioStream *getSeekableAudioStream() const; private: + QuickTimeDecoder *_decoder; QuickTimeAudioTrack *_audioTrack; }; // The VideoTrackHandler is the bridge between the time of playback // and the media for the given track. It calculates when to start // tracks and at what rate to play the media using the edit list. - class VideoTrackHandler : public TrackHandler { + class VideoTrackHandler : public VideoTrack { public: - VideoTrackHandler(QuickTimeDecoder *decoder, Track *parent); + VideoTrackHandler(QuickTimeDecoder *decoder, Common::QuickTimeParser::Track *parent); ~VideoTrackHandler(); - TrackType getTrackType() const { return kTrackTypeVideo; } - - const Graphics::Surface *decodeNextFrame(); - - uint32 getNextFrameStartTime(); - - uint32 getFrameCount(); - - int32 getCurFrame() { return _curFrame; } + bool endOfTrack() const; + bool isSeekable() const { return true; } + bool seek(const Audio::Timestamp &time); + Audio::Timestamp getDuration() const; + uint16 getWidth() const; + uint16 getHeight() const; Graphics::PixelFormat getPixelFormat() const; + int getCurFrame() const { return _curFrame; } + int getFrameCount() const; + uint32 getNextFrameStartTime() const; + const Graphics::Surface *decodeNextFrame(); + const byte *getPalette() const { _dirtyPalette = false; return _curPalette; } + bool hasDirtyPalette() const { return _curPalette; } - void seekToTime(Audio::Timestamp time); - - Common::Rational getWidth() const; - Common::Rational getHeight() const; + Common::Rational getScaledWidth() const; + Common::Rational getScaledHeight() const; private: + QuickTimeDecoder *_decoder; + Common::QuickTimeParser::Track *_parent; + uint32 _curEdit; int32 _curFrame; uint32 _nextFrameStartTime; Graphics::Surface *_scaledSurface; bool _holdNextFrameStartTime; int32 _durationOverride; + const byte *_curPalette; + mutable bool _dirtyPalette; Common::SeekableReadStream *getNextFramePacket(uint32 &descId); uint32 getFrameDuration(); @@ -241,12 +160,6 @@ private: uint32 getCurEditTimeOffset() const; uint32 getCurEditTrackDuration() const; }; - - Common::Array<TrackHandler *> _handlers; - VideoTrackHandler *_nextVideoTrack; - VideoTrackHandler *findNextVideoTrack() const; - - void freeAllTrackHandlers(); }; } // End of namespace Video diff --git a/video/smk_decoder.cpp b/video/smk_decoder.cpp index 084028300d..bea65142a1 100644 --- a/video/smk_decoder.cpp +++ b/video/smk_decoder.cpp @@ -204,8 +204,7 @@ BigHuffmanTree::BigHuffmanTree(Common::BitStream &bs, int allocSize) delete _hiBytes; } -BigHuffmanTree::~BigHuffmanTree() -{ +BigHuffmanTree::~BigHuffmanTree() { delete[] _tree; } @@ -278,24 +277,17 @@ uint32 BigHuffmanTree::getCode(Common::BitStream &bs) { return v; } -SmackerDecoder::SmackerDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) - : _audioStarted(false), _audioStream(0), _mixer(mixer), _soundType(soundType) { - _surface = 0; +SmackerDecoder::SmackerDecoder(Audio::Mixer::SoundType soundType) : _soundType(soundType) { _fileStream = 0; - _dirtyPalette = false; + _firstFrameStart = 0; + _frameTypes = 0; + _frameSizes = 0; } SmackerDecoder::~SmackerDecoder() { close(); } -uint32 SmackerDecoder::getElapsedTime() const { - if (_audioStream && _audioStarted) - return _mixer->getSoundElapsedTime(_audioHandle); - - return FixedRateVideoDecoder::getElapsedTime(); -} - bool SmackerDecoder::loadStream(Common::SeekableReadStream *stream) { close(); @@ -309,16 +301,17 @@ bool SmackerDecoder::loadStream(Common::SeekableReadStream *stream) { uint32 width = _fileStream->readUint32LE(); uint32 height = _fileStream->readUint32LE(); - _frameCount = _fileStream->readUint32LE(); - int32 frameRate = _fileStream->readSint32LE(); - - // framerate contains 2 digits after the comma, so 1497 is actually 14.97 fps - if (frameRate > 0) - _frameRate = Common::Rational(1000, frameRate); - else if (frameRate < 0) - _frameRate = Common::Rational(100000, -frameRate); + uint32 frameCount = _fileStream->readUint32LE(); + int32 frameDelay = _fileStream->readSint32LE(); + + // frame rate contains 2 digits after the comma, so 1497 is actually 14.97 fps + Common::Rational frameRate; + if (frameDelay > 0) + frameRate = Common::Rational(1000, frameDelay); + else if (frameDelay < 0) + frameRate = Common::Rational(100000, -frameDelay); else - _frameRate = 1000; + frameRate = 1000; // Flags are determined by which bit is set, which can be one of the following: // 0 - set to 1 if file contains a ring frame. @@ -328,6 +321,9 @@ bool SmackerDecoder::loadStream(Common::SeekableReadStream *stream) { // before it is displayed. _header.flags = _fileStream->readUint32LE(); + SmackerVideoTrack *videoTrack = createVideoTrack(width, height, frameCount, frameRate, _header.flags, _header.signature); + addTrack(videoTrack); + // TODO: should we do any extra processing for Smacker files with ring frames? // TODO: should we do any extra processing for Y-doubled videos? Are they the @@ -374,92 +370,77 @@ bool SmackerDecoder::loadStream(Common::SeekableReadStream *stream) { warning("Unhandled Smacker v2 audio compression"); if (i == 0) - _audioStream = Audio::makeQueuingAudioStream(_header.audioInfo[0].sampleRate, _header.audioInfo[0].isStereo); + addTrack(new SmackerAudioTrack(_header.audioInfo[i], _soundType)); } } _header.dummy = _fileStream->readUint32LE(); - _frameSizes = new uint32[_frameCount]; - for (i = 0; i < _frameCount; ++i) + _frameSizes = new uint32[frameCount]; + for (i = 0; i < frameCount; ++i) _frameSizes[i] = _fileStream->readUint32LE(); - _frameTypes = new byte[_frameCount]; - for (i = 0; i < _frameCount; ++i) + _frameTypes = new byte[frameCount]; + for (i = 0; i < frameCount; ++i) _frameTypes[i] = _fileStream->readByte(); byte *huffmanTrees = (byte *) malloc(_header.treesSize); _fileStream->read(huffmanTrees, _header.treesSize); Common::BitStream8LSB bs(new Common::MemoryReadStream(huffmanTrees, _header.treesSize, DisposeAfterUse::YES), true); + videoTrack->readTrees(bs, _header.mMapSize, _header.mClrSize, _header.fullSize, _header.typeSize); - _MMapTree = new BigHuffmanTree(bs, _header.mMapSize); - _MClrTree = new BigHuffmanTree(bs, _header.mClrSize); - _FullTree = new BigHuffmanTree(bs, _header.fullSize); - _TypeTree = new BigHuffmanTree(bs, _header.typeSize); - - _surface = new Graphics::Surface(); + _firstFrameStart = _fileStream->pos(); - // Height needs to be doubled if we have flags (Y-interlaced or Y-doubled) - _surface->create(width, height * (_header.flags ? 2 : 1), Graphics::PixelFormat::createFormatCLUT8()); - - memset(_palette, 0, 3 * 256); return true; } void SmackerDecoder::close() { - if (!_fileStream) - return; - - if (_audioStream) { - if (_audioStarted) { - // The mixer will delete the stream. - _mixer->stopHandle(_audioHandle); - _audioStarted = false; - } else { - delete _audioStream; - } - _audioStream = 0; - } + VideoDecoder::close(); delete _fileStream; _fileStream = 0; - _surface->free(); - delete _surface; - _surface = 0; - - delete _MMapTree; - delete _MClrTree; - delete _FullTree; - delete _TypeTree; + delete[] _frameTypes; + _frameTypes = 0; delete[] _frameSizes; - delete[] _frameTypes; + _frameSizes = 0; +} - reset(); +bool SmackerDecoder::rewind() { + // Call the parent method to rewind the tracks first + if (!VideoDecoder::rewind()) + return false; + + // And seek back to where the first frame begins + _fileStream->seek(_firstFrameStart); + return true; } -const Graphics::Surface *SmackerDecoder::decodeNextFrame() { +void SmackerDecoder::readNextPacket() { + SmackerVideoTrack *videoTrack = (SmackerVideoTrack *)getTrack(0); + + if (videoTrack->endOfTrack()) + return; + + videoTrack->increaseCurFrame(); + uint i; uint32 chunkSize = 0; uint32 dataSizeUnpacked = 0; uint32 startPos = _fileStream->pos(); - _curFrame++; - // Check if we got a frame with palette data, and // call back the virtual setPalette function to set // the current palette - if (_frameTypes[_curFrame] & 1) { - unpackPalette(); - _dirtyPalette = true; - } + if (_frameTypes[videoTrack->getCurFrame()] & 1) + videoTrack->unpackPalette(_fileStream); // Load audio tracks for (i = 0; i < 7; ++i) { - if (!(_frameTypes[_curFrame] & (2 << i))) + if (!(_frameTypes[videoTrack->getCurFrame()] & (2 << i))) continue; chunkSize = _fileStream->readUint32LE(); @@ -475,29 +456,109 @@ const Graphics::Surface *SmackerDecoder::decodeNextFrame() { handleAudioTrack(i, chunkSize, dataSizeUnpacked); } - uint32 frameSize = _frameSizes[_curFrame] & ~3; -// uint32 remainder = _frameSizes[_curFrame] & 3; + uint32 frameSize = _frameSizes[videoTrack->getCurFrame()] & ~3; +// uint32 remainder = _frameSizes[videoTrack->getCurFrame()] & 3; if (_fileStream->pos() - startPos > frameSize) error("Smacker actual frame size exceeds recorded frame size"); uint32 frameDataSize = frameSize - (_fileStream->pos() - startPos); - _frameData = (byte *)malloc(frameDataSize + 1); + byte *frameData = (byte *)malloc(frameDataSize + 1); // Padding to keep the BigHuffmanTrees from reading past the data end - _frameData[frameDataSize] = 0x00; + frameData[frameDataSize] = 0x00; + + _fileStream->read(frameData, frameDataSize); + + Common::BitStream8LSB bs(new Common::MemoryReadStream(frameData, frameDataSize + 1, DisposeAfterUse::YES), true); + videoTrack->decodeFrame(bs); + + _fileStream->seek(startPos + frameSize); +} + +void SmackerDecoder::handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize) { + if (_header.audioInfo[track].hasAudio && chunkSize > 0 && track == 0) { + // Get the audio track, which start at offset 1 (first track is video) + SmackerAudioTrack *audioTrack = (SmackerAudioTrack *)getTrack(track + 1); + + // If it's track 0, play the audio data + byte *soundBuffer = (byte *)malloc(chunkSize + 1); + // Padding to keep the SmallHuffmanTrees from reading past the data end + soundBuffer[chunkSize] = 0x00; + + _fileStream->read(soundBuffer, chunkSize); + + if (_header.audioInfo[track].compression == kCompressionRDFT || _header.audioInfo[track].compression == kCompressionDCT) { + // TODO: Compressed audio (Bink RDFT/DCT encoded) + free(soundBuffer); + return; + } else if (_header.audioInfo[track].compression == kCompressionDPCM) { + // Compressed audio (Huffman DPCM encoded) + audioTrack->queueCompressedBuffer(soundBuffer, chunkSize + 1, unpackedSize); + free(soundBuffer); + } else { + // Uncompressed audio (PCM) + audioTrack->queuePCM(soundBuffer, chunkSize); + } + } else { + // Ignore the rest of the audio tracks, if they exist + // TODO: Are there any Smacker videos with more than one audio stream? + // If yes, we should play the rest of the audio streams as well + if (chunkSize > 0) + _fileStream->skip(chunkSize); + } +} - _fileStream->read(_frameData, frameDataSize); +SmackerDecoder::SmackerVideoTrack::SmackerVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, uint32 flags, uint32 signature) { + _surface = new Graphics::Surface(); + _surface->create(width, height * (flags ? 2 : 1), Graphics::PixelFormat::createFormatCLUT8()); + _frameCount = frameCount; + _frameRate = frameRate; + _flags = flags; + _signature = signature; + _curFrame = -1; + _dirtyPalette = false; + _MMapTree = _MClrTree = _FullTree = _TypeTree = 0; + memset(_palette, 0, 3 * 256); +} - Common::BitStream8LSB bs(new Common::MemoryReadStream(_frameData, frameDataSize + 1, DisposeAfterUse::YES), true); +SmackerDecoder::SmackerVideoTrack::~SmackerVideoTrack() { + _surface->free(); + delete _surface; + delete _MMapTree; + delete _MClrTree; + delete _FullTree; + delete _TypeTree; +} + +uint16 SmackerDecoder::SmackerVideoTrack::getWidth() const { + return _surface->w; +} + +uint16 SmackerDecoder::SmackerVideoTrack::getHeight() const { + return _surface->h; +} + +Graphics::PixelFormat SmackerDecoder::SmackerVideoTrack::getPixelFormat() const { + return _surface->format; +} + +void SmackerDecoder::SmackerVideoTrack::readTrees(Common::BitStream &bs, uint32 mMapSize, uint32 mClrSize, uint32 fullSize, uint32 typeSize) { + _MMapTree = new BigHuffmanTree(bs, mMapSize); + _MClrTree = new BigHuffmanTree(bs, mClrSize); + _FullTree = new BigHuffmanTree(bs, fullSize); + _TypeTree = new BigHuffmanTree(bs, typeSize); +} + +void SmackerDecoder::SmackerVideoTrack::decodeFrame(Common::BitStream &bs) { _MMapTree->reset(); _MClrTree->reset(); _FullTree->reset(); _TypeTree->reset(); // Height needs to be doubled if we have flags (Y-interlaced or Y-doubled) - uint doubleY = _header.flags ? 2 : 1; + uint doubleY = _flags ? 2 : 1; uint bw = getWidth() / 4; uint bh = getHeight() / doubleY / 4; @@ -508,6 +569,7 @@ const Graphics::Surface *SmackerDecoder::decodeNextFrame() { uint type, run, j, mode; uint32 p1, p2, clr, map; byte hi, lo; + uint i; while (block < blocks) { type = _TypeTree->getCode(bs); @@ -536,7 +598,7 @@ const Graphics::Surface *SmackerDecoder::decodeNextFrame() { break; case SMK_BLOCK_FULL: // Smacker v2 has one mode, Smacker v4 has three - if (_header.signature == MKTAG('S','M','K','2')) { + if (_signature == MKTAG('S','M','K','2')) { mode = 0; } else { // 00 - mode 0 @@ -628,60 +690,81 @@ const Graphics::Surface *SmackerDecoder::decodeNextFrame() { break; } } +} - _fileStream->seek(startPos + frameSize); +void SmackerDecoder::SmackerVideoTrack::unpackPalette(Common::SeekableReadStream *stream) { + uint startPos = stream->pos(); + uint32 len = 4 * stream->readByte(); - if (_curFrame == 0) - _startTime = g_system->getMillis(); + byte *chunk = (byte *)malloc(len); + stream->read(chunk, len); + byte *p = chunk; - return _surface; -} + byte oldPalette[3 * 256]; + memcpy(oldPalette, _palette, 3 * 256); -void SmackerDecoder::handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize) { - if (_header.audioInfo[track].hasAudio && chunkSize > 0 && track == 0) { - // If it's track 0, play the audio data - byte *soundBuffer = (byte *)malloc(chunkSize + 1); - // Padding to keep the SmallHuffmanTrees from reading past the data end - soundBuffer[chunkSize] = 0x00; + byte *pal = _palette; - _fileStream->read(soundBuffer, chunkSize); + int sz = 0; + byte b0; + while (sz < 256) { + b0 = *p++; + if (b0 & 0x80) { // if top bit is 1 (0x80 = 10000000) + sz += (b0 & 0x7f) + 1; // get lower 7 bits + 1 (0x7f = 01111111) + pal += 3 * ((b0 & 0x7f) + 1); + } else if (b0 & 0x40) { // if top 2 bits are 01 (0x40 = 01000000) + byte c = (b0 & 0x3f) + 1; // get lower 6 bits + 1 (0x3f = 00111111) + uint s = 3 * *p++; + sz += c; - if (_header.audioInfo[track].compression == kCompressionRDFT || _header.audioInfo[track].compression == kCompressionDCT) { - // TODO: Compressed audio (Bink RDFT/DCT encoded) - free(soundBuffer); - return; - } else if (_header.audioInfo[track].compression == kCompressionDPCM) { - // Compressed audio (Huffman DPCM encoded) - queueCompressedBuffer(soundBuffer, chunkSize + 1, unpackedSize, track); - free(soundBuffer); - } else { - // Uncompressed audio (PCM) - byte flags = 0; - if (_header.audioInfo[track].is16Bits) - flags = flags | Audio::FLAG_16BITS; - if (_header.audioInfo[track].isStereo) - flags = flags | Audio::FLAG_STEREO; - - _audioStream->queueBuffer(soundBuffer, chunkSize, DisposeAfterUse::YES, flags); - // The sound buffer will be deleted by QueuingAudioStream - } + while (c--) { + *pal++ = oldPalette[s + 0]; + *pal++ = oldPalette[s + 1]; + *pal++ = oldPalette[s + 2]; + s += 3; + } + } else { // top 2 bits are 00 + sz++; + // get the lower 6 bits for each component (0x3f = 00111111) + byte b = b0 & 0x3f; + byte g = (*p++) & 0x3f; + byte r = (*p++) & 0x3f; + + assert(g < 0xc0 && b < 0xc0); - if (!_audioStarted) { - _mixer->playStream(_soundType, &_audioHandle, _audioStream, -1, 255); - _audioStarted = true; + // upscale to full 8-bit color values by multiplying by 4 + *pal++ = b * 4; + *pal++ = g * 4; + *pal++ = r * 4; } - } else { - // Ignore the rest of the audio tracks, if they exist - // TODO: Are there any Smacker videos with more than one audio stream? - // If yes, we should play the rest of the audio streams as well - if (chunkSize > 0) - _fileStream->skip(chunkSize); } + + stream->seek(startPos + len); + free(chunk); + + _dirtyPalette = true; } -void SmackerDecoder::queueCompressedBuffer(byte *buffer, uint32 bufferSize, - uint32 unpackedSize, int streamNum) { +SmackerDecoder::SmackerAudioTrack::SmackerAudioTrack(const AudioInfo &audioInfo, Audio::Mixer::SoundType soundType) : + _audioInfo(audioInfo), _soundType(soundType) { + _audioStream = Audio::makeQueuingAudioStream(_audioInfo.sampleRate, _audioInfo.isStereo); +} +SmackerDecoder::SmackerAudioTrack::~SmackerAudioTrack() { + delete _audioStream; +} + +bool SmackerDecoder::SmackerAudioTrack::rewind() { + delete _audioStream; + _audioStream = Audio::makeQueuingAudioStream(_audioInfo.sampleRate, _audioInfo.isStereo); + return true; +} + +Audio::AudioStream *SmackerDecoder::SmackerAudioTrack::getAudioStream() const { + return _audioStream; +} + +void SmackerDecoder::SmackerAudioTrack::queueCompressedBuffer(byte *buffer, uint32 bufferSize, uint32 unpackedSize) { Common::BitStream8LSB audioBS(new Common::MemoryReadStream(buffer, bufferSize), true); bool dataPresent = audioBS.getBit(); @@ -689,9 +772,9 @@ void SmackerDecoder::queueCompressedBuffer(byte *buffer, uint32 bufferSize, return; bool isStereo = audioBS.getBit(); - assert(isStereo == _header.audioInfo[streamNum].isStereo); + assert(isStereo == _audioInfo.isStereo); bool is16Bits = audioBS.getBit(); - assert(is16Bits == _header.audioInfo[streamNum].is16Bits); + assert(is16Bits == _audioInfo.is16Bits); int numBytes = 1 * (isStereo ? 2 : 1) * (is16Bits ? 2 : 1); @@ -759,64 +842,21 @@ void SmackerDecoder::queueCompressedBuffer(byte *buffer, uint32 bufferSize, for (int k = 0; k < numBytes; k++) delete audioTrees[k]; - byte flags = 0; - if (_header.audioInfo[0].is16Bits) - flags = flags | Audio::FLAG_16BITS; - if (_header.audioInfo[0].isStereo) - flags = flags | Audio::FLAG_STEREO; - _audioStream->queueBuffer(unpackedBuffer, unpackedSize, DisposeAfterUse::YES, flags); - // unpackedBuffer will be deleted by QueuingAudioStream + queuePCM(unpackedBuffer, unpackedSize); } -void SmackerDecoder::unpackPalette() { - uint startPos = _fileStream->pos(); - uint32 len = 4 * _fileStream->readByte(); - - byte *chunk = (byte *)malloc(len); - _fileStream->read(chunk, len); - byte *p = chunk; - - byte oldPalette[3*256]; - memcpy(oldPalette, _palette, 3 * 256); - - byte *pal = _palette; - - int sz = 0; - byte b0; - while (sz < 256) { - b0 = *p++; - if (b0 & 0x80) { // if top bit is 1 (0x80 = 10000000) - sz += (b0 & 0x7f) + 1; // get lower 7 bits + 1 (0x7f = 01111111) - pal += 3 * ((b0 & 0x7f) + 1); - } else if (b0 & 0x40) { // if top 2 bits are 01 (0x40 = 01000000) - byte c = (b0 & 0x3f) + 1; // get lower 6 bits + 1 (0x3f = 00111111) - uint s = 3 * *p++; - sz += c; - - while (c--) { - *pal++ = oldPalette[s + 0]; - *pal++ = oldPalette[s + 1]; - *pal++ = oldPalette[s + 2]; - s += 3; - } - } else { // top 2 bits are 00 - sz++; - // get the lower 6 bits for each component (0x3f = 00111111) - byte b = b0 & 0x3f; - byte g = (*p++) & 0x3f; - byte r = (*p++) & 0x3f; - - assert(g < 0xc0 && b < 0xc0); +void SmackerDecoder::SmackerAudioTrack::queuePCM(byte *buffer, uint32 bufferSize) { + byte flags = 0; + if (_audioInfo.is16Bits) + flags |= Audio::FLAG_16BITS; + if (_audioInfo.isStereo) + flags |= Audio::FLAG_STEREO; - // upscale to full 8-bit color values by multiplying by 4 - *pal++ = b * 4; - *pal++ = g * 4; - *pal++ = r * 4; - } - } + _audioStream->queueBuffer(buffer, bufferSize, DisposeAfterUse::YES, flags); +} - _fileStream->seek(startPos + len); - free(chunk); +SmackerDecoder::SmackerVideoTrack *SmackerDecoder::createVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, uint32 flags, uint32 signature) const { + return new SmackerVideoTrack(width, height, frameCount, frameRate, flags, signature); } } // End of namespace Video diff --git a/video/smk_decoder.h b/video/smk_decoder.h index 72cd32a222..7227238373 100644 --- a/video/smk_decoder.h +++ b/video/smk_decoder.h @@ -34,6 +34,7 @@ class QueuingAudioStream; } namespace Common { +class BitStream; class SeekableReadStream; } @@ -56,36 +57,72 @@ class BigHuffmanTree; * - sword2 * - toon */ -class SmackerDecoder : public FixedRateVideoDecoder { +class SmackerDecoder : public VideoDecoder { public: - SmackerDecoder(Audio::Mixer *mixer, - Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType); + SmackerDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType); virtual ~SmackerDecoder(); - bool loadStream(Common::SeekableReadStream *stream); + virtual bool loadStream(Common::SeekableReadStream *stream); void close(); - bool isVideoLoaded() const { return _fileStream != 0; } - uint16 getWidth() const { return _surface->w; } - uint16 getHeight() const { return _surface->h; } - uint32 getFrameCount() const { return _frameCount; } - uint32 getElapsedTime() const; - const Graphics::Surface *decodeNextFrame(); - Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } - const byte *getPalette() { _dirtyPalette = false; return _palette; } - bool hasDirtyPalette() const { return _dirtyPalette; } - virtual void handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize); + bool rewind(); protected: - Common::Rational getFrameRate() const { return _frameRate; } - Common::SeekableReadStream *_fileStream; + void readNextPacket(); -protected: - void unpackPalette(); - // Possible runs of blocks - uint getBlockRun(int index) { return (index <= 58) ? index + 1 : 128 << (index - 59); } - void queueCompressedBuffer(byte *buffer, uint32 bufferSize, uint32 unpackedSize, int streamNum); + virtual void handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize); + + class SmackerVideoTrack : public FixedRateVideoTrack { + public: + SmackerVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, uint32 flags, uint32 signature); + ~SmackerVideoTrack(); + + bool isRewindable() const { return true; } + bool rewind() { _curFrame = -1; return true; } + + uint16 getWidth() const; + uint16 getHeight() const; + Graphics::PixelFormat getPixelFormat() const; + int getCurFrame() const { return _curFrame; } + int getFrameCount() const { return _frameCount; } + const Graphics::Surface *decodeNextFrame() { return _surface; } + const byte *getPalette() const { _dirtyPalette = false; return _palette; } + bool hasDirtyPalette() const { return _dirtyPalette; } + + void readTrees(Common::BitStream &bs, uint32 mMapSize, uint32 mClrSize, uint32 fullSize, uint32 typeSize); + void increaseCurFrame() { _curFrame++; } + void decodeFrame(Common::BitStream &bs); + void unpackPalette(Common::SeekableReadStream *stream); + + protected: + Common::Rational getFrameRate() const { return _frameRate; } + + Graphics::Surface *_surface; + + private: + Common::Rational _frameRate; + uint32 _flags, _signature; + + byte _palette[3 * 256]; + mutable bool _dirtyPalette; + + int _curFrame; + uint32 _frameCount; + BigHuffmanTree *_MMapTree; + BigHuffmanTree *_MClrTree; + BigHuffmanTree *_FullTree; + BigHuffmanTree *_TypeTree; + + // Possible runs of blocks + static uint getBlockRun(int index) { return (index <= 58) ? index + 1 : 128 << (index - 59); } + }; + + virtual SmackerVideoTrack *createVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, uint32 flags, uint32 signature) const; + + Common::SeekableReadStream *_fileStream; + +private: enum AudioCompression { kCompressionNone, kCompressionDPCM, @@ -114,6 +151,28 @@ protected: uint32 dummy; } _header; + class SmackerAudioTrack : public AudioTrack { + public: + SmackerAudioTrack(const AudioInfo &audioInfo, Audio::Mixer::SoundType soundType); + ~SmackerAudioTrack(); + + bool isRewindable() const { return true; } + bool rewind(); + + Audio::Mixer::SoundType getSoundType() const { return _soundType; } + + void queueCompressedBuffer(byte *buffer, uint32 bufferSize, uint32 unpackedSize); + void queuePCM(byte *buffer, uint32 bufferSize); + + protected: + Audio::AudioStream *getAudioStream() const; + + private: + Audio::Mixer::SoundType _soundType; + Audio::QueuingAudioStream *_audioStream; + AudioInfo _audioInfo; + }; + uint32 *_frameSizes; // The FrameTypes section of a Smacker file contains an array of bytes, where // the 8 bits of each byte describe the contents of the corresponding frame. @@ -121,25 +180,10 @@ protected: // and so on), so there can be up to 7 different audio tracks. When the lowest bit // (bit 0) is set, it denotes a frame that contains a palette record byte *_frameTypes; - byte *_frameData; - // The RGB palette - byte _palette[3 * 256]; - bool _dirtyPalette; - Common::Rational _frameRate; - uint32 _frameCount; - Graphics::Surface *_surface; + uint32 _firstFrameStart; Audio::Mixer::SoundType _soundType; - Audio::Mixer *_mixer; - bool _audioStarted; - Audio::QueuingAudioStream *_audioStream; - Audio::SoundHandle _audioHandle; - - BigHuffmanTree *_MMapTree; - BigHuffmanTree *_MClrTree; - BigHuffmanTree *_FullTree; - BigHuffmanTree *_TypeTree; }; } // End of namespace Video diff --git a/video/theora_decoder.cpp b/video/theora_decoder.cpp new file mode 100644 index 0000000000..d7260469e6 --- /dev/null +++ b/video/theora_decoder.cpp @@ -0,0 +1,487 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * Source is based on the player example from libvorbis package, + * available at: http://svn.xiph.org/trunk/theora/examples/player_example.c + * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. + * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ + * + */ + +#include "video/theora_decoder.h" + +#include "audio/audiostream.h" +#include "audio/decoders/raw.h" +#include "common/stream.h" +#include "common/system.h" +#include "common/textconsole.h" +#include "common/util.h" +#include "graphics/pixelformat.h" +#include "graphics/yuv_to_rgb.h" + +namespace Video { + +TheoraDecoder::TheoraDecoder(Audio::Mixer::SoundType soundType) : _soundType(soundType) { + _fileStream = 0; + + _videoTrack = 0; + _audioTrack = 0; + _hasVideo = _hasAudio = false; +} + +TheoraDecoder::~TheoraDecoder() { + close(); +} + +bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) { + close(); + + _fileStream = stream; + + // start up Ogg stream synchronization layer + ogg_sync_init(&_oggSync); + + // init supporting Vorbis structures needed in header parsing + vorbis_info_init(&_vorbisInfo); + vorbis_comment vorbisComment; + vorbis_comment_init(&vorbisComment); + + // init supporting Theora structures needed in header parsing + th_info theoraInfo; + th_info_init(&theoraInfo); + th_comment theoraComment; + th_comment_init(&theoraComment); + th_setup_info *theoraSetup = 0; + + uint theoraPackets = 0, vorbisPackets = 0; + + // Ogg file open; parse the headers + // Only interested in Vorbis/Theora streams + bool foundHeader = false; + while (!foundHeader) { + int ret = bufferData(); + + if (ret == 0) + break; // FIXME: Shouldn't this error out? + + while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) { + ogg_stream_state test; + + // is this a mandated initial header? If not, stop parsing + if (!ogg_page_bos(&_oggPage)) { + // don't leak the page; get it into the appropriate stream + queuePage(&_oggPage); + foundHeader = true; + break; + } + + ogg_stream_init(&test, ogg_page_serialno(&_oggPage)); + ogg_stream_pagein(&test, &_oggPage); + ogg_stream_packetout(&test, &_oggPacket); + + // identify the codec: try theora + if (theoraPackets == 0 && th_decode_headerin(&theoraInfo, &theoraComment, &theoraSetup, &_oggPacket) >= 0) { + // it is theora + memcpy(&_theoraOut, &test, sizeof(test)); + theoraPackets = 1; + _hasVideo = true; + } else if (vorbisPackets == 0 && vorbis_synthesis_headerin(&_vorbisInfo, &vorbisComment, &_oggPacket) >= 0) { + // it is vorbis + memcpy(&_vorbisOut, &test, sizeof(test)); + vorbisPackets = 1; + _hasAudio = true; + } else { + // whatever it is, we don't care about it + ogg_stream_clear(&test); + } + } + // fall through to non-bos page parsing + } + + // we're expecting more header packets. + while ((theoraPackets && theoraPackets < 3) || (vorbisPackets && vorbisPackets < 3)) { + int ret; + + // look for further theora headers + while (theoraPackets && (theoraPackets < 3) && (ret = ogg_stream_packetout(&_theoraOut, &_oggPacket))) { + if (ret < 0) + error("Error parsing Theora stream headers; corrupt stream?"); + + if (!th_decode_headerin(&theoraInfo, &theoraComment, &theoraSetup, &_oggPacket)) + error("Error parsing Theora stream headers; corrupt stream?"); + + theoraPackets++; + } + + // look for more vorbis header packets + while (vorbisPackets && (vorbisPackets < 3) && (ret = ogg_stream_packetout(&_vorbisOut, &_oggPacket))) { + if (ret < 0) + error("Error parsing Vorbis stream headers; corrupt stream?"); + + if (vorbis_synthesis_headerin(&_vorbisInfo, &vorbisComment, &_oggPacket)) + error("Error parsing Vorbis stream headers; corrupt stream?"); + + vorbisPackets++; + + if (vorbisPackets == 3) + break; + } + + // The header pages/packets will arrive before anything else we + // care about, or the stream is not obeying spec + + if (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) { + queuePage(&_oggPage); // demux into the appropriate stream + } else { + ret = bufferData(); // someone needs more data + + if (ret == 0) + error("End of file while searching for codec headers."); + } + } + + // And now we have it all. Initialize decoders next + if (_hasVideo) { + _videoTrack = new TheoraVideoTrack(getDefaultHighColorFormat(), theoraInfo, theoraSetup); + addTrack(_videoTrack); + } + + th_info_clear(&theoraInfo); + th_comment_clear(&theoraComment); + th_setup_free(theoraSetup); + + if (_hasAudio) { + _audioTrack = new VorbisAudioTrack(_soundType, _vorbisInfo); + + // Get enough audio data to start us off + while (!_audioTrack->hasAudio()) { + // Queue more data + bufferData(); + while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) + queuePage(&_oggPage); + + queueAudio(); + } + + addTrack(_audioTrack); + } + + vorbis_comment_clear(&vorbisComment); + + return true; +} + +void TheoraDecoder::close() { + VideoDecoder::close(); + + if (!_fileStream) + return; + + if (_videoTrack) { + ogg_stream_clear(&_theoraOut); + _videoTrack = 0; + } + + if (_audioTrack) { + ogg_stream_clear(&_vorbisOut); + _audioTrack = 0; + } + + ogg_sync_clear(&_oggSync); + vorbis_info_clear(&_vorbisInfo); + + delete _fileStream; + _fileStream = 0; + + _hasVideo = _hasAudio = false; +} + +void TheoraDecoder::readNextPacket() { + // First, let's get our frame + if (_hasVideo) { + while (!_videoTrack->endOfTrack()) { + // theora is one in, one out... + if (ogg_stream_packetout(&_theoraOut, &_oggPacket) > 0) { + if (_videoTrack->decodePacket(_oggPacket)) + break; + } else if (_theoraOut.e_o_s || _fileStream->eos()) { + // If we can't get any more frames, we're done. + _videoTrack->setEndOfVideo(); + } else { + // Queue more data + bufferData(); + while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) + queuePage(&_oggPage); + } + + // Update audio if we can + queueAudio(); + } + } + + // Then make sure we have enough audio buffered + ensureAudioBufferSize(); +} + +TheoraDecoder::TheoraVideoTrack::TheoraVideoTrack(const Graphics::PixelFormat &format, th_info &theoraInfo, th_setup_info *theoraSetup) { + _theoraDecode = th_decode_alloc(&theoraInfo, theoraSetup); + + if (theoraInfo.pixel_fmt != TH_PF_420) + error("Only theora YUV420 is supported"); + + int postProcessingMax; + th_decode_ctl(_theoraDecode, TH_DECCTL_GET_PPLEVEL_MAX, &postProcessingMax, sizeof(postProcessingMax)); + th_decode_ctl(_theoraDecode, TH_DECCTL_SET_PPLEVEL, &postProcessingMax, sizeof(postProcessingMax)); + + _surface.create(theoraInfo.frame_width, theoraInfo.frame_height, format); + + // Set up a display surface + _displaySurface.pixels = _surface.getBasePtr(theoraInfo.pic_x, theoraInfo.pic_y); + _displaySurface.w = theoraInfo.pic_width; + _displaySurface.h = theoraInfo.pic_height; + _displaySurface.format = format; + _displaySurface.pitch = _surface.pitch; + + // Set the frame rate + _frameRate = Common::Rational(theoraInfo.fps_numerator, theoraInfo.fps_denominator); + + _endOfVideo = false; + _nextFrameStartTime = 0.0; + _curFrame = -1; +} + +TheoraDecoder::TheoraVideoTrack::~TheoraVideoTrack() { + th_decode_free(_theoraDecode); + + _surface.free(); + _displaySurface.pixels = 0; +} + +bool TheoraDecoder::TheoraVideoTrack::decodePacket(ogg_packet &oggPacket) { + if (th_decode_packetin(_theoraDecode, &oggPacket, 0) == 0) { + _curFrame++; + + // Convert YUV data to RGB data + th_ycbcr_buffer yuv; + th_decode_ycbcr_out(_theoraDecode, yuv); + translateYUVtoRGBA(yuv); + + double time = th_granule_time(_theoraDecode, oggPacket.granulepos); + + // We need to calculate when the next frame should be shown + // This is all in floating point because that's what the Ogg code gives us + // Ogg is a lossy container format, so it doesn't always list the time to the + // next frame. In such cases, we need to calculate it ourselves. + if (time == -1.0) + _nextFrameStartTime += _frameRate.getInverse().toDouble(); + else + _nextFrameStartTime = time; + + return true; + } + + return false; +} + +enum TheoraYUVBuffers { + kBufferY = 0, + kBufferU = 1, + kBufferV = 2 +}; + +void TheoraDecoder::TheoraVideoTrack::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer) { + // Width and height of all buffers have to be divisible by 2. + assert((YUVBuffer[kBufferY].width & 1) == 0); + assert((YUVBuffer[kBufferY].height & 1) == 0); + assert((YUVBuffer[kBufferU].width & 1) == 0); + assert((YUVBuffer[kBufferV].width & 1) == 0); + + // UV images have to have a quarter of the Y image resolution + assert(YUVBuffer[kBufferU].width == YUVBuffer[kBufferY].width >> 1); + assert(YUVBuffer[kBufferV].width == YUVBuffer[kBufferY].width >> 1); + assert(YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height >> 1); + assert(YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height >> 1); + + Graphics::convertYUV420ToRGB(&_surface, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride); +} + +static vorbis_info *info = 0; + +TheoraDecoder::VorbisAudioTrack::VorbisAudioTrack(Audio::Mixer::SoundType soundType, vorbis_info &vorbisInfo) : _soundType(soundType) { + vorbis_synthesis_init(&_vorbisDSP, &vorbisInfo); + vorbis_block_init(&_vorbisDSP, &_vorbisBlock); + info = &vorbisInfo; + + _audStream = Audio::makeQueuingAudioStream(vorbisInfo.rate, vorbisInfo.channels); + + _audioBufferFill = 0; + _audioBuffer = 0; + _endOfAudio = false; +} + +TheoraDecoder::VorbisAudioTrack::~VorbisAudioTrack() { + vorbis_dsp_clear(&_vorbisDSP); + vorbis_block_clear(&_vorbisBlock); + delete _audStream; + free(_audioBuffer); +} + +Audio::AudioStream *TheoraDecoder::VorbisAudioTrack::getAudioStream() const { + return _audStream; +} + +#define AUDIOFD_FRAGSIZE 10240 + +static double rint(double v) { + return floor(v + 0.5); +} + +bool TheoraDecoder::VorbisAudioTrack::decodeSamples() { + float **pcm; + + // if there's pending, decoded audio, grab it + int ret = vorbis_synthesis_pcmout(&_vorbisDSP, &pcm); + + if (ret > 0) { + if (!_audioBuffer) { + _audioBuffer = (ogg_int16_t *)malloc(AUDIOFD_FRAGSIZE * sizeof(ogg_int16_t)); + assert(_audioBuffer); + } + + int channels = _audStream->isStereo() ? 2 : 1; + int count = _audioBufferFill / 2; + int maxsamples = ((AUDIOFD_FRAGSIZE - _audioBufferFill) / channels) >> 1; + int i; + + for (i = 0; i < ret && i < maxsamples; i++) { + for (int j = 0; j < channels; j++) { + int val = CLIP((int)rint(pcm[j][i] * 32767.f), -32768, 32767); + _audioBuffer[count++] = val; + } + } + + vorbis_synthesis_read(&_vorbisDSP, i); + _audioBufferFill += (i * channels) << 1; + + if (_audioBufferFill == AUDIOFD_FRAGSIZE) { + byte flags = Audio::FLAG_16BITS; + + if (_audStream->isStereo()) + flags |= Audio::FLAG_STEREO; + +#ifdef SCUMM_LITTLE_ENDIAN + flags |= Audio::FLAG_LITTLE_ENDIAN; +#endif + + _audStream->queueBuffer((byte *)_audioBuffer, AUDIOFD_FRAGSIZE, DisposeAfterUse::YES, flags); + + // The audio mixer is now responsible for the old audio buffer. + // We need to create a new one. + _audioBuffer = 0; + _audioBufferFill = 0; + } + + return true; + } + + return false; +} + +bool TheoraDecoder::VorbisAudioTrack::hasAudio() const { + return _audStream->numQueuedStreams() > 0; +} + +bool TheoraDecoder::VorbisAudioTrack::needsAudio() const { + // TODO: 5 is very arbitrary. We probably should do something like QuickTime does. + return !_endOfAudio && _audStream->numQueuedStreams() < 5; +} + +void TheoraDecoder::VorbisAudioTrack::synthesizePacket(ogg_packet &oggPacket) { + if (vorbis_synthesis(&_vorbisBlock, &oggPacket) == 0) // test for success + vorbis_synthesis_blockin(&_vorbisDSP, &_vorbisBlock); +} + +void TheoraDecoder::queuePage(ogg_page *page) { + if (_hasVideo) + ogg_stream_pagein(&_theoraOut, page); + + if (_hasAudio) + ogg_stream_pagein(&_vorbisOut, page); +} + +int TheoraDecoder::bufferData() { + char *buffer = ogg_sync_buffer(&_oggSync, 4096); + int bytes = _fileStream->read(buffer, 4096); + + ogg_sync_wrote(&_oggSync, bytes); + + return bytes; +} + +bool TheoraDecoder::queueAudio() { + if (!_hasAudio) + return false; + + bool queuedAudio = false; + + for (;;) { + if (_audioTrack->decodeSamples()) { + // we queued some pending audio + queuedAudio = true; + } else if (ogg_stream_packetout(&_vorbisOut, &_oggPacket) > 0) { + // no pending audio; is there a pending packet to decode? + _audioTrack->synthesizePacket(_oggPacket); + } else { + // we've buffered all we have, break out for now + break; + } + } + + return queuedAudio; +} + +void TheoraDecoder::ensureAudioBufferSize() { + if (!_hasAudio) + return; + + // Force at least some audio to be buffered + while (_audioTrack->needsAudio()) { + bufferData(); + while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) + queuePage(&_oggPage); + + bool queuedAudio = queueAudio(); + if ((_vorbisOut.e_o_s || _fileStream->eos()) && !queuedAudio) { + _audioTrack->setEndOfAudio(); + break; + } + } +} + +} // End of namespace Video diff --git a/video/theora_decoder.h b/video/theora_decoder.h new file mode 100644 index 0000000000..7e36d829e7 --- /dev/null +++ b/video/theora_decoder.h @@ -0,0 +1,157 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" // for USE_THEORADEC + +#ifdef USE_THEORADEC + +#ifndef VIDEO_THEORA_DECODER_H +#define VIDEO_THEORA_DECODER_H + +#include "common/rational.h" +#include "video/video_decoder.h" +#include "audio/mixer.h" +#include "graphics/surface.h" + +#include <theora/theoradec.h> +#include <vorbis/codec.h> + +namespace Common { +class SeekableReadStream; +} + +namespace Audio { +class AudioStream; +class QueuingAudioStream; +} + +namespace Video { + +/** + * + * Decoder for Theora videos. + * Video decoder used in engines: + * - sword25 + */ +class TheoraDecoder : public VideoDecoder { +public: + TheoraDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType); + virtual ~TheoraDecoder(); + + /** + * Load a video file + * @param stream the stream to load + */ + bool loadStream(Common::SeekableReadStream *stream); + void close(); + +protected: + void readNextPacket(); + +private: + class TheoraVideoTrack : public VideoTrack { + public: + TheoraVideoTrack(const Graphics::PixelFormat &format, th_info &theoraInfo, th_setup_info *theoraSetup); + ~TheoraVideoTrack(); + + bool endOfTrack() const { return _endOfVideo; } + uint16 getWidth() const { return _displaySurface.w; } + uint16 getHeight() const { return _displaySurface.h; } + Graphics::PixelFormat getPixelFormat() const { return _displaySurface.format; } + int getCurFrame() const { return _curFrame; } + uint32 getNextFrameStartTime() const { return (uint32)(_nextFrameStartTime * 1000); } + const Graphics::Surface *decodeNextFrame() { return &_displaySurface; } + + bool decodePacket(ogg_packet &oggPacket); + void setEndOfVideo() { _endOfVideo = true; } + + private: + int _curFrame; + bool _endOfVideo; + Common::Rational _frameRate; + double _nextFrameStartTime; + + Graphics::Surface _surface; + Graphics::Surface _displaySurface; + + th_dec_ctx *_theoraDecode; + + void translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer); + }; + + class VorbisAudioTrack : public AudioTrack { + public: + VorbisAudioTrack(Audio::Mixer::SoundType soundType, vorbis_info &vorbisInfo); + ~VorbisAudioTrack(); + + Audio::Mixer::SoundType getSoundType() const { return _soundType; } + + bool decodeSamples(); + bool hasAudio() const; + bool needsAudio() const; + void synthesizePacket(ogg_packet &oggPacket); + void setEndOfAudio() { _endOfAudio = true; } + + protected: + Audio::AudioStream *getAudioStream() const; + + private: + // single audio fragment audio buffering + int _audioBufferFill; + ogg_int16_t *_audioBuffer; + + Audio::Mixer::SoundType _soundType; + Audio::QueuingAudioStream *_audStream; + + vorbis_block _vorbisBlock; + vorbis_dsp_state _vorbisDSP; + + bool _endOfAudio; + }; + + void queuePage(ogg_page *page); + int bufferData(); + bool queueAudio(); + void ensureAudioBufferSize(); + + Common::SeekableReadStream *_fileStream; + + Audio::Mixer::SoundType _soundType; + + ogg_sync_state _oggSync; + ogg_page _oggPage; + ogg_packet _oggPacket; + + ogg_stream_state _theoraOut, _vorbisOut; + bool _hasVideo, _hasAudio; + + vorbis_info _vorbisInfo; + + TheoraVideoTrack *_videoTrack; + VorbisAudioTrack *_audioTrack; +}; + +} // End of namespace Video + +#endif + +#endif diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp index e1122132a8..559880acee 100644 --- a/video/video_decoder.cpp +++ b/video/video_decoder.cpp @@ -22,6 +22,9 @@ #include "video/video_decoder.h" +#include "audio/audiostream.h" +#include "audio/mixer.h" // for kMaxChannelVolume + #include "common/rational.h" #include "common/file.h" #include "common/system.h" @@ -31,7 +34,45 @@ namespace Video { VideoDecoder::VideoDecoder() { - reset(); + _startTime = 0; + _needsRewind = false; + _dirtyPalette = false; + _palette = 0; + _isPlaying = false; + _audioVolume = Audio::Mixer::kMaxChannelVolume; + _audioBalance = 0; + _pauseLevel = 0; + _needsUpdate = false; + _lastTimeChange = 0; + _endTime = 0; + _endTimeSet = false; + + // Find the best format for output + _defaultHighColorFormat = g_system->getScreenFormat(); + + if (_defaultHighColorFormat.bytesPerPixel == 1) + _defaultHighColorFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0); +} + +void VideoDecoder::close() { + if (isPlaying()) + stop(); + + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) + delete *it; + + _tracks.clear(); + _needsRewind = false; + _dirtyPalette = false; + _palette = 0; + _startTime = 0; + _audioVolume = Audio::Mixer::kMaxChannelVolume; + _audioBalance = 0; + _pauseLevel = 0; + _needsUpdate = false; + _lastTimeChange = 0; + _endTime = 0; + _endTimeSet = false; } bool VideoDecoder::loadFile(const Common::String &filename) { @@ -45,28 +86,10 @@ bool VideoDecoder::loadFile(const Common::String &filename) { return loadStream(file); } -uint32 VideoDecoder::getElapsedTime() const { - return g_system->getMillis() - _startTime; -} - -void VideoDecoder::setSystemPalette() { - g_system->getPaletteManager()->setPalette(getPalette(), 0, 256); -} - bool VideoDecoder::needsUpdate() const { return !endOfVideo() && getTimeToNextFrame() == 0; } -void VideoDecoder::reset() { - _curFrame = -1; - _startTime = 0; - _pauseLevel = 0; -} - -bool VideoDecoder::endOfVideo() const { - return !isVideoLoaded() || (getCurFrame() >= (int32)getFrameCount() - 1); -} - void VideoDecoder::pauseVideo(bool pause) { if (pause) { _pauseLevel++; @@ -82,10 +105,14 @@ void VideoDecoder::pauseVideo(bool pause) { if (_pauseLevel == 1 && pause) { _pauseStartTime = g_system->getMillis(); // Store the starting time from pausing to keep it for later - pauseVideoIntern(true); + + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) + (*it)->pause(true); } else if (_pauseLevel == 0) { - pauseVideoIntern(false); - addPauseTime(g_system->getMillis() - _pauseStartTime); + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) + (*it)->pause(false); + + _startTime += (g_system->getMillis() - _pauseStartTime); } } @@ -94,25 +121,562 @@ void VideoDecoder::resetPauseStartTime() { _pauseStartTime = g_system->getMillis(); } -uint32 FixedRateVideoDecoder::getTimeToNextFrame() const { - if (endOfVideo() || _curFrame < 0) +void VideoDecoder::setVolume(byte volume) { + _audioVolume = volume; + + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeAudio) + ((AudioTrack *)*it)->setVolume(_audioVolume); +} + +void VideoDecoder::setBalance(int8 balance) { + _audioBalance = balance; + + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeAudio) + ((AudioTrack *)*it)->setBalance(_audioBalance); +} + +bool VideoDecoder::isVideoLoaded() const { + return !_tracks.empty(); +} + +uint16 VideoDecoder::getWidth() const { + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeVideo) + return ((VideoTrack *)*it)->getWidth(); + + return 0; +} + +uint16 VideoDecoder::getHeight() const { + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeVideo) + return ((VideoTrack *)*it)->getHeight(); + + return 0; +} + +Graphics::PixelFormat VideoDecoder::getPixelFormat() const { + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeVideo) + return ((VideoTrack *)*it)->getPixelFormat(); + + return Graphics::PixelFormat(); +} + +const Graphics::Surface *VideoDecoder::decodeNextFrame() { + _needsUpdate = false; + + readNextPacket(); + VideoTrack *track = findNextVideoTrack(); + + if (!track) return 0; - uint32 elapsedTime = getElapsedTime(); - uint32 nextFrameStartTime = getFrameBeginTime(_curFrame + 1); + const Graphics::Surface *frame = track->decodeNextFrame(); + + if (track->hasDirtyPalette()) { + _palette = track->getPalette(); + _dirtyPalette = true; + } + + return frame; +} + +const byte *VideoDecoder::getPalette() { + _dirtyPalette = false; + return _palette; +} + +int VideoDecoder::getCurFrame() const { + int32 frame = -1; + + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeVideo) + frame += ((VideoTrack *)*it)->getCurFrame() + 1; + + return frame; +} + +uint32 VideoDecoder::getFrameCount() const { + int count = 0; + + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeVideo) + count += ((VideoTrack *)*it)->getFrameCount(); + + return count; +} + +uint32 VideoDecoder::getTime() const { + if (!isPlaying()) + return _lastTimeChange.msecs(); + + if (isPaused()) + return _pauseStartTime - _startTime; + + if (useAudioSync()) { + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) { + if ((*it)->getTrackType() == Track::kTrackTypeAudio && !(*it)->endOfTrack()) { + uint32 time = ((const AudioTrack *)*it)->getRunningTime(); + + if (time != 0) + return time + _lastTimeChange.msecs(); + } + } + } + + return g_system->getMillis() - _startTime; +} + +uint32 VideoDecoder::getTimeToNextFrame() const { + if (endOfVideo() || _needsUpdate) + return 0; + + const VideoTrack *track = findNextVideoTrack(); + + if (!track) + return 0; + + uint32 elapsedTime = getTime(); + uint32 nextFrameStartTime = track->getNextFrameStartTime(); - // If the time that the next frame should be shown has past - // the frame should be shown ASAP. if (nextFrameStartTime <= elapsedTime) return 0; return nextFrameStartTime - elapsedTime; } -uint32 FixedRateVideoDecoder::getFrameBeginTime(uint32 frame) const { - Common::Rational beginTime = frame * 1000; - beginTime /= getFrameRate(); - return beginTime.toInt(); +bool VideoDecoder::endOfVideo() const { + if (!isVideoLoaded()) + return true; + + if (_endTimeSet) { + const VideoTrack *track = findNextVideoTrack(); + + if (track && track->getNextFrameStartTime() >= (uint)_endTime.msecs()) + return true; + } + + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) + if (!(*it)->endOfTrack()) + return false; + + return true; +} + +bool VideoDecoder::isRewindable() const { + if (!isVideoLoaded()) + return false; + + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) + if (!(*it)->isRewindable()) + return false; + + return true; +} + +bool VideoDecoder::rewind() { + if (!isRewindable()) + return false; + + _needsRewind = false; + + // Stop all tracks so they can be rewound + if (isPlaying()) + stopAudio(); + + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) + if (!(*it)->rewind()) + return false; + + // Now that we've rewound, start all tracks again + if (isPlaying()) + startAudio(); + + _lastTimeChange = 0; + _startTime = g_system->getMillis(); + resetPauseStartTime(); + return true; +} + +bool VideoDecoder::isSeekable() const { + if (!isVideoLoaded()) + return false; + + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) + if (!(*it)->isSeekable()) + return false; + + return true; +} + +bool VideoDecoder::seek(const Audio::Timestamp &time) { + if (!isSeekable()) + return false; + + _needsRewind = false; + + // Stop all tracks so they can be seeked + if (isPlaying()) + stopAudio(); + + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) + if (!(*it)->seek(time)) + return false; + + _lastTimeChange = time; + + // Now that we've seeked, start all tracks again + // Also reset our start time + if (isPlaying()) { + startAudio(); + _startTime = g_system->getMillis() - time.msecs(); + } + + resetPauseStartTime(); + _needsUpdate = true; + return true; +} + +void VideoDecoder::start() { + if (isPlaying() || !isVideoLoaded()) + return; + + _isPlaying = true; + _startTime = g_system->getMillis(); + + // If someone previously called stop(), we'll rewind it. + if (_needsRewind) + rewind(); + + // Adjust start time if we've seeked to something besides zero time + if (_lastTimeChange.totalNumberOfFrames() != 0) + _startTime -= _lastTimeChange.msecs(); + + startAudio(); +} + +void VideoDecoder::stop() { + if (!isPlaying()) + return; + + _isPlaying = false; + _startTime = 0; + _palette = 0; + _dirtyPalette = false; + _needsUpdate = false; + + stopAudio(); + + // Also reset the pause state. + _pauseLevel = 0; + + // If this is a rewindable video, don't close it too. We'll just rewind() the video + // the next time someone calls start(). Otherwise, since it can't be rewound, we + // just close it. + if (isRewindable()) { + _lastTimeChange = getTime(); + _needsRewind = true; + } else { + close(); + } +} + +Audio::Timestamp VideoDecoder::getDuration() const { + Audio::Timestamp maxDuration(0, 1000); + + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) { + Audio::Timestamp duration = (*it)->getDuration(); + + if (duration > maxDuration) + maxDuration = duration; + } + + return maxDuration; +} + +VideoDecoder::Track::Track() { + _paused = false; +} + +bool VideoDecoder::Track::isRewindable() const { + return isSeekable(); +} + +bool VideoDecoder::Track::rewind() { + return seek(Audio::Timestamp(0, 1000)); +} + +Audio::Timestamp VideoDecoder::Track::getDuration() const { + return Audio::Timestamp(0, 1000); +} + +bool VideoDecoder::VideoTrack::endOfTrack() const { + return getCurFrame() >= (getFrameCount() - 1); +} + +uint32 VideoDecoder::FixedRateVideoTrack::getNextFrameStartTime() const { + if (endOfTrack() || getCurFrame() < 0) + return 0; + + Common::Rational time = (getCurFrame() + 1) * 1000; + time /= getFrameRate(); + return time.toInt(); +} + +Audio::Timestamp VideoDecoder::FixedRateVideoTrack::getDuration() const { + // Since Audio::Timestamp doesn't support a fractional frame rate, we're currently + // just converting to milliseconds. + Common::Rational time = getFrameCount() * 1000; + time /= getFrameRate(); + return time.toInt(); +} + +bool VideoDecoder::AudioTrack::endOfTrack() const { + Audio::AudioStream *stream = getAudioStream(); + return !stream || !g_system->getMixer()->isSoundHandleActive(_handle) || stream->endOfData(); +} + +void VideoDecoder::AudioTrack::setVolume(byte volume) { + _volume = volume; + + if (g_system->getMixer()->isSoundHandleActive(_handle)) + g_system->getMixer()->setChannelVolume(_handle, _volume); +} + +void VideoDecoder::AudioTrack::setBalance(int8 balance) { + _balance = balance; + + if (g_system->getMixer()->isSoundHandleActive(_handle)) + g_system->getMixer()->setChannelBalance(_handle, _balance); +} + +void VideoDecoder::AudioTrack::start() { + stop(); + + Audio::AudioStream *stream = getAudioStream(); + assert(stream); + + g_system->getMixer()->playStream(getSoundType(), &_handle, stream, -1, getVolume(), getBalance(), DisposeAfterUse::NO); + + // Pause the audio again if we're still paused + if (isPaused()) + g_system->getMixer()->pauseHandle(_handle, true); +} + +void VideoDecoder::AudioTrack::stop() { + g_system->getMixer()->stopHandle(_handle); +} + +void VideoDecoder::AudioTrack::start(const Audio::Timestamp &limit) { + stop(); + + Audio::AudioStream *stream = getAudioStream(); + assert(stream); + + stream = Audio::makeLimitingAudioStream(stream, limit, DisposeAfterUse::NO); + + g_system->getMixer()->playStream(getSoundType(), &_handle, stream, -1, getVolume(), getBalance(), DisposeAfterUse::YES); + + // Pause the audio again if we're still paused + if (isPaused()) + g_system->getMixer()->pauseHandle(_handle, true); +} + +uint32 VideoDecoder::AudioTrack::getRunningTime() const { + if (g_system->getMixer()->isSoundHandleActive(_handle)) + return g_system->getMixer()->getSoundElapsedTime(_handle); + + return 0; +} + +void VideoDecoder::AudioTrack::pauseIntern(bool shouldPause) { + if (g_system->getMixer()->isSoundHandleActive(_handle)) + g_system->getMixer()->pauseHandle(_handle, shouldPause); +} + +Audio::AudioStream *VideoDecoder::RewindableAudioTrack::getAudioStream() const { + return getRewindableAudioStream(); +} + +bool VideoDecoder::RewindableAudioTrack::rewind() { + Audio::RewindableAudioStream *stream = getRewindableAudioStream(); + assert(stream); + return stream->rewind(); +} + +Audio::Timestamp VideoDecoder::SeekableAudioTrack::getDuration() const { + Audio::SeekableAudioStream *stream = getSeekableAudioStream(); + assert(stream); + return stream->getLength(); +} + +Audio::AudioStream *VideoDecoder::SeekableAudioTrack::getAudioStream() const { + return getSeekableAudioStream(); +} + +bool VideoDecoder::SeekableAudioTrack::seek(const Audio::Timestamp &time) { + Audio::SeekableAudioStream *stream = getSeekableAudioStream(); + assert(stream); + return stream->seek(time); +} + +VideoDecoder::StreamFileAudioTrack::StreamFileAudioTrack() { + _stream = 0; +} + +VideoDecoder::StreamFileAudioTrack::~StreamFileAudioTrack() { + delete _stream; +} + +bool VideoDecoder::StreamFileAudioTrack::loadFromFile(const Common::String &baseName) { + // TODO: Make sure the stream isn't being played + delete _stream; + _stream = Audio::SeekableAudioStream::openStreamFile(baseName); + return _stream != 0; +} + +void VideoDecoder::addTrack(Track *track) { + _tracks.push_back(track); + + // Update volume settings if it's an audio track + if (track->getTrackType() == Track::kTrackTypeAudio) { + ((AudioTrack *)track)->setVolume(_audioVolume); + ((AudioTrack *)track)->setBalance(_audioBalance); + } + + // Keep the track paused if we're paused + if (isPaused()) + track->pause(true); + + // Start the track if we're playing + if (isPlaying() && track->getTrackType() == Track::kTrackTypeAudio) + ((AudioTrack *)track)->start(); +} + +bool VideoDecoder::addStreamFileTrack(const Common::String &baseName) { + // Only allow adding external tracks if a video is already loaded + if (!isVideoLoaded()) + return false; + + StreamFileAudioTrack *track = new StreamFileAudioTrack(); + + bool result = track->loadFromFile(baseName); + + if (result) + addTrack(track); + + return result; +} + +void VideoDecoder::setEndTime(const Audio::Timestamp &endTime) { + Audio::Timestamp startTime = 0; + + if (isPlaying()) { + startTime = getTime(); + stopAudio(); + } + + _endTime = endTime; + _endTimeSet = true; + + if (startTime > endTime) + return; + + if (isPlaying()) { + // We'll assume the audio track is going to start up at the same time it just was + // and therefore not do any seeking. + // Might want to set it anyway if we're seekable. + startAudioLimit(_endTime.msecs() - startTime.msecs()); + _lastTimeChange = startTime; + } +} + +VideoDecoder::Track *VideoDecoder::getTrack(uint track) { + if (track > _tracks.size()) + return 0; + + return _tracks[track]; +} + +const VideoDecoder::Track *VideoDecoder::getTrack(uint track) const { + if (track > _tracks.size()) + return 0; + + return _tracks[track]; +} + +bool VideoDecoder::endOfVideoTracks() const { + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeVideo && !(*it)->endOfTrack()) + return false; + + return true; +} + +VideoDecoder::VideoTrack *VideoDecoder::findNextVideoTrack() { + VideoTrack *bestTrack = 0; + uint32 bestTime = 0xFFFFFFFF; + + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) { + if ((*it)->getTrackType() == Track::kTrackTypeVideo && !(*it)->endOfTrack()) { + VideoTrack *track = (VideoTrack *)*it; + uint32 time = track->getNextFrameStartTime(); + + if (time < bestTime) { + bestTime = time; + bestTrack = track; + } + } + } + + return bestTrack; +} + +const VideoDecoder::VideoTrack *VideoDecoder::findNextVideoTrack() const { + const VideoTrack *bestTrack = 0; + uint32 bestTime = 0xFFFFFFFF; + + for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++) { + if ((*it)->getTrackType() == Track::kTrackTypeVideo && !(*it)->endOfTrack()) { + const VideoTrack *track = (const VideoTrack *)*it; + uint32 time = track->getNextFrameStartTime(); + + if (time < bestTime) { + bestTime = time; + bestTrack = track; + } + } + } + + return bestTrack; +} + +void VideoDecoder::startAudio() { + if (_endTimeSet) { + // HACK: Timestamp's subtraction asserts out when subtracting two times + // with different rates. + startAudioLimit(_endTime - _lastTimeChange.convertToFramerate(_endTime.framerate())); + return; + } + + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeAudio) + ((AudioTrack *)*it)->start(); +} + +void VideoDecoder::stopAudio() { + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeAudio) + ((AudioTrack *)*it)->stop(); +} + +void VideoDecoder::startAudioLimit(const Audio::Timestamp &limit) { + for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeAudio) + ((AudioTrack *)*it)->start(limit); } } // End of namespace Video diff --git a/video/video_decoder.h b/video/video_decoder.h index 52ced4777c..5abe1d917c 100644 --- a/video/video_decoder.h +++ b/video/video_decoder.h @@ -23,10 +23,17 @@ #ifndef VIDEO_DECODER_H #define VIDEO_DECODER_H -#include "common/str.h" - +#include "audio/mixer.h" #include "audio/timestamp.h" // TODO: Move this to common/ ? +#include "common/array.h" +#include "common/str.h" +#include "graphics/pixelformat.h" +namespace Audio { +class AudioStream; +class RewindableAudioStream; +class SeekableAudioStream; +} namespace Common { class Rational; @@ -34,7 +41,6 @@ class SeekableReadStream; } namespace Graphics { -struct PixelFormat; struct Surface; } @@ -48,10 +54,14 @@ public: VideoDecoder(); virtual ~VideoDecoder() {} + ///////////////////////////////////////// + // Opening/Closing a Video + ///////////////////////////////////////// + /** * Load a video from a file with the given name. * - * A default implementation using loadStream is provided. + * A default implementation using Common::File and loadStream is provided. * * @param filename the filename to load * @return whether loading the file succeeded @@ -62,6 +72,10 @@ public: * Load a video from a generic read stream. The ownership of the * stream object transfers to this VideoDecoder instance, which is * hence also responsible for eventually deleting it. + * + * Implementations of this function are required to call addTrack() + * for each track in the video upon success. + * * @param stream the stream to load * @return whether loading the stream succeeded */ @@ -69,206 +83,706 @@ public: /** * Close the active video stream and free any associated resources. + * + * All subclasses that need to close their own resources should still + * call the base class' close() function at the start of their function. */ - virtual void close() = 0; + virtual void close(); /** * Returns if a video stream is currently loaded or not. */ - virtual bool isVideoLoaded() const = 0; + bool isVideoLoaded() const; + ///////////////////////////////////////// + // Playback Control + ///////////////////////////////////////// /** - * Returns the width of the video's frames. - * @return the width of the video's frames + * Begin playback of the video. + * + * @note This has no effect is the video is already playing. */ - virtual uint16 getWidth() const = 0; + void start(); /** - * Returns the height of the video's frames. - * @return the height of the video's frames + * Stop playback of the video. + * + * @note This will close() the video if it is not rewindable. + * @note If the video is rewindable, the video will be rewound on the + * next start() call unless rewind() or seek() is called before then. */ - virtual uint16 getHeight() const = 0; + void stop(); /** - * Get the pixel format of the currently loaded video. + * Returns if the video is currently playing or not. + * + * This is not equivalent to the inverse of endOfVideo(). A video keeps + * its playing status even after reaching the end of the video. This will + * return true after calling start() and will continue to return true + * until stop() (or close()) is called. */ - virtual Graphics::PixelFormat getPixelFormat() const = 0; + bool isPlaying() const { return _isPlaying; } /** - * Get the palette for the video in RGB format (if 8bpp or less). + * Returns if a video is rewindable or not. The default implementation + * polls each track for rewindability. */ - virtual const byte *getPalette() { return 0; } + virtual bool isRewindable() const; /** - * Returns if the palette is dirty or not. + * Rewind a video to its beginning. + * + * If the video is playing, it will continue to play. The default + * implementation will rewind each track. + * + * @return true on success, false otherwise + */ + virtual bool rewind(); + + /** + * Returns if a video is seekable or not. The default implementation + * polls each track for seekability. */ - virtual bool hasDirtyPalette() const { return false; } + virtual bool isSeekable() const; /** - * Set the system palette to the palette returned by getPalette. - * @see getPalette + * Seek to a given time in the video. + * + * If the video is playing, it will continue to play. The default + * implementation will seek each track and must still be called + * from any other implementation. + * + * @param time The time to seek to + * @return true on success, false otherwise */ - void setSystemPalette(); + virtual bool seek(const Audio::Timestamp &time); + + /** + * Pause or resume the video. This should stop/resume any audio playback + * and other stuff. The initial pause time is kept so that any timing + * variables can be updated appropriately. + * + * This is a convenience method which automatically keeps track on how + * often the video has been paused, ensuring that after pausing an video + * e.g. twice, it has to be unpaused twice before actuallying resuming. + * + * @param pause true to pause the video, false to resume it + */ + void pauseVideo(bool pause); + + /** + * Return whether the video is currently paused or not. + */ + bool isPaused() const { return _pauseLevel != 0; } + + /** + * Set the time for this video to end at. At this time in the video, + * all audio will stop and endOfVideo() will return true. + */ + void setEndTime(const Audio::Timestamp &endTime); + + /** + * Get the stop time of the video (if not set, zero) + */ + Audio::Timestamp getEndTime() const { return _endTime; } + + + ///////////////////////////////////////// + // Playback Status + ///////////////////////////////////////// + + /** + * Returns if the video has reached the end or not. + * @return true if the video has finished playing or if none is loaded, false otherwise + */ + bool endOfVideo() const; /** * Returns the current frame number of the video. * @return the last frame decoded by the video */ - virtual int32 getCurFrame() const { return _curFrame; } + int32 getCurFrame() const; /** * Returns the number of frames in the video. * @return the number of frames in the video */ - virtual uint32 getFrameCount() const = 0; + uint32 getFrameCount() const; /** - * Returns the time (in ms) that the video has been running. - * This is based on the "wall clock" time as determined by - * OSystem::getMillis, and takes pausing the video into account. + * Returns the time position (in ms) of the current video. + * This can be based on the "wall clock" time as determined by + * OSystem::getMillis() or the current time of any audio track + * running in the video, and takes pausing the video into account. * - * As such, it can differ from what multiplying getCurFrame() by + * As such, it will differ from what multiplying getCurFrame() by * some constant would yield, e.g. for a video with non-constant * frame rate. + * + * Due to the nature of the timing, this value may not always be + * completely accurate (since our mixer does not have precise + * timing). + */ + uint32 getTime() const; + + + ///////////////////////////////////////// + // Video Info + ///////////////////////////////////////// + + /** + * Returns the width of the video's frames. + * + * By default, this finds the largest width between all of the loaded + * tracks. However, a subclass may override this if it does any kind + * of post-processing on it. + * + * @return the width of the video's frames + */ + virtual uint16 getWidth() const; + + /** + * Returns the height of the video's frames. + * + * By default, this finds the largest height between all of the loaded + * tracks. However, a subclass may override this if it does any kind + * of post-processing on it. + * + * @return the height of the video's frames + */ + virtual uint16 getHeight() const; + + /** + * Get the pixel format of the currently loaded video. + */ + Graphics::PixelFormat getPixelFormat() const; + + /** + * Get the duration of the video. + * + * If the duration is unknown, this will return 0. If this is not + * overriden, it will take the length of the longest track. + */ + virtual Audio::Timestamp getDuration() const; + + + ///////////////////////////////////////// + // Frame Decoding + ///////////////////////////////////////// + + /** + * Get the palette for the video in RGB format (if 8bpp or less). + * + * The palette's format is the same as PaletteManager's palette + * (interleaved RGB values). + */ + const byte *getPalette(); + + /** + * Returns if the palette is dirty or not. */ - virtual uint32 getElapsedTime() const; + bool hasDirtyPalette() const { return _dirtyPalette; } /** * Return the time (in ms) until the next frame should be displayed. */ - virtual uint32 getTimeToNextFrame() const = 0; + uint32 getTimeToNextFrame() const; /** * Check whether a new frame should be decoded, i.e. because enough * time has elapsed since the last frame was decoded. * @return whether a new frame should be decoded or not */ - virtual bool needsUpdate() const; + bool needsUpdate() const; /** * Decode the next frame into a surface and return the latter. + * + * A subclass may override this, but must still call this function. As an + * example, a subclass may do this to apply some global video scale to + * individual track's frame. + * + * Note that this will call readNextPacket() internally first before calling + * the next video track's decodeNextFrame() function. + * * @return a surface containing the decoded frame, or 0 * @note Ownership of the returned surface stays with the VideoDecoder, * hence the caller must *not* free it. * @note this may return 0, in which case the last frame should be kept on screen */ - virtual const Graphics::Surface *decodeNextFrame() = 0; + virtual const Graphics::Surface *decodeNextFrame(); /** - * Returns if the video has finished playing or not. - * @return true if the video has finished playing or if none is loaded, false otherwise + * Set the default high color format for videos that convert from YUV. + * + * By default, VideoDecoder will attempt to use the screen format + * if it's >8bpp and use a 32bpp format when not. + * + * This must be set before calling loadStream(). */ - virtual bool endOfVideo() const; + void setDefaultHighColorFormat(const Graphics::PixelFormat &format) { _defaultHighColorFormat = format; } + + + ///////////////////////////////////////// + // Audio Control + ///////////////////////////////////////// /** - * Pause or resume the video. This should stop/resume any audio playback - * and other stuff. The initial pause time is kept so that any timing - * variables can be updated appropriately. + * Get the current volume at which the audio in the video is being played + * @return the current volume at which the audio in the video is being played + */ + byte getVolume() const { return _audioVolume; } + + /** + * Set the volume at which the audio in the video should be played. + * This setting remains until close() is called (which may be called + * from loadStream()). The default volume is the maximum. * - * This is a convenience method which automatically keeps track on how - * often the video has been paused, ensuring that after pausing an video - * e.g. twice, it has to be unpaused twice before actuallying resuming. + * @param volume The volume at which to play the audio in the video + */ + void setVolume(byte volume); + + /** + * Get the current balance at which the audio in the video is being played + * @return the current balance at which the audio in the video is being played + */ + int8 getBalance() const { return _audioBalance; } + + /** + * Set the balance at which the audio in the video should be played. + * This setting remains until close() is called (which may be called + * from loadStream()). The default balance is 0. * - * @param pause true to pause the video, false to resume it + * @param balance The balance at which to play the audio in the video */ - void pauseVideo(bool pause); + void setBalance(int8 balance); /** - * Return whether the video is currently paused or not. + * Add an audio track from a stream file. + * + * This calls SeekableAudioStream::openStreamFile() internally */ - bool isPaused() const { return _pauseLevel != 0; } + bool addStreamFileTrack(const Common::String &baseName); + + + // Future API + //void setRate(const Common::Rational &rate); + //Common::Rational getRate() const; protected: /** - * Resets _curFrame and _startTime. Should be called from every close() function. + * An abstract representation of a track in a movie. */ - void reset(); + class Track { + public: + Track(); + virtual ~Track() {} + + /** + * The types of tracks this class can be. + */ + enum TrackType { + kTrackTypeNone, + kTrackTypeVideo, + kTrackTypeAudio + }; + + /** + * Get the type of track. + */ + virtual TrackType getTrackType() const = 0; + + /** + * Return if the track has finished. + */ + virtual bool endOfTrack() const = 0; + + /** + * Return if the track is rewindable. + * + * If a video is seekable, it does not need to implement this + * for it to also be rewindable. + */ + virtual bool isRewindable() const; + + /** + * Rewind the video to the beginning. + * + * If a video is seekable, it does not need to implement this + * for it to also be rewindable. + * + * @return true on success, false otherwise. + */ + virtual bool rewind(); + + /** + * Return if the track is seekable. + */ + virtual bool isSeekable() const { return false; } + + /** + * Seek to the given time. + * @param time The time to seek to, from the beginning of the video. + * @return true on success, false otherwise. + */ + virtual bool seek(const Audio::Timestamp &time) { return false; } + + /** + * Set the pause status of the track. + */ + void pause(bool shouldPause) {} + + /** + * Return if the track is paused. + */ + bool isPaused() const { return _paused; } + + /** + * Get the duration of the track (starting from this track's start time). + * + * By default, this returns 0 for unknown. + */ + virtual Audio::Timestamp getDuration() const; + + protected: + /** + * Function called by pause() for subclasses to implement. + */ + void pauseIntern(bool pause); + + private: + bool _paused; + }; /** - * Actual implementation of pause by subclasses. See pause() - * for details. + * An abstract representation of a video track. */ - virtual void pauseVideoIntern(bool pause) {} + class VideoTrack : public Track { + public: + VideoTrack() {} + virtual ~VideoTrack() {} + + TrackType getTrackType() const { return kTrackTypeVideo; } + virtual bool endOfTrack() const; + + /** + * Get the width of this track + */ + virtual uint16 getWidth() const = 0; + + /** + * Get the height of this track + */ + virtual uint16 getHeight() const = 0; + + /** + * Get the pixel format of this track + */ + virtual Graphics::PixelFormat getPixelFormat() const = 0; + + /** + * Get the current frame of this track + * + * @see VideoDecoder::getCurFrame() + */ + virtual int getCurFrame() const = 0; + + /** + * Get the frame count of this track + * + * @note If the frame count is unknown, return 0 (which is also + * the default implementation of the function). However, one must + * also implement endOfTrack() in that case. + */ + virtual int getFrameCount() const { return 0; } + + /** + * Get the start time of the next frame in milliseconds since + * the start of the video + */ + virtual uint32 getNextFrameStartTime() const = 0; + + /** + * Decode the next frame + */ + virtual const Graphics::Surface *decodeNextFrame() = 0; + + /** + * Get the palette currently in use by this track + */ + virtual const byte *getPalette() const { return 0; } + + /** + * Does the palette currently in use by this track need to be updated? + */ + virtual bool hasDirtyPalette() const { return false; } + }; /** - * Add the time the video has been paused to maintain sync + * A VideoTrack that is played at a constant rate. + * + * If the frame count is unknown, you must override endOfTrack(). + */ + class FixedRateVideoTrack : public VideoTrack { + public: + FixedRateVideoTrack() {} + virtual ~FixedRateVideoTrack() {} + + uint32 getNextFrameStartTime() const; + virtual Audio::Timestamp getDuration() const; + + protected: + /** + * Get the rate at which this track is played. + */ + virtual Common::Rational getFrameRate() const = 0; + }; + + /** + * An abstract representation of an audio track. + */ + class AudioTrack : public Track { + public: + AudioTrack() {} + virtual ~AudioTrack() {} + + TrackType getTrackType() const { return kTrackTypeAudio; } + + virtual bool endOfTrack() const; + + /** + * Start playing this track + */ + void start(); + + /** + * Stop playing this track + */ + void stop(); + + void start(const Audio::Timestamp &limit); + + /** + * Get the volume for this track + */ + byte getVolume() const { return _volume; } + + /** + * Set the volume for this track + */ + void setVolume(byte volume); + + /** + * Get the balance for this track + */ + int8 getBalance() const { return _balance; } + + /** + * Set the balance for this track + */ + void setBalance(int8 balance); + + /** + * Get the time the AudioStream behind this track has been + * running + */ + uint32 getRunningTime() const; + + /** + * Get the sound type to be used when playing this audio track + */ + virtual Audio::Mixer::SoundType getSoundType() const { return Audio::Mixer::kPlainSoundType; } + + protected: + void pauseIntern(bool pause); + + /** + * Get the AudioStream that is the representation of this AudioTrack + */ + virtual Audio::AudioStream *getAudioStream() const = 0; + + private: + Audio::SoundHandle _handle; + byte _volume; + int8 _balance; + }; + + /** + * An AudioTrack that implements isRewindable() and rewind() using + * RewindableAudioStream. + */ + class RewindableAudioTrack : public AudioTrack { + public: + RewindableAudioTrack() {} + virtual ~RewindableAudioTrack() {} + + bool isRewindable() const { return true; } + bool rewind(); + + protected: + Audio::AudioStream *getAudioStream() const; + + /** + * Get the RewindableAudioStream pointer to be used by this class + * for rewind() and getAudioStream() + */ + virtual Audio::RewindableAudioStream *getRewindableAudioStream() const = 0; + }; + + /** + * An AudioTrack that implements isSeekable() and seek() using + * SeekableAudioStream. + */ + class SeekableAudioTrack : public AudioTrack { + public: + SeekableAudioTrack() {} + virtual ~SeekableAudioTrack() {} + + bool isSeekable() const { return true; } + bool seek(const Audio::Timestamp &time); + + Audio::Timestamp getDuration() const; + + protected: + Audio::AudioStream *getAudioStream() const; + + /** + * Get the SeekableAudioStream pointer to be used by this class + * for seek(), getDuration(), and getAudioStream() + */ + virtual Audio::SeekableAudioStream *getSeekableAudioStream() const = 0; + }; + + /** + * A SeekableAudioTrack that constructs its SeekableAudioStream using + * SeekableAudioStream::openStreamFile() */ - virtual void addPauseTime(uint32 ms) { _startTime += ms; } + class StreamFileAudioTrack : public SeekableAudioTrack { + public: + StreamFileAudioTrack(); + ~StreamFileAudioTrack(); + + /** + * Load the track from a file with the given base name. + * + * @return true on success, false otherwise + */ + bool loadFromFile(const Common::String &baseName); + + protected: + Audio::SeekableAudioStream *_stream; + Audio::SeekableAudioStream *getSeekableAudioStream() const { return _stream; } + }; /** * Reset the pause start time (which should be called when seeking) */ void resetPauseStartTime(); - int32 _curFrame; - int32 _startTime; - -private: - uint32 _pauseLevel; - uint32 _pauseStartTime; -}; + /** + * Decode enough data for the next frame and enough audio to last that long. + * + * This function is used by the decodeNextFrame() function. A subclass + * of a Track may decide to just have its decodeNextFrame() function read + * and decode the frame. + */ + virtual void readNextPacket() {} -/** - * A VideoDecoder wrapper that implements getTimeToNextFrame() based on getFrameRate(). - */ -class FixedRateVideoDecoder : public virtual VideoDecoder { -public: - uint32 getTimeToNextFrame() const; + /** + * Define a track to be used by this class. + * + * The pointer is then owned by this base class. + */ + void addTrack(Track *track); -protected: /** - * Return the frame rate in frames per second. - * This returns a Rational because videos can have rates that are not integers and - * there are some videos with frame rates < 1. + * Whether or not getTime() will sync with a playing audio track. + * + * A subclass can override this to disable this feature. */ - virtual Common::Rational getFrameRate() const = 0; + virtual bool useAudioSync() const { return true; } -private: - uint32 getFrameBeginTime(uint32 frame) const; -}; + /** + * Get the given track based on its index. + * + * @return A valid track pointer on success, 0 otherwise + */ + Track *getTrack(uint track); -/** - * A VideoDecoder that can be rewound back to the beginning. - */ -class RewindableVideoDecoder : public virtual VideoDecoder { -public: /** - * Rewind to the beginning of the video. + * Get the given track based on its index + * + * @return A valid track pointer on success, 0 otherwise */ - virtual void rewind() = 0; -}; + const Track *getTrack(uint track) const; -/** - * A VideoDecoder that can seek to a frame or point in time. - */ -class SeekableVideoDecoder : public virtual RewindableVideoDecoder { -public: /** - * Seek to the specified time. + * Find out if all video tracks have finished * - * This will round to the previous frame showing. If the time would happen to - * land while a frame is showing, this function will seek to the beginning of that - * frame. In other words, there is *no* subframe accuracy. This may change in a - * later revision of the API. + * This is useful if one wants to figure out if they need to buffer all + * remaining audio in a file. + */ + bool endOfVideoTracks() const; + + /** + * Get the default high color format + */ + Graphics::PixelFormat getDefaultHighColorFormat() const { return _defaultHighColorFormat; } + + /** + * Find the video track with the lowest start time for the next frame + */ + VideoTrack *findNextVideoTrack(); + + /** + * Find the video track with the lowest start time for the next frame */ - virtual void seekToTime(Audio::Timestamp time) = 0; + const VideoTrack *findNextVideoTrack() const; /** - * Seek to the specified time (in ms). + * Typedef helpers for accessing tracks */ - void seekToTime(uint32 msecs) { seekToTime(Audio::Timestamp(msecs, 1000)); } + typedef Common::Array<Track *> TrackList; + typedef TrackList::iterator TrackListIterator; /** - * Implementation of RewindableVideoDecoder::rewind(). + * Get the begin iterator of the tracks */ - virtual void rewind() { seekToTime(0); } + TrackListIterator getTrackListBegin() { return _tracks.begin(); } /** - * Get the total duration of the video (in ms). + * Get the end iterator of the tracks */ - virtual uint32 getDuration() const = 0; + TrackListIterator getTrackListEnd() { return _tracks.end(); } + +private: + // Tracks owned by this VideoDecoder + TrackList _tracks; + + // Current playback status + bool _isPlaying, _needsRewind, _needsUpdate; + Audio::Timestamp _lastTimeChange, _endTime; + bool _endTimeSet; + + // Palette settings from individual tracks + mutable bool _dirtyPalette; + const byte *_palette; + + // Default PixelFormat settings + Graphics::PixelFormat _defaultHighColorFormat; + + // Internal helper functions + void stopAudio(); + void startAudio(); + void startAudioLimit(const Audio::Timestamp &limit); + + int32 _startTime; + uint32 _pauseLevel; + uint32 _pauseStartTime; + byte _audioVolume; + int8 _audioBalance; }; } // End of namespace Video |