1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Jpeg XL header verification 3cabdff1aSopenharmony_ci * Copyright (c) 2022 Leo Izen <leo.izen@gmail.com> 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "jpegxl_probe.h" 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#define UNCHECKED_BITSTREAM_READER 0 25cabdff1aSopenharmony_ci#define BITSTREAM_READER_LE 26cabdff1aSopenharmony_ci#include "libavcodec/get_bits.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_cienum JpegXLExtraChannelType { 29cabdff1aSopenharmony_ci FF_JPEGXL_CT_ALPHA = 0, 30cabdff1aSopenharmony_ci FF_JPEGXL_CT_DEPTH, 31cabdff1aSopenharmony_ci FF_JPEGXL_CT_SPOT_COLOR, 32cabdff1aSopenharmony_ci FF_JPEGXL_CT_SELECTION_MASK, 33cabdff1aSopenharmony_ci FF_JPEGXL_CT_BLACK, 34cabdff1aSopenharmony_ci FF_JPEGXL_CT_CFA, 35cabdff1aSopenharmony_ci FF_JPEGXL_CT_THERMAL, 36cabdff1aSopenharmony_ci FF_JPEGXL_CT_NON_OPTIONAL = 15, 37cabdff1aSopenharmony_ci FF_JPEGXL_CT_OPTIONAL 38cabdff1aSopenharmony_ci}; 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_cienum JpegXLColorSpace { 41cabdff1aSopenharmony_ci FF_JPEGXL_CS_RGB = 0, 42cabdff1aSopenharmony_ci FF_JPEGXL_CS_GRAY, 43cabdff1aSopenharmony_ci FF_JPEGXL_CS_XYB, 44cabdff1aSopenharmony_ci FF_JPEGXL_CS_UNKNOWN 45cabdff1aSopenharmony_ci}; 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_cienum JpegXLWhitePoint { 48cabdff1aSopenharmony_ci FF_JPEGXL_WP_D65 = 1, 49cabdff1aSopenharmony_ci FF_JPEGXL_WP_CUSTOM, 50cabdff1aSopenharmony_ci FF_JPEGXL_WP_E = 10, 51cabdff1aSopenharmony_ci FF_JPEGXL_WP_DCI = 11 52cabdff1aSopenharmony_ci}; 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_cienum JpegXLPrimaries { 55cabdff1aSopenharmony_ci FF_JPEGXL_PR_SRGB = 1, 56cabdff1aSopenharmony_ci FF_JPEGXL_PR_CUSTOM, 57cabdff1aSopenharmony_ci FF_JPEGXL_PR_2100 = 9, 58cabdff1aSopenharmony_ci FF_JPEGXL_PR_P3 = 11, 59cabdff1aSopenharmony_ci}; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci/* read a U32(c_i + u(u_i)) */ 62cabdff1aSopenharmony_cistatic av_always_inline uint32_t jxl_u32(GetBitContext *gb, 63cabdff1aSopenharmony_ci uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, 64cabdff1aSopenharmony_ci uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) 65cabdff1aSopenharmony_ci{ 66cabdff1aSopenharmony_ci const uint32_t constants[4] = {c0, c1, c2, c3}; 67cabdff1aSopenharmony_ci const uint32_t ubits [4] = {u0, u1, u2, u3}; 68cabdff1aSopenharmony_ci uint32_t ret, choice = get_bits(gb, 2); 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci ret = constants[choice]; 71cabdff1aSopenharmony_ci if (ubits[choice]) 72cabdff1aSopenharmony_ci ret += get_bits_long(gb, ubits[choice]); 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci return ret; 75cabdff1aSopenharmony_ci} 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_cistatic av_always_inline uint32_t jxl_enum(GetBitContext *gb) 78cabdff1aSopenharmony_ci{ 79cabdff1aSopenharmony_ci return jxl_u32(gb, 0, 1, 2, 18, 0, 0, 4, 6); 80cabdff1aSopenharmony_ci} 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci/* read a U64() */ 83cabdff1aSopenharmony_cistatic uint64_t jpegxl_u64(GetBitContext *gb) 84cabdff1aSopenharmony_ci{ 85cabdff1aSopenharmony_ci uint64_t shift = 12, ret; 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci switch (get_bits(gb, 2)) { 88cabdff1aSopenharmony_ci case 0: 89cabdff1aSopenharmony_ci ret = 0; 90cabdff1aSopenharmony_ci break; 91cabdff1aSopenharmony_ci case 1: 92cabdff1aSopenharmony_ci ret = 1 + get_bits(gb, 4); 93cabdff1aSopenharmony_ci break; 94cabdff1aSopenharmony_ci case 2: 95cabdff1aSopenharmony_ci ret = 17 + get_bits(gb, 8); 96cabdff1aSopenharmony_ci break; 97cabdff1aSopenharmony_ci case 3: 98cabdff1aSopenharmony_ci ret = get_bits(gb, 12); 99cabdff1aSopenharmony_ci while (get_bits1(gb)) { 100cabdff1aSopenharmony_ci if (shift < 60) { 101cabdff1aSopenharmony_ci ret |= (uint64_t)get_bits(gb, 8) << shift; 102cabdff1aSopenharmony_ci shift += 8; 103cabdff1aSopenharmony_ci } else { 104cabdff1aSopenharmony_ci ret |= (uint64_t)get_bits(gb, 4) << shift; 105cabdff1aSopenharmony_ci break; 106cabdff1aSopenharmony_ci } 107cabdff1aSopenharmony_ci } 108cabdff1aSopenharmony_ci break; 109cabdff1aSopenharmony_ci } 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci return ret; 112cabdff1aSopenharmony_ci} 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_cistatic uint32_t jpegxl_width_from_ratio(uint32_t height, int ratio) 115cabdff1aSopenharmony_ci{ 116cabdff1aSopenharmony_ci uint64_t height64 = height; /* avoid integer overflow */ 117cabdff1aSopenharmony_ci switch (ratio) { 118cabdff1aSopenharmony_ci case 1: 119cabdff1aSopenharmony_ci return height; 120cabdff1aSopenharmony_ci case 2: 121cabdff1aSopenharmony_ci return (uint32_t)((height64 * 12) / 10); 122cabdff1aSopenharmony_ci case 3: 123cabdff1aSopenharmony_ci return (uint32_t)((height64 * 4) / 3); 124cabdff1aSopenharmony_ci case 4: 125cabdff1aSopenharmony_ci return (uint32_t)((height64 * 3) / 2); 126cabdff1aSopenharmony_ci case 5: 127cabdff1aSopenharmony_ci return (uint32_t)((height64 * 16) / 9); 128cabdff1aSopenharmony_ci case 6: 129cabdff1aSopenharmony_ci return (uint32_t)((height64 * 5) / 4); 130cabdff1aSopenharmony_ci case 7: 131cabdff1aSopenharmony_ci return (uint32_t)(height64 * 2); 132cabdff1aSopenharmony_ci default: 133cabdff1aSopenharmony_ci break; 134cabdff1aSopenharmony_ci } 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci return 0; /* manual width */ 137cabdff1aSopenharmony_ci} 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_ci/** 140cabdff1aSopenharmony_ci * validate a Jpeg XL Size Header 141cabdff1aSopenharmony_ci * @return >= 0 upon valid size, < 0 upon invalid size found 142cabdff1aSopenharmony_ci */ 143cabdff1aSopenharmony_cistatic int jpegxl_read_size_header(GetBitContext *gb) 144cabdff1aSopenharmony_ci{ 145cabdff1aSopenharmony_ci uint32_t width, height; 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ci if (get_bits1(gb)) { 148cabdff1aSopenharmony_ci /* small size header */ 149cabdff1aSopenharmony_ci height = (get_bits(gb, 5) + 1) << 3; 150cabdff1aSopenharmony_ci width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); 151cabdff1aSopenharmony_ci if (!width) 152cabdff1aSopenharmony_ci width = (get_bits(gb, 5) + 1) << 3; 153cabdff1aSopenharmony_ci } else { 154cabdff1aSopenharmony_ci /* large size header */ 155cabdff1aSopenharmony_ci height = 1 + jxl_u32(gb, 0, 0, 0, 0, 9, 13, 18, 30); 156cabdff1aSopenharmony_ci width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); 157cabdff1aSopenharmony_ci if (!width) 158cabdff1aSopenharmony_ci width = 1 + jxl_u32(gb, 0, 0, 0, 0, 9, 13, 18, 30); 159cabdff1aSopenharmony_ci } 160cabdff1aSopenharmony_ci if (width > (1 << 18) || height > (1 << 18) 161cabdff1aSopenharmony_ci || (width >> 4) * (height >> 4) > (1 << 20)) 162cabdff1aSopenharmony_ci return -1; 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_ci return 0; 165cabdff1aSopenharmony_ci} 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_ci/** 168cabdff1aSopenharmony_ci * validate a Jpeg XL Preview Header 169cabdff1aSopenharmony_ci * @return >= 0 upon valid size, < 0 upon invalid size found 170cabdff1aSopenharmony_ci */ 171cabdff1aSopenharmony_cistatic int jpegxl_read_preview_header(GetBitContext *gb) 172cabdff1aSopenharmony_ci{ 173cabdff1aSopenharmony_ci uint32_t width, height; 174cabdff1aSopenharmony_ci 175cabdff1aSopenharmony_ci if (get_bits1(gb)) { 176cabdff1aSopenharmony_ci /* coded height and width divided by eight */ 177cabdff1aSopenharmony_ci height = jxl_u32(gb, 16, 32, 1, 33, 0, 0, 5, 9) << 3; 178cabdff1aSopenharmony_ci width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); 179cabdff1aSopenharmony_ci if (!width) 180cabdff1aSopenharmony_ci width = jxl_u32(gb, 16, 32, 1, 33, 0, 0, 5, 9) << 3; 181cabdff1aSopenharmony_ci } else { 182cabdff1aSopenharmony_ci /* full height and width coded */ 183cabdff1aSopenharmony_ci height = jxl_u32(gb, 1, 65, 321, 1345, 6, 8, 10, 12); 184cabdff1aSopenharmony_ci width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); 185cabdff1aSopenharmony_ci if (!width) 186cabdff1aSopenharmony_ci width = jxl_u32(gb, 1, 65, 321, 1345, 6, 8, 10, 12); 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci if (width > 4096 || height > 4096) 189cabdff1aSopenharmony_ci return -1; 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci return 0; 192cabdff1aSopenharmony_ci} 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci/** 195cabdff1aSopenharmony_ci * skip a Jpeg XL BitDepth Header. These cannot be invalid. 196cabdff1aSopenharmony_ci */ 197cabdff1aSopenharmony_cistatic void jpegxl_skip_bit_depth(GetBitContext *gb) 198cabdff1aSopenharmony_ci{ 199cabdff1aSopenharmony_ci if (get_bits1(gb)) { 200cabdff1aSopenharmony_ci /* float samples */ 201cabdff1aSopenharmony_ci jxl_u32(gb, 32, 16, 24, 1, 0, 0, 0, 6); /* mantissa */ 202cabdff1aSopenharmony_ci skip_bits_long(gb, 4); /* exponent */ 203cabdff1aSopenharmony_ci } else { 204cabdff1aSopenharmony_ci /* integer samples */ 205cabdff1aSopenharmony_ci jxl_u32(gb, 8, 10, 12, 1, 0, 0, 0, 6); 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci} 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci/** 210cabdff1aSopenharmony_ci * validate a Jpeg XL Extra Channel Info bundle 211cabdff1aSopenharmony_ci * @return >= 0 upon valid, < 0 upon invalid 212cabdff1aSopenharmony_ci */ 213cabdff1aSopenharmony_cistatic int jpegxl_read_extra_channel_info(GetBitContext *gb) 214cabdff1aSopenharmony_ci{ 215cabdff1aSopenharmony_ci int all_default = get_bits1(gb); 216cabdff1aSopenharmony_ci uint32_t type, name_len = 0; 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_ci if (!all_default) { 219cabdff1aSopenharmony_ci type = jxl_enum(gb); 220cabdff1aSopenharmony_ci if (type > 63) 221cabdff1aSopenharmony_ci return -1; /* enum types cannot be 64+ */ 222cabdff1aSopenharmony_ci if (type == FF_JPEGXL_CT_BLACK) 223cabdff1aSopenharmony_ci return -1; 224cabdff1aSopenharmony_ci jpegxl_skip_bit_depth(gb); 225cabdff1aSopenharmony_ci jxl_u32(gb, 0, 3, 4, 1, 0, 0, 0, 3); /* dim-shift */ 226cabdff1aSopenharmony_ci /* max of name_len is 1071 = 48 + 2^10 - 1 */ 227cabdff1aSopenharmony_ci name_len = jxl_u32(gb, 0, 0, 16, 48, 0, 4, 5, 10); 228cabdff1aSopenharmony_ci } else { 229cabdff1aSopenharmony_ci type = FF_JPEGXL_CT_ALPHA; 230cabdff1aSopenharmony_ci } 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci /* skip over the name */ 233cabdff1aSopenharmony_ci skip_bits_long(gb, 8 * name_len); 234cabdff1aSopenharmony_ci 235cabdff1aSopenharmony_ci if (!all_default && type == FF_JPEGXL_CT_ALPHA) 236cabdff1aSopenharmony_ci skip_bits1(gb); 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci if (type == FF_JPEGXL_CT_SPOT_COLOR) 239cabdff1aSopenharmony_ci skip_bits_long(gb, 16 * 4); 240cabdff1aSopenharmony_ci 241cabdff1aSopenharmony_ci if (type == FF_JPEGXL_CT_CFA) 242cabdff1aSopenharmony_ci jxl_u32(gb, 1, 0, 3, 19, 0, 2, 4, 8); 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_ci return 0; 245cabdff1aSopenharmony_ci} 246cabdff1aSopenharmony_ci 247cabdff1aSopenharmony_ci/* verify that a codestream header is valid */ 248cabdff1aSopenharmony_ciint ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen) 249cabdff1aSopenharmony_ci{ 250cabdff1aSopenharmony_ci GetBitContext gbi, *gb = &gbi; 251cabdff1aSopenharmony_ci int all_default, extra_fields = 0; 252cabdff1aSopenharmony_ci int xyb_encoded = 1, have_icc_profile = 0; 253cabdff1aSopenharmony_ci uint32_t num_extra_channels; 254cabdff1aSopenharmony_ci uint64_t extensions; 255cabdff1aSopenharmony_ci int ret; 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci ret = init_get_bits8(gb, buf, buflen); 258cabdff1aSopenharmony_ci if (ret < 0) 259cabdff1aSopenharmony_ci return ret; 260cabdff1aSopenharmony_ci 261cabdff1aSopenharmony_ci if (get_bits_long(gb, 16) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE) 262cabdff1aSopenharmony_ci return -1; 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci if ((ret = jpegxl_read_size_header(gb)) < 0) 265cabdff1aSopenharmony_ci return ret; 266cabdff1aSopenharmony_ci 267cabdff1aSopenharmony_ci all_default = get_bits1(gb); 268cabdff1aSopenharmony_ci if (!all_default) 269cabdff1aSopenharmony_ci extra_fields = get_bits1(gb); 270cabdff1aSopenharmony_ci 271cabdff1aSopenharmony_ci if (extra_fields) { 272cabdff1aSopenharmony_ci skip_bits_long(gb, 3); /* orientation */ 273cabdff1aSopenharmony_ci 274cabdff1aSopenharmony_ci /* 275cabdff1aSopenharmony_ci * intrinstic size 276cabdff1aSopenharmony_ci * any size header here is valid, but as it 277cabdff1aSopenharmony_ci * is variable length we have to read it 278cabdff1aSopenharmony_ci */ 279cabdff1aSopenharmony_ci if (get_bits1(gb)) 280cabdff1aSopenharmony_ci jpegxl_read_size_header(gb); 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci /* preview header */ 283cabdff1aSopenharmony_ci if (get_bits1(gb)) { 284cabdff1aSopenharmony_ci ret = jpegxl_read_preview_header(gb); 285cabdff1aSopenharmony_ci if (ret < 0) 286cabdff1aSopenharmony_ci return ret; 287cabdff1aSopenharmony_ci } 288cabdff1aSopenharmony_ci 289cabdff1aSopenharmony_ci /* animation header */ 290cabdff1aSopenharmony_ci if (get_bits1(gb)) { 291cabdff1aSopenharmony_ci jxl_u32(gb, 100, 1000, 1, 1, 0, 0, 10, 30); 292cabdff1aSopenharmony_ci jxl_u32(gb, 1, 1001, 1, 1, 0, 0, 8, 10); 293cabdff1aSopenharmony_ci jxl_u32(gb, 0, 0, 0, 0, 0, 3, 16, 32); 294cabdff1aSopenharmony_ci skip_bits_long(gb, 1); 295cabdff1aSopenharmony_ci } 296cabdff1aSopenharmony_ci } 297cabdff1aSopenharmony_ci if (get_bits_left(gb) < 1) 298cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci if (!all_default) { 301cabdff1aSopenharmony_ci jpegxl_skip_bit_depth(gb); 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_ci /* modular_16bit_buffers must equal 1 */ 304cabdff1aSopenharmony_ci if (!get_bits1(gb)) 305cabdff1aSopenharmony_ci return -1; 306cabdff1aSopenharmony_ci 307cabdff1aSopenharmony_ci num_extra_channels = jxl_u32(gb, 0, 1, 2, 1, 0, 0, 4, 12); 308cabdff1aSopenharmony_ci if (num_extra_channels > 4) 309cabdff1aSopenharmony_ci return -1; 310cabdff1aSopenharmony_ci for (uint32_t i = 0; i < num_extra_channels; i++) { 311cabdff1aSopenharmony_ci ret = jpegxl_read_extra_channel_info(gb); 312cabdff1aSopenharmony_ci if (ret < 0) 313cabdff1aSopenharmony_ci return ret; 314cabdff1aSopenharmony_ci if (get_bits_left(gb) < 1) 315cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 316cabdff1aSopenharmony_ci } 317cabdff1aSopenharmony_ci 318cabdff1aSopenharmony_ci xyb_encoded = get_bits1(gb); 319cabdff1aSopenharmony_ci 320cabdff1aSopenharmony_ci /* color encoding bundle */ 321cabdff1aSopenharmony_ci if (!get_bits1(gb)) { 322cabdff1aSopenharmony_ci uint32_t color_space; 323cabdff1aSopenharmony_ci have_icc_profile = get_bits1(gb); 324cabdff1aSopenharmony_ci color_space = jxl_enum(gb); 325cabdff1aSopenharmony_ci if (color_space > 63) 326cabdff1aSopenharmony_ci return -1; 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci if (!have_icc_profile) { 329cabdff1aSopenharmony_ci if (color_space != FF_JPEGXL_CS_XYB) { 330cabdff1aSopenharmony_ci uint32_t white_point = jxl_enum(gb); 331cabdff1aSopenharmony_ci if (white_point > 63) 332cabdff1aSopenharmony_ci return -1; 333cabdff1aSopenharmony_ci if (white_point == FF_JPEGXL_WP_CUSTOM) { 334cabdff1aSopenharmony_ci /* ux and uy values */ 335cabdff1aSopenharmony_ci jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21); 336cabdff1aSopenharmony_ci jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21); 337cabdff1aSopenharmony_ci } 338cabdff1aSopenharmony_ci if (color_space != FF_JPEGXL_CS_GRAY) { 339cabdff1aSopenharmony_ci /* primaries */ 340cabdff1aSopenharmony_ci uint32_t primaries = jxl_enum(gb); 341cabdff1aSopenharmony_ci if (primaries > 63) 342cabdff1aSopenharmony_ci return -1; 343cabdff1aSopenharmony_ci if (primaries == FF_JPEGXL_PR_CUSTOM) { 344cabdff1aSopenharmony_ci /* ux/uy values for r,g,b */ 345cabdff1aSopenharmony_ci for (int i = 0; i < 6; i++) { 346cabdff1aSopenharmony_ci jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21); 347cabdff1aSopenharmony_ci if (get_bits_left(gb) < 1) 348cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 349cabdff1aSopenharmony_ci } 350cabdff1aSopenharmony_ci } 351cabdff1aSopenharmony_ci } 352cabdff1aSopenharmony_ci } 353cabdff1aSopenharmony_ci 354cabdff1aSopenharmony_ci /* transfer characteristics */ 355cabdff1aSopenharmony_ci if (get_bits1(gb)) { 356cabdff1aSopenharmony_ci /* gamma */ 357cabdff1aSopenharmony_ci skip_bits_long(gb, 24); 358cabdff1aSopenharmony_ci } else { 359cabdff1aSopenharmony_ci /* transfer function */ 360cabdff1aSopenharmony_ci if (jxl_enum(gb) > 63) 361cabdff1aSopenharmony_ci return -1; 362cabdff1aSopenharmony_ci } 363cabdff1aSopenharmony_ci 364cabdff1aSopenharmony_ci /* rendering intent */ 365cabdff1aSopenharmony_ci if (jxl_enum(gb) > 63) 366cabdff1aSopenharmony_ci return -1; 367cabdff1aSopenharmony_ci } 368cabdff1aSopenharmony_ci } 369cabdff1aSopenharmony_ci 370cabdff1aSopenharmony_ci /* tone mapping bundle */ 371cabdff1aSopenharmony_ci if (extra_fields && !get_bits1(gb)) 372cabdff1aSopenharmony_ci skip_bits_long(gb, 16 + 16 + 1 + 16); 373cabdff1aSopenharmony_ci 374cabdff1aSopenharmony_ci extensions = jpegxl_u64(gb); 375cabdff1aSopenharmony_ci if (get_bits_left(gb) < 1) 376cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 377cabdff1aSopenharmony_ci if (extensions) { 378cabdff1aSopenharmony_ci for (int i = 0; i < 64; i++) { 379cabdff1aSopenharmony_ci if (extensions & (UINT64_C(1) << i)) 380cabdff1aSopenharmony_ci jpegxl_u64(gb); 381cabdff1aSopenharmony_ci if (get_bits_left(gb) < 1) 382cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 383cabdff1aSopenharmony_ci } 384cabdff1aSopenharmony_ci } 385cabdff1aSopenharmony_ci } 386cabdff1aSopenharmony_ci 387cabdff1aSopenharmony_ci /* default transform */ 388cabdff1aSopenharmony_ci if (!get_bits1(gb)) { 389cabdff1aSopenharmony_ci /* opsin inverse matrix */ 390cabdff1aSopenharmony_ci if (xyb_encoded && !get_bits1(gb)) 391cabdff1aSopenharmony_ci skip_bits_long(gb, 16 * 16); 392cabdff1aSopenharmony_ci /* cw_mask and default weights */ 393cabdff1aSopenharmony_ci if (get_bits1(gb)) 394cabdff1aSopenharmony_ci skip_bits_long(gb, 16 * 15); 395cabdff1aSopenharmony_ci if (get_bits1(gb)) 396cabdff1aSopenharmony_ci skip_bits_long(gb, 16 * 55); 397cabdff1aSopenharmony_ci if (get_bits1(gb)) 398cabdff1aSopenharmony_ci skip_bits_long(gb, 16 * 210); 399cabdff1aSopenharmony_ci } 400cabdff1aSopenharmony_ci 401cabdff1aSopenharmony_ci if (!have_icc_profile) { 402cabdff1aSopenharmony_ci int bits_remaining = 7 - (get_bits_count(gb) - 1) % 8; 403cabdff1aSopenharmony_ci if (bits_remaining && get_bits(gb, bits_remaining)) 404cabdff1aSopenharmony_ci return -1; 405cabdff1aSopenharmony_ci } 406cabdff1aSopenharmony_ci 407cabdff1aSopenharmony_ci if (get_bits_left(gb) < 0) 408cabdff1aSopenharmony_ci return -1; 409cabdff1aSopenharmony_ci 410cabdff1aSopenharmony_ci return 0; 411cabdff1aSopenharmony_ci} 412