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_