Commit 7d62e7ca authored by David Flynn's avatar David Flynn
Browse files

m42522/geometry: code occupancy using a binary arithmetic codec

This commit provides an implementation of m42522 to code occupancy
using a binary context model rather than a 255-ary model.  A total of
581 binary contexts are used compared to the previous 10 255-ary
contexts.
parent 3f0aceb1
......@@ -35,6 +35,8 @@
#ifndef PCCTMC3Common_h
#define PCCTMC3Common_h
#include "ArithmeticCodec.h"
#include "PCCKdTree.h"
#include "PCCMath.h"
#include "ringbuf.h"
......@@ -358,6 +360,39 @@ isDirectModeEligible(
//---------------------------------------------------------------------------
struct CtxModelOctreeOccupancy {
o3dgc::Adaptive_Bit_Model b0[10];
o3dgc::Adaptive_Bit_Model b1[2 * 10];
o3dgc::Adaptive_Bit_Model b2[4 * 10];
o3dgc::Adaptive_Bit_Model b3[8 * 10];
o3dgc::Adaptive_Bit_Model b4[75];
o3dgc::Adaptive_Bit_Model b5[112];
o3dgc::Adaptive_Bit_Model b6[117];
o3dgc::Adaptive_Bit_Model b7[127];
CtxModelOctreeOccupancy()
{
for (auto& ctx : b0)
ctx.reset(true);
for (auto& ctx : b1)
ctx.reset(true);
for (auto& ctx : b2)
ctx.reset(true);
for (auto& ctx : b3)
ctx.reset(true);
for (auto& ctx : b4)
ctx.reset(true);
for (auto& ctx : b5)
ctx.reset(true);
for (auto& ctx : b6)
ctx.reset(true);
for (auto& ctx : b7)
ctx.reset(true);
}
};
//---------------------------------------------------------------------------
} // namespace pcc
#endif /* PCCTMC3Common_h */
......@@ -358,6 +358,122 @@ private:
return occupancy;
}
//---------------------------------------------------------------------------
// decode occupancy bits (neighPattern10 == 0 case)
int decodeOccupancyNeighZ(
o3dgc::Arithmetic_Codec* arithmeticDecoder,
CtxModelOctreeOccupancy& ctxOccupancy)
{
int numOccupiedAcc = 0;
int bit;
int occupancy = 0;
bit = arithmeticDecoder->decode(ctxOccupancy.b0[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 1;
bit = arithmeticDecoder->decode(ctxOccupancy.b1[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 7;
bit = arithmeticDecoder->decode(ctxOccupancy.b2[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 5;
bit = arithmeticDecoder->decode(ctxOccupancy.b3[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 3;
bit = arithmeticDecoder->decode(ctxOccupancy.b4[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 2;
bit = arithmeticDecoder->decode(ctxOccupancy.b5[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 4;
// NB: There must be at least two occupied child nodes
// -- avoid coding the occupancyB if it is implied.
bit = 1;
if (numOccupiedAcc >= 1)
bit = arithmeticDecoder->decode(ctxOccupancy.b6[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 6;
bit = 1;
if (numOccupiedAcc >= 2)
bit = arithmeticDecoder->decode(ctxOccupancy.b7[numOccupiedAcc]);
occupancy |= bit << 0;
return occupancy;
}
//---------------------------------------------------------------------------
// decode occupancy bits (neighPattern10 != 0 case)
int decodeOccupancyNeighNZ(
o3dgc::Arithmetic_Codec* arithmeticDecoder,
CtxModelOctreeOccupancy& ctxOccupancy,
int neighPattern10)
{
int occupancy = 0;
int partialOccupancy = 0;
int idx;
int bit;
idx = neighPattern10;
bit = arithmeticDecoder->decode(ctxOccupancy.b0[idx]);
partialOccupancy |= bit << 0;
occupancy |= bit << 1;
idx = (neighPattern10 << 1) + partialOccupancy;
bit = arithmeticDecoder->decode(ctxOccupancy.b1[idx]);
partialOccupancy |= bit << 1;
occupancy |= bit << 7;
idx = (neighPattern10 << 2) + partialOccupancy;
bit = arithmeticDecoder->decode(ctxOccupancy.b2[idx]);
partialOccupancy |= bit << 2;
occupancy |= bit << 5;
idx = (neighPattern10 << 3) + partialOccupancy;
bit = arithmeticDecoder->decode(ctxOccupancy.b3[idx]);
partialOccupancy |= bit << 3;
occupancy |= bit << 3;
// todo(df): merge constants into lut.
idx = ((neighPattern10 - 1) << 4) + partialOccupancy;
idx = kOccMapBit4CtxIdx[idx] - 1 + 5;
bit = arithmeticDecoder->decode(ctxOccupancy.b4[idx]);
partialOccupancy |= bit << 4;
occupancy |= bit << 2;
idx = ((neighPattern10 - 1) << 5) + partialOccupancy;
idx = kOccMapBit5CtxIdx[idx] - 1 + 6;
bit = arithmeticDecoder->decode(ctxOccupancy.b5[idx]);
partialOccupancy |= bit << 5;
occupancy |= bit << 4;
int neighPattern7 = kNeighPattern10to7[neighPattern10];
idx = ((neighPattern7 - 1) << 6) + partialOccupancy;
idx = kOccMapBit6CtxIdx[idx] - 1 + 7;
bit = arithmeticDecoder->decode(ctxOccupancy.b6[idx]);
partialOccupancy += bit << 6;
occupancy |= bit << 6;
int neighPattern5 = kNeighPattern7to5[neighPattern7];
idx = ((neighPattern5 - 1) << 7) + partialOccupancy;
idx = kOccMapBit7CtxIdx[idx] - 1 + 8;
// NB: if firt 7 bits are 0, then the last is implicitly 1.
bit = 1;
if (partialOccupancy)
bit = arithmeticDecoder->decode(ctxOccupancy.b7[idx]);
occupancy |= bit << 0;
return occupancy;
}
//-------------------------------------------------------------------------
// decode node occupancy bits
//
......@@ -366,11 +482,12 @@ private:
o3dgc::Arithmetic_Codec* arithmeticDecoder,
o3dgc::Adaptive_Bit_Model& ctxSingleChild,
o3dgc::Static_Bit_Model& ctxEquiProb,
o3dgc::Adaptive_Data_Model (&ctxOccupancy)[10],
CtxModelOctreeOccupancy& ctxOccupancy,
const PCCOctree3Node& node0)
{
if (!neighbourContextsEnabled) {
return arithmeticDecoder->decode(ctxOccupancy[0]);
assert(0); // todo(df): fixme -- we need an old context for this.
//return arithmeticDecoder->decode(ctxOccupancy[0]);
}
// neighbouring configuration with reduction from 64 to 10
......@@ -387,13 +504,14 @@ private:
cnt |= arithmeticDecoder->decode(ctxEquiProb) << 2;
occupancy = 1 << cnt;
} else {
occupancy = arithmeticDecoder->decode(ctxOccupancy[0]);
occupancy = decodeOccupancyNeighZ(arithmeticDecoder, ctxOccupancy);
}
} else {
occupancy = arithmeticDecoder->decode(ctxOccupancy[neighPattern10]);
occupancy = decodeOccupancyNeighNZ(
arithmeticDecoder, ctxOccupancy, neighPattern10);
occupancy = mapGeometryOccupancyInv(occupancy, neighPattern);
}
return occupancy;
}
......@@ -471,14 +589,7 @@ private:
o3dgc::Adaptive_Bit_Model ctxPointCountPerBlock;
o3dgc::Adaptive_Bit_Model ctxBlockSkipTh;
o3dgc::Adaptive_Bit_Model ctxNumIdcmPointsEq1;
// pattern model using ten 6-neighbour configurations
o3dgc::Adaptive_Data_Model ctxOccupancy[10];
for (int i = 0; i < 10; i++) {
ctxOccupancy[i].set_alphabet(256);
if (neighbourContextsEnabled)
ctxOccupancy[i].reset(kInitCtxOccupancy + 256 * i, true);
}
CtxModelOctreeOccupancy ctxOccupancy;
// init main fifo
// -- worst case size is the last level containing every input poit
......
......@@ -353,19 +353,129 @@ private:
}
//-------------------------------------------------------------------------
// enecode a node's occupancy bits
// encode occupancy bits (neighPattern10 == 0 case)
void encodeOccupancyNeighZ(
o3dgc::Arithmetic_Codec* arithmeticEncoder,
CtxModelOctreeOccupancy& ctxOccupancy,
int mappedOccupancy)
{
int occupancyB0 = !!(mappedOccupancy & 2);
int occupancyB1 = !!(mappedOccupancy & 128);
int occupancyB2 = !!(mappedOccupancy & 32);
int occupancyB3 = !!(mappedOccupancy & 8);
int occupancyB4 = !!(mappedOccupancy & 4);
int occupancyB5 = !!(mappedOccupancy & 16);
int occupancyB6 = !!(mappedOccupancy & 64);
int occupancyB7 = !!(mappedOccupancy & 1);
int numOccupiedAcc = 0;
arithmeticEncoder->encode(occupancyB0, ctxOccupancy.b0[numOccupiedAcc]);
numOccupiedAcc += occupancyB0;
arithmeticEncoder->encode(occupancyB1, ctxOccupancy.b1[numOccupiedAcc]);
numOccupiedAcc += occupancyB1;
arithmeticEncoder->encode(occupancyB2, ctxOccupancy.b2[numOccupiedAcc]);
numOccupiedAcc += occupancyB2;
arithmeticEncoder->encode(occupancyB3, ctxOccupancy.b3[numOccupiedAcc]);
numOccupiedAcc += occupancyB3;
arithmeticEncoder->encode(occupancyB4, ctxOccupancy.b4[numOccupiedAcc]);
numOccupiedAcc += occupancyB4;
arithmeticEncoder->encode(occupancyB5, ctxOccupancy.b5[numOccupiedAcc]);
numOccupiedAcc += occupancyB5;
// NB: There must be at least two occupied child nodes
// -- avoid coding the occupancyB if it is implied.
if (numOccupiedAcc >= 1)
arithmeticEncoder->encode(occupancyB6, ctxOccupancy.b6[numOccupiedAcc]);
numOccupiedAcc += occupancyB6;
if (numOccupiedAcc >= 2)
arithmeticEncoder->encode(occupancyB7, ctxOccupancy.b7[numOccupiedAcc]);
}
//-------------------------------------------------------------------------
// encode occupancy bits (neighPattern10 != 0 case)
void encodeOccupancyNeighNZ(
o3dgc::Arithmetic_Codec* arithmeticEncoder,
CtxModelOctreeOccupancy& ctxOccupancy,
int mappedOccupancy,
int neighPattern10)
{
int occupancyB0 = !!(mappedOccupancy & 2);
int occupancyB1 = !!(mappedOccupancy & 128);
int occupancyB2 = !!(mappedOccupancy & 32);
int occupancyB3 = !!(mappedOccupancy & 8);
int occupancyB4 = !!(mappedOccupancy & 4);
int occupancyB5 = !!(mappedOccupancy & 16);
int occupancyB6 = !!(mappedOccupancy & 64);
int occupancyB7 = !!(mappedOccupancy & 1);
uint32_t partialOccupancy = 0;
int idx;
idx = neighPattern10;
arithmeticEncoder->encode(occupancyB0, ctxOccupancy.b0[idx]);
partialOccupancy |= occupancyB0;
idx = (neighPattern10 << 1) + partialOccupancy;
arithmeticEncoder->encode(occupancyB1, ctxOccupancy.b1[idx]);
partialOccupancy |= occupancyB1 << 1;
idx = (neighPattern10 << 2) + partialOccupancy;
arithmeticEncoder->encode(occupancyB2, ctxOccupancy.b2[idx]);
partialOccupancy |= occupancyB2 << 2;
idx = (neighPattern10 << 3) + partialOccupancy;
arithmeticEncoder->encode(occupancyB3, ctxOccupancy.b3[idx]);
partialOccupancy |= occupancyB3 << 3;
// todo(df): merge constants into lut.
idx = ((neighPattern10 - 1) << 4) + partialOccupancy;
idx = kOccMapBit4CtxIdx[idx] - 1 + 5;
arithmeticEncoder->encode(occupancyB4, ctxOccupancy.b4[idx]);
partialOccupancy |= occupancyB4 << 4;
idx = ((neighPattern10 - 1) << 5) + partialOccupancy;
idx = kOccMapBit5CtxIdx[idx] - 1 + 6;
arithmeticEncoder->encode(occupancyB5, ctxOccupancy.b5[idx]);
partialOccupancy |= occupancyB5 << 5;
int neighPattern7 = kNeighPattern10to7[neighPattern10];
idx = ((neighPattern7 - 1) << 6) + partialOccupancy;
idx = kOccMapBit6CtxIdx[idx] - 1 + 7;
arithmeticEncoder->encode(occupancyB6, ctxOccupancy.b6[idx]);
partialOccupancy |= occupancyB6 << 6;
int neighPattern5 = kNeighPattern7to5[neighPattern7];
idx = ((neighPattern5 - 1) << 7) + partialOccupancy;
idx = kOccMapBit7CtxIdx[idx] - 1 + 8;
// NB: if firt 7 bits are 0, then the last is implicitly 1.
if (partialOccupancy)
arithmeticEncoder->encode(occupancyB7, ctxOccupancy.b7[idx]);
}
//-------------------------------------------------------------------------
// decode node occupancy bits
//
void encodeGeometryOccupancy(
bool neighbourContextsEnabled,
o3dgc::Arithmetic_Codec* arithmeticEncoder,
o3dgc::Adaptive_Bit_Model& ctxSingleChild,
o3dgc::Static_Bit_Model& ctxEquiProb,
o3dgc::Adaptive_Data_Model (&ctxOccupancy)[10],
CtxModelOctreeOccupancy& ctxOccupancy,
const PCCOctree3Node& node0,
int occupancy)
{
if (!neighbourContextsEnabled) {
arithmeticEncoder->encode(occupancy, ctxOccupancy[0]);
assert(0); // todo(df): fixme -- old contexts needed
// arithmeticEncoder->encode(occupancy, ctxOccupancy[0]);
return;
}
......@@ -374,6 +484,8 @@ private:
int neighPattern = node0.neighPattern;
int neighPattern10 = kNeighPattern64to10[neighPattern];
uint32_t mappedOccupancy = mapGeometryOccupancy(occupancy, neighPattern);
if (neighPattern10 == 0) {
bool singleChild = !popcntGt1(occupancy);
arithmeticEncoder->encode(singleChild, ctxSingleChild);
......@@ -384,11 +496,12 @@ private:
arithmeticEncoder->encode(!!(occupancy & 0xcc), ctxEquiProb); // y
arithmeticEncoder->encode(!!(occupancy & 0xf0), ctxEquiProb); // x
} else {
arithmeticEncoder->encode(occupancy, ctxOccupancy[0]);
encodeOccupancyNeighZ(
arithmeticEncoder, ctxOccupancy, mappedOccupancy);
}
} else {
uint32_t mappedOccupancy = mapGeometryOccupancy(occupancy, neighPattern);
arithmeticEncoder->encode(mappedOccupancy, ctxOccupancy[neighPattern10]);
encodeOccupancyNeighNZ(
arithmeticEncoder, ctxOccupancy, mappedOccupancy, neighPattern10);
}
}
......@@ -460,14 +573,7 @@ private:
o3dgc::Adaptive_Bit_Model ctxPointCountPerBlock;
o3dgc::Adaptive_Bit_Model ctxBlockSkipTh;
o3dgc::Adaptive_Bit_Model ctxNumIdcmPointsEq1;
// occupancy map model using ten 6-neighbour configurations
o3dgc::Adaptive_Data_Model ctxOccupancy[10];
for (int i = 0; i < 10; i++) {
ctxOccupancy[i].set_alphabet(256);
if (params.neighbourContextsEnabled)
ctxOccupancy[i].reset(kInitCtxOccupancy + 256 * i, true);
}
CtxModelOctreeOccupancy ctxOccupancy;
// init main fifo
// -- worst case size is the last level containing every input poit
......
......@@ -40,6 +40,10 @@ const uint8_t pcc::kNeighPattern64to10[64] = {
6, 7, 3, 6, 6, 7, 4, 7, 7, 8, 1, 3, 3, 4, 3, 6, 6, 7, 3, 6, 6, 7,
4, 7, 7, 8, 2, 4, 4, 5, 4, 7, 7, 8, 4, 7, 7, 8, 5, 8, 8, 9};
const uint8_t pcc::kNeighPattern10to7[10] = {0, 1, 2, 3, 4, 5, 3, 4, 5, 6};
const uint8_t pcc::kNeighPattern7to5[7] = {0, 1, 2, 1, 4, 4, 3};
const uint8_t pcc::kOccMapRotateXIdFromPattern[64] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0,
0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 1, 1, 2, 1, 0, 0, 0, 1, 0, 0, 0,
......@@ -243,119 +247,93 @@ const uint8_t pcc::kOccMapRotateZ090[256] = {
50, 54, 58, 62, 114, 118, 122, 126, 178, 182, 186, 190, 242, 246, 250, 254,
51, 55, 59, 63, 115, 119, 123, 127, 179, 183, 187, 191, 243, 247, 251, 255};
const unsigned int pcc::kInitCtxOccupancy[10 * 256] = {
//
0, 32, 32, 4, 64, 0, 2, 2, 32, 0, 4, 0, 4, 0, 0, 0, 32, 8, 0, 0, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 8, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 8,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 8, 4, 0, 0, 0, 0,
0, 0, 2, 0, 0, 0, 0, 4, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 32, 0, 2, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
//
0, 8, 4, 0, 8, 1, 0, 0, 4, 0, 1, 0, 1, 1, 0, 0, 64, 4, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 64, 0, 4, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 8, 1,
1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 2, 0, 0, 4, 2, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 16, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 4, 1, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 64, 0, 1, 0, 0, 0, 0, 0, 8, 1, 1, 1, 0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 2, 0, 0, 0, 1, 0, 2, 0, 2, 0, 0, 1, 0, 0,
4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 8, 0, 0, 1, 0, 0, 0, 0, 1, 0,
1, 0, 1, 0, 0, 0, 4, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 1, 1,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
0, 0,
//
0, 16, 8, 4, 4, 4, 0, 0, 4, 0, 4, 0, 0, 0, 4, 0, 8, 32, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 8, 0, 32, 0, 0, 0, 0, 0, 4, 0, 2, 0, 0, 0, 0, 0, 2, 4,
4, 16, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 16, 0, 0, 0, 32, 4, 0, 0, 2, 0, 0,
0, 2, 0, 0, 2, 4, 4, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 4, 2, 2, 0, 0, 0, 0, 0, 32, 0, 8, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 0,
2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 4, 0, 0,
0, 8, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 4, 0, 0, 0, 4, 0, 0, 0, 0, 2, 2, 2,
0,
//
0, 2, 2, 0, 8, 1, 0, 0, 8, 0, 1, 0, 2, 0, 0, 0, 8, 1, 0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 8, 1, 0, 0, 2, 0, 0, 0, 2,
0, 0, 0, 8, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64, 1, 1, 0, 4, 0, 0, 0, 8, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 0, 0, 0, 0, 0, 4, 0, 1, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0,
0, 4, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 1,
0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0,
0,
//
0, 16, 32, 16, 16, 16, 4, 16, 16, 2, 16, 4, 8, 8, 8, 16, 4, 4, 1, 2, 1, 4, 0,
2, 1, 0, 0, 1, 0, 2, 0, 2, 4, 1, 4, 2, 1, 1, 1, 2, 1, 0, 4, 2, 0, 0, 1, 2, 0,
0, 0, 2, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 4, 4, 2, 0, 1, 4, 8, 0, 2, 1, 0, 1,
0, 2, 2, 2, 2, 2, 0, 0, 0, 1, 8, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1,
2, 4, 0, 2, 1, 0, 0, 0, 0, 4, 0, 4, 1, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 2, 0, 2, 0, 1, 0, 0, 0, 2, 0, 8, 1, 0, 0, 1, 2, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 1,
1, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 2, 1, 2,
//
0, 1, 1, 0, 1, 1, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0,
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 1, 2, 0, 1, 1, 128, 0, 4, 0, 0, 0, 0, 1, 8, 0, 4, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 4, 0, 0, 0, 0, 0, 1, 0, 2, 2,
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 128, 2, 0, 0, 1, 2, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 4, 0, 1, 0, 0, 0, 0, 0, 4, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 4, 0, 4, 0, 0, 4, 2, 0, 2, 2, 8,
//
0, 0, 2, 0, 1, 0, 0, 0, 8, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 8, 0, 2, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128,
0, 2, 0, 1, 0, 0, 0, 32, 0, 2, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 32, 0, 4, 0, 0, 0, 0, 0, 32, 0, 8, 0, 0, 0, 0, 0, 2, 0, 0,
0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 32, 0, 0, 0, 2, 0, 0, 0, 8, 0, 1, 0,
4, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 1, 0,
0, 0, 8, 0, 2, 0, 4, 0, 1, 0, 8, 0, 0, 0, 1, 0, 0, 0, 4, 0, 1, 0, 4, 0, 2, 1,
//
0, 4, 16, 4, 2, 2, 1, 1, 32, 2, 32, 8, 8, 1, 8, 16, 1, 1, 0, 1, 0, 1, 0, 0,
0, 0, 1, 1, 0, 0, 0, 1, 4, 0, 8, 4, 0, 0, 0, 1, 2, 0, 16, 8, 1, 0, 2, 8, 1,
0, 0, 2, 0, 0, 0, 1, 0, 0, 1, 2, 0, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 4, 0, 2, 0, 0, 0, 0, 0, 8, 0, 16, 2, 4, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 1, 0, 0, 0, 0, 2, 0, 32, 8, 1, 0, 4, 16, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 4, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1,
8,
//
0, 1, 4, 1, 1, 0, 0, 0, 4, 1, 4, 2, 2, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 4, 0, 4, 1, 0, 0, 0, 0, 2, 0, 4, 2, 1, 0, 1, 1, 2, 1, 1, 2,
0, 0, 0, 0, 1, 0, 1, 2, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 8, 0, 1, 0, 0, 0, 0, 0, 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 1, 0, 2, 4, 0,
2, 0, 0, 0, 0, 0, 4, 0, 8, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 4, 0, 8, 1, 0, 0, 0, 0, 4, 0, 64, 4, 1, 0, 8, 4, 1, 0, 2, 2, 0,
0, 0, 1, 2, 0, 8, 8, 0, 0, 2, 8, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 2, 0, 2,
4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 8, 1, 0, 1, 0, 0, 0, 0, 0, 2,
0, 4, 2, 2, 0, 8, 8, 2, 0, 2, 2, 0, 2, 0, 8, 1, 1, 8, 8, 2, 2, 4, 32,
//
0, 1, 1, 1, 2, 1, 0, 0, 1, 0, 1, 0, 2, 1, 0, 1, 2, 2, 0, 1, 0, 1, 0, 0, 0, 0,
1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 1, 2,
0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1,
0, 2, 1, 1, 0, 1, 1, 4, 0, 2, 0, 0, 0, 0, 0, 2, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 1, 2, 1, 4, 0, 0, 0, 1, 1, 1, 1, 8, 1, 0,
0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 2, 0, 0, 2, 2, 1, 1, 0, 1, 0, 0,
0, 2, 0, 1, 2, 4, 1, 1, 1, 4, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 2, 2, 2, 4,
1, 1, 0, 1, 1, 2, 0, 2, 1, 1, 0, 1, 2, 4, 1, 16, 0, 0, 1, 0, 0, 1, 0, 1, 0,
0, 1, 0, 1, 1, 4, 16, 2, 2, 2, 4, 1, 4, 1, 16, 1, 0, 4, 16, 4, 8, 8, 128};
const uint8_t pcc::kOccMapBit4CtxIdx[16 * 9] = {
1, 3, 3, 3, 3, 4, 5, 6, 7, 6, 8, 4, 3, 9, 10, 11, 12, 13,
14, 15, 13, 16, 13, 17, 5, 18, 19, 18, 20, 21, 22, 16, 23, 20, 4, 4,
5, 4, 9, 24, 4, 4, 25, 26, 4, 9, 13, 25, 27, 28, 29, 19, 24, 30,
17, 31, 26, 32, 33, 34, 9, 23, 35, 36, 37, 13, 38, 3, 33, 39, 40, 9,
13, 41, 18, 6, 7, 9, 29, 20, 11, 9, 8, 24, 4, 24, 6, 22, 15, 34,
18, 23, 33, 42, 43, 23, 44, 28, 43, 16, 39, 11, 12, 45, 33,