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