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