Coverage Report

Created: 2022-08-24 06:04

/src/libjxl/lib/jxl/dec_huffman.cc
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
#include "lib/jxl/dec_huffman.h"
7
8
#include <string.h> /* for memset */
9
10
#include <vector>
11
12
#include "lib/jxl/ans_params.h"
13
#include "lib/jxl/base/bits.h"
14
#include "lib/jxl/huffman_table.h"
15
16
namespace jxl {
17
18
static const int kCodeLengthCodes = 18;
19
static const uint8_t kCodeLengthCodeOrder[kCodeLengthCodes] = {
20
    1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
21
};
22
static const uint8_t kDefaultCodeLength = 8;
23
static const uint8_t kCodeLengthRepeatCode = 16;
24
25
int ReadHuffmanCodeLengths(const uint8_t* code_length_code_lengths,
26
                           int num_symbols, uint8_t* code_lengths,
27
0
                           BitReader* br) {
28
0
  int symbol = 0;
29
0
  uint8_t prev_code_len = kDefaultCodeLength;
30
0
  int repeat = 0;
31
0
  uint8_t repeat_code_len = 0;
32
0
  int space = 32768;
33
0
  HuffmanCode table[32];
34
35
0
  uint16_t counts[16] = {0};
36
0
  for (int i = 0; i < kCodeLengthCodes; ++i) {
37
0
    ++counts[code_length_code_lengths[i]];
38
0
  }
39
0
  if (!BuildHuffmanTable(table, 5, code_length_code_lengths, kCodeLengthCodes,
40
0
                         &counts[0])) {
41
0
    return 0;
42
0
  }
43
44
0
  while (symbol < num_symbols && space > 0) {
45
0
    const HuffmanCode* p = table;
46
0
    uint8_t code_len;
47
0
    br->Refill();
48
0
    p += br->PeekFixedBits<5>();
49
0
    br->Consume(p->bits);
50
0
    code_len = (uint8_t)p->value;
51
0
    if (code_len < kCodeLengthRepeatCode) {
52
0
      repeat = 0;
53
0
      code_lengths[symbol++] = code_len;
54
0
      if (code_len != 0) {
55
0
        prev_code_len = code_len;
56
0
        space -= 32768u >> code_len;
57
0
      }
58
0
    } else {
59
0
      const int extra_bits = code_len - 14;
60
0
      int old_repeat;
61
0
      int repeat_delta;
62
0
      uint8_t new_len = 0;
63
0
      if (code_len == kCodeLengthRepeatCode) {
64
0
        new_len = prev_code_len;
65
0
      }
66
0
      if (repeat_code_len != new_len) {
67
0
        repeat = 0;
68
0
        repeat_code_len = new_len;
69
0
      }
70
0
      old_repeat = repeat;
71
0
      if (repeat > 0) {
72
0
        repeat -= 2;
73
0
        repeat <<= extra_bits;
74
0
      }
75
0
      repeat += (int)br->ReadBits(extra_bits) + 3;
76
0
      repeat_delta = repeat - old_repeat;
77
0
      if (symbol + repeat_delta > num_symbols) {
78
0
        return 0;
79
0
      }
80
0
      memset(&code_lengths[symbol], repeat_code_len, (size_t)repeat_delta);
81
0
      symbol += repeat_delta;
82
0
      if (repeat_code_len != 0) {
83
0
        space -= repeat_delta << (15 - repeat_code_len);
84
0
      }
85
0
    }
86
0
  }
87
0
  if (space != 0) {
88
0
    return 0;
89
0
  }
90
0
  memset(&code_lengths[symbol], 0, (size_t)(num_symbols - symbol));
91
0
  return true;
92
0
}
93
94
static JXL_INLINE bool ReadSimpleCode(size_t alphabet_size, BitReader* br,
95
0
                                      HuffmanCode* table) {
96
0
  size_t max_bits =
97
0
      (alphabet_size > 1u) ? FloorLog2Nonzero(alphabet_size - 1u) + 1 : 0;
98
99
0
  size_t num_symbols = br->ReadFixedBits<2>() + 1;
100
101
0
  uint16_t symbols[4] = {0};
102
0
  for (size_t i = 0; i < num_symbols; ++i) {
103
0
    uint16_t symbol = br->ReadBits(max_bits);
104
0
    if (symbol >= alphabet_size) {
105
0
      return false;
106
0
    }
107
0
    symbols[i] = symbol;
108
0
  }
109
110
0
  for (size_t i = 0; i < num_symbols - 1; ++i) {
111
0
    for (size_t j = i + 1; j < num_symbols; ++j) {
112
0
      if (symbols[i] == symbols[j]) return false;
113
0
    }
114
0
  }
115
116
  // 4 symbols have to option to encode.
117
0
  if (num_symbols == 4) num_symbols += br->ReadFixedBits<1>();
118
119
0
  const auto swap_symbols = [&symbols](size_t i, size_t j) {
120
0
    uint16_t t = symbols[j];
121
0
    symbols[j] = symbols[i];
122
0
    symbols[i] = t;
123
0
  };
124
125
0
  size_t table_size = 1;
126
0
  switch (num_symbols) {
127
0
    case 1:
128
0
      table[0] = {0, symbols[0]};
129
0
      break;
130
0
    case 2:
131
0
      if (symbols[0] > symbols[1]) swap_symbols(0, 1);
132
0
      table[0] = {1, symbols[0]};
133
0
      table[1] = {1, symbols[1]};
134
0
      table_size = 2;
135
0
      break;
136
0
    case 3:
137
0
      if (symbols[1] > symbols[2]) swap_symbols(1, 2);
138
0
      table[0] = {1, symbols[0]};
139
0
      table[2] = {1, symbols[0]};
140
0
      table[1] = {2, symbols[1]};
141
0
      table[3] = {2, symbols[2]};
142
0
      table_size = 4;
143
0
      break;
144
0
    case 4: {
145
0
      for (size_t i = 0; i < 3; ++i) {
146
0
        for (size_t j = i + 1; j < 4; ++j) {
147
0
          if (symbols[i] > symbols[j]) swap_symbols(i, j);
148
0
        }
149
0
      }
150
0
      table[0] = {2, symbols[0]};
151
0
      table[2] = {2, symbols[1]};
152
0
      table[1] = {2, symbols[2]};
153
0
      table[3] = {2, symbols[3]};
154
0
      table_size = 4;
155
0
      break;
156
0
    }
157
0
    case 5: {
158
0
      if (symbols[2] > symbols[3]) swap_symbols(2, 3);
159
0
      table[0] = {1, symbols[0]};
160
0
      table[1] = {2, symbols[1]};
161
0
      table[2] = {1, symbols[0]};
162
0
      table[3] = {3, symbols[2]};
163
0
      table[4] = {1, symbols[0]};
164
0
      table[5] = {2, symbols[1]};
165
0
      table[6] = {1, symbols[0]};
166
0
      table[7] = {3, symbols[3]};
167
0
      table_size = 8;
168
0
      break;
169
0
    }
170
0
    default: {
171
      // Unreachable.
172
0
      return false;
173
0
    }
174
0
  }
175
176
0
  const uint32_t goal_size = 1u << kHuffmanTableBits;
177
0
  while (table_size != goal_size) {
178
0
    memcpy(&table[table_size], &table[0],
179
0
           (size_t)table_size * sizeof(table[0]));
180
0
    table_size <<= 1;
181
0
  }
182
183
0
  return true;
184
0
}
185
186
bool HuffmanDecodingData::ReadFromBitStream(size_t alphabet_size,
187
0
                                            BitReader* br) {
188
0
  if (alphabet_size > (1 << PREFIX_MAX_BITS)) return false;
189
190
  /* simple_code_or_skip is used as follows:
191
     1 for simple code;
192
     0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
193
0
  uint32_t simple_code_or_skip = br->ReadFixedBits<2>();
194
0
  if (simple_code_or_skip == 1u) {
195
0
    table_.resize(1u << kHuffmanTableBits);
196
0
    return ReadSimpleCode(alphabet_size, br, table_.data());
197
0
  }
198
199
0
  std::vector<uint8_t> code_lengths(alphabet_size, 0);
200
0
  uint8_t code_length_code_lengths[kCodeLengthCodes] = {0};
201
0
  int space = 32;
202
0
  int num_codes = 0;
203
  /* Static Huffman code for the code length code lengths */
204
0
  static const HuffmanCode huff[16] = {
205
0
      {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 1},
206
0
      {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 5},
207
0
  };
208
0
  for (size_t i = simple_code_or_skip; i < kCodeLengthCodes && space > 0; ++i) {
209
0
    const int code_len_idx = kCodeLengthCodeOrder[i];
210
0
    const HuffmanCode* p = huff;
211
0
    uint8_t v;
212
0
    br->Refill();
213
0
    p += br->PeekFixedBits<4>();
214
0
    br->Consume(p->bits);
215
0
    v = (uint8_t)p->value;
216
0
    code_length_code_lengths[code_len_idx] = v;
217
0
    if (v != 0) {
218
0
      space -= (32u >> v);
219
0
      ++num_codes;
220
0
    }
221
0
  }
222
0
  bool ok = (num_codes == 1 || space == 0) &&
223
0
            ReadHuffmanCodeLengths(code_length_code_lengths, alphabet_size,
224
0
                                   &code_lengths[0], br);
225
226
0
  if (!ok) return false;
227
0
  uint16_t counts[16] = {0};
228
0
  for (size_t i = 0; i < alphabet_size; ++i) {
229
0
    ++counts[code_lengths[i]];
230
0
  }
231
0
  table_.resize(alphabet_size + 376);
232
0
  uint32_t table_size =
233
0
      BuildHuffmanTable(table_.data(), kHuffmanTableBits, &code_lengths[0],
234
0
                        alphabet_size, &counts[0]);
235
0
  table_.resize(table_size);
236
0
  return (table_size > 0);
237
0
}
238
239
// Decodes the next Huffman coded symbol from the bit-stream.
240
0
uint16_t HuffmanDecodingData::ReadSymbol(BitReader* br) const {
241
0
  size_t n_bits;
242
0
  const HuffmanCode* table = table_.data();
243
0
  table += br->PeekBits(kHuffmanTableBits);
244
0
  n_bits = table->bits;
245
0
  if (n_bits > kHuffmanTableBits) {
246
0
    br->Consume(kHuffmanTableBits);
247
0
    n_bits -= kHuffmanTableBits;
248
0
    table += table->value;
249
0
    table += br->PeekBits(n_bits);
250
0
  }
251
0
  br->Consume(table->bits);
252
0
  return table->value;
253
0
}
254
255
}  // namespace jxl