Differential D4501 Diff 14521 extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.cc
Changeset View
Changeset View
Standalone View
Standalone View
extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.cc
- This file was added.
| // 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::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::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::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::ERROR, "Failed to initialize the decoder."); | |||||
| if (!DecodeGeometryData()) | |||||
| return Status(Status::ERROR, "Failed to decode geometry data."); | |||||
| if (!DecodePointAttributes()) | |||||
| return Status(Status::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 | |||||