bit_reader_test.cc (7668B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #include <stddef.h> 7 #include <stdint.h> 8 9 #include <array> 10 #include <vector> 11 12 #include "lib/jxl/base/common.h" 13 #include "lib/jxl/base/data_parallel.h" 14 #include "lib/jxl/base/random.h" 15 #include "lib/jxl/base/span.h" 16 #include "lib/jxl/dec_bit_reader.h" 17 #include "lib/jxl/enc_aux_out.h" 18 #include "lib/jxl/enc_bit_writer.h" 19 #include "lib/jxl/test_utils.h" 20 #include "lib/jxl/testing.h" 21 22 namespace jxl { 23 namespace { 24 25 TEST(BitReaderTest, ExtendsWithZeroes) { 26 for (size_t size = 4; size < 32; ++size) { 27 std::vector<uint8_t> data(size, 0xff); 28 29 for (size_t n_bytes = 0; n_bytes < size; n_bytes++) { 30 BitReader br(Bytes(data.data(), n_bytes)); 31 // Read all the bits 32 for (size_t i = 0; i < n_bytes * kBitsPerByte; i++) { 33 ASSERT_EQ(br.ReadBits(1), 1u) << "n_bytes=" << n_bytes << " i=" << i; 34 } 35 36 // PEEK more than the declared size - all will be zero. Cannot consume. 37 for (size_t i = 0; i < BitReader::kMaxBitsPerCall; i++) { 38 ASSERT_EQ(br.PeekBits(i), 0u) 39 << "size=" << size << "n_bytes=" << n_bytes << " i=" << i; 40 } 41 42 EXPECT_TRUE(br.Close()); 43 } 44 } 45 } 46 47 struct Symbol { 48 uint32_t num_bits; 49 uint32_t value; 50 }; 51 52 // Reading from output gives the same values. 53 TEST(BitReaderTest, TestRoundTrip) { 54 test::ThreadPoolForTests pool(8); 55 EXPECT_TRUE(RunOnPool( 56 &pool, 0, 1000, ThreadPool::NoInit, 57 [](const uint32_t task, size_t /* thread */) { 58 constexpr size_t kMaxBits = 8000; 59 BitWriter writer; 60 BitWriter::Allotment allotment(&writer, kMaxBits); 61 62 std::vector<Symbol> symbols; 63 symbols.reserve(1000); 64 65 Rng rng(55537 + 129 * task); 66 67 for (;;) { 68 const uint32_t num_bits = rng.UniformU(1, 33); 69 if (writer.BitsWritten() + num_bits > kMaxBits) break; 70 const uint32_t value = rng.UniformU(0, 1ULL << num_bits); 71 symbols.push_back({num_bits, value}); 72 writer.Write(num_bits, value); 73 } 74 75 writer.ZeroPadToByte(); 76 allotment.ReclaimAndCharge(&writer, 0, nullptr); 77 BitReader reader(writer.GetSpan()); 78 for (const Symbol& s : symbols) { 79 EXPECT_EQ(s.value, reader.ReadBits(s.num_bits)); 80 } 81 EXPECT_TRUE(reader.Close()); 82 }, 83 "TestTBitReaderRoundTrip")); 84 } 85 86 // SkipBits is the same as reading that many bits. 87 TEST(BitReaderTest, TestSkip) { 88 test::ThreadPoolForTests pool(8); 89 EXPECT_TRUE(RunOnPool( 90 &pool, 0, 96, ThreadPool::NoInit, 91 [](const uint32_t task, size_t /* thread */) { 92 constexpr size_t kSize = 100; 93 94 for (size_t skip = 0; skip < 128; ++skip) { 95 BitWriter writer; 96 BitWriter::Allotment allotment(&writer, kSize * kBitsPerByte); 97 // Start with "task" 1-bits. 98 for (size_t i = 0; i < task; ++i) { 99 writer.Write(1, 1); 100 } 101 102 // Write 0-bits that we will skip over 103 for (size_t i = 0; i < skip; ++i) { 104 writer.Write(1, 0); 105 } 106 107 // Write terminator bits '101' 108 writer.Write(3, 5); 109 EXPECT_EQ(task + skip + 3, writer.BitsWritten()); 110 writer.ZeroPadToByte(); 111 AuxOut aux_out; 112 allotment.ReclaimAndCharge(&writer, 0, &aux_out); 113 EXPECT_LT(aux_out.layers[0].total_bits, kSize * 8); 114 115 BitReader reader1(writer.GetSpan()); 116 BitReader reader2(writer.GetSpan()); 117 // Verify initial 1-bits 118 for (size_t i = 0; i < task; ++i) { 119 EXPECT_EQ(1u, reader1.ReadBits(1)); 120 EXPECT_EQ(1u, reader2.ReadBits(1)); 121 } 122 123 // SkipBits or manually read "skip" bits 124 reader1.SkipBits(skip); 125 for (size_t i = 0; i < skip; ++i) { 126 EXPECT_EQ(0u, reader2.ReadBits(1)) 127 << " skip=" << skip << " i=" << i; 128 } 129 EXPECT_EQ(reader1.TotalBitsConsumed(), reader2.TotalBitsConsumed()); 130 131 // Ensure both readers see the terminator bits. 132 EXPECT_EQ(5u, reader1.ReadBits(3)); 133 EXPECT_EQ(5u, reader2.ReadBits(3)); 134 135 EXPECT_TRUE(reader1.Close()); 136 EXPECT_TRUE(reader2.Close()); 137 } 138 }, 139 "TestSkip")); 140 } 141 142 // Verifies byte order and different groupings of bits. 143 TEST(BitReaderTest, TestOrder) { 144 constexpr size_t kMaxBits = 16; 145 146 // u(1) - bits written into LSBs of first byte 147 { 148 BitWriter writer; 149 BitWriter::Allotment allotment(&writer, kMaxBits); 150 for (size_t i = 0; i < 5; ++i) { 151 writer.Write(1, 1); 152 } 153 for (size_t i = 0; i < 5; ++i) { 154 writer.Write(1, 0); 155 } 156 for (size_t i = 0; i < 6; ++i) { 157 writer.Write(1, 1); 158 } 159 160 writer.ZeroPadToByte(); 161 allotment.ReclaimAndCharge(&writer, 0, nullptr); 162 BitReader reader(writer.GetSpan()); 163 EXPECT_EQ(0x1Fu, reader.ReadFixedBits<8>()); 164 EXPECT_EQ(0xFCu, reader.ReadFixedBits<8>()); 165 EXPECT_TRUE(reader.Close()); 166 } 167 168 // u(8) - get bytes in the same order 169 { 170 BitWriter writer; 171 BitWriter::Allotment allotment(&writer, kMaxBits); 172 writer.Write(8, 0xF8); 173 writer.Write(8, 0x3F); 174 175 writer.ZeroPadToByte(); 176 allotment.ReclaimAndCharge(&writer, 0, nullptr); 177 BitReader reader(writer.GetSpan()); 178 EXPECT_EQ(0xF8u, reader.ReadFixedBits<8>()); 179 EXPECT_EQ(0x3Fu, reader.ReadFixedBits<8>()); 180 EXPECT_TRUE(reader.Close()); 181 } 182 183 // u(16) - little-endian bytes 184 { 185 BitWriter writer; 186 BitWriter::Allotment allotment(&writer, kMaxBits); 187 writer.Write(16, 0xF83F); 188 189 writer.ZeroPadToByte(); 190 allotment.ReclaimAndCharge(&writer, 0, nullptr); 191 BitReader reader(writer.GetSpan()); 192 EXPECT_EQ(0x3Fu, reader.ReadFixedBits<8>()); 193 EXPECT_EQ(0xF8u, reader.ReadFixedBits<8>()); 194 EXPECT_TRUE(reader.Close()); 195 } 196 197 // Non-byte-aligned, mixed sizes 198 { 199 BitWriter writer; 200 BitWriter::Allotment allotment(&writer, kMaxBits); 201 writer.Write(1, 1); 202 writer.Write(3, 6); 203 writer.Write(8, 0xDB); 204 writer.Write(4, 8); 205 206 writer.ZeroPadToByte(); 207 allotment.ReclaimAndCharge(&writer, 0, nullptr); 208 BitReader reader(writer.GetSpan()); 209 EXPECT_EQ(0xBDu, reader.ReadFixedBits<8>()); 210 EXPECT_EQ(0x8Du, reader.ReadFixedBits<8>()); 211 EXPECT_TRUE(reader.Close()); 212 } 213 } 214 215 TEST(BitReaderTest, TotalCountersTest) { 216 uint8_t buf[8] = {1, 2, 3, 4}; 217 BitReader reader(Bytes(buf, sizeof(buf))); 218 219 EXPECT_EQ(sizeof(buf), reader.TotalBytes()); 220 EXPECT_EQ(0u, reader.TotalBitsConsumed()); 221 reader.ReadFixedBits<1>(); 222 EXPECT_EQ(1u, reader.TotalBitsConsumed()); 223 224 reader.ReadFixedBits<10>(); 225 EXPECT_EQ(11u, reader.TotalBitsConsumed()); 226 227 reader.ReadFixedBits<4>(); 228 EXPECT_EQ(15u, reader.TotalBitsConsumed()); 229 230 reader.ReadFixedBits<1>(); 231 EXPECT_EQ(16u, reader.TotalBitsConsumed()); 232 233 reader.ReadFixedBits<16>(); 234 EXPECT_EQ(32u, reader.TotalBitsConsumed()); 235 236 EXPECT_TRUE(reader.Close()); 237 } 238 239 TEST(BitReaderTest, MoveTest) { 240 uint8_t buf[8] = {1, 2, 3, 4}; 241 BitReader reader2; 242 { 243 BitReader reader1(Bytes(buf, sizeof(buf))); 244 245 EXPECT_EQ(0u, reader1.TotalBitsConsumed()); 246 reader1.ReadFixedBits<16>(); 247 EXPECT_EQ(16u, reader1.TotalBitsConsumed()); 248 249 reader2 = std::move(reader1); 250 // From this point reader1 is invalid, but can continue to access reader2 251 // and we don't need to call Close() on reader1. 252 } 253 254 EXPECT_EQ(16u, reader2.TotalBitsConsumed()); 255 EXPECT_EQ(3U, reader2.ReadFixedBits<8>()); 256 EXPECT_EQ(24u, reader2.TotalBitsConsumed()); 257 258 EXPECT_TRUE(reader2.Close()); 259 } 260 261 } // namespace 262 } // namespace jxl