Commit 5181146c authored by David Flynn's avatar David Flynn
Browse files

geometry: add GeometryCodecType to select geometry coding method

This commit aims to reduce the overload on the --mode option and to
restore it to the previous encode/decode functionality.  To this end,
a new option (--geometryCodec=...) is added that selects the geometry
codec.

Version v1.0 use of --mode=... is supported.
parent 7f3f66f2
...@@ -49,6 +49,16 @@ const uint32_t PCCTMC3MaxPredictionNearestNeighborCount = 4; ...@@ -49,6 +49,16 @@ const uint32_t PCCTMC3MaxPredictionNearestNeighborCount = 4;
const int MAX_NUM_DM_LEAF_POINTS = 2; const int MAX_NUM_DM_LEAF_POINTS = 2;
// Describes the geometry coding method.
enum class GeometryCodecType {
// No geometry coding is performed (geometry is known a priori)
kBypass = 0,
// TMC3 lossless geometry codec using ocrees
kOctree = 1,
// TMC1 octree + triangulation
kTriSoup = 2,
};
enum class TransformType { enum class TransformType {
kIntegerLift = 0, kIntegerLift = 0,
kRAHT = 1 kRAHT = 1
......
...@@ -56,6 +56,9 @@ ...@@ -56,6 +56,9 @@
namespace pcc { namespace pcc {
struct PCCTMC3Encoder3Parameters { struct PCCTMC3Encoder3Parameters {
// The method used for geometry coding.
GeometryCodecType geometryCodec;
double positionQuantizationScale; double positionQuantizationScale;
bool mergeDuplicatedPoints; bool mergeDuplicatedPoints;
......
...@@ -97,6 +97,11 @@ static std::istream& operator>>(std::istream &in, TransformType &val) { ...@@ -97,6 +97,11 @@ static std::istream& operator>>(std::istream &in, TransformType &val) {
return readUInt(in, val); return readUInt(in, val);
}} }}
namespace pcc {
static std::istream& operator>>(std::istream &in, GeometryCodecType &val) {
return readUInt(in, val);
}}
namespace pcc { namespace pcc {
static std::ostream& operator<<(std::ostream &out, const TransformType &val) { static std::ostream& operator<<(std::ostream &out, const TransformType &val) {
switch (val) { switch (val) {
...@@ -106,6 +111,16 @@ static std::ostream& operator<<(std::ostream &out, const TransformType &val) { ...@@ -106,6 +111,16 @@ static std::ostream& operator<<(std::ostream &out, const TransformType &val) {
return out; return out;
}} }}
namespace pcc {
static std::ostream& operator<<(std::ostream &out, const GeometryCodecType &val) {
switch (val) {
case GeometryCodecType::kBypass: out << "0 (Bypass)"; break;
case GeometryCodecType::kOctree: out << "1 (TMC1 Octree)"; break;
case GeometryCodecType::kTriSoup: out << "2 (TMC3 TriSoup)"; break;
}
return out;
}}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// :: Command line / config parsing // :: Command line / config parsing
...@@ -145,10 +160,9 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) { ...@@ -145,10 +160,9 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) {
"The encoding/decoding mode:\n" "The encoding/decoding mode:\n"
" 0: encode\n" " 0: encode\n"
" 1: decode\n" " 1: decode\n"
// NB: the following forms are deprecated
" 2: encode with lossless geometry\n" " 2: encode with lossless geometry\n"
" 3: decode with lossless geometry\n" " 3: decode with lossless geometry")
" 4: encode with trisoup geometry\n"
" 5: decode with trisoup geoemtry")
// i/o parameters // i/o parameters
("reconstructedDataPath", ("reconstructedDataPath",
...@@ -183,6 +197,13 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) { ...@@ -183,6 +197,13 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) {
"todo(kmammou)") "todo(kmammou)")
// tools // tools
("geometryCodec",
params.encodeParameters.geometryCodec, GeometryCodecType::kOctree,
"Controls the method used to encode geometry:"
" 0: bypass (a priori)\n"
" 1: octree (TMC3)\n"
" 2: trisoup (TMC1)")
("neighbourContextualisation", ("neighbourContextualisation",
params.encodeParameters.neighbourContextsEnabled, true, params.encodeParameters.neighbourContextsEnabled, true,
"Contextualise geometry octree occupancy based on neighbour patterns") "Contextualise geometry octree occupancy based on neighbour patterns")
...@@ -270,10 +291,20 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) { ...@@ -270,10 +291,20 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) {
return false; return false;
} }
// Set GeometryCodecType according to codec mode
// NB: for bypass, the decoder must load the a priori geometry
if (params.mode == 2 || params.mode == 3) {
params.encodeParameters.geometryCodec = GeometryCodecType::kBypass;
}
if (params.mode == 4) {
params.encodeParameters.geometryCodec = GeometryCodecType::kTriSoup;
}
// Restore params.mode to be encode vs decode
params.mode = CodecMode(params.mode & 1);
// For trisoup, ensure that positionQuantizationScale is the exact inverse of intToOrigScale. // For trisoup, ensure that positionQuantizationScale is the exact inverse of intToOrigScale.
if (params.mode == 4 && if (params.encodeParameters.geometryCodec == GeometryCodecType::kTriSoup) {
params.encodeParameters.positionQuantizationScale !=
1.0 / params.encodeParameters.triSoup.intToOrigScale) {
params.encodeParameters.positionQuantizationScale = params.encodeParameters.positionQuantizationScale =
1.0 / params.encodeParameters.triSoup.intToOrigScale; 1.0 / params.encodeParameters.triSoup.intToOrigScale;
} }
...@@ -314,10 +345,7 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) { ...@@ -314,10 +345,7 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) {
// check required arguments are specified // check required arguments are specified
const bool encode = const bool encode = params.mode == CODEC_MODE_ENCODE;
params.mode == CODEC_MODE_ENCODE
|| params.mode == CODEC_MODE_ENCODE_LOSSLESS_GEOMETRY
|| params.mode == CODEC_MODE_ENCODE_TRISOUP_GEOMETRY;
if (encode && params.uncompressedDataPath.empty()) if (encode && params.uncompressedDataPath.empty())
err.error() << "uncompressedDataPath not set\n"; err.error() << "uncompressedDataPath not set\n";
...@@ -330,7 +358,7 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) { ...@@ -330,7 +358,7 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) {
// currently the attributes with lossless geometry require the source data // currently the attributes with lossless geometry require the source data
// todo(?): remove this dependency by improving reporting // todo(?): remove this dependency by improving reporting
if (params.mode == CODEC_MODE_DECODE_LOSSLESS_GEOMETRY if (params.encodeParameters.geometryCodec == GeometryCodecType::kBypass
&& params.uncompressedDataPath.empty()) && params.uncompressedDataPath.empty())
err.error() << "uncompressedDataPath not set\n"; err.error() << "uncompressedDataPath not set\n";
...@@ -340,32 +368,32 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) { ...@@ -340,32 +368,32 @@ bool ParseParameters(int argc, char *argv[], Parameters &params) {
return false; return false;
cout << "+ Parameters" << endl; cout << "+ Parameters" << endl;
cout << "\t mode ";
if (params.mode == CODEC_MODE_ENCODE) { if (params.mode == CODEC_MODE_ENCODE) {
cout << "encode" << endl; cout << "\t mode encode\n";
} else if (params.mode == CODEC_MODE_ENCODE_LOSSLESS_GEOMETRY) {
cout << "encode with lossless geometry" << endl;
} else if (params.mode == CODEC_MODE_ENCODE_TRISOUP_GEOMETRY) {
cout << "encode with trisoup geometry" << endl;
} else if (params.mode == CODEC_MODE_DECODE) { } else if (params.mode == CODEC_MODE_DECODE) {
cout << "decode" << endl; cout << "\t mode decode\n";
} else if (params.mode == CODEC_MODE_DECODE_LOSSLESS_GEOMETRY) {
cout << "decode with lossless geometry" << endl;
} else if (params.mode == CODEC_MODE_DECODE_TRISOUP_GEOMETRY) {
cout << "decode with trisoup geometry" << endl;
} }
cout << "\t uncompressedDataPath " << params.uncompressedDataPath << endl; cout << "\t uncompressedDataPath " << params.uncompressedDataPath << endl;
cout << "\t compressedStreamPath " << params.compressedStreamPath << endl; cout << "\t compressedStreamPath " << params.compressedStreamPath << endl;
cout << "\t reconstructedDataPath " << params.reconstructedDataPath << endl; cout << "\t reconstructedDataPath " << params.reconstructedDataPath << endl;
cout << "\t colorTransform " << params.colorTransform << endl; cout << "\t colorTransform " << params.colorTransform << endl;
if (encode) { if (encode) {
cout << "\t mergeDuplicatedPoints " << params.encodeParameters.mergeDuplicatedPoints cout << "\t geometryCodec "
<< endl; << params.encodeParameters.geometryCodec << endl;
cout << "\t positionQuantizationScale " << params.encodeParameters.positionQuantizationScale cout << "\t positionQuantizationScale " << params.encodeParameters.positionQuantizationScale
<< endl; << endl;
cout << "\t neighbourContextualisation " << params.encodeParameters.neighbourContextsEnabled
<< endl; if (params.encodeParameters.geometryCodec == GeometryCodecType::kOctree) {
if (params.mode == CODEC_MODE_ENCODE_TRISOUP_GEOMETRY) { cout << "\t mergeDuplicatedPoints "
<< params.encodeParameters.mergeDuplicatedPoints << '\n';
cout << "\t neighbourContextualisation "
<< params.encodeParameters.neighbourContextsEnabled << '\n';
cout << "\t inferredDirectCodingMode "
<< params.encodeParameters.inferredDirectCodingModeEnabled << '\n';
}
if (params.encodeParameters.geometryCodec == GeometryCodecType::kTriSoup) {
cout << "\t triSoupDepth " << params.encodeParameters.triSoup.depth << endl; cout << "\t triSoupDepth " << params.encodeParameters.triSoup.depth << endl;
cout << "\t triSoupLevel " << params.encodeParameters.triSoup.level << endl; cout << "\t triSoupLevel " << params.encodeParameters.triSoup.level << endl;
cout << "\t triSoupIntToOrigScale " << params.encodeParameters.triSoup.intToOrigScale << endl; cout << "\t triSoupIntToOrigScale " << params.encodeParameters.triSoup.intToOrigScale << endl;
...@@ -440,15 +468,20 @@ int Compress(const Parameters &params, Stopwatch& clock) { ...@@ -440,15 +468,20 @@ int Compress(const Parameters &params, Stopwatch& clock) {
reconstructedPointCloud.reset(new PCCPointSet3); reconstructedPointCloud.reset(new PCCPointSet3);
} }
if ((params.mode == CODEC_MODE_ENCODE && int ret;
encoder.compress(pointCloud, params.encodeParameters, bitstream, if (params.encodeParameters.geometryCodec == GeometryCodecType::kOctree)
reconstructedPointCloud.get())) || ret = encoder.compress(
(params.mode == CODEC_MODE_ENCODE_LOSSLESS_GEOMETRY && pointCloud, params.encodeParameters, bitstream,
encoder.compressWithLosslessGeometry(pointCloud, params.encodeParameters, bitstream, reconstructedPointCloud.get());
reconstructedPointCloud.get())) || if (params.encodeParameters.geometryCodec == GeometryCodecType::kBypass)
(params.mode == CODEC_MODE_ENCODE_TRISOUP_GEOMETRY && ret = encoder.compressWithLosslessGeometry(
encoder.compressWithTrisoupGeometry(pointCloud, params.encodeParameters, bitstream, pointCloud, params.encodeParameters, bitstream,
reconstructedPointCloud.get()))) { reconstructedPointCloud.get());
if (params.encodeParameters.geometryCodec == GeometryCodecType::kTriSoup)
ret = encoder.compressWithTrisoupGeometry(
pointCloud, params.encodeParameters, bitstream,
reconstructedPointCloud.get());
if (ret) {
cout << "Error: can't compress point cloud!" << endl; cout << "Error: can't compress point cloud!" << endl;
return -1; return -1;
} }
...@@ -496,7 +529,9 @@ int Decompress(const Parameters &params, Stopwatch &clock) { ...@@ -496,7 +529,9 @@ int Decompress(const Parameters &params, Stopwatch &clock) {
PCCTMC3Decoder3 decoder; PCCTMC3Decoder3 decoder;
PCCPointSet3 pointCloud; PCCPointSet3 pointCloud;
if (params.mode == CODEC_MODE_DECODE_LOSSLESS_GEOMETRY) { // read geometry from input file
// read a priori geometry from input file for bypass case
if (params.encodeParameters.geometryCodec == GeometryCodecType::kBypass) {
if (!pointCloud.read(params.uncompressedDataPath) || pointCloud.getPointCount() == 0) { if (!pointCloud.read(params.uncompressedDataPath) || pointCloud.getPointCount() == 0) {
cout << "Error: can't open input file!" << endl; cout << "Error: can't open input file!" << endl;
return -1; return -1;
...@@ -505,11 +540,17 @@ int Decompress(const Parameters &params, Stopwatch &clock) { ...@@ -505,11 +540,17 @@ int Decompress(const Parameters &params, Stopwatch &clock) {
pointCloud.removeColors(); pointCloud.removeColors();
} }
if ((params.mode == CODEC_MODE_DECODE && decoder.decompress(bitstream, pointCloud, params.roundOutputPositions)) || int ret;
(params.mode == CODEC_MODE_DECODE_LOSSLESS_GEOMETRY && if (params.encodeParameters.geometryCodec == GeometryCodecType::kOctree)
decoder.decompressWithLosslessGeometry(bitstream, pointCloud)) || ret = decoder.decompress(
(params.mode == CODEC_MODE_DECODE_TRISOUP_GEOMETRY && bitstream, pointCloud, params.roundOutputPositions);
decoder.decompressWithTrisoupGeometry(bitstream, pointCloud, params.roundOutputPositions))) { if (params.encodeParameters.geometryCodec == GeometryCodecType::kBypass)
ret = decoder.decompressWithLosslessGeometry(
bitstream, pointCloud);
if (params.encodeParameters.geometryCodec == GeometryCodecType::kTriSoup)
ret = decoder.decompressWithTrisoupGeometry(
bitstream, pointCloud, params.roundOutputPositions);
if (ret) {
cout << "Error: can't decompress point cloud!" << endl; cout << "Error: can't decompress point cloud!" << endl;
return -1; return -1;
} }
......
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