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