libjxl

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

fields.h (13982B)


      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 #ifndef LIB_JXL_FIELDS_H_
      7 #define LIB_JXL_FIELDS_H_
      8 
      9 // Forward/backward-compatible 'bundles' with auto-serialized 'fields'.
     10 
     11 #include <cmath>  // abs
     12 #include <cstdarg>
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <cstdlib>
     16 #include <cstring>
     17 
     18 #include "lib/jxl/base/bits.h"
     19 #include "lib/jxl/base/compiler_specific.h"
     20 #include "lib/jxl/base/status.h"
     21 #include "lib/jxl/dec_bit_reader.h"
     22 #include "lib/jxl/field_encodings.h"
     23 
     24 namespace jxl {
     25 
     26 struct AuxOut;
     27 struct BitWriter;
     28 
     29 // Integer coders: BitsCoder (raw), U32Coder (table), U64Coder (varint).
     30 
     31 // Reads/writes a given (fixed) number of bits <= 32.
     32 namespace BitsCoder {
     33 size_t MaxEncodedBits(size_t bits);
     34 
     35 Status CanEncode(size_t bits, uint32_t value,
     36                  size_t* JXL_RESTRICT encoded_bits);
     37 
     38 uint32_t Read(size_t bits, BitReader* JXL_RESTRICT reader);
     39 
     40 // Returns false if the value is too large to encode.
     41 Status Write(size_t bits, uint32_t value, BitWriter* JXL_RESTRICT writer);
     42 }  // namespace BitsCoder
     43 
     44 // Encodes u32 using a lookup table and/or extra bits, governed by a per-field
     45 // encoding `enc` which consists of four distributions `d` chosen via a 2-bit
     46 // selector (least significant = 0). Each d may have two modes:
     47 // - direct: if d.IsDirect(), the value is d.Direct();
     48 // - offset: the value is derived from d.ExtraBits() extra bits plus d.Offset();
     49 // This encoding is denser than Exp-Golomb or Gamma codes when both small and
     50 // large values occur.
     51 //
     52 // Examples:
     53 // Direct: U32Enc(Val(8), Val(16), Val(32), Bits(6)), value 32 => 10b.
     54 // Offset: U32Enc(Val(0), BitsOffset(1, 1), BitsOffset(2, 3), BitsOffset(8, 8))
     55 //   defines the following prefix code:
     56 //   00 -> 0
     57 //   01x -> 1..2
     58 //   10xx -> 3..7
     59 //   11xxxxxxxx -> 8..263
     60 namespace U32Coder {
     61 size_t MaxEncodedBits(U32Enc enc);
     62 Status CanEncode(U32Enc enc, uint32_t value, size_t* JXL_RESTRICT encoded_bits);
     63 uint32_t Read(U32Enc enc, BitReader* JXL_RESTRICT reader);
     64 
     65 // Returns false if the value is too large to encode.
     66 Status Write(U32Enc enc, uint32_t value, BitWriter* JXL_RESTRICT writer);
     67 
     68 // "private"
     69 Status ChooseSelector(U32Enc enc, uint32_t value,
     70                       uint32_t* JXL_RESTRICT selector,
     71                       size_t* JXL_RESTRICT total_bits);
     72 }  // namespace U32Coder
     73 
     74 // Encodes 64-bit unsigned integers with a fixed distribution, taking 2 bits
     75 // to encode 0, 6 bits to encode 1 to 16, 10 bits to encode 17 to 272, 15 bits
     76 // to encode up to 4095, and on the order of log2(value) * 1.125 bits for
     77 // larger values.
     78 namespace U64Coder {
     79 constexpr size_t MaxEncodedBits() { return 2 + 12 + 6 * (8 + 1) + (4 + 1); }
     80 
     81 uint64_t Read(BitReader* JXL_RESTRICT reader);
     82 
     83 // Returns false if the value is too large to encode.
     84 Status Write(uint64_t value, BitWriter* JXL_RESTRICT writer);
     85 
     86 // Can always encode, but useful because it also returns bit size.
     87 Status CanEncode(uint64_t value, size_t* JXL_RESTRICT encoded_bits);
     88 }  // namespace U64Coder
     89 
     90 // IEEE 754 half-precision (binary16). Refuses to read/write NaN/Inf.
     91 namespace F16Coder {
     92 constexpr size_t MaxEncodedBits() { return 16; }
     93 
     94 // Returns false if the bit representation is NaN or infinity
     95 Status Read(BitReader* JXL_RESTRICT reader, float* JXL_RESTRICT value);
     96 
     97 // Returns false if the value is too large to encode.
     98 Status Write(float value, BitWriter* JXL_RESTRICT writer);
     99 Status CanEncode(float value, size_t* JXL_RESTRICT encoded_bits);
    100 }  // namespace F16Coder
    101 
    102 // A "bundle" is a forward- and backward compatible collection of fields.
    103 // They are used for SizeHeader/FrameHeader/GroupHeader. Bundles can be
    104 // extended by appending(!) fields. Optional fields may be omitted from the
    105 // bitstream by conditionally visiting them. When reading new bitstreams with
    106 // old code, we skip unknown fields at the end of the bundle. This requires
    107 // storing the amount of extra appended bits, and that fields are visited in
    108 // chronological order of being added to the format, because old decoders
    109 // cannot skip some future fields and resume reading old fields. Similarly,
    110 // new readers query bits in an "extensions" field to skip (groups of) fields
    111 // not present in old bitstreams. Note that each bundle must include an
    112 // "extensions" field prior to freezing the format, otherwise it cannot be
    113 // extended.
    114 //
    115 // To ensure interoperability, there will be no opaque fields.
    116 //
    117 // HOWTO:
    118 // - basic usage: define a struct with member variables ("fields") and a
    119 //   VisitFields(v) member function that calls v->U32/Bool etc. for each
    120 //   field, specifying their default values. The ctor must call
    121 //   Bundle::Init(this).
    122 //
    123 // - print a trace of visitors: ensure each bundle has a static Name() member
    124 //   function, and change Bundle::Print* to return true.
    125 //
    126 // - optional fields: in VisitFields, add if (v->Conditional(your_condition))
    127 //   { v->Bool(default, &field); }. This prevents reading/writing field
    128 //   if !your_condition, which is typically computed from a prior field.
    129 //   WARNING: to ensure all fields are initialized, do not add an else branch;
    130 //   instead add another if (v->Conditional(!your_condition)).
    131 //
    132 // - repeated fields: for dynamic sizes, use e.g. std::vector and in
    133 //   VisitFields, if (v->IsReading()) field.resize(size) before accessing field.
    134 //   For static or bounded sizes, use an array or std::array. In all cases,
    135 //   simply visit each array element as if it were a normal field.
    136 //
    137 // - nested bundles: add a bundle as a normal field and in VisitFields call
    138 //   JXL_RETURN_IF_ERROR(v->VisitNested(&nested));
    139 //
    140 // - allow future extensions: define a "uint64_t extensions" field and call
    141 //   v->BeginExtensions(&extensions) after visiting all non-extension fields,
    142 //   and `return v->EndExtensions();` after the last extension field.
    143 //
    144 // - encode an entire bundle in one bit if ALL its fields equal their default
    145 //   values: add a "mutable bool all_default" field and as the first visitor:
    146 //   if (v->AllDefault(*this, &all_default)) {
    147 //     // Overwrite all serialized fields, but not any nonserialized_*.
    148 //     v->SetDefault(this);
    149 //     return true;
    150 //   }
    151 //   Note: if extensions are present, AllDefault() == false.
    152 
    153 namespace Bundle {
    154 constexpr size_t kMaxExtensions = 64;  // bits in u64
    155 
    156 // Initializes fields to the default values. It is not recursive to nested
    157 // fields, this function is intended to be called in the constructors so
    158 // each nested field will already Init itself.
    159 void Init(Fields* JXL_RESTRICT fields);
    160 
    161 // Similar to Init, but recursive to nested fields.
    162 void SetDefault(Fields* JXL_RESTRICT fields);
    163 
    164 // Returns whether ALL fields (including `extensions`, if present) are equal
    165 // to their default value.
    166 bool AllDefault(const Fields& fields);
    167 
    168 // Returns max number of bits required to encode a T.
    169 size_t MaxBits(const Fields& fields);
    170 
    171 // Returns whether a header's fields can all be encoded, i.e. they have a
    172 // valid representation. If so, "*total_bits" is the exact number of bits
    173 // required. Called by Write.
    174 Status CanEncode(const Fields& fields, size_t* JXL_RESTRICT extension_bits,
    175                  size_t* JXL_RESTRICT total_bits);
    176 
    177 Status Read(BitReader* reader, Fields* JXL_RESTRICT fields);
    178 
    179 // Returns whether enough bits are available to fully read this bundle using
    180 // Read. Also returns true in case of a codestream error (other than not being
    181 // large enough): that means enough bits are available to determine there's an
    182 // error, use Read to get such error status.
    183 // NOTE: this advances the BitReader, a different one pointing back at the
    184 // original bit position in the codestream must be created to use Read after
    185 // this.
    186 bool CanRead(BitReader* reader, Fields* JXL_RESTRICT fields);
    187 
    188 Status Write(const Fields& fields, BitWriter* JXL_RESTRICT writer, size_t layer,
    189              AuxOut* aux_out);
    190 }  // namespace Bundle
    191 
    192 // Different subclasses of Visitor are passed to implementations of Fields
    193 // throughout their lifetime. Templates used to be used for this but dynamic
    194 // polymorphism produces more compact executables than template reification did.
    195 class Visitor {
    196  public:
    197   virtual ~Visitor() = default;
    198   virtual Status Visit(Fields* fields) = 0;
    199 
    200   virtual Status Bool(bool default_value, bool* JXL_RESTRICT value) = 0;
    201   virtual Status U32(U32Enc, uint32_t, uint32_t*) = 0;
    202 
    203   // Helper to construct U32Enc from U32Distr.
    204   Status U32(const U32Distr d0, const U32Distr d1, const U32Distr d2,
    205              const U32Distr d3, const uint32_t default_value,
    206              uint32_t* JXL_RESTRICT value) {
    207     return U32(U32Enc(d0, d1, d2, d3), default_value, value);
    208   }
    209 
    210   template <typename EnumT>
    211   Status Enum(const EnumT default_value, EnumT* JXL_RESTRICT value) {
    212     uint32_t u32 = static_cast<uint32_t>(*value);
    213     // 00 -> 0
    214     // 01 -> 1
    215     // 10xxxx -> 2..17
    216     // 11yyyyyy -> 18..81
    217     JXL_RETURN_IF_ERROR(U32(Val(0), Val(1), BitsOffset(4, 2), BitsOffset(6, 18),
    218                             static_cast<uint32_t>(default_value), &u32));
    219     *value = static_cast<EnumT>(u32);
    220     return EnumValid(*value);
    221   }
    222 
    223   virtual Status Bits(size_t bits, uint32_t default_value,
    224                       uint32_t* JXL_RESTRICT value) = 0;
    225   virtual Status U64(uint64_t default_value, uint64_t* JXL_RESTRICT value) = 0;
    226   virtual Status F16(float default_value, float* JXL_RESTRICT value) = 0;
    227 
    228   // Returns whether VisitFields should visit some subsequent fields.
    229   // "condition" is typically from prior fields, e.g. flags.
    230   // Overridden by InitVisitor and MaxBitsVisitor.
    231   virtual Status Conditional(bool condition) { return condition; }
    232 
    233   // Overridden by InitVisitor, AllDefaultVisitor and CanEncodeVisitor.
    234   virtual Status AllDefault(const Fields& /*fields*/,
    235                             bool* JXL_RESTRICT all_default) {
    236     JXL_RETURN_IF_ERROR(Bool(true, all_default));
    237     return *all_default;
    238   }
    239 
    240   virtual void SetDefault(Fields* /*fields*/) {
    241     // Do nothing by default, this is overridden by ReadVisitor.
    242   }
    243 
    244   // Returns the result of visiting a nested Bundle.
    245   // Overridden by InitVisitor.
    246   virtual Status VisitNested(Fields* fields) { return Visit(fields); }
    247 
    248   // Overridden by ReadVisitor. Enables dynamically-sized fields.
    249   virtual bool IsReading() const { return false; }
    250 
    251   virtual Status BeginExtensions(uint64_t* JXL_RESTRICT extensions) = 0;
    252   virtual Status EndExtensions() = 0;
    253 };
    254 
    255 namespace fields_internal {
    256 // A bundle can be in one of three states concerning extensions: not-begun,
    257 // active, ended. Bundles may be nested, so we need a stack of states.
    258 class ExtensionStates {
    259  public:
    260   void Push() {
    261     // Initial state = not-begun.
    262     begun_ <<= 1;
    263     ended_ <<= 1;
    264   }
    265 
    266   // Clears current state; caller must check IsEnded beforehand.
    267   void Pop() {
    268     begun_ >>= 1;
    269     ended_ >>= 1;
    270   }
    271 
    272   // Returns true if state == active || state == ended.
    273   Status IsBegun() const { return (begun_ & 1) != 0; }
    274   // Returns true if state != not-begun && state != active.
    275   Status IsEnded() const { return (ended_ & 1) != 0; }
    276 
    277   void Begin() {
    278     JXL_ASSERT(!IsBegun());
    279     JXL_ASSERT(!IsEnded());
    280     begun_ += 1;
    281   }
    282 
    283   void End() {
    284     JXL_ASSERT(IsBegun());
    285     JXL_ASSERT(!IsEnded());
    286     ended_ += 1;
    287   }
    288 
    289  private:
    290   // Current state := least-significant bit of begun_ and ended_.
    291   uint64_t begun_ = 0;
    292   uint64_t ended_ = 0;
    293 };
    294 
    295 // Visitors generate Init/AllDefault/Read/Write logic for all fields. Each
    296 // bundle's VisitFields member function calls visitor->U32 etc. We do not
    297 // overload operator() because a function name is easier to search for.
    298 
    299 class VisitorBase : public Visitor {
    300  public:
    301   explicit VisitorBase() = default;
    302   ~VisitorBase() override { JXL_ASSERT(depth_ == 0); }
    303 
    304   // This is the only call site of Fields::VisitFields.
    305   // Ensures EndExtensions was called.
    306   Status Visit(Fields* fields) override {
    307     depth_ += 1;
    308     JXL_ASSERT(depth_ <= Bundle::kMaxExtensions);
    309     extension_states_.Push();
    310 
    311     const Status ok = fields->VisitFields(this);
    312 
    313     if (ok) {
    314       // If VisitFields called BeginExtensions, must also call
    315       // EndExtensions.
    316       JXL_ASSERT(!extension_states_.IsBegun() || extension_states_.IsEnded());
    317     } else {
    318       // Failed, undefined state: don't care whether EndExtensions was
    319       // called.
    320     }
    321 
    322     extension_states_.Pop();
    323     JXL_ASSERT(depth_ != 0);
    324     depth_ -= 1;
    325 
    326     return ok;
    327   }
    328 
    329   // For visitors accepting a const Visitor, need to const-cast so we can call
    330   // the non-const Visitor::VisitFields. NOTE: C is not modified except the
    331   // `all_default` field by CanEncodeVisitor.
    332   Status VisitConst(const Fields& t) { return Visit(const_cast<Fields*>(&t)); }
    333 
    334   // Derived types (overridden by InitVisitor because it is unsafe to read
    335   // from *value there)
    336 
    337   Status Bool(bool default_value, bool* JXL_RESTRICT value) override {
    338     uint32_t bits = *value ? 1 : 0;
    339     JXL_RETURN_IF_ERROR(Bits(1, static_cast<uint32_t>(default_value), &bits));
    340     JXL_DASSERT(bits <= 1);
    341     *value = bits == 1;
    342     return true;
    343   }
    344 
    345   // Overridden by ReadVisitor and WriteVisitor.
    346   // Called before any conditional visit based on "extensions".
    347   // Overridden by ReadVisitor, CanEncodeVisitor and WriteVisitor.
    348   Status BeginExtensions(uint64_t* JXL_RESTRICT extensions) override {
    349     JXL_RETURN_IF_ERROR(U64(0, extensions));
    350 
    351     extension_states_.Begin();
    352     return true;
    353   }
    354 
    355   // Called after all extension fields (if any). Although non-extension
    356   // fields could be visited afterward, we prefer the convention that
    357   // extension fields are always the last to be visited. Overridden by
    358   // ReadVisitor.
    359   Status EndExtensions() override {
    360     extension_states_.End();
    361     return true;
    362   }
    363 
    364  private:
    365   size_t depth_ = 0;  // to check nesting
    366   ExtensionStates extension_states_;
    367 };
    368 }  // namespace fields_internal
    369 
    370 Status CheckHasEnoughBits(Visitor* visitor, size_t bits);
    371 
    372 }  // namespace jxl
    373 
    374 #endif  // LIB_JXL_FIELDS_H_