Differential D9642 Diff 31697 extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc
Changeset View
Changeset View
Standalone View
Standalone View
extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc
- This file was moved from extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.cc.
| Show All 29 Lines | Status PointCloudEncoder::Encode(const EncoderOptions &options, | ||||
| options_ = &options; | options_ = &options; | ||||
| buffer_ = out_buffer; | buffer_ = out_buffer; | ||||
| // Cleanup from previous runs. | // Cleanup from previous runs. | ||||
| attributes_encoders_.clear(); | attributes_encoders_.clear(); | ||||
| attribute_to_encoder_map_.clear(); | attribute_to_encoder_map_.clear(); | ||||
| attributes_encoder_ids_order_.clear(); | attributes_encoder_ids_order_.clear(); | ||||
| if (!point_cloud_) | if (!point_cloud_) { | ||||
| return Status(Status::DRACO_ERROR, "Invalid input geometry."); | return Status(Status::DRACO_ERROR, "Invalid input geometry."); | ||||
| } | |||||
| DRACO_RETURN_IF_ERROR(EncodeHeader()) | DRACO_RETURN_IF_ERROR(EncodeHeader()) | ||||
| DRACO_RETURN_IF_ERROR(EncodeMetadata()) | DRACO_RETURN_IF_ERROR(EncodeMetadata()) | ||||
| if (!InitializeEncoder()) | if (!InitializeEncoder()) { | ||||
| return Status(Status::DRACO_ERROR, "Failed to initialize encoder."); | return Status(Status::DRACO_ERROR, "Failed to initialize encoder."); | ||||
| if (!EncodeEncoderData()) | } | ||||
| if (!EncodeEncoderData()) { | |||||
| return Status(Status::DRACO_ERROR, "Failed to encode internal data."); | return Status(Status::DRACO_ERROR, "Failed to encode internal data."); | ||||
| } | |||||
| DRACO_RETURN_IF_ERROR(EncodeGeometryData()); | DRACO_RETURN_IF_ERROR(EncodeGeometryData()); | ||||
| if (!EncodePointAttributes()) | if (!EncodePointAttributes()) { | ||||
| return Status(Status::DRACO_ERROR, "Failed to encode point attributes."); | return Status(Status::DRACO_ERROR, "Failed to encode point attributes."); | ||||
| if (options.GetGlobalBool("store_number_of_encoded_points", false)) | } | ||||
| if (options.GetGlobalBool("store_number_of_encoded_points", false)) { | |||||
| ComputeNumberOfEncodedPoints(); | ComputeNumberOfEncodedPoints(); | ||||
| } | |||||
| return OkStatus(); | return OkStatus(); | ||||
| } | } | ||||
| Status PointCloudEncoder::EncodeHeader() { | Status PointCloudEncoder::EncodeHeader() { | ||||
| // Encode the header according to our v1 specification. | // Encode the header according to our v1 specification. | ||||
| // Five bytes for Draco format. | // Five bytes for Draco format. | ||||
| buffer_->Encode("DRACO", 5); | buffer_->Encode("DRACO", 5); | ||||
| // Version (major, minor). | // Version (major, minor). | ||||
| Show All 28 Lines | Status PointCloudEncoder::EncodeMetadata() { | ||||
| if (!metadata_encoder.EncodeGeometryMetadata(buffer_, | if (!metadata_encoder.EncodeGeometryMetadata(buffer_, | ||||
| point_cloud_->GetMetadata())) { | point_cloud_->GetMetadata())) { | ||||
| return Status(Status::DRACO_ERROR, "Failed to encode metadata."); | return Status(Status::DRACO_ERROR, "Failed to encode metadata."); | ||||
| } | } | ||||
| return OkStatus(); | return OkStatus(); | ||||
| } | } | ||||
| bool PointCloudEncoder::EncodePointAttributes() { | bool PointCloudEncoder::EncodePointAttributes() { | ||||
| if (!GenerateAttributesEncoders()) | if (!GenerateAttributesEncoders()) { | ||||
| return false; | return false; | ||||
| } | |||||
| // Encode the number of attribute encoders. | // Encode the number of attribute encoders. | ||||
| buffer_->Encode(static_cast<uint8_t>(attributes_encoders_.size())); | buffer_->Encode(static_cast<uint8_t>(attributes_encoders_.size())); | ||||
| // Initialize all the encoders (this is used for example to init attribute | // Initialize all the encoders (this is used for example to init attribute | ||||
| // dependencies, no data is encoded in this step). | // dependencies, no data is encoded in this step). | ||||
| for (auto &att_enc : attributes_encoders_) { | for (auto &att_enc : attributes_encoders_) { | ||||
| if (!att_enc->Init(this, point_cloud_)) | if (!att_enc->Init(this, point_cloud_)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| // Rearrange attributes to respect dependencies between individual attributes. | // Rearrange attributes to respect dependencies between individual attributes. | ||||
| if (!RearrangeAttributesEncoders()) | if (!RearrangeAttributesEncoders()) { | ||||
| return false; | return false; | ||||
| } | |||||
| // Encode any data that is necessary to create the corresponding attribute | // Encode any data that is necessary to create the corresponding attribute | ||||
| // decoder. | // decoder. | ||||
| for (int att_encoder_id : attributes_encoder_ids_order_) { | for (int att_encoder_id : attributes_encoder_ids_order_) { | ||||
| if (!EncodeAttributesEncoderIdentifier(att_encoder_id)) | if (!EncodeAttributesEncoderIdentifier(att_encoder_id)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| // Also encode any attribute encoder data (such as the info about encoded | // Also encode any attribute encoder data (such as the info about encoded | ||||
| // attributes). | // attributes). | ||||
| for (int att_encoder_id : attributes_encoder_ids_order_) { | for (int att_encoder_id : attributes_encoder_ids_order_) { | ||||
| if (!attributes_encoders_[att_encoder_id]->EncodeAttributesEncoderData( | if (!attributes_encoders_[att_encoder_id]->EncodeAttributesEncoderData( | ||||
| buffer_)) | buffer_)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| // Lastly encode all the attributes using the provided attribute encoders. | // Lastly encode all the attributes using the provided attribute encoders. | ||||
| if (!EncodeAllAttributes()) | if (!EncodeAllAttributes()) { | ||||
| return false; | return false; | ||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| bool PointCloudEncoder::GenerateAttributesEncoders() { | bool PointCloudEncoder::GenerateAttributesEncoders() { | ||||
| for (int i = 0; i < point_cloud_->num_attributes(); ++i) { | for (int i = 0; i < point_cloud_->num_attributes(); ++i) { | ||||
| if (!GenerateAttributesEncoder(i)) | if (!GenerateAttributesEncoder(i)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| attribute_to_encoder_map_.resize(point_cloud_->num_attributes()); | attribute_to_encoder_map_.resize(point_cloud_->num_attributes()); | ||||
| for (uint32_t i = 0; i < attributes_encoders_.size(); ++i) { | for (uint32_t i = 0; i < attributes_encoders_.size(); ++i) { | ||||
| for (uint32_t j = 0; j < attributes_encoders_[i]->num_attributes(); ++j) { | for (uint32_t j = 0; j < attributes_encoders_[i]->num_attributes(); ++j) { | ||||
| attribute_to_encoder_map_[attributes_encoders_[i]->GetAttributeId(j)] = i; | attribute_to_encoder_map_[attributes_encoders_[i]->GetAttributeId(j)] = i; | ||||
| } | } | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| bool PointCloudEncoder::EncodeAllAttributes() { | bool PointCloudEncoder::EncodeAllAttributes() { | ||||
| for (int att_encoder_id : attributes_encoder_ids_order_) { | for (int att_encoder_id : attributes_encoder_ids_order_) { | ||||
| if (!attributes_encoders_[att_encoder_id]->EncodeAttributes(buffer_)) | if (!attributes_encoders_[att_encoder_id]->EncodeAttributes(buffer_)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| bool PointCloudEncoder::MarkParentAttribute(int32_t parent_att_id) { | bool PointCloudEncoder::MarkParentAttribute(int32_t parent_att_id) { | ||||
| if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) | if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) { | ||||
| return false; | return false; | ||||
| } | |||||
| const int32_t parent_att_encoder_id = | const int32_t parent_att_encoder_id = | ||||
| attribute_to_encoder_map_[parent_att_id]; | attribute_to_encoder_map_[parent_att_id]; | ||||
| if (!attributes_encoders_[parent_att_encoder_id]->MarkParentAttribute( | if (!attributes_encoders_[parent_att_encoder_id]->MarkParentAttribute( | ||||
| parent_att_id)) | parent_att_id)) { | ||||
| return false; | return false; | ||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| const PointAttribute *PointCloudEncoder::GetPortableAttribute( | const PointAttribute *PointCloudEncoder::GetPortableAttribute( | ||||
| int32_t parent_att_id) { | int32_t parent_att_id) { | ||||
| if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) | if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) { | ||||
| return nullptr; | return nullptr; | ||||
| } | |||||
| const int32_t parent_att_encoder_id = | const int32_t parent_att_encoder_id = | ||||
| attribute_to_encoder_map_[parent_att_id]; | attribute_to_encoder_map_[parent_att_id]; | ||||
| return attributes_encoders_[parent_att_encoder_id]->GetPortableAttribute( | return attributes_encoders_[parent_att_encoder_id]->GetPortableAttribute( | ||||
| parent_att_id); | parent_att_id); | ||||
| } | } | ||||
| bool PointCloudEncoder::RearrangeAttributesEncoders() { | bool PointCloudEncoder::RearrangeAttributesEncoders() { | ||||
| // Find the encoding order of the attribute encoders that is determined by | // Find the encoding order of the attribute encoders that is determined by | ||||
| Show All 10 Lines | bool PointCloudEncoder::RearrangeAttributesEncoders() { | ||||
| // but it will require changes in the current API. | // but it will require changes in the current API. | ||||
| attributes_encoder_ids_order_.resize(attributes_encoders_.size()); | attributes_encoder_ids_order_.resize(attributes_encoders_.size()); | ||||
| std::vector<bool> is_encoder_processed(attributes_encoders_.size(), false); | std::vector<bool> is_encoder_processed(attributes_encoders_.size(), false); | ||||
| uint32_t num_processed_encoders = 0; | uint32_t num_processed_encoders = 0; | ||||
| while (num_processed_encoders < attributes_encoders_.size()) { | while (num_processed_encoders < attributes_encoders_.size()) { | ||||
| // Flagged when any of the encoder get processed. | // Flagged when any of the encoder get processed. | ||||
| bool encoder_processed = false; | bool encoder_processed = false; | ||||
| for (uint32_t i = 0; i < attributes_encoders_.size(); ++i) { | for (uint32_t i = 0; i < attributes_encoders_.size(); ++i) { | ||||
| if (is_encoder_processed[i]) | if (is_encoder_processed[i]) { | ||||
| continue; // Encoder already processed. | continue; // Encoder already processed. | ||||
| } | |||||
| // Check if all parent encoders are already processed. | // Check if all parent encoders are already processed. | ||||
| bool can_be_processed = true; | bool can_be_processed = true; | ||||
| for (uint32_t p = 0; p < attributes_encoders_[i]->num_attributes(); ++p) { | for (uint32_t p = 0; p < attributes_encoders_[i]->num_attributes(); ++p) { | ||||
| const int32_t att_id = attributes_encoders_[i]->GetAttributeId(p); | const int32_t att_id = attributes_encoders_[i]->GetAttributeId(p); | ||||
| for (int ap = 0; | for (int ap = 0; | ||||
| ap < attributes_encoders_[i]->NumParentAttributes(att_id); ++ap) { | ap < attributes_encoders_[i]->NumParentAttributes(att_id); ++ap) { | ||||
| const uint32_t parent_att_id = | const uint32_t parent_att_id = | ||||
| attributes_encoders_[i]->GetParentAttributeId(att_id, ap); | attributes_encoders_[i]->GetParentAttributeId(att_id, ap); | ||||
| const int32_t parent_encoder_id = | const int32_t parent_encoder_id = | ||||
| attribute_to_encoder_map_[parent_att_id]; | attribute_to_encoder_map_[parent_att_id]; | ||||
| if (parent_att_id != i && !is_encoder_processed[parent_encoder_id]) { | if (parent_att_id != i && !is_encoder_processed[parent_encoder_id]) { | ||||
| can_be_processed = false; | can_be_processed = false; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (!can_be_processed) | if (!can_be_processed) { | ||||
| continue; // Try to process the encoder in the next iteration. | continue; // Try to process the encoder in the next iteration. | ||||
| } | |||||
| // Encoder can be processed. Update the encoding order. | // Encoder can be processed. Update the encoding order. | ||||
| attributes_encoder_ids_order_[num_processed_encoders++] = i; | attributes_encoder_ids_order_[num_processed_encoders++] = i; | ||||
| is_encoder_processed[i] = true; | is_encoder_processed[i] = true; | ||||
| encoder_processed = true; | encoder_processed = true; | ||||
| } | } | ||||
| if (!encoder_processed && | if (!encoder_processed && | ||||
| num_processed_encoders < attributes_encoders_.size()) { | num_processed_encoders < attributes_encoders_.size()) { | ||||
| // No encoder was processed but there are still some remaining unprocessed | // No encoder was processed but there are still some remaining unprocessed | ||||
| Show All 9 Lines | bool PointCloudEncoder::RearrangeAttributesEncoders() { | ||||
| std::vector<bool> is_attribute_processed(point_cloud_->num_attributes(), | std::vector<bool> is_attribute_processed(point_cloud_->num_attributes(), | ||||
| false); | false); | ||||
| int num_processed_attributes; | int num_processed_attributes; | ||||
| for (uint32_t ae_order = 0; ae_order < attributes_encoders_.size(); | for (uint32_t ae_order = 0; ae_order < attributes_encoders_.size(); | ||||
| ++ae_order) { | ++ae_order) { | ||||
| const int ae = attributes_encoder_ids_order_[ae_order]; | const int ae = attributes_encoder_ids_order_[ae_order]; | ||||
| const int32_t num_encoder_attributes = | const int32_t num_encoder_attributes = | ||||
| attributes_encoders_[ae]->num_attributes(); | attributes_encoders_[ae]->num_attributes(); | ||||
| if (num_encoder_attributes < 2) | if (num_encoder_attributes < 2) { | ||||
| continue; // No need to resolve dependencies for a single attribute. | continue; // No need to resolve dependencies for a single attribute. | ||||
| } | |||||
| num_processed_attributes = 0; | num_processed_attributes = 0; | ||||
| attribute_encoding_order.resize(num_encoder_attributes); | attribute_encoding_order.resize(num_encoder_attributes); | ||||
| while (num_processed_attributes < num_encoder_attributes) { | while (num_processed_attributes < num_encoder_attributes) { | ||||
| // Flagged when any of the attributes get processed. | // Flagged when any of the attributes get processed. | ||||
| bool attribute_processed = false; | bool attribute_processed = false; | ||||
| for (int i = 0; i < num_encoder_attributes; ++i) { | for (int i = 0; i < num_encoder_attributes; ++i) { | ||||
| const int32_t att_id = attributes_encoders_[ae]->GetAttributeId(i); | const int32_t att_id = attributes_encoders_[ae]->GetAttributeId(i); | ||||
| if (is_attribute_processed[i]) | if (is_attribute_processed[i]) { | ||||
| continue; // Attribute already processed. | continue; // Attribute already processed. | ||||
| } | |||||
| // Check if all parent attributes are already processed. | // Check if all parent attributes are already processed. | ||||
| bool can_be_processed = true; | bool can_be_processed = true; | ||||
| for (int p = 0; | for (int p = 0; | ||||
| p < attributes_encoders_[ae]->NumParentAttributes(att_id); ++p) { | p < attributes_encoders_[ae]->NumParentAttributes(att_id); ++p) { | ||||
| const int32_t parent_att_id = | const int32_t parent_att_id = | ||||
| attributes_encoders_[ae]->GetParentAttributeId(att_id, p); | attributes_encoders_[ae]->GetParentAttributeId(att_id, p); | ||||
| if (!is_attribute_processed[parent_att_id]) { | if (!is_attribute_processed[parent_att_id]) { | ||||
| can_be_processed = false; | can_be_processed = false; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (!can_be_processed) | if (!can_be_processed) { | ||||
| continue; // Try to process the attribute in the next iteration. | continue; // Try to process the attribute in the next iteration. | ||||
| } | |||||
| // Attribute can be processed. Update the encoding order. | // Attribute can be processed. Update the encoding order. | ||||
| attribute_encoding_order[num_processed_attributes++] = i; | attribute_encoding_order[num_processed_attributes++] = i; | ||||
| is_attribute_processed[i] = true; | is_attribute_processed[i] = true; | ||||
| attribute_processed = true; | attribute_processed = true; | ||||
| } | } | ||||
| if (!attribute_processed && | if (!attribute_processed && | ||||
| num_processed_attributes < num_encoder_attributes) { | num_processed_attributes < num_encoder_attributes) { | ||||
| // No attribute was processed but there are still some remaining | // No attribute was processed but there are still some remaining | ||||
| Show All 11 Lines | |||||