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