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