From: Leo Izen <leo.izen@gmail.com> To: ffmpeg-devel@ffmpeg.org Subject: Re: [FFmpeg-devel] [PATCH v5 3/4] avformat/jpegxl: remove jpegxl_probe, instead call avcodec/jpegxl_parse Date: Sun, 23 Jul 2023 19:58:45 -0400 Message-ID: <e7d4bb45-20ce-e54d-bc1e-f8ba09281d02@gmail.com> (raw) In-Reply-To: <GV1P250MB07374E06AA7DF758CECC86D98F3DA@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM> On 7/23/23 06:08, Andreas Rheinhardt wrote: > Leo Izen: >> 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 > > How large is it? Whatever the size of jpegxl_parse.c is, which is about 520 LOC including all the comments, and the object file is 174k on my system, including debug symbols, and about 13k after stripping. > >> code it will only exist in one location now. >> >> Signed-off-by: Leo Izen <leo.izen@gmail.com> >> --- >> libavformat/Makefile | 6 +- >> libavformat/img2dec.c | 4 +- >> libavformat/jpegxl_anim_dec.c | 115 +---- >> .../{jpegxl_probe.h => jpegxl_parse.c} | 21 +- >> libavformat/jpegxl_probe.c | 412 ------------------ >> libavformat/version.h | 2 +- >> 6 files changed, 31 insertions(+), 529 deletions(-) >> rename libavformat/{jpegxl_probe.h => jpegxl_parse.c} (55%) >> delete mode 100644 libavformat/jpegxl_probe.c >> >> diff --git a/libavformat/Makefile b/libavformat/Makefile >> index 4cb00f8700..c6f7457ac5 100644 >> --- a/libavformat/Makefile >> +++ b/libavformat/Makefile >> @@ -283,7 +283,7 @@ OBJS-$(CONFIG_IMAGE_HDR_PIPE_DEMUXER) += img2dec.o img2.o >> OBJS-$(CONFIG_IMAGE_J2K_PIPE_DEMUXER) += img2dec.o img2.o >> OBJS-$(CONFIG_IMAGE_JPEG_PIPE_DEMUXER) += img2dec.o img2.o >> OBJS-$(CONFIG_IMAGE_JPEGLS_PIPE_DEMUXER) += img2dec.o img2.o >> -OBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += img2dec.o img2.o jpegxl_probe.o >> +OBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += img2dec.o img2.o jpegxl_parse.o >> OBJS-$(CONFIG_IMAGE_PAM_PIPE_DEMUXER) += img2dec.o img2.o >> OBJS-$(CONFIG_IMAGE_PBM_PIPE_DEMUXER) += img2dec.o img2.o >> OBJS-$(CONFIG_IMAGE_PCX_PIPE_DEMUXER) += img2dec.o img2.o >> @@ -320,7 +320,7 @@ OBJS-$(CONFIG_IVF_MUXER) += ivfenc.o >> OBJS-$(CONFIG_IVR_DEMUXER) += rmdec.o rm.o rmsipr.o >> OBJS-$(CONFIG_JACOSUB_DEMUXER) += jacosubdec.o subtitles.o >> OBJS-$(CONFIG_JACOSUB_MUXER) += jacosubenc.o rawenc.o >> -OBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_anim_dec.o jpegxl_probe.o >> +OBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_anim_dec.o jpegxl_parse.o >> OBJS-$(CONFIG_JV_DEMUXER) += jvdec.o >> OBJS-$(CONFIG_KUX_DEMUXER) += flvdec.o >> OBJS-$(CONFIG_KVAG_DEMUXER) += kvag.o >> @@ -717,6 +717,8 @@ SHLIBOBJS += log2_tab.o to_upper4.o >> SHLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o >> SHLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o >> SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o >> +SHLIBOBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += jpegxl_parse.o >> +SHLIBOBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_parse.o >> SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o >> SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o >> SHLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o > > The typical way to do these Makefile dependencies is to add SHLIBOBJS to > the the dependent library (so that this stuff is included in it for > shared builds) and to add a STLIBOBJS dependency to the lavc Makefile > (so that it will be included in libavcodec.a even if nothing in > libavcodec needs it on its own when making a static build). > > As is it, including jpegxl_parse.o in the dependencies above is > redundant, because it is already in OBJS. I have both this dependency SHLIOBJS in lavf and STLIBOBJS in lavc, I didn't realize that meant I can remove it from OBJS. I will do that. > >> diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c >> index b986d3a502..15fd67927f 100644 >> --- a/libavformat/img2dec.c >> +++ b/libavformat/img2dec.c >> @@ -36,7 +36,7 @@ >> #include "avio_internal.h" >> #include "internal.h" >> #include "img2.h" >> -#include "jpegxl_probe.h" >> +#include "libavcodec/jpegxl_parse.h" >> #include "libavcodec/mjpeg.h" >> #include "libavcodec/vbn.h" >> #include "libavcodec/xwd.h" >> @@ -850,7 +850,7 @@ static int jpegxl_probe(const AVProbeData *p) >> if (AV_RL16(b) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE) >> return 0; >> #if CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER >> - if (ff_jpegxl_verify_codestream_header(p->buf, p->buf_size, 1) >= 0) >> + if (ff_jpegxl_parse_codestream_header(p->buf, p->buf_size, NULL, 5) >= 0) >> return AVPROBE_SCORE_MAX - 2; >> #endif >> return 0; >> diff --git a/libavformat/jpegxl_anim_dec.c b/libavformat/jpegxl_anim_dec.c >> index 956b56c1d8..7d0df3820c 100644 >> --- a/libavformat/jpegxl_anim_dec.c >> +++ b/libavformat/jpegxl_anim_dec.c >> @@ -28,96 +28,28 @@ >> #include <stdint.h> >> #include <string.h> >> >> -#include "libavcodec/bytestream.h" >> -#define BITSTREAM_READER_LE >> -#include "libavcodec/get_bits.h" >> - >> +#include "libavcodec/jpegxl.h" >> +#include "libavcodec/jpegxl_parse.h" >> #include "libavutil/intreadwrite.h" >> #include "libavutil/opt.h" >> >> #include "avformat.h" >> #include "internal.h" >> -#include "jpegxl_probe.h" >> >> typedef struct JXLAnimDemuxContext { >> AVBufferRef *initial; >> } JXLAnimDemuxContext; >> >> -/* >> - * copies as much of the codestream into the buffer as possible >> - * pass a shorter buflen to request less >> - * returns the number of bytes consumed from input, may be greater than input_len >> - * if the input doesn't end on an ISOBMFF-box boundary >> - */ >> -static int jpegxl_collect_codestream_header(const uint8_t *input_buffer, int input_len, >> - uint8_t *buffer, int buflen, int *copied) { >> - GetByteContext gb; >> - *copied = 0; >> - bytestream2_init(&gb, input_buffer, input_len); >> - >> - while (1) { >> - uint64_t size; >> - uint32_t tag; >> - int head_size = 8; >> - >> - if (bytestream2_get_bytes_left(&gb) < 16) >> - break; >> - >> - size = bytestream2_get_be32(&gb); >> - if (size == 1) { >> - size = bytestream2_get_be64(&gb); >> - head_size = 16; >> - } >> - /* invalid ISOBMFF size */ >> - if (size && size <= head_size) >> - return AVERROR_INVALIDDATA; >> - if (size) >> - size -= head_size; >> - >> - tag = bytestream2_get_le32(&gb); >> - if (tag == MKTAG('j', 'x', 'l', 'p')) { >> - if (bytestream2_get_bytes_left(&gb) < 4) >> - break; >> - bytestream2_skip(&gb, 4); >> - if (size) { >> - if (size <= 4) >> - return AVERROR_INVALIDDATA; >> - size -= 4; >> - } >> - } >> - /* >> - * size = 0 means "until EOF". this is legal but uncommon >> - * here we just set it to the remaining size of the probe buffer >> - */ >> - if (!size) >> - size = bytestream2_get_bytes_left(&gb); >> - >> - if (tag == MKTAG('j', 'x', 'l', 'c') || tag == MKTAG('j', 'x', 'l', 'p')) { >> - if (size > buflen - *copied) >> - size = buflen - *copied; >> - /* >> - * arbitrary chunking of the payload makes this memcpy hard to avoid >> - * in practice this will only be performed one or two times at most >> - */ >> - *copied += bytestream2_get_buffer(&gb, buffer + *copied, size); >> - } else { >> - bytestream2_skip(&gb, size); >> - } >> - if (bytestream2_get_bytes_left(&gb) <= 0 || *copied >= buflen) >> - break; >> - } >> - >> - return bytestream2_tell(&gb); >> -} >> - >> static int jpegxl_anim_probe(const AVProbeData *p) >> { >> uint8_t buffer[4096 + AV_INPUT_BUFFER_PADDING_SIZE]; >> - int copied; >> + int copied = 0, ret; >> + FFJXLMetadata meta = { 0 }; >> >> /* this is a raw codestream */ >> if (AV_RL16(p->buf) == FF_JPEGXL_CODESTREAM_SIGNATURE_LE) { >> - if (ff_jpegxl_verify_codestream_header(p->buf, p->buf_size, 1) >= 1) >> + ret = ff_jpegxl_parse_codestream_header(p->buf, p->buf_size, &meta, 5); >> + if (ret >= 0 && meta.animation_offset > 0) >> return AVPROBE_SCORE_MAX; >> >> return 0; >> @@ -127,10 +59,13 @@ static int jpegxl_anim_probe(const AVProbeData *p) >> if (AV_RL64(p->buf) != FF_JPEGXL_CONTAINER_SIGNATURE_LE) >> return 0; >> >> - if (jpegxl_collect_codestream_header(p->buf, p->buf_size, buffer, sizeof(buffer) - AV_INPUT_BUFFER_PADDING_SIZE, &copied) <= 0 || copied <= 0) >> + if (ff_jpegxl_collect_codestream_header(p->buf, p->buf_size, buffer, >> + sizeof(buffer) - AV_INPUT_BUFFER_PADDING_SIZE, &copied) <= 0 >> + || copied <= 0) >> return 0; >> >> - if (ff_jpegxl_verify_codestream_header(buffer, copied, 0) >= 1) >> + ret = ff_jpegxl_parse_codestream_header(buffer, copied, &meta, 10); >> + if (ret >= 0 && meta.animation_offset > 0) >> return AVPROBE_SCORE_MAX; >> >> return 0; >> @@ -141,13 +76,10 @@ static int jpegxl_anim_read_header(AVFormatContext *s) >> JXLAnimDemuxContext *ctx = s->priv_data; >> AVIOContext *pb = s->pb; >> AVStream *st; >> - int offset = 0; >> uint8_t head[256 + AV_INPUT_BUFFER_PADDING_SIZE]; >> const int sizeofhead = sizeof(head) - AV_INPUT_BUFFER_PADDING_SIZE; >> - int headsize = 0; >> - int ctrl; >> - AVRational tb; >> - GetBitContext gbi, *gb = &gbi; >> + int headsize = 0, ret; >> + FFJXLMetadata meta = { 0 }; >> >> uint64_t sig16 = avio_rl16(pb); >> if (sig16 == FF_JPEGXL_CODESTREAM_SIGNATURE_LE) { >> @@ -167,7 +99,7 @@ static int jpegxl_anim_read_header(AVFormatContext *s) >> return AVERROR_INVALIDDATA; >> avio_skip(pb, 2); // first box always 12 bytes >> while (1) { >> - int copied; >> + int copied = 0; >> uint8_t buf[4096]; >> int read = avio_read(pb, buf, sizeof(buf)); >> if (read < 0) >> @@ -183,20 +115,18 @@ static int jpegxl_anim_read_header(AVFormatContext *s) >> if (av_buffer_realloc(&ctx->initial, ctx->initial->size + read) < 0) >> return AVERROR(ENOMEM); >> } >> - jpegxl_collect_codestream_header(buf, read, head + headsize, sizeofhead - headsize, &copied); >> + ff_jpegxl_collect_codestream_header(buf, read, head + headsize, sizeofhead - headsize, &copied); >> memcpy(ctx->initial->data + (ctx->initial->size - read), buf, read); >> headsize += copied; >> if (headsize >= sizeofhead || read < sizeof(buf)) >> break; >> } >> } >> + >> /* offset in bits of the animation header */ >> - offset = ff_jpegxl_verify_codestream_header(head, headsize, 0); >> - if (offset <= 0) >> - return AVERROR_INVALIDDATA; >> - if (init_get_bits8(gb, head, headsize) < 0) >> + ret = ff_jpegxl_parse_codestream_header(head, headsize, &meta, 0); >> + if (ret < 0 || meta.animation_offset <= 0) >> return AVERROR_INVALIDDATA; >> - skip_bits_long(gb, offset); >> >> st = avformat_new_stream(s, NULL); >> if (!st) >> @@ -204,11 +134,8 @@ static int jpegxl_anim_read_header(AVFormatContext *s) >> >> st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; >> st->codecpar->codec_id = AV_CODEC_ID_JPEGXL; >> - ctrl = get_bits(gb, 2); >> - tb.den = (const uint32_t[]){100, 1000, 1, 1}[ctrl] + get_bits_long(gb, (const uint32_t[]){0, 0, 10, 30}[ctrl]); >> - ctrl = get_bits(gb, 2); >> - tb.num = (const uint32_t[]){1, 1001, 1, 1}[ctrl] + get_bits_long(gb, (const uint32_t[]){0, 0, 8, 10}[ctrl]); >> - avpriv_set_pts_info(st, 1, tb.num, tb.den); >> + avpriv_set_pts_info(st, 1, meta.timebase.num, meta.timebase.den); >> + ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL; >> >> return 0; >> } >> @@ -265,7 +192,7 @@ const AVInputFormat ff_jpegxl_anim_demuxer = { >> .read_packet = jpegxl_anim_read_packet, >> .read_close = jpegxl_anim_close, >> .flags_internal = FF_FMT_INIT_CLEANUP, >> - .flags = AVFMT_GENERIC_INDEX, >> + .flags = AVFMT_GENERIC_INDEX | AVFMT_NOTIMESTAMPS, > > Why this change? Seems unrelated to the commit. > >> .mime_type = "image/jxl", >> .extensions = "jxl", >> }; >> diff --git a/libavformat/jpegxl_probe.h b/libavformat/jpegxl_parse.c >> similarity index 55% >> rename from libavformat/jpegxl_probe.h >> rename to libavformat/jpegxl_parse.c >> index 496445fbce..1be5fd716f 100644 >> --- a/libavformat/jpegxl_probe.h >> +++ b/libavformat/jpegxl_parse.c >> @@ -1,6 +1,6 @@ >> /* >> - * Jpeg XL header verification >> - * Copyright (c) 2022 Leo Izen <leo.izen@gmail.com> >> + * JPEG XL Header Parser >> + * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com> >> * >> * This file is part of FFmpeg. >> * >> @@ -19,19 +19,4 @@ >> * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA >> */ >> >> -#ifndef AVFORMAT_JPEGXL_PROBE_H >> -#define AVFORMAT_JPEGXL_PROBE_H >> - >> -#include <stdint.h> >> - >> -#define FF_JPEGXL_CODESTREAM_SIGNATURE_LE 0x0aff >> -#define FF_JPEGXL_CONTAINER_SIGNATURE_LE 0x204c584a0c000000 >> - >> -/** >> - * @brief verify that a codestream header is valid >> - * @return Negative upon error, 0 upon verifying that the codestream is not animated, >> - * and 1 upon verifying that it is animated >> - */ >> -int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int validate_level); >> - >> -#endif /* AVFORMAT_JPEGXL_PROBE_H */ >> + #include "libavcodec/jpegxl_parse.c" >> diff --git a/libavformat/jpegxl_probe.c b/libavformat/jpegxl_probe.c >> deleted file mode 100644 >> index 88492cb772..0000000000 >> --- a/libavformat/jpegxl_probe.c >> +++ /dev/null >> @@ -1,412 +0,0 @@ >> -/* >> - * Jpeg XL header verification >> - * Copyright (c) 2022 Leo Izen <leo.izen@gmail.com> >> - * >> - * This file is part of FFmpeg. >> - * >> - * FFmpeg is free software; you can redistribute it and/or >> - * modify it under the terms of the GNU Lesser General Public >> - * License as published by the Free Software Foundation; either >> - * version 2.1 of the License, or (at your option) any later version. >> - * >> - * FFmpeg is distributed in the hope that it will be useful, >> - * but WITHOUT ANY WARRANTY; without even the implied warranty of >> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> - * Lesser General Public License for more details. >> - * >> - * You should have received a copy of the GNU Lesser General Public >> - * License along with FFmpeg; if not, write to the Free Software >> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA >> - */ >> - >> -#include "jpegxl_probe.h" >> - >> -#define UNCHECKED_BITSTREAM_READER 0 >> -#define BITSTREAM_READER_LE >> -#include "libavcodec/get_bits.h" >> - >> -enum JpegXLExtraChannelType { >> - FF_JPEGXL_CT_ALPHA = 0, >> - FF_JPEGXL_CT_DEPTH, >> - FF_JPEGXL_CT_SPOT_COLOR, >> - FF_JPEGXL_CT_SELECTION_MASK, >> - FF_JPEGXL_CT_BLACK, >> - FF_JPEGXL_CT_CFA, >> - FF_JPEGXL_CT_THERMAL, >> - FF_JPEGXL_CT_NON_OPTIONAL = 15, >> - FF_JPEGXL_CT_OPTIONAL >> -}; >> - >> -enum JpegXLColorSpace { >> - FF_JPEGXL_CS_RGB = 0, >> - FF_JPEGXL_CS_GRAY, >> - FF_JPEGXL_CS_XYB, >> - FF_JPEGXL_CS_UNKNOWN >> -}; >> - >> -enum JpegXLWhitePoint { >> - FF_JPEGXL_WP_D65 = 1, >> - FF_JPEGXL_WP_CUSTOM, >> - FF_JPEGXL_WP_E = 10, >> - FF_JPEGXL_WP_DCI = 11 >> -}; >> - >> -enum JpegXLPrimaries { >> - FF_JPEGXL_PR_SRGB = 1, >> - FF_JPEGXL_PR_CUSTOM, >> - FF_JPEGXL_PR_2100 = 9, >> - FF_JPEGXL_PR_P3 = 11, >> -}; >> - >> -/* read a U32(c_i + u(u_i)) */ >> -static av_always_inline uint32_t jxl_u32(GetBitContext *gb, >> - uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, >> - uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) >> -{ >> - const uint32_t constants[4] = {c0, c1, c2, c3}; >> - const uint32_t ubits [4] = {u0, u1, u2, u3}; >> - uint32_t ret, choice = get_bits(gb, 2); >> - >> - ret = constants[choice]; >> - if (ubits[choice]) >> - ret += get_bits_long(gb, ubits[choice]); >> - >> - return ret; >> -} >> - >> -static av_always_inline uint32_t jxl_enum(GetBitContext *gb) >> -{ >> - return jxl_u32(gb, 0, 1, 2, 18, 0, 0, 4, 6); >> -} >> - >> -/* read a U64() */ >> -static uint64_t jpegxl_u64(GetBitContext *gb) >> -{ >> - uint64_t shift = 12, ret; >> - >> - switch (get_bits(gb, 2)) { >> - case 0: >> - ret = 0; >> - break; >> - case 1: >> - ret = 1 + get_bits(gb, 4); >> - break; >> - case 2: >> - ret = 17 + get_bits(gb, 8); >> - break; >> - case 3: >> - ret = get_bits(gb, 12); >> - while (get_bits1(gb)) { >> - if (shift < 60) { >> - ret |= (uint64_t)get_bits(gb, 8) << shift; >> - shift += 8; >> - } else { >> - ret |= (uint64_t)get_bits(gb, 4) << shift; >> - break; >> - } >> - } >> - break; >> - } >> - >> - return ret; >> -} >> - >> -static uint32_t jpegxl_width_from_ratio(uint32_t height, int ratio) >> -{ >> - uint64_t height64 = height; /* avoid integer overflow */ >> - switch (ratio) { >> - case 1: >> - return height; >> - case 2: >> - return (uint32_t)((height64 * 12) / 10); >> - case 3: >> - return (uint32_t)((height64 * 4) / 3); >> - case 4: >> - return (uint32_t)((height64 * 3) / 2); >> - case 5: >> - return (uint32_t)((height64 * 16) / 9); >> - case 6: >> - return (uint32_t)((height64 * 5) / 4); >> - case 7: >> - return (uint32_t)(height64 * 2); >> - default: >> - break; >> - } >> - >> - return 0; /* manual width */ >> -} >> - >> -/** >> - * validate a Jpeg XL Size Header >> - * @return >= 0 upon valid size, < 0 upon invalid size found >> - */ >> -static int jpegxl_read_size_header(GetBitContext *gb) >> -{ >> - uint32_t width, height; >> - >> - if (get_bits1(gb)) { >> - /* small size header */ >> - height = (get_bits(gb, 5) + 1) << 3; >> - width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); >> - if (!width) >> - width = (get_bits(gb, 5) + 1) << 3; >> - } else { >> - /* large size header */ >> - height = 1 + jxl_u32(gb, 0, 0, 0, 0, 9, 13, 18, 30); >> - width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); >> - if (!width) >> - width = 1 + jxl_u32(gb, 0, 0, 0, 0, 9, 13, 18, 30); >> - } >> - if (width > (1 << 18) || height > (1 << 18) >> - || (width >> 4) * (height >> 4) > (1 << 20)) >> - return -1; >> - >> - return 0; >> -} >> - >> -/** >> - * validate a Jpeg XL Preview Header >> - * @return >= 0 upon valid size, < 0 upon invalid size found >> - */ >> -static int jpegxl_read_preview_header(GetBitContext *gb) >> -{ >> - uint32_t width, height; >> - >> - if (get_bits1(gb)) { >> - /* coded height and width divided by eight */ >> - height = jxl_u32(gb, 16, 32, 1, 33, 0, 0, 5, 9) << 3; >> - width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); >> - if (!width) >> - width = jxl_u32(gb, 16, 32, 1, 33, 0, 0, 5, 9) << 3; >> - } else { >> - /* full height and width coded */ >> - height = jxl_u32(gb, 1, 65, 321, 1345, 6, 8, 10, 12); >> - width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); >> - if (!width) >> - width = jxl_u32(gb, 1, 65, 321, 1345, 6, 8, 10, 12); >> - } >> - if (width > 4096 || height > 4096) >> - return -1; >> - >> - return 0; >> -} >> - >> -/** >> - * skip a Jpeg XL BitDepth Header. These cannot be invalid. >> - */ >> -static void jpegxl_skip_bit_depth(GetBitContext *gb) >> -{ >> - if (get_bits1(gb)) { >> - /* float samples */ >> - jxl_u32(gb, 32, 16, 24, 1, 0, 0, 0, 6); /* mantissa */ >> - skip_bits_long(gb, 4); /* exponent */ >> - } else { >> - /* integer samples */ >> - jxl_u32(gb, 8, 10, 12, 1, 0, 0, 0, 6); >> - } >> -} >> - >> -/** >> - * validate a Jpeg XL Extra Channel Info bundle >> - * @return >= 0 upon valid, < 0 upon invalid >> - */ >> -static int jpegxl_read_extra_channel_info(GetBitContext *gb, int validate_level) >> -{ >> - int all_default = get_bits1(gb); >> - uint32_t type, name_len = 0; >> - >> - if (!all_default) { >> - type = jxl_enum(gb); >> - if (type > 63) >> - return -1; /* enum types cannot be 64+ */ >> - if (type == FF_JPEGXL_CT_BLACK && validate_level) >> - return -1; >> - jpegxl_skip_bit_depth(gb); >> - jxl_u32(gb, 0, 3, 4, 1, 0, 0, 0, 3); /* dim-shift */ >> - /* max of name_len is 1071 = 48 + 2^10 - 1 */ >> - name_len = jxl_u32(gb, 0, 0, 16, 48, 0, 4, 5, 10); >> - } else { >> - type = FF_JPEGXL_CT_ALPHA; >> - } >> - >> - /* skip over the name */ >> - skip_bits_long(gb, 8 * name_len); >> - >> - if (!all_default && type == FF_JPEGXL_CT_ALPHA) >> - skip_bits1(gb); >> - >> - if (type == FF_JPEGXL_CT_SPOT_COLOR) >> - skip_bits_long(gb, 16 * 4); >> - >> - if (type == FF_JPEGXL_CT_CFA) >> - jxl_u32(gb, 1, 0, 3, 19, 0, 2, 4, 8); >> - >> - return 0; >> -} >> - >> -int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int validate_level) >> -{ >> - GetBitContext gbi, *gb = &gbi; >> - int all_default, extra_fields = 0; >> - int xyb_encoded = 1, have_icc_profile = 0; >> - int animation_offset = 0; >> - uint32_t num_extra_channels; >> - uint64_t extensions; >> - int ret; >> - >> - ret = init_get_bits8(gb, buf, buflen); >> - if (ret < 0) >> - return ret; >> - >> - if (get_bits_long(gb, 16) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE) >> - return -1; >> - >> - if ((ret = jpegxl_read_size_header(gb)) < 0 && validate_level) >> - return ret; >> - >> - all_default = get_bits1(gb); >> - if (!all_default) >> - extra_fields = get_bits1(gb); >> - >> - if (extra_fields) { >> - skip_bits_long(gb, 3); /* orientation */ >> - >> - /* >> - * intrinstic size >> - * any size header here is valid, but as it >> - * is variable length we have to read it >> - */ >> - if (get_bits1(gb)) >> - jpegxl_read_size_header(gb); >> - >> - /* preview header */ >> - if (get_bits1(gb)) { >> - ret = jpegxl_read_preview_header(gb); >> - if (ret < 0) >> - return ret; >> - } >> - >> - /* animation header */ >> - if (get_bits1(gb)) { >> - animation_offset = get_bits_count(gb); >> - jxl_u32(gb, 100, 1000, 1, 1, 0, 0, 10, 30); >> - jxl_u32(gb, 1, 1001, 1, 1, 0, 0, 8, 10); >> - jxl_u32(gb, 0, 0, 0, 0, 0, 3, 16, 32); >> - skip_bits_long(gb, 1); >> - } >> - } >> - if (get_bits_left(gb) < 1) >> - return AVERROR_INVALIDDATA; >> - >> - if (!all_default) { >> - jpegxl_skip_bit_depth(gb); >> - >> - /* modular_16bit_buffers must equal 1 */ >> - if (!get_bits1(gb) && validate_level) >> - return -1; >> - >> - num_extra_channels = jxl_u32(gb, 0, 1, 2, 1, 0, 0, 4, 12); >> - if (num_extra_channels > 4 && validate_level) >> - return -1; >> - for (uint32_t i = 0; i < num_extra_channels; i++) { >> - ret = jpegxl_read_extra_channel_info(gb, validate_level); >> - if (ret < 0) >> - return ret; >> - if (get_bits_left(gb) < 1) >> - return AVERROR_INVALIDDATA; >> - } >> - >> - xyb_encoded = get_bits1(gb); >> - >> - /* color encoding bundle */ >> - if (!get_bits1(gb)) { >> - uint32_t color_space; >> - have_icc_profile = get_bits1(gb); >> - color_space = jxl_enum(gb); >> - if (color_space > 63) >> - return -1; >> - >> - if (!have_icc_profile) { >> - if (color_space != FF_JPEGXL_CS_XYB) { >> - uint32_t white_point = jxl_enum(gb); >> - if (white_point > 63) >> - return -1; >> - if (white_point == FF_JPEGXL_WP_CUSTOM) { >> - /* ux and uy values */ >> - jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21); >> - jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21); >> - } >> - if (color_space != FF_JPEGXL_CS_GRAY) { >> - /* primaries */ >> - uint32_t primaries = jxl_enum(gb); >> - if (primaries > 63) >> - return -1; >> - if (primaries == FF_JPEGXL_PR_CUSTOM) { >> - /* ux/uy values for r,g,b */ >> - for (int i = 0; i < 6; i++) { >> - jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21); >> - if (get_bits_left(gb) < 1) >> - return AVERROR_INVALIDDATA; >> - } >> - } >> - } >> - } >> - >> - /* transfer characteristics */ >> - if (get_bits1(gb)) { >> - /* gamma */ >> - skip_bits_long(gb, 24); >> - } else { >> - /* transfer function */ >> - if (jxl_enum(gb) > 63) >> - return -1; >> - } >> - >> - /* rendering intent */ >> - if (jxl_enum(gb) > 63) >> - return -1; >> - } >> - } >> - >> - /* tone mapping bundle */ >> - if (extra_fields && !get_bits1(gb)) >> - skip_bits_long(gb, 16 + 16 + 1 + 16); >> - >> - extensions = jpegxl_u64(gb); >> - if (get_bits_left(gb) < 1) >> - return AVERROR_INVALIDDATA; >> - if (extensions) { >> - for (int i = 0; i < 64; i++) { >> - if (extensions & (UINT64_C(1) << i)) >> - jpegxl_u64(gb); >> - if (get_bits_left(gb) < 1) >> - return AVERROR_INVALIDDATA; >> - } >> - } >> - } >> - >> - /* default transform */ >> - if (!get_bits1(gb)) { >> - /* opsin inverse matrix */ >> - if (xyb_encoded && !get_bits1(gb)) >> - skip_bits_long(gb, 16 * 16); >> - /* cw_mask and default weights */ >> - if (get_bits1(gb)) >> - skip_bits_long(gb, 16 * 15); >> - if (get_bits1(gb)) >> - skip_bits_long(gb, 16 * 55); >> - if (get_bits1(gb)) >> - skip_bits_long(gb, 16 * 210); >> - } >> - >> - if (!have_icc_profile) { >> - int bits_remaining = 7 - (get_bits_count(gb) - 1) % 8; >> - if (bits_remaining && get_bits(gb, bits_remaining)) >> - return -1; >> - } >> - >> - if (get_bits_left(gb) < 0) >> - return -1; >> - >> - return animation_offset; >> -} >> diff --git a/libavformat/version.h b/libavformat/version.h >> index 979952183c..787ee8c90b 100644 >> --- a/libavformat/version.h >> +++ b/libavformat/version.h >> @@ -32,7 +32,7 @@ >> #include "version_major.h" >> >> #define LIBAVFORMAT_VERSION_MINOR 10 >> -#define LIBAVFORMAT_VERSION_MICRO 100 >> +#define LIBAVFORMAT_VERSION_MICRO 101 >> >> #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ >> LIBAVFORMAT_VERSION_MINOR, \ > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2023-07-23 23:58 UTC|newest] Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top 2023-07-10 23:57 [FFmpeg-devel] [PATCH v5 0/4] JPEG XL Parser Leo Izen 2023-07-10 23:57 ` [FFmpeg-devel] [PATCH v5 1/4] avcodec/libjxldec: use internal AVFrame as buffered space Leo Izen 2023-07-10 23:57 ` [FFmpeg-devel] [PATCH v5 2/4] avcodec/jpegxl_parser: add JPEG XL parser Leo Izen 2023-07-23 10:55 ` Andreas Rheinhardt 2023-07-23 23:53 ` Leo Izen 2023-07-10 23:57 ` [FFmpeg-devel] [PATCH v5 3/4] avformat/jpegxl: remove jpegxl_probe, instead call avcodec/jpegxl_parse Leo Izen 2023-07-23 10:08 ` Andreas Rheinhardt 2023-07-23 23:58 ` Leo Izen [this message] 2023-07-10 23:57 ` [FFmpeg-devel] [PATCH v5 4/4] fate/jpegxl_anim: add demuxer fate test for jpegxl_anim Leo Izen 2023-07-21 13:49 ` [FFmpeg-devel] [PATCH v5 0/4] JPEG XL Parser Leo Izen
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=e7d4bb45-20ce-e54d-bc1e-f8ba09281d02@gmail.com \ --to=leo.izen@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git