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

attr: move fixed point adjustment out of quantization functions

The quantization functions are applied to both fixed-point and unitary
precision data using the same QP.  This commit moves the implicit
conversion adjustment out of the quantiser and into the calling code.
parent ac0d1d7b
......@@ -297,8 +297,9 @@ AttributeDecoder::decodeReflectancesPred(
}
const int64_t quantPredAttValue =
predictor.predictReflectance(pointCloud, indexesLOD);
const int64_t delta =
PCCInverseQuantization(UIntToInt(attValue0), qs, true);
const int64_t delta = divExp2RoundHalfUp(
PCCInverseQuantization(UIntToInt(attValue0), qs),
kFixedPointAttributeShift);
const int64_t reconstructedQuantAttValue = quantPredAttValue + delta;
reflectance = uint16_t(
PCCClip(reconstructedQuantAttValue, int64_t(0), maxReflectance));
......@@ -385,16 +386,18 @@ AttributeDecoder::decodeColorsPred(
const Vec3<uint8_t> predictedColor =
predictor.predictColor(pointCloud, indexesLOD);
const int64_t quantPredAttValue = predictedColor[0];
const int64_t delta =
PCCInverseQuantization(UIntToInt(values[0]), qs, true);
const int64_t delta = divExp2RoundHalfUp(
PCCInverseQuantization(UIntToInt(values[0]), qs),
kFixedPointAttributeShift);
const int64_t reconstructedQuantAttValue = quantPredAttValue + delta;
int64_t clipMax = (1 << desc.attr_bitdepth) - 1;
color[0] =
uint8_t(PCCClip(reconstructedQuantAttValue, int64_t(0), clipMax));
for (size_t k = 1; k < 3; ++k) {
const int64_t quantPredAttValue = predictedColor[k];
const int64_t delta =
PCCInverseQuantization(UIntToInt(values[k]), qs2, true);
const int64_t delta = divExp2RoundHalfUp(
PCCInverseQuantization(UIntToInt(values[k]), qs2),
kFixedPointAttributeShift);
const int64_t reconstructedQuantAttValue = quantPredAttValue + delta;
color[k] =
uint8_t(PCCClip(reconstructedQuantAttValue, int64_t(0), clipMax));
......
......@@ -387,8 +387,8 @@ AttributeEncoder::computeReflectanceResidual(
{
const int64_t quantAttValue = reflectance;
const int64_t quantPredAttValue = predictedReflectance;
const int64_t delta =
PCCQuantization(quantAttValue - quantPredAttValue, qs, true);
const int64_t delta = PCCQuantization(
(quantAttValue - quantPredAttValue) << kFixedPointAttributeShift, qs);
return IntToUInt(delta);
}
......@@ -503,10 +503,11 @@ AttributeEncoder::encodeReflectancesPred(
predictor.predictReflectance(pointCloud, indexesLOD);
const int64_t quantAttValue = reflectance;
const int64_t quantPredAttValue = predictedReflectance;
const int64_t delta =
PCCQuantization(quantAttValue - quantPredAttValue, qs, true);
const int64_t delta = PCCQuantization(
(quantAttValue - quantPredAttValue) << kFixedPointAttributeShift, qs);
const uint32_t attValue0 = uint32_t(IntToUInt(long(delta)));
const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs, true);
const int64_t reconstructedDelta = divExp2RoundHalfUp(
PCCInverseQuantization(delta, qs), kFixedPointAttributeShift);
const int64_t reconstructedQuantAttValue =
quantPredAttValue + reconstructedDelta;
const uint16_t reconstructedReflectance =
......@@ -557,14 +558,14 @@ AttributeEncoder::computeColorResiduals(
Vec3<int64_t> residuals;
const int64_t quantAttValue = color[0];
const int64_t quantPredAttValue = predictedColor[0];
const int64_t delta =
PCCQuantization(quantAttValue - quantPredAttValue, qs, true);
const int64_t delta = PCCQuantization(
(quantAttValue - quantPredAttValue) << kFixedPointAttributeShift, qs);
residuals[0] = IntToUInt(delta);
for (size_t k = 1; k < 3; ++k) {
const int64_t quantAttValue = color[k];
const int64_t quantPredAttValue = predictedColor[k];
const int64_t delta =
PCCQuantization(quantAttValue - quantPredAttValue, qs2, true);
const int64_t delta = PCCQuantization(
(quantAttValue - quantPredAttValue) << kFixedPointAttributeShift, qs2);
residuals[k] = IntToUInt(delta);
}
return residuals;
......@@ -691,9 +692,10 @@ AttributeEncoder::encodeColorsPred(
predictor.predictColor(pointCloud, indexesLOD);
const int64_t quantAttValue = color[0];
const int64_t quantPredAttValue = predictedColor[0];
const int64_t delta =
PCCQuantization(quantAttValue - quantPredAttValue, qs, true);
const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs, true);
const int64_t delta = PCCQuantization(
(quantAttValue - quantPredAttValue) << kFixedPointAttributeShift, qs);
const int64_t reconstructedDelta = divExp2RoundHalfUp(
PCCInverseQuantization(delta, qs), kFixedPointAttributeShift);
const int64_t reconstructedQuantAttValue =
quantPredAttValue + reconstructedDelta;
values[0] = uint32_t(IntToUInt(long(delta)));
......@@ -703,10 +705,10 @@ AttributeEncoder::encodeColorsPred(
for (size_t k = 1; k < 3; ++k) {
const int64_t quantAttValue = color[k];
const int64_t quantPredAttValue = predictedColor[k];
const int64_t delta =
PCCQuantization(quantAttValue - quantPredAttValue, qs2, true);
const int64_t reconstructedDelta =
PCCInverseQuantization(delta, qs2, true);
const int64_t delta = PCCQuantization(
(quantAttValue - quantPredAttValue) << kFixedPointAttributeShift, qs2);
const int64_t reconstructedDelta = divExp2RoundHalfUp(
PCCInverseQuantization(delta, qs2), kFixedPointAttributeShift);
const int64_t reconstructedQuantAttValue =
quantPredAttValue + reconstructedDelta;
values[k] = uint32_t(IntToUInt(long(delta)));
......
......@@ -393,6 +393,20 @@ PCCClip(const int64_t& n, const int64_t& lower, const int64_t& upper)
return std::max(lower, std::min(n, upper));
}
//---------------------------------------------------------------------------
// Integer division of @x by 2^shift, rounding intermediate half values
// to +Inf.
inline int64_t
divExp2RoundHalfUp(int64_t x, int shift)
{
if (!shift)
return x;
int64_t half = 1 << (shift - 1);
return (x + half) >> shift;
}
//---------------------------------------------------------------------------
// Integer division of @scalar by 2^shift, rounding intermediate half values
// away from zero.
......
......@@ -246,34 +246,25 @@ struct PCCPredictor {
//---------------------------------------------------------------------------
inline int64_t
PCCQuantization(const int64_t value, const int64_t qs, bool isup = false)
PCCQuantization(const int64_t value, const int64_t qs)
{
const int64_t shift = (qs / 3);
if (!qs) {
return value;
}
if (isup) {
if (value >= 0) {
return ((value << kFixedPointAttributeShift) + shift) / qs;
}
return -((shift - (value << kFixedPointAttributeShift)) / qs);
} else if (value >= 0) {
if (value >= 0) {
return (value + shift) / qs;
}
return -((shift - value) / qs);
}
inline int64_t
PCCInverseQuantization(
const int64_t value, const int64_t qs, bool isdown = false)
PCCInverseQuantization(const int64_t value, const int64_t qs)
{
if (!qs)
return value;
if (isdown) {
const int offset = 1 << (kFixedPointAttributeShift - 1);
return (value * qs + offset) >> kFixedPointAttributeShift;
}
return value * qs;
}
......
......@@ -718,14 +718,16 @@ uraht_process(
if (isEncoder) {
auto coeff = transformBuf[k][idx].round();
assert(coeff <= INT_MAX && coeff >= INT_MIN);
*coeffBufItK[k]++ = coeff =
PCCQuantization(coeff, quantStepSize, true);
transformPredBuf[k][idx] +=
PCCInverseQuantization(coeff, quantStepSize, true);
*coeffBufItK[k]++ = coeff = PCCQuantization(
coeff << kFixedPointAttributeShift, quantStepSize);
transformPredBuf[k][idx] += divExp2RoundHalfUp(
PCCInverseQuantization(coeff, quantStepSize),
kFixedPointAttributeShift);
} else {
int64_t coeff = *coeffBufItK[k]++;
transformPredBuf[k][idx] +=
PCCInverseQuantization(coeff, quantStepSize, true);
transformPredBuf[k][idx] += divExp2RoundHalfUp(
PCCInverseQuantization(coeff, quantStepSize),
kFixedPointAttributeShift);
}
}
});
......@@ -820,11 +822,15 @@ uraht_process(
auto coeff = transformBuf[1].round();
assert(coeff <= INT_MAX && coeff >= INT_MIN);
*coeffBufItK[k]++ = coeff =
PCCQuantization(coeff, quantStepSize, true);
transformBuf[1] = PCCInverseQuantization(coeff, quantStepSize, true);
PCCQuantization(coeff << kFixedPointAttributeShift, quantStepSize);
transformBuf[1] = divExp2RoundHalfUp(
PCCInverseQuantization(coeff, quantStepSize),
kFixedPointAttributeShift);
} else {
int64_t coeff = *coeffBufItK[k]++;
transformBuf[1] = PCCInverseQuantization(coeff, quantStepSize, true);
transformBuf[1] = divExp2RoundHalfUp(
PCCInverseQuantization(coeff, quantStepSize),
kFixedPointAttributeShift);
}
// inherit the DC value
......
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