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