Commit 4c0c1201 authored by David Flynn's avatar David Flynn Committed by David Flynn
Browse files

attr/m47378: top-down raht

In order to support transform domain prediction of AC coefficients using
upsampled previously reconstructed transform levels, this commit
replaces the existing RAHT implementation with a descent based RAHT tree
traversal for both encoder and decoder with the transform performed in
units of 2×2×2 blocks.
parent e88781d9
......@@ -413,11 +413,8 @@ AttributeDecoder::decodeReflectancesRaht(
PCCPointSet3& pointCloud)
{
const int voxelCount = int(pointCloud.getPointCount());
uint64_t* weight = new uint64_t[voxelCount];
int* binaryLayer = new int[voxelCount];
std::vector<MortonCodeWithIndex> packedVoxel(voxelCount);
for (int n = 0; n < voxelCount; n++) {
weight[n] = 1;
packedVoxel[n].mortonCode = mortonAddr(pointCloud[n], 0);
packedVoxel[n].index = n;
}
......@@ -431,7 +428,7 @@ AttributeDecoder::decodeReflectancesRaht(
// Entropy decode
const int attribCount = 1;
int* integerizedAttributes = new int[attribCount * voxelCount];
int* coefficients = new int[attribCount * voxelCount];
int zero_cnt = decoder.decodeZeroCnt(voxelCount);
for (int n = 0; n < voxelCount; ++n) {
uint32_t value = 0;
......@@ -441,30 +438,27 @@ AttributeDecoder::decodeReflectancesRaht(
value = decoder.decode();
zero_cnt = decoder.decodeZeroCnt(voxelCount);
}
integerizedAttributes[n] = UIntToInt(value);
coefficients[n] = UIntToInt(value);
}
FixedPoint* attributes = new FixedPoint[attribCount * voxelCount];
int* attributes = new int[attribCount * voxelCount];
regionAdaptiveHierarchicalInverseTransform(
FixedPoint(qstep[0]), mortonCode, attributes, weight, attribCount,
voxelCount, integerizedAttributes);
qstep, mortonCode, attributes, attribCount, voxelCount, coefficients);
const int64_t maxReflectance = (1 << desc.attr_bitdepth) - 1;
const int64_t minReflectance = 0;
for (int n = 0; n < voxelCount; n++) {
int64_t val = attributes[attribCount * n].round();
int64_t val = attributes[attribCount * n];
const uint16_t reflectance =
(uint16_t)PCCClip(val, minReflectance, maxReflectance);
pointCloud.setReflectance(packedVoxel[n].index, reflectance);
}
// De-allocate arrays.
delete[] binaryLayer;
delete[] mortonCode;
delete[] attributes;
delete[] integerizedAttributes;
delete[] weight;
delete[] coefficients;
}
//----------------------------------------------------------------------------
......@@ -478,11 +472,8 @@ AttributeDecoder::decodeColorsRaht(
PCCPointSet3& pointCloud)
{
const int voxelCount = int(pointCloud.getPointCount());
uint64_t* weight = new uint64_t[voxelCount];
int* binaryLayer = new int[voxelCount];
std::vector<MortonCodeWithIndex> packedVoxel(voxelCount);
for (int n = 0; n < voxelCount; n++) {
weight[n] = 1;
packedVoxel[n].mortonCode = mortonAddr(pointCloud[n], 0);
packedVoxel[n].index = n;
}
......@@ -497,7 +488,7 @@ AttributeDecoder::decodeColorsRaht(
// Entropy decode
const int attribCount = 3;
int zero_cnt = decoder.decodeZeroCnt(voxelCount);
int* integerizedAttributes = new int[attribCount * voxelCount];
int* coefficients = new int[attribCount * voxelCount];
for (int n = 0; n < voxelCount; ++n) {
uint32_t values[3];
......@@ -509,21 +500,20 @@ AttributeDecoder::decodeColorsRaht(
zero_cnt = decoder.decodeZeroCnt(voxelCount);
}
for (int d = 0; d < attribCount; ++d) {
integerizedAttributes[voxelCount * d + n] = UIntToInt(values[d]);
coefficients[voxelCount * d + n] = UIntToInt(values[d]);
}
}
FixedPoint* attributes = new FixedPoint[attribCount * voxelCount];
int* attributes = new int[attribCount * voxelCount];
regionAdaptiveHierarchicalInverseTransform(
FixedPoint(qstep[0]), mortonCode, attributes, weight, attribCount,
voxelCount, integerizedAttributes);
qstep, mortonCode, attributes, attribCount, voxelCount, coefficients);
const int clipMax = (1 << desc.attr_bitdepth) - 1;
for (int n = 0; n < voxelCount; n++) {
const int r = attributes[attribCount * n].round();
const int g = attributes[attribCount * n + 1].round();
const int b = attributes[attribCount * n + 2].round();
const int r = attributes[attribCount * n];
const int g = attributes[attribCount * n + 1];
const int b = attributes[attribCount * n + 2];
Vec3<uint8_t> color;
color[0] = uint8_t(PCCClip(r, 0, clipMax));
color[1] = uint8_t(PCCClip(g, 0, clipMax));
......@@ -532,11 +522,9 @@ AttributeDecoder::decodeColorsRaht(
}
// De-allocate arrays.
delete[] binaryLayer;
delete[] mortonCode;
delete[] attributes;
delete[] integerizedAttributes;
delete[] weight;
delete[] coefficients;
}
//----------------------------------------------------------------------------
......
......@@ -773,14 +773,11 @@ AttributeEncoder::encodeReflectancesTransformRaht(
// Allocate arrays.
int64_t* mortonCode = new int64_t[voxelCount];
const int attribCount = 1;
FixedPoint* attributes = new FixedPoint[attribCount * voxelCount];
int* integerizedAttributes = new int[attribCount * voxelCount];
uint64_t* weight = new uint64_t[voxelCount];
int* binaryLayer = new int[voxelCount];
int* attributes = new int[attribCount * voxelCount];
int* coefficients = new int[attribCount * voxelCount];
// Populate input arrays.
for (int n = 0; n < voxelCount; n++) {
weight[n] = 1;
mortonCode[n] = packedVoxel[n].mortonCode;
const auto reflectance = pointCloud.getReflectance(packedVoxel[n].index);
attributes[attribCount * n] = reflectance;
......@@ -788,14 +785,13 @@ AttributeEncoder::encodeReflectancesTransformRaht(
// Transform.
regionAdaptiveHierarchicalTransform(
FixedPoint(qstep[0]), mortonCode, attributes, weight, binaryLayer,
attribCount, voxelCount, integerizedAttributes);
qstep, mortonCode, attributes, attribCount, voxelCount, coefficients);
// Entropy encode.
int zero_cnt = 0;
uint32_t value;
for (int n = 0; n < voxelCount; ++n) {
const int64_t detail = IntToUInt(integerizedAttributes[n]);
const int64_t detail = IntToUInt(coefficients[n]);
assert(detail < std::numeric_limits<uint32_t>::max());
value = uint32_t(detail);
if (!value)
......@@ -808,32 +804,19 @@ AttributeEncoder::encodeReflectancesTransformRaht(
}
encoder.encodeZeroCnt(zero_cnt, voxelCount);
// local decode
std::fill_n(attributes, attribCount * voxelCount, FixedPoint(0));
for (int n = 0; n < voxelCount; n++) {
mortonCode[n] = packedVoxel[n].mortonCode;
weight[n] = 1;
}
regionAdaptiveHierarchicalInverseTransform(
FixedPoint(qstep[0]), mortonCode, attributes, weight, attribCount,
voxelCount, integerizedAttributes);
const int64_t maxReflectance = (1 << desc.attr_bitdepth) - 1;
const int64_t minReflectance = 0;
for (int n = 0; n < voxelCount; n++) {
int64_t val = attributes[attribCount * n].round();
int64_t val = attributes[attribCount * n];
const uint16_t reflectance =
(uint16_t)PCCClip(val, minReflectance, maxReflectance);
pointCloud.setReflectance(packedVoxel[n].index, reflectance);
}
// De-allocate arrays.
delete[] binaryLayer;
delete[] mortonCode;
delete[] attributes;
delete[] integerizedAttributes;
delete[] weight;
delete[] coefficients;
}
//----------------------------------------------------------------------------
......@@ -857,14 +840,11 @@ AttributeEncoder::encodeColorsTransformRaht(
// Allocate arrays.
int64_t* mortonCode = new int64_t[voxelCount];
const int attribCount = 3;
FixedPoint* attributes = new FixedPoint[attribCount * voxelCount];
int* integerizedAttributes = new int[attribCount * voxelCount];
uint64_t* weight = new uint64_t[voxelCount];
int* binaryLayer = new int[voxelCount];
int* attributes = new int[attribCount * voxelCount];
int* coefficients = new int[attribCount * voxelCount];
// Populate input arrays.
for (int n = 0; n < voxelCount; n++) {
weight[n] = 1;
mortonCode[n] = packedVoxel[n].mortonCode;
const auto color = pointCloud.getColor(packedVoxel[n].index);
attributes[attribCount * n] = color[0];
......@@ -874,16 +854,14 @@ AttributeEncoder::encodeColorsTransformRaht(
// Transform.
regionAdaptiveHierarchicalTransform(
FixedPoint(qstep[0]), mortonCode, attributes, weight, binaryLayer,
attribCount, voxelCount, integerizedAttributes);
qstep, mortonCode, attributes, attribCount, voxelCount, coefficients);
// Entropy encode.
uint32_t values[attribCount];
int zero_cnt = 0;
for (int n = 0; n < voxelCount; ++n) {
for (int d = 0; d < attribCount; ++d) {
const int64_t detail =
IntToUInt(integerizedAttributes[voxelCount * d + n]);
const int64_t detail = IntToUInt(coefficients[voxelCount * d + n]);
assert(detail < std::numeric_limits<uint32_t>::max());
values[d] = uint32_t(detail);
}
......@@ -895,25 +873,13 @@ AttributeEncoder::encodeColorsTransformRaht(
zero_cnt = 0;
}
}
encoder.encodeZeroCnt(zero_cnt, voxelCount);
// local decode
std::fill_n(attributes, attribCount * voxelCount, FixedPoint(0));
for (int n = 0; n < voxelCount; n++) {
weight[n] = 1;
mortonCode[n] = packedVoxel[n].mortonCode;
}
regionAdaptiveHierarchicalInverseTransform(
FixedPoint(qstep[0]), mortonCode, attributes, weight, attribCount,
voxelCount, integerizedAttributes);
const int clipMax = (1 << desc.attr_bitdepth) - 1;
for (int n = 0; n < voxelCount; n++) {
const int r = attributes[attribCount * n].round();
const int g = attributes[attribCount * n + 1].round();
const int b = attributes[attribCount * n + 2].round();
const int r = attributes[attribCount * n];
const int g = attributes[attribCount * n + 1];
const int b = attributes[attribCount * n + 2];
Vec3<uint8_t> color;
color[0] = uint8_t(PCCClip(r, 0, clipMax));
color[1] = uint8_t(PCCClip(g, 0, clipMax));
......@@ -922,11 +888,9 @@ AttributeEncoder::encodeColorsTransformRaht(
}
// De-allocate arrays.
delete[] binaryLayer;
delete[] mortonCode;
delete[] attributes;
delete[] integerizedAttributes;
delete[] weight;
delete[] coefficients;
}
//----------------------------------------------------------------------------
......
......@@ -57,6 +57,8 @@ public:
FixedPoint& operator=(FixedPoint&&) = default;
FixedPoint(int val) { this->operator=(int64_t(val)); }
FixedPoint(int64_t val) { this->operator=(val); }
FixedPoint(double val) { this->val = int64_t(val * (1 << kFracBits)); }
// return the rounded integer value
int64_t round();
......
......@@ -174,7 +174,7 @@ ceillog2(uint32_t x)
//---------------------------------------------------------------------------
// Compute an approximation of \left\floor \sqrt{x} \right\floor
uint32_t isqrt(uint64_t x);
uint32_t isqrt(uint64_t x) __attribute__((const));
//---------------------------------------------------------------------------
// Decrement the @axis-th dimension of 3D morton code @x.
......@@ -186,6 +186,23 @@ morton3dAxisDec(int64_t val, int axis)
return ((val & mask0) - 1 & mask0) | (val & ~mask0);
}
//---------------------------------------------------------------------------
// add the three dimentional addresses @a + @b;
//
inline uint64_t
morton3dAdd(uint64_t a, uint64_t b)
{
uint64_t mask = 0x9249249249249249llu;
uint64_t val = 0;
for (int i = 0; i < 3; i++) {
val |= (a | ~mask) + (b & mask) & mask;
mask <<= 1;
}
return val;
}
//---------------------------------------------------------------------------
// Sort the elements in range [@first, @last) using a counting sort.
//
......
This diff is collapsed.
......@@ -38,26 +38,24 @@
#include <cstdint>
#include "FixedPoint.h"
#include "quantization.h"
namespace pcc {
void regionAdaptiveHierarchicalTransform(
FixedPoint quantStepSizeLuma,
const Quantizers& qstep,
int64_t* mortonCode,
FixedPoint* attributes,
uint64_t* weight,
int* binaryLayer,
int* attributes,
const int attribCount,
const int voxelCount,
int* integerizedAttributes);
int* coefficients);
void regionAdaptiveHierarchicalInverseTransform(
FixedPoint quantStepSizeLuma,
const Quantizers& qstep,
int64_t* mortonCode,
FixedPoint* attributes,
uint64_t* weight,
int* attributes,
const int attribCount,
const int voxelCount,
int* integerizedAttributes);
int* coefficients);
} /* namespace pcc */
......@@ -549,9 +549,6 @@ ParseParameters(int argc, char* argv[], Parameters& params)
if (attr_aps.attr_encoding == AttributeEncoding::kRAHTransform) {
attr_aps.num_detail_levels = 0;
attr_aps.adaptive_prediction_threshold = 0;
// todo(df): suggest chroma quant_step_size for raht
attr_aps.aps_chroma_qp_offset = 0;
}
}
......
......@@ -262,7 +262,6 @@ write(const AttributeParameterSet& aps)
bs.writeUe(aps.attr_encoding);
bs.writeUe(aps.init_qp);
// todo(?): raht chroma qp support?
bs.writeSe(aps.aps_chroma_qp_offset);
bs.write(aps.aps_slice_qp_deltas_present_flag);
......@@ -311,7 +310,6 @@ parseAps(const PayloadBuffer& buf)
bs.readUe(&aps.attr_encoding);
bs.readUe(&aps.init_qp);
// todo(?): raht chroma qp support?
bs.readSe(&aps.aps_chroma_qp_offset);
bs.read(&aps.aps_slice_qp_deltas_present_flag);
......
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