/src/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc
Line | Count | Source (jump to first uncovered line) |
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/sequential_integer_attribute_decoder.h" |
16 | | |
17 | | #include "draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h" |
18 | | #include "draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h" |
19 | | #include "draco/compression/entropy/symbol_decoding.h" |
20 | | |
21 | | namespace draco { |
22 | | |
23 | 61.1k | SequentialIntegerAttributeDecoder::SequentialIntegerAttributeDecoder() {} |
24 | | |
25 | | bool SequentialIntegerAttributeDecoder::Init(PointCloudDecoder *decoder, |
26 | 61.1k | int attribute_id) { |
27 | 61.1k | if (!SequentialAttributeDecoder::Init(decoder, attribute_id)) { |
28 | 0 | return false; |
29 | 0 | } |
30 | 61.1k | return true; |
31 | 61.1k | } |
32 | | |
33 | | bool SequentialIntegerAttributeDecoder::TransformAttributeToOriginalFormat( |
34 | 4.50k | const std::vector<PointIndex> &point_ids) { |
35 | 4.50k | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED |
36 | 4.50k | if (decoder() && |
37 | 4.50k | decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { |
38 | 2 | return true; // Don't revert the transform here for older files. |
39 | 2 | } |
40 | 4.50k | #endif |
41 | 4.50k | return StoreValues(static_cast<uint32_t>(point_ids.size())); |
42 | 4.50k | } |
43 | | |
44 | | bool SequentialIntegerAttributeDecoder::DecodeValues( |
45 | 13.4k | const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) { |
46 | | // Decode prediction scheme. |
47 | 13.4k | int8_t prediction_scheme_method; |
48 | 13.4k | if (!in_buffer->Decode(&prediction_scheme_method)) { |
49 | 34 | return false; |
50 | 34 | } |
51 | | // Check that decoded prediction scheme method type is valid. |
52 | 13.3k | if (prediction_scheme_method < PREDICTION_NONE || |
53 | 13.3k | prediction_scheme_method >= NUM_PREDICTION_SCHEMES) { |
54 | 252 | return false; |
55 | 252 | } |
56 | 13.1k | if (prediction_scheme_method != PREDICTION_NONE) { |
57 | 13.0k | int8_t prediction_transform_type; |
58 | 13.0k | if (!in_buffer->Decode(&prediction_transform_type)) { |
59 | 22 | return false; |
60 | 22 | } |
61 | | // Check that decoded prediction scheme transform type is valid. |
62 | 13.0k | if (prediction_transform_type < PREDICTION_TRANSFORM_NONE || |
63 | 13.0k | prediction_transform_type >= NUM_PREDICTION_SCHEME_TRANSFORM_TYPES) { |
64 | 154 | return false; |
65 | 154 | } |
66 | 12.9k | prediction_scheme_ = CreateIntPredictionScheme( |
67 | 12.9k | static_cast<PredictionSchemeMethod>(prediction_scheme_method), |
68 | 12.9k | static_cast<PredictionSchemeTransformType>(prediction_transform_type)); |
69 | 12.9k | } |
70 | | |
71 | 12.9k | if (prediction_scheme_) { |
72 | 7.25k | if (!InitPredictionScheme(prediction_scheme_.get())) { |
73 | 27 | return false; |
74 | 27 | } |
75 | 7.25k | } |
76 | | |
77 | 12.9k | if (!DecodeIntegerValues(point_ids, in_buffer)) { |
78 | 1.88k | return false; |
79 | 1.88k | } |
80 | | |
81 | 11.0k | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED |
82 | 11.0k | const int32_t num_values = static_cast<uint32_t>(point_ids.size()); |
83 | 11.0k | if (decoder() && |
84 | 11.0k | decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { |
85 | | // For older files, revert the transform right after we decode the data. |
86 | 40 | if (!StoreValues(num_values)) { |
87 | 0 | return false; |
88 | 0 | } |
89 | 40 | } |
90 | 11.0k | #endif |
91 | 11.0k | return true; |
92 | 11.0k | } |
93 | | |
94 | | std::unique_ptr<PredictionSchemeTypedDecoderInterface<int32_t>> |
95 | | SequentialIntegerAttributeDecoder::CreateIntPredictionScheme( |
96 | | PredictionSchemeMethod method, |
97 | 11.7k | PredictionSchemeTransformType transform_type) { |
98 | 11.7k | if (transform_type != PREDICTION_TRANSFORM_WRAP) { |
99 | 5.59k | return nullptr; // For now we support only wrap transform. |
100 | 5.59k | } |
101 | 6.13k | return CreatePredictionSchemeForDecoder< |
102 | 6.13k | int32_t, PredictionSchemeWrapDecodingTransform<int32_t>>( |
103 | 6.13k | method, attribute_id(), decoder()); |
104 | 11.7k | } |
105 | | |
106 | | bool SequentialIntegerAttributeDecoder::DecodeIntegerValues( |
107 | 12.9k | const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) { |
108 | 12.9k | const int num_components = GetNumValueComponents(); |
109 | 12.9k | if (num_components <= 0) { |
110 | 0 | return false; |
111 | 0 | } |
112 | 12.9k | const size_t num_entries = point_ids.size(); |
113 | 12.9k | const size_t num_values = num_entries * num_components; |
114 | 12.9k | PreparePortableAttribute(static_cast<int>(num_entries), num_components); |
115 | 12.9k | int32_t *const portable_attribute_data = GetPortableAttributeData(); |
116 | 12.9k | if (portable_attribute_data == nullptr) { |
117 | 11 | return false; |
118 | 11 | } |
119 | 12.9k | uint8_t compressed; |
120 | 12.9k | if (!in_buffer->Decode(&compressed)) { |
121 | 19 | return false; |
122 | 19 | } |
123 | 12.8k | if (compressed > 0) { |
124 | | // Decode compressed values. |
125 | 702 | if (!DecodeSymbols(static_cast<uint32_t>(num_values), num_components, |
126 | 702 | in_buffer, |
127 | 702 | reinterpret_cast<uint32_t *>(portable_attribute_data))) { |
128 | 258 | return false; |
129 | 258 | } |
130 | 12.1k | } else { |
131 | | // Decode the integer data directly. |
132 | | // Get the number of bytes for a given entry. |
133 | 12.1k | uint8_t num_bytes; |
134 | 12.1k | if (!in_buffer->Decode(&num_bytes)) { |
135 | 3 | return false; |
136 | 3 | } |
137 | 12.1k | if (num_bytes == DataTypeLength(DT_INT32)) { |
138 | 599 | if (portable_attribute()->buffer()->data_size() < |
139 | 599 | sizeof(int32_t) * num_values) { |
140 | 0 | return false; |
141 | 0 | } |
142 | 599 | if (!in_buffer->Decode(portable_attribute_data, |
143 | 599 | sizeof(int32_t) * num_values)) { |
144 | 4 | return false; |
145 | 4 | } |
146 | 11.5k | } else { |
147 | 11.5k | if (portable_attribute()->buffer()->data_size() < |
148 | 11.5k | num_bytes * num_values) { |
149 | 52 | return false; |
150 | 52 | } |
151 | 11.5k | if (in_buffer->remaining_size() < |
152 | 11.5k | static_cast<int64_t>(num_bytes) * static_cast<int64_t>(num_values)) { |
153 | 14 | return false; |
154 | 14 | } |
155 | 530M | for (size_t i = 0; i < num_values; ++i) { |
156 | 530M | if (!in_buffer->Decode(portable_attribute_data + i, num_bytes)) { |
157 | 0 | return false; |
158 | 0 | } |
159 | 530M | } |
160 | 11.5k | } |
161 | 12.1k | } |
162 | | |
163 | 12.5k | if (num_values > 0 && (prediction_scheme_ == nullptr || |
164 | 12.5k | !prediction_scheme_->AreCorrectionsPositive())) { |
165 | | // Convert the values back to the original signed format. |
166 | 11.4k | ConvertSymbolsToSignedInts( |
167 | 11.4k | reinterpret_cast<const uint32_t *>(portable_attribute_data), |
168 | 11.4k | static_cast<int>(num_values), portable_attribute_data); |
169 | 11.4k | } |
170 | | |
171 | | // If the data was encoded with a prediction scheme, we must revert it. |
172 | 12.5k | if (prediction_scheme_) { |
173 | 7.04k | if (!prediction_scheme_->DecodePredictionData(in_buffer)) { |
174 | 983 | return false; |
175 | 983 | } |
176 | | |
177 | 6.06k | if (num_values > 0) { |
178 | 6.06k | if (!prediction_scheme_->ComputeOriginalValues( |
179 | 6.06k | portable_attribute_data, portable_attribute_data, |
180 | 6.06k | static_cast<int>(num_values), num_components, point_ids.data())) { |
181 | 539 | return false; |
182 | 539 | } |
183 | 6.06k | } |
184 | 6.06k | } |
185 | 11.0k | return true; |
186 | 12.5k | } |
187 | | |
188 | 3.91k | bool SequentialIntegerAttributeDecoder::StoreValues(uint32_t num_values) { |
189 | 3.91k | switch (attribute()->data_type()) { |
190 | 647 | case DT_UINT8: |
191 | 647 | StoreTypedValues<uint8_t>(num_values); |
192 | 647 | break; |
193 | 2.08k | case DT_INT8: |
194 | 2.08k | StoreTypedValues<int8_t>(num_values); |
195 | 2.08k | break; |
196 | 106 | case DT_UINT16: |
197 | 106 | StoreTypedValues<uint16_t>(num_values); |
198 | 106 | break; |
199 | 250 | case DT_INT16: |
200 | 250 | StoreTypedValues<int16_t>(num_values); |
201 | 250 | break; |
202 | 140 | case DT_UINT32: |
203 | 140 | StoreTypedValues<uint32_t>(num_values); |
204 | 140 | break; |
205 | 408 | case DT_INT32: |
206 | 408 | StoreTypedValues<int32_t>(num_values); |
207 | 408 | break; |
208 | 275 | default: |
209 | 275 | return false; |
210 | 3.91k | } |
211 | 3.63k | return true; |
212 | 3.91k | } |
213 | | |
214 | | template <typename AttributeTypeT> |
215 | 3.63k | void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) { |
216 | 3.63k | const int num_components = attribute()->num_components(); |
217 | 3.63k | const int entry_size = sizeof(AttributeTypeT) * num_components; |
218 | 3.63k | const std::unique_ptr<AttributeTypeT[]> att_val( |
219 | 3.63k | new AttributeTypeT[num_components]); |
220 | 3.63k | const int32_t *const portable_attribute_data = GetPortableAttributeData(); |
221 | 3.63k | int val_id = 0; |
222 | 3.63k | int out_byte_pos = 0; |
223 | 8.47M | for (uint32_t i = 0; i < num_values; ++i) { |
224 | 317M | for (int c = 0; c < num_components; ++c) { |
225 | 309M | const AttributeTypeT value = |
226 | 309M | static_cast<AttributeTypeT>(portable_attribute_data[val_id++]); |
227 | 309M | att_val[c] = value; |
228 | 309M | } |
229 | | // Store the integer value into the attribute buffer. |
230 | 8.47M | attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size); |
231 | 8.47M | out_byte_pos += entry_size; |
232 | 8.47M | } |
233 | 3.63k | } void draco::SequentialIntegerAttributeDecoder::StoreTypedValues<unsigned char>(unsigned int) Line | Count | Source | 215 | 647 | void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) { | 216 | 647 | const int num_components = attribute()->num_components(); | 217 | 647 | const int entry_size = sizeof(AttributeTypeT) * num_components; | 218 | 647 | const std::unique_ptr<AttributeTypeT[]> att_val( | 219 | 647 | new AttributeTypeT[num_components]); | 220 | 647 | const int32_t *const portable_attribute_data = GetPortableAttributeData(); | 221 | 647 | int val_id = 0; | 222 | 647 | int out_byte_pos = 0; | 223 | 1.64M | for (uint32_t i = 0; i < num_values; ++i) { | 224 | 75.3M | for (int c = 0; c < num_components; ++c) { | 225 | 73.6M | const AttributeTypeT value = | 226 | 73.6M | static_cast<AttributeTypeT>(portable_attribute_data[val_id++]); | 227 | 73.6M | att_val[c] = value; | 228 | 73.6M | } | 229 | | // Store the integer value into the attribute buffer. | 230 | 1.64M | attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size); | 231 | 1.64M | out_byte_pos += entry_size; | 232 | 1.64M | } | 233 | 647 | } |
void draco::SequentialIntegerAttributeDecoder::StoreTypedValues<signed char>(unsigned int) Line | Count | Source | 215 | 2.08k | void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) { | 216 | 2.08k | const int num_components = attribute()->num_components(); | 217 | 2.08k | const int entry_size = sizeof(AttributeTypeT) * num_components; | 218 | 2.08k | const std::unique_ptr<AttributeTypeT[]> att_val( | 219 | 2.08k | new AttributeTypeT[num_components]); | 220 | 2.08k | const int32_t *const portable_attribute_data = GetPortableAttributeData(); | 221 | 2.08k | int val_id = 0; | 222 | 2.08k | int out_byte_pos = 0; | 223 | 3.22M | for (uint32_t i = 0; i < num_values; ++i) { | 224 | 80.9M | for (int c = 0; c < num_components; ++c) { | 225 | 77.6M | const AttributeTypeT value = | 226 | 77.6M | static_cast<AttributeTypeT>(portable_attribute_data[val_id++]); | 227 | 77.6M | att_val[c] = value; | 228 | 77.6M | } | 229 | | // Store the integer value into the attribute buffer. | 230 | 3.22M | attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size); | 231 | 3.22M | out_byte_pos += entry_size; | 232 | 3.22M | } | 233 | 2.08k | } |
void draco::SequentialIntegerAttributeDecoder::StoreTypedValues<unsigned short>(unsigned int) Line | Count | Source | 215 | 106 | void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) { | 216 | 106 | const int num_components = attribute()->num_components(); | 217 | 106 | const int entry_size = sizeof(AttributeTypeT) * num_components; | 218 | 106 | const std::unique_ptr<AttributeTypeT[]> att_val( | 219 | 106 | new AttributeTypeT[num_components]); | 220 | 106 | const int32_t *const portable_attribute_data = GetPortableAttributeData(); | 221 | 106 | int val_id = 0; | 222 | 106 | int out_byte_pos = 0; | 223 | 925k | for (uint32_t i = 0; i < num_values; ++i) { | 224 | 49.1M | for (int c = 0; c < num_components; ++c) { | 225 | 48.1M | const AttributeTypeT value = | 226 | 48.1M | static_cast<AttributeTypeT>(portable_attribute_data[val_id++]); | 227 | 48.1M | att_val[c] = value; | 228 | 48.1M | } | 229 | | // Store the integer value into the attribute buffer. | 230 | 925k | attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size); | 231 | 925k | out_byte_pos += entry_size; | 232 | 925k | } | 233 | 106 | } |
void draco::SequentialIntegerAttributeDecoder::StoreTypedValues<short>(unsigned int) Line | Count | Source | 215 | 250 | void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) { | 216 | 250 | const int num_components = attribute()->num_components(); | 217 | 250 | const int entry_size = sizeof(AttributeTypeT) * num_components; | 218 | 250 | const std::unique_ptr<AttributeTypeT[]> att_val( | 219 | 250 | new AttributeTypeT[num_components]); | 220 | 250 | const int32_t *const portable_attribute_data = GetPortableAttributeData(); | 221 | 250 | int val_id = 0; | 222 | 250 | int out_byte_pos = 0; | 223 | 1.11M | for (uint32_t i = 0; i < num_values; ++i) { | 224 | 59.4M | for (int c = 0; c < num_components; ++c) { | 225 | 58.3M | const AttributeTypeT value = | 226 | 58.3M | static_cast<AttributeTypeT>(portable_attribute_data[val_id++]); | 227 | 58.3M | att_val[c] = value; | 228 | 58.3M | } | 229 | | // Store the integer value into the attribute buffer. | 230 | 1.11M | attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size); | 231 | 1.11M | out_byte_pos += entry_size; | 232 | 1.11M | } | 233 | 250 | } |
void draco::SequentialIntegerAttributeDecoder::StoreTypedValues<unsigned int>(unsigned int) Line | Count | Source | 215 | 140 | void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) { | 216 | 140 | const int num_components = attribute()->num_components(); | 217 | 140 | const int entry_size = sizeof(AttributeTypeT) * num_components; | 218 | 140 | const std::unique_ptr<AttributeTypeT[]> att_val( | 219 | 140 | new AttributeTypeT[num_components]); | 220 | 140 | const int32_t *const portable_attribute_data = GetPortableAttributeData(); | 221 | 140 | int val_id = 0; | 222 | 140 | int out_byte_pos = 0; | 223 | 470k | for (uint32_t i = 0; i < num_values; ++i) { | 224 | 25.2M | for (int c = 0; c < num_components; ++c) { | 225 | 24.8M | const AttributeTypeT value = | 226 | 24.8M | static_cast<AttributeTypeT>(portable_attribute_data[val_id++]); | 227 | 24.8M | att_val[c] = value; | 228 | 24.8M | } | 229 | | // Store the integer value into the attribute buffer. | 230 | 470k | attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size); | 231 | 470k | out_byte_pos += entry_size; | 232 | 470k | } | 233 | 140 | } |
void draco::SequentialIntegerAttributeDecoder::StoreTypedValues<int>(unsigned int) Line | Count | Source | 215 | 408 | void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) { | 216 | 408 | const int num_components = attribute()->num_components(); | 217 | 408 | const int entry_size = sizeof(AttributeTypeT) * num_components; | 218 | 408 | const std::unique_ptr<AttributeTypeT[]> att_val( | 219 | 408 | new AttributeTypeT[num_components]); | 220 | 408 | const int32_t *const portable_attribute_data = GetPortableAttributeData(); | 221 | 408 | int val_id = 0; | 222 | 408 | int out_byte_pos = 0; | 223 | 1.08M | for (uint32_t i = 0; i < num_values; ++i) { | 224 | 27.6M | for (int c = 0; c < num_components; ++c) { | 225 | 26.5M | const AttributeTypeT value = | 226 | 26.5M | static_cast<AttributeTypeT>(portable_attribute_data[val_id++]); | 227 | 26.5M | att_val[c] = value; | 228 | 26.5M | } | 229 | | // Store the integer value into the attribute buffer. | 230 | 1.08M | attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size); | 231 | 1.08M | out_byte_pos += entry_size; | 232 | 1.08M | } | 233 | 408 | } |
|
234 | | |
235 | | void SequentialIntegerAttributeDecoder::PreparePortableAttribute( |
236 | 12.9k | int num_entries, int num_components) { |
237 | 12.9k | GeometryAttribute ga; |
238 | 12.9k | ga.Init(attribute()->attribute_type(), nullptr, num_components, DT_INT32, |
239 | 12.9k | false, num_components * DataTypeLength(DT_INT32), 0); |
240 | 12.9k | std::unique_ptr<PointAttribute> port_att(new PointAttribute(ga)); |
241 | 12.9k | port_att->SetIdentityMapping(); |
242 | 12.9k | port_att->Reset(num_entries); |
243 | 12.9k | port_att->set_unique_id(attribute()->unique_id()); |
244 | 12.9k | SetPortableAttribute(std::move(port_att)); |
245 | 12.9k | } |
246 | | |
247 | | } // namespace draco |