Commit 0eab32df authored by Hyejung Hur's avatar Hyejung Hur Committed by David Flynn
Browse files

attr/m51092: reuse lods between attributes of same slice

This commit enables sharing of LoDs between attributes of the same
slice if certain preconditions are met.
parent 4a73572f
......@@ -57,6 +57,9 @@ public:
int minGeomNodeSizeLog2,
const PayloadBuffer&,
PCCPointSet3& pointCloud) = 0;
// Indicates if the attribute decoder can decode the given aps
virtual bool isReusable(const AttributeParameterSet& aps) const = 0;
};
//----------------------------------------------------------------------------
......@@ -76,6 +79,9 @@ public:
const AttributeBrickHeader& abh,
PCCPointSet3& pointCloud,
PayloadBuffer* payload) = 0;
// Indicates if the attribute decoder can decode the given aps
virtual bool isReusable(const AttributeParameterSet& aps) const = 0;
};
//----------------------------------------------------------------------------
......
......@@ -48,6 +48,8 @@ AttributeLods::generate(
int minGeomNodeSizeLog2,
const PCCPointSet3& cloud)
{
_aps = aps;
if (minGeomNodeSizeLog2 > 0)
assert(aps.scalable_lifting_enabled_flag);
......@@ -59,6 +61,44 @@ AttributeLods::generate(
predictor.computeWeights();
}
//----------------------------------------------------------------------------
bool
AttributeLods::isReusable(const AttributeParameterSet& aps) const
{
if (numPointsInLod.empty())
return true;
if (_aps.lod_decimation_enabled_flag != aps.lod_decimation_enabled_flag)
return false;
if (_aps.num_pred_nearest_neighbours != aps.num_pred_nearest_neighbours)
return false;
if (_aps.search_range != aps.search_range)
return false;
if (_aps.lod_neigh_bias != aps.lod_neigh_bias)
return false;
if (
_aps.intra_lod_prediction_enabled_flag
!= aps.intra_lod_prediction_enabled_flag)
return false;
if (_aps.num_detail_levels != aps.num_detail_levels)
return false;
if (_aps.dist2 != aps.dist2)
return false;
// until this feature is stable, always generate LoDs.
if (_aps.scalable_lifting_enabled_flag || aps.scalable_lifting_enabled_flag)
return false;
return true;
}
//============================================================================
} // namespace pcc
......@@ -46,6 +46,9 @@ namespace pcc {
//============================================================================
struct AttributeLods {
// Indicates if the generated LoDs are compatible with the provided aps
bool isReusable(const AttributeParameterSet& aps) const;
bool empty() const { return numPointsInLod.empty(); };
void generate(
......@@ -56,6 +59,11 @@ struct AttributeLods {
std::vector<PCCPredictor> predictors;
std::vector<uint32_t> numPointsInLod;
std::vector<uint32_t> indexes;
private:
// This is the aps that was used to generate the LoDs. It is used to check
// if the generated LoDs are reusable.
AttributeParameterSet _aps;
};
//============================================================================
......
......@@ -260,6 +260,14 @@ AttributeDecoder::decode(
//----------------------------------------------------------------------------
bool
AttributeDecoder::isReusable(const AttributeParameterSet& aps) const
{
return _lods.isReusable(aps);
}
//----------------------------------------------------------------------------
void
AttributeDecoder::computeReflectancePredictionWeights(
const AttributeParameterSet& aps,
......
......@@ -63,6 +63,8 @@ public:
const PayloadBuffer&,
PCCPointSet3& pointCloud) override;
bool isReusable(const AttributeParameterSet& aps) const override;
protected:
// todo(df): consider alternative encapsulation
......
......@@ -406,6 +406,14 @@ AttributeEncoder::encode(
//----------------------------------------------------------------------------
bool
AttributeEncoder::isReusable(const AttributeParameterSet& aps) const
{
return _lods.isReusable(aps);
}
//----------------------------------------------------------------------------
int64_t
AttributeEncoder::computeReflectanceResidual(
const uint64_t reflectance,
......
......@@ -64,6 +64,8 @@ public:
PCCPointSet3& pointCloud,
PayloadBuffer* payload) override;
bool isReusable(const AttributeParameterSet& aps) const override;
protected:
// todo(df): consider alternative encapsulation
......
......@@ -38,6 +38,7 @@
#include <functional>
#include <map>
#include "Attribute.h"
#include "PayloadBuffer.h"
#include "PCCMath.h"
#include "PCCPointSet.h"
......@@ -124,6 +125,9 @@ private:
const GeometryParameterSet* _gps;
GeometryBrickHeader _gbh;
// Attribute decoder for reuse between attributes of same slice
std::unique_ptr<AttributeDecoderIntf> _attrDecoder;
};
//----------------------------------------------------------------------------
......
......@@ -38,7 +38,6 @@
#include <cassert>
#include <string>
#include "Attribute.h"
#include "PayloadBuffer.h"
#include "PCCPointSet.h"
#include "geometry.h"
......@@ -110,6 +109,7 @@ PCCTMC3Decoder3::decompress(
callback->onOutputCloud(*_sps, _accumCloud);
_accumCloud.clear();
_currentFrameIdx = -1;
_attrDecoder.reset();
return 0;
case PayloadType::kGeometryBrick:
......@@ -118,6 +118,9 @@ PCCTMC3Decoder3::decompress(
callback->onOutputCloud(*_sps, _accumCloud);
_accumCloud.clear();
}
// avoid accidents with stale attribute decoder on next slice
_attrDecoder.reset();
return decodeGeometryBrick(*buf);
case PayloadType::kAttributeBrick: decodeAttributeBrick(*buf); return 0;
......@@ -283,11 +286,14 @@ PCCTMC3Decoder3::decodeAttributeBrick(const PayloadBuffer& buf)
const auto& attr_sps = _sps->attributeSets[abh.attr_sps_attr_idx];
const auto& label = attr_sps.attributeLabel;
auto attrDecoder = makeAttributeDecoder();
pcc::chrono::Stopwatch<pcc::chrono::utime_inc_children_clock> clock_user;
// replace the attribute decoder if not compatible
if (!_attrDecoder || !_attrDecoder->isReusable(attr_aps))
_attrDecoder = makeAttributeDecoder();
clock_user.start();
attrDecoder->decode(
_attrDecoder->decode(
*_sps, attr_sps, attr_aps, _gbh.geom_num_points,
_params.minGeomNodeSizeLog2, buf, _currentPointCloud);
clock_user.stop();
......
......@@ -389,6 +389,7 @@ PCCTMC3Encoder3::compressPartition(
callback->onPostRecolour(pointCloud);
// attributeCoding
auto attrEncoder = makeAttributeEncoder();
// for each attribute
for (const auto& it : params->attributeIdxMap) {
......@@ -420,7 +421,10 @@ PCCTMC3Encoder3::compressPartition(
write(attr_aps, abh, &payload);
auto attrEncoder = makeAttributeEncoder();
// replace the attribute encoder if not compatible
if (!attrEncoder->isReusable(attr_aps))
attrEncoder = makeAttributeEncoder();
attrEncoder->encode(*_sps, attr_sps, attr_aps, abh, pointCloud, &payload);
clock_user.stop();
......
......@@ -342,6 +342,7 @@ struct GeometryBrickHeader {
};
//============================================================================
// NB: when updating this, remember to update AttributeLods::isReusable(...)
struct AttributeParameterSet {
int aps_attr_parameter_set_id;
......
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