| @@ -408,6 +408,73 @@ static int get_siz(Jpeg2000DecoderContext *s) · 407 unmodified lines |
| 408 | s->avctx->bits_per_raw_sample = s->precision; | 408 | s->avctx->bits_per_raw_sample = s->precision; |
| 409 | return 0; | 409 | return 0; |
| 410 | } | 410 | } |
| | 411 | /* get extended capabilities (CAP) marker segment */ |
| | 412 | static int get_cap(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) |
| | 413 | { |
| | 414 | uint32_t Pcap; |
| | 415 | uint16_t Ccap_i[32] = { 0 }; |
| | 416 | uint16_t Ccap_15; |
| | 417 | uint8_t P; |
| | 418 | |
| | 419 | if (bytestream2_get_bytes_left(&s->g) < 6) { |
| | 420 | av_log(s->avctx, AV_LOG_ERROR, "Underflow while parsing the CAP marker\n"); |
| | 421 | return AVERROR_INVALIDDATA; |
| | 422 | } |
| | 423 | |
| | 424 | Pcap = bytestream2_get_be32u(&s->g); |
| | 425 | s->isHT = (Pcap >> (31 - (15 - 1))) & 1; |
| | 426 | for (int i = 0; i < 32; i++) { |
| | 427 | if ((Pcap >> (31 - i)) & 1) |
| | 428 | Ccap_i[i] = bytestream2_get_be16u(&s->g); |
| | 429 | } |
| | 430 | Ccap_15 = Ccap_i[14]; |
| | 431 | if (s->isHT == 1) { |
| | 432 | av_log(s->avctx, AV_LOG_INFO, "This codestream uses the HT block coder.\n"); |
| | 433 | // Bits 14-15 |
| | 434 | switch ((Ccap_15 >> 14) & 0x3) { |
| | 435 | case 0x3: |
| | 436 | s->Ccap15_b14_15 = HTJ2K_MIXED; |
| | 437 | break; |
| | 438 | case 0x1: |
| | 439 | s->Ccap15_b14_15 = HTJ2K_HTDECLARED; |
| | 440 | break; |
| | 441 | case 0x0: |
| | 442 | s->Ccap15_b14_15 = HTJ2K_HTONLY; |
| | 443 | break; |
| | 444 | default: |
| | 445 | av_log(s->avctx, AV_LOG_ERROR, "Unknown CCap value.\n"); |
| | 446 | return AVERROR(EINVAL); |
| | 447 | break; |
| | 448 | } |
| | 449 | // Bit 13 |
| | 450 | if ((Ccap_15 >> 13) & 1) { |
| | 451 | av_log(s->avctx, AV_LOG_ERROR, "MULTIHT set is not supported.\n"); |
| | 452 | return AVERROR_PATCHWELCOME; |
| | 453 | } |
| | 454 | // Bit 12 |
| | 455 | s->Ccap15_b12 = (Ccap_15 >> 12) & 1; |
| | 456 | // Bit 11 |
| | 457 | s->Ccap15_b11 = (Ccap_15 >> 11) & 1; |
| | 458 | // Bit 5 |
| | 459 | s->Ccap15_b05 = (Ccap_15 >> 5) & 1; |
| | 460 | // Bit 0-4 |
| | 461 | P = Ccap_15 & 0x1F; |
| | 462 | if (!P) |
| | 463 | s->HT_B = 8; |
| | 464 | else if (P < 20) |
| | 465 | s->HT_B = P + 8; |
| | 466 | else if (P < 31) |
| | 467 | s->HT_B = 4 * (P - 19) + 27; |
| | 468 | else |
| | 469 | s->HT_B = 74; |
| | 470 | |
| | 471 | if (s->HT_B > 31) { |
| | 472 | av_log(s->avctx, AV_LOG_ERROR, "Codestream exceeds available precision (B > 31).\n"); |
| | 473 | return AVERROR_PATCHWELCOME; |
| | 474 | } |
| | 475 | } |
| | 476 | return 0; |
| | 477 | } |
| 411 | | 478 | |
| 412 | /* get common part for COD and COC segments */ | 479 | /* get common part for COD and COC segments */ |
| 413 | static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) | 480 | static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) |
| @@ -802,6 +869,15 @@ static int read_crg(Jpeg2000DecoderContext *s, int n) · 388 unmodified lines |
| 802 | bytestream2_skip(&s->g, n - 2); | 869 | bytestream2_skip(&s->g, n - 2); |
| 803 | return 0; | 870 | return 0; |
| 804 | } | 871 | } |
| | 872 | |
| | 873 | static int read_cpf(Jpeg2000DecoderContext *s, int n) |
| | 874 | { |
| | 875 | if (bytestream2_get_bytes_left(&s->g) < (n - 2)) |
| | 876 | return AVERROR_INVALIDDATA; |
| | 877 | bytestream2_skip(&s->g, n - 2); |
| | 878 | return 0; |
| | 879 | } |
| | 880 | |
| 805 | /* Tile-part lengths: see ISO 15444-1:2002, section A.7.1 | 881 | /* Tile-part lengths: see ISO 15444-1:2002, section A.7.1 |
| 806 | * Used to know the number of tile parts and lengths. | 882 | * Used to know the number of tile parts and lengths. |
| 807 | * There may be multiple TLMs in the header. | 883 | * There may be multiple TLMs in the header. |
| @@ -965,6 +1041,14 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno) · 157 unmodified lines |
| 965 | comp->roi_shift = s->roi_shift[compno]; | 1041 | comp->roi_shift = s->roi_shift[compno]; |
| 966 | if (!codsty->init) | 1042 | if (!codsty->init) |
| 967 | return AVERROR_INVALIDDATA; | 1043 | return AVERROR_INVALIDDATA; |
| | 1044 | if (s->isHT && (!s->Ccap15_b05) && (!codsty->transform)) { |
| | 1045 | av_log(s->avctx, AV_LOG_ERROR, "Transformation = 0 (lossy DWT) is found in HTREV HT set\n"); |
| | 1046 | return AVERROR_INVALIDDATA; |
| | 1047 | } |
| | 1048 | if (s->isHT && s->Ccap15_b14_15 != (codsty->cblk_style >> 6) && s->Ccap15_b14_15 != HTJ2K_HTONLY) { |
| | 1049 | av_log(s->avctx, AV_LOG_ERROR, "SPcod/SPcoc value does not match bit 14-15 values of Ccap15\n"); |
| | 1050 | return AVERROR_INVALIDDATA; |
| | 1051 | } |
| 968 | if (ret = ff_jpeg2000_init_component(comp, codsty, qntsty, | 1052 | if (ret = ff_jpeg2000_init_component(comp, codsty, qntsty, |
| 969 | s->cbps[compno], s->cdx[compno], | 1053 | s->cbps[compno], s->cdx[compno], |
| 970 | s->cdy[compno], s->avctx)) | 1054 | s->cdy[compno], s->avctx)) |
| @@ -2187,22 +2271,63 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) · 1216 unmodified lines |
| 2187 | if (!s->tile) | 2271 | if (!s->tile) |
| 2188 | s->numXtiles = s->numYtiles = 0; | 2272 | s->numXtiles = s->numYtiles = 0; |
| 2189 | break; | 2273 | break; |
| | 2274 | case JPEG2000_CAP: |
| | 2275 | if (!s->ncomponents) { |
| | 2276 | av_log(s->avctx, AV_LOG_ERROR, "CAP marker segment shall come after SIZ\n"); |
| | 2277 | return AVERROR_INVALIDDATA; |
| | 2278 | } |
| | 2279 | ret = get_cap(s, codsty); |
| | 2280 | break; |
| 2190 | case JPEG2000_COC: | 2281 | case JPEG2000_COC: |
| | 2282 | if (s->in_tile_headers == 1 && s->isHT && (!s->Ccap15_b11)) { |
| | 2283 | av_log(s->avctx, AV_LOG_ERROR, |
| | 2284 | "COC marker found in a tile header but the codestream belongs to the HOMOGENEOUS set\n"); |
| | 2285 | return AVERROR_INVALIDDATA; |
| | 2286 | } |
| 2191 | ret = get_coc(s, codsty, properties); | 2287 | ret = get_coc(s, codsty, properties); |
| 2192 | break; | 2288 | break; |
| 2193 | case JPEG2000_COD: | 2289 | case JPEG2000_COD: |
| | 2290 | if (s->in_tile_headers == 1 && s->isHT && (!s->Ccap15_b11)) { |
| | 2291 | av_log(s->avctx, AV_LOG_ERROR, |
| | 2292 | "COD marker found in a tile header but the codestream belongs to the HOMOGENEOUS set\n"); |
| | 2293 | return AVERROR_INVALIDDATA; |
| | 2294 | } |
| 2194 | ret = get_cod(s, codsty, properties); | 2295 | ret = get_cod(s, codsty, properties); |
| 2195 | break; | 2296 | break; |
| 2196 | case JPEG2000_RGN: | 2297 | case JPEG2000_RGN: |
| | 2298 | if (s->in_tile_headers == 1 && s->isHT && (!s->Ccap15_b11)) { |
| | 2299 | av_log(s->avctx, AV_LOG_ERROR, |
| | 2300 | "RGN marker found in a tile header but the codestream belongs to the HOMOGENEOUS set\n"); |
| | 2301 | return AVERROR_INVALIDDATA; |
| | 2302 | } |
| 2197 | ret = get_rgn(s, len); | 2303 | ret = get_rgn(s, len); |
| | 2304 | if ((!s->Ccap15_b12) && s->isHT) { |
| | 2305 | av_log(s->avctx, AV_LOG_ERROR, "RGN marker found but the codestream belongs to the RGNFREE set\n"); |
| | 2306 | return AVERROR_INVALIDDATA; |
| | 2307 | } |
| 2198 | break; | 2308 | break; |
| 2199 | case JPEG2000_QCC: | 2309 | case JPEG2000_QCC: |
| | 2310 | if (s->in_tile_headers == 1 && s->isHT && (!s->Ccap15_b11)) { |
| | 2311 | av_log(s->avctx, AV_LOG_ERROR, |
| | 2312 | "QCC marker found in a tile header but the codestream belongs to the HOMOGENEOUS set\n"); |
| | 2313 | return AVERROR_INVALIDDATA; |
| | 2314 | } |
| 2200 | ret = get_qcc(s, len, qntsty, properties); | 2315 | ret = get_qcc(s, len, qntsty, properties); |
| 2201 | break; | 2316 | break; |
| 2202 | case JPEG2000_QCD: | 2317 | case JPEG2000_QCD: |
| | 2318 | if (s->in_tile_headers == 1 && s->isHT && (!s->Ccap15_b11)) { |
| | 2319 | av_log(s->avctx, AV_LOG_ERROR, |
| | 2320 | "QCD marker found in a tile header but the codestream belongs to the HOMOGENEOUS set\n"); |
| | 2321 | return AVERROR_INVALIDDATA; |
| | 2322 | } |
| 2203 | ret = get_qcd(s, len, qntsty, properties); | 2323 | ret = get_qcd(s, len, qntsty, properties); |
| 2204 | break; | 2324 | break; |
| 2205 | case JPEG2000_POC: | 2325 | case JPEG2000_POC: |
| | 2326 | if (s->in_tile_headers == 1 && s->isHT && (!s->Ccap15_b11)) { |
| | 2327 | av_log(s->avctx, AV_LOG_ERROR, |
| | 2328 | "POC marker found in a tile header but the codestream belongs to the HOMOGENEOUS set\n"); |
| | 2329 | return AVERROR_INVALIDDATA; |
| | 2330 | } |
| 2206 | ret = get_poc(s, len, poc); | 2331 | ret = get_poc(s, len, poc); |
| 2207 | break; | 2332 | break; |
| 2208 | case JPEG2000_SOT: | 2333 | case JPEG2000_SOT: |
| @@ -2252,9 +2377,16 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) · 43 unmodified lines |
| 2252 | "Cannot have both PPT and PPM marker.\n"); | 2377 | "Cannot have both PPT and PPM marker.\n"); |
| 2253 | return AVERROR_INVALIDDATA; | 2378 | return AVERROR_INVALIDDATA; |
| 2254 | } | 2379 | } |
| 2255 | | 2380 | if ((!s->Ccap15_b11) && s->isHT) { |
| | 2381 | av_log(s->avctx, AV_LOG_ERROR, "PPT marker found but the codestream belongs to the HOMOGENEOUS set\n"); |
| | 2382 | return AVERROR_INVALIDDATA; |
| | 2383 | } |
| 2256 | ret = get_ppt(s, len); | 2384 | ret = get_ppt(s, len); |
| 2257 | break; | 2385 | break; |
| | 2386 | case JPEG2000_CPF: |
| | 2387 | // Corresponding profile marker |
| | 2388 | ret = read_cpf(s, len); |
| | 2389 | break; |
| 2258 | default: | 2390 | default: |
| 2259 | av_log(s->avctx, AV_LOG_ERROR, | 2391 | av_log(s->avctx, AV_LOG_ERROR, |
| 2260 | "unsupported marker 0x%.4"PRIX16" at pos 0x%X\n", | 2392 | "unsupported marker 0x%.4"PRIX16" at pos 0x%X\n", |