Commit a03dc25d authored by David Flynn's avatar David Flynn
Browse files

geom: refactor occupancy (de)coding

This commit replaces some repetitive code with a loop.
parent 2c6d7287
...@@ -121,6 +121,22 @@ struct CtxModelOctreeOccupancy { ...@@ -121,6 +121,22 @@ struct CtxModelOctreeOccupancy {
o3dgc::Adaptive_Bit_Model b7[127]; o3dgc::Adaptive_Bit_Model b7[127];
CtxModelOctreeOccupancy(); CtxModelOctreeOccupancy();
o3dgc::Adaptive_Bit_Model* operator[](int bit_pos)
{
assert(unsigned(bit_pos) < 8);
switch (bit_pos) {
case 0: return b0;
case 1: return b1;
case 2: return b2;
case 3: return b3;
case 4: return b4;
case 5: return b5;
case 6: return b6;
case 7: return b7;
default: return nullptr;
}
}
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
......
...@@ -106,46 +106,22 @@ GeometryOctreeDecoder::decodePositionLeafNumPoints() ...@@ -106,46 +106,22 @@ GeometryOctreeDecoder::decodePositionLeafNumPoints()
int int
GeometryOctreeDecoder::decodeOccupancyNeighZ() GeometryOctreeDecoder::decodeOccupancyNeighZ()
{ {
static const int8_t occupancyCodingOrder[8]{1, 7, 5, 3, 2, 4, 6, 0};
int minOccupied = 2;
int numOccupiedAcc = 0; int numOccupiedAcc = 0;
int bit;
int occupancy = 0; int occupancy = 0;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b0[numOccupiedAcc]); for (int i = 0; i < 8; i++) {
numOccupiedAcc += bit; int bit = 1;
occupancy |= bit << 1; // NB: There must be at least two occupied child nodes
// -- avoid coding the occupancy bit if it is implied.
bit = _arithmeticDecoder->decode(_ctxOccupancy.b1[numOccupiedAcc]); if (numOccupiedAcc >= minOccupied + i - 7) {
numOccupiedAcc += bit; int idx = numOccupiedAcc;
occupancy |= bit << 7; bit = _arithmeticDecoder->decode(_ctxOccupancy[i][idx]);
}
bit = _arithmeticDecoder->decode(_ctxOccupancy.b2[numOccupiedAcc]); numOccupiedAcc += bit;
numOccupiedAcc += bit; occupancy |= bit << occupancyCodingOrder[i];
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; return occupancy;
} }
...@@ -156,59 +132,44 @@ GeometryOctreeDecoder::decodeOccupancyNeighZ() ...@@ -156,59 +132,44 @@ GeometryOctreeDecoder::decodeOccupancyNeighZ()
int int
GeometryOctreeDecoder::decodeOccupancyNeighNZ(int neighPattern10) GeometryOctreeDecoder::decodeOccupancyNeighNZ(int neighPattern10)
{ {
static const int8_t occupancyCodingOrder[8]{1, 7, 5, 3, 2, 4, 6, 0};
int neighPattern7 = kNeighPattern10to7[neighPattern10];
int neighPattern5 = kNeighPattern7to5[neighPattern7];
int occupancy = 0; int occupancy = 0;
int partialOccupancy = 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]; // NB: it is impossible for pattern to be 0 (handled in Z case).
idx = ((neighPattern7 - 1) << 6) + partialOccupancy; // NB: offsets are added since ctxIdxMap is shared between Z and NZ cases.
idx = kOccMapBit6CtxIdx[idx] - 1 + 7; for (int i = 0; i < 8; i++) {
bit = _arithmeticDecoder->decode(_ctxOccupancy.b6[idx]); int idx, bit;
partialOccupancy += bit << 6; if (i < 4) {
occupancy |= bit << 6; idx = (neighPattern10 << i) + partialOccupancy;
} else if (i == 4) {
idx = ((neighPattern10 - 1) << i) + partialOccupancy;
idx = kOccMapBit4CtxIdx[idx] + i;
} else if (i == 5) {
idx = ((neighPattern10 - 1) << i) + partialOccupancy;
idx = kOccMapBit5CtxIdx[idx] + i;
} else if (i == 6) {
idx = ((neighPattern7 - 1) << i) + partialOccupancy;
idx = kOccMapBit6CtxIdx[idx] + i;
} else if (i == 7) {
idx = ((neighPattern5 - 1) << i) + partialOccupancy;
idx = kOccMapBit7CtxIdx[idx] + i;
bit = 1;
} else {
// work around clang -Wsometimes-uninitialized fault
break;
}
int neighPattern5 = kNeighPattern7to5[neighPattern7]; // NB: if firt 7 bits are 0, then the last is implicitly 1.
idx = ((neighPattern5 - 1) << 7) + partialOccupancy; if (i < 7 || partialOccupancy)
idx = kOccMapBit7CtxIdx[idx] - 1 + 8; bit = _arithmeticDecoder->decode(_ctxOccupancy[i][idx]);
// NB: if firt 7 bits are 0, then the last is implicitly 1. partialOccupancy |= bit << i;
bit = 1; occupancy |= bit << occupancyCodingOrder[i];
if (partialOccupancy) }
bit = _arithmeticDecoder->decode(_ctxOccupancy.b7[idx]);
occupancy |= bit << 0;
return occupancy; return occupancy;
} }
......
...@@ -106,43 +106,23 @@ GeometryOctreeEncoder::encodePositionLeafNumPoints(int count) ...@@ -106,43 +106,23 @@ GeometryOctreeEncoder::encodePositionLeafNumPoints(int count)
void void
GeometryOctreeEncoder::encodeOccupancyNeighZ(int mappedOccupancy) GeometryOctreeEncoder::encodeOccupancyNeighZ(int mappedOccupancy)
{ {
int occupancyB0 = !!(mappedOccupancy & 2); static const int8_t occupancyCodingOrder[8]{1, 7, 5, 3, 2, 4, 6, 0};
int occupancyB1 = !!(mappedOccupancy & 128); int minOccupied = 2;
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; int numOccupiedAcc = 0;
_arithmeticEncoder->encode(occupancyB0, _ctxOccupancy.b0[numOccupiedAcc]); for (int i = 0; i < 8; i++) {
numOccupiedAcc += occupancyB0; // NB: There must be at least minOccupied child nodes
// -- avoid coding the occupancyBit if it is implied.
_arithmeticEncoder->encode(occupancyB1, _ctxOccupancy.b1[numOccupiedAcc]); if (numOccupiedAcc < minOccupied + i - 7) {
numOccupiedAcc += occupancyB1; assert(i >= 6);
break;
_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) int occupancyBit = (mappedOccupancy >> occupancyCodingOrder[i]) & 1;
_arithmeticEncoder->encode(occupancyB7, _ctxOccupancy.b7[numOccupiedAcc]); int idx = numOccupiedAcc;
_arithmeticEncoder->encode(occupancyBit, _ctxOccupancy[i][idx]);
numOccupiedAcc += occupancyBit;
}
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
...@@ -152,57 +132,43 @@ void ...@@ -152,57 +132,43 @@ void
GeometryOctreeEncoder::encodeOccupancyNeighNZ( GeometryOctreeEncoder::encodeOccupancyNeighNZ(
int mappedOccupancy, int neighPattern10) int mappedOccupancy, int neighPattern10)
{ {
int occupancyB0 = !!(mappedOccupancy & 2); static const int8_t occupancyCodingOrder[8]{1, 7, 5, 3, 2, 4, 6, 0};
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; int neighPattern7 = kNeighPattern10to7[neighPattern10];
_arithmeticEncoder->encode(occupancyB1, _ctxOccupancy.b1[idx]); int neighPattern5 = kNeighPattern7to5[neighPattern7];
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; uint32_t partialOccupancy = 0;
idx = kOccMapBit5CtxIdx[idx] - 1 + 6;
_arithmeticEncoder->encode(occupancyB5, _ctxOccupancy.b5[idx]);
partialOccupancy |= occupancyB5 << 5;
int neighPattern7 = kNeighPattern10to7[neighPattern10]; // NB: it is impossible for pattern to be 0 (handled in Z case).
idx = ((neighPattern7 - 1) << 6) + partialOccupancy; for (int i = 0; i < 8; i++) {
idx = kOccMapBit6CtxIdx[idx] - 1 + 7; int occupancyBit = (mappedOccupancy >> occupancyCodingOrder[i]) & 1;
_arithmeticEncoder->encode(occupancyB6, _ctxOccupancy.b6[idx]);
partialOccupancy |= occupancyB6 << 6; int idx;
if (i < 4)
idx = (neighPattern10 << i) + partialOccupancy;
else if (i == 4) {
idx = ((neighPattern10 - 1) << i) + partialOccupancy;
idx = kOccMapBit4CtxIdx[idx] + i;
} else if (i == 5) {
idx = ((neighPattern10 - 1) << i) + partialOccupancy;
idx = kOccMapBit5CtxIdx[idx] + i;
} else if (i == 6) {
idx = ((neighPattern7 - 1) << i) + partialOccupancy;
idx = kOccMapBit6CtxIdx[idx] + i;
} else if (i == 7) {
// NB: if firt 7 bits are 0, then the last is implicitly 1.
if (!partialOccupancy)
break;
idx = ((neighPattern5 - 1) << i) + partialOccupancy;
idx = kOccMapBit7CtxIdx[idx] + i;
} else {
// work around clang -Wsometimes-uninitialized fault
break;
}
int neighPattern5 = kNeighPattern7to5[neighPattern7]; _arithmeticEncoder->encode(occupancyBit, _ctxOccupancy[i][idx]);
idx = ((neighPattern5 - 1) << 7) + partialOccupancy; partialOccupancy |= occupancyBit << i;
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]);
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment