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/config/compression_shared.h"
16 #include "draco/compression/entropy/symbol_decoding.h"
17 #include "draco/compression/entropy/symbol_encoding.h"
18 #include "draco/core/bit_utils.h"
19 #include "draco/core/decoder_buffer.h"
20 #include "draco/core/draco_test_base.h"
21 #include "draco/core/encoder_buffer.h"
22 
23 namespace draco {
24 
25 class SymbolCodingTest : public ::testing::Test {
26  protected:
SymbolCodingTest()27   SymbolCodingTest() : bitstream_version_(kDracoMeshBitstreamVersion) {}
28 
29   template <class SignedIntTypeT>
TestConvertToSymbolAndBack(SignedIntTypeT x)30   void TestConvertToSymbolAndBack(SignedIntTypeT x) {
31     typedef typename std::make_unsigned<SignedIntTypeT>::type Symbol;
32     Symbol symbol = ConvertSignedIntToSymbol(x);
33     SignedIntTypeT y = ConvertSymbolToSignedInt(symbol);
34     ASSERT_EQ(x, y);
35   }
36 
37   uint16_t bitstream_version_;
38 };
39 
TEST_F(SymbolCodingTest,TestLargeNumbers)40 TEST_F(SymbolCodingTest, TestLargeNumbers) {
41   // This test verifies that SymbolCoding successfully encodes an array of large
42   // numbers.
43   const uint32_t in[] = {12345678, 1223333, 111, 5};
44   const int num_values = sizeof(in) / sizeof(uint32_t);
45   EncoderBuffer eb;
46   ASSERT_TRUE(EncodeSymbols(in, num_values, 1, nullptr, &eb));
47 
48   std::vector<uint32_t> out;
49   out.resize(num_values);
50   DecoderBuffer db;
51   db.Init(eb.data(), eb.size());
52   db.set_bitstream_version(bitstream_version_);
53   ASSERT_TRUE(DecodeSymbols(num_values, 1, &db, &out[0]));
54   for (int i = 0; i < num_values; ++i) {
55     EXPECT_EQ(in[i], out[i]);
56   }
57 }
58 
TEST_F(SymbolCodingTest,TestManyNumbers)59 TEST_F(SymbolCodingTest, TestManyNumbers) {
60   // This test verifies that SymbolCoding successfully encodes an array of
61   // several numbers that repeat many times.
62 
63   // Value/frequency pairs.
64   const std::pair<uint32_t, uint32_t> in[] = {
65       {12, 1500}, {1025, 31000}, {7, 1}, {9, 5}, {0, 6432}};
66 
67   const int num_pairs = sizeof(in) / sizeof(std::pair<uint32_t, uint32_t>);
68 
69   std::vector<uint32_t> in_values;
70   for (int i = 0; i < num_pairs; ++i) {
71     in_values.insert(in_values.end(), in[i].second, in[i].first);
72   }
73   for (int method = 0; method < NUM_SYMBOL_CODING_METHODS; ++method) {
74     // Test the encoding using all available symbol coding methods.
75     Options options;
76     SetSymbolEncodingMethod(&options, static_cast<SymbolCodingMethod>(method));
77 
78     EncoderBuffer eb;
79     ASSERT_TRUE(
80         EncodeSymbols(in_values.data(), in_values.size(), 1, &options, &eb));
81     std::vector<uint32_t> out_values;
82     out_values.resize(in_values.size());
83     DecoderBuffer db;
84     db.Init(eb.data(), eb.size());
85     db.set_bitstream_version(bitstream_version_);
86     ASSERT_TRUE(DecodeSymbols(in_values.size(), 1, &db, &out_values[0]));
87     for (uint32_t i = 0; i < in_values.size(); ++i) {
88       ASSERT_EQ(in_values[i], out_values[i]);
89     }
90   }
91 }
92 
TEST_F(SymbolCodingTest,TestEmpty)93 TEST_F(SymbolCodingTest, TestEmpty) {
94   // This test verifies that SymbolCoding successfully encodes an empty array.
95   EncoderBuffer eb;
96   ASSERT_TRUE(EncodeSymbols(nullptr, 0, 1, nullptr, &eb));
97   DecoderBuffer db;
98   db.Init(eb.data(), eb.size());
99   db.set_bitstream_version(bitstream_version_);
100   ASSERT_TRUE(DecodeSymbols(0, 1, &db, nullptr));
101 }
102 
TEST_F(SymbolCodingTest,TestOneSymbol)103 TEST_F(SymbolCodingTest, TestOneSymbol) {
104   // This test verifies that SymbolCoding successfully encodes an a single
105   // symbol.
106   EncoderBuffer eb;
107   const std::vector<uint32_t> in(1200, 0);
108   ASSERT_TRUE(EncodeSymbols(in.data(), in.size(), 1, nullptr, &eb));
109 
110   std::vector<uint32_t> out(in.size());
111   DecoderBuffer db;
112   db.Init(eb.data(), eb.size());
113   db.set_bitstream_version(bitstream_version_);
114   ASSERT_TRUE(DecodeSymbols(in.size(), 1, &db, &out[0]));
115   for (uint32_t i = 0; i < in.size(); ++i) {
116     ASSERT_EQ(in[i], out[i]);
117   }
118 }
119 
TEST_F(SymbolCodingTest,TestBitLengths)120 TEST_F(SymbolCodingTest, TestBitLengths) {
121   // This test verifies that SymbolCoding successfully encodes symbols of
122   // various bit lengths
123   EncoderBuffer eb;
124   std::vector<uint32_t> in;
125   constexpr int bit_lengths = 18;
126   for (int i = 0; i < bit_lengths; ++i) {
127     in.push_back(1 << i);
128   }
129   std::vector<uint32_t> out(in.size());
130   for (int i = 0; i < bit_lengths; ++i) {
131     eb.Clear();
132     ASSERT_TRUE(EncodeSymbols(in.data(), i + 1, 1, nullptr, &eb));
133     DecoderBuffer db;
134     db.Init(eb.data(), eb.size());
135     db.set_bitstream_version(bitstream_version_);
136     ASSERT_TRUE(DecodeSymbols(i + 1, 1, &db, &out[0]));
137     for (int j = 0; j < i + 1; ++j) {
138       ASSERT_EQ(in[j], out[j]);
139     }
140   }
141 }
142 
TEST_F(SymbolCodingTest,TestLargeNumberCondition)143 TEST_F(SymbolCodingTest, TestLargeNumberCondition) {
144   // This test verifies that SymbolCoding successfully encodes large symbols
145   // that are on the boundary between raw scheme and tagged scheme (18 bits).
146   EncoderBuffer eb;
147   constexpr int num_symbols = 1000000;
148   const std::vector<uint32_t> in(num_symbols, 1 << 18);
149   ASSERT_TRUE(EncodeSymbols(in.data(), in.size(), 1, nullptr, &eb));
150 
151   std::vector<uint32_t> out(in.size());
152   DecoderBuffer db;
153   db.Init(eb.data(), eb.size());
154   db.set_bitstream_version(bitstream_version_);
155   ASSERT_TRUE(DecodeSymbols(in.size(), 1, &db, &out[0]));
156   for (uint32_t i = 0; i < in.size(); ++i) {
157     ASSERT_EQ(in[i], out[i]);
158   }
159 }
160 
TEST_F(SymbolCodingTest,TestConversionFullRange)161 TEST_F(SymbolCodingTest, TestConversionFullRange) {
162   TestConvertToSymbolAndBack(static_cast<int8_t>(-128));
163   TestConvertToSymbolAndBack(static_cast<int8_t>(-127));
164   TestConvertToSymbolAndBack(static_cast<int8_t>(-1));
165   TestConvertToSymbolAndBack(static_cast<int8_t>(0));
166   TestConvertToSymbolAndBack(static_cast<int8_t>(1));
167   TestConvertToSymbolAndBack(static_cast<int8_t>(127));
168 }
169 
170 }  // namespace draco
171