Commit fc813708 authored by Khaled Mammou's avatar Khaled Mammou Committed by David Flynn
Browse files

attr/m43780: use dual lut coder for transform coefficients

This commit replaces the m-ary coding of transform coefficient values
with a binary coding using the dual-lut coder.

Reworked to include a bug fix where the maximum attribute symbol value
used by the dual lut coder is 64 rather than 255
parent 23ba6f71
......@@ -35,7 +35,7 @@
#include "AttributeDecoder.h"
#include "ArithmeticCodec.h"
#include "DualLutCoder.h"
#include "constants.h"
#include "io_hls.h"
#include "RAHT.h"
......@@ -49,16 +49,16 @@ struct PCCResidualsDecoder {
o3dgc::Arithmetic_Codec arithmeticDecoder;
o3dgc::Static_Bit_Model binaryModel0;
o3dgc::Adaptive_Bit_Model binaryModelPred;
o3dgc::Adaptive_Bit_Model binaryModelDiff0;
o3dgc::Adaptive_Data_Model multiSymbolModelDiff0;
o3dgc::Adaptive_Bit_Model binaryModelDiff1;
o3dgc::Adaptive_Data_Model multiSymbolModelDiff1;
o3dgc::Adaptive_Bit_Model binaryModelDiff[7];
o3dgc::Adaptive_Bit_Model binaryModelIsZero[7];
DualLutCoder<false> symbolCoder[2];
void start(const char* buf, int buf_len);
void stop();
bool decodePred();
uint32_t decode0();
uint32_t decode1();
uint32_t decodeSymbol(int k1, int k2);
void decode(uint32_t values[3]);
uint32_t decode();
};
//----------------------------------------------------------------------------
......@@ -66,9 +66,6 @@ struct PCCResidualsDecoder {
void
PCCResidualsDecoder::start(const char* buf, int buf_len)
{
multiSymbolModelDiff0.set_alphabet(kAttributeResidualAlphabetSize + 1);
multiSymbolModelDiff1.set_alphabet(kAttributeResidualAlphabetSize + 1);
arithmeticDecoder.set_buffer(
buf_len, reinterpret_cast<uint8_t*>(const_cast<char*>(buf)));
......@@ -94,27 +91,40 @@ PCCResidualsDecoder::decodePred()
//----------------------------------------------------------------------------
uint32_t
PCCResidualsDecoder::decode0()
PCCResidualsDecoder::decodeSymbol(int k1, int k2)
{
uint32_t value = arithmeticDecoder.decode(multiSymbolModelDiff0);
if (arithmeticDecoder.decode(binaryModelIsZero[k1])) {
return 0u;
}
uint32_t value = symbolCoder[k2].decode(&arithmeticDecoder);
if (value == kAttributeResidualAlphabetSize) {
value +=
arithmeticDecoder.ExpGolombDecode(0, binaryModel0, binaryModelDiff0);
arithmeticDecoder.ExpGolombDecode(0, binaryModel0, binaryModelDiff[k1]);
}
++value;
return value;
}
//----------------------------------------------------------------------------
void
PCCResidualsDecoder::decode(uint32_t value[3])
{
value[0] = decodeSymbol(0, 0);
int b0 = value[0] == 0;
value[1] = decodeSymbol(1 + b0, 1);
int b1 = value[1] == 0;
value[2] = decodeSymbol(3 + (b0 << 1) + b1, 1);
}
//----------------------------------------------------------------------------
uint32_t
PCCResidualsDecoder::decode1()
PCCResidualsDecoder::decode()
{
uint32_t value = arithmeticDecoder.decode(multiSymbolModelDiff1);
if (value == kAttributeResidualAlphabetSize) {
value +=
arithmeticDecoder.ExpGolombDecode(0, binaryModel0, binaryModelDiff1);
}
return value;
return decodeSymbol(0, 0);
}
//============================================================================
......@@ -231,7 +241,7 @@ AttributeDecoder::decodeReflectancesPred(
computeReflectancePredictionWeights(aps, pointCloud, predictor, decoder);
uint16_t& reflectance = pointCloud.getReflectance(predictor.index);
const uint32_t attValue0 = decoder.decode0();
const uint32_t attValue0 = decoder.decode();
const int64_t quantPredAttValue = predictor.predictReflectance(pointCloud);
const int64_t delta =
PCCInverseQuantization(o3dgc::UIntToInt(attValue0), qs);
......@@ -305,9 +315,7 @@ AttributeDecoder::decodeColorsPred(
const int64_t qs = aps.quant_step_size_luma;
const int64_t qs2 = aps.quant_step_size_chroma;
computeColorPredictionWeights(aps, pointCloud, predictor, decoder);
values[0] = decoder.decode0();
values[1] = decoder.decode1();
values[2] = decoder.decode1();
decoder.decode(values);
PCCColor3B& color = pointCloud.getColor(predictor.index);
const PCCColor3B predictedColor = predictor.predictColor(pointCloud);
const int64_t quantPredAttValue = predictedColor[0];
......@@ -379,7 +387,7 @@ AttributeDecoder::decodeReflectancesRaht(
// Entropy decode
int* sortedIntegerizedAttributes = new int[voxelCount];
for (int n = 0; n < voxelCount; ++n) {
const uint32_t attValue0 = decoder.decode0();
const uint32_t attValue0 = decoder.decode();
sortedIntegerizedAttributes[n] = o3dgc::UIntToInt(attValue0);
}
......@@ -465,18 +473,20 @@ AttributeDecoder::decodeColorsRaht(
// Entropy decode
const int attribCount = 3;
uint32_t values[3];
int* sortedIntegerizedAttributes = new int[attribCount * voxelCount];
for (int n = 0; n < voxelCount; ++n) {
const uint32_t attValue0 = decoder.decode0();
sortedIntegerizedAttributes[n] = o3dgc::UIntToInt(attValue0);
if (
binaryLayer[sortedWeight[n].index] >= aps.raht_binary_level_threshold) {
decoder.decode(values);
sortedIntegerizedAttributes[n] = o3dgc::UIntToInt(values[0]);
for (int d = 1; d < 3; ++d) {
const uint32_t attValue1 = decoder.decode1();
sortedIntegerizedAttributes[voxelCount * d + n] =
o3dgc::UIntToInt(attValue1);
o3dgc::UIntToInt(values[d]);
}
} else {
values[0] = decoder.decode();
sortedIntegerizedAttributes[n] = o3dgc::UIntToInt(values[0]);
for (int d = 1; d < 3; d++) {
sortedIntegerizedAttributes[voxelCount * d + n] = 0;
}
......@@ -558,9 +568,7 @@ AttributeDecoder::decodeColorsLift(
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
uint32_t values[3];
values[0] = decoder.decode0();
values[1] = decoder.decode1();
values[2] = decoder.decode1();
decoder.decode(values);
const int64_t qs = aps.quant_step_size_luma;
const int64_t qs2 = aps.quant_step_size_chroma;
const double quantWeight = sqrt(weights[predictorIndex]);
......@@ -626,7 +634,7 @@ AttributeDecoder::decodeReflectancesLift(
// decompress
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
const int64_t detail = decoder.decode0();
const int64_t detail = decoder.decode();
const int64_t qs = aps.quant_step_size_luma;
const double quantWeight = sqrt(weights[predictorIndex]);
auto& reflectance = reflectances[predictorIndex];
......
......@@ -36,6 +36,7 @@
#include "AttributeEncoder.h"
#include "ArithmeticCodec.h"
#include "DualLutCoder.h"
#include "constants.h"
#include "RAHT.h"
......@@ -47,16 +48,16 @@ struct PCCResidualsEncoder {
o3dgc::Arithmetic_Codec arithmeticEncoder;
o3dgc::Static_Bit_Model binaryModel0;
o3dgc::Adaptive_Bit_Model binaryModelPred;
o3dgc::Adaptive_Bit_Model binaryModelDiff0;
o3dgc::Adaptive_Data_Model multiSymbolModelDiff0;
o3dgc::Adaptive_Bit_Model binaryModelDiff1;
o3dgc::Adaptive_Data_Model multiSymbolModelDiff1;
o3dgc::Adaptive_Bit_Model binaryModelDiff[7];
o3dgc::Adaptive_Bit_Model binaryModelIsZero[7];
DualLutCoder<false> symbolCoder[2];
void start(int numPoints);
int stop();
void encode0(const uint32_t value);
void encode1(const uint32_t value);
void encodePred(const bool value);
void encodeSymbol(uint32_t value, int k1, int k2);
void encode(uint32_t value0, uint32_t value1, uint32_t value2);
void encode(uint32_t value);
};
//----------------------------------------------------------------------------
......@@ -64,9 +65,6 @@ struct PCCResidualsEncoder {
void
PCCResidualsEncoder::start(int pointCount)
{
multiSymbolModelDiff0.set_alphabet(kAttributeResidualAlphabetSize + 1);
multiSymbolModelDiff1.set_alphabet(kAttributeResidualAlphabetSize + 1);
// todo(df): remove estimate when arithmetic codec is replaced
int maxAcBufLen = pointCount * 3 * 2 + 1024;
arithmeticEncoder.set_buffer(maxAcBufLen, nullptr);
......@@ -83,40 +81,51 @@ PCCResidualsEncoder::stop()
//----------------------------------------------------------------------------
inline void
PCCResidualsEncoder::encode0(const uint32_t value)
void
PCCResidualsEncoder::encodePred(const bool value)
{
if (value < kAttributeResidualAlphabetSize) {
arithmeticEncoder.encode(value, multiSymbolModelDiff0);
} else {
int alphabetSize = kAttributeResidualAlphabetSize;
arithmeticEncoder.encode(alphabetSize, multiSymbolModelDiff0);
arithmeticEncoder.ExpGolombEncode(
value - alphabetSize, 0, binaryModel0, binaryModelDiff0);
}
arithmeticEncoder.encode(value, binaryModelPred);
}
//----------------------------------------------------------------------------
inline void
PCCResidualsEncoder::encode1(const uint32_t value)
void
PCCResidualsEncoder::encodeSymbol(uint32_t value, int k1, int k2)
{
bool isZero = value == 0;
arithmeticEncoder.encode(isZero, binaryModelIsZero[k1]);
if (isZero) {
return;
}
--value;
if (value < kAttributeResidualAlphabetSize) {
arithmeticEncoder.encode(value, multiSymbolModelDiff1);
symbolCoder[k2].encode(value, &arithmeticEncoder);
} else {
int alphabetSize = kAttributeResidualAlphabetSize;
arithmeticEncoder.encode(alphabetSize, multiSymbolModelDiff1);
symbolCoder[k2].encode(alphabetSize, &arithmeticEncoder);
arithmeticEncoder.ExpGolombEncode(
value - alphabetSize, 0, binaryModel0, binaryModelDiff1);
value - alphabetSize, 0, binaryModel0, binaryModelDiff[k1]);
}
}
//----------------------------------------------------------------------------
void
PCCResidualsEncoder::encodePred(const bool value)
PCCResidualsEncoder::encode(uint32_t value0, uint32_t value1, uint32_t value2)
{
arithmeticEncoder.encode(value, binaryModelPred);
int b0 = value0 == 0;
int b1 = value1 == 0;
encodeSymbol(value0, 0, 0);
encodeSymbol(value1, 1 + b0, 1);
encodeSymbol(value2, 3 + (b0 << 1) + b1, 1);
}
//----------------------------------------------------------------------------
void
PCCResidualsEncoder::encode(uint32_t value)
{
encodeSymbol(value, 0, 0);
}
//============================================================================
......@@ -416,7 +425,7 @@ AttributeEncoder::encodeReflectancesPred(
const uint16_t reconstructedReflectance =
uint16_t(PCCClip(reconstructedQuantAttValue, int64_t(0), clipMax));
encoder.encode0(attValue0);
encoder.encode(attValue0);
pointCloud.setReflectance(predictor.index, reconstructedReflectance);
}
}
......@@ -558,9 +567,7 @@ AttributeEncoder::encodeColorsPred(
uint8_t(PCCClip(reconstructedQuantAttValue, int64_t(0), clipMax));
}
pointCloud.setColor(predictor.index, reconstructedColor);
encoder.encode0(values[0]);
encoder.encode1(values[1]);
encoder.encode1(values[2]);
encoder.encode(values[0], values[1], values[2]);
}
}
......@@ -634,7 +641,7 @@ AttributeEncoder::encodeReflectancesTransformRaht(
const int64_t detail = o3dgc::IntToUInt(sortedIntegerizedAttributes[n]);
assert(detail < std::numeric_limits<uint32_t>::max());
const uint32_t attValue0 = uint32_t(detail);
encoder.encode0(attValue0);
encoder.encode(attValue0);
}
// Re-obtain weights at the decoder by calling Raht without any attributes.
regionAdaptiveHierarchicalTransform(
......@@ -750,24 +757,25 @@ AttributeEncoder::encodeColorsTransformRaht(
}
// Entropy encode.
uint32_t values[3];
for (int n = 0; n < voxelCount; ++n) {
const int64_t detail = o3dgc::IntToUInt(sortedIntegerizedAttributes[n]);
assert(detail < std::numeric_limits<uint32_t>::max());
const uint32_t attValue0 = uint32_t(detail);
encoder.encode0(attValue0);
values[0] = uint32_t(detail);
if (
binaryLayer[sortedWeight[n].index] >= aps.raht_binary_level_threshold) {
for (int d = 1; d < 3; ++d) {
const int64_t detail =
o3dgc::IntToUInt(sortedIntegerizedAttributes[voxelCount * d + n]);
assert(detail < std::numeric_limits<uint32_t>::max());
const uint32_t attValue1 = uint32_t(detail);
encoder.encode1(attValue1);
values[d] = uint32_t(detail);
}
encoder.encode(values[0], values[1], values[2]);
} else {
for (int d = 1; d < 3; d++) {
sortedIntegerizedAttributes[voxelCount * d + n] = 0;
}
encoder.encode(values[0]);
}
}
......@@ -888,9 +896,7 @@ AttributeEncoder::encodeColorsLift(
color[d] = reconstructedDelta / quantWeight;
values[d] = uint32_t(detail);
}
encoder.encode0(values[0]);
encoder.encode1(values[1]);
encoder.encode1(values[2]);
encoder.encode(values[0], values[1], values[2]);
}
// reconstruct
......@@ -965,7 +971,7 @@ AttributeEncoder::encodeReflectancesLift(
assert(detail < std::numeric_limits<uint32_t>::max());
const double reconstructedDelta = PCCInverseQuantization(delta, qs);
reflectance = reconstructedDelta / quantWeight;
encoder.encode0(detail);
encoder.encode(detail);
}
// reconstruct
......
......@@ -42,7 +42,7 @@ namespace pcc {
//============================================================================
const uint32_t kAttributePredictionMaxNeighbourCount = 3;
const uint32_t kAttributeResidualAlphabetSize = 64;
const uint32_t kAttributeResidualAlphabetSize = 255;
//============================================================================
......
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