jpegxl_probe.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  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. #include "jpegxl_probe.h"
  22. #define BITSTREAM_READER_LE
  23. #include "libavcodec/get_bits.h"
  24. enum JpegXLExtraChannelType {
  25. FF_JPEGXL_CT_ALPHA = 0,
  26. FF_JPEGXL_CT_DEPTH,
  27. FF_JPEGXL_CT_SPOT_COLOR,
  28. FF_JPEGXL_CT_SELECTION_MASK,
  29. FF_JPEGXL_CT_BLACK,
  30. FF_JPEGXL_CT_CFA,
  31. FF_JPEGXL_CT_THERMAL,
  32. FF_JPEGXL_CT_NON_OPTIONAL = 15,
  33. FF_JPEGXL_CT_OPTIONAL
  34. };
  35. enum JpegXLColorSpace {
  36. FF_JPEGXL_CS_RGB = 0,
  37. FF_JPEGXL_CS_GRAY,
  38. FF_JPEGXL_CS_XYB,
  39. FF_JPEGXL_CS_UNKNOWN
  40. };
  41. enum JpegXLWhitePoint {
  42. FF_JPEGXL_WP_D65 = 1,
  43. FF_JPEGXL_WP_CUSTOM,
  44. FF_JPEGXL_WP_E = 10,
  45. FF_JPEGXL_WP_DCI = 11
  46. };
  47. enum JpegXLPrimaries {
  48. FF_JPEGXL_PR_SRGB = 1,
  49. FF_JPEGXL_PR_CUSTOM,
  50. FF_JPEGXL_PR_2100 = 9,
  51. FF_JPEGXL_PR_P3 = 11,
  52. };
  53. #define jxl_bits(n) get_bits_long(gb, (n))
  54. #define jxl_bits_skip(n) skip_bits_long(gb, (n))
  55. #define jxl_u32(c0, c1, c2, c3, u0, u1, u2, u3) jpegxl_u32(gb, \
  56. (const uint32_t[]){c0, c1, c2, c3}, (const uint32_t[]){u0, u1, u2, u3})
  57. #define jxl_u64() jpegxl_u64(gb)
  58. #define jxl_enum() jxl_u32(0, 1, 2, 18, 0, 0, 4, 6)
  59. /* read a U32(c_i + u(u_i)) */
  60. static uint32_t jpegxl_u32(GetBitContext *gb,
  61. const uint32_t constants[4], const uint32_t ubits[4])
  62. {
  63. uint32_t ret, choice = jxl_bits(2);
  64. ret = constants[choice];
  65. if (ubits[choice])
  66. ret += jxl_bits(ubits[choice]);
  67. return ret;
  68. }
  69. /* read a U64() */
  70. static uint64_t jpegxl_u64(GetBitContext *gb)
  71. {
  72. uint64_t shift = 12, ret;
  73. switch (jxl_bits(2)) {
  74. case 0:
  75. ret = 0;
  76. break;
  77. case 1:
  78. ret = 1 + jxl_bits(4);
  79. break;
  80. case 2:
  81. ret = 17 + jxl_bits(8);
  82. break;
  83. case 3:
  84. ret = jxl_bits(12);
  85. while (jxl_bits(1)) {
  86. if (shift < 60) {
  87. ret |= jxl_bits(8) << shift;
  88. shift += 8;
  89. } else {
  90. ret |= jxl_bits(4) << shift;
  91. break;
  92. }
  93. }
  94. break;
  95. }
  96. return ret;
  97. }
  98. static uint32_t jpegxl_width_from_ratio(uint32_t height, int ratio)
  99. {
  100. uint64_t height64 = height; /* avoid integer overflow */
  101. switch (ratio) {
  102. case 1:
  103. return height;
  104. case 2:
  105. return (uint32_t)((height64 * 12) / 10);
  106. case 3:
  107. return (uint32_t)((height64 * 4) / 3);
  108. case 4:
  109. return (uint32_t)((height64 * 3) / 2);
  110. case 5:
  111. return (uint32_t)((height64 * 16) / 9);
  112. case 6:
  113. return (uint32_t)((height64 * 5) / 4);
  114. case 7:
  115. return (uint32_t)(height64 * 2);
  116. default:
  117. break;
  118. }
  119. return 0; /* manual width */
  120. }
  121. /**
  122. * validate a Jpeg XL Size Header
  123. * @return >= 0 upon valid size, < 0 upon invalid size found
  124. */
  125. static int jpegxl_read_size_header(GetBitContext *gb)
  126. {
  127. uint32_t width, height;
  128. if (jxl_bits(1)) {
  129. /* small size header */
  130. height = (jxl_bits(5) + 1) << 3;
  131. width = jpegxl_width_from_ratio(height, jxl_bits(3));
  132. if (!width)
  133. width = (jxl_bits(5) + 1) << 3;
  134. } else {
  135. /* large size header */
  136. height = 1 + jxl_u32(0, 0, 0, 0, 9, 13, 18, 30);
  137. width = jpegxl_width_from_ratio(height, jxl_bits(3));
  138. if (!width)
  139. width = 1 + jxl_u32(0, 0, 0, 0, 9, 13, 18, 30);
  140. }
  141. if (width > (1 << 18) || height > (1 << 18)
  142. || (width >> 4) * (height >> 4) > (1 << 20))
  143. return -1;
  144. return 0;
  145. }
  146. /**
  147. * validate a Jpeg XL Preview Header
  148. * @return >= 0 upon valid size, < 0 upon invalid size found
  149. */
  150. static int jpegxl_read_preview_header(GetBitContext *gb)
  151. {
  152. uint32_t width, height;
  153. if (jxl_bits(1)) {
  154. /* coded height and width divided by eight */
  155. height = jxl_u32(16, 32, 1, 33, 0, 0, 5, 9) << 3;
  156. width = jpegxl_width_from_ratio(height, jxl_bits(3));
  157. if (!width)
  158. width = jxl_u32(16, 32, 1, 33, 0, 0, 5, 9) << 3;
  159. } else {
  160. /* full height and width coded */
  161. height = jxl_u32(1, 65, 321, 1345, 6, 8, 10, 12);
  162. width = jpegxl_width_from_ratio(height, jxl_bits(3));
  163. if (!width)
  164. width = jxl_u32(1, 65, 321, 1345, 6, 8, 10, 12);
  165. }
  166. if (width > 4096 || height > 4096)
  167. return -1;
  168. return 0;
  169. }
  170. /**
  171. * skip a Jpeg XL BitDepth Header. These cannot be invalid.
  172. */
  173. static void jpegxl_skip_bit_depth(GetBitContext *gb)
  174. {
  175. if (jxl_bits(1)) {
  176. /* float samples */
  177. jxl_u32(32, 16, 24, 1, 0, 0, 0, 6); /* mantissa */
  178. jxl_bits_skip(4); /* exponent */
  179. } else {
  180. /* integer samples */
  181. jxl_u32(8, 10, 12, 1, 0, 0, 0, 6);
  182. }
  183. }
  184. /**
  185. * validate a Jpeg XL Extra Channel Info bundle
  186. * @return >= 0 upon valid, < 0 upon invalid
  187. */
  188. static int jpegxl_read_extra_channel_info(GetBitContext *gb)
  189. {
  190. int all_default = jxl_bits(1);
  191. uint32_t type, name_len = 0;
  192. if (!all_default) {
  193. type = jxl_enum();
  194. if (type > 63)
  195. return -1; /* enum types cannot be 64+ */
  196. if (type == FF_JPEGXL_CT_BLACK)
  197. return -1;
  198. jpegxl_skip_bit_depth(gb);
  199. jxl_u32(0, 3, 4, 1, 0, 0, 0, 3); /* dim-shift */
  200. /* max of name_len is 1071 = 48 + 2^10 - 1 */
  201. name_len = jxl_u32(0, 0, 16, 48, 0, 4, 5, 10);
  202. } else {
  203. type = FF_JPEGXL_CT_ALPHA;
  204. }
  205. /* skip over the name */
  206. jxl_bits_skip(8 * name_len);
  207. if (!all_default && type == FF_JPEGXL_CT_ALPHA)
  208. jxl_bits_skip(1);
  209. if (type == FF_JPEGXL_CT_SPOT_COLOR)
  210. jxl_bits_skip(16 * 4);
  211. if (type == FF_JPEGXL_CT_CFA)
  212. jxl_u32(1, 0, 3, 19, 0, 2, 4, 8);
  213. return 0;
  214. }
  215. /* verify that a codestream header is valid */
  216. int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen)
  217. {
  218. GetBitContext gbi, *gb = &gbi;
  219. int all_default, extra_fields = 0;
  220. int xyb_encoded = 1, have_icc_profile = 0;
  221. uint32_t num_extra_channels;
  222. uint64_t extensions;
  223. init_get_bits8(gb, buf, buflen);
  224. if (jxl_bits(16) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE)
  225. return -1;
  226. if (jpegxl_read_size_header(gb) < 0)
  227. return -1;
  228. all_default = jxl_bits(1);
  229. if (!all_default)
  230. extra_fields = jxl_bits(1);
  231. if (extra_fields) {
  232. jxl_bits_skip(3); /* orientation */
  233. /*
  234. * intrinstic size
  235. * any size header here is valid, but as it
  236. * is variable length we have to read it
  237. */
  238. if (jxl_bits(1))
  239. jpegxl_read_size_header(gb);
  240. /* preview header */
  241. if (jxl_bits(1)) {
  242. if (jpegxl_read_preview_header(gb) < 0)
  243. return -1;
  244. }
  245. /* animation header */
  246. if (jxl_bits(1)) {
  247. jxl_u32(100, 1000, 1, 1, 0, 0, 10, 30);
  248. jxl_u32(1, 1001, 1, 1, 0, 0, 8, 10);
  249. jxl_u32(0, 0, 0, 0, 0, 3, 16, 32);
  250. jxl_bits_skip(1);
  251. }
  252. }
  253. if (!all_default) {
  254. jpegxl_skip_bit_depth(gb);
  255. /* modular_16bit_buffers must equal 1 */
  256. if (!jxl_bits(1))
  257. return -1;
  258. num_extra_channels = jxl_u32(0, 1, 2, 1, 0, 0, 4, 12);
  259. if (num_extra_channels > 4)
  260. return -1;
  261. for (uint32_t i = 0; i < num_extra_channels; i++) {
  262. if (jpegxl_read_extra_channel_info(gb) < 0)
  263. return -1;
  264. }
  265. xyb_encoded = jxl_bits(1);
  266. /* color encoding bundle */
  267. if (!jxl_bits(1)) {
  268. uint32_t color_space;
  269. have_icc_profile = jxl_bits(1);
  270. color_space = jxl_enum();
  271. if (color_space > 63)
  272. return -1;
  273. if (!have_icc_profile) {
  274. if (color_space != FF_JPEGXL_CS_XYB) {
  275. uint32_t white_point = jxl_enum();
  276. if (white_point > 63)
  277. return -1;
  278. if (white_point == FF_JPEGXL_WP_CUSTOM) {
  279. /* ux and uy values */
  280. jxl_u32(0, 524288, 1048576, 2097152, 19, 19, 20, 21);
  281. jxl_u32(0, 524288, 1048576, 2097152, 19, 19, 20, 21);
  282. }
  283. if (color_space != FF_JPEGXL_CS_GRAY) {
  284. /* primaries */
  285. uint32_t primaries = jxl_enum();
  286. if (primaries > 63)
  287. return -1;
  288. if (primaries == FF_JPEGXL_PR_CUSTOM) {
  289. /* ux/uy values for r,g,b */
  290. for (int i = 0; i < 6; i++)
  291. jxl_u32(0, 524288, 1048576, 2097152, 19, 19, 20, 21);
  292. }
  293. }
  294. }
  295. /* transfer characteristics */
  296. if (jxl_bits(1)) {
  297. /* gamma */
  298. jxl_bits_skip(24);
  299. } else {
  300. /* transfer function */
  301. if (jxl_enum() > 63)
  302. return -1;
  303. }
  304. /* rendering intent */
  305. if (jxl_enum() > 63)
  306. return -1;
  307. }
  308. }
  309. /* tone mapping bundle */
  310. if (extra_fields && !jxl_bits(1))
  311. jxl_bits_skip(16 + 16 + 1 + 16);
  312. extensions = jxl_u64();
  313. if (extensions) {
  314. for (int i = 0; i < 64; i++) {
  315. if (extensions & (UINT64_C(1) << i))
  316. jxl_u64();
  317. }
  318. }
  319. }
  320. /* default transform */
  321. if (!jxl_bits(1)) {
  322. /* opsin inverse matrix */
  323. if (xyb_encoded && !jxl_bits(1))
  324. jxl_bits_skip(16 * 16);
  325. /* cw_mask and default weights */
  326. if (jxl_bits(1))
  327. jxl_bits_skip(16 * 15);
  328. if (jxl_bits(1))
  329. jxl_bits_skip(16 * 55);
  330. if (jxl_bits(1))
  331. jxl_bits_skip(16 * 210);
  332. }
  333. if (!have_icc_profile) {
  334. int bits_remaining = 7 - (get_bits_count(gb) - 1) % 8;
  335. if (bits_remaining && jxl_bits(bits_remaining))
  336. return -1;
  337. }
  338. if (get_bits_left(gb) < 0)
  339. return -1;
  340. return 0;
  341. }