CDecoder(3)

NAME
CDecoder - 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.