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