Commit 952112c4 authored by David Flynn's avatar David Flynn
Browse files

geom: refactor/isolate geometry brick coding

This commit splits the handling of the geometry brick header and octree
geometry coding.  The encoder/decoder classes now take care of coding
the header, while the geometry coder handles the geometry coding itself.
parent a9d066e6
......@@ -71,6 +71,7 @@ file(GLOB PROJECT_INC_FILES
"RAHT.h"
"TMC3.h"
"constants.h"
"geometry.h"
"geometry_octree.h"
"hls.h"
"io_hls.h"
......
......@@ -79,7 +79,6 @@ private:
int decodeGeometryBrick(const PayloadBuffer& buf);
void decodeAttributeBrick(const PayloadBuffer& buf);
int decodeTrisoup(const PayloadBuffer& buf, PCCPointSet3& pointCloud);
void decodePositions(const PayloadBuffer& buf, PCCPointSet3& pointCloud);
//==========================================================================
......
......@@ -82,7 +82,7 @@ public:
private:
void reconstructedPointCloud(PCCPointSet3* reconstructedCloud);
void encodePositions(PayloadBuffer* buf);
void encodeGeometryBrick(PayloadBuffer* buf);
int encodeTrisoup(bool hasColor, bool hasReflectance, PayloadBuffer* buf);
......
......@@ -41,6 +41,7 @@
#include "AttributeDecoder.h"
#include "PayloadBuffer.h"
#include "PCCPointSet.h"
#include "geometry.h"
#include "io_hls.h"
#include "io_tlv.h"
#include "pcc_chrono.h"
......@@ -159,13 +160,27 @@ PCCTMC3Decoder3::decodeGeometryBrick(const PayloadBuffer& buf)
pcc::chrono::Stopwatch<pcc::chrono::utime_inc_children_clock> clock_user;
clock_user.start();
int gbhSize;
GeometryBrickHeader gbh = parseGbh(*_gps, buf, &gbhSize);
minPositions.x() = gbh.geomBoxOrigin.x();
minPositions.y() = gbh.geomBoxOrigin.y();
minPositions.z() = gbh.geomBoxOrigin.z();
o3dgc::Arithmetic_Codec arithmeticDecoder(
int(buf.size()) - gbhSize,
reinterpret_cast<uint8_t*>(const_cast<char*>(buf.data() + gbhSize)));
arithmeticDecoder.start_decoder();
if (_gps->geom_codec_type == GeometryCodecType::kOctree) {
decodePositions(buf, _currentPointCloud);
_currentPointCloud.resize(gbh.geom_num_points);
decodeGeometryOctree(*_gps, gbh, _currentPointCloud, &arithmeticDecoder);
}
if (_gps->geom_codec_type == GeometryCodecType::kTriSoup) {
if (decodeTrisoup(buf, _currentPointCloud))
return -1;
}
arithmeticDecoder.stop_decoder();
clock_user.stop();
auto total_user =
......
......@@ -40,6 +40,7 @@
#include "AttributeEncoder.h"
#include "PCCPointSetProcessing.h"
#include "geometry.h"
#include "io_hls.h"
#include "osspecific.h"
#include "pcc_chrono.h"
......@@ -157,7 +158,7 @@ PCCTMC3Encoder3::compress(
clock_user.start();
if (_gps->geom_codec_type == GeometryCodecType::kOctree) {
encodePositions(&payload);
encodeGeometryBrick(&payload);
}
if (_gps->geom_codec_type == GeometryCodecType::kTriSoup) {
bool hasColor = inputPointCloud.hasColors();
......@@ -245,6 +246,42 @@ PCCTMC3Encoder3::compress(
//----------------------------------------------------------------------------
void
PCCTMC3Encoder3::encodeGeometryBrick(PayloadBuffer* buf)
{
// todo(df): confirm minimum of 1 isn't needed
uint32_t maxBB =
std::max({1u, boundingBox.max[0], boundingBox.max[1], boundingBox.max[2]});
// the current node dimension (log2) encompasing maxBB
int nodeSizeLog2 = ceillog2(maxBB + 1);
GeometryBrickHeader gbh;
gbh.geom_geom_parameter_set_id = _gps->gps_geom_parameter_set_id;
gbh.geomBoxOrigin.x() = int(minPositions.x());
gbh.geomBoxOrigin.y() = int(minPositions.y());
gbh.geomBoxOrigin.z() = int(minPositions.z());
gbh.geom_box_log2_scale = 0;
gbh.geom_max_node_size_log2 = nodeSizeLog2;
gbh.geom_num_points = int(pointCloud.getPointCount());
write(*_gps, gbh, buf);
// todo(df): remove estimate when arithmetic codec is replaced
int maxAcBufLen = int(pointCloud.getPointCount()) * 3 * 4 + 1024;
o3dgc::Arithmetic_Codec arithmeticEncoder(maxAcBufLen, nullptr);
arithmeticEncoder.start_encoder();
if (_gps->geom_codec_type == GeometryCodecType::kOctree) {
encodeGeometryOctree(*_gps, gbh, pointCloud, &arithmeticEncoder);
}
// todo(df): move trisoup coding here
uint32_t dataLen = arithmeticEncoder.stop_encoder();
std::copy_n(arithmeticEncoder.buffer(), dataLen, std::back_inserter(*buf));
}
//----------------------------------------------------------------------------
void
PCCTMC3Encoder3::reconstructedPointCloud(PCCPointSet3* reconstructedCloud)
{
......
/* The copyright in this software is being made available under the BSD
* Licence, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such
* rights are granted under this licence.
*
* Copyright (c) 2017-2018, ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the ISO/IEC nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "ArithmeticCodec.h"
#include "PCCPointSet.h"
#include "hls.h"
namespace pcc {
//============================================================================
void encodeGeometryOctree(
const GeometryParameterSet& gps,
const GeometryBrickHeader& gbh,
PCCPointSet3& pointCloud,
o3dgc::Arithmetic_Codec* arithmeticEncoder);
void decodeGeometryOctree(
const GeometryParameterSet& gps,
const GeometryBrickHeader& gbh,
PCCPointSet3& pointCloud,
o3dgc::Arithmetic_Codec* arithmeticDecoder);
//============================================================================
} // namespace pcc
......@@ -33,12 +33,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "geometry_octree.h"
// todo: break dependency
#include "PCCTMC3Decoder.h"
#include "geometry.h"
#include "OctreeNeighMap.h"
#include "geometry_octree.h"
#include "io_hls.h"
#include "tables.h"
......@@ -252,29 +250,18 @@ GeometryOctreeDecoder::decodeDirectPosition(
//-------------------------------------------------------------------------
void
PCCTMC3Decoder3::decodePositions(
const PayloadBuffer& buf, PCCPointSet3& pointCloud)
decodeGeometryOctree(
const GeometryParameterSet& gps,
const GeometryBrickHeader& gbh,
PCCPointSet3& pointCloud,
o3dgc::Arithmetic_Codec* arithmeticDecoder)
{
assert(buf.type == PayloadType::kGeometryBrick);
int gbhSize;
GeometryBrickHeader gbh = parseGbh(*_gps, buf, &gbhSize);
minPositions.x() = gbh.geomBoxOrigin.x();
minPositions.y() = gbh.geomBoxOrigin.y();
minPositions.z() = gbh.geomBoxOrigin.z();
pointCloud.resize(gbh.geom_num_points);
o3dgc::Arithmetic_Codec arithmeticDecoder(
int(buf.size()) - gbhSize,
reinterpret_cast<uint8_t*>(const_cast<char*>(buf.data() + gbhSize)));
arithmeticDecoder.start_decoder();
GeometryOctreeDecoder decoder(&arithmeticDecoder);
GeometryOctreeDecoder decoder(arithmeticDecoder);
// init main fifo
// -- worst case size is the last level containing every input poit
// and each point being isolated in the previous level.
pcc::ringbuf<PCCOctree3Node> fifo(pointCloud.getPointCount() + 1);
pcc::ringbuf<PCCOctree3Node> fifo(gbh.geom_num_points + 1);
// the current node dimension (log2)
int nodeSizeLog2 = gbh.geom_max_node_size_log2;
......@@ -283,7 +270,7 @@ PCCTMC3Decoder3::decodePositions(
fifo.emplace_back();
PCCOctree3Node& node00 = fifo.back();
node00.start = uint32_t(0);
node00.end = uint32_t(pointCloud.getPointCount());
node00.end = uint32_t(0);
node00.pos = uint32_t(0);
node00.neighPattern = 0;
node00.numSiblingsPlus1 = 8;
......@@ -300,8 +287,8 @@ PCCTMC3Decoder3::decodePositions(
PCCVector3<uint32_t> occupancyAtlasOrigin(0xffffffff);
MortonMap3D occupancyAtlas;
if (_gps->neighbour_avail_boundary_log2) {
occupancyAtlas.resize(_gps->neighbour_avail_boundary_log2);
if (gps.neighbour_avail_boundary_log2) {
occupancyAtlas.resize(gps.neighbour_avail_boundary_log2);
occupancyAtlas.clear();
}
......@@ -315,7 +302,7 @@ PCCTMC3Decoder3::decodePositions(
}
PCCOctree3Node& node0 = fifo.front();
if (_gps->neighbour_avail_boundary_log2) {
if (gps.neighbour_avail_boundary_log2) {
updateGeometryOccupancyAtlas(
node0.pos, nodeSizeLog2, fifo, fifoCurrLvlEnd, &occupancyAtlas,
&occupancyAtlasOrigin);
......@@ -351,7 +338,7 @@ PCCTMC3Decoder3::decodePositions(
if (childSizeLog2 == 0) {
int numPoints = 1;
if (!_gps->geom_unique_points_flag) {
if (!gps.geom_unique_points_flag) {
numPoints = decoder.decodePositionLeafNumPoints();
}
......@@ -377,7 +364,7 @@ PCCTMC3Decoder3::decodePositions(
child.numSiblingsPlus1 = numOccupied;
child.siblingOccupancy = occupancy;
bool idcmEnabled = _gps->inferred_direct_coding_mode_enabled_flag;
bool idcmEnabled = gps.inferred_direct_coding_mode_enabled_flag;
if (isDirectModeEligible(idcmEnabled, nodeSizeLog2, node0, child)) {
int numPoints = decoder.decodeDirectPosition(
childSizeLog2, child, &pointCloud[processedPointCount]);
......@@ -395,16 +382,13 @@ PCCTMC3Decoder3::decodePositions(
numNodesNextLvl++;
if (!_gps->neighbour_avail_boundary_log2) {
if (!gps.neighbour_avail_boundary_log2) {
updateGeometryNeighState(
_gps->neighbour_context_restriction_flag, fifo.end(),
numNodesNextLvl, childSizeLog2, child, i, node0.neighPattern,
occupancy);
gps.neighbour_context_restriction_flag, fifo.end(), numNodesNextLvl,
childSizeLog2, child, i, node0.neighPattern, occupancy);
}
}
}
arithmeticDecoder.stop_decoder();
}
//============================================================================
......
......@@ -33,12 +33,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "geometry_octree.h"
// todo: break dependency
#include "PCCTMC3Encoder.h"
#include "geometry.h"
#include "OctreeNeighMap.h"
#include "geometry_octree.h"
#include "io_hls.h"
#include "tables.h"
......@@ -248,30 +246,13 @@ GeometryOctreeEncoder::encodeDirectPosition(
//-------------------------------------------------------------------------
void
PCCTMC3Encoder3::encodePositions(PayloadBuffer* buf)
encodeGeometryOctree(
const GeometryParameterSet& gps,
const GeometryBrickHeader& gbh,
PCCPointSet3& pointCloud,
o3dgc::Arithmetic_Codec* arithmeticEncoder)
{
uint32_t maxBB =
std::max({// todo(df): confirm minimum of 1 isn't needed
1u, boundingBox.max[0], boundingBox.max[1], boundingBox.max[2]});
// the current node dimension (log2) encompasing maxBB
int nodeSizeLog2 = ceillog2(maxBB + 1);
GeometryBrickHeader gbh;
gbh.geom_geom_parameter_set_id = _gps->gps_geom_parameter_set_id;
gbh.geomBoxOrigin.x() = int(minPositions.x());
gbh.geomBoxOrigin.y() = int(minPositions.y());
gbh.geomBoxOrigin.z() = int(minPositions.z());
gbh.geom_box_log2_scale = 0;
gbh.geom_max_node_size_log2 = nodeSizeLog2;
gbh.geom_num_points = int(pointCloud.getPointCount());
write(*_gps, gbh, buf);
// todo(df): remove estimate when arithmetic codec is replaced
int maxAcBufLen = int(pointCloud.getPointCount()) * 3 * 4 + 1024;
o3dgc::Arithmetic_Codec arithmeticEncoder(maxAcBufLen, nullptr);
arithmeticEncoder.start_encoder();
GeometryOctreeEncoder encoder(&arithmeticEncoder);
GeometryOctreeEncoder encoder(arithmeticEncoder);
// init main fifo
// -- worst case size is the last level containing every input poit
......@@ -298,13 +279,16 @@ PCCTMC3Encoder3::encodePositions(PayloadBuffer* buf)
auto fifoCurrLvlEnd = fifo.end();
// the initial node size is the root node's
int nodeSizeLog2 = gbh.geom_max_node_size_log2;
// this counter represents fifo.end() - fifoCurrLvlEnd().
// ie, the number of nodes added to the next level of the tree
int numNodesNextLvl = 0;
MortonMap3D occupancyAtlas;
if (_gps->neighbour_avail_boundary_log2) {
occupancyAtlas.resize(_gps->neighbour_avail_boundary_log2);
if (gps.neighbour_avail_boundary_log2) {
occupancyAtlas.resize(gps.neighbour_avail_boundary_log2);
occupancyAtlas.clear();
}
PCCVector3<uint32_t> occupancyAtlasOrigin(0xffffffff);
......@@ -346,7 +330,7 @@ PCCTMC3Encoder3::encodePositions(PayloadBuffer* buf)
}
}
if (_gps->neighbour_avail_boundary_log2) {
if (gps.neighbour_avail_boundary_log2) {
updateGeometryOccupancyAtlas(
node0.pos, nodeSizeLog2, fifo, fifoCurrLvlEnd, &occupancyAtlas,
&occupancyAtlasOrigin);
......@@ -370,7 +354,7 @@ PCCTMC3Encoder3::encodePositions(PayloadBuffer* buf)
// if the bitstream is configured to represent unique points,
// no point count is sent.
if (_gps->geom_unique_points_flag) {
if (gps.geom_unique_points_flag) {
assert(childCounts[i] == 1);
continue;
}
......@@ -412,7 +396,7 @@ PCCTMC3Encoder3::encodePositions(PayloadBuffer* buf)
child.numSiblingsPlus1 = numSiblings;
child.siblingOccupancy = occupancy;
bool idcmEnabled = _gps->inferred_direct_coding_mode_enabled_flag;
bool idcmEnabled = gps.inferred_direct_coding_mode_enabled_flag;
if (isDirectModeEligible(idcmEnabled, nodeSizeLog2, node0, child)) {
bool directModeUsed =
encoder.encodeDirectPosition(childSizeLog2, child, pointCloud);
......@@ -436,11 +420,10 @@ PCCTMC3Encoder3::encodePositions(PayloadBuffer* buf)
// NB: when neighbourAvailBoundaryLog2 is set, an alternative
// implementation is used to calculate neighPattern.
if (!_gps->neighbour_avail_boundary_log2) {
if (!gps.neighbour_avail_boundary_log2) {
updateGeometryNeighState(
_gps->neighbour_context_restriction_flag, fifo.end(),
numNodesNextLvl, childSizeLog2, child, i, node0.neighPattern,
occupancy);
gps.neighbour_context_restriction_flag, fifo.end(), numNodesNextLvl,
childSizeLog2, child, i, node0.neighPattern, occupancy);
}
}
}
......@@ -470,9 +453,6 @@ PCCTMC3Encoder3::encodePositions(PayloadBuffer* buf)
}
swap(pointCloud, pointCloud2);
uint32_t acDataLen = arithmeticEncoder.stop_encoder();
std::copy_n(arithmeticEncoder.buffer(), acDataLen, std::back_inserter(*buf));
}
//============================================================================
......
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