Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc')
-rw-r--r--extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc189
1 files changed, 189 insertions, 0 deletions
diff --git a/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc
new file mode 100644
index 00000000000..5196edf960c
--- /dev/null
+++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc
@@ -0,0 +1,189 @@
+// Copyright 2016 The Draco Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "draco/compression/point_cloud/point_cloud_decoder.h"
+
+#include "draco/metadata/metadata_decoder.h"
+
+namespace draco {
+
+PointCloudDecoder::PointCloudDecoder()
+ : point_cloud_(nullptr),
+ buffer_(nullptr),
+ version_major_(0),
+ version_minor_(0),
+ options_(nullptr) {}
+
+Status PointCloudDecoder::DecodeHeader(DecoderBuffer *buffer,
+ DracoHeader *out_header) {
+ constexpr char kIoErrorMsg[] = "Failed to parse Draco header.";
+ if (!buffer->Decode(out_header->draco_string, 5)) {
+ return Status(Status::IO_ERROR, kIoErrorMsg);
+ }
+ if (memcmp(out_header->draco_string, "DRACO", 5) != 0) {
+ return Status(Status::DRACO_ERROR, "Not a Draco file.");
+ }
+ if (!buffer->Decode(&(out_header->version_major))) {
+ return Status(Status::IO_ERROR, kIoErrorMsg);
+ }
+ if (!buffer->Decode(&(out_header->version_minor))) {
+ return Status(Status::IO_ERROR, kIoErrorMsg);
+ }
+ if (!buffer->Decode(&(out_header->encoder_type))) {
+ return Status(Status::IO_ERROR, kIoErrorMsg);
+ }
+ if (!buffer->Decode(&(out_header->encoder_method))) {
+ return Status(Status::IO_ERROR, kIoErrorMsg);
+ }
+ if (!buffer->Decode(&(out_header->flags))) {
+ return Status(Status::IO_ERROR, kIoErrorMsg);
+ }
+ return OkStatus();
+}
+
+Status PointCloudDecoder::DecodeMetadata() {
+ std::unique_ptr<GeometryMetadata> metadata =
+ std::unique_ptr<GeometryMetadata>(new GeometryMetadata());
+ MetadataDecoder metadata_decoder;
+ if (!metadata_decoder.DecodeGeometryMetadata(buffer_, metadata.get())) {
+ return Status(Status::DRACO_ERROR, "Failed to decode metadata.");
+ }
+ point_cloud_->AddMetadata(std::move(metadata));
+ return OkStatus();
+}
+
+Status PointCloudDecoder::Decode(const DecoderOptions &options,
+ DecoderBuffer *in_buffer,
+ PointCloud *out_point_cloud) {
+ options_ = &options;
+ buffer_ = in_buffer;
+ point_cloud_ = out_point_cloud;
+ DracoHeader header;
+ DRACO_RETURN_IF_ERROR(DecodeHeader(buffer_, &header))
+ // Sanity check that we are really using the right decoder (mostly for cases
+ // where the Decode method was called manually outside of our main API.
+ if (header.encoder_type != GetGeometryType()) {
+ return Status(Status::DRACO_ERROR,
+ "Using incompatible decoder for the input geometry.");
+ }
+ // TODO(ostava): We should check the method as well, but currently decoders
+ // don't expose the decoding method id.
+ version_major_ = header.version_major;
+ version_minor_ = header.version_minor;
+
+ const uint8_t max_supported_major_version =
+ header.encoder_type == POINT_CLOUD ? kDracoPointCloudBitstreamVersionMajor
+ : kDracoMeshBitstreamVersionMajor;
+ const uint8_t max_supported_minor_version =
+ header.encoder_type == POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor
+ : kDracoMeshBitstreamVersionMinor;
+ // Check for version compatibility.
+ if (version_major_ < 1 || version_major_ > max_supported_major_version) {
+ return Status(Status::UNKNOWN_VERSION, "Unknown major version.");
+ }
+ if (version_major_ == max_supported_major_version &&
+ version_minor_ > max_supported_minor_version) {
+ return Status(Status::UNKNOWN_VERSION, "Unknown minor version.");
+ }
+ buffer_->set_bitstream_version(
+ DRACO_BITSTREAM_VERSION(version_major_, version_minor_));
+
+ if (bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 3) &&
+ (header.flags & METADATA_FLAG_MASK)) {
+ DRACO_RETURN_IF_ERROR(DecodeMetadata())
+ }
+ if (!InitializeDecoder()) {
+ return Status(Status::DRACO_ERROR, "Failed to initialize the decoder.");
+ }
+ if (!DecodeGeometryData()) {
+ return Status(Status::DRACO_ERROR, "Failed to decode geometry data.");
+ }
+ if (!DecodePointAttributes()) {
+ return Status(Status::DRACO_ERROR, "Failed to decode point attributes.");
+ }
+ return OkStatus();
+}
+
+bool PointCloudDecoder::DecodePointAttributes() {
+ uint8_t num_attributes_decoders;
+ if (!buffer_->Decode(&num_attributes_decoders)) {
+ return false;
+ }
+ // Create all attribute decoders. This is implementation specific and the
+ // derived classes can use any data encoded in the
+ // PointCloudEncoder::EncodeAttributesEncoderIdentifier() call.
+ for (int i = 0; i < num_attributes_decoders; ++i) {
+ if (!CreateAttributesDecoder(i)) {
+ return false;
+ }
+ }
+
+ // Initialize all attributes decoders. No data is decoded here.
+ for (auto &att_dec : attributes_decoders_) {
+ if (!att_dec->Init(this, point_cloud_)) {
+ return false;
+ }
+ }
+
+ // Decode any data needed by the attribute decoders.
+ for (int i = 0; i < num_attributes_decoders; ++i) {
+ if (!attributes_decoders_[i]->DecodeAttributesDecoderData(buffer_)) {
+ return false;
+ }
+ }
+
+ // Create map between attribute and decoder ids.
+ for (int i = 0; i < num_attributes_decoders; ++i) {
+ const int32_t num_attributes = attributes_decoders_[i]->GetNumAttributes();
+ for (int j = 0; j < num_attributes; ++j) {
+ int att_id = attributes_decoders_[i]->GetAttributeId(j);
+ if (att_id >= attribute_to_decoder_map_.size()) {
+ attribute_to_decoder_map_.resize(att_id + 1);
+ }
+ attribute_to_decoder_map_[att_id] = i;
+ }
+ }
+
+ // Decode the actual attributes using the created attribute decoders.
+ if (!DecodeAllAttributes()) {
+ return false;
+ }
+
+ if (!OnAttributesDecoded()) {
+ return false;
+ }
+ return true;
+}
+
+bool PointCloudDecoder::DecodeAllAttributes() {
+ for (auto &att_dec : attributes_decoders_) {
+ if (!att_dec->DecodeAttributes(buffer_)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+const PointAttribute *PointCloudDecoder::GetPortableAttribute(
+ int32_t parent_att_id) {
+ if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) {
+ return nullptr;
+ }
+ const int32_t parent_att_decoder_id =
+ attribute_to_decoder_map_[parent_att_id];
+ return attributes_decoders_[parent_att_decoder_id]->GetPortableAttribute(
+ parent_att_id);
+}
+
+} // namespace draco