File indexing completed on 2025-01-05 03:56:36
0001 /* 0002 * The Progressive Graphics File; http://www.libpgf.org 0003 * 0004 * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $ 0005 * $Revision: 229 $ 0006 * 0007 * This file Copyright (C) 2006 xeraina GmbH, Switzerland 0008 * 0009 * This program is free software; you can redistribute it and/or 0010 * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE 0011 * as published by the Free Software Foundation; either version 2.1 0012 * of the License, or (at your option) any later version. 0013 * 0014 * This program is distributed in the hope that it will be useful, 0015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 * GNU General Public License for more details. 0018 * 0019 * You should have received a copy of the GNU General Public License 0020 * along with this program; if not, write to the Free Software 0021 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 0022 */ 0023 0024 ////////////////////////////////////////////////////////////////////// 0025 /// @file Decoder.cpp 0026 /// @brief PGF decoder class implementation 0027 /// @author C. Stamm, R. Spuler 0028 0029 #include "Decoder.h" 0030 #ifdef TRACE 0031 #include <stdio.h> 0032 #endif 0033 0034 #if defined(__GNUC__) 0035 #pragma GCC diagnostic push 0036 #pragma GCC diagnostic ignored "-Wextra" 0037 #endif 0038 0039 #if defined(__APPLE__) 0040 #pragma clang diagnostic push 0041 #pragma clang diagnostic ignored "-Wextra" 0042 #endif 0043 0044 ////////////////////////////////////////////////////// 0045 // PGF: file structure 0046 // 0047 // PGFPreHeader PGFHeader [PGFPostHeader] LevelLengths Level_n-1 Level_n-2 ... Level_0 0048 // PGFPostHeader ::= [ColorTable] [UserData] 0049 // LevelLengths ::= UINT32[nLevels] 0050 0051 ////////////////////////////////////////////////////// 0052 // Decoding scheme 0053 // input: binary file 0054 // output: wavelet coefficients stored in subbands 0055 // 0056 // file (for each buffer: packedLength (16 bit), packed bits) 0057 // | 0058 // m_codeBuffer (for each plane: RLcodeLength (16 bit), RLcoded sigBits + m_sign, refBits) 0059 // | | | 0060 // m_sign sigBits refBits [BufferLen, BufferLen, BufferLen] 0061 // | | | 0062 // m_value [BufferSize] 0063 // | 0064 // subband 0065 // 0066 0067 // Constants 0068 #define CodeBufferBitLen (CodeBufferLen*WordWidth) ///< max number of bits in m_codeBuffer 0069 #define MaxCodeLen ((1 << RLblockSizeLen) - 1) ///< max length of RL encoded block 0070 0071 ///////////////////////////////////////////////////////////////////// 0072 /// Constructor 0073 /// Read pre-header, header, and levelLength 0074 /// It might throw an IOException. 0075 /// @param stream A PGF stream 0076 /// @param preHeader [out] A PGF pre-header 0077 /// @param header [out] A PGF header 0078 /// @param postHeader [out] A PGF post-header 0079 /// @param levelLength The location of the levelLength array. The array is allocated in this method. The caller has to delete this array. 0080 /// @param userDataPos The stream position of the user data (metadata) 0081 /// @param useOMP If true, then the decoder will use multi-threading based on openMP 0082 /// @param userDataPolicy Policy of user data (meta-data) handling while reading PGF headers. 0083 CDecoder::CDecoder(CPGFStream* stream, PGFPreHeader& preHeader, PGFHeader& header, 0084 PGFPostHeader& postHeader, UINT32*& levelLength, UINT64& userDataPos, 0085 bool useOMP, UINT32 userDataPolicy) 0086 : m_stream(stream) 0087 , m_startPos(0) 0088 , m_streamSizeEstimation(0) 0089 , m_encodedHeaderLength(0) 0090 , m_currentBlockIndex(0) 0091 , m_macroBlocksAvailable(0) 0092 #ifdef __PGFROISUPPORT__ 0093 , m_roi(false) 0094 #endif 0095 { 0096 ASSERT(m_stream); 0097 0098 int count, expected; 0099 0100 // store current stream position 0101 m_startPos = m_stream->GetPos(); 0102 0103 // read magic and version 0104 count = expected = MagicVersionSize; 0105 m_stream->Read(&count, &preHeader); 0106 if (count != expected) ReturnWithError(MissingData); 0107 0108 // read header size 0109 if (preHeader.version & Version6) { 0110 // 32 bit header size since version 6 0111 count = expected = 4; 0112 } else { 0113 count = expected = 2; 0114 } 0115 m_stream->Read(&count, ((UINT8*)&preHeader) + MagicVersionSize); 0116 if (count != expected) ReturnWithError(MissingData); 0117 0118 // make sure the values are correct read 0119 preHeader.hSize = __VAL(preHeader.hSize); 0120 0121 // check magic number 0122 if (memcmp(preHeader.magic, PGFMagic, 3) != 0) { 0123 // error condition: wrong Magic number 0124 ReturnWithError(FormatCannotRead); 0125 } 0126 0127 // read file header 0128 count = expected = (preHeader.hSize < HeaderSize) ? preHeader.hSize : HeaderSize; 0129 m_stream->Read(&count, &header); 0130 if (count != expected) ReturnWithError(MissingData); 0131 0132 // make sure the values are correct read 0133 header.height = __VAL(UINT32(header.height)); 0134 header.width = __VAL(UINT32(header.width)); 0135 0136 // be ready to read all versions including version 0 0137 if (preHeader.version > 0) { 0138 #ifndef __PGFROISUPPORT__ 0139 // check ROI usage 0140 if (preHeader.version & PGFROI) ReturnWithError(FormatCannotRead); 0141 #endif 0142 0143 UINT32 size = preHeader.hSize; 0144 0145 if (size > HeaderSize) { 0146 size -= HeaderSize; 0147 count = 0; 0148 0149 // read post-header 0150 if (header.mode == ImageModeIndexedColor) { 0151 if (size < ColorTableSize) ReturnWithError(FormatCannotRead); 0152 // read color table 0153 count = expected = ColorTableSize; 0154 m_stream->Read(&count, postHeader.clut); 0155 if (count != expected) ReturnWithError(MissingData); 0156 } 0157 0158 if (size > (UINT32)count) { 0159 size -= count; 0160 0161 // read/skip user data 0162 UserdataPolicy policy = (UserdataPolicy)((userDataPolicy <= MaxUserDataSize) ? UP_CachePrefix : 0xFFFFFFFF - userDataPolicy); 0163 userDataPos = m_stream->GetPos(); 0164 postHeader.userDataLen = size; 0165 0166 if (policy == UP_Skip) { 0167 postHeader.cachedUserDataLen = 0; 0168 postHeader.userData = nullptr; 0169 Skip(size); 0170 } else { 0171 postHeader.cachedUserDataLen = (policy == UP_CachePrefix) ? __min(size, userDataPolicy) : size; 0172 0173 // create user data memory block 0174 postHeader.userData = new(std::nothrow) UINT8[postHeader.cachedUserDataLen]; 0175 if (!postHeader.userData) ReturnWithError(InsufficientMemory); 0176 0177 // read user data 0178 count = expected = postHeader.cachedUserDataLen; 0179 m_stream->Read(&count, postHeader.userData); 0180 if (count != expected) ReturnWithError(MissingData); 0181 0182 // skip remaining user data 0183 if (postHeader.cachedUserDataLen < size) Skip(size - postHeader.cachedUserDataLen); 0184 } 0185 } 0186 } 0187 0188 // create levelLength 0189 levelLength = new(std::nothrow) UINT32[header.nLevels]; 0190 if (!levelLength) ReturnWithError(InsufficientMemory); 0191 0192 // read levelLength 0193 count = expected = header.nLevels*WordBytes; 0194 m_stream->Read(&count, levelLength); 0195 if (count != expected) ReturnWithError(MissingData); 0196 0197 #ifdef PGF_USE_BIG_ENDIAN 0198 // make sure the values are correct read 0199 for (int i=0; i < header.nLevels; i++) { 0200 levelLength[i] = __VAL(levelLength[i]); 0201 } 0202 #endif 0203 0204 // compute the total size in bytes; keep attention: level length information is optional 0205 for (int i=0; i < header.nLevels; i++) { 0206 m_streamSizeEstimation += levelLength[i]; 0207 } 0208 0209 } 0210 0211 // store current stream position 0212 m_encodedHeaderLength = UINT32(m_stream->GetPos() - m_startPos); 0213 0214 // set number of threads 0215 #ifdef LIBPGF_USE_OPENMP 0216 m_macroBlockLen = omp_get_num_procs(); 0217 #else 0218 m_macroBlockLen = 1; 0219 #endif 0220 0221 if (useOMP && m_macroBlockLen > 1) { 0222 #ifdef LIBPGF_USE_OPENMP 0223 omp_set_num_threads(m_macroBlockLen); 0224 #endif 0225 0226 // create macro block array 0227 m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen]; 0228 if (!m_macroBlocks) ReturnWithError(InsufficientMemory); 0229 for (int i = 0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(); 0230 m_currentBlock = m_macroBlocks[m_currentBlockIndex]; 0231 } else { 0232 m_macroBlocks = 0; 0233 m_macroBlockLen = 1; // there is only one macro block 0234 m_currentBlock = new(std::nothrow) CMacroBlock(); 0235 if (!m_currentBlock) ReturnWithError(InsufficientMemory); 0236 } 0237 } 0238 0239 ///////////////////////////////////////////////////////////////////// 0240 // Destructor 0241 CDecoder::~CDecoder() { 0242 if (m_macroBlocks) { 0243 for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i]; 0244 delete[] m_macroBlocks; 0245 } else { 0246 delete m_currentBlock; 0247 } 0248 } 0249 0250 ////////////////////////////////////////////////////////////////////// 0251 /// Copies data from the open stream to a target buffer. 0252 /// It might throw an IOException. 0253 /// @param target The target buffer 0254 /// @param len The number of bytes to read 0255 /// @return The number of bytes copied to the target buffer 0256 UINT32 CDecoder::ReadEncodedData(UINT8* target, UINT32 len) const { 0257 ASSERT(m_stream); 0258 0259 int count = len; 0260 m_stream->Read(&count, target); 0261 0262 return count; 0263 } 0264 0265 ///////////////////////////////////////////////////////////////////// 0266 /// Unpartitions a rectangular region of a given subband. 0267 /// Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize. 0268 /// Read wavelet coefficients from the output buffer of a macro block. 0269 /// It might throw an IOException. 0270 /// @param band A subband 0271 /// @param quantParam Dequantization value 0272 /// @param width The width of the rectangle 0273 /// @param height The height of the rectangle 0274 /// @param startPos The relative subband position of the top left corner of the rectangular region 0275 /// @param pitch The number of bytes in row of the subband 0276 void CDecoder::Partition(CSubband* band, int quantParam, int width, int height, int startPos, int pitch) { 0277 ASSERT(band); 0278 0279 const div_t ww = div(width, LinBlockSize); 0280 const div_t hh = div(height, LinBlockSize); 0281 const int ws = pitch - LinBlockSize; 0282 const int wr = pitch - ww.rem; 0283 int pos, base = startPos, base2; 0284 0285 // main height 0286 for (int i=0; i < hh.quot; i++) { 0287 // main width 0288 base2 = base; 0289 for (int j=0; j < ww.quot; j++) { 0290 pos = base2; 0291 for (int y=0; y < LinBlockSize; y++) { 0292 for (int x=0; x < LinBlockSize; x++) { 0293 DequantizeValue(band, pos, quantParam); 0294 pos++; 0295 } 0296 pos += ws; 0297 } 0298 base2 += LinBlockSize; 0299 } 0300 // rest of width 0301 pos = base2; 0302 for (int y=0; y < LinBlockSize; y++) { 0303 for (int x=0; x < ww.rem; x++) { 0304 DequantizeValue(band, pos, quantParam); 0305 pos++; 0306 } 0307 pos += wr; 0308 base += pitch; 0309 } 0310 } 0311 // main width 0312 base2 = base; 0313 for (int j=0; j < ww.quot; j++) { 0314 // rest of height 0315 pos = base2; 0316 for (int y=0; y < hh.rem; y++) { 0317 for (int x=0; x < LinBlockSize; x++) { 0318 DequantizeValue(band, pos, quantParam); 0319 pos++; 0320 } 0321 pos += ws; 0322 } 0323 base2 += LinBlockSize; 0324 } 0325 // rest of height 0326 pos = base2; 0327 for (int y=0; y < hh.rem; y++) { 0328 // rest of width 0329 for (int x=0; x < ww.rem; x++) { 0330 DequantizeValue(band, pos, quantParam); 0331 pos++; 0332 } 0333 pos += wr; 0334 } 0335 } 0336 0337 //////////////////////////////////////////////////////////////////// 0338 // Decodes and dequantizes HL, and LH band of one level 0339 // LH and HH are interleaved in the codestream and must be split 0340 // Deccoding and dequantization of HL and LH Band (interleaved) using partitioning scheme 0341 // partitions the plane in squares of side length InterBlockSize 0342 // It might throw an IOException. 0343 void CDecoder::DecodeInterleaved(CWaveletTransform* wtChannel, int level, int quantParam) { 0344 CSubband* hlBand = wtChannel->GetSubband(level, HL); 0345 CSubband* lhBand = wtChannel->GetSubband(level, LH); 0346 const div_t lhH = div(lhBand->GetHeight(), InterBlockSize); 0347 const div_t hlW = div(hlBand->GetWidth(), InterBlockSize); 0348 const int hlws = hlBand->GetWidth() - InterBlockSize; 0349 const int hlwr = hlBand->GetWidth() - hlW.rem; 0350 const int lhws = lhBand->GetWidth() - InterBlockSize; 0351 const int lhwr = lhBand->GetWidth() - hlW.rem; 0352 int hlPos, lhPos; 0353 int hlBase = 0, lhBase = 0, hlBase2, lhBase2; 0354 0355 ASSERT(lhBand->GetWidth() >= hlBand->GetWidth()); 0356 ASSERT(hlBand->GetHeight() >= lhBand->GetHeight()); 0357 0358 if (!hlBand->AllocMemory()) ReturnWithError(InsufficientMemory); 0359 if (!lhBand->AllocMemory()) ReturnWithError(InsufficientMemory); 0360 0361 // correct quantParam with normalization factor 0362 quantParam -= level; 0363 if (quantParam < 0) quantParam = 0; 0364 0365 // main height 0366 for (int i=0; i < lhH.quot; i++) { 0367 // main width 0368 hlBase2 = hlBase; 0369 lhBase2 = lhBase; 0370 for (int j=0; j < hlW.quot; j++) { 0371 hlPos = hlBase2; 0372 lhPos = lhBase2; 0373 for (int y=0; y < InterBlockSize; y++) { 0374 for (int x=0; x < InterBlockSize; x++) { 0375 DequantizeValue(hlBand, hlPos, quantParam); 0376 DequantizeValue(lhBand, lhPos, quantParam); 0377 hlPos++; 0378 lhPos++; 0379 } 0380 hlPos += hlws; 0381 lhPos += lhws; 0382 } 0383 hlBase2 += InterBlockSize; 0384 lhBase2 += InterBlockSize; 0385 } 0386 // rest of width 0387 hlPos = hlBase2; 0388 lhPos = lhBase2; 0389 for (int y=0; y < InterBlockSize; y++) { 0390 for (int x=0; x < hlW.rem; x++) { 0391 DequantizeValue(hlBand, hlPos, quantParam); 0392 DequantizeValue(lhBand, lhPos, quantParam); 0393 hlPos++; 0394 lhPos++; 0395 } 0396 // width difference between HL and LH 0397 if (lhBand->GetWidth() > hlBand->GetWidth()) { 0398 DequantizeValue(lhBand, lhPos, quantParam); 0399 } 0400 hlPos += hlwr; 0401 lhPos += lhwr; 0402 hlBase += hlBand->GetWidth(); 0403 lhBase += lhBand->GetWidth(); 0404 } 0405 } 0406 // main width 0407 hlBase2 = hlBase; 0408 lhBase2 = lhBase; 0409 for (int j=0; j < hlW.quot; j++) { 0410 // rest of height 0411 hlPos = hlBase2; 0412 lhPos = lhBase2; 0413 for (int y=0; y < lhH.rem; y++) { 0414 for (int x=0; x < InterBlockSize; x++) { 0415 DequantizeValue(hlBand, hlPos, quantParam); 0416 DequantizeValue(lhBand, lhPos, quantParam); 0417 hlPos++; 0418 lhPos++; 0419 } 0420 hlPos += hlws; 0421 lhPos += lhws; 0422 } 0423 hlBase2 += InterBlockSize; 0424 lhBase2 += InterBlockSize; 0425 } 0426 // rest of height 0427 hlPos = hlBase2; 0428 lhPos = lhBase2; 0429 for (int y=0; y < lhH.rem; y++) { 0430 // rest of width 0431 for (int x=0; x < hlW.rem; x++) { 0432 DequantizeValue(hlBand, hlPos, quantParam); 0433 DequantizeValue(lhBand, lhPos, quantParam); 0434 hlPos++; 0435 lhPos++; 0436 } 0437 // width difference between HL and LH 0438 if (lhBand->GetWidth() > hlBand->GetWidth()) { 0439 DequantizeValue(lhBand, lhPos, quantParam); 0440 } 0441 hlPos += hlwr; 0442 lhPos += lhwr; 0443 hlBase += hlBand->GetWidth(); 0444 } 0445 // height difference between HL and LH 0446 if (hlBand->GetHeight() > lhBand->GetHeight()) { 0447 // total width 0448 hlPos = hlBase; 0449 for (int j=0; j < hlBand->GetWidth(); j++) { 0450 DequantizeValue(hlBand, hlPos, quantParam); 0451 hlPos++; 0452 } 0453 } 0454 } 0455 0456 //////////////////////////////////////////////////////////////////// 0457 /// Skips a given number of bytes in the open stream. 0458 /// It might throw an IOException. 0459 void CDecoder::Skip(UINT64 offset) { 0460 m_stream->SetPos(FSFromCurrent, offset); 0461 } 0462 0463 ////////////////////////////////////////////////////////////////////// 0464 /// Dequantization of a single value at given position in subband. 0465 /// If encoded data is available, then stores dequantized band value into 0466 /// buffer m_value at position m_valuePos. 0467 /// Otherwise reads encoded data block and decodes it. 0468 /// It might throw an IOException. 0469 /// @param band A subband 0470 /// @param bandPos A valid position in subband band 0471 /// @param quantParam The quantization parameter 0472 void CDecoder::DequantizeValue(CSubband* band, UINT32 bandPos, int quantParam) { 0473 ASSERT(m_currentBlock); 0474 0475 if (m_currentBlock->IsCompletelyRead()) { 0476 // all data of current macro block has been read --> prepare next macro block 0477 GetNextMacroBlock(); 0478 } 0479 0480 band->SetData(bandPos, m_currentBlock->m_value[m_currentBlock->m_valuePos] << quantParam); 0481 m_currentBlock->m_valuePos++; 0482 } 0483 0484 ////////////////////////////////////////////////////////////////////// 0485 // Gets next macro block 0486 // It might throw an IOException. 0487 void CDecoder::GetNextMacroBlock() { 0488 // current block has been read --> prepare next current block 0489 m_macroBlocksAvailable--; 0490 0491 if (m_macroBlocksAvailable > 0) { 0492 m_currentBlock = m_macroBlocks[++m_currentBlockIndex]; 0493 } else { 0494 DecodeBuffer(); 0495 } 0496 ASSERT(m_currentBlock); 0497 } 0498 0499 ////////////////////////////////////////////////////////////////////// 0500 // Reads next block(s) from stream and decodes them 0501 // Decoding scheme: <wordLen>(16 bits) [ ROI ] data 0502 // ROI ::= <bufferSize>(15 bits) <eofTile>(1 bit) 0503 // It might throw an IOException. 0504 void CDecoder::DecodeBuffer() { 0505 ASSERT(m_macroBlocksAvailable <= 0); 0506 0507 // macro block management 0508 if (m_macroBlockLen == 1) { 0509 ASSERT(m_currentBlock); 0510 ReadMacroBlock(m_currentBlock); 0511 m_currentBlock->BitplaneDecode(); 0512 m_macroBlocksAvailable = 1; 0513 } else { 0514 m_macroBlocksAvailable = 0; 0515 for (int i=0; i < m_macroBlockLen; i++) { 0516 // read sequentially several blocks 0517 try { 0518 ReadMacroBlock(m_macroBlocks[i]); 0519 m_macroBlocksAvailable++; 0520 } catch(IOException& ex) { 0521 if (ex.error == MissingData || ex.error == FormatCannotRead) { 0522 break; // no further data available or the data isn't valid PGF data (might occur in streaming or PPPExt) 0523 } else { 0524 throw; 0525 } 0526 } 0527 } 0528 #ifdef LIBPGF_USE_OPENMP 0529 // decode in parallel 0530 #pragma omp parallel for default(shared) //no declared exceptions in next block 0531 #endif 0532 for (int i=0; i < m_macroBlocksAvailable; i++) { 0533 m_macroBlocks[i]->BitplaneDecode(); 0534 } 0535 0536 // prepare current macro block 0537 m_currentBlockIndex = 0; 0538 m_currentBlock = m_macroBlocks[m_currentBlockIndex]; 0539 } 0540 } 0541 0542 ////////////////////////////////////////////////////////////////////// 0543 // Reads next block from stream and stores it in the given macro block 0544 // It might throw an IOException. 0545 void CDecoder::ReadMacroBlock(CMacroBlock* block) { 0546 ASSERT(block); 0547 0548 UINT16 wordLen; 0549 ROIBlockHeader h(BufferSize); 0550 int count, expected; 0551 0552 #ifdef TRACE 0553 //UINT32 filePos = (UINT32)m_stream->GetPos(); 0554 //printf("DecodeBuffer: %d\n", filePos); 0555 #endif 0556 0557 // read wordLen 0558 count = expected = sizeof(UINT16); 0559 m_stream->Read(&count, &wordLen); 0560 if (count != expected) ReturnWithError(MissingData); 0561 wordLen = __VAL(wordLen); // convert wordLen 0562 if (wordLen > BufferSize) ReturnWithError(FormatCannotRead); 0563 0564 #ifdef __PGFROISUPPORT__ 0565 // read ROIBlockHeader 0566 if (m_roi) { 0567 count = expected = sizeof(ROIBlockHeader); 0568 m_stream->Read(&count, &h.val); 0569 if (count != expected) ReturnWithError(MissingData); 0570 h.val = __VAL(h.val); // convert ROIBlockHeader 0571 } 0572 #endif 0573 // save header 0574 block->m_header = h; 0575 0576 // read data 0577 count = expected = wordLen*WordBytes; 0578 m_stream->Read(&count, block->m_codeBuffer); 0579 if (count != expected) ReturnWithError(MissingData); 0580 0581 #ifdef PGF_USE_BIG_ENDIAN 0582 // convert data 0583 count /= WordBytes; 0584 for (int i=0; i < count; i++) { 0585 block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]); 0586 } 0587 #endif 0588 0589 #ifdef __PGFROISUPPORT__ 0590 ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize); 0591 #else 0592 ASSERT(h.rbh.bufferSize == BufferSize); 0593 #endif 0594 } 0595 0596 #ifdef __PGFROISUPPORT__ 0597 ////////////////////////////////////////////////////////////////////// 0598 // Resets stream position to next tile. 0599 // Used with ROI encoding scheme only. 0600 // Reads several next blocks from stream but doesn't decode them into macro blocks 0601 // Encoding scheme: <wordLen>(16 bits) ROI data 0602 // ROI ::= <bufferSize>(15 bits) <eofTile>(1 bit) 0603 // It might throw an IOException. 0604 void CDecoder::SkipTileBuffer() { 0605 ASSERT(m_roi); 0606 0607 // current macro block belongs to the last tile, so go to the next macro block 0608 m_macroBlocksAvailable--; 0609 m_currentBlockIndex++; 0610 0611 // check if pre-decoded data is available 0612 while (m_macroBlocksAvailable > 0 && !m_macroBlocks[m_currentBlockIndex]->m_header.rbh.tileEnd) { 0613 m_macroBlocksAvailable--; 0614 m_currentBlockIndex++; 0615 } 0616 if (m_macroBlocksAvailable > 0) { 0617 // set new current macro block 0618 m_currentBlock = m_macroBlocks[m_currentBlockIndex]; 0619 ASSERT(m_currentBlock->m_header.rbh.tileEnd); 0620 return; 0621 } 0622 0623 ASSERT(m_macroBlocksAvailable <= 0); 0624 m_macroBlocksAvailable = 0; 0625 UINT16 wordLen; 0626 ROIBlockHeader h(0); 0627 int count, expected; 0628 0629 // skips all blocks until tile end 0630 do { 0631 // read wordLen 0632 count = expected = sizeof(wordLen); 0633 m_stream->Read(&count, &wordLen); 0634 if (count != expected) ReturnWithError(MissingData); 0635 wordLen = __VAL(wordLen); // convert wordLen 0636 if (wordLen > BufferSize) ReturnWithError(FormatCannotRead); 0637 0638 // read ROIBlockHeader 0639 count = expected = sizeof(ROIBlockHeader); 0640 m_stream->Read(&count, &h.val); 0641 if (count != expected) ReturnWithError(MissingData); 0642 h.val = __VAL(h.val); // convert ROIBlockHeader 0643 0644 // skip data 0645 m_stream->SetPos(FSFromCurrent, wordLen*WordBytes); 0646 } while (!h.rbh.tileEnd); 0647 } 0648 #endif 0649 0650 ////////////////////////////////////////////////////////////////////// 0651 // Decodes macro block into buffer of given size using bit plane coding. 0652 // A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane. 0653 // Following coding scheme is used: 0654 // Buffer ::= <nPlanes>(5 bits) Q_FOREACH (plane i): Plane[i] 0655 // Plane[i] ::= [ Sig1 | Sig2 ] [DWORD alignment] refBits 0656 // Sig1 ::= 1 <codeLen>(15 bits) codedSigAndSignBits 0657 // Sig2 ::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] [DWORD alignment] sigBits 0658 // Sign1 ::= 1 <codeLen>(15 bits) codedSignBits 0659 // Sign2 ::= 0 <signLen>(15 bits) [DWORD alignment] signBits 0660 void CDecoder::CMacroBlock::BitplaneDecode() { 0661 UINT32 bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize); 0662 0663 // clear significance vector 0664 for (UINT32 k=0; k < bufferSize; k++) { 0665 m_sigFlagVector[k] = false; 0666 } 0667 m_sigFlagVector[bufferSize] = true; // sentinel 0668 0669 // clear output buffer 0670 for (UINT32 k=0; k < BufferSize; k++) { 0671 m_value[k] = 0; 0672 } 0673 0674 // read number of bit planes 0675 // <nPlanes> 0676 UINT32 nPlanes = GetValueBlock(m_codeBuffer, 0, MaxBitPlanesLog); 0677 UINT32 codePos = MaxBitPlanesLog; 0678 0679 // loop through all bit planes 0680 if (nPlanes == 0) nPlanes = MaxBitPlanes + 1; 0681 ASSERT(0 < nPlanes && nPlanes <= MaxBitPlanes + 1); 0682 DataT planeMask = 1 << (nPlanes - 1); 0683 0684 for (int plane = nPlanes - 1; plane >= 0; plane--) { 0685 UINT32 sigLen = 0; 0686 0687 // read RL code 0688 if (GetBit(m_codeBuffer, codePos)) { 0689 // RL coding of sigBits is used 0690 // <1><codeLen><codedSigAndSignBits>_<refBits> 0691 codePos++; 0692 0693 // read codeLen 0694 UINT32 codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(codeLen <= MaxCodeLen); 0695 0696 // position of encoded sigBits and signBits 0697 UINT32 sigPos = codePos + RLblockSizeLen; ASSERT(sigPos < CodeBufferBitLen); 0698 0699 // refinement bits 0700 codePos = AlignWordPos(sigPos + codeLen); ASSERT(codePos < CodeBufferBitLen); 0701 0702 // run-length decode significant bits and signs from m_codeBuffer and 0703 // read refinement bits from m_codeBuffer and compose bit plane 0704 sigLen = ComposeBitplaneRLD(bufferSize, planeMask, sigPos, &m_codeBuffer[codePos >> WordWidthLog]); 0705 0706 } else { 0707 // no RL coding is used for sigBits and signBits together 0708 // <0><sigLen> 0709 codePos++; 0710 0711 // read sigLen 0712 sigLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(sigLen <= MaxCodeLen); 0713 codePos += RLblockSizeLen; ASSERT(codePos < CodeBufferBitLen); 0714 0715 // read RL code for signBits 0716 if (GetBit(m_codeBuffer, codePos)) { 0717 // RL coding is used just for signBits 0718 // <1><codeLen><codedSignBits>_<sigBits>_<refBits> 0719 codePos++; 0720 0721 // read codeLen 0722 UINT32 codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(codeLen <= MaxCodeLen); 0723 0724 // sign bits 0725 UINT32 signPos = codePos + RLblockSizeLen; ASSERT(signPos < CodeBufferBitLen); 0726 0727 // significant bits 0728 UINT32 sigPos = AlignWordPos(signPos + codeLen); ASSERT(sigPos < CodeBufferBitLen); 0729 0730 // refinement bits 0731 codePos = AlignWordPos(sigPos + sigLen); ASSERT(codePos < CodeBufferBitLen); 0732 0733 // read significant and refinement bitset from m_codeBuffer 0734 sigLen = ComposeBitplaneRLD(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], signPos); 0735 0736 } else { 0737 // RL coding of signBits was not efficient and therefore not used 0738 // <0><signLen>_<signBits>_<sigBits>_<refBits> 0739 codePos++; 0740 0741 // read signLen 0742 UINT32 signLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(signLen <= MaxCodeLen); 0743 0744 // sign bits 0745 UINT32 signPos = AlignWordPos(codePos + RLblockSizeLen); ASSERT(signPos < CodeBufferBitLen); 0746 0747 // significant bits 0748 UINT32 sigPos = AlignWordPos(signPos + signLen); ASSERT(sigPos < CodeBufferBitLen); 0749 0750 // refinement bits 0751 codePos = AlignWordPos(sigPos + sigLen); ASSERT(codePos < CodeBufferBitLen); 0752 0753 // read significant and refinement bitset from m_codeBuffer 0754 sigLen = ComposeBitplane(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], &m_codeBuffer[signPos >> WordWidthLog]); 0755 } 0756 } 0757 0758 // start of next chunk 0759 codePos = AlignWordPos(codePos + bufferSize - sigLen); ASSERT(codePos < CodeBufferBitLen); 0760 0761 // next plane 0762 planeMask >>= 1; 0763 } 0764 0765 m_valuePos = 0; 0766 } 0767 0768 //////////////////////////////////////////////////////////////////// 0769 // Reconstructs bitplane from significant bitset and refinement bitset 0770 // returns length [bits] of sigBits 0771 // input: sigBits, refBits, signBits 0772 // output: m_value 0773 UINT32 CDecoder::CMacroBlock::ComposeBitplane(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits) { 0774 ASSERT(sigBits); 0775 ASSERT(refBits); 0776 ASSERT(signBits); 0777 0778 UINT32 valPos = 0, signPos = 0, refPos = 0, sigPos = 0; 0779 0780 while (valPos < bufferSize) { 0781 // search next 1 in m_sigFlagVector using searching with sentinel 0782 UINT32 sigEnd = valPos; 0783 while(!m_sigFlagVector[sigEnd]) { sigEnd++; } 0784 sigEnd -= valPos; 0785 sigEnd += sigPos; 0786 0787 // search 1's in sigBits[sigPos..sigEnd) 0788 // these 1's are significant bits 0789 while (sigPos < sigEnd) { 0790 // search 0's 0791 UINT32 zerocnt = SeekBitRange(sigBits, sigPos, sigEnd - sigPos); 0792 sigPos += zerocnt; 0793 valPos += zerocnt; 0794 if (sigPos < sigEnd) { 0795 // write bit to m_value 0796 SetBitAtPos(valPos, planeMask); 0797 0798 // copy sign bit 0799 SetSign(valPos, GetBit(signBits, signPos++)); 0800 0801 // update significance flag vector 0802 m_sigFlagVector[valPos++] = true; 0803 sigPos++; 0804 } 0805 } 0806 // refinement bit 0807 if (valPos < bufferSize) { 0808 // write one refinement bit 0809 if (GetBit(refBits, refPos)) { 0810 SetBitAtPos(valPos, planeMask); 0811 } 0812 refPos++; 0813 valPos++; 0814 } 0815 } 0816 ASSERT(sigPos <= bufferSize); 0817 ASSERT(refPos <= bufferSize); 0818 ASSERT(signPos <= bufferSize); 0819 ASSERT(valPos == bufferSize); 0820 0821 return sigPos; 0822 } 0823 0824 //////////////////////////////////////////////////////////////////// 0825 // Reconstructs bitplane from significant bitset and refinement bitset 0826 // returns length [bits] of decoded significant bits 0827 // input: RL encoded sigBits and signBits in m_codeBuffer, refBits 0828 // output: m_value 0829 // RLE: 0830 // - Decode run of 2^k zeros by a single 0. 0831 // - Decode run of count 0's followed by a 1 with codeword: 1<count>x 0832 // - x is 0: if a positive sign has been stored, otherwise 1 0833 // - Read each bit from m_codeBuffer[codePos] and increment codePos. 0834 UINT32 CDecoder::CMacroBlock::ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32 codePos, UINT32* refBits) { 0835 ASSERT(refBits); 0836 0837 UINT32 valPos = 0, refPos = 0; 0838 UINT32 sigPos = 0, sigEnd; 0839 UINT32 k = 3; 0840 UINT32 runlen = 1 << k; // = 2^k 0841 UINT32 count = 0, rest = 0; 0842 bool set1 = false; 0843 0844 while (valPos < bufferSize) { 0845 // search next 1 in m_sigFlagVector using searching with sentinel 0846 sigEnd = valPos; 0847 while(!m_sigFlagVector[sigEnd]) { sigEnd++; } 0848 sigEnd -= valPos; 0849 sigEnd += sigPos; 0850 0851 while (sigPos < sigEnd) { 0852 if (rest || set1) { 0853 // rest of last run 0854 sigPos += rest; 0855 valPos += rest; 0856 rest = 0; 0857 } else { 0858 // decode significant bits 0859 if (GetBit(m_codeBuffer, codePos++)) { 0860 // extract counter and generate zero run of length count 0861 if (k > 0) { 0862 // extract counter 0863 count = GetValueBlock(m_codeBuffer, codePos, k); 0864 codePos += k; 0865 if (count > 0) { 0866 sigPos += count; 0867 valPos += count; 0868 } 0869 0870 // adapt k (half run-length interval) 0871 k--; 0872 runlen >>= 1; 0873 } 0874 0875 set1 = true; 0876 0877 } else { 0878 // generate zero run of length 2^k 0879 sigPos += runlen; 0880 valPos += runlen; 0881 0882 // adapt k (double run-length interval) 0883 if (k < WordWidth) { 0884 k++; 0885 runlen <<= 1; 0886 } 0887 } 0888 } 0889 0890 if (sigPos < sigEnd) { 0891 if (set1) { 0892 set1 = false; 0893 0894 // write 1 bit 0895 SetBitAtPos(valPos, planeMask); 0896 0897 // set sign bit 0898 SetSign(valPos, GetBit(m_codeBuffer, codePos++)); 0899 0900 // update significance flag vector 0901 m_sigFlagVector[valPos++] = true; 0902 sigPos++; 0903 } 0904 } else { 0905 rest = sigPos - sigEnd; 0906 sigPos = sigEnd; 0907 valPos -= rest; 0908 } 0909 0910 } 0911 0912 // refinement bit 0913 if (valPos < bufferSize) { 0914 // write one refinement bit 0915 if (GetBit(refBits, refPos)) { 0916 SetBitAtPos(valPos, planeMask); 0917 } 0918 refPos++; 0919 valPos++; 0920 } 0921 } 0922 ASSERT(sigPos <= bufferSize); 0923 ASSERT(refPos <= bufferSize); 0924 ASSERT(valPos == bufferSize); 0925 0926 return sigPos; 0927 } 0928 0929 //////////////////////////////////////////////////////////////////// 0930 // Reconstructs bitplane from significant bitset, refinement bitset, and RL encoded sign bits 0931 // returns length [bits] of sigBits 0932 // input: sigBits, refBits, RL encoded signBits 0933 // output: m_value 0934 // RLE: 0935 // decode run of 2^k 1's by a single 1 0936 // decode run of count 1's followed by a 0 with codeword: 0<count> 0937 UINT32 CDecoder::CMacroBlock::ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32 signPos) { 0938 ASSERT(sigBits); 0939 ASSERT(refBits); 0940 0941 UINT32 valPos = 0, refPos = 0; 0942 UINT32 sigPos = 0, sigEnd; 0943 UINT32 zerocnt, count = 0; 0944 UINT32 k = 0; 0945 UINT32 runlen = 1 << k; // = 2^k 0946 bool signBit = false; 0947 bool zeroAfterRun = false; 0948 0949 while (valPos < bufferSize) { 0950 // search next 1 in m_sigFlagVector using searching with sentinel 0951 sigEnd = valPos; 0952 while(!m_sigFlagVector[sigEnd]) { sigEnd++; } 0953 sigEnd -= valPos; 0954 sigEnd += sigPos; 0955 0956 // search 1's in sigBits[sigPos..sigEnd) 0957 // these 1's are significant bits 0958 while (sigPos < sigEnd) { 0959 // search 0's 0960 zerocnt = SeekBitRange(sigBits, sigPos, sigEnd - sigPos); 0961 sigPos += zerocnt; 0962 valPos += zerocnt; 0963 if (sigPos < sigEnd) { 0964 // write bit to m_value 0965 SetBitAtPos(valPos, planeMask); 0966 0967 // check sign bit 0968 if (count == 0) { 0969 // all 1's have been set 0970 if (zeroAfterRun) { 0971 // finish the run with a 0 0972 signBit = false; 0973 zeroAfterRun = false; 0974 } else { 0975 // decode next sign bit 0976 if (GetBit(m_codeBuffer, signPos++)) { 0977 // generate 1's run of length 2^k 0978 count = runlen - 1; 0979 signBit = true; 0980 0981 // adapt k (double run-length interval) 0982 if (k < WordWidth) { 0983 k++; 0984 runlen <<= 1; 0985 } 0986 } else { 0987 // extract counter and generate 1's run of length count 0988 if (k > 0) { 0989 // extract counter 0990 count = GetValueBlock(m_codeBuffer, signPos, k); 0991 signPos += k; 0992 0993 // adapt k (half run-length interval) 0994 k--; 0995 runlen >>= 1; 0996 } 0997 if (count > 0) { 0998 count--; 0999 signBit = true; 1000 zeroAfterRun = true; 1001 } else { 1002 signBit = false; 1003 } 1004 } 1005 } 1006 } else { 1007 ASSERT(count > 0); 1008 ASSERT(signBit); 1009 count--; 1010 } 1011 1012 // copy sign bit 1013 SetSign(valPos, signBit); 1014 1015 // update significance flag vector 1016 m_sigFlagVector[valPos++] = true; 1017 sigPos++; 1018 } 1019 } 1020 1021 // refinement bit 1022 if (valPos < bufferSize) { 1023 // write one refinement bit 1024 if (GetBit(refBits, refPos)) { 1025 SetBitAtPos(valPos, planeMask); 1026 } 1027 refPos++; 1028 valPos++; 1029 } 1030 } 1031 ASSERT(sigPos <= bufferSize); 1032 ASSERT(refPos <= bufferSize); 1033 ASSERT(valPos == bufferSize); 1034 1035 return sigPos; 1036 } 1037 1038 //////////////////////////////////////////////////////////////////// 1039 #ifdef TRACE 1040 void CDecoder::DumpBuffer() { 1041 //printf("\nDump\n"); 1042 //for (int i=0; i < BufferSize; i++) { 1043 // printf("%d", m_value[i]); 1044 //} 1045 } 1046 #endif //TRACE 1047 1048 #if defined(__GNUC__) 1049 #pragma GCC diagnostic pop 1050 #endif 1051 1052 #if defined(__APPLE__) 1053 #pragma clang diagnostic pop 1054 #endif