1 // Copyright 2016 The Draco Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 #include "draco/compression/attributes/attributes_decoder.h"
16
17 #include "draco/core/varint_decoding.h"
18
19 namespace draco {
20
AttributesDecoder()21 AttributesDecoder::AttributesDecoder()
22 : point_cloud_decoder_(nullptr), point_cloud_(nullptr) {}
23
Init(PointCloudDecoder * decoder,PointCloud * pc)24 bool AttributesDecoder::Init(PointCloudDecoder *decoder, PointCloud *pc) {
25 point_cloud_decoder_ = decoder;
26 point_cloud_ = pc;
27 return true;
28 }
29
DecodeAttributesDecoderData(DecoderBuffer * in_buffer)30 bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
31 // Decode and create attributes.
32 uint32_t num_attributes;
33 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
34 if (point_cloud_decoder_->bitstream_version() <
35 DRACO_BITSTREAM_VERSION(2, 0)) {
36 if (!in_buffer->Decode(&num_attributes)) {
37 return false;
38 }
39 } else
40 #endif
41 {
42 if (!DecodeVarint(&num_attributes, in_buffer)) {
43 return false;
44 }
45 }
46
47 // Check that decoded number of attributes is valid.
48 if (num_attributes == 0) {
49 return false;
50 }
51 if (num_attributes > 5 * in_buffer->remaining_size()) {
52 // The decoded number of attributes is unreasonably high, because at least
53 // five bytes of attribute descriptor data per attribute are expected.
54 return false;
55 }
56
57 // Decode attribute descriptor data.
58 point_attribute_ids_.resize(num_attributes);
59 PointCloud *pc = point_cloud_;
60 for (uint32_t i = 0; i < num_attributes; ++i) {
61 // Decode attribute descriptor data.
62 uint8_t att_type, data_type, num_components, normalized;
63 if (!in_buffer->Decode(&att_type)) {
64 return false;
65 }
66 if (!in_buffer->Decode(&data_type)) {
67 return false;
68 }
69 if (!in_buffer->Decode(&num_components)) {
70 return false;
71 }
72 if (!in_buffer->Decode(&normalized)) {
73 return false;
74 }
75 if (att_type >= GeometryAttribute::NAMED_ATTRIBUTES_COUNT) {
76 return false;
77 }
78 if (data_type == DT_INVALID || data_type >= DT_TYPES_COUNT) {
79 return false;
80 }
81
82 // Check decoded attribute descriptor data.
83 if (num_components == 0) {
84 return false;
85 }
86
87 // Add the attribute to the point cloud.
88 const DataType draco_dt = static_cast<DataType>(data_type);
89 GeometryAttribute ga;
90 ga.Init(static_cast<GeometryAttribute::Type>(att_type), nullptr,
91 num_components, draco_dt, normalized > 0,
92 DataTypeLength(draco_dt) * num_components, 0);
93 uint32_t unique_id;
94 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
95 if (point_cloud_decoder_->bitstream_version() <
96 DRACO_BITSTREAM_VERSION(1, 3)) {
97 uint16_t custom_id;
98 if (!in_buffer->Decode(&custom_id)) {
99 return false;
100 }
101 // TODO(draco-eng): Add "custom_id" to attribute metadata.
102 unique_id = static_cast<uint32_t>(custom_id);
103 ga.set_unique_id(unique_id);
104 } else
105 #endif
106 {
107 if (!DecodeVarint(&unique_id, in_buffer)) {
108 return false;
109 }
110 ga.set_unique_id(unique_id);
111 }
112 const int att_id = pc->AddAttribute(
113 std::unique_ptr<PointAttribute>(new PointAttribute(ga)));
114 pc->attribute(att_id)->set_unique_id(unique_id);
115 point_attribute_ids_[i] = att_id;
116
117 // Update the inverse map.
118 if (att_id >=
119 static_cast<int32_t>(point_attribute_to_local_id_map_.size())) {
120 point_attribute_to_local_id_map_.resize(att_id + 1, -1);
121 }
122 point_attribute_to_local_id_map_[att_id] = i;
123 }
124 return true;
125 }
126
127 } // namespace draco
128