Commit 6b18730b authored by Noritaka Iguchi's avatar Noritaka Iguchi Committed by David Flynn
Browse files

attr/m49626: add region-wise quantization support for LoD coding

A per-slice region may be defined with a qp offset.  Points within
the region have an offset applied to the per-level QP.
parent 1654a45d
......@@ -189,7 +189,7 @@ AttributeDecoder::decode(
int abhSize;
AttributeBrickHeader abh = parseAbh(attr_aps, payload, &abhSize);
std::vector<Quantizers> quantLayers = deriveQuantizerLayers(attr_aps, abh);
QpSet qpSet = deriveQpSet(attr_aps, abh);
PCCResidualsDecoder decoder;
decoder.start(sps, payload.data() + abhSize, payload.size() - abhSize);
......@@ -197,34 +197,32 @@ AttributeDecoder::decode(
if (attr_desc.attr_num_dimensions == 1) {
switch (attr_aps.attr_encoding) {
case AttributeEncoding::kRAHTransform:
decodeReflectancesRaht(
attr_desc, attr_aps, quantLayers, decoder, pointCloud);
decodeReflectancesRaht(attr_desc, attr_aps, qpSet, decoder, pointCloud);
break;
case AttributeEncoding::kPredictingTransform:
decodeReflectancesPred(
attr_desc, attr_aps, quantLayers, decoder, pointCloud);
decodeReflectancesPred(attr_desc, attr_aps, qpSet, decoder, pointCloud);
break;
case AttributeEncoding::kLiftingTransform:
decodeReflectancesLift(
attr_desc, attr_aps, quantLayers, geom_num_points, minGeomNodeSizeLog2,
attr_desc, attr_aps, qpSet, geom_num_points, minGeomNodeSizeLog2,
decoder, pointCloud);
break;
}
} else if (attr_desc.attr_num_dimensions == 3) {
switch (attr_aps.attr_encoding) {
case AttributeEncoding::kRAHTransform:
decodeColorsRaht(attr_desc, attr_aps, quantLayers, decoder, pointCloud);
decodeColorsRaht(attr_desc, attr_aps, qpSet, decoder, pointCloud);
break;
case AttributeEncoding::kPredictingTransform:
decodeColorsPred(attr_desc, attr_aps, quantLayers, decoder, pointCloud);
decodeColorsPred(attr_desc, attr_aps, qpSet, decoder, pointCloud);
break;
case AttributeEncoding::kLiftingTransform:
decodeColorsLift(
attr_desc, attr_aps, quantLayers, geom_num_points, minGeomNodeSizeLog2,
attr_desc, attr_aps, qpSet, geom_num_points, minGeomNodeSizeLog2,
decoder, pointCloud);
break;
}
......@@ -277,7 +275,7 @@ void
AttributeDecoder::decodeReflectancesPred(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCResidualsDecoder& decoder,
PCCPointSet3& pointCloud)
{
......@@ -295,14 +293,14 @@ AttributeDecoder::decodeReflectancesPred(
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
quantLayer = std::min(int(qpSet.layers.size()) - 1, quantLayer + 1);
}
auto& quant = quantLayers[quantLayer];
const uint32_t pointIndex = indexesLOD[predictorIndex];
auto quant = qpSet.quantizers(pointCloud[pointIndex], quantLayer);
auto& predictor = predictors[predictorIndex];
computeReflectancePredictionWeights(
aps, pointCloud, indexesLOD, predictor, decoder);
const uint32_t pointIndex = indexesLOD[predictorIndex];
attr_t& reflectance = pointCloud.getReflectance(pointIndex);
uint32_t attValue0 = 0;
if (zero_cnt > 0) {
......@@ -365,7 +363,7 @@ void
AttributeDecoder::decodeColorsPred(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCResidualsDecoder& decoder,
PCCPointSet3& pointCloud)
{
......@@ -387,9 +385,10 @@ AttributeDecoder::decodeColorsPred(
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
quantLayer = std::min(int(qpSet.layers.size()) - 1, quantLayer + 1);
}
auto& quant = quantLayers[quantLayer];
const uint32_t pointIndex = indexesLOD[predictorIndex];
auto quant = qpSet.quantizers(pointCloud[pointIndex], quantLayer);
auto& predictor = predictors[predictorIndex];
computeColorPredictionWeights(
......@@ -401,7 +400,6 @@ AttributeDecoder::decodeColorsPred(
decoder.decode(values);
zero_cnt = decoder.decodeZeroCnt(pointCount);
}
const uint32_t pointIndex = indexesLOD[predictorIndex];
Vec3<attr_t>& color = pointCloud.getColor(pointIndex);
const Vec3<attr_t> predictedColor =
predictor.predictColor(pointCloud, indexesLOD);
......@@ -426,7 +424,7 @@ void
AttributeDecoder::decodeReflectancesRaht(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCResidualsDecoder& decoder,
PCCPointSet3& pointCloud)
{
......@@ -460,7 +458,7 @@ AttributeDecoder::decodeReflectancesRaht(
}
int* attributes = new int[attribCount * voxelCount];
auto quantLayers = qpSet.quantizerLayers();
regionAdaptiveHierarchicalInverseTransform(
aps.raht_prediction_enabled_flag, quantLayers, mortonCode, attributes,
attribCount, voxelCount, coefficients);
......@@ -486,7 +484,7 @@ void
AttributeDecoder::decodeColorsRaht(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCResidualsDecoder& decoder,
PCCPointSet3& pointCloud)
{
......@@ -524,7 +522,7 @@ AttributeDecoder::decodeColorsRaht(
}
int* attributes = new int[attribCount * voxelCount];
auto quantLayers = qpSet.quantizerLayers();
regionAdaptiveHierarchicalInverseTransform(
aps.raht_prediction_enabled_flag, quantLayers, mortonCode, attributes,
attribCount, voxelCount, coefficients);
......@@ -556,7 +554,7 @@ void
AttributeDecoder::decodeColorsLift(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
int geom_num_points,
int minGeomNodeSizeLog2,
PCCResidualsDecoder& decoder,
......@@ -603,9 +601,10 @@ AttributeDecoder::decodeColorsLift(
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
quantLayer = std::min(int(qpSet.layers.size()) - 1, quantLayer + 1);
}
auto& quant = quantLayers[quantLayer];
const uint32_t pointIndex = indexesLOD[predictorIndex];
auto quant = qpSet.quantizers(pointCloud[pointIndex], quantLayer);
uint32_t values[3];
if (zero_cnt > 0) {
......@@ -658,7 +657,7 @@ void
AttributeDecoder::decodeReflectancesLift(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
int geom_num_points,
int minGeomNodeSizeLog2,
PCCResidualsDecoder& decoder,
......@@ -705,9 +704,10 @@ AttributeDecoder::decodeReflectancesLift(
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
quantLayer = std::min(int(qpSet.layers.size()) - 1, quantLayer + 1);
}
auto& quant = quantLayers[quantLayer];
const uint32_t pointIndex = indexesLOD[predictorIndex];
auto quant = qpSet.quantizers(pointCloud[pointIndex], quantLayer);
int64_t detail = 0;
if (zero_cnt > 0) {
......
......@@ -67,7 +67,7 @@ protected:
void decodeReflectancesLift(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
int geom_num_points,
int minGeomNodeSizeLog2,
PCCResidualsDecoder& decoder,
......@@ -76,7 +76,7 @@ protected:
void decodeColorsLift(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
int geom_num_points,
int minGeomNodeSizeLog2,
PCCResidualsDecoder& decoder,
......@@ -85,28 +85,28 @@ protected:
void decodeReflectancesPred(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCResidualsDecoder& decoder,
PCCPointSet3& pointCloud);
void decodeColorsPred(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCResidualsDecoder& decoder,
PCCPointSet3& pointCloud);
void decodeReflectancesRaht(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCResidualsDecoder& decoder,
PCCPointSet3& pointCloud);
void decodeColorsRaht(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCResidualsDecoder& decoder,
PCCPointSet3& pointCloud);
......
......@@ -337,7 +337,7 @@ AttributeEncoder::encode(
PCCPointSet3& pointCloud,
PayloadBuffer* payload)
{
std::vector<Quantizers> quantLayers = deriveQuantizerLayers(attr_aps, abh);
QpSet qpSet = deriveQpSet(attr_aps, abh);
PCCResidualsEncoder encoder;
encoder.start(sps, int(pointCloud.getPointCount()));
......@@ -346,30 +346,29 @@ AttributeEncoder::encode(
switch (attr_aps.attr_encoding) {
case AttributeEncoding::kRAHTransform:
encodeReflectancesTransformRaht(
desc, attr_aps, quantLayers, pointCloud, encoder);
desc, attr_aps, qpSet, pointCloud, encoder);
break;
case AttributeEncoding::kPredictingTransform:
encodeReflectancesPred(desc, attr_aps, quantLayers, pointCloud, encoder);
encodeReflectancesPred(desc, attr_aps, qpSet, pointCloud, encoder);
break;
case AttributeEncoding::kLiftingTransform:
encodeReflectancesLift(desc, attr_aps, quantLayers, pointCloud, encoder);
encodeReflectancesLift(desc, attr_aps, qpSet, pointCloud, encoder);
break;
}
} else if (desc.attr_num_dimensions == 3) {
switch (attr_aps.attr_encoding) {
case AttributeEncoding::kRAHTransform:
encodeColorsTransformRaht(
desc, attr_aps, quantLayers, pointCloud, encoder);
encodeColorsTransformRaht(desc, attr_aps, qpSet, pointCloud, encoder);
break;
case AttributeEncoding::kPredictingTransform:
encodeColorsPred(desc, attr_aps, quantLayers, pointCloud, encoder);
encodeColorsPred(desc, attr_aps, qpSet, pointCloud, encoder);
break;
case AttributeEncoding::kLiftingTransform:
encodeColorsLift(desc, attr_aps, quantLayers, pointCloud, encoder);
encodeColorsLift(desc, attr_aps, qpSet, pointCloud, encoder);
break;
}
} else {
......@@ -472,7 +471,7 @@ void
AttributeEncoder::encodeReflectancesPred(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder)
{
......@@ -496,16 +495,16 @@ AttributeEncoder::encodeReflectancesPred(
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
quantLayer = std::min(int(qpSet.layers.size()) - 1, quantLayer + 1);
}
auto& quant = quantLayers[quantLayer];
const uint32_t pointIndex = indexesLOD[predictorIndex];
auto quant = qpSet.quantizers(pointCloud[pointIndex], quantLayer);
auto& predictor = predictors[predictorIndex];
computeReflectancePredictionWeights(
aps, pointCloud, indexesLOD, predictorIndex, predictor, encoder, context,
quant[0]);
const uint32_t pointIndex = indexesLOD[predictorIndex];
const uint64_t reflectance = pointCloud.getReflectance(pointIndex);
const attr_t predictedReflectance =
predictor.predictReflectance(pointCloud, indexesLOD);
......@@ -658,7 +657,7 @@ void
AttributeEncoder::encodeColorsPred(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder)
{
......@@ -682,20 +681,19 @@ AttributeEncoder::encodeColorsPred(
for (int i = 0; i < 3; i++) {
residual[i].resize(pointCount);
}
int quantLayer = 0;
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
quantLayer = std::min(int(qpSet.layers.size()) - 1, quantLayer + 1);
}
auto& quant = quantLayers[quantLayer];
const auto pointIndex = indexesLOD[predictorIndex];
auto quant = qpSet.quantizers(pointCloud[pointIndex], quantLayer);
auto& predictor = predictors[predictorIndex];
computeColorPredictionWeights(
aps, pointCloud, indexesLOD, predictorIndex, predictor, encoder, context,
quant);
const auto pointIndex = indexesLOD[predictorIndex];
const Vec3<attr_t> color = pointCloud.getColor(pointIndex);
const Vec3<attr_t> predictedColor =
predictor.predictColor(pointCloud, indexesLOD);
......@@ -770,7 +768,7 @@ void
AttributeEncoder::encodeReflectancesTransformRaht(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder)
{
......@@ -795,6 +793,7 @@ AttributeEncoder::encodeReflectancesTransformRaht(
attributes[attribCount * n] = reflectance;
}
auto quantLayers = qpSet.quantizerLayers();
// Transform.
regionAdaptiveHierarchicalTransform(
aps.raht_prediction_enabled_flag, quantLayers, mortonCode, attributes,
......@@ -838,7 +837,7 @@ void
AttributeEncoder::encodeColorsTransformRaht(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder)
{
......@@ -865,6 +864,7 @@ AttributeEncoder::encodeColorsTransformRaht(
attributes[attribCount * n + 2] = color[2];
}
auto quantLayers = qpSet.quantizerLayers();
// Transform.
regionAdaptiveHierarchicalTransform(
aps.raht_prediction_enabled_flag, quantLayers, mortonCode, attributes,
......@@ -915,7 +915,7 @@ void
AttributeEncoder::encodeColorsLift(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder)
{
......@@ -963,9 +963,10 @@ AttributeEncoder::encodeColorsLift(
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
quantLayer = std::min(int(qpSet.layers.size()) - 1, quantLayer + 1);
}
auto& quant = quantLayers[quantLayer];
const auto pointIndex = indexesLOD[predictorIndex];
auto quant = qpSet.quantizers(pointCloud[pointIndex], quantLayer);
const int64_t quantWeight = weights[predictorIndex];
auto& color = colors[predictorIndex];
......@@ -1023,7 +1024,7 @@ void
AttributeEncoder::encodeReflectancesLift(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder)
{
......@@ -1071,9 +1072,10 @@ AttributeEncoder::encodeReflectancesLift(
for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) {
if (predictorIndex == numberOfPointsPerLOD[quantLayer]) {
quantLayer = std::min(int(quantLayers.size()) - 1, quantLayer + 1);
quantLayer = std::min(int(qpSet.layers.size()) - 1, quantLayer + 1);
}
auto& quant = quantLayers[quantLayer];
const auto pointIndex = indexesLOD[predictorIndex];
auto quant = qpSet.quantizers(pointCloud[pointIndex], quantLayer);
const int64_t quantWeight = weights[predictorIndex];
auto& reflectance = reflectances[predictorIndex];
......
......@@ -68,42 +68,42 @@ protected:
void encodeReflectancesLift(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder);
void encodeColorsLift(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder);
void encodeReflectancesPred(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder);
void encodeColorsPred(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder);
void encodeReflectancesTransformRaht(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder);
void encodeColorsTransformRaht(
const AttributeDescription& desc,
const AttributeParameterSet& aps,
const std::vector<Quantizers>& quantLayers,
const QpSet& qpSet,
PCCPointSet3& pointCloud,
PCCResidualsEncoder& encoder);
......
......@@ -409,6 +409,11 @@ PCCTMC3Encoder3::compressPartition(
abh.attr_layer_qp_delta_luma = attr_enc.abh.attr_layer_qp_delta_luma;
abh.attr_layer_qp_delta_chroma = attr_enc.abh.attr_layer_qp_delta_chroma;
abh.attr_region_qp_present_flag = false;
abh.attr_region_qp_origin = Vec3<int>{0};
abh.attr_region_qp_whd = Vec3<int>{0};
abh.attr_region_qp_delta = 0;
write(attr_aps, abh, &payload);
AttributeEncoder attrEncoder;
......
......@@ -343,6 +343,11 @@ struct AttributeBrickHeader {
{
return !attr_layer_qp_delta_luma.empty();
}
Vec3<int> attr_region_qp_origin;
Vec3<int> attr_region_qp_whd;
int attr_region_qp_delta;
bool attr_region_qp_present_flag;
};
//============================================================================
......
......@@ -512,6 +512,16 @@ write(
}
}
bs.write(abh.attr_region_qp_present_flag);
if (abh.attr_region_qp_present_flag) {
bs.writeUe(abh.attr_region_qp_origin.x());
bs.writeUe(abh.attr_region_qp_origin.y());
bs.writeUe(abh.attr_region_qp_origin.z());
bs.writeUe(abh.attr_region_qp_whd.x());
bs.writeUe(abh.attr_region_qp_whd.y());
bs.writeUe(abh.attr_region_qp_whd.z());
bs.writeSe(abh.attr_region_qp_delta);
}
bs.byteAlign();
}
......@@ -568,6 +578,17 @@ parseAbh(
}
}
bs.read(&abh.attr_region_qp_present_flag);
if (abh.attr_region_qp_present_flag) {
bs.readUe(&abh.attr_region_qp_origin.x());
bs.readUe(&abh.attr_region_qp_origin.y());
bs.readUe(&abh.attr_region_qp_origin.z());
bs.readUe(&abh.attr_region_qp_whd.x());
bs.readUe(&abh.attr_region_qp_whd.y());
bs.readUe(&abh.attr_region_qp_whd.z());
bs.readSe(&abh.attr_region_qp_delta);
}
bs.byteAlign();
if (bytesRead)
......
......@@ -45,6 +45,7 @@ namespace pcc {
Quantizer::Quantizer(int qp)
{
qp = std::max(qp, 4);
int qpShift = qp / 6;
_stepSize = kQpStep[qp % 6] << qpShift;
_stepSizeRecip = kQpStepRecip[qp % 6] >> qpShift;
......@@ -52,8 +53,8 @@ Quantizer::Quantizer(int qp)
//============================================================================
Quantizers
deriveQuantizers(
Qps
deriveQps(
const AttributeParameterSet& attr_aps,
const AttributeBrickHeader& abh,
int qpLayer)
......@@ -77,29 +78,27 @@ deriveQuantizers(
if (abh.attr_layer_qp_present_flag()) {
sliceQpLuma += abh.attr_layer_qp_delta_luma[qpLayer];
sliceQpChroma += abh.attr_layer_qp_delta_chroma[qpLayer];
sliceQpLuma = std::max(sliceQpLuma, 4);
sliceQpChroma = std::max(sliceQpChroma, 4);
}
return {Quantizer{sliceQpLuma}, Quantizer{sliceQpChroma}};
return {sliceQpLuma, sliceQpChroma};
}
//============================================================================
std::vector<Quantizers>
deriveQuantizerLayers(
QpLayers
deriveLayerQps(
const AttributeParameterSet& attr_aps, const AttributeBrickHeader& abh)
{
std::vector<Quantizers> layers;
QpLayers layers;
layers.push_back(deriveQuantizers(attr_aps, abh, 0));
layers.push_back(deriveQps(attr_aps, abh, 0));
if (abh.attr_layer_qp_present_flag()) {
int numLayers = attr_aps.attr_encoding == AttributeEncoding::kRAHTransform
? attr_aps.raht_depth + 1
: attr_aps.num_detail_levels + 1;
for (int layer = 1; layer < numLayers; layer++) {
layers.push_back(deriveQuantizers(attr_aps, abh, layer));
layers.push_back(deriveQps(attr_aps, abh, layer));
}
}
......@@ -108,4 +107,57 @@ deriveQuantizerLayers(
//============================================================================
QpRegionOffset
deriveQpRegions(
const AttributeParameterSet& attr_aps, const AttributeBrickHeader& abh)
{
QpRegionOffset qpRegionOffset;
qpRegionOffset.valid = abh.attr_region_qp_present_flag;
if (qpRegionOffset.valid) {
qpRegionOffset.qpOffset = abh.attr_region_qp_delta;
for (int i = 0; i < 3; i++) {
qpRegionOffset.region.min[i] = abh.attr_region_qp_origin[i];
qpRegionOffset.region.max[i] =
abh.attr_region_qp_origin[i] + abh.attr_region_qp_whd[i];
}
}
return qpRegionOffset;
}
//============================================================================
QpSet
deriveQpSet(
const AttributeParameterSet& attr_aps, const AttributeBrickHeader& abh)
{
return {deriveLayerQps(attr_aps, abh), deriveQpRegions(attr_aps, abh)};
}