libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

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