Coverage Report

Created: 2022-08-24 06:33

/src/libjxl/lib/jxl/enc_ans.h
Line
Count
Source (jump to first uncovered line)
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_ENC_ANS_H_
7
#define LIB_JXL_ENC_ANS_H_
8
9
// Library to encode the ANS population counts to the bit-stream and encode
10
// symbols based on the respective distributions.
11
12
#include <stddef.h>
13
#include <stdint.h>
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <string.h>
17
18
#include <algorithm>
19
#include <vector>
20
21
#include "lib/jxl/ans_common.h"
22
#include "lib/jxl/ans_params.h"
23
#include "lib/jxl/aux_out.h"
24
#include "lib/jxl/aux_out_fwd.h"
25
#include "lib/jxl/base/compiler_specific.h"
26
#include "lib/jxl/base/status.h"
27
#include "lib/jxl/dec_ans.h"
28
#include "lib/jxl/enc_ans_params.h"
29
#include "lib/jxl/enc_bit_writer.h"
30
#include "lib/jxl/huffman_table.h"
31
32
namespace jxl {
33
34
#define USE_MULT_BY_RECIPROCAL
35
36
// precision must be equal to:  #bits(state_) + #bits(freq)
37
0
#define RECIPROCAL_PRECISION (32 + ANS_LOG_TAB_SIZE)
38
39
// Data structure representing one element of the encoding table built
40
// from a distribution.
41
// TODO(veluca): split this up, or use an union.
42
struct ANSEncSymbolInfo {
43
  // ANS
44
  uint16_t freq_;
45
  std::vector<uint16_t> reverse_map_;
46
#ifdef USE_MULT_BY_RECIPROCAL
47
  uint64_t ifreq_;
48
#endif
49
  // Prefix coding.
50
  uint8_t depth;
51
  uint16_t bits;
52
};
53
54
class ANSCoder {
55
 public:
56
0
  ANSCoder() : state_(ANS_SIGNATURE << 16) {}
57
58
0
  uint32_t PutSymbol(const ANSEncSymbolInfo& t, uint8_t* nbits) {
59
0
    uint32_t bits = 0;
60
0
    *nbits = 0;
61
0
    if ((state_ >> (32 - ANS_LOG_TAB_SIZE)) >= t.freq_) {
62
0
      bits = state_ & 0xffff;
63
0
      state_ >>= 16;
64
0
      *nbits = 16;
65
0
    }
66
0
#ifdef USE_MULT_BY_RECIPROCAL
67
    // We use mult-by-reciprocal trick, but that requires 64b calc.
68
0
    const uint32_t v = (state_ * t.ifreq_) >> RECIPROCAL_PRECISION;
69
0
    const uint32_t offset = t.reverse_map_[state_ - v * t.freq_];
70
0
    state_ = (v << ANS_LOG_TAB_SIZE) + offset;
71
#else
72
    state_ = ((state_ / t.freq_) << ANS_LOG_TAB_SIZE) +
73
             t.reverse_map_[state_ % t.freq_];
74
#endif
75
0
    return bits;
76
0
  }
77
78
0
  uint32_t GetState() const { return state_; }
79
80
 private:
81
  uint32_t state_;
82
};
83
84
// RebalanceHistogram requires a signed type.
85
using ANSHistBin = int32_t;
86
87
struct EntropyEncodingData {
88
  std::vector<std::vector<ANSEncSymbolInfo>> encoding_info;
89
  bool use_prefix_code;
90
  std::vector<HybridUintConfig> uint_config;
91
  LZ77Params lz77;
92
};
93
94
// Integer to be encoded by an entropy coder, either ANS or Huffman.
95
struct Token {
96
736
  Token() {}
97
  Token(uint32_t c, uint32_t value)
98
14.8k
      : is_lz77_length(false), context(c), value(value) {}
99
  uint32_t is_lz77_length : 1;
100
  uint32_t context : 31;
101
  uint32_t value;
102
};
103
104
// Returns an estimate of the number of bits required to encode the given
105
// histogram (header bits plus data bits).
106
float ANSPopulationCost(const ANSHistBin* data, size_t alphabet_size);
107
108
// Apply context clustering, compute histograms and encode them. Returns an
109
// estimate of the total bits used for encoding the stream. If `writer` ==
110
// nullptr, the bit estimate will not take into account the context map (which
111
// does not get written if `num_contexts` == 1).
112
size_t BuildAndEncodeHistograms(const HistogramParams& params,
113
                                size_t num_contexts,
114
                                std::vector<std::vector<Token>>& tokens,
115
                                EntropyEncodingData* codes,
116
                                std::vector<uint8_t>* context_map,
117
                                BitWriter* writer, size_t layer,
118
                                AuxOut* aux_out);
119
120
// Write the tokens to a string.
121
void WriteTokens(const std::vector<Token>& tokens,
122
                 const EntropyEncodingData& codes,
123
                 const std::vector<uint8_t>& context_map, BitWriter* writer,
124
                 size_t layer, AuxOut* aux_out);
125
126
// Same as above, but assumes allotment created by caller.
127
size_t WriteTokens(const std::vector<Token>& tokens,
128
                   const EntropyEncodingData& codes,
129
                   const std::vector<uint8_t>& context_map, BitWriter* writer);
130
131
// Exposed for tests; to be used with Writer=BitWriter only.
132
template <typename Writer>
133
void EncodeUintConfigs(const std::vector<HybridUintConfig>& uint_config,
134
                       Writer* writer, size_t log_alpha_size);
135
extern template void EncodeUintConfigs(const std::vector<HybridUintConfig>&,
136
                                       BitWriter*, size_t);
137
138
// Globally set the option to create fuzzer-friendly ANS streams. Negatively
139
// impacts compression. Not thread-safe.
140
void SetANSFuzzerFriendly(bool ans_fuzzer_friendly);
141
}  // namespace jxl
142
143
#endif  // LIB_JXL_ENC_ANS_H_