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