FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/jpegxl_parser.c
Date: 2025-11-10 16:28:23
Exec Total Coverage
Lines: 449 937 47.9%
Functions: 21 27 77.8%
Branches: 254 692 36.7%

Line Branch Exec Source
1 /**
2 * JPEG XL parser
3 * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <errno.h>
23 #include <stdint.h>
24 #include <string.h>
25
26 #include "libavutil/attributes.h"
27 #include "libavutil/error.h"
28 #include "libavutil/intmath.h"
29 #include "libavutil/macros.h"
30 #include "libavutil/mem.h"
31 #include "libavutil/pixfmt.h"
32
33 #include "bytestream.h"
34 #include "codec_id.h"
35 #include "parser_internal.h"
36 #define UNCHECKED_BITSTREAM_READER 0
37 #define BITSTREAM_READER_LE
38 #include "get_bits.h"
39 #include "jpegxl.h"
40 #include "jpegxl_parse.h"
41 #include "parser.h"
42 #include "vlc.h"
43
44 #define JXL_FLAG_NOISE 1
45 #define JXL_FLAG_PATCHES 2
46 #define JXL_FLAG_SPLINES 16
47 #define JXL_FLAG_USE_LF_FRAME 32
48 #define JXL_FLAG_SKIP_ADAPTIVE_LF_SMOOTH 128
49
50 #define MAX_PREFIX_ALPHABET_SIZE (1u << 15)
51
52 #define clog1p(x) (ff_log2(x) + !!(x))
53 #define unpack_signed(x) (((x) & 1 ? -(x)-1 : (x))/2)
54 #define div_ceil(x, y) (((x) - 1) / (y) + 1)
55 #define vlm(a,b) {.sym = (a), .len = (b)}
56
57 typedef struct JXLHybridUintConf {
58 int split_exponent;
59 uint32_t msb_in_token;
60 uint32_t lsb_in_token;
61 } JXLHybridUintConf;
62
63 typedef struct JXLSymbolDistribution {
64 JXLHybridUintConf config;
65 int log_bucket_size;
66 /* this is the actual size of the alphabet */
67 int alphabet_size;
68 /* ceil(log(alphabet_size)) */
69 int log_alphabet_size;
70
71 /* for prefix code distributions */
72 VLC vlc;
73 /* in case bits == 0 */
74 uint32_t default_symbol;
75
76 /*
77 * each (1 << log_alphabet_size) length
78 * with log_alphabet_size <= 8
79 */
80 /* frequencies associated with this Distribution */
81 uint32_t freq[258];
82 /* cutoffs for using the symbol table */
83 uint16_t cutoffs[258];
84 /* the symbol table for this distribution */
85 uint16_t symbols[258];
86 /* the offset for symbols */
87 uint16_t offsets[258];
88
89 /* if this distribution contains only one symbol this is its index */
90 int uniq_pos;
91 } JXLSymbolDistribution;
92
93 typedef struct JXLDistributionBundle {
94 /* lz77 flags */
95 int lz77_enabled;
96 uint32_t lz77_min_symbol;
97 uint32_t lz77_min_length;
98 JXLHybridUintConf lz_len_conf;
99
100 /* one entry for each distribution */
101 uint8_t *cluster_map;
102 /* length of cluster_map */
103 int num_dist;
104
105 /* one for each cluster */
106 JXLSymbolDistribution *dists;
107 int num_clusters;
108
109 /* whether to use brotli prefixes or ans */
110 int use_prefix_code;
111 /* bundle log alphabet size, dist ones may be smaller */
112 int log_alphabet_size;
113 } JXLDistributionBundle;
114
115 typedef struct JXLEntropyDecoder {
116
117 /* state is a positive 32-bit integer, or -1 if unset */
118 int64_t state;
119
120 /* lz77 values */
121 uint32_t num_to_copy;
122 uint32_t copy_pos;
123 uint32_t num_decoded;
124
125 /* length is (1 << 20) */
126 /* if lz77 is enabled for this bundle */
127 /* if lz77 is disabled it's NULL */
128 uint32_t *window;
129
130 /* primary bundle associated with this distribution */
131 JXLDistributionBundle bundle;
132
133 /* for av_log */
134 void *logctx;
135 } JXLEntropyDecoder;
136
137 typedef struct JXLFrame {
138 FFJXLFrameType type;
139 FFJXLFrameEncoding encoding;
140
141 int is_last;
142 int full_frame;
143
144 uint32_t total_length;
145 uint32_t body_length;
146 } JXLFrame;
147
148 typedef struct JXLCodestream {
149 FFJXLMetadata meta;
150 JXLFrame frame;
151 } JXLCodestream;
152
153 typedef struct JXLParseContext {
154 ParseContext pc;
155 JXLCodestream codestream;
156
157 /* using ISOBMFF-based container */
158 int container;
159 int64_t skip;
160 int copied;
161 int64_t collected_size;
162 int64_t codestream_length;
163 int skipped_icc;
164 int64_t next;
165
166 uint8_t cs_buffer[4096 + AV_INPUT_BUFFER_PADDING_SIZE];
167 } JXLParseContext;
168
169 /* used for reading brotli prefixes */
170 static const VLCElem level0_table[16] = {
171 vlm(0, 2), vlm(4, 2), vlm(3, 2), vlm(2, 3), vlm(0, 2), vlm(4, 2), vlm(3, 2), vlm(1, 4),
172 vlm(0, 2), vlm(4, 2), vlm(3, 2), vlm(2, 3), vlm(0, 2), vlm(4, 2), vlm(3, 2), vlm(5, 4),
173 };
174
175 /* prefix table for populating ANS distribution */
176 static const VLCElem dist_prefix_table[128] = {
177 vlm(10, 3), vlm(12, 7), vlm(7, 3), vlm(3, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(5, 4),
178 vlm(10, 3), vlm(4, 4), vlm(7, 3), vlm(1, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(2, 4),
179 vlm(10, 3), vlm(0, 5), vlm(7, 3), vlm(3, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(5, 4),
180 vlm(10, 3), vlm(4, 4), vlm(7, 3), vlm(1, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(2, 4),
181 vlm(10, 3), vlm(11, 6), vlm(7, 3), vlm(3, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(5, 4),
182 vlm(10, 3), vlm(4, 4), vlm(7, 3), vlm(1, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(2, 4),
183 vlm(10, 3), vlm(0, 5), vlm(7, 3), vlm(3, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(5, 4),
184 vlm(10, 3), vlm(4, 4), vlm(7, 3), vlm(1, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(2, 4),
185 vlm(10, 3), vlm(13, 7), vlm(7, 3), vlm(3, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(5, 4),
186 vlm(10, 3), vlm(4, 4), vlm(7, 3), vlm(1, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(2, 4),
187 vlm(10, 3), vlm(0, 5), vlm(7, 3), vlm(3, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(5, 4),
188 vlm(10, 3), vlm(4, 4), vlm(7, 3), vlm(1, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(2, 4),
189 vlm(10, 3), vlm(11, 6), vlm(7, 3), vlm(3, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(5, 4),
190 vlm(10, 3), vlm(4, 4), vlm(7, 3), vlm(1, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(2, 4),
191 vlm(10, 3), vlm(0, 5), vlm(7, 3), vlm(3, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(5, 4),
192 vlm(10, 3), vlm(4, 4), vlm(7, 3), vlm(1, 4), vlm(6, 3), vlm(8, 3), vlm(9, 3), vlm(2, 4),
193 };
194
195 static const uint8_t prefix_codelen_map[18] = {
196 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
197 };
198
199 /**
200 * Read a variable-length 8-bit integer.
201 * Used when populating the ANS frequency tables.
202 */
203 static av_always_inline uint8_t jxl_u8(GetBitContext *gb)
204 {
205 int n;
206 if (!get_bits1(gb))
207 return 0;
208 n = get_bits(gb, 3);
209
210 return get_bitsz(gb, n) | (1 << n);
211 }
212
213 /* read a U32(c_i + u(u_i)) */
214 2412 static av_always_inline uint32_t jxl_u32(GetBitContext *gb,
215 uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3,
216 uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3)
217 {
218 2412 const uint32_t constants[4] = {c0, c1, c2, c3};
219 2412 const uint32_t ubits [4] = {u0, u1, u2, u3};
220 2412 uint32_t ret, choice = get_bits(gb, 2);
221
222 2412 ret = constants[choice];
223
2/2
✓ Branch 0 taken 1590 times.
✓ Branch 1 taken 822 times.
2412 if (ubits[choice])
224 1590 ret += get_bits_long(gb, ubits[choice]);
225
226 2412 return ret;
227 }
228
229 /* read a U64() */
230 530 static uint64_t jxl_u64(GetBitContext *gb)
231 {
232 530 uint64_t shift = 12, ret;
233
234
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 143 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 387 times.
530 switch (get_bits(gb, 2)) {
235 case 1:
236 ret = 1 + get_bits(gb, 4);
237 break;
238 143 case 2:
239 143 ret = 17 + get_bits(gb, 8);
240 143 break;
241 case 3:
242 ret = get_bits(gb, 12);
243 while (get_bits1(gb)) {
244 if (shift < 60) {
245 ret |= (uint64_t)get_bits(gb, 8) << shift;
246 shift += 8;
247 } else {
248 ret |= (uint64_t)get_bits(gb, 4) << shift;
249 break;
250 }
251 }
252 break;
253 387 default:
254 387 ret = 0;
255 }
256
257 530 return ret;
258 }
259
260 143 static int read_hybrid_uint_conf(GetBitContext *gb, JXLHybridUintConf *conf, int log_alphabet_size)
261 {
262 143 conf->split_exponent = get_bitsz(gb, clog1p(log_alphabet_size));
263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (conf->split_exponent == log_alphabet_size) {
264 conf->msb_in_token = conf->lsb_in_token = 0;
265 return 0;
266 }
267
268 143 conf->msb_in_token = get_bitsz(gb, clog1p(conf->split_exponent));
269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (conf->msb_in_token > conf->split_exponent)
270 return AVERROR_INVALIDDATA;
271 143 conf->lsb_in_token = get_bitsz(gb, clog1p(conf->split_exponent - conf->msb_in_token));
272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (conf->msb_in_token + conf->lsb_in_token > conf->split_exponent)
273 return AVERROR_INVALIDDATA;
274
275 143 return 0;
276 }
277
278 875 static int read_hybrid_uint(GetBitContext *gb, const JXLHybridUintConf *conf, uint32_t token, uint32_t *hybrid_uint)
279 {
280 875 uint32_t n, low, split = 1 << conf->split_exponent;
281
282
2/2
✓ Branch 0 taken 849 times.
✓ Branch 1 taken 26 times.
875 if (token < split) {
283 849 *hybrid_uint = token;
284 849 return 0;
285 }
286
287 26 n = conf->split_exponent - conf->lsb_in_token - conf->msb_in_token +
288 26 ((token - split) >> (conf->msb_in_token + conf->lsb_in_token));
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (n >= 32)
290 return AVERROR_INVALIDDATA;
291 26 low = token & ((1 << conf->lsb_in_token) - 1);
292 26 token >>= conf->lsb_in_token;
293 26 token &= (1 << conf->msb_in_token) - 1;
294 26 token |= 1 << conf->msb_in_token;
295 26 *hybrid_uint = (((token << n) | get_bits_long(gb, n)) << conf->lsb_in_token ) | low;
296
297 26 return 0;
298 }
299
300 875 static inline uint32_t read_prefix_symbol(GetBitContext *gb, const JXLSymbolDistribution *dist)
301 {
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 875 times.
875 if (!dist->vlc.bits)
303 return dist->default_symbol;
304
305 875 return get_vlc2(gb, dist->vlc.table, dist->vlc.bits, 1);
306 }
307
308 static uint32_t read_ans_symbol(GetBitContext *gb, JXLEntropyDecoder *dec, const JXLSymbolDistribution *dist)
309 {
310 uint32_t index, i, pos, symbol, offset;
311
312 if (dec->state < 0)
313 dec->state = get_bits_long(gb, 32);
314
315 index = dec->state & 0xFFF;
316 i = index >> dist->log_bucket_size;
317 pos = index & ((1 << dist->log_bucket_size) - 1);
318 symbol = pos >= dist->cutoffs[i] ? dist->symbols[i] : i;
319 offset = pos >= dist->cutoffs[i] ? dist->offsets[i] + pos : pos;
320 dec->state = dist->freq[symbol] * (dec->state >> 12) + offset;
321 if (dec->state < (1 << 16))
322 dec->state = (dec->state << 16) | get_bits(gb, 16);
323 dec->state &= 0xFFFFFFFF;
324
325 return symbol;
326 }
327
328 875 static int decode_hybrid_varlen_uint(GetBitContext *gb, JXLEntropyDecoder *dec,
329 const JXLDistributionBundle *bundle,
330 uint32_t context, uint32_t *hybrid_uint)
331 {
332 int ret;
333 uint32_t token, distance;
334 const JXLSymbolDistribution *dist;
335
336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 875 times.
875 if (dec->num_to_copy > 0) {
337 *hybrid_uint = dec->window[dec->copy_pos++ & 0xFFFFF];
338 dec->num_to_copy--;
339 dec->window[dec->num_decoded++ & 0xFFFFF] = *hybrid_uint;
340 return 0;
341 }
342
343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 875 times.
875 if (context >= bundle->num_dist)
344 return AVERROR(EINVAL);
345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 875 times.
875 if (bundle->cluster_map[context] >= bundle->num_clusters)
346 return AVERROR_INVALIDDATA;
347
348 875 dist = &bundle->dists[bundle->cluster_map[context]];
349
1/2
✓ Branch 0 taken 875 times.
✗ Branch 1 not taken.
875 if (bundle->use_prefix_code)
350 875 token = read_prefix_symbol(gb, dist);
351 else
352 token = read_ans_symbol(gb, dec, dist);
353
354
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 875 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
875 if (bundle->lz77_enabled && token >= bundle->lz77_min_symbol) {
355 const JXLSymbolDistribution *lz77dist = &bundle->dists[bundle->cluster_map[bundle->num_dist - 1]];
356 if (!dec->num_decoded)
357 return AVERROR_INVALIDDATA;
358 ret = read_hybrid_uint(gb, &bundle->lz_len_conf, token - bundle->lz77_min_symbol, &dec->num_to_copy);
359 if (ret < 0)
360 return ret;
361 dec->num_to_copy += bundle->lz77_min_length;
362 if (bundle->use_prefix_code)
363 token = read_prefix_symbol(gb, lz77dist);
364 else
365 token = read_ans_symbol(gb, dec, lz77dist);
366 ret = read_hybrid_uint(gb, &lz77dist->config, token, &distance);
367 if (ret < 0)
368 return ret;
369 distance++;
370 distance = FFMIN3(distance, dec->num_decoded, 1 << 20);
371 dec->copy_pos = dec->num_decoded - distance;
372 return decode_hybrid_varlen_uint(gb, dec, bundle, context, hybrid_uint);
373 }
374 875 ret = read_hybrid_uint(gb, &dist->config, token, hybrid_uint);
375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 875 times.
875 if (ret < 0)
376 return ret;
377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 875 times.
875 if (bundle->lz77_enabled)
378 dec->window[dec->num_decoded++ & 0xFFFFF] = *hybrid_uint;
379
380 875 return 0;
381 }
382
383 static int populate_distribution(GetBitContext *gb, JXLSymbolDistribution *dist, int log_alphabet_size)
384 {
385 int len = 0, shift, omit_log = -1, omit_pos = -1;
386 int prev = 0, num_same = 0;
387 uint32_t total_count = 0;
388 uint8_t logcounts[258] = { 0 };
389 uint8_t same[258] = { 0 };
390 const int table_size = 1 << log_alphabet_size;
391 dist->uniq_pos = -1;
392
393 if (get_bits1(gb)) {
394 /* simple code */
395 if (get_bits1(gb)) {
396 uint8_t v1 = jxl_u8(gb);
397 uint8_t v2 = jxl_u8(gb);
398 if (v1 == v2)
399 return AVERROR_INVALIDDATA;
400 dist->freq[v1] = get_bits(gb, 12);
401 dist->freq[v2] = (1 << 12) - dist->freq[v1];
402 if (!dist->freq[v1])
403 dist->uniq_pos = v2;
404 dist->alphabet_size = 1 + FFMAX(v1, v2);
405 } else {
406 uint8_t x = jxl_u8(gb);
407 dist->freq[x] = 1 << 12;
408 dist->uniq_pos = x;
409 dist->alphabet_size = 1 + x;
410 }
411 if (dist->alphabet_size > table_size)
412 return AVERROR_INVALIDDATA;
413
414 return 0;
415 }
416
417 if (get_bits1(gb)) {
418 /* flat code */
419 dist->alphabet_size = jxl_u8(gb) + 1;
420 if (dist->alphabet_size > table_size)
421 return AVERROR_INVALIDDATA;
422 for (int i = 0; i < dist->alphabet_size; i++)
423 dist->freq[i] = (1 << 12) / dist->alphabet_size;
424 for (int i = 0; i < (1 << 12) % dist->alphabet_size; i++)
425 dist->freq[i]++;
426 return 0;
427 }
428
429 do {
430 if (!get_bits1(gb))
431 break;
432 } while (++len < 3);
433
434 shift = (get_bitsz(gb, len) | (1 << len)) - 1;
435 if (shift > 13)
436 return AVERROR_INVALIDDATA;
437
438 dist->alphabet_size = jxl_u8(gb) + 3;
439 if (dist->alphabet_size > table_size)
440 return AVERROR_INVALIDDATA;
441
442 for (int i = 0; i < dist->alphabet_size; i++) {
443 logcounts[i] = get_vlc2(gb, dist_prefix_table, 7, 1);
444 if (logcounts[i] == 13) {
445 int rle = jxl_u8(gb);
446 same[i] = rle + 5;
447 i += rle + 3;
448 continue;
449 }
450 if (logcounts[i] > omit_log) {
451 omit_log = logcounts[i];
452 omit_pos = i;
453 }
454 }
455 if (omit_pos < 0 || omit_pos + 1 < dist->alphabet_size && logcounts[omit_pos + 1] == 13)
456 return AVERROR_INVALIDDATA;
457
458 for (int i = 0; i < dist->alphabet_size; i++) {
459 if (same[i]) {
460 num_same = same[i] - 1;
461 prev = i > 0 ? dist->freq[i - 1] : 0;
462 }
463 if (num_same) {
464 dist->freq[i] = prev;
465 num_same--;
466 } else {
467 if (i == omit_pos || !logcounts[i])
468 continue;
469 if (logcounts[i] == 1) {
470 dist->freq[i] = 1;
471 } else {
472 int bitcount = FFMIN(FFMAX(0, shift - ((12 - logcounts[i] + 1) >> 1)), logcounts[i] - 1);
473 dist->freq[i] = (1 << (logcounts[i] - 1)) + (get_bitsz(gb, bitcount) << (logcounts[i] - 1 - bitcount));
474 }
475 }
476 total_count += dist->freq[i];
477 }
478 dist->freq[omit_pos] = (1 << 12) - total_count;
479
480 return 0;
481 }
482
483 143 static void dist_bundle_close(JXLDistributionBundle *bundle)
484 {
485
2/4
✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 143 times.
✗ Branch 3 not taken.
143 if (bundle->use_prefix_code && bundle->dists)
486
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 143 times.
286 for (int i = 0; i < bundle->num_clusters; i++)
487 143 ff_vlc_free(&bundle->dists[i].vlc);
488 143 av_freep(&bundle->dists);
489 143 av_freep(&bundle->cluster_map);
490 143 }
491
492
493 static int read_distribution_bundle(GetBitContext *gb, JXLEntropyDecoder *dec,
494 JXLDistributionBundle *bundle, int num_dist, int disallow_lz77);
495
496 143 static int read_dist_clustering(GetBitContext *gb, JXLEntropyDecoder *dec, JXLDistributionBundle *bundle)
497 {
498 int ret;
499
500 143 bundle->cluster_map = av_malloc(bundle->num_dist);
501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (!bundle->cluster_map)
502 return AVERROR(ENOMEM);
503
504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (bundle->num_dist == 1) {
505 bundle->cluster_map[0] = 0;
506 bundle->num_clusters = 1;
507 return 0;
508 }
509
510
1/2
✓ Branch 1 taken 143 times.
✗ Branch 2 not taken.
143 if (get_bits1(gb)) {
511 /* simple clustering */
512 143 uint32_t nbits = get_bits(gb, 2);
513
2/2
✓ Branch 0 taken 1144 times.
✓ Branch 1 taken 143 times.
1287 for (int i = 0; i < bundle->num_dist; i++)
514 1144 bundle->cluster_map[i] = get_bitsz(gb, nbits);
515 } else {
516 /* complex clustering */
517 int use_mtf = get_bits1(gb);
518 JXLDistributionBundle nested = { 0 };
519 /* num_dist == 1 prevents this from recursing again */
520 ret = read_distribution_bundle(gb, dec, &nested, 1, bundle->num_dist <= 2);
521 if (ret < 0) {
522 dist_bundle_close(&nested);
523 return ret;
524 }
525 for (int i = 0; i < bundle->num_dist; i++) {
526 uint32_t clust;
527 ret = decode_hybrid_varlen_uint(gb, dec, &nested, 0, &clust);
528 if (ret < 0) {
529 dist_bundle_close(&nested);
530 return ret;
531 }
532 bundle->cluster_map[i] = clust;
533 }
534 dec->state = -1;
535 /* it's not going to necessarily be zero after reading */
536 dec->num_to_copy = 0;
537 dec->num_decoded = 0;
538 dist_bundle_close(&nested);
539 if (use_mtf) {
540 uint8_t mtf[256];
541 for (int i = 0; i < 256; i++)
542 mtf[i] = i;
543 for (int i = 0; i < bundle->num_dist; i++) {
544 int index = bundle->cluster_map[i];
545 bundle->cluster_map[i] = mtf[index];
546 if (index) {
547 int value = mtf[index];
548 for (int j = index; j > 0; j--)
549 mtf[j] = mtf[j - 1];
550 mtf[0] = value;
551 }
552 }
553 }
554 }
555
2/2
✓ Branch 0 taken 1144 times.
✓ Branch 1 taken 143 times.
1287 for (int i = 0; i < bundle->num_dist; i++) {
556
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 1001 times.
1144 if (bundle->cluster_map[i] >= bundle->num_clusters)
557 143 bundle->num_clusters = bundle->cluster_map[i] + 1;
558 }
559
560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (bundle->num_clusters > bundle->num_dist)
561 return AVERROR_INVALIDDATA;
562
563 143 return 0;
564 }
565
566 static int gen_alias_map(JXLEntropyDecoder *dec, JXLSymbolDistribution *dist, int log_alphabet_size)
567 {
568 uint32_t bucket_size, table_size;
569 uint8_t overfull[256], underfull[256];
570 int overfull_pos = 0, underfull_pos = 0;
571 dist->log_bucket_size = 12 - log_alphabet_size;
572 bucket_size = 1 << dist->log_bucket_size;
573 table_size = 1 << log_alphabet_size;
574
575 if (dist->uniq_pos >= 0) {
576 for (int i = 0; i < table_size; i++) {
577 dist->symbols[i] = dist->uniq_pos;
578 dist->offsets[i] = bucket_size * i;
579 dist->cutoffs[i] = 0;
580 }
581 return 0;
582 }
583
584 for (int i = 0; i < dist->alphabet_size; i++) {
585 dist->cutoffs[i] = dist->freq[i];
586 dist->symbols[i] = i;
587 if (dist->cutoffs[i] > bucket_size)
588 overfull[overfull_pos++] = i;
589 else if (dist->cutoffs[i] < bucket_size)
590 underfull[underfull_pos++] = i;
591 }
592
593 for (int i = dist->alphabet_size; i < table_size; i++) {
594 dist->cutoffs[i] = 0;
595 underfull[underfull_pos++] = i;
596 }
597
598 while (overfull_pos) {
599 int o, u, by;
600 /* this should be impossible */
601 if (!underfull_pos)
602 return AVERROR_INVALIDDATA;
603 u = underfull[--underfull_pos];
604 o = overfull[--overfull_pos];
605 by = bucket_size - dist->cutoffs[u];
606 dist->cutoffs[o] -= by;
607 dist->symbols[u] = o;
608 dist->offsets[u] = dist->cutoffs[o];
609 if (dist->cutoffs[o] < bucket_size)
610 underfull[underfull_pos++] = o;
611 else if (dist->cutoffs[o] > bucket_size)
612 overfull[overfull_pos++] = o;
613 }
614
615 for (int i = 0; i < table_size; i++) {
616 if (dist->cutoffs[i] == bucket_size) {
617 dist->symbols[i] = i;
618 dist->offsets[i] = 0;
619 dist->cutoffs[i] = 0;
620 } else {
621 dist->offsets[i] -= dist->cutoffs[i];
622 }
623 }
624
625 return 0;
626 }
627
628 142 static int read_simple_vlc_prefix(GetBitContext *gb, JXLEntropyDecoder *dec, JXLSymbolDistribution *dist)
629 {
630 int nsym, tree_select, bits;
631
632 int8_t lens[4];
633 int16_t symbols[4];
634
635 142 nsym = 1 + get_bits(gb, 2);
636
2/2
✓ Branch 0 taken 326 times.
✓ Branch 1 taken 142 times.
468 for (int i = 0; i < nsym; i++)
637 326 symbols[i] = get_bitsz(gb, dist->log_alphabet_size);
638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
142 if (nsym == 4)
639 tree_select = get_bits1(gb);
640
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
142 switch (nsym) {
641 case 1:
642 dist->vlc.bits = 0;
643 dist->default_symbol = symbols[0];
644 return 0;
645 100 case 2:
646 100 bits = 1;
647 100 lens[0] = 1, lens[1] = 1, lens[2] = 0, lens[3] = 0;
648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (symbols[1] < symbols[0])
649 FFSWAP(int16_t, symbols[0], symbols[1]);
650 100 break;
651 42 case 3:
652 42 bits = 2;
653 42 lens[0] = 1, lens[1] = 2, lens[2] = 2, lens[3] = 0;
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (symbols[2] < symbols[1])
655 FFSWAP(int16_t, symbols[1], symbols[2]);
656 42 break;
657 case 4:
658 if (tree_select) {
659 bits = 3;
660 lens[0] = 1, lens[1] = 2, lens[2] = 3, lens[3] = 3;
661 if (symbols[3] < symbols[2])
662 FFSWAP(int16_t, symbols[2], symbols[3]);
663 } else {
664 bits = 2;
665 lens[0] = 2, lens[1] = 2, lens[2] = 2, lens[3] = 2;
666 while (1) {
667 if (symbols[1] < symbols[0])
668 FFSWAP(int16_t, symbols[0], symbols[1]);
669 if (symbols[3] < symbols[2])
670 FFSWAP(int16_t, symbols[2], symbols[3]);
671 if (symbols[1] <= symbols[2])
672 break;
673 FFSWAP(int16_t, symbols[1], symbols[2]);
674 }
675 }
676 break;
677 default:
678 // Challenge Complete! How did we get here?
679 return AVERROR_BUG;
680 }
681
682 142 return ff_vlc_init_from_lengths(&dist->vlc, bits, nsym, lens, 1, symbols,
683 2, 2, 0, VLC_INIT_LE, dec->logctx);
684 }
685
686 143 static int read_vlc_prefix(GetBitContext *gb, JXLEntropyDecoder *dec, JXLSymbolDistribution *dist)
687 {
688 143 int8_t level1_lens[18] = { 0 };
689 143 int8_t level1_lens_s[18] = { 0 };
690 143 int16_t level1_syms[18] = { 0 };
691 143 uint32_t level1_codecounts[19] = { 0 };
692 143 uint8_t *buf = NULL;
693 int8_t *level2_lens, *level2_lens_s;
694 int16_t *level2_syms;
695 uint32_t *level2_codecounts;
696
697 143 int repeat_count_prev = 0, repeat_count_zero = 0, prev = 8;
698 143 int total_code = 0, len, hskip, num_codes = 0, ret;
699
700 143 VLC level1_vlc = { 0 };
701
702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (dist->alphabet_size == 1) {
703 dist->vlc.bits = 0;
704 dist->default_symbol = 0;
705 return 0;
706 }
707
708 143 hskip = get_bits(gb, 2);
709
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 1 times.
143 if (hskip == 1)
710 142 return read_simple_vlc_prefix(gb, dec, dist);
711
712 1 level1_codecounts[0] = hskip;
713
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (int i = hskip; i < 18; i++) {
714 8 len = level1_lens[prefix_codelen_map[i]] = get_vlc2(gb, level0_table, 4, 1);
715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (len < 0) {
716 ret = AVERROR_INVALIDDATA;
717 goto end;
718 }
719 8 level1_codecounts[len]++;
720
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 if (len) {
721 7 total_code += (32 >> len);
722 7 num_codes++;
723 }
724
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (total_code >= 32) {
725 1 level1_codecounts[0] += 18 - i - 1;
726 1 break;
727 }
728 }
729
730
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if (total_code != 32 && num_codes >= 2 || num_codes < 1) {
731 ret = AVERROR_INVALIDDATA;
732 goto end;
733 }
734
735
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1 times.
19 for (int i = 1; i < 19; i++)
736 18 level1_codecounts[i] += level1_codecounts[i - 1];
737
738
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1 times.
19 for (int i = 17; i >= 0; i--) {
739 18 int idx = --level1_codecounts[level1_lens[i]];
740 18 level1_lens_s[idx] = level1_lens[i];
741 18 level1_syms[idx] = i;
742 }
743
744 1 ret = ff_vlc_init_from_lengths(&level1_vlc, 5, 18, level1_lens_s, 1, level1_syms, 2, 2,
745 0, VLC_INIT_LE, dec->logctx);
746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
747 goto end;
748
749 1 buf = av_mallocz(MAX_PREFIX_ALPHABET_SIZE * (2 * sizeof(int8_t) + sizeof(int16_t) + sizeof(uint32_t))
750 + sizeof(uint32_t));
751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!buf) {
752 ret = AVERROR(ENOMEM);
753 goto end;
754 }
755
756 1 level2_lens = (int8_t *)buf;
757 1 level2_lens_s = (int8_t *)(buf + MAX_PREFIX_ALPHABET_SIZE * sizeof(int8_t));
758 1 level2_syms = (int16_t *)(buf + MAX_PREFIX_ALPHABET_SIZE * (2 * sizeof(int8_t)));
759 1 level2_codecounts = (uint32_t *)(buf + MAX_PREFIX_ALPHABET_SIZE * (2 * sizeof(int8_t) + sizeof(int16_t)));
760
761 1 total_code = 0;
762
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 for (int i = 0; i < dist->alphabet_size; i++) {
763 16 len = get_vlc2(gb, level1_vlc.table, 5, 1);
764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (len < 0) {
765 ret = AVERROR_INVALIDDATA;
766 goto end;
767 }
768
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (get_bits_left(gb) < 0) {
769 ret = AVERROR_BUFFER_TOO_SMALL;
770 goto end;
771 }
772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (len == 16) {
773 int extra = 3 + get_bits(gb, 2);
774 if (repeat_count_prev)
775 extra += 4 * (repeat_count_prev - 2) - repeat_count_prev;
776 extra = FFMIN(extra, dist->alphabet_size - i);
777 for (int j = 0; j < extra; j++)
778 level2_lens[i + j] = prev;
779 total_code += (32768 >> prev) * extra;
780 i += extra - 1;
781 repeat_count_prev += extra;
782 repeat_count_zero = 0;
783 level2_codecounts[prev] += extra;
784
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 } else if (len == 17) {
785 2 int extra = 3 + get_bits(gb, 3);
786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (repeat_count_zero > 0)
787 extra += 8 * (repeat_count_zero - 2) - repeat_count_zero;
788 2 extra = FFMIN(extra, dist->alphabet_size - i);
789 2 i += extra - 1;
790 2 repeat_count_prev = 0;
791 2 repeat_count_zero += extra;
792 2 level2_codecounts[0] += extra;
793 } else {
794 14 level2_lens[i] = len;
795 14 repeat_count_prev = repeat_count_zero = 0;
796
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 5 times.
14 if (len) {
797 9 total_code += (32768 >> len);
798 9 prev = len;
799 }
800 14 level2_codecounts[len]++;
801 }
802
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 15 times.
16 if (total_code >= 32768) {
803 1 level2_codecounts[0] += dist->alphabet_size - i - 1;
804 1 break;
805 }
806 }
807
808
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (total_code != 32768 && level2_codecounts[0] < dist->alphabet_size - 1) {
809 ret = AVERROR_INVALIDDATA;
810 goto end;
811 }
812
813
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 1 times.
29 for (int i = 1; i < dist->alphabet_size + 1; i++)
814 28 level2_codecounts[i] += level2_codecounts[i - 1];
815
816
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 1 times.
29 for (int i = dist->alphabet_size - 1; i >= 0; i--) {
817 28 int idx = --level2_codecounts[level2_lens[i]];
818 28 level2_lens_s[idx] = level2_lens[i];
819 28 level2_syms[idx] = i;
820 }
821
822 1 ret = ff_vlc_init_from_lengths(&dist->vlc, 15, dist->alphabet_size, level2_lens_s,
823 1, level2_syms, 2, 2, 0, VLC_INIT_LE, dec->logctx);
824
825 1 end:
826 1 av_freep(&buf);
827 1 ff_vlc_free(&level1_vlc);
828
829 1 return ret;
830 }
831
832 143 static int read_distribution_bundle(GetBitContext *gb, JXLEntropyDecoder *dec,
833 JXLDistributionBundle *bundle, int num_dist, int disallow_lz77)
834 {
835 int ret;
836
837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (num_dist <= 0)
838 return AVERROR(EINVAL);
839
840 143 bundle->num_dist = num_dist;
841 143 bundle->lz77_enabled = get_bits1(gb);
842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (bundle->lz77_enabled) {
843 if (disallow_lz77)
844 return AVERROR_INVALIDDATA;
845 bundle->lz77_min_symbol = jxl_u32(gb, 224, 512, 4096, 8, 0, 0, 0, 15);
846 bundle->lz77_min_length = jxl_u32(gb, 3, 4, 5, 9, 0, 0, 2, 8);
847 bundle->num_dist++;
848 ret = read_hybrid_uint_conf(gb, &bundle->lz_len_conf, 8);
849 if (ret < 0)
850 return ret;
851 }
852
853
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
143 if (bundle->lz77_enabled && !dec->window) {
854 dec->window = av_malloc_array(1 << 20, sizeof(uint32_t));
855 if (!dec->window)
856 return AVERROR(ENOMEM);
857 }
858
859 143 ret = read_dist_clustering(gb, dec, bundle);
860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (ret < 0)
861 return ret;
862
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 143 times.
143 if (get_bits_left(gb) < 0)
863 return AVERROR_BUFFER_TOO_SMALL;
864
865 143 bundle->dists = av_calloc(bundle->num_clusters, sizeof(JXLSymbolDistribution));
866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (!bundle->dists)
867 return AVERROR(ENOMEM);
868
869 143 bundle->use_prefix_code = get_bits1(gb);
870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 bundle->log_alphabet_size = bundle->use_prefix_code ? 15 : 5 + get_bits(gb, 2);
871
872
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 143 times.
286 for (int i = 0; i < bundle->num_clusters; i++) {
873 143 ret = read_hybrid_uint_conf(gb, &bundle->dists[i].config, bundle->log_alphabet_size);
874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (ret < 0)
875 return ret;
876
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 143 times.
143 if (get_bits_left(gb) < 0)
877 return AVERROR_BUFFER_TOO_SMALL;
878 }
879
880
1/2
✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
143 if (bundle->use_prefix_code) {
881
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 143 times.
286 for (int i = 0; i < bundle->num_clusters; i++) {
882 143 JXLSymbolDistribution *dist = &bundle->dists[i];
883
1/2
✓ Branch 1 taken 143 times.
✗ Branch 2 not taken.
143 if (get_bits1(gb)) {
884 143 int n = get_bits(gb, 4);
885 143 dist->alphabet_size = 1 + (1 << n) + get_bitsz(gb, n);
886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (dist->alphabet_size > MAX_PREFIX_ALPHABET_SIZE)
887 return AVERROR_INVALIDDATA;
888 } else {
889 dist->alphabet_size = 1;
890 }
891 143 dist->log_alphabet_size = clog1p(dist->alphabet_size - 1);
892 }
893
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 143 times.
286 for (int i = 0; i < bundle->num_clusters; i++) {
894 143 ret = read_vlc_prefix(gb, dec, &bundle->dists[i]);
895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (ret < 0)
896 return ret;
897
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 143 times.
143 if (get_bits_left(gb) < 0)
898 return AVERROR_BUFFER_TOO_SMALL;
899 }
900 } else {
901 for (int i = 0; i < bundle->num_clusters; i++) {
902 ret = populate_distribution(gb, &bundle->dists[i], bundle->log_alphabet_size);
903 if (ret < 0)
904 return ret;
905 if (get_bits_left(gb) < 0)
906 return AVERROR_BUFFER_TOO_SMALL;
907 }
908 for (int i = 0; i < bundle->num_clusters; i++) {
909 ret = gen_alias_map(dec, &bundle->dists[i], bundle->log_alphabet_size);
910 if (ret < 0)
911 return ret;
912 }
913 }
914
915 143 return 0;
916 }
917
918 143 static void entropy_decoder_close(JXLEntropyDecoder *dec)
919 {
920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (!dec)
921 return;
922 143 av_freep(&dec->window);
923 143 dist_bundle_close(&dec->bundle);
924 }
925
926 143 static int entropy_decoder_init(void *avctx, GetBitContext *gb, JXLEntropyDecoder *dec, int num_dist)
927 {
928 int ret;
929
930 143 memset(dec, 0, sizeof(*dec));
931 143 dec->logctx = avctx;
932 143 dec->state = -1;
933
934 143 ret = read_distribution_bundle(gb, dec, &dec->bundle, num_dist, 0);
935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (ret < 0) {
936 entropy_decoder_close(dec);
937 return ret;
938 }
939
940 143 return 0;
941 }
942
943 875 static int64_t entropy_decoder_read_symbol(GetBitContext *gb, JXLEntropyDecoder *dec, uint32_t context)
944 {
945 int ret;
946 uint32_t hybrid_uint;
947
948 875 ret = decode_hybrid_varlen_uint(gb, dec, &dec->bundle, context, &hybrid_uint);
949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 875 times.
875 if (ret < 0)
950 return ret;
951
952 875 return hybrid_uint;
953 }
954
955 static inline uint32_t icc_context(uint64_t i, uint32_t b1, uint32_t b2)
956 {
957 uint32_t p1, p2;
958 if (i <= 128)
959 return 0;
960 if (b1 >= 'a' && b1 <= 'z' || b1 >= 'A' && b1 <= 'Z')
961 p1 = 0;
962 else if (b1 >= '0' && b1 <= '9' || b1 == '.' || b1 == ',')
963 p1 = 1;
964 else if (b1 <= 1)
965 p1 = b1 + 2;
966 else if (b1 > 1 && b1 < 16)
967 p1 = 4;
968 else if (b1 > 240 && b1 < 255)
969 p1 = 5;
970 else if (b1 == 255)
971 p1 = 6;
972 else
973 p1 = 7;
974
975 if (b2 >= 'a' && b2 <= 'z' || b2 >= 'A' && b2 <= 'Z')
976 p2 = 0;
977 else if (b2 >= '0' && b2 <= '9' || b2 == '.' || b2 == ',')
978 p2 = 1;
979 else if (b2 < 16)
980 p2 = 2;
981 else if (b2 > 240)
982 p2 = 3;
983 else
984 p2 = 4;
985
986 return 1 + p1 + p2 * 8;
987 }
988
989 875 static inline uint32_t toc_context(uint32_t x)
990 {
991 875 return FFMIN(7, clog1p(x));
992 }
993
994 14 static void populate_fields(AVCodecParserContext *s, AVCodecContext *avctx, const FFJXLMetadata *meta)
995 {
996 14 s->width = meta->width;
997 14 s->height = meta->height;
998
999
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 switch (meta->csp) {
1000 14 case JPEGXL_CS_RGB:
1001 case JPEGXL_CS_XYB:
1002 14 avctx->colorspace = AVCOL_SPC_RGB;
1003 14 break;
1004 default:
1005 avctx->colorspace = AVCOL_SPC_UNSPECIFIED;
1006 }
1007
1008
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (meta->wp == JPEGXL_WP_D65) {
1009
1/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14 switch (meta->primaries) {
1010 14 case JPEGXL_PR_SRGB:
1011 14 avctx->color_primaries = AVCOL_PRI_BT709;
1012 14 break;
1013 case JPEGXL_PR_P3:
1014 avctx->color_primaries = AVCOL_PRI_SMPTE432;
1015 break;
1016 case JPEGXL_PR_2100:
1017 avctx->color_primaries = AVCOL_PRI_BT2020;
1018 break;
1019 default:
1020 avctx->color_primaries = AVCOL_PRI_UNSPECIFIED;
1021 }
1022 } else if (meta->wp == JPEGXL_WP_DCI && meta->primaries == JPEGXL_PR_P3) {
1023 avctx->color_primaries = AVCOL_PRI_SMPTE431;
1024 } else {
1025 avctx->color_primaries = AVCOL_PRI_UNSPECIFIED;
1026 }
1027
1028
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (meta->trc > JPEGXL_TR_GAMMA) {
1029 14 FFJXLTransferCharacteristic trc = meta->trc - JPEGXL_TR_GAMMA;
1030
1/7
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
14 switch (trc) {
1031 case JPEGXL_TR_BT709:
1032 avctx->color_trc = AVCOL_TRC_BT709;
1033 break;
1034 case JPEGXL_TR_LINEAR:
1035 avctx->color_trc = AVCOL_TRC_LINEAR;
1036 break;
1037 14 case JPEGXL_TR_SRGB:
1038 14 avctx->color_trc = AVCOL_TRC_IEC61966_2_1;
1039 14 break;
1040 case JPEGXL_TR_PQ:
1041 avctx->color_trc = AVCOL_TRC_SMPTEST2084;
1042 break;
1043 case JPEGXL_TR_DCI:
1044 avctx->color_trc = AVCOL_TRC_SMPTE428;
1045 break;
1046 case JPEGXL_TR_HLG:
1047 avctx->color_trc = AVCOL_TRC_ARIB_STD_B67;
1048 break;
1049 default:
1050 avctx->color_trc = AVCOL_TRC_UNSPECIFIED;
1051 }
1052 } else if (meta->trc > 0) {
1053 if (meta->trc > 45355 && meta->trc < 45555)
1054 avctx->color_trc = AVCOL_TRC_GAMMA22;
1055 else if (meta->trc > 35614 && meta->trc < 35814)
1056 avctx->color_trc = AVCOL_TRC_GAMMA28;
1057 else
1058 avctx->color_trc = AVCOL_TRC_UNSPECIFIED;
1059 } else {
1060 avctx->color_trc = AVCOL_TRC_UNSPECIFIED;
1061 }
1062
1063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (meta->csp == JPEGXL_CS_GRAY) {
1064 if (meta->bit_depth <= 8)
1065 s->format = meta->have_alpha ? AV_PIX_FMT_YA8 : AV_PIX_FMT_GRAY8;
1066 else if (meta->bit_depth <= 16)
1067 s->format = meta->have_alpha ? AV_PIX_FMT_YA16 : AV_PIX_FMT_GRAY16;
1068 else
1069 s->format = meta->have_alpha ? AV_PIX_FMT_NONE : AV_PIX_FMT_GRAYF32;
1070 } else {
1071
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (meta->bit_depth <= 8)
1072
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 s->format = meta->have_alpha ? AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB24;
1073 else if (meta->bit_depth <= 16)
1074 s->format = meta->have_alpha ? AV_PIX_FMT_RGBA64 : AV_PIX_FMT_RGB48;
1075 else
1076 s->format = meta->have_alpha ? AV_PIX_FMT_RGBAF32 : AV_PIX_FMT_RGBF32;
1077 }
1078
1079
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (meta->have_alpha) {
1080 2 avctx->alpha_mode = meta->alpha_associated ? AVALPHA_MODE_PREMULTIPLIED
1081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 : AVALPHA_MODE_STRAIGHT;
1082 }
1083 14 }
1084
1085 static int skip_icc_profile(void *avctx, JXLParseContext *ctx, GetBitContext *gb)
1086 {
1087 int64_t ret;
1088 uint32_t last = 0, last2 = 0;
1089 JXLEntropyDecoder dec = { 0 };
1090 uint64_t enc_size = jxl_u64(gb);
1091 uint64_t output_size = 0;
1092 int out_size_shift = 0;
1093
1094 if (!enc_size || enc_size > (1 << 22))
1095 return AVERROR_INVALIDDATA;
1096
1097 ret = entropy_decoder_init(avctx, gb, &dec, 41);
1098 if (ret < 0)
1099 goto end;
1100
1101 if (get_bits_left(gb) < 0) {
1102 ret = AVERROR_BUFFER_TOO_SMALL;
1103 goto end;
1104 }
1105
1106 for (uint64_t read = 0; read < enc_size; read++) {
1107 ret = entropy_decoder_read_symbol(gb, &dec, icc_context(read, last, last2));
1108 if (ret < 0)
1109 goto end;
1110 if (ret > 255) {
1111 ret = AVERROR_INVALIDDATA;
1112 goto end;
1113 }
1114 if (get_bits_left(gb) < 0) {
1115 ret = AVERROR_BUFFER_TOO_SMALL;
1116 goto end;
1117 }
1118 last2 = last;
1119 last = ret;
1120 if (out_size_shift < 63) {
1121 output_size += (ret & UINT64_C(0x7F)) << out_size_shift;
1122 if (!(ret & 0x80)) {
1123 out_size_shift = 63;
1124 } else {
1125 out_size_shift += 7;
1126 if (out_size_shift > 56) {
1127 ret = AVERROR_INVALIDDATA;
1128 goto end;
1129 }
1130 }
1131 } else if (output_size < 132) {
1132 ret = AVERROR_INVALIDDATA;
1133 goto end;
1134 }
1135 }
1136
1137 ret = 0;
1138
1139 end:
1140 entropy_decoder_close(&dec);
1141
1142 return ret;
1143 }
1144
1145 337 static int skip_extensions(GetBitContext *gb)
1146 {
1147 337 uint64_t extensions = jxl_u64(gb), extensions_len = 0;
1148
1149
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 337 times.
337 if (get_bits_left(gb) < 0)
1150 return AVERROR_BUFFER_TOO_SMALL;
1151
1152
1/2
✓ Branch 0 taken 337 times.
✗ Branch 1 not taken.
337 if (!extensions)
1153 337 return 0;
1154
1155 for (int i = 0; i < 64; i++) {
1156 if (extensions & (UINT64_C(1) << i))
1157 extensions_len += jxl_u64(gb);
1158 if (get_bits_left(gb) < 0)
1159 return AVERROR_BUFFER_TOO_SMALL;
1160 }
1161
1162 if (extensions_len > INT_MAX || get_bits_left(gb) < extensions_len)
1163 return AVERROR_BUFFER_TOO_SMALL;
1164
1165 skip_bits_long(gb, extensions_len);
1166
1167 return 0;
1168 }
1169
1170 193 static int parse_frame_header(void *avctx, JXLParseContext *ctx, GetBitContext *gb)
1171 {
1172 193 int all_default, do_yCbCr = 0, num_passes = 1, ret;
1173 193 int group_size_shift = 1, lf_level = 0, save_as_ref = 0;
1174 193 int have_crop = 0, full_frame = 1, resets_canvas = 1, upsampling = 1;
1175 193 JXLFrame *frame = &ctx->codestream.frame;
1176 193 const FFJXLMetadata *meta = &ctx->codestream.meta;
1177 193 int32_t x0 = 0, y0 = 0;
1178 193 uint32_t duration = 0, width = meta->coded_width, height = meta->coded_height;
1179 uint32_t name_len, num_groups, num_lf_groups, group_dim, lf_group_dim, toc_count;
1180 193 uint64_t flags = 0;
1181 193 int start_len = get_bits_count(gb);
1182
1183 193 memset(frame, 0, sizeof(*frame));
1184 193 frame->is_last = 1;
1185
1186 193 all_default = get_bits1(gb);
1187
1/2
✓ Branch 0 taken 193 times.
✗ Branch 1 not taken.
193 if (!all_default) {
1188 193 frame->type = get_bits(gb, 2);
1189 193 frame->encoding = get_bits1(gb);
1190 193 flags = jxl_u64(gb);
1191
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 192 times.
193 if (!meta->xyb_encoded)
1192 1 do_yCbCr = get_bits1(gb);
1193
1/2
✓ Branch 0 taken 193 times.
✗ Branch 1 not taken.
193 if (!(flags & JXL_FLAG_USE_LF_FRAME)) {
1194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (do_yCbCr)
1195 skip_bits(gb, 6); // jpeg upsampling
1196 193 upsampling = jxl_u32(gb, 1, 2, 4, 8, 0, 0, 0, 0);
1197 193 skip_bits_long(gb, 2 * meta->num_extra_channels);
1198
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 193 times.
193 if (get_bits_left(gb) < 0)
1199 return AVERROR_BUFFER_TOO_SMALL;
1200 }
1201
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 192 times.
193 if (frame->encoding == JPEGXL_ENC_MODULAR)
1202 1 group_size_shift = get_bits(gb, 2);
1203
1/2
✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
192 else if (meta->xyb_encoded)
1204 192 skip_bits(gb, 6); // xqm and bqm scales
1205
1/2
✓ Branch 0 taken 193 times.
✗ Branch 1 not taken.
193 if (frame->type != JPEGXL_FRAME_REFERENCE_ONLY) {
1206 193 num_passes = jxl_u32(gb, 1, 2, 3, 4, 0, 0, 0, 3);
1207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (num_passes != 1) {
1208 int num_ds = jxl_u32(gb, 0, 1, 2, 3, 0, 0, 0, 1);
1209 skip_bits(gb, 2 * (num_passes - 1)); // shift
1210 skip_bits(gb, 2 * num_ds); // downsample
1211 for (int i = 0; i < num_ds; i++)
1212 jxl_u32(gb, 0, 1, 2, 0, 0, 0, 0, 3);
1213 }
1214 }
1215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (frame->type == JPEGXL_FRAME_LF)
1216 lf_level = 1 + get_bits(gb, 2);
1217 else
1218 193 have_crop = get_bits1(gb);
1219
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 3 times.
193 if (have_crop) {
1220
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 if (frame->type != JPEGXL_FRAME_REFERENCE_ONLY) {
1221 190 uint32_t ux0 = jxl_u32(gb, 0, 256, 2304, 18688, 8, 11, 14, 30);
1222 190 uint32_t uy0 = jxl_u32(gb, 0, 256, 2304, 18688, 8, 11, 14, 30);
1223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
190 x0 = unpack_signed(ux0);
1224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
190 y0 = unpack_signed(uy0);
1225 }
1226 190 width = jxl_u32(gb, 0, 256, 2304, 18688, 8, 11, 14, 30);
1227 190 height = jxl_u32(gb, 0, 256, 2304, 18688, 8, 11, 14, 30);
1228
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
212 full_frame = x0 <= 0 && y0 <= 0 && width + x0 >= meta->coded_width
1229
2/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
212 && height + y0 >= meta->coded_height;
1230 }
1231
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 193 times.
193 if (get_bits_left(gb) < 0)
1232 return AVERROR_BUFFER_TOO_SMALL;
1233
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
193 if (frame->type == JPEGXL_FRAME_REGULAR || frame->type == JPEGXL_FRAME_SKIP_PROGRESSIVE) {
1234
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 193 times.
435 for (int i = 0; i <= meta->num_extra_channels; i++) {
1235 242 int mode = jxl_u32(gb, 0, 1, 2, 3, 0, 0, 0, 2);
1236
4/6
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 98 times.
242 if (meta->num_extra_channels && (mode == JPEGXL_BM_BLEND || mode == JPEGXL_BM_MULADD))
1237 jxl_u32(gb, 0, 1, 2, 3, 0, 0, 0, 2);
1238
4/6
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
242 if (meta->num_extra_channels && (mode == JPEGXL_BM_BLEND || mode == JPEGXL_BM_MULADD
1239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 || mode == JPEGXL_BM_MUL))
1240 skip_bits1(gb);
1241
2/2
✓ Branch 0 taken 193 times.
✓ Branch 1 taken 49 times.
242 if (!i)
1242
3/4
✓ Branch 0 taken 193 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 190 times.
193 resets_canvas = mode == JPEGXL_BM_REPLACE && full_frame;
1243
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 4 times.
242 if (!resets_canvas)
1244 238 skip_bits(gb, 2);
1245
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 242 times.
242 if (get_bits_left(gb) < 0)
1246 return AVERROR_BUFFER_TOO_SMALL;
1247 }
1248
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 144 times.
193 if (meta->animation_offset)
1249 49 duration = jxl_u32(gb, 0, 1, 0, 0, 0, 0, 8, 32);
1250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (meta->have_timecodes)
1251 skip_bits_long(gb, 32);
1252 193 frame->is_last = get_bits1(gb);
1253 } else {
1254 frame->is_last = 0;
1255 }
1256
3/4
✓ Branch 0 taken 193 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 185 times.
✓ Branch 3 taken 8 times.
193 if (frame->type != JPEGXL_FRAME_LF && !frame->is_last)
1257 185 save_as_ref = get_bits(gb, 2);
1258
3/4
✓ Branch 0 taken 193 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 190 times.
193 if (frame->type == JPEGXL_FRAME_REFERENCE_ONLY ||
1259
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
3 (resets_canvas && !frame->is_last && (!duration || save_as_ref)
1260 && frame->type != JPEGXL_FRAME_LF))
1261 skip_bits1(gb); // save before color transform
1262 193 name_len = 8 * jxl_u32(gb, 0, 0, 16, 48, 0, 4, 5, 10);
1263
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 193 times.
193 if (get_bits_left(gb) < name_len)
1264 return AVERROR_BUFFER_TOO_SMALL;
1265 193 skip_bits_long(gb, name_len);
1266 }
1267
1268
1/2
✓ Branch 0 taken 193 times.
✗ Branch 1 not taken.
193 if (!all_default) {
1269 193 int restd = get_bits1(gb), gab = 1;
1270
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 49 times.
193 if (!restd)
1271 144 gab = get_bits1(gb);
1272
3/6
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
193 if (gab && !restd && get_bits1(gb))
1273 // gab custom
1274 skip_bits_long(gb, 16 * 6);
1275
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 193 times.
193 if (get_bits_left(gb) < 0)
1276 return AVERROR_BUFFER_TOO_SMALL;
1277
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 49 times.
193 if (!restd) {
1278 144 int epf = get_bits(gb, 2);
1279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (epf) {
1280 if (frame->encoding == JPEGXL_ENC_VARDCT && get_bits1(gb)) {
1281 skip_bits_long(gb, 16 * 8); // custom epf sharpness
1282 if (get_bits_left(gb) < 0)
1283 return AVERROR_BUFFER_TOO_SMALL;
1284 }
1285 if (get_bits1(gb)) {
1286 skip_bits_long(gb, 3 * 16 + 32); // custom epf weight
1287 if (get_bits_left(gb) < 0)
1288 return AVERROR_BUFFER_TOO_SMALL;
1289 }
1290 if (get_bits1(gb)) { // custom epf sigma
1291 if (frame->encoding == JPEGXL_ENC_VARDCT)
1292 skip_bits(gb, 16);
1293 skip_bits_long(gb, 16 * 3);
1294 if (get_bits_left(gb) < 0)
1295 return AVERROR_BUFFER_TOO_SMALL;
1296 }
1297 if (frame->encoding == JPEGXL_ENC_MODULAR)
1298 skip_bits(gb, 16);
1299 }
1300 144 ret = skip_extensions(gb);
1301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (ret < 0)
1302 return ret;
1303 }
1304 193 ret = skip_extensions(gb);
1305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (ret < 0)
1306 return ret;
1307 }
1308
1309 193 width = div_ceil(div_ceil(width, upsampling), 1 << (3 * lf_level));
1310 193 height = div_ceil(div_ceil(height, upsampling), 1 << (3 * lf_level));
1311 193 group_dim = 128 << group_size_shift;
1312 193 lf_group_dim = group_dim << 3;
1313 193 num_groups = div_ceil(width, group_dim) * div_ceil(height, group_dim);
1314 193 num_lf_groups = div_ceil(width, lf_group_dim) * div_ceil(height, lf_group_dim);
1315
3/4
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 150 times.
✗ Branch 3 not taken.
193 if (num_groups == 1 && num_passes == 1)
1316 150 toc_count = 1;
1317 else
1318 43 toc_count = 2 + num_lf_groups + num_groups * num_passes;
1319
1320 // permuted toc
1321
2/2
✓ Branch 1 taken 143 times.
✓ Branch 2 taken 50 times.
193 if (get_bits1(gb)) {
1322 JXLEntropyDecoder dec;
1323 143 int64_t end, lehmer = 0;
1324 /* parser sanity check to prevent TOC perm from spinning cpu */
1325
2/4
✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 143 times.
143 if (width > meta->coded_width * 8 || height > meta->coded_height * 8) {
1326 av_log(avctx, AV_LOG_WARNING, "frame of size %" PRIu32 "x%" PRIu32
1327 " exceeds max size of %" PRIu32 "x%" PRIu32 ", aborting parser\n",
1328 width, height, meta->coded_width * 8, meta->coded_height * 8);
1329 return AVERROR_INVALIDDATA;
1330 }
1331 143 ret = entropy_decoder_init(avctx, gb, &dec, 8);
1332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
143 if (ret < 0)
1333 return ret;
1334
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 143 times.
143 if (get_bits_left(gb) < 0) {
1335 entropy_decoder_close(&dec);
1336 return AVERROR_BUFFER_TOO_SMALL;
1337 }
1338 143 end = entropy_decoder_read_symbol(gb, &dec, toc_context(toc_count));
1339
2/4
✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 143 times.
143 if (end < 0 || end > toc_count) {
1340 entropy_decoder_close(&dec);
1341 return AVERROR_INVALIDDATA;
1342 }
1343
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 143 times.
875 for (uint32_t i = 0; i < end; i++) {
1344 732 lehmer = entropy_decoder_read_symbol(gb, &dec, toc_context(lehmer));
1345
2/4
✓ Branch 0 taken 732 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 732 times.
732 if (lehmer < 0 || get_bits_left(gb) < 0) {
1346 entropy_decoder_close(&dec);
1347 return lehmer < 0 ? lehmer : AVERROR_BUFFER_TOO_SMALL;
1348 }
1349 }
1350 143 entropy_decoder_close(&dec);
1351 }
1352 193 align_get_bits(gb);
1353
1354
2/2
✓ Branch 0 taken 782 times.
✓ Branch 1 taken 193 times.
975 for (uint32_t i = 0; i < toc_count; i++) {
1355 782 frame->body_length += 8 * jxl_u32(gb, 0, 1024, 17408, 4211712, 10, 14, 22, 30);
1356
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 782 times.
782 if (get_bits_left(gb) < 0)
1357 return AVERROR_BUFFER_TOO_SMALL;
1358 }
1359 193 align_get_bits(gb);
1360
1361 193 frame->total_length = frame->body_length + get_bits_count(gb) - start_len;
1362
1363 193 return 0;
1364 }
1365
1366 10 static int skip_boxes(JXLParseContext *ctx, const uint8_t *buf, int buf_size)
1367 {
1368 GetByteContext gb;
1369
1370
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 if (ctx->skip > buf_size)
1371 3 return AVERROR_BUFFER_TOO_SMALL;
1372
1373 7 buf += ctx->skip;
1374 7 buf_size -= ctx->skip;
1375 7 bytestream2_init(&gb, buf, buf_size);
1376
1377 while (1) {
1378 uint64_t size;
1379 7 int head_size = 8;
1380
1381
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (bytestream2_peek_le16(&gb) == FF_JPEGXL_CODESTREAM_SIGNATURE_LE)
1382 break;
1383
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4 times.
7 if (bytestream2_peek_le64(&gb) == FF_JPEGXL_CONTAINER_SIGNATURE_LE)
1384 3 break;
1385
1386
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 if (bytestream2_get_bytes_left(&gb) < 8)
1387 3 return AVERROR_BUFFER_TOO_SMALL;
1388
1389 1 size = bytestream2_get_be32(&gb);
1390 1 bytestream2_skip(&gb, 4); // tag
1391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (size == 1) {
1392 if (bytestream2_get_bytes_left(&gb) < 8)
1393 return AVERROR_BUFFER_TOO_SMALL;
1394 size = bytestream2_get_be64(&gb);
1395 head_size = 16;
1396 }
1397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!size)
1398 return AVERROR_INVALIDDATA;
1399 /* invalid ISOBMFF size */
1400
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (size <= head_size || size > INT_MAX - ctx->skip)
1401 return AVERROR_INVALIDDATA;
1402
1403 1 ctx->skip += size;
1404 1 bytestream2_skip(&gb, size - head_size);
1405
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (bytestream2_get_bytes_left(&gb) <= 0)
1406 1 return AVERROR_BUFFER_TOO_SMALL;
1407 }
1408
1409 3 return 0;
1410 }
1411
1412 92 static int64_t try_parse(AVCodecParserContext *s, AVCodecContext *avctx, JXLParseContext *ctx,
1413 const uint8_t *buf, int buf_size)
1414 {
1415 int ret, cs_buflen, header_skip;
1416 const uint8_t *cs_buffer;
1417 GetBitContext gb;
1418
1419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
92 if (ctx->skip > buf_size)
1420 return AVERROR_BUFFER_TOO_SMALL;
1421
1422 92 buf += ctx->skip;
1423 92 buf_size -= ctx->skip;
1424
1425
3/4
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 86 times.
92 if (ctx->container || AV_RL64(buf) == FF_JPEGXL_CONTAINER_SIGNATURE_LE) {
1426 6 ctx->container = 1;
1427 6 ret = ff_jpegxl_collect_codestream_header(buf, buf_size, ctx->cs_buffer,
1428 sizeof(ctx->cs_buffer) - AV_INPUT_BUFFER_PADDING_SIZE, &ctx->copied);
1429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
1430 return ret;
1431 6 ctx->collected_size = ret;
1432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!ctx->copied) {
1433 ctx->skip += ret;
1434 return AVERROR_BUFFER_TOO_SMALL;
1435 }
1436 6 cs_buffer = ctx->cs_buffer;
1437
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 cs_buflen = FFMIN(sizeof(ctx->cs_buffer) - AV_INPUT_BUFFER_PADDING_SIZE, ctx->copied);
1438 } else {
1439 86 cs_buffer = buf;
1440 86 cs_buflen = buf_size;
1441 }
1442
1443
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 72 times.
92 if (!ctx->codestream_length) {
1444 20 header_skip = ff_jpegxl_parse_codestream_header(cs_buffer, cs_buflen, &ctx->codestream.meta, 0);
1445
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 14 times.
20 if (header_skip < 0)
1446 6 return header_skip;
1447 14 ctx->codestream_length = header_skip;
1448 14 populate_fields(s, avctx, &ctx->codestream.meta);
1449 }
1450
1451
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 80 times.
86 if (ctx->container)
1452 6 return ctx->collected_size;
1453
1454 80 ret = init_get_bits8(&gb, cs_buffer, cs_buflen);
1455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (ret < 0)
1456 return ret;
1457
1458 80 skip_bits_long(&gb, ctx->codestream_length);
1459
1460
2/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
80 if (!ctx->skipped_icc && ctx->codestream.meta.have_icc_profile) {
1461 ret = skip_icc_profile(avctx, ctx, &gb);
1462 if (ret < 0)
1463 return ret;
1464 ctx->skipped_icc = 1;
1465 align_get_bits(&gb);
1466 ctx->codestream_length = get_bits_count(&gb);
1467 }
1468
1469
2/2
✓ Branch 1 taken 75 times.
✓ Branch 2 taken 5 times.
80 if (get_bits_left(&gb) <= 0)
1470 5 return AVERROR_BUFFER_TOO_SMALL;
1471
1472 while (1) {
1473 193 ret = parse_frame_header(avctx, ctx, &gb);
1474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (ret < 0)
1475 return ret;
1476 193 ctx->codestream_length += ctx->codestream.frame.total_length;
1477
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 185 times.
193 if (ctx->codestream.frame.is_last)
1478 8 return ctx->codestream_length / 8;
1479
2/2
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 118 times.
185 if (get_bits_left(&gb) <= ctx->codestream.frame.body_length)
1480 67 return AVERROR_BUFFER_TOO_SMALL;
1481 118 skip_bits_long(&gb, ctx->codestream.frame.body_length);
1482 }
1483 }
1484
1485 97 static int jpegxl_parse(AVCodecParserContext *s, AVCodecContext *avctx,
1486 const uint8_t **poutbuf, int *poutbuf_size,
1487 const uint8_t *buf, int buf_size)
1488 {
1489 97 JXLParseContext *ctx = s->priv_data;
1490 97 int next = END_NOT_FOUND, ret;
1491 97 const uint8_t *pbuf = ctx->pc.buffer;
1492 97 int pindex = ctx->pc.index;
1493
1494 97 *poutbuf_size = 0;
1495 97 *poutbuf = NULL;
1496
1497
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 77 times.
97 if (!ctx->pc.index) {
1498
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 19 times.
20 if (ctx->pc.overread)
1499 1 goto flush;
1500 19 pbuf = buf;
1501 19 pindex = buf_size;
1502 }
1503
1504
4/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 92 times.
✗ Branch 5 not taken.
96 if ((!ctx->container || !ctx->codestream_length) && !ctx->next) {
1505 92 int64_t ret64 = try_parse(s, avctx, ctx, pbuf, pindex);
1506
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 14 times.
92 if (ret64 < 0)
1507 78 goto flush;
1508 14 ctx->next = ret64;
1509
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (ctx->container)
1510 6 ctx->skip += ctx->next;
1511 }
1512
1513
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
18 if (ctx->container && ctx->next >= 0) {
1514 10 ret = skip_boxes(ctx, pbuf, pindex);
1515
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 if (ret < 0) {
1516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret == AVERROR_INVALIDDATA)
1517 ctx->next = -1;
1518 7 goto flush;
1519 }
1520 3 ctx->next = ret + ctx->skip;
1521 }
1522
1523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ctx->next >= 0)
1524 11 next = ctx->next - ctx->pc.index;
1525
1526 flush:
1527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 if (next > buf_size)
1528 next = END_NOT_FOUND;
1529
1530 97 ret = ff_combine_frame(&ctx->pc, next, &buf, &buf_size);
1531
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 20 times.
97 if (ret < 0)
1532 77 return buf_size;
1533
1534 20 *poutbuf = buf;
1535 20 *poutbuf_size = buf_size;
1536
1537 20 ctx->codestream_length = 0;
1538 20 ctx->collected_size = 0;
1539 20 ctx->container = 0;
1540 20 ctx->copied = 0;
1541 20 ctx->skip = 0;
1542 20 ctx->skipped_icc = 0;
1543 20 ctx->next = 0;
1544 20 memset(&ctx->codestream, 0, sizeof(ctx->codestream));
1545
1546 20 return next;
1547 }
1548
1549 const FFCodecParser ff_jpegxl_parser = {
1550 PARSER_CODEC_LIST(AV_CODEC_ID_JPEGXL, AV_CODEC_ID_JPEGXL_ANIM),
1551 .priv_data_size = sizeof(JXLParseContext),
1552 .parse = jpegxl_parse,
1553 .close = ff_parse_close,
1554 };
1555