tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

frame_header.h (16987B)


      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_FRAME_HEADER_H_
      7 #define LIB_JXL_FRAME_HEADER_H_
      8 
      9 // Frame header with backward and forward-compatible extension capability and
     10 // compressed integer fields.
     11 
     12 #include <algorithm>
     13 #include <array>
     14 #include <cstddef>
     15 #include <cstdint>
     16 #include <string>
     17 #include <vector>
     18 
     19 #include "lib/jxl/base/common.h"
     20 #include "lib/jxl/base/compiler_specific.h"
     21 #include "lib/jxl/base/status.h"
     22 #include "lib/jxl/coeff_order_fwd.h"
     23 #include "lib/jxl/common.h"  // kMaxNumPasses
     24 #include "lib/jxl/dec_bit_reader.h"
     25 #include "lib/jxl/field_encodings.h"
     26 #include "lib/jxl/fields.h"
     27 #include "lib/jxl/frame_dimensions.h"
     28 #include "lib/jxl/image_metadata.h"
     29 #include "lib/jxl/loop_filter.h"
     30 
     31 namespace jxl {
     32 
     33 // TODO(eustas): move to proper place?
     34 // Also used by extra channel names.
     35 static inline Status VisitNameString(Visitor* JXL_RESTRICT visitor,
     36                                     std::string* name) {
     37  uint32_t name_length = static_cast<uint32_t>(name->length());
     38  // Allows layer name lengths up to 1071 bytes
     39  JXL_QUIET_RETURN_IF_ERROR(visitor->U32(Val(0), Bits(4), BitsOffset(5, 16),
     40                                         BitsOffset(10, 48), 0, &name_length));
     41  if (visitor->IsReading()) {
     42    name->resize(name_length);
     43  }
     44  for (size_t i = 0; i < name_length; i++) {
     45    uint32_t c = static_cast<uint8_t>((*name)[i]);
     46    JXL_QUIET_RETURN_IF_ERROR(visitor->Bits(8, 0, &c));
     47    (*name)[i] = static_cast<char>(c);
     48  }
     49  return true;
     50 }
     51 
     52 enum class FrameEncoding : uint32_t {
     53  kVarDCT,
     54  kModular,
     55 };
     56 
     57 enum class ColorTransform : uint32_t {
     58  kXYB,    // Values are encoded with XYB. May only be used if
     59           // ImageBundle::xyb_encoded.
     60  kNone,   // Values are encoded according to the attached color profile. May
     61           // only be used if !ImageBundle::xyb_encoded.
     62  kYCbCr,  // Values are encoded according to the attached color profile, but
     63           // transformed to YCbCr. May only be used if
     64           // !ImageBundle::xyb_encoded.
     65 };
     66 
     67 inline std::array<int, 3> JpegOrder(ColorTransform ct, bool is_gray) {
     68  if (is_gray) {
     69    return {{0, 0, 0}};
     70  }
     71  if (ct == ColorTransform::kYCbCr) {
     72    return {{1, 0, 2}};
     73  } else if (ct == ColorTransform::kNone) {
     74    return {{0, 1, 2}};
     75  } else {
     76    JXL_DEBUG_ABORT("Internal logic error");
     77    return {{0, 1, 2}};
     78  }
     79 }
     80 
     81 struct YCbCrChromaSubsampling : public Fields {
     82  YCbCrChromaSubsampling();
     83  JXL_FIELDS_NAME(YCbCrChromaSubsampling)
     84  size_t HShift(size_t c) const { return maxhs_ - kHShift[channel_mode_[c]]; }
     85  size_t VShift(size_t c) const { return maxvs_ - kVShift[channel_mode_[c]]; }
     86 
     87  Status VisitFields(Visitor* JXL_RESTRICT visitor) override {
     88    // TODO(veluca): consider allowing 4x downsamples
     89    for (uint32_t& ch : channel_mode_) {
     90      JXL_QUIET_RETURN_IF_ERROR(visitor->Bits(2, 0, &ch));
     91    }
     92    Recompute();
     93    return true;
     94  }
     95 
     96  uint8_t MaxHShift() const { return maxhs_; }
     97  uint8_t MaxVShift() const { return maxvs_; }
     98 
     99  uint8_t RawHShift(size_t c) const { return kHShift[channel_mode_[c]]; }
    100  uint8_t RawVShift(size_t c) const { return kVShift[channel_mode_[c]]; }
    101 
    102  // Uses JPEG channel order (Y, Cb, Cr).
    103  Status Set(const uint8_t* hsample, const uint8_t* vsample) {
    104    for (size_t c = 0; c < 3; c++) {
    105      size_t cjpeg = c < 2 ? c ^ 1 : c;
    106      size_t i = 0;
    107      for (; i < 4; i++) {
    108        if (1 << kHShift[i] == hsample[cjpeg] &&
    109            1 << kVShift[i] == vsample[cjpeg]) {
    110          channel_mode_[c] = i;
    111          break;
    112        }
    113      }
    114      if (i == 4) {
    115        return JXL_FAILURE("Invalid subsample mode");
    116      }
    117    }
    118    Recompute();
    119    return true;
    120  }
    121 
    122  bool Is444() const {
    123    return HShift(0) == 0 && VShift(0) == 0 &&  // Cb
    124           HShift(2) == 0 && VShift(2) == 0 &&  // Cr
    125           HShift(1) == 0 && VShift(1) == 0;    // Y
    126  }
    127 
    128  bool Is420() const {
    129    return HShift(0) == 1 && VShift(0) == 1 &&  // Cb
    130           HShift(2) == 1 && VShift(2) == 1 &&  // Cr
    131           HShift(1) == 0 && VShift(1) == 0;    // Y
    132  }
    133 
    134  bool Is422() const {
    135    return HShift(0) == 1 && VShift(0) == 0 &&  // Cb
    136           HShift(2) == 1 && VShift(2) == 0 &&  // Cr
    137           HShift(1) == 0 && VShift(1) == 0;    // Y
    138  }
    139 
    140  bool Is440() const {
    141    return HShift(0) == 0 && VShift(0) == 1 &&  // Cb
    142           HShift(2) == 0 && VShift(2) == 1 &&  // Cr
    143           HShift(1) == 0 && VShift(1) == 0;    // Y
    144  }
    145 
    146  std::string DebugString() const {
    147    if (Is444()) return "444";
    148    if (Is420()) return "420";
    149    if (Is422()) return "422";
    150    if (Is440()) return "440";
    151    return "cs" + std::to_string(channel_mode_[0]) +
    152           std::to_string(channel_mode_[1]) + std::to_string(channel_mode_[2]);
    153  }
    154 
    155 private:
    156  void Recompute() {
    157    maxhs_ = 0;
    158    maxvs_ = 0;
    159    for (uint32_t ch : channel_mode_) {
    160      maxhs_ = std::max(maxhs_, kHShift[ch]);
    161      maxvs_ = std::max(maxvs_, kVShift[ch]);
    162    }
    163  }
    164  static const uint8_t kHShift[4];
    165  static const uint8_t kVShift[4];
    166  uint32_t channel_mode_[3];
    167  uint8_t maxhs_;
    168  uint8_t maxvs_;
    169 };
    170 
    171 // Indicates how to combine the current frame with a previously-saved one. Can
    172 // be independently controlled for color and extra channels. Formulas are
    173 // indicative and treat alpha as if it is in range 0.0-1.0. In descriptions
    174 // below, alpha channel is the extra channel of type alpha used for blending
    175 // according to the blend_channel, or fully opaque if there is no alpha channel.
    176 // The blending specified here is used for performing blending *after* color
    177 // transforms - in linear sRGB if blending a XYB-encoded frame on another
    178 // XYB-encoded frame, in sRGB if blending a frame with kColorSpace == kSRGB, or
    179 // in the original colorspace otherwise. Blending in XYB or YCbCr is done by
    180 // using patches.
    181 enum class BlendMode {
    182  // The new values (in the crop) replace the old ones: sample = new
    183  kReplace = 0,
    184  // The new values (in the crop) get added to the old ones: sample = old + new
    185  kAdd = 1,
    186  // The new values (in the crop) replace the old ones if alpha>0:
    187  // For the alpha channel that is used as source:
    188  // alpha = old + new * (1 - old)
    189  // For other channels if !alpha_associated:
    190  // sample = ((1 - new_alpha) * old * old_alpha + new_alpha * new) / alpha
    191  // For other channels if alpha_associated:
    192  // sample = (1 - new_alpha) * old + new
    193  // The alpha formula applies to the alpha used for the division in the other
    194  // channels formula, and applies to the alpha channel itself if its
    195  // blend_channel value matches itself.
    196  kBlend = 2,
    197  // The new values (in the crop) are added to the old ones if alpha>0:
    198  // For the alpha channel that is used as source:
    199  // sample = sample = old + new * (1 - old)
    200  // For other channels: sample = old + alpha * new
    201  kAlphaWeightedAdd = 3,
    202  // The new values (in the crop) get multiplied by the old ones:
    203  // sample = old * new
    204  // The range of the new value matters for multiplication purposes, and its
    205  // nominal range of 0..1 is computed the same way as this is done for the
    206  // alpha values in kBlend and kAlphaWeightedAdd.
    207  // If using kMul as a blend mode for color channels, no color transform is
    208  // performed on the current frame.
    209  kMul = 4,
    210 };
    211 
    212 struct BlendingInfo : public Fields {
    213  BlendingInfo();
    214  JXL_FIELDS_NAME(BlendingInfo)
    215  Status VisitFields(Visitor* JXL_RESTRICT visitor) override;
    216  BlendMode mode;
    217  // Which extra channel to use as alpha channel for blending, only encoded
    218  // for blend modes that involve alpha and if there are more than 1 extra
    219  // channels.
    220  uint32_t alpha_channel;
    221  // Clamp alpha or channel values to 0-1 range.
    222  bool clamp;
    223  // Frame ID to copy from (0-3). Only encoded if blend_mode is not kReplace.
    224  uint32_t source;
    225 
    226  std::string DebugString() const;
    227 
    228  size_t nonserialized_num_extra_channels = 0;
    229  bool nonserialized_is_partial_frame = false;
    230 };
    231 
    232 // Origin of the current frame. Not present for frames of type
    233 // kOnlyPatches.
    234 struct FrameOrigin {
    235  int32_t x0, y0;  // can be negative.
    236 };
    237 
    238 // Size of the current frame.
    239 struct FrameSize {
    240  uint32_t xsize, ysize;
    241 };
    242 
    243 // AnimationFrame defines duration of animation frames.
    244 struct AnimationFrame : public Fields {
    245  explicit AnimationFrame(const CodecMetadata* metadata);
    246  JXL_FIELDS_NAME(AnimationFrame)
    247 
    248  Status VisitFields(Visitor* JXL_RESTRICT visitor) override;
    249 
    250  // How long to wait [in ticks, see Animation{}] after rendering.
    251  // May be 0 if the current frame serves as a foundation for another frame.
    252  uint32_t duration;
    253 
    254  uint32_t timecode;  // 0xHHMMSSFF
    255 
    256  // Must be set to the one ImageMetadata acting as the full codestream header,
    257  // with correct xyb_encoded, list of extra channels, etc...
    258  const CodecMetadata* nonserialized_metadata = nullptr;
    259 };
    260 
    261 // For decoding to lower resolutions. Only used for kRegular frames.
    262 struct Passes : public Fields {
    263  Passes();
    264  JXL_FIELDS_NAME(Passes)
    265 
    266  Status VisitFields(Visitor* JXL_RESTRICT visitor) override;
    267 
    268  void GetDownsamplingBracket(size_t pass, int& minShift, int& maxShift) const {
    269    maxShift = 2;
    270    minShift = 3;
    271    for (size_t i = 0;; i++) {
    272      for (uint32_t j = 0; j < num_downsample; ++j) {
    273        if (i == last_pass[j]) {
    274          if (downsample[j] == 8) minShift = 3;
    275          if (downsample[j] == 4) minShift = 2;
    276          if (downsample[j] == 2) minShift = 1;
    277          if (downsample[j] == 1) minShift = 0;
    278        }
    279      }
    280      if (i == num_passes - 1) minShift = 0;
    281      if (i == pass) return;
    282      maxShift = minShift - 1;
    283    }
    284  }
    285 
    286  uint32_t GetDownsamplingTargetForCompletedPasses(uint32_t num_p) const {
    287    if (num_p >= num_passes) return 1;
    288    uint32_t retval = 8;
    289    for (uint32_t i = 0; i < num_downsample; ++i) {
    290      if (num_p > last_pass[i]) {
    291        retval = std::min(retval, downsample[i]);
    292      }
    293    }
    294    return retval;
    295  }
    296 
    297  std::string DebugString() const;
    298 
    299  uint32_t num_passes;      // <= kMaxNumPasses
    300  uint32_t num_downsample;  // <= num_passes
    301 
    302  // Array of num_downsample pairs. downsample=1/last_pass=num_passes-1 and
    303  // downsample=8/last_pass=0 need not be specified; they are implicit.
    304  uint32_t downsample[kMaxNumPasses];
    305  uint32_t last_pass[kMaxNumPasses];
    306  // Array of shift values for each pass. It is implicitly assumed to be 0 for
    307  // the last pass.
    308  uint32_t shift[kMaxNumPasses];
    309 };
    310 
    311 enum FrameType {
    312  // A "regular" frame: might be a crop, and will be blended on a previous
    313  // frame, if any, and displayed or blended in future frames.
    314  kRegularFrame = 0,
    315  // A DC frame: this frame is downsampled and will be *only* used as the DC of
    316  // a future frame and, possibly, for previews. Cannot be cropped, blended, or
    317  // referenced by patches or blending modes. Frames that *use* a DC frame
    318  // cannot have non-default sizes either.
    319  kDCFrame = 1,
    320  // A PatchesSource frame: this frame will be only used as a source frame for
    321  // taking patches. Can be cropped, but cannot have non-(0, 0) x0 and y0.
    322  kReferenceOnly = 2,
    323  // Same as kRegularFrame, but not used for progressive rendering. This also
    324  // implies no early display of DC.
    325  kSkipProgressive = 3,
    326 };
    327 
    328 // Image/frame := one of more of these, where the last has is_last = true.
    329 // Starts at a byte-aligned address "a"; the next pass starts at "a + size".
    330 struct FrameHeader : public Fields {
    331  // Optional postprocessing steps. These flags are the source of truth;
    332  // Override must set/clear them rather than change their meaning. Values
    333  // chosen such that typical flags == 0 (encoded in only two bits).
    334  enum Flags {
    335    // Often but not always off => low bit value:
    336 
    337    // Inject noise into decoded output.
    338    kNoise = 1,
    339 
    340    // Overlay patches.
    341    kPatches = 2,
    342 
    343    // 4, 8 = reserved for future sometimes-off
    344 
    345    // Overlay splines.
    346    kSplines = 16,
    347 
    348    kUseDcFrame = 32,  // Implies kSkipAdaptiveDCSmoothing.
    349 
    350    // 64 = reserved for future often-off
    351 
    352    // Almost always on => negated:
    353 
    354    kSkipAdaptiveDCSmoothing = 128,
    355  };
    356 
    357  explicit FrameHeader(const CodecMetadata* metadata);
    358  JXL_FIELDS_NAME(FrameHeader)
    359 
    360  Status VisitFields(Visitor* JXL_RESTRICT visitor) override;
    361 
    362  // Sets/clears `flag` based upon `condition`.
    363  void UpdateFlag(const bool condition, const uint64_t flag) {
    364    if (condition) {
    365      flags |= flag;
    366    } else {
    367      flags &= ~flag;
    368    }
    369  }
    370 
    371  // Returns true if this frame is supposed to be saved for future usage by
    372  // other frames.
    373  bool CanBeReferenced() const {
    374    // DC frames cannot be referenced. The last frame cannot be referenced. A
    375    // duration 0 frame makes little sense if it is not referenced. A
    376    // non-duration 0 frame may or may not be referenced.
    377    return !is_last && frame_type != FrameType::kDCFrame &&
    378           (animation_frame.duration == 0 || save_as_reference != 0);
    379  }
    380 
    381  mutable bool all_default;
    382 
    383  // Always present
    384  FrameEncoding encoding;
    385  // Some versions of UBSAN complain in VisitFrameType if not initialized.
    386  FrameType frame_type = FrameType::kRegularFrame;
    387 
    388  uint64_t flags;
    389 
    390  ColorTransform color_transform;
    391  YCbCrChromaSubsampling chroma_subsampling;
    392 
    393  uint32_t group_size_shift;  // only if encoding == kModular;
    394 
    395  uint32_t x_qm_scale;  // only if VarDCT and color_transform == kXYB
    396  uint32_t b_qm_scale;  // only if VarDCT and color_transform == kXYB
    397 
    398  std::string name;
    399 
    400  // Skipped for kReferenceOnly.
    401  Passes passes;
    402 
    403  // Skipped for kDCFrame
    404  bool custom_size_or_origin;
    405  FrameSize frame_size;
    406 
    407  // upsampling factors for color and extra channels.
    408  // Upsampling is always performed before applying any inverse color transform.
    409  // Skipped (1) if kUseDCFrame
    410  uint32_t upsampling;
    411  std::vector<uint32_t> extra_channel_upsampling;
    412 
    413  // Only for kRegular frames.
    414  FrameOrigin frame_origin;
    415 
    416  BlendingInfo blending_info;
    417  std::vector<BlendingInfo> extra_channel_blending_info;
    418 
    419  // Animation info for this frame.
    420  AnimationFrame animation_frame;
    421 
    422  // This is the last frame.
    423  bool is_last;
    424 
    425  // ID to refer to this frame with. 0-3, not present if kDCFrame.
    426  // 0 has a special meaning for kRegular frames of nonzero duration: it defines
    427  // a frame that will not be referenced in the future.
    428  uint32_t save_as_reference;
    429 
    430  // Whether to save this frame before or after the color transform. A frame
    431  // that is saved before the color transform can only be used for blending
    432  // through patches. On the contrary, a frame that is saved after the color
    433  // transform can only be used for blending through blending modes.
    434  // Irrelevant for extra channel blending. Can only be true if
    435  // blending_info.mode == kReplace and this is not a partial kRegularFrame; if
    436  // this is a DC frame, it is always true.
    437  bool save_before_color_transform;
    438 
    439  uint32_t dc_level;  // 1-4 if kDCFrame (0 otherwise).
    440 
    441  // Must be set to the one ImageMetadata acting as the full codestream header,
    442  // with correct xyb_encoded, list of extra channels, etc...
    443  const CodecMetadata* nonserialized_metadata = nullptr;
    444 
    445  // NOTE: This is ignored by AllDefault.
    446  LoopFilter loop_filter;
    447 
    448  bool nonserialized_is_preview = false;
    449 
    450  size_t default_xsize() const {
    451    if (!nonserialized_metadata) return 0;
    452    if (nonserialized_is_preview) {
    453      return nonserialized_metadata->m.preview_size.xsize();
    454    }
    455    return nonserialized_metadata->xsize();
    456  }
    457 
    458  size_t default_ysize() const {
    459    if (!nonserialized_metadata) return 0;
    460    if (nonserialized_is_preview) {
    461      return nonserialized_metadata->m.preview_size.ysize();
    462    }
    463    return nonserialized_metadata->ysize();
    464  }
    465 
    466  FrameDimensions ToFrameDimensions() const {
    467    size_t xsize = default_xsize();
    468    size_t ysize = default_ysize();
    469 
    470    xsize = frame_size.xsize ? frame_size.xsize : xsize;
    471    ysize = frame_size.ysize ? frame_size.ysize : ysize;
    472 
    473    if (dc_level != 0) {
    474      xsize = DivCeil(xsize, 1 << (3 * dc_level));
    475      ysize = DivCeil(ysize, 1 << (3 * dc_level));
    476    }
    477 
    478    FrameDimensions frame_dim;
    479    frame_dim.Set(xsize, ysize, group_size_shift,
    480                  chroma_subsampling.MaxHShift(),
    481                  chroma_subsampling.MaxVShift(),
    482                  encoding == FrameEncoding::kModular, upsampling);
    483    return frame_dim;
    484  }
    485 
    486  // True if a color transform should be applied to this frame.
    487  bool needs_color_transform() const {
    488    return !save_before_color_transform ||
    489           frame_type == FrameType::kRegularFrame ||
    490           frame_type == FrameType::kSkipProgressive;
    491  }
    492 
    493  std::string DebugString() const;
    494 
    495  uint64_t extensions;
    496 };
    497 
    498 Status ReadFrameHeader(BitReader* JXL_RESTRICT reader,
    499                       FrameHeader* JXL_RESTRICT frame);
    500 
    501 // Shared by enc/dec. 5F and 13 are by far the most common for d1/2/4/8, 0
    502 // ensures low overhead for small images.
    503 static constexpr U32Enc kOrderEnc =
    504    U32Enc(Val(0x5F), Val(0x13), Val(0), Bits(kNumOrders));
    505 
    506 }  // namespace jxl
    507 
    508 #endif  // LIB_JXL_FRAME_HEADER_H_