History

avformat/jpegxl: remove jpegxl_probe, instead call avcodec/jpegxl_parse

This prevents code duplication in the source form by calling the parse code that was moved to avcodec last commit. The code will be duplicated in binary form for shared builds (it's not that large), but for source code it will only exist in one location now.

Leo Izen committed 3 years ago

Commit e8a63b41 parent 0c0dd236 files · +41 −536Browse files

Unified · Split

6 files
  1. libavformat/Makefile +4 −2
  2. libavformat/img2dec.c +2 −2
  3. libavformat/jpegxl_anim_dec.c +31 −101
  4. libavformat/jpegxl_parse.c +3 −18
  5. libavformat/jpegxl_probe.c +0 −412
  6. libavformat/version.h +1 −1
libavformat/Makefile+4−2
@@ -283,7 +283,7 @@ OBJS-$(CONFIG_IMAGE_HDR_PIPE_DEMUXER) += img2dec.o img2.o · 282 unmodified lines
283283 OBJS-$(CONFIG_IMAGE_J2K_PIPE_DEMUXER) += img2dec.o img2.o
284284 OBJS-$(CONFIG_IMAGE_JPEG_PIPE_DEMUXER) += img2dec.o img2.o
285285 OBJS-$(CONFIG_IMAGE_JPEGLS_PIPE_DEMUXER) += img2dec.o img2.o
286−OBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += img2dec.o img2.o jpegxl_probe.o
286+OBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += img2dec.o img2.o
287287 OBJS-$(CONFIG_IMAGE_PAM_PIPE_DEMUXER) += img2dec.o img2.o
288288 OBJS-$(CONFIG_IMAGE_PBM_PIPE_DEMUXER) += img2dec.o img2.o
289289 OBJS-$(CONFIG_IMAGE_PCX_PIPE_DEMUXER) += img2dec.o img2.o
@@ -320,7 +320,7 @@ OBJS-$(CONFIG_IVF_MUXER) += ivfenc.o · 30 unmodified lines
320320 OBJS-$(CONFIG_IVR_DEMUXER) += rmdec.o rm.o rmsipr.o
321321 OBJS-$(CONFIG_JACOSUB_DEMUXER) += jacosubdec.o subtitles.o
322322 OBJS-$(CONFIG_JACOSUB_MUXER) += jacosubenc.o rawenc.o
323−OBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_anim_dec.o jpegxl_probe.o
323+OBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_anim_dec.o
324324 OBJS-$(CONFIG_JV_DEMUXER) += jvdec.o
325325 OBJS-$(CONFIG_KUX_DEMUXER) += flvdec.o
326326 OBJS-$(CONFIG_KVAG_DEMUXER) += kvag.o
@@ -717,6 +717,8 @@ SHLIBOBJS += log2_tab.o to_upper4.o · 390 unmodified lines
717717 SHLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o
718718 SHLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o
719719 SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o
720+SHLIBOBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += jpegxl_parse.o
721+SHLIBOBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_parse.o
720722 SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o
721723 SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o
722724 SHLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o
libavformat/img2dec.c+2−2
@@ -36,7 +36,7 @@ · 35 unmodified lines
3636 #include "avio_internal.h"
3737 #include "internal.h"
3838 #include "img2.h"
39−#include "jpegxl_probe.h"
39+#include "libavcodec/jpegxl_parse.h"
4040 #include "libavcodec/mjpeg.h"
4141 #include "libavcodec/vbn.h"
4242 #include "libavcodec/xwd.h"
@@ -850,7 +850,7 @@ static int jpegxl_probe(const AVProbeData *p) · 807 unmodified lines
850850 if (AV_RL16(b) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE)
851851 return 0;
852852 #if CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER
853− if (ff_jpegxl_verify_codestream_header(p->buf, p->buf_size, 1) >= 0)
853+ if (ff_jpegxl_parse_codestream_header(p->buf, p->buf_size, NULL, 5) >= 0)
854854 return AVPROBE_SCORE_MAX - 2;
855855 #endif
856856 return 0;
libavformat/jpegxl_anim_dec.c+31−101
@@ -28,96 +28,28 @@ · 27 unmodified lines
2828 #include <stdint.h>
2929 #include <string.h>
3030
31−#include "libavcodec/bytestream.h"
32−#define BITSTREAM_READER_LE
33−#include "libavcodec/get_bits.h"
34−
31+#include "libavcodec/jpegxl.h"
32+#include "libavcodec/jpegxl_parse.h"
3533 #include "libavutil/intreadwrite.h"
3634 #include "libavutil/opt.h"
3735
3836 #include "avformat.h"
3937 #include "internal.h"
40−#include "jpegxl_probe.h"
4138
4239 typedef struct JXLAnimDemuxContext {
4340 AVBufferRef *initial;
4441 } JXLAnimDemuxContext;
4542
46−/*
47− * copies as much of the codestream into the buffer as possible
48− * pass a shorter buflen to request less
49− * returns the number of bytes consumed from input, may be greater than input_len
50− * if the input doesn't end on an ISOBMFF-box boundary
51− */
52−static int jpegxl_collect_codestream_header(const uint8_t *input_buffer, int input_len,
53− uint8_t *buffer, int buflen, int *copied) {
54− GetByteContext gb;
55− *copied = 0;
56− bytestream2_init(&gb, input_buffer, input_len);
57−
58− while (1) {
59− uint64_t size;
60− uint32_t tag;
61− int head_size = 8;
62−
63− if (bytestream2_get_bytes_left(&gb) < 16)
64− break;
65−
66− size = bytestream2_get_be32(&gb);
67− if (size == 1) {
68− size = bytestream2_get_be64(&gb);
69− head_size = 16;
70− }
71− /* invalid ISOBMFF size */
72− if (size && size <= head_size)
73− return AVERROR_INVALIDDATA;
74− if (size)
75− size -= head_size;
76−
77− tag = bytestream2_get_le32(&gb);
78− if (tag == MKTAG('j', 'x', 'l', 'p')) {
79− if (bytestream2_get_bytes_left(&gb) < 4)
80− break;
81− bytestream2_skip(&gb, 4);
82− if (size) {
83− if (size <= 4)
84− return AVERROR_INVALIDDATA;
85− size -= 4;
86− }
87− }
88− /*
89− * size = 0 means "until EOF". this is legal but uncommon
90− * here we just set it to the remaining size of the probe buffer
91− */
92− if (!size)
93− size = bytestream2_get_bytes_left(&gb);
94−
95− if (tag == MKTAG('j', 'x', 'l', 'c') || tag == MKTAG('j', 'x', 'l', 'p')) {
96− if (size > buflen - *copied)
97− size = buflen - *copied;
98− /*
99− * arbitrary chunking of the payload makes this memcpy hard to avoid
100− * in practice this will only be performed one or two times at most
101− */
102− *copied += bytestream2_get_buffer(&gb, buffer + *copied, size);
103− } else {
104− bytestream2_skip(&gb, size);
105− }
106− if (bytestream2_get_bytes_left(&gb) <= 0 || *copied >= buflen)
107− break;
108− }
109−
110− return bytestream2_tell(&gb);
111−}
112−
11343 static int jpegxl_anim_probe(const AVProbeData *p)
11444 {
11545 uint8_t buffer[4096 + AV_INPUT_BUFFER_PADDING_SIZE];
116− int copied;
46+ int copied = 0, ret;
47+ FFJXLMetadata meta = { 0 };
11748
11849 /* this is a raw codestream */
11950 if (AV_RL16(p->buf) == FF_JPEGXL_CODESTREAM_SIGNATURE_LE) {
120− if (ff_jpegxl_verify_codestream_header(p->buf, p->buf_size, 1) >= 1)
51+ ret = ff_jpegxl_parse_codestream_header(p->buf, p->buf_size, &meta, 5);
52+ if (ret >= 0 && meta.animation_offset > 0)
12153 return AVPROBE_SCORE_MAX;
12254
12355 return 0;
@@ -127,10 +59,13 @@ static int jpegxl_anim_probe(const AVProbeData *p) · 3 unmodified lines
12759 if (AV_RL64(p->buf) != FF_JPEGXL_CONTAINER_SIGNATURE_LE)
12860 return 0;
12961
130− if (jpegxl_collect_codestream_header(p->buf, p->buf_size, buffer, sizeof(buffer) - AV_INPUT_BUFFER_PADDING_SIZE, &copied) <= 0 || copied <= 0)
62+ if (ff_jpegxl_collect_codestream_header(p->buf, p->buf_size, buffer,
63+ sizeof(buffer) - AV_INPUT_BUFFER_PADDING_SIZE, &copied) <= 0
64+ || copied <= 0)
13165 return 0;
13266
133− if (ff_jpegxl_verify_codestream_header(buffer, copied, 0) >= 1)
67+ ret = ff_jpegxl_parse_codestream_header(buffer, copied, &meta, 10);
68+ if (ret >= 0 && meta.animation_offset > 0)
13469 return AVPROBE_SCORE_MAX;
13570
13671 return 0;
@@ -141,13 +76,10 @@ static int jpegxl_anim_read_header(AVFormatContext *s) · 4 unmodified lines
14176 JXLAnimDemuxContext *ctx = s->priv_data;
14277 AVIOContext *pb = s->pb;
14378 AVStream *st;
144− int offset = 0;
14579 uint8_t head[256 + AV_INPUT_BUFFER_PADDING_SIZE];
14680 const int sizeofhead = sizeof(head) - AV_INPUT_BUFFER_PADDING_SIZE;
147− int headsize = 0;
148− int ctrl;
149− AVRational tb;
150− GetBitContext gbi, *gb = &gbi;
81+ int headsize = 0, ret;
82+ FFJXLMetadata meta = { 0 };
15183
15284 uint64_t sig16 = avio_rl16(pb);
15385 if (sig16 == FF_JPEGXL_CODESTREAM_SIGNATURE_LE) {
@@ -167,7 +99,7 @@ static int jpegxl_anim_read_header(AVFormatContext *s) · 13 unmodified lines
16799 return AVERROR_INVALIDDATA;
168100 avio_skip(pb, 2); // first box always 12 bytes
169101 while (1) {
170− int copied;
102+ int copied = 0;
171103 uint8_t buf[4096];
172104 int read = avio_read(pb, buf, sizeof(buf));
173105 if (read < 0)
@@ -183,20 +115,18 @@ static int jpegxl_anim_read_header(AVFormatContext *s) · 9 unmodified lines
183115 if (av_buffer_realloc(&ctx->initial, ctx->initial->size + read) < 0)
184116 return AVERROR(ENOMEM);
185117 }
186− jpegxl_collect_codestream_header(buf, read, head + headsize, sizeofhead - headsize, &copied);
118+ ff_jpegxl_collect_codestream_header(buf, read, head + headsize, sizeofhead - headsize, &copied);
187119 memcpy(ctx->initial->data + (ctx->initial->size - read), buf, read);
188120 headsize += copied;
189121 if (headsize >= sizeofhead || read < sizeof(buf))
190122 break;
191123 }
192124 }
125+
193126 /* offset in bits of the animation header */
194− offset = ff_jpegxl_verify_codestream_header(head, headsize, 0);
195− if (offset <= 0)
196− return AVERROR_INVALIDDATA;
197− if (init_get_bits8(gb, head, headsize) < 0)
127+ ret = ff_jpegxl_parse_codestream_header(head, headsize, &meta, 0);
128+ if (ret < 0 || meta.animation_offset <= 0)
198129 return AVERROR_INVALIDDATA;
199− skip_bits_long(gb, offset);
200130
201131 st = avformat_new_stream(s, NULL);
202132 if (!st)
@@ -204,11 +134,8 @@ static int jpegxl_anim_read_header(AVFormatContext *s) · 1 unmodified line
204134
205135 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
206136 st->codecpar->codec_id = AV_CODEC_ID_JPEGXL;
207− ctrl = get_bits(gb, 2);
208− tb.den = (const uint32_t[]){100, 1000, 1, 1}[ctrl] + get_bits_long(gb, (const uint32_t[]){0, 0, 10, 30}[ctrl]);
209− ctrl = get_bits(gb, 2);
210− tb.num = (const uint32_t[]){1, 1001, 1, 1}[ctrl] + get_bits_long(gb, (const uint32_t[]){0, 0, 8, 10}[ctrl]);
211− avpriv_set_pts_info(st, 1, tb.num, tb.den);
137+ avpriv_set_pts_info(st, 1, meta.timebase.num, meta.timebase.den);
138+ ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
212139
213140 return 0;
214141 }
@@ -222,17 +149,17 @@ static int jpegxl_anim_read_packet(AVFormatContext *s, AVPacket *pkt) · 7 unmodified lines
222149 int64_t size;
223150 size_t offset = 0;
224151
225− if ((size = avio_size(pb)) < 0)
152+ size = avio_size(pb);
153+ if (size < 0)
226154 return size;
227−
228− /* animated JXL this big should not exist */
229− if (size > INT_MAX)
230− return AVERROR_INVALIDDATA;
155+ if (size == 0)
156+ size = 4096;
231157
232158 if (ctx->initial && size < ctx->initial->size)
233159 size = ctx->initial->size;
234160
235− if ((ret = av_new_packet(pkt, size)) < 0)
161+ ret = av_new_packet(pkt, size);
162+ if (ret < 0)
236163 return ret;
237164
238165 if (ctx->initial) {
@@ -241,8 +168,11 @@ static int jpegxl_anim_read_packet(AVFormatContext *s, AVPacket *pkt) · 2 unmodified lines
241168 av_buffer_unref(&ctx->initial);
242169 }
243170
244− if ((ret = avio_read(pb, pkt->data + offset, size - offset)) < 0)
171+ ret = avio_read(pb, pkt->data + offset, size - offset);
172+ if (ret < 0)
245173 return ret;
174+ if (ret < size - offset)
175+ pkt->size = ret + offset;
246176
247177 return 0;
248178 }
@@ -265,7 +195,7 @@ const AVInputFormat ff_jpegxl_anim_demuxer = { · 16 unmodified lines
265195 .read_packet = jpegxl_anim_read_packet,
266196 .read_close = jpegxl_anim_close,
267197 .flags_internal = FF_FMT_INIT_CLEANUP,
268− .flags = AVFMT_GENERIC_INDEX,
198+ .flags = AVFMT_GENERIC_INDEX | AVFMT_NOTIMESTAMPS,
269199 .mime_type = "image/jxl",
270200 .extensions = "jxl",
271201 };
libavformat/jpegxl_parse.crenamed from libavformat/jpegxl_probe.h+3−18
@@ -1,6 +1,6 @@
11 /*
2− * Jpeg XL header verification
3− * Copyright (c) 2022 Leo Izen <leo.izen@gmail.com>
2+ * JPEG XL Header Parser Stub
3+ * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com>
44 *
55 * This file is part of FFmpeg.
66 *
@@ -19,19 +19,4 @@ · 12 unmodified lines
1919 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2020 */
2121
22−#ifndef AVFORMAT_JPEGXL_PROBE_H
23−#define AVFORMAT_JPEGXL_PROBE_H
24−
25−#include <stdint.h>
26−
27−#define FF_JPEGXL_CODESTREAM_SIGNATURE_LE 0x0aff
28−#define FF_JPEGXL_CONTAINER_SIGNATURE_LE 0x204c584a0c000000
29−
30−/**
31− * @brief verify that a codestream header is valid
32− * @return Negative upon error, 0 upon verifying that the codestream is not animated,
33− * and 1 upon verifying that it is animated
34− */
35−int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int validate_level);
36−
37−#endif /* AVFORMAT_JPEGXL_PROBE_H */
22+#include "libavcodec/jpegxl_parse.c"
libavformat/jpegxl_probe.c+0−412
@@ -1,412 +0,0 @@
1−/*
2− * Jpeg XL header verification
3− * Copyright (c) 2022 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 "jpegxl_probe.h"
23−
24−#define UNCHECKED_BITSTREAM_READER 0
25−#define BITSTREAM_READER_LE
26−#include "libavcodec/get_bits.h"
27−
28−enum JpegXLExtraChannelType {
29− FF_JPEGXL_CT_ALPHA = 0,
30− FF_JPEGXL_CT_DEPTH,
31− FF_JPEGXL_CT_SPOT_COLOR,
32− FF_JPEGXL_CT_SELECTION_MASK,
33− FF_JPEGXL_CT_BLACK,
34− FF_JPEGXL_CT_CFA,
35− FF_JPEGXL_CT_THERMAL,
36− FF_JPEGXL_CT_NON_OPTIONAL = 15,
37− FF_JPEGXL_CT_OPTIONAL
38−};
39−
40−enum JpegXLColorSpace {
41− FF_JPEGXL_CS_RGB = 0,
42− FF_JPEGXL_CS_GRAY,
43− FF_JPEGXL_CS_XYB,
44− FF_JPEGXL_CS_UNKNOWN
45−};
46−
47−enum JpegXLWhitePoint {
48− FF_JPEGXL_WP_D65 = 1,
49− FF_JPEGXL_WP_CUSTOM,
50− FF_JPEGXL_WP_E = 10,
51− FF_JPEGXL_WP_DCI = 11
52−};
53−
54−enum JpegXLPrimaries {
55− FF_JPEGXL_PR_SRGB = 1,
56− FF_JPEGXL_PR_CUSTOM,
57− FF_JPEGXL_PR_2100 = 9,
58− FF_JPEGXL_PR_P3 = 11,
59−};
60−
61−/* read a U32(c_i + u(u_i)) */
62−static av_always_inline uint32_t jxl_u32(GetBitContext *gb,
63− uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3,
64− uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3)
65−{
66− const uint32_t constants[4] = {c0, c1, c2, c3};
67− const uint32_t ubits [4] = {u0, u1, u2, u3};
68− uint32_t ret, choice = get_bits(gb, 2);
69−
70− ret = constants[choice];
71− if (ubits[choice])
72− ret += get_bits_long(gb, ubits[choice]);
73−
74− return ret;
75−}
76−
77−static av_always_inline uint32_t jxl_enum(GetBitContext *gb)
78−{
79− return jxl_u32(gb, 0, 1, 2, 18, 0, 0, 4, 6);
80−}
81−
82−/* read a U64() */
83−static uint64_t jpegxl_u64(GetBitContext *gb)
84−{
85− uint64_t shift = 12, ret;
86−
87− switch (get_bits(gb, 2)) {
88− case 0:
89− ret = 0;
90− break;
91− case 1:
92− ret = 1 + get_bits(gb, 4);
93− break;
94− case 2:
95− ret = 17 + get_bits(gb, 8);
96− break;
97− case 3:
98− ret = get_bits(gb, 12);
99− while (get_bits1(gb)) {
100− if (shift < 60) {
101− ret |= (uint64_t)get_bits(gb, 8) << shift;
102− shift += 8;
103− } else {
104− ret |= (uint64_t)get_bits(gb, 4) << shift;
105− break;
106− }
107− }
108− break;
109− }
110−
111− return ret;
112−}
113−
114−static uint32_t jpegxl_width_from_ratio(uint32_t height, int ratio)
115−{
116− uint64_t height64 = height; /* avoid integer overflow */
117− switch (ratio) {
118− case 1:
119− return height;
120− case 2:
121− return (uint32_t)((height64 * 12) / 10);
122− case 3:
123− return (uint32_t)((height64 * 4) / 3);
124− case 4:
125− return (uint32_t)((height64 * 3) / 2);
126− case 5:
127− return (uint32_t)((height64 * 16) / 9);
128− case 6:
129− return (uint32_t)((height64 * 5) / 4);
130− case 7:
131− return (uint32_t)(height64 * 2);
132− default:
133− break;
134− }
135−
136− return 0; /* manual width */
137−}
138−
139−/**
140− * validate a Jpeg XL Size Header
141− * @return >= 0 upon valid size, < 0 upon invalid size found
142− */
143−static int jpegxl_read_size_header(GetBitContext *gb)
144−{
145− uint32_t width, height;
146−
147− if (get_bits1(gb)) {
148− /* small size header */
149− height = (get_bits(gb, 5) + 1) << 3;
150− width = jpegxl_width_from_ratio(height, get_bits(gb, 3));
151− if (!width)
152− width = (get_bits(gb, 5) + 1) << 3;
153− } else {
154− /* large size header */
155− height = 1 + jxl_u32(gb, 0, 0, 0, 0, 9, 13, 18, 30);
156− width = jpegxl_width_from_ratio(height, get_bits(gb, 3));
157− if (!width)
158− width = 1 + jxl_u32(gb, 0, 0, 0, 0, 9, 13, 18, 30);
159− }
160− if (width > (1 << 18) || height > (1 << 18)
161− || (width >> 4) * (height >> 4) > (1 << 20))
162− return -1;
163−
164− return 0;
165−}
166−
167−/**
168− * validate a Jpeg XL Preview Header
169− * @return >= 0 upon valid size, < 0 upon invalid size found
170− */
171−static int jpegxl_read_preview_header(GetBitContext *gb)
172−{
173− uint32_t width, height;
174−
175− if (get_bits1(gb)) {
176− /* coded height and width divided by eight */
177− height = jxl_u32(gb, 16, 32, 1, 33, 0, 0, 5, 9) << 3;
178− width = jpegxl_width_from_ratio(height, get_bits(gb, 3));
179− if (!width)
180− width = jxl_u32(gb, 16, 32, 1, 33, 0, 0, 5, 9) << 3;
181− } else {
182− /* full height and width coded */
183− height = jxl_u32(gb, 1, 65, 321, 1345, 6, 8, 10, 12);
184− width = jpegxl_width_from_ratio(height, get_bits(gb, 3));
185− if (!width)
186− width = jxl_u32(gb, 1, 65, 321, 1345, 6, 8, 10, 12);
187− }
188− if (width > 4096 || height > 4096)
189− return -1;
190−
191− return 0;
192−}
193−
194−/**
195− * skip a Jpeg XL BitDepth Header. These cannot be invalid.
196− */
197−static void jpegxl_skip_bit_depth(GetBitContext *gb)
198−{
199− if (get_bits1(gb)) {
200− /* float samples */
201− jxl_u32(gb, 32, 16, 24, 1, 0, 0, 0, 6); /* mantissa */
202− skip_bits_long(gb, 4); /* exponent */
203− } else {
204− /* integer samples */
205− jxl_u32(gb, 8, 10, 12, 1, 0, 0, 0, 6);
206− }
207−}
208−
209−/**
210− * validate a Jpeg XL Extra Channel Info bundle
211− * @return >= 0 upon valid, < 0 upon invalid
212− */
213−static int jpegxl_read_extra_channel_info(GetBitContext *gb, int validate_level)
214−{
215− int all_default = get_bits1(gb);
216− uint32_t type, name_len = 0;
217−
218− if (!all_default) {
219− type = jxl_enum(gb);
220− if (type > 63)
221− return -1; /* enum types cannot be 64+ */
222− if (type == FF_JPEGXL_CT_BLACK && validate_level)
223− return -1;
224− jpegxl_skip_bit_depth(gb);
225− jxl_u32(gb, 0, 3, 4, 1, 0, 0, 0, 3); /* dim-shift */
226− /* max of name_len is 1071 = 48 + 2^10 - 1 */
227− name_len = jxl_u32(gb, 0, 0, 16, 48, 0, 4, 5, 10);
228− } else {
229− type = FF_JPEGXL_CT_ALPHA;
230− }
231−
232− /* skip over the name */
233− skip_bits_long(gb, 8 * name_len);
234−
235− if (!all_default && type == FF_JPEGXL_CT_ALPHA)
236− skip_bits1(gb);
237−
238− if (type == FF_JPEGXL_CT_SPOT_COLOR)
239− skip_bits_long(gb, 16 * 4);
240−
241− if (type == FF_JPEGXL_CT_CFA)
242− jxl_u32(gb, 1, 0, 3, 19, 0, 2, 4, 8);
243−
244− return 0;
245−}
246−
247−int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int validate_level)
248−{
249− GetBitContext gbi, *gb = &gbi;
250− int all_default, extra_fields = 0;
251− int xyb_encoded = 1, have_icc_profile = 0;
252− int animation_offset = 0;
253− uint32_t num_extra_channels;
254− uint64_t extensions;
255− int ret;
256−
257− ret = init_get_bits8(gb, buf, buflen);
258− if (ret < 0)
259− return ret;
260−
261− if (get_bits_long(gb, 16) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE)
262− return -1;
263−
264− if ((ret = jpegxl_read_size_header(gb)) < 0 && validate_level)
265− return ret;
266−
267− all_default = get_bits1(gb);
268− if (!all_default)
269− extra_fields = get_bits1(gb);
270−
271− if (extra_fields) {
272− skip_bits_long(gb, 3); /* orientation */
273−
274− /*
275− * intrinstic size
276− * any size header here is valid, but as it
277− * is variable length we have to read it
278− */
279− if (get_bits1(gb))
280− jpegxl_read_size_header(gb);
281−
282− /* preview header */
283− if (get_bits1(gb)) {
284− ret = jpegxl_read_preview_header(gb);
285− if (ret < 0)
286− return ret;
287− }
288−
289− /* animation header */
290− if (get_bits1(gb)) {
291− animation_offset = get_bits_count(gb);
292− jxl_u32(gb, 100, 1000, 1, 1, 0, 0, 10, 30);
293− jxl_u32(gb, 1, 1001, 1, 1, 0, 0, 8, 10);
294− jxl_u32(gb, 0, 0, 0, 0, 0, 3, 16, 32);
295− skip_bits_long(gb, 1);
296− }
297− }
298− if (get_bits_left(gb) < 1)
299− return AVERROR_INVALIDDATA;
300−
301− if (!all_default) {
302− jpegxl_skip_bit_depth(gb);
303−
304− /* modular_16bit_buffers must equal 1 */
305− if (!get_bits1(gb) && validate_level)
306− return -1;
307−
308− num_extra_channels = jxl_u32(gb, 0, 1, 2, 1, 0, 0, 4, 12);
309− if (num_extra_channels > 4 && validate_level)
310− return -1;
311− for (uint32_t i = 0; i < num_extra_channels; i++) {
312− ret = jpegxl_read_extra_channel_info(gb, validate_level);
313− if (ret < 0)
314− return ret;
315− if (get_bits_left(gb) < 1)
316− return AVERROR_INVALIDDATA;
317− }
318−
319− xyb_encoded = get_bits1(gb);
320−
321− /* color encoding bundle */
322− if (!get_bits1(gb)) {
323− uint32_t color_space;
324− have_icc_profile = get_bits1(gb);
325− color_space = jxl_enum(gb);
326− if (color_space > 63)
327− return -1;
328−
329− if (!have_icc_profile) {
330− if (color_space != FF_JPEGXL_CS_XYB) {
331− uint32_t white_point = jxl_enum(gb);
332− if (white_point > 63)
333− return -1;
334− if (white_point == FF_JPEGXL_WP_CUSTOM) {
335− /* ux and uy values */
336− jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21);
337− jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21);
338− }
339− if (color_space != FF_JPEGXL_CS_GRAY) {
340− /* primaries */
341− uint32_t primaries = jxl_enum(gb);
342− if (primaries > 63)
343− return -1;
344− if (primaries == FF_JPEGXL_PR_CUSTOM) {
345− /* ux/uy values for r,g,b */
346− for (int i = 0; i < 6; i++) {
347− jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21);
348− if (get_bits_left(gb) < 1)
349− return AVERROR_INVALIDDATA;
350− }
351− }
352− }
353− }
354−
355− /* transfer characteristics */
356− if (get_bits1(gb)) {
357− /* gamma */
358− skip_bits_long(gb, 24);
359− } else {
360− /* transfer function */
361− if (jxl_enum(gb) > 63)
362− return -1;
363− }
364−
365− /* rendering intent */
366− if (jxl_enum(gb) > 63)
367− return -1;
368− }
369− }
370−
371− /* tone mapping bundle */
372− if (extra_fields && !get_bits1(gb))
373− skip_bits_long(gb, 16 + 16 + 1 + 16);
374−
375− extensions = jpegxl_u64(gb);
376− if (get_bits_left(gb) < 1)
377− return AVERROR_INVALIDDATA;
378− if (extensions) {
379− for (int i = 0; i < 64; i++) {
380− if (extensions & (UINT64_C(1) << i))
381− jpegxl_u64(gb);
382− if (get_bits_left(gb) < 1)
383− return AVERROR_INVALIDDATA;
384− }
385− }
386− }
387−
388− /* default transform */
389− if (!get_bits1(gb)) {
390− /* opsin inverse matrix */
391− if (xyb_encoded && !get_bits1(gb))
392− skip_bits_long(gb, 16 * 16);
393− /* cw_mask and default weights */
394− if (get_bits1(gb))
395− skip_bits_long(gb, 16 * 15);
396− if (get_bits1(gb))
397− skip_bits_long(gb, 16 * 55);
398− if (get_bits1(gb))
399− skip_bits_long(gb, 16 * 210);
400− }
401−
402− if (!have_icc_profile) {
403− int bits_remaining = 7 - (get_bits_count(gb) - 1) % 8;
404− if (bits_remaining && get_bits(gb, bits_remaining))
405− return -1;
406− }
407−
408− if (get_bits_left(gb) < 0)
409− return -1;
410−
411− return animation_offset;
412−}
libavformat/version.h+1−1
@@ -32,7 +32,7 @@ · 31 unmodified lines
3232 #include "version_major.h"
3333
3434 #define LIBAVFORMAT_VERSION_MINOR 10
35−#define LIBAVFORMAT_VERSION_MICRO 100
35+#define LIBAVFORMAT_VERSION_MICRO 101
3636
3737 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
3838 LIBAVFORMAT_VERSION_MINOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t