Make decoder more robust, build and Javascript fixes

1. Add 'use strict'to example Javascript.
2. Small fixes to README.md.
3. Fix Draco compiler flag tests.
4. Fixed issue when number of quantized bits was to large.
5. Changed StartDecoding to return a value.
6. Check that num of attributes are not less than 0.
7. Check that the number of attributes is a valid value.
This commit is contained in:
Frank Galligan 2017-01-23 14:55:45 -08:00
parent b0215d525b
commit 3682ca2801
19 changed files with 81 additions and 44 deletions

View File

@ -32,7 +32,7 @@ _**Contents**_
* [CMake Build Configuration](#cmake-build-config) * [CMake Build Configuration](#cmake-build-config)
* [Debugging and Optimization](#debugging-and-optimization) * [Debugging and Optimization](#debugging-and-optimization)
* [Googletest Integration](#googletest-integration) * [Googletest Integration](#googletest-integration)
* [Javascript Decoder](#build-javascript-decoder) * [Javascript Decoder](#javascript-decoder)
* [Android Studio Project Integration](#android-studio-project-integration) * [Android Studio Project Integration](#android-studio-project-integration)
* [Usage](#usage) * [Usage](#usage)
* [Command Line Applications](#command-line-applications) * [Command Line Applications](#command-line-applications)
@ -40,7 +40,7 @@ _**Contents**_
* [Encoding Point Clouds](#encoding-point-clouds) * [Encoding Point Clouds](#encoding-point-clouds)
* [Decoding Tool](#decoding-tool) * [Decoding Tool](#decoding-tool)
* [C++ Decoder API](#c-decoder-api) * [C++ Decoder API](#c-decoder-api)
* [Javascript Decoder](#javascript-decoder) * [Javascript Decoder API](#javascript-decoder-api)
* [Javascript Decoder Performance](#javascript-decoder-performance) * [Javascript Decoder Performance](#javascript-decoder-performance)
* [three.js Renderer Example](#threejs-renderer-example) * [three.js Renderer Example](#threejs-renderer-example)
* [Support](#support) * [Support](#support)
@ -95,7 +95,7 @@ C:\Users\nobody> cmake path/to/draco -G "Visual Studio 14 2015"
To generate 64-bit Windows Visual Studio 2015 projects: To generate 64-bit Windows Visual Studio 2015 projects:
~~~~~ bash ~~~~~ bash
C:\Users\nobody> cmake path/to/draco "Visual Studio 14 2015 Win64" C:\Users\nobody> cmake path/to/draco -G "Visual Studio 14 2015 Win64"
~~~~~ ~~~~~
@ -314,8 +314,8 @@ if (geom_type == draco::TRIANGULAR_MESH) {
Please see `mesh/mesh.h` for the full Mesh class interface and Please see `mesh/mesh.h` for the full Mesh class interface and
`point_cloud/point_cloud.h` for the full `PointCloud` class interface. `point_cloud/point_cloud.h` for the full `PointCloud` class interface.
Javascript Decoder Javascript Decoder API
------------------ ----------------------
The Javascript decoder is located in `javascript/draco_decoder.js`. The The Javascript decoder is located in `javascript/draco_decoder.js`. The
Javascript decoder can decode mesh and point cloud. In order to use the Javascript decoder can decode mesh and point cloud. In order to use the

View File

@ -66,13 +66,13 @@ function (require_cxx_flag cxx_flag)
string(FIND "${CMAKE_CXX_FLAGS}" "${cxx_flag}" CXX_FLAG_FOUND) string(FIND "${CMAKE_CXX_FLAGS}" "${cxx_flag}" CXX_FLAG_FOUND)
if (${CXX_FLAG_FOUND} EQUAL -1) if (${CXX_FLAG_FOUND} EQUAL -1)
unset(DRACO_HAVE_CXX_FLAG) unset(DRACO_HAVE_CXX_FLAG CACHE)
message("Checking CXX compiler flag support for: " ${cxx_flag}) message("Checking CXX compiler flag support for: " ${cxx_flag})
check_cxx_compiler_flag("${cxx_flag}" DRACO_HAVE_CXX_FLAG) check_cxx_compiler_flag("${cxx_flag}" DRACO_HAVE_CXX_FLAG)
if (NOT DRACO_HAVE_CXX_FLAG) if (NOT DRACO_HAVE_CXX_FLAG)
message(FATAL_ERROR "Draco requires support for CXX flag: ${flag}.") message(FATAL_ERROR "Draco requires support for CXX flag: ${cxx_flag}.")
endif () endif ()
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}" CACHE STRING "" FORCE) set(CMAKE_CXX_FLAGS "${cxx_flag} ${CMAKE_CXX_FLAGS}" CACHE STRING "" FORCE)
endif () endif ()
endfunction () endfunction ()

View File

@ -28,7 +28,7 @@ bool AttributesDecoder::Initialize(PointCloudDecoder *decoder, PointCloud *pc) {
bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) { bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
// Decode and create attributes. // Decode and create attributes.
int32_t num_attributes; int32_t num_attributes;
if (!in_buffer->Decode(&num_attributes)) if (!in_buffer->Decode(&num_attributes) || num_attributes <= 0)
return false; return false;
point_attribute_ids_.resize(num_attributes); point_attribute_ids_.resize(num_attributes);
PointCloud *pc = point_cloud_; PointCloud *pc = point_cloud_;

View File

@ -186,7 +186,8 @@ bool MeshPredictionSchemeTexCoords<DataTypeT, TransformT, MeshDataT>::
orientations_.resize(num_orientations); orientations_.resize(num_orientations);
bool last_orientation = true; bool last_orientation = true;
BinaryDecoder decoder; BinaryDecoder decoder;
decoder.StartDecoding(buffer); if (!decoder.StartDecoding(buffer))
return false;
for (int i = 0; i < num_orientations; ++i) { for (int i = 0; i < num_orientations; ++i) {
if (!decoder.DecodeNextBit()) if (!decoder.DecodeNextBit())
last_orientation = !last_orientation; last_orientation = !last_orientation;

View File

@ -54,7 +54,8 @@ bool SequentialQuantizationAttributeDecoder::DecodeQuantizedDataInfo() {
if (!decoder()->buffer()->Decode(&max_value_dif_)) if (!decoder()->buffer()->Decode(&max_value_dif_))
return false; return false;
uint8_t quantization_bits; uint8_t quantization_bits;
if (!decoder()->buffer()->Decode(&quantization_bits)) if (!decoder()->buffer()->Decode(&quantization_bits) ||
quantization_bits > 31)
return false; return false;
quantization_bits_ = quantization_bits; quantization_bits_ = quantization_bits;
return true; return true;

View File

@ -220,7 +220,8 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
last_vert_id_ = -1; last_vert_id_ = -1;
int8_t num_attribute_data; int8_t num_attribute_data;
if (!decoder_->buffer()->Decode(&num_attribute_data)) if (!decoder_->buffer()->Decode(&num_attribute_data) ||
num_attribute_data < 0)
return false; return false;
attribute_data_.clear(); attribute_data_.clear();

View File

@ -156,10 +156,14 @@ bool IntegerPointsKdTreeDecoder<PointDiT, compression_level_t>::DecodePoints(
if (num_points_ == 0) if (num_points_ == 0)
return true; return true;
numbers_decoder_.StartDecoding(buffer); if (!numbers_decoder_.StartDecoding(buffer))
remaining_bits_decoder_.StartDecoding(buffer); return false;
axis_decoder_.StartDecoding(buffer); if (!remaining_bits_decoder_.StartDecoding(buffer))
half_decoder_.StartDecoding(buffer); return false;
if (!axis_decoder_.StartDecoding(buffer))
return false;
if (!half_decoder_.StartDecoding(buffer))
return false;
OctreeDecode(num_points_, PointTraits<PointDiT>::Origin(), OctreeDecode(num_points_, PointTraits<PointDiT>::Origin(),
PointTraits<PointDiT>::ZeroArray(), 0, oit); PointTraits<PointDiT>::ZeroArray(), 0, oit);

View File

@ -76,16 +76,21 @@ AdaptiveRAnsBitDecoder::AdaptiveRAnsBitDecoder() : p0_f_(0.5) {}
AdaptiveRAnsBitDecoder::~AdaptiveRAnsBitDecoder() { Clear(); } AdaptiveRAnsBitDecoder::~AdaptiveRAnsBitDecoder() { Clear(); }
void AdaptiveRAnsBitDecoder::StartDecoding(DecoderBuffer *source_buffer) { bool AdaptiveRAnsBitDecoder::StartDecoding(DecoderBuffer *source_buffer) {
Clear(); Clear();
uint32_t size_in_bytes; uint32_t size_in_bytes;
source_buffer->Decode(&size_in_bytes); if (!source_buffer->Decode(&size_in_bytes))
return false;
ans_read_init(&ans_decoder_, reinterpret_cast<uint8_t *>(const_cast<char *>( if (size_in_bytes > source_buffer->remaining_size())
source_buffer->data_head())), return false;
size_in_bytes); if (ans_read_init(&ans_decoder_,
reinterpret_cast<uint8_t *>(
const_cast<char *>(source_buffer->data_head())),
size_in_bytes) != 0)
return false;
source_buffer->Advance(size_in_bytes); source_buffer->Advance(size_in_bytes);
return true;
} }
bool AdaptiveRAnsBitDecoder::DecodeNextBit() { bool AdaptiveRAnsBitDecoder::DecodeNextBit() {

View File

@ -65,7 +65,7 @@ class AdaptiveRAnsBitDecoder {
~AdaptiveRAnsBitDecoder(); ~AdaptiveRAnsBitDecoder();
// Sets |source_buffer| as the buffer to decode bits from. // Sets |source_buffer| as the buffer to decode bits from.
void StartDecoding(DecoderBuffer *source_buffer); bool StartDecoding(DecoderBuffer *source_buffer);
// Decode one bit. Returns true if the bit is a 1, otherwsie false. // Decode one bit. Returns true if the bit is a 1, otherwsie false.
bool DecodeNextBit(); bool DecodeNextBit();

View File

@ -411,7 +411,8 @@ class RAnsDecoder {
RAnsDecoder() {} RAnsDecoder() {}
// Initializes the decoder from the input buffer. The |offset| specifies the // Initializes the decoder from the input buffer. The |offset| specifies the
// number of bytes encoded by the encoder. // number of bytes encoded by the encoder. A non zero return value is an
// error.
inline int read_init(const uint8_t *const buf, int offset) { inline int read_init(const uint8_t *const buf, int offset) {
unsigned x; unsigned x;
if (offset < 1) if (offset < 1)
@ -485,7 +486,9 @@ class RAnsDecoder {
} }
act_prob = cum_prob; act_prob = cum_prob;
} }
assert(cum_prob == rans_precision); if (cum_prob != rans_precision) {
return false;
}
return true; return true;
} }

View File

@ -41,14 +41,19 @@ DirectBitDecoder::DirectBitDecoder() : pos_(bits_.end()), num_used_bits_(0) {}
DirectBitDecoder::~DirectBitDecoder() { Clear(); } DirectBitDecoder::~DirectBitDecoder() { Clear(); }
void DirectBitDecoder::StartDecoding(DecoderBuffer *source_buffer) { bool DirectBitDecoder::StartDecoding(DecoderBuffer *source_buffer) {
Clear(); Clear();
uint32_t size_in_bytes; uint32_t size_in_bytes;
source_buffer->Decode(&size_in_bytes); if (!source_buffer->Decode(&size_in_bytes))
return false;
if (size_in_bytes > source_buffer->remaining_size())
return false;
bits_.resize(size_in_bytes / 4); bits_.resize(size_in_bytes / 4);
source_buffer->Decode(bits_.data(), size_in_bytes); if (!source_buffer->Decode(bits_.data(), size_in_bytes))
return false;
pos_ = bits_.begin(); pos_ = bits_.begin();
num_used_bits_ = 0; num_used_bits_ = 0;
return true;
} }
void DirectBitDecoder::Clear() { void DirectBitDecoder::Clear() {

View File

@ -91,7 +91,7 @@ class DirectBitDecoder {
~DirectBitDecoder(); ~DirectBitDecoder();
// Sets |source_buffer| as the buffer to decode bits from. // Sets |source_buffer| as the buffer to decode bits from.
void StartDecoding(DecoderBuffer *source_buffer); bool StartDecoding(DecoderBuffer *source_buffer);
// Decode one bit. Returns true if the bit is a 1, otherwsie false. // Decode one bit. Returns true if the bit is a 1, otherwsie false.
bool DecodeNextBit() { bool DecodeNextBit() {

View File

@ -84,11 +84,12 @@ class FoldedBit32Decoder {
~FoldedBit32Decoder() {} ~FoldedBit32Decoder() {}
// Sets |source_buffer| as the buffer to decode bits from. // Sets |source_buffer| as the buffer to decode bits from.
void StartDecoding(DecoderBuffer *source_buffer) { bool StartDecoding(DecoderBuffer *source_buffer) {
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
folded_number_decoders_[i].StartDecoding(source_buffer); if (!folded_number_decoders_[i].StartDecoding(source_buffer))
return false;
} }
bit_decoder_.StartDecoding(source_buffer); return bit_decoder_.StartDecoding(source_buffer);
} }
// Decode one bit. Returns true if the bit is a 1, otherwise false. // Decode one bit. Returns true if the bit is a 1, otherwise false.

View File

@ -125,17 +125,21 @@ RAnsBitDecoder::~RAnsBitDecoder() { Clear(); }
bool RAnsBitDecoder::StartDecoding(DecoderBuffer *source_buffer) { bool RAnsBitDecoder::StartDecoding(DecoderBuffer *source_buffer) {
Clear(); Clear();
source_buffer->Decode(&prob_zero_); if (!source_buffer->Decode(&prob_zero_))
return false;
uint32_t size_in_bytes; uint32_t size_in_bytes;
source_buffer->Decode(&size_in_bytes); if (!source_buffer->Decode(&size_in_bytes))
return false;
if (size_in_bytes > source_buffer->remaining_size()) if (size_in_bytes > source_buffer->remaining_size())
return false; return false;
ans_read_init(&ans_decoder_, reinterpret_cast<uint8_t *>(const_cast<char *>( if (ans_read_init(&ans_decoder_,
source_buffer->data_head())), reinterpret_cast<uint8_t *>(
size_in_bytes); const_cast<char *>(source_buffer->data_head())),
size_in_bytes) != 0)
return false;
source_buffer->Advance(size_in_bytes); source_buffer->Advance(size_in_bytes);
return true; return true;
} }

View File

@ -36,7 +36,7 @@ class RAnsSymbolDecoder {
// Starts decoding from the buffer. The buffer will be advanced past the // Starts decoding from the buffer. The buffer will be advanced past the
// encoded data after this call. // encoded data after this call.
void StartDecoding(DecoderBuffer *buffer); bool StartDecoding(DecoderBuffer *buffer);
uint32_t DecodeSymbol() { return ans_.rans_read(); } uint32_t DecodeSymbol() { return ans_.rans_read(); }
void EndDecoding(); void EndDecoding();
@ -84,16 +84,21 @@ bool RAnsSymbolDecoder<max_symbol_bit_length_t>::Create(DecoderBuffer *buffer) {
} }
template <int max_symbol_bit_length_t> template <int max_symbol_bit_length_t>
void RAnsSymbolDecoder<max_symbol_bit_length_t>::StartDecoding( bool RAnsSymbolDecoder<max_symbol_bit_length_t>::StartDecoding(
DecoderBuffer *buffer) { DecoderBuffer *buffer) {
uint64_t bytes_encoded; uint64_t bytes_encoded;
// Decode the number of bytes encoded by the encoder. // Decode the number of bytes encoded by the encoder.
buffer->Decode(&bytes_encoded); if (!buffer->Decode(&bytes_encoded))
return false;
if (bytes_encoded > buffer->remaining_size())
return false;
const uint8_t *const data_head = const uint8_t *const data_head =
reinterpret_cast<const uint8_t *>(buffer->data_head()); reinterpret_cast<const uint8_t *>(buffer->data_head());
// Advance the buffer past the rANS data. // Advance the buffer past the rANS data.
buffer->Advance(bytes_encoded); buffer->Advance(bytes_encoded);
ans_.read_init(data_head, bytes_encoded); if (ans_.read_init(data_head, bytes_encoded) != 0)
return false;
return true;
} }
template <int max_symbol_bit_length_t> template <int max_symbol_bit_length_t>

View File

@ -71,7 +71,8 @@ bool DecodeTaggedSymbols(int num_values, int num_components,
if (!tag_decoder.Create(src_buffer)) if (!tag_decoder.Create(src_buffer))
return false; return false;
tag_decoder.StartDecoding(src_buffer); if (!tag_decoder.StartDecoding(src_buffer))
return false;
if (num_values > 0 && tag_decoder.num_symbols() == 0) if (num_values > 0 && tag_decoder.num_symbols() == 0)
return false; // Wrong number of symbols. return false; // Wrong number of symbols.
@ -106,7 +107,8 @@ bool DecodeRawSymbolsInternal(int num_values, DecoderBuffer *src_buffer,
if (num_values > 0 && decoder.num_symbols() == 0) if (num_values > 0 && decoder.num_symbols() == 0)
return false; // Wrong number of symbols. return false; // Wrong number of symbols.
decoder.StartDecoding(src_buffer); if (!decoder.StartDecoding(src_buffer))
return false;
for (int i = 0; i < num_values; ++i) { for (int i = 0; i < num_values; ++i) {
// Decode a symbol into the value. // Decode a symbol into the value.
const uint32_t value = decoder.DecodeSymbol(); const uint32_t value = decoder.DecodeSymbol();

View File

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// //
'use strict';
THREE.DRACOLoader = function(manager) { THREE.DRACOLoader = function(manager) {
this.manager = (manager !== undefined) ? manager : this.manager = (manager !== undefined) ? manager :
THREE.DefaultLoadingManager; THREE.DefaultLoadingManager;

View File

@ -45,11 +45,13 @@
<script src="draco_decoder.js"></script> <script src="draco_decoder.js"></script>
<script src="DRACOLoader.js"></script> <script src="DRACOLoader.js"></script>
<script> <script>
'use strict';
// Module that exposes all the core funcionality of the Draco decoder. // Module that exposes all the core funcionality of the Draco decoder.
const DracoModule = Module; const DracoModule = Module;
let container; let container;
let camera, scene, renderer; let camera, cameraTarget, scene, renderer;
let mouseX = 0, mouseY = 0; let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2; let windowHalfX = window.innerWidth / 2;

View File

@ -5,6 +5,7 @@
<script type="text/javascript" src="draco_decoder.js"> </script> <script type="text/javascript" src="draco_decoder.js"> </script>
<script type="text/javascript"> <script type="text/javascript">
'use strict';
// String to hold table output. // String to hold table output.
let dt = ''; let dt = '';