Commit 20d66c65 authored by David Flynn's avatar David Flynn
Browse files

attr/m49601: add support to signal chroma (secondary) bitdepth

Some imput formats and colour spaces have a different bitdepth
for their chroma (non-primary) component.  This commit adds
support to signal their bitdepth as described by the codec
independent code points.
parent a8f27566
...@@ -377,6 +377,10 @@ AttributeDecoder::decodeColorsPred( ...@@ -377,6 +377,10 @@ AttributeDecoder::decodeColorsPred(
buildPredictorsFast( buildPredictorsFast(
aps, pointCloud, 0, predictors, numberOfPointsPerLOD, indexesLOD); aps, pointCloud, 0, predictors, numberOfPointsPerLOD, indexesLOD);
Vec3<int64_t> clipMax{(1 << desc.attr_bitdepth) - 1,
(1 << desc.attr_bitdepth_secondary) - 1,
(1 << desc.attr_bitdepth_secondary) - 1};
uint32_t values[3]; uint32_t values[3];
int zero_cnt = decoder.decodeZeroCnt(pointCount); int zero_cnt = decoder.decodeZeroCnt(pointCount);
int quantLayer = 0; int quantLayer = 0;
...@@ -402,14 +406,13 @@ AttributeDecoder::decodeColorsPred( ...@@ -402,14 +406,13 @@ AttributeDecoder::decodeColorsPred(
const Vec3<attr_t> predictedColor = const Vec3<attr_t> predictedColor =
predictor.predictColor(pointCloud, indexesLOD); predictor.predictColor(pointCloud, indexesLOD);
int64_t clipMax = (1 << desc.attr_bitdepth) - 1;
int64_t residual0 = 0; int64_t residual0 = 0;
for (int k = 0; k < 3; ++k) { for (int k = 0; k < 3; ++k) {
const auto& q = quant[std::min(k, 1)]; const auto& q = quant[std::min(k, 1)];
const int64_t residual = divExp2RoundHalfUp( const int64_t residual = divExp2RoundHalfUp(
q.scale(UIntToInt(values[k])), kFixedPointAttributeShift); q.scale(UIntToInt(values[k])), kFixedPointAttributeShift);
const int64_t recon = predictedColor[k] + residual + residual0; const int64_t recon = predictedColor[k] + residual + residual0;
color[k] = attr_t(PCCClip(recon, int64_t(0), clipMax)); color[k] = attr_t(PCCClip(recon, int64_t(0), clipMax[k]));
if (!k && aps.inter_component_prediction_enabled_flag) if (!k && aps.inter_component_prediction_enabled_flag)
residual0 = residual; residual0 = residual;
...@@ -526,15 +529,18 @@ AttributeDecoder::decodeColorsRaht( ...@@ -526,15 +529,18 @@ AttributeDecoder::decodeColorsRaht(
aps.raht_prediction_enabled_flag, quantLayers, mortonCode, attributes, aps.raht_prediction_enabled_flag, quantLayers, mortonCode, attributes,
attribCount, voxelCount, coefficients); attribCount, voxelCount, coefficients);
const int clipMax = (1 << desc.attr_bitdepth) - 1; Vec3<int> clipMax{(1 << desc.attr_bitdepth) - 1,
(1 << desc.attr_bitdepth_secondary) - 1,
(1 << desc.attr_bitdepth_secondary) - 1};
for (int n = 0; n < voxelCount; n++) { for (int n = 0; n < voxelCount; n++) {
const int r = attributes[attribCount * n]; const int r = attributes[attribCount * n];
const int g = attributes[attribCount * n + 1]; const int g = attributes[attribCount * n + 1];
const int b = attributes[attribCount * n + 2]; const int b = attributes[attribCount * n + 2];
Vec3<attr_t> color; Vec3<attr_t> color;
color[0] = attr_t(PCCClip(r, 0, clipMax)); color[0] = attr_t(PCCClip(r, 0, clipMax[0]));
color[1] = attr_t(PCCClip(g, 0, clipMax)); color[1] = attr_t(PCCClip(g, 0, clipMax[1]));
color[2] = attr_t(PCCClip(b, 0, clipMax)); color[2] = attr_t(PCCClip(b, 0, clipMax[2]));
pointCloud.setColor(packedVoxel[n].index, color); pointCloud.setColor(packedVoxel[n].index, color);
} }
...@@ -631,13 +637,16 @@ AttributeDecoder::decodeColorsLift( ...@@ -631,13 +637,16 @@ AttributeDecoder::decodeColorsLift(
PCCLiftPredict(predictors, startIndex, endIndex, false, colors); PCCLiftPredict(predictors, startIndex, endIndex, false, colors);
} }
const int64_t clipMax = (1 << desc.attr_bitdepth) - 1; Vec3<int64_t> clipMax{(1 << desc.attr_bitdepth) - 1,
(1 << desc.attr_bitdepth_secondary) - 1,
(1 << desc.attr_bitdepth_secondary) - 1};
for (size_t f = 0; f < pointCount; ++f) { for (size_t f = 0; f < pointCount; ++f) {
const auto color0 = const auto color0 =
divExp2RoundHalfInf(colors[f], kFixedPointAttributeShift); divExp2RoundHalfInf(colors[f], kFixedPointAttributeShift);
Vec3<attr_t> color; Vec3<attr_t> color;
for (size_t d = 0; d < 3; ++d) { for (size_t d = 0; d < 3; ++d) {
color[d] = attr_t(PCCClip(color0[d], int64_t(0), clipMax)); color[d] = attr_t(PCCClip(color0[d], int64_t(0), clipMax[d]));
} }
pointCloud.setColor(indexesLOD[f], color); pointCloud.setColor(indexesLOD[f], color);
} }
......
...@@ -670,7 +670,10 @@ AttributeEncoder::encodeColorsPred( ...@@ -670,7 +670,10 @@ AttributeEncoder::encodeColorsPred(
buildPredictorsFast( buildPredictorsFast(
aps, pointCloud, 0, predictors, numberOfPointsPerLOD, indexesLOD); aps, pointCloud, 0, predictors, numberOfPointsPerLOD, indexesLOD);
const int64_t clipMax = (1ll << desc.attr_bitdepth) - 1; Vec3<int64_t> clipMax{(1 << desc.attr_bitdepth) - 1,
(1 << desc.attr_bitdepth_secondary) - 1,
(1 << desc.attr_bitdepth_secondary) - 1};
uint32_t values[3]; uint32_t values[3];
PCCResidualsEntropyEstimator context; PCCResidualsEntropyEstimator context;
int zero_cnt = 0; int zero_cnt = 0;
...@@ -720,7 +723,7 @@ AttributeEncoder::encodeColorsPred( ...@@ -720,7 +723,7 @@ AttributeEncoder::encodeColorsPred(
values[k] = uint32_t(IntToUInt(long(residualQ))); values[k] = uint32_t(IntToUInt(long(residualQ)));
int64_t recon = predictedColor[k] + residualR; int64_t recon = predictedColor[k] + residualR;
reconstructedColor[k] = attr_t(PCCClip(recon, int64_t(0), clipMax)); reconstructedColor[k] = attr_t(PCCClip(recon, int64_t(0), clipMax[k]));
} }
pointCloud.setColor(pointIndex, reconstructedColor); pointCloud.setColor(pointIndex, reconstructedColor);
...@@ -886,15 +889,18 @@ AttributeEncoder::encodeColorsTransformRaht( ...@@ -886,15 +889,18 @@ AttributeEncoder::encodeColorsTransformRaht(
} }
encoder.encodeZeroCnt(zero_cnt, voxelCount); encoder.encodeZeroCnt(zero_cnt, voxelCount);
const int clipMax = (1 << desc.attr_bitdepth) - 1; Vec3<int> clipMax{(1 << desc.attr_bitdepth) - 1,
(1 << desc.attr_bitdepth_secondary) - 1,
(1 << desc.attr_bitdepth_secondary) - 1};
for (int n = 0; n < voxelCount; n++) { for (int n = 0; n < voxelCount; n++) {
const int r = attributes[attribCount * n]; const int r = attributes[attribCount * n];
const int g = attributes[attribCount * n + 1]; const int g = attributes[attribCount * n + 1];
const int b = attributes[attribCount * n + 2]; const int b = attributes[attribCount * n + 2];
Vec3<attr_t> color; Vec3<attr_t> color;
color[0] = attr_t(PCCClip(r, 0, clipMax)); color[0] = attr_t(PCCClip(r, 0, clipMax[0]));
color[1] = attr_t(PCCClip(g, 0, clipMax)); color[1] = attr_t(PCCClip(g, 0, clipMax[1]));
color[2] = attr_t(PCCClip(b, 0, clipMax)); color[2] = attr_t(PCCClip(b, 0, clipMax[2]));
pointCloud.setColor(packedVoxel[n].index, color); pointCloud.setColor(packedVoxel[n].index, color);
} }
...@@ -996,13 +1002,16 @@ AttributeEncoder::encodeColorsLift( ...@@ -996,13 +1002,16 @@ AttributeEncoder::encodeColorsLift(
PCCLiftPredict(predictors, startIndex, endIndex, false, colors); PCCLiftPredict(predictors, startIndex, endIndex, false, colors);
} }
const int64_t clipMax = (1 << desc.attr_bitdepth) - 1; Vec3<int64_t> clipMax{(1 << desc.attr_bitdepth) - 1,
(1 << desc.attr_bitdepth_secondary) - 1,
(1 << desc.attr_bitdepth_secondary) - 1};
for (size_t f = 0; f < pointCount; ++f) { for (size_t f = 0; f < pointCount; ++f) {
const auto color0 = const auto color0 =
divExp2RoundHalfInf(colors[f], kFixedPointAttributeShift); divExp2RoundHalfInf(colors[f], kFixedPointAttributeShift);
Vec3<attr_t> color; Vec3<attr_t> color;
for (size_t d = 0; d < 3; ++d) { for (size_t d = 0; d < 3; ++d) {
color[d] = attr_t(PCCClip(color0[d], 0, clipMax)); color[d] = attr_t(PCCClip(color0[d], 0, clipMax[d]));
} }
pointCloud.setColor(indexesLOD[f], color); pointCloud.setColor(indexesLOD[f], color);
} }
......
...@@ -770,6 +770,11 @@ ParseParameters(int argc, char* argv[], Parameters& params) ...@@ -770,6 +770,11 @@ ParseParameters(int argc, char* argv[], Parameters& params)
attr_sps.attributeLabel = KnownAttributeLabel::kColour; attr_sps.attributeLabel = KnownAttributeLabel::kColour;
} }
// Derive the secondary bitdepth
// todo(df): this needs to be a command line argument
// -- but there are a few edge cases to handle
attr_sps.attr_bitdepth_secondary = attr_sps.attr_bitdepth;
bool isLifting = bool isLifting =
attr_aps.attr_encoding == AttributeEncoding::kPredictingTransform attr_aps.attr_encoding == AttributeEncoding::kPredictingTransform
|| attr_aps.attr_encoding == AttributeEncoding::kLiftingTransform; || attr_aps.attr_encoding == AttributeEncoding::kLiftingTransform;
...@@ -855,10 +860,8 @@ ParseParameters(int argc, char* argv[], Parameters& params) ...@@ -855,10 +860,8 @@ ParseParameters(int argc, char* argv[], Parameters& params)
if (attr_sps.attr_bitdepth > 16) if (attr_sps.attr_bitdepth > 16)
err.error() << it.first << ".bitdepth must be less than 17\n"; err.error() << it.first << ".bitdepth must be less than 17\n";
if (it.first == "reflectance") { if (attr_sps.attr_bitdepth_secondary > 16)
if (attr_sps.attr_bitdepth > 16) err.error() << it.first << ".bitdepth_secondary must be less than 17\n";
err.error() << it.first << ".bitdepth must be less than 17\n";
}
if (isLifting) { if (isLifting) {
int lod = attr_aps.num_detail_levels; int lod = attr_aps.num_detail_levels;
......
...@@ -166,6 +166,7 @@ struct AttributeDescription { ...@@ -166,6 +166,7 @@ struct AttributeDescription {
int attr_num_dimensions; int attr_num_dimensions;
int attr_instance_id; int attr_instance_id;
int attr_bitdepth; int attr_bitdepth;
int attr_bitdepth_secondary;
int cicp_colour_primaries_idx; int cicp_colour_primaries_idx;
int cicp_transfer_characteristics_idx; int cicp_transfer_characteristics_idx;
ColourMatrix cicp_matrix_coefficients_idx; ColourMatrix cicp_matrix_coefficients_idx;
......
...@@ -95,6 +95,7 @@ write(const SequenceParameterSet& sps) ...@@ -95,6 +95,7 @@ write(const SequenceParameterSet& sps)
bs.writeUe(attr.attr_num_dimensions); bs.writeUe(attr.attr_num_dimensions);
bs.writeUe(attr.attr_instance_id); bs.writeUe(attr.attr_instance_id);
bs.writeUe(attr.attr_bitdepth); bs.writeUe(attr.attr_bitdepth);
bs.writeUe(attr.attr_bitdepth_secondary);
bs.writeUe(attr.cicp_colour_primaries_idx); bs.writeUe(attr.cicp_colour_primaries_idx);
bs.writeUe(attr.cicp_transfer_characteristics_idx); bs.writeUe(attr.cicp_transfer_characteristics_idx);
bs.writeUe(attr.cicp_matrix_coefficients_idx); bs.writeUe(attr.cicp_matrix_coefficients_idx);
...@@ -156,6 +157,7 @@ parseSps(const PayloadBuffer& buf) ...@@ -156,6 +157,7 @@ parseSps(const PayloadBuffer& buf)
bs.readUe(&attr.attr_num_dimensions); bs.readUe(&attr.attr_num_dimensions);
bs.readUe(&attr.attr_instance_id); bs.readUe(&attr.attr_instance_id);
bs.readUe(&attr.attr_bitdepth); bs.readUe(&attr.attr_bitdepth);
bs.readUe(&attr.attr_bitdepth_secondary);
bs.readUe(&attr.cicp_colour_primaries_idx); bs.readUe(&attr.cicp_colour_primaries_idx);
bs.readUe(&attr.cicp_transfer_characteristics_idx); bs.readUe(&attr.cicp_transfer_characteristics_idx);
bs.readUe(&attr.cicp_matrix_coefficients_idx); bs.readUe(&attr.cicp_matrix_coefficients_idx);
......
...@@ -222,7 +222,9 @@ recolourColour( ...@@ -222,7 +222,9 @@ recolourColour(
std::vector<Vec3<attr_t>> refinedColors1; std::vector<Vec3<attr_t>> refinedColors1;
refinedColors1.resize(pointCountTarget); refinedColors1.resize(pointCountTarget);
double clipMax = (1 << attrDesc.attr_bitdepth) - 1; Vec3<double> clipMax{double((1 << attrDesc.attr_bitdepth) - 1),
double((1 << attrDesc.attr_bitdepth_secondary) - 1),
double((1 << attrDesc.attr_bitdepth_secondary) - 1)};
double maxGeometryDist2Fwd = params.maxGeometryDist2Fwd < 512 double maxGeometryDist2Fwd = params.maxGeometryDist2Fwd < 512
? params.maxGeometryDist2Fwd ? params.maxGeometryDist2Fwd
...@@ -322,7 +324,7 @@ recolourColour( ...@@ -322,7 +324,7 @@ recolourColour(
} }
for (int k = 0; k < 3; ++k) { for (int k = 0; k < 3; ++k) {
refinedColors1[index][k] = refinedColors1[index][k] =
attr_t(PCCClip(round(refinedColor[k]), 0.0, clipMax)); attr_t(PCCClip(round(refinedColor[k]), 0.0, clipMax[k]));
} }
isDone = true; isDone = true;
} }
...@@ -488,7 +490,7 @@ recolourColour( ...@@ -488,7 +490,7 @@ recolourColour(
Vec3<double> color0; Vec3<double> color0;
for (size_t k = 0; k < 3; ++k) { for (size_t k = 0; k < 3; ++k) {
color0[k] = PCCClip( color0[k] = PCCClip(
round(w * centroid1[k] + oneMinusW * centroid2[k]), 0.0, clipMax); round(w * centroid1[k] + oneMinusW * centroid2[k]), 0.0, clipMax[k]);
} }
const double rSource = 1.0 / double(pointCountSource); const double rSource = 1.0 / double(pointCountSource);
const double rTarget = 1.0 / double(pointCountTarget); const double rTarget = 1.0 / double(pointCountTarget);
...@@ -496,13 +498,13 @@ recolourColour( ...@@ -496,13 +498,13 @@ recolourColour(
Vec3<double> bestColor(color0); Vec3<double> bestColor(color0);
Vec3<double> color; Vec3<double> color;
for (int32_t s1 = -params.searchRange; s1 <= params.searchRange; ++s1) { for (int32_t s1 = -params.searchRange; s1 <= params.searchRange; ++s1) {
color[0] = PCCClip(color0[0] + s1, 0.0, clipMax); color[0] = PCCClip(color0[0] + s1, 0.0, clipMax[0]);
for (int32_t s2 = -params.searchRange; s2 <= params.searchRange; for (int32_t s2 = -params.searchRange; s2 <= params.searchRange;
++s2) { ++s2) {
color[1] = PCCClip(color0[1] + s2, 0.0, clipMax); color[1] = PCCClip(color0[1] + s2, 0.0, clipMax[1]);
for (int32_t s3 = -params.searchRange; s3 <= params.searchRange; for (int32_t s3 = -params.searchRange; s3 <= params.searchRange;
++s3) { ++s3) {
color[2] = PCCClip(color0[2] + s3, 0.0, clipMax); color[2] = PCCClip(color0[2] + s3, 0.0, clipMax[2]);
double e1 = 0.0; double e1 = 0.0;
for (size_t k = 0; k < 3; ++k) { for (size_t k = 0; k < 3; ++k) {
......
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