CDecoder - Man Page
PGF decoder.
Synopsis
#include <Decoder.h>
Classes
class CMacroBlock
A macro block is a decoding unit of fixed size (uncoded)
Public Member Functions
CDecoder (CPGFStream *stream, PGFPreHeader &preHeader, PGFHeader &header, PGFPostHeader &postHeader, UINT32 *&levelLength, UINT64 &userDataPos, bool useOMP, UINT32 userDataPolicy)
~CDecoder ()
Destructor.
void Partition (CSubband *band, int quantParam, int width, int height, int startPos, int pitch)
void DecodeInterleaved (CWaveletTransform *wtChannel, int level, int quantParam)
UINT32 GetEncodedHeaderLength () const
void SetStreamPosToStart ()
Resets stream position to beginning of PGF pre-header.
void SetStreamPosToData ()
Resets stream position to beginning of data block.
void Skip (UINT64 offset)
void DequantizeValue (CSubband *band, UINT32 bandPos, int quantParam)
UINT32 ReadEncodedData (UINT8 *target, UINT32 len) const
void DecodeBuffer ()
CPGFStream * GetStream ()
void GetNextMacroBlock ()
Private Member Functions
void ReadMacroBlock (CMacroBlock *block)
throws IOException
Private Attributes
CPGFStream * m_stream
input PGF stream
UINT64 m_startPos
stream position at the beginning of the PGF pre-header
UINT64 m_streamSizeEstimation
estimation of stream size
UINT32 m_encodedHeaderLength
stream offset from startPos to the beginning of the data part (highest level)
CMacroBlock ** m_macroBlocks
array of macroblocks
int m_currentBlockIndex
index of current macro block
int m_macroBlockLen
array length
int m_macroBlocksAvailable
number of decoded macro blocks (including currently used macro block)
CMacroBlock * m_currentBlock
current macro block (used by main thread)
Detailed Description
PGF decoder.
PGF decoder class.
- Author
C. Stamm, R. Spuler
Definition at line 46 of file Decoder.h.
Constructor & Destructor Documentation
CDecoder::CDecoder (CPGFStream * stream, PGFPreHeader & preHeader, PGFHeader & header, PGFPostHeader & postHeader, UINT32 *& levelLength, UINT64 & userDataPos, bool useOMP, UINT32 userDataPolicy)
Constructor: Read pre-header, header, and levelLength at current stream position. It might throw an IOException.
- Parameters
stream A PGF stream
preHeader [out] A PGF pre-header
header [out] A PGF header
postHeader [out] A PGF post-header
levelLength The location of the levelLength array. The array is allocated in this method. The caller has to delete this array.
userDataPos The stream position of the user data (metadata)
useOMP If true, then the decoder will use multi-threading based on openMP
userDataPolicy Policy of user data (meta-data) handling while reading PGF headers.
Constructor Read pre-header, header, and levelLength It might throw an IOException.
- Parameters
stream A PGF stream
preHeader [out] A PGF pre-header
header [out] A PGF header
postHeader [out] A PGF post-header
levelLength The location of the levelLength array. The array is allocated in this method. The caller has to delete this array.
userDataPos The stream position of the user data (metadata)
useOMP If true, then the decoder will use multi-threading based on openMP
userDataPolicy Policy of user data (meta-data) handling while reading PGF headers.
Definition at line 73 of file Decoder.cpp.
76 : m_stream(stream) 77 , m_startPos(0) 78 , m_streamSizeEstimation(0) 79 , m_encodedHeaderLength(0) 80 , m_currentBlockIndex(0) 81 , m_macroBlocksAvailable(0) 82 #ifdef __PGFROISUPPORT__ 83 , m_roi(false) 84 #endif 85 { 86 ASSERT(m_stream); 87 88 int count, expected; 89 90 // store current stream position 91 m_startPos = m_stream->GetPos(); 92 93 // read magic and version 94 count = expected = MagicVersionSize; 95 m_stream->Read(&count, &preHeader); 96 if (count != expected) ReturnWithError(MissingData); 97 98 // read header size 99 if (preHeader.version & Version6) { 100 // 32 bit header size since version 6 101 count = expected = 4; 102 } else { 103 count = expected = 2; 104 } 105 m_stream->Read(&count, ((UINT8*)&preHeader) + MagicVersionSize); 106 if (count != expected) ReturnWithError(MissingData); 107 108 // make sure the values are correct read 109 preHeader.hSize = __VAL(preHeader.hSize); 110 111 // check magic number 112 if (memcmp(preHeader.magic, PGFMagic, 3) != 0) { 113 // error condition: wrong Magic number 114 ReturnWithError(FormatCannotRead); 115 } 116 117 // read file header 118 count = expected = (preHeader.hSize < HeaderSize) ? preHeader.hSize : HeaderSize; 119 m_stream->Read(&count, &header); 120 if (count != expected) ReturnWithError(MissingData); 121 122 // make sure the values are correct read 123 header.height = __VAL(UINT32(header.height)); 124 header.width = __VAL(UINT32(header.width)); 125 126 // be ready to read all versions including version 0 127 if (preHeader.version > 0) { 128 #ifndef __PGFROISUPPORT__ 129 // check ROI usage 130 if (preHeader.version & PGFROI) ReturnWithError(FormatCannotRead); 131 #endif 132 133 UINT32 size = preHeader.hSize; 134 135 if (size > HeaderSize) { 136 size -= HeaderSize; 137 count = 0; 138 139 // read post-header 140 if (header.mode == ImageModeIndexedColor) { 141 if (size < ColorTableSize) ReturnWithError(FormatCannotRead); 142 // read color table 143 count = expected = ColorTableSize; 144 m_stream->Read(&count, postHeader.clut); 145 if (count != expected) ReturnWithError(MissingData); 146 } 147 148 if (size > (UINT32)count) { 149 size -= count; 150 151 // read/skip user data 152 UserdataPolicy policy = (UserdataPolicy)((userDataPolicy <= MaxUserDataSize) ? UP_CachePrefix : 0xFFFFFFFF - userDataPolicy); 153 userDataPos = m_stream->GetPos(); 154 postHeader.userDataLen = size; 155 156 if (policy == UP_Skip) { 157 postHeader.cachedUserDataLen = 0; 158 postHeader.userData = nullptr; 159 Skip(size); 160 } else { 161 postHeader.cachedUserDataLen = (policy == UP_CachePrefix) ? __min(size, userDataPolicy) : size; 162 163 // create user data memory block 164 postHeader.userData = new(std::nothrow) UINT8[postHeader.cachedUserDataLen]; 165 if (!postHeader.userData) ReturnWithError(InsufficientMemory); 166 167 // read user data 168 count = expected = postHeader.cachedUserDataLen; 169 m_stream->Read(&count, postHeader.userData); 170 if (count != expected) ReturnWithError(MissingData); 171 172 // skip remaining user data 173 if (postHeader.cachedUserDataLen < size) Skip(size - postHeader.cachedUserDataLen); 174 } 175 } 176 } 177 178 // create levelLength 179 levelLength = new(std::nothrow) UINT32[header.nLevels]; 180 if (!levelLength) ReturnWithError(InsufficientMemory); 181 182 // read levelLength 183 count = expected = header.nLevels*WordBytes; 184 m_stream->Read(&count, levelLength); 185 if (count != expected) ReturnWithError(MissingData); 186 187 #ifdef PGF_USE_BIG_ENDIAN 188 // make sure the values are correct read 189 for (int i=0; i < header.nLevels; i++) { 190 levelLength[i] = __VAL(levelLength[i]); 191 } 192 #endif 193 194 // compute the total size in bytes; keep attention: level length information is optional 195 for (int i=0; i < header.nLevels; i++) { 196 m_streamSizeEstimation += levelLength[i]; 197 } 198 199 } 200 201 // store current stream position 202 m_encodedHeaderLength = UINT32(m_stream->GetPos() - m_startPos); 203 204 // set number of threads 205 #ifdef LIBPGF_USE_OPENMP 206 m_macroBlockLen = omp_get_num_procs(); 207 #else 208 m_macroBlockLen = 1; 209 #endif 210 211 if (useOMP && m_macroBlockLen > 1) { 212 #ifdef LIBPGF_USE_OPENMP 213 omp_set_num_threads(m_macroBlockLen); 214 #endif 215 216 // create macro block array 217 m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen]; 218 if (!m_macroBlocks) ReturnWithError(InsufficientMemory); 219 for (int i = 0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(); 220 m_currentBlock = m_macroBlocks[m_currentBlockIndex]; 221 } else { 222 m_macroBlocks = 0; 223 m_macroBlockLen = 1; // there is only one macro block 224 m_currentBlock = new(std::nothrow) CMacroBlock(); 225 if (!m_currentBlock) ReturnWithError(InsufficientMemory); 226 } 227 }
CDecoder::~CDecoder ()
Destructor.
Definition at line 231 of file Decoder.cpp.
231 { 232 if (m_macroBlocks) { 233 for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i]; 234 delete[] m_macroBlocks; 235 } else { 236 delete m_currentBlock; 237 } 238 }
Member Function Documentation
void CDecoder::DecodeBuffer ()
Reads next block(s) from stream and decodes them It might throw an IOException.
Definition at line 494 of file Decoder.cpp.
494 { 495 ASSERT(m_macroBlocksAvailable <= 0); 496 497 // macro block management 498 if (m_macroBlockLen == 1) { 499 ASSERT(m_currentBlock); 500 ReadMacroBlock(m_currentBlock); 501 m_currentBlock->BitplaneDecode(); 502 m_macroBlocksAvailable = 1; 503 } else { 504 m_macroBlocksAvailable = 0; 505 for (int i=0; i < m_macroBlockLen; i++) { 506 // read sequentially several blocks 507 try { 508 ReadMacroBlock(m_macroBlocks[i]); 509 m_macroBlocksAvailable++; 510 } catch(IOException& ex) { 511 if (ex.error == MissingData || ex.error == FormatCannotRead) { 512 break; // no further data available or the data isn't valid PGF data (might occur in streaming or PPPExt) 513 } else { 514 throw; 515 } 516 } 517 } 518 #ifdef LIBPGF_USE_OPENMP 519 // decode in parallel 520 #pragma omp parallel for default(shared) //no declared exceptions in next block 521 #endif 522 for (int i=0; i < m_macroBlocksAvailable; i++) { 523 m_macroBlocks[i]->BitplaneDecode(); 524 } 525 526 // prepare current macro block 527 m_currentBlockIndex = 0; 528 m_currentBlock = m_macroBlocks[m_currentBlockIndex]; 529 } 530 }
void CDecoder::DecodeInterleaved (CWaveletTransform * wtChannel, int level, int quantParam)
Deccoding and dequantization of HL and LH subband (interleaved) using partitioning scheme. Partitioning scheme: The plane is partitioned in squares of side length InterBlockSize. It might throw an IOException.
- Parameters
wtChannel A wavelet transform channel containing the HL and HL band
level Wavelet transform level
quantParam Dequantization value
Definition at line 333 of file Decoder.cpp.
333 { 334 CSubband* hlBand = wtChannel->GetSubband(level, HL); 335 CSubband* lhBand = wtChannel->GetSubband(level, LH); 336 const div_t lhH = div(lhBand->GetHeight(), InterBlockSize); 337 const div_t hlW = div(hlBand->GetWidth(), InterBlockSize); 338 const int hlws = hlBand->GetWidth() - InterBlockSize; 339 const int hlwr = hlBand->GetWidth() - hlW.rem; 340 const int lhws = lhBand->GetWidth() - InterBlockSize; 341 const int lhwr = lhBand->GetWidth() - hlW.rem; 342 int hlPos, lhPos; 343 int hlBase = 0, lhBase = 0, hlBase2, lhBase2; 344 345 ASSERT(lhBand->GetWidth() >= hlBand->GetWidth()); 346 ASSERT(hlBand->GetHeight() >= lhBand->GetHeight()); 347 348 if (!hlBand->AllocMemory()) ReturnWithError(InsufficientMemory); 349 if (!lhBand->AllocMemory()) ReturnWithError(InsufficientMemory); 350 351 // correct quantParam with normalization factor 352 quantParam -= level; 353 if (quantParam < 0) quantParam = 0; 354 355 // main height 356 for (int i=0; i < lhH.quot; i++) { 357 // main width 358 hlBase2 = hlBase; 359 lhBase2 = lhBase; 360 for (int j=0; j < hlW.quot; j++) { 361 hlPos = hlBase2; 362 lhPos = lhBase2; 363 for (int y=0; y < InterBlockSize; y++) { 364 for (int x=0; x < InterBlockSize; x++) { 365 DequantizeValue(hlBand, hlPos, quantParam); 366 DequantizeValue(lhBand, lhPos, quantParam); 367 hlPos++; 368 lhPos++; 369 } 370 hlPos += hlws; 371 lhPos += lhws; 372 } 373 hlBase2 += InterBlockSize; 374 lhBase2 += InterBlockSize; 375 } 376 // rest of width 377 hlPos = hlBase2; 378 lhPos = lhBase2; 379 for (int y=0; y < InterBlockSize; y++) { 380 for (int x=0; x < hlW.rem; x++) { 381 DequantizeValue(hlBand, hlPos, quantParam); 382 DequantizeValue(lhBand, lhPos, quantParam); 383 hlPos++; 384 lhPos++; 385 } 386 // width difference between HL and LH 387 if (lhBand->GetWidth() > hlBand->GetWidth()) { 388 DequantizeValue(lhBand, lhPos, quantParam); 389 } 390 hlPos += hlwr; 391 lhPos += lhwr; 392 hlBase += hlBand->GetWidth(); 393 lhBase += lhBand->GetWidth(); 394 } 395 } 396 // main width 397 hlBase2 = hlBase; 398 lhBase2 = lhBase; 399 for (int j=0; j < hlW.quot; j++) { 400 // rest of height 401 hlPos = hlBase2; 402 lhPos = lhBase2; 403 for (int y=0; y < lhH.rem; y++) { 404 for (int x=0; x < InterBlockSize; x++) { 405 DequantizeValue(hlBand, hlPos, quantParam); 406 DequantizeValue(lhBand, lhPos, quantParam); 407 hlPos++; 408 lhPos++; 409 } 410 hlPos += hlws; 411 lhPos += lhws; 412 } 413 hlBase2 += InterBlockSize; 414 lhBase2 += InterBlockSize; 415 } 416 // rest of height 417 hlPos = hlBase2; 418 lhPos = lhBase2; 419 for (int y=0; y < lhH.rem; y++) { 420 // rest of width 421 for (int x=0; x < hlW.rem; x++) { 422 DequantizeValue(hlBand, hlPos, quantParam); 423 DequantizeValue(lhBand, lhPos, quantParam); 424 hlPos++; 425 lhPos++; 426 } 427 // width difference between HL and LH 428 if (lhBand->GetWidth() > hlBand->GetWidth()) { 429 DequantizeValue(lhBand, lhPos, quantParam); 430 } 431 hlPos += hlwr; 432 lhPos += lhwr; 433 hlBase += hlBand->GetWidth(); 434 } 435 // height difference between HL and LH 436 if (hlBand->GetHeight() > lhBand->GetHeight()) { 437 // total width 438 hlPos = hlBase; 439 for (int j=0; j < hlBand->GetWidth(); j++) { 440 DequantizeValue(hlBand, hlPos, quantParam); 441 hlPos++; 442 } 443 } 444 }
void CDecoder::DequantizeValue (CSubband * band, UINT32 bandPos, int quantParam)
Dequantization of a single value at given position in subband. It might throw an IOException.
- Parameters
band A subband
bandPos A valid position in subband band
quantParam The quantization parameter
Dequantization of a single value at given position in subband. If encoded data is available, then stores dequantized band value into buffer m_value at position m_valuePos. Otherwise reads encoded data block and decodes it. It might throw an IOException.
- Parameters
band A subband
bandPos A valid position in subband band
quantParam The quantization parameter
Definition at line 462 of file Decoder.cpp.
462 { 463 ASSERT(m_currentBlock); 464 465 if (m_currentBlock->IsCompletelyRead()) { 466 // all data of current macro block has been read --> prepare next macro block 467 GetNextMacroBlock(); 468 } 469 470 band->SetData(bandPos, m_currentBlock->m_value[m_currentBlock->m_valuePos] << quantParam); 471 m_currentBlock->m_valuePos++; 472 }
UINT32 CDecoder::GetEncodedHeaderLength () const [inline]
Returns the length of all encoded headers in bytes.
- Returns
The length of all encoded headers in bytes
Definition at line 136 of file Decoder.h.
136 { return m_encodedHeaderLength; }
void CDecoder::GetNextMacroBlock ()
Gets next macro block It might throw an IOException.
Definition at line 477 of file Decoder.cpp.
477 { 478 // current block has been read --> prepare next current block 479 m_macroBlocksAvailable--; 480 481 if (m_macroBlocksAvailable > 0) { 482 m_currentBlock = m_macroBlocks[++m_currentBlockIndex]; 483 } else { 484 DecodeBuffer(); 485 } 486 ASSERT(m_currentBlock); 487 }
CPGFStream * CDecoder::GetStream () [inline]
- Returns
Stream
Definition at line 174 of file Decoder.h.
174 { return m_stream; }
void CDecoder::Partition (CSubband * band, int quantParam, int width, int height, int startPos, int pitch)
Unpartitions a rectangular region of a given subband. Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize. Read wavelet coefficients from the output buffer of a macro block. It might throw an IOException.
- Parameters
band A subband
quantParam Dequantization value
width The width of the rectangle
height The height of the rectangle
startPos The relative subband position of the top left corner of the rectangular region
pitch The number of bytes in row of the subband
Definition at line 266 of file Decoder.cpp.
266 { 267 ASSERT(band); 268 269 const div_t ww = div(width, LinBlockSize); 270 const div_t hh = div(height, LinBlockSize); 271 const int ws = pitch - LinBlockSize; 272 const int wr = pitch - ww.rem; 273 int pos, base = startPos, base2; 274 275 // main height 276 for (int i=0; i < hh.quot; i++) { 277 // main width 278 base2 = base; 279 for (int j=0; j < ww.quot; j++) { 280 pos = base2; 281 for (int y=0; y < LinBlockSize; y++) { 282 for (int x=0; x < LinBlockSize; x++) { 283 DequantizeValue(band, pos, quantParam); 284 pos++; 285 } 286 pos += ws; 287 } 288 base2 += LinBlockSize; 289 } 290 // rest of width 291 pos = base2; 292 for (int y=0; y < LinBlockSize; y++) { 293 for (int x=0; x < ww.rem; x++) { 294 DequantizeValue(band, pos, quantParam); 295 pos++; 296 } 297 pos += wr; 298 base += pitch; 299 } 300 } 301 // main width 302 base2 = base; 303 for (int j=0; j < ww.quot; j++) { 304 // rest of height 305 pos = base2; 306 for (int y=0; y < hh.rem; y++) { 307 for (int x=0; x < LinBlockSize; x++) { 308 DequantizeValue(band, pos, quantParam); 309 pos++; 310 } 311 pos += ws; 312 } 313 base2 += LinBlockSize; 314 } 315 // rest of height 316 pos = base2; 317 for (int y=0; y < hh.rem; y++) { 318 // rest of width 319 for (int x=0; x < ww.rem; x++) { 320 DequantizeValue(band, pos, quantParam); 321 pos++; 322 } 323 pos += wr; 324 } 325 }
UINT32 CDecoder::ReadEncodedData (UINT8 * target, UINT32 len) const
Copies data from the open stream to a target buffer. It might throw an IOException.
- Parameters
target The target buffer
len The number of bytes to read- Returns
The number of bytes copied to the target buffer
Definition at line 246 of file Decoder.cpp.
246 { 247 ASSERT(m_stream); 248 249 int count = len; 250 m_stream->Read(&count, target); 251 252 return count; 253 }
void CDecoder::ReadMacroBlock (CMacroBlock * block) [private]
throws IOException
Definition at line 535 of file Decoder.cpp.
535 { 536 ASSERT(block); 537 538 UINT16 wordLen; 539 ROIBlockHeader h(BufferSize); 540 int count, expected; 541 542 #ifdef TRACE 543 //UINT32 filePos = (UINT32)m_stream->GetPos(); 544 //printf("DecodeBuffer: %d\n", filePos); 545 #endif 546 547 // read wordLen 548 count = expected = sizeof(UINT16); 549 m_stream->Read(&count, &wordLen); 550 if (count != expected) ReturnWithError(MissingData); 551 wordLen = __VAL(wordLen); // convert wordLen 552 if (wordLen > BufferSize) ReturnWithError(FormatCannotRead); 553 554 #ifdef __PGFROISUPPORT__ 555 // read ROIBlockHeader 556 if (m_roi) { 557 count = expected = sizeof(ROIBlockHeader); 558 m_stream->Read(&count, &h.val); 559 if (count != expected) ReturnWithError(MissingData); 560 h.val = __VAL(h.val); // convert ROIBlockHeader 561 } 562 #endif 563 // save header 564 block->m_header = h; 565 566 // read data 567 count = expected = wordLen*WordBytes; 568 m_stream->Read(&count, block->m_codeBuffer); 569 if (count != expected) ReturnWithError(MissingData); 570 571 #ifdef PGF_USE_BIG_ENDIAN 572 // convert data 573 count /= WordBytes; 574 for (int i=0; i < count; i++) { 575 block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]); 576 } 577 #endif 578 579 #ifdef __PGFROISUPPORT__ 580 ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize); 581 #else 582 ASSERT(h.rbh.bufferSize == BufferSize); 583 #endif 584 }
void CDecoder::SetStreamPosToData () [inline]
Resets stream position to beginning of data block.
Definition at line 144 of file Decoder.h.
144 { ASSERT(m_stream); m_stream->SetPos(FSFromStart, m_startPos + m_encodedHeaderLength); }
void CDecoder::SetStreamPosToStart () [inline]
Resets stream position to beginning of PGF pre-header.
Definition at line 140 of file Decoder.h.
140 { ASSERT(m_stream); m_stream->SetPos(FSFromStart, m_startPos); }
void CDecoder::Skip (UINT64 offset)
Skips a given number of bytes in the open stream. It might throw an IOException.
Definition at line 449 of file Decoder.cpp.
449 { 450 m_stream->SetPos(FSFromCurrent, offset); 451 }
Member Data Documentation
CMacroBlock* CDecoder::m_currentBlock [private]
current macro block (used by main thread)
Definition at line 209 of file Decoder.h.
int CDecoder::m_currentBlockIndex [private]
index of current macro block
Definition at line 206 of file Decoder.h.
UINT32 CDecoder::m_encodedHeaderLength [private]
stream offset from startPos to the beginning of the data part (highest level)
Definition at line 203 of file Decoder.h.
int CDecoder::m_macroBlockLen [private]
array length
Definition at line 207 of file Decoder.h.
CMacroBlock** CDecoder::m_macroBlocks [private]
array of macroblocks
Definition at line 205 of file Decoder.h.
int CDecoder::m_macroBlocksAvailable [private]
number of decoded macro blocks (including currently used macro block)
Definition at line 208 of file Decoder.h.
UINT64 CDecoder::m_startPos [private]
stream position at the beginning of the PGF pre-header
Definition at line 201 of file Decoder.h.
CPGFStream* CDecoder::m_stream [private]
input PGF stream
Definition at line 200 of file Decoder.h.
UINT64 CDecoder::m_streamSizeEstimation [private]
estimation of stream size
Definition at line 202 of file Decoder.h.
Author
Generated automatically by Doxygen for libpgf from the source code.