CDecoder::CMacroBlock(3)

πŸ“¦
version 7.21.7 Β· 4 versions
, in fedora 43

✨ NAME ✨

CDecoder::CMacroBlock β€” bestie, a macro block is a decoding unit of fixed size (uncoded). That's the whole vibe. πŸ¦‹

(oh and fyi, this page lives in the libpgf manual, section 3 β€” part 1 of 3, so don't go anywhere πŸ’…)


🌈 SYNOPSIS 🌈

πŸ’– Public Member Functions

  • CMacroBlock () β€” Constructor: initializes a new macro block, fresh out the wrapper ✨
  • bool IsCompletelyRead () const β€” tells you if she's completely read
  • void BitplaneDecode () β€” decodes the bitplane

πŸŽ€ Public Attributes

  • ROIBlockHeader m_header β€” block header
  • DataT m_value [BufferSize] β€” output buffer of values with index m_valuePos
  • UINT32 m_codeBuffer [CodeBufferLen] β€” input buffer for encoded bitstream
  • UINT32 m_valuePos β€” current position in m_value

πŸ’… Private Member Functions

  • UINT32 ComposeBitplane (UINT32 bufferSize, DataT planeMask, UINT32 *sigBits, UINT32 *refBits, UINT32 *signBits)
  • UINT32 ComposeBitplaneRLD (UINT32 bufferSize, DataT planeMask, UINT32 sigPos, UINT32 *refBits)
  • UINT32 ComposeBitplaneRLD (UINT32 bufferSize, DataT planeMask, UINT32 *sigBits, UINT32 *refBits, UINT32 signPos)
  • void SetBitAtPos (UINT32 pos, DataT planeMask)
  • void SetSign (UINT32 pos, bool sign)

🫢 Private Attributes

  • bool m_sigFlagVector [BufferSize+1]

🌸 Detailed Description 🌸

A macro block is a decoding unit of fixed size (uncoded). Periodt.

PGF decoder macro block class. πŸ‘‘

Author β€” C. Stamm, I. Bauersachs

Definition at line 51 of file Decoder.h.


πŸ›  Constructor & Destructor Documentation πŸ› 

CDecoder::CMacroBlock::CMacroBlock () [inline]

Constructor: initializes a new macro block. She's brand new here, be nice to her πŸ₯Ί

Definition at line 55 of file Decoder.h.

56                 : m_header(0)                                                           // makes sure that IsCompletelyRead() returns true for an empty macro block
57 #pragma warning( suppress : 4351 )
58                 , m_value()
59                 , m_codeBuffer()
60                 , m_valuePos(0)
61                 , m_sigFlagVector()
62                 {
63                 }

🧚 Member Function Documentation 🧚

void CDecoder::CMacroBlock::BitplaneDecode ()

Okay so this one decodes input data that's already been read into this macro block. And here's the cute part β€” several macro blocks can be decoded in parallel, no cap πŸƒβ€β™€οΈπŸƒβ€β™€οΈπŸƒβ€β™€οΈ. But bestie, promise me: call CDecoder::ReadMacroBlock before this method. Order matters, iykyk.

Definition at line 650 of file Decoder.cpp.

650                                          {
651         UINT32 bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize);
652
653         // clear significance vector
654         for (UINT32 k=0; k < bufferSize; k++) {
655                 m_sigFlagVector[k] = false;
656         }
657         m_sigFlagVector[bufferSize] = true; // sentinel
658
659         // clear output buffer
660         for (UINT32 k=0; k < BufferSize; k++) {
661                 m_value[k] = 0;
662         }
663
664         // read number of bit planes
665         // <nPlanes>
666         UINT32 nPlanes = GetValueBlock(m_codeBuffer, 0, MaxBitPlanesLog);
667         UINT32 codePos = MaxBitPlanesLog;
668
669         // loop through all bit planes
670         if (nPlanes == 0) nPlanes = MaxBitPlanes + 1;
671         ASSERT(0 < nPlanes && nPlanes <= MaxBitPlanes + 1);
672         DataT planeMask = 1 << (nPlanes - 1);
673
674         for (int plane = nPlanes - 1; plane >= 0; plane--) {
675                 UINT32 sigLen = 0;
676
677                 // read RL code
678                 if (GetBit(m_codeBuffer, codePos)) {
679                         // RL coding of sigBits is used
680                         // <1><codeLen><codedSigAndSignBits>_<refBits>
681                         codePos++;
682
683                         // read codeLen
684                         UINT32 codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(codeLen <= MaxCodeLen);
685
686                         // position of encoded sigBits and signBits
687                         UINT32 sigPos = codePos + RLblockSizeLen; ASSERT(sigPos < CodeBufferBitLen);
688
689                         // refinement bits
690                         codePos = AlignWordPos(sigPos + codeLen); ASSERT(codePos < CodeBufferBitLen);
691
692                         // run-length decode significant bits and signs from m_codeBuffer and
693                         // read refinement bits from m_codeBuffer and compose bit plane
694                         sigLen = ComposeBitplaneRLD(bufferSize, planeMask, sigPos, &m_codeBuffer[codePos >> WordWidthLog]);
695
696                 } else {
697                         // no RL coding is used for sigBits and signBits together
698                         // <0><sigLen>
699                         codePos++;
700
701                         // read sigLen
702                         sigLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(sigLen <= MaxCodeLen);
703                         codePos += RLblockSizeLen; ASSERT(codePos < CodeBufferBitLen);
704
705                         // read RL code for signBits
706                         if (GetBit(m_codeBuffer, codePos)) {
707                                 // RL coding is used just for signBits
708                                 // <1><codeLen><codedSignBits>_<sigBits>_<refBits>
709                                 codePos++;
710
711                                 // read codeLen
712                                 UINT32 codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(codeLen <= MaxCodeLen);
713
714                                 // sign bits
715                                 UINT32 signPos = codePos + RLblockSizeLen; ASSERT(signPos < CodeBufferBitLen);
716
717                                 // significant bits
718                                 UINT32 sigPos = AlignWordPos(signPos + codeLen); ASSERT(sigPos < CodeBufferBitLen);
719
720                                 // refinement bits
721                                 codePos = AlignWordPos(sigPos + sigLen); ASSERT(codePos < CodeBufferBitLen);
722
723                                 // read significant and refinement bitset from m_codeBuffer
724                                 sigLen = ComposeBitplaneRLD(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], signPos);
725
726                         } else {
727                                 // RL coding of signBits was not efficient and therefore not used
728                                 // <0><signLen>_<signBits>_<sigBits>_<refBits>
729                                 codePos++;
730
731                                 // read signLen
732                                 UINT32 signLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(signLen <= MaxCodeLen);
733
734                                 // sign bits
735                                 UINT32 signPos = AlignWordPos(codePos + RLblockSizeLen); ASSERT(signPos < CodeBufferBitLen);
736
737                                 // significant bits
738                                 UINT32 sigPos = AlignWordPos(signPos + signLen); ASSERT(sigPos < CodeBufferBitLen);
739
740                                 // refinement bits
741                                 codePos = AlignWordPos(sigPos + sigLen); ASSERT(codePos < CodeBufferBitLen);
742
743                                 // read significant and refinement bitset from m_codeBuffer
744                                 sigLen = ComposeBitplane(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], &m_codeBuffer[signPos >> WordWidthLog]);
745                         }
746                 }
747
748                 // start of next chunk
749                 codePos = AlignWordPos(codePos + bufferSize - sigLen); ASSERT(codePos < CodeBufferBitLen);
750
751                 // next plane
752                 planeMask >>= 1;
753         }
754
755         m_valuePos = 0;
756 }

UINT32 CDecoder::CMacroBlock::ComposeBitplane (UINT32 bufferSize, DataT planeMask, UINT32 * sigBits, UINT32 * refBits, UINT32 * signBits) [private]

Definition at line 763 of file Decoder.cpp.

763                                                                                                                                   {
764         ASSERT(sigBits);
765         ASSERT(refBits);
766         ASSERT(signBits);
767
768         UINT32 valPos = 0, signPos = 0, refPos = 0, sigPos = 0;
769
770         while (valPos < bufferSize) {
771                 // search next 1 in m_sigFlagVector using searching with sentinel
772                 UINT32 sigEnd = valPos;
773                 while(!m_sigFlagVector[sigEnd]) { sigEnd++; }
774                 sigEnd -= valPos;
775                 sigEnd += sigPos;
776
777                 // search 1's in sigBits[sigPos..sigEnd)
778                 // these 1's are significant bits
779                 while (sigPos < sigEnd) {
780                         // search 0's
781                         UINT32 zerocnt = SeekBitRange(sigBits, sigPos, sigEnd - sigPos);
782                         sigPos += zerocnt;
783                         valPos += zerocnt;
784                         if (sigPos < sigEnd) {
785                                 // write bit to m_value
786                                 SetBitAtPos(valPos, planeMask);
787
788                                 // copy sign bit
789                                 SetSign(valPos, GetBit(signBits, signPos++));
790
791                                 // update significance flag vector
792                                 m_sigFlagVector[valPos++] = true;
793                                 sigPos++;
794                         }
795                 }
796                 // refinement bit
797                 if (valPos < bufferSize) {
798                         // write one refinement bit
799                         if (GetBit(refBits, refPos)) {
800                                 SetBitAtPos(valPos, planeMask);
801                         }
802                         refPos++;
803                         valPos++;
804                 }
805         }
806         ASSERT(sigPos <= bufferSize);
807         ASSERT(refPos <= bufferSize);
808         ASSERT(signPos <= bufferSize);
809         ASSERT(valPos == bufferSize);
810
811         return sigPos;
812 }

UINT32 CDecoder::CMacroBlock::ComposeBitplaneRLD (UINT32 bufferSize, DataT planeMask, UINT32 * sigBits, UINT32 * refBits, UINT32 signPos) [private]

okay so we're back in the code mines β›οΈβœ¨ and ngl this stretch is just straight-up source, no prose, no mercy. Here's the body that belongs to the signature we just saw β€” Definition at line 927 of file Decoder.cpp, and it's giving iconic:

927     {
928         ASSERT(sigBits);
929         ASSERT(refBits);
930
931         UINT32 valPos = 0, refPos = 0;
932         UINT32 sigPos = 0, sigEnd;
933         UINT32 zerocnt, count = 0;
934         UINT32 k = 0;
935         UINT32 runlen = 1 << k; // = 2^k
936         bool signBit = false;
937         bool zeroAfterRun = false;
938
939         while (valPos < bufferSize) {
940             // search next 1 in m_sigFlagVector using searching with sentinel
941             sigEnd = valPos;
942             while(!m_sigFlagVector[sigEnd]) { sigEnd++; }
943             sigEnd -= valPos;
944             sigEnd += sigPos;
945
946             // search 1's in sigBits[sigPos..sigEnd)
947             // these 1's are significant bits
948             while (sigPos < sigEnd) {
949                 // search 0's
950                 zerocnt = SeekBitRange(sigBits, sigPos, sigEnd - sigPos);
951                 sigPos += zerocnt;
952                 valPos += zerocnt;
953                 if (sigPos < sigEnd) {
954                     // write bit to m_value
955                     SetBitAtPos(valPos, planeMask);
956
957                     // check sign bit
958                     if (count == 0) {
959                         // all 1's have been set
960                         if (zeroAfterRun) {
961                             // finish the run with a 0
962                             signBit = false;
963                             zeroAfterRun = false;
964                         } else {
965                             // decode next sign bit
966                             if (GetBit(m_codeBuffer, signPos++)) {
967                                 // generate 1's run of length 2^k
968                                 count = runlen - 1;
969                                 signBit = true;
970
971                                 // adapt k (double run-length interval)
972                                 if (k < WordWidth) {
973                                     k++;
974                                     runlen <<= 1;
975                                 }
976                             } else {
977                                 // extract counter and generate 1's run of length count
978                                 if (k > 0) {
979                                     // extract counter
980                                     count = GetValueBlock(m_codeBuffer, signPos, k);
981                                     signPos += k;
982
983                                     // adapt k (half run-length interval)
984                                     k--;
985                                     runlen >>= 1;
986                                 }
987                                 if (count > 0) {
988                                     count--;
989                                     signBit = true;
990                                     zeroAfterRun = true;
991                                 } else {
992                                     signBit = false;
993                                 }
994                             }
995                         }
996                     } else {
997                         ASSERT(count > 0);
998                         ASSERT(signBit);
999                         count--;
1000                    }
1001
1002                    // copy sign bit
1003                    SetSign(valPos, signBit);
1004
1005                    // update significance flag vector
1006                    m_sigFlagVector[valPos++] = true;
1007                    sigPos++;
1008                }
1009            }
1010
1011            // refinement bit
1012            if (valPos < bufferSize) {
1013                // write one refinement bit
1014                if (GetBit(refBits, refPos)) {
1015                    SetBitAtPos(valPos, planeMask);
1016                }
1017                refPos++;
1018                valPos++;
1019            }
1020        }
1021        ASSERT(sigPos <= bufferSize);
1022        ASSERT(refPos <= bufferSize);
1023        ASSERT(valPos == bufferSize);
1024
1025        return sigPos;
1026    }

πŸ¦‹ CDecoder::CMacroBlock::ComposeBitplaneRLD πŸ¦‹

UINT32 CDecoder::CMacroBlock::ComposeBitplaneRLD (UINT32 bufferSize, DataT planeMask, UINT32 sigPos, UINT32 * refBits) [private]

Definition at line 824 of file Decoder.cpp.

okay so before anyone comes for me: yes, the parameter is literally named sigPos and then line 828 goes and declares UINT32 sigPos = 0, sigEnd; anyway. Not my business, not my problem πŸ’… I am only the messenger, and the messenger copies it character for character.
824     {
825         ASSERT(refBits);
826
827         UINT32 valPos = 0, refPos = 0;
828         UINT32 sigPos = 0, sigEnd;
829         UINT32 k = 3;
830         UINT32 runlen = 1 << k; // = 2^k
831         UINT32 count = 0, rest = 0;
832         bool set1 = false;
833
834         while (valPos < bufferSize) {
835             // search next 1 in m_sigFlagVector using searching with sentinel
836             sigEnd = valPos;
837             while(!m_sigFlagVector[sigEnd]) { sigEnd++; }
838             sigEnd -= valPos;
839             sigEnd += sigPos;
840
841             while (sigPos < sigEnd) {
842                 if (rest || set1) {
843                     // rest of last run
844                     sigPos += rest;
845                     valPos += rest;
846                     rest = 0;
847                 } else {
848                     // decode significant bits
849                     if (GetBit(m_codeBuffer, codePos++)) {
850                         // extract counter and generate zero run of length count
851                         if (k > 0) {
852                             // extract counter
853                             count = GetValueBlock(m_codeBuffer, codePos, k);
854                             codePos += k;
855                             if (count > 0) {
856                                 sigPos += count;
857                                 valPos += count;
858                             }
859
860                             // adapt k (half run-length interval)
861                             k--;
862                             runlen >>= 1;
863                         }
864
865                         set1 = true;
866
867                     } else {
868                         // generate zero run of length 2^k
869                         sigPos += runlen;
870                         valPos += runlen;
871
872                         // adapt k (double run-length interval)
873                         if (k < WordWidth) {
874                             k++;
875                             runlen <<= 1;
876                         }
877                     }
878                 }
879
880                 if (sigPos < sigEnd) {
881                     if (set1) {
882                         set1 = false;
883
884                         // write 1 bit
885                         SetBitAtPos(valPos, planeMask);
886
887                         // set sign bit
888                         SetSign(valPos, GetBit(m_codeBuffer, codePos++));
889
890                         // update significance flag vector
891                         m_sigFlagVector[valPos++] = true;
892                         sigPos++;
893                     }
894                 } else {
895                     rest = sigPos - sigEnd;
896                     sigPos = sigEnd;
897                     valPos -= rest;
898                 }
899
900             }
901
902             // refinement bit
903             if (valPos < bufferSize) {
904                 // write one refinement bit
905                 if (GetBit(refBits, refPos)) {
906                     SetBitAtPos(valPos, planeMask);
907                 }
908                 refPos++;
909                 valPos++;
910             }
911         }
912         ASSERT(sigPos <= bufferSize);
913         ASSERT(refPos <= bufferSize);
914         ASSERT(valPos == bufferSize);
915
916         return sigPos;
917     }

✨ bool CDecoder::CMacroBlock::IsCompletelyRead () const [inline] ✨

Returns true if this macro block has been completely read. slay β€” a yes/no queen, we love a one-liner that knows what it wants 🫢

Returns

true if current value position is at block end

Definition at line 68 of file Decoder.h.

68 { return m_valuePos >= m_header.rbh.bufferSize; }

πŸ’– void CDecoder::CMacroBlock::SetBitAtPos (UINT32 pos, DataT planeMask) [inline], [private] πŸ’–

Definition at line 85 of file Decoder.h.

85 { (m_value[pos] >= 0) ? m_value[pos] |= planeMask : m_value[pos] -= planeMask; }

and bestie we are not even close to done β€” keep scrolling, the code said "there's more" and it meant it πŸ‘€πŸ’œ

So the very last private lil' helper in the member-function lineup is this one, and honestly? It's giving tiny but mighty. πŸ’…

SetSign (the inline private one, iykyk)

void CDecoder::CMacroBlock::SetSign (UINT32 pos, bool sign) [inline],
    [private]

Bestie, this one lives at Definition at line 86 of file Decoder.h. and it's literally a one-liner, no cap:

86 { m_value[pos] = -m_value[pos]*sign + m_value[pos]*(!sign); }
It's inline and private, so it's not out here for public consumption β€” it's a backstage pass situation only. πŸŽ€

✨ Member Data Documentation ✨

Okay so now we get to the actual data, the members, the little variables holding the whole vibe together. Let's go one by one, no skipping, periodt. πŸ’–

  • UINT32 CDecoder::CMacroBlock::m_codeBuffer[CodeBufferLen] β€” the input buffer for encoded bitstream. That's where the encoded bits roll up before anything else happens.
Definition at line 78 of file Decoder.h.
  • ROIBlockHeader CDecoder::CMacroBlock::m_header β€” the block header. Just the header, doing header things, main character energy. πŸ‘‘
Definition at line 76 of file Decoder.h.
  • bool CDecoder::CMacroBlock::m_sigFlagVector[BufferSize+1] [private] β€” she's a private girlie, so we don't get a description, we just get to know she's there. πŸ™ˆ
Definition at line 88 of file Decoder.h.
  • DataT CDecoder::CMacroBlock::m_value[BufferSize] β€” the output buffer of values with index m_valuePos. So like, the values come out here, and m_valuePos is the lil' pointer telling you where you're at. 🌸
Definition at line 77 of file Decoder.h.
  • UINT32 CDecoder::CMacroBlock::m_valuePos β€” the current position in m_value. The GPS of the value buffer fr fr. 🧭
Definition at line 79 of file Decoder.h.

πŸ¦‹ Author πŸ¦‹

Generated automatically by Doxygen for libpgf from the source code.

(So like, no human wrote this, a robot did, and honestly? The robot ate. πŸ’€βœ¨)


And that's a wrap on CDecoder::CMacroBlock(3), bestie!! 🫢 This was Version 7.21.2, dated Thu Jul 24 2025 00:00:00 β€” shoutout to that timestamp for being so satisfyingly round, we love a clean footer. Thanks for reading all the way to the end, you're the real MVP of the manpage marathon. πŸ†πŸ’œ Now go forth and decode, my love. ⭐

πŸ“¦ where this page comes from