Update OpenJPEG to 2.5.3 Change-Id: Ib25f76a918592adc76cce1ac2ee4290c0bb3c7d5 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/127130 Commit-Queue: Lei Zhang <thestig@chromium.org> Reviewed-by: Tom Sepez <tsepez@chromium.org> Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/third_party/libopenjpeg/0003-dwt-decode.patch b/third_party/libopenjpeg/0003-dwt-decode.patch index 3d43a89..5c76809 100644 --- a/third_party/libopenjpeg/0003-dwt-decode.patch +++ b/third_party/libopenjpeg/0003-dwt-decode.patch
@@ -1,5 +1,5 @@ diff --git a/third_party/libopenjpeg/dwt.c b/third_party/libopenjpeg/dwt.c -index 4164ba090..a36b7ed10 100644 +index 11aae472d..731e7b2c9 100644 --- a/third_party/libopenjpeg/dwt.c +++ b/third_party/libopenjpeg/dwt.c @@ -63,9 +63,6 @@ @@ -9,10 +9,10 @@ -#define OPJ_WS(i) v->mem[(i)*2] -#define OPJ_WD(i) v->mem[(1+(i)*2)] - - #ifdef __AVX2__ - /** Number of int32 values in a AVX2 register */ - #define VREG_INT_COUNT 8 -@@ -82,6 +79,7 @@ + #if defined(__AVX512F__) + /** Number of int32 values in a AVX512 register */ + #define VREG_INT_COUNT 16 +@@ -85,6 +82,7 @@ typedef struct dwt_local { OPJ_INT32* mem; @@ -20,7 +20,7 @@ OPJ_INT32 dn; /* number of elements in high pass band */ OPJ_INT32 sn; /* number of elements in low pass band */ OPJ_INT32 cas; /* 0 = start on even coord, 1 = start on odd coord */ -@@ -140,7 +138,7 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, +@@ -143,7 +141,7 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, Inverse wavelet transform in 2-D. */ static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, @@ -29,7 +29,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile( opj_tcd_tilecomp_t* tilec, -@@ -181,13 +179,20 @@ static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r, +@@ -184,13 +182,20 @@ static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r, /*@}*/ @@ -56,7 +56,7 @@ /* <summary> */ /* This table contains the norms of the 5-3 wavelets for different bands. */ -@@ -296,8 +301,8 @@ static void opj_dwt_interleave_v(const opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) +@@ -299,8 +304,8 @@ static void opj_dwt_interleave_v(const opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) /* <summary> */ /* Inverse 5-3 wavelet transform in 1-D. */ /* </summary> */ @@ -67,7 +67,7 @@ { OPJ_INT32 i; -@@ -326,7 +331,7 @@ static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, +@@ -329,7 +334,7 @@ static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, static void opj_dwt_decode_1(const opj_dwt_t *v) { @@ -76,7 +76,7 @@ } #endif /* STANDARD_SLOW_VERSION */ -@@ -2062,7 +2067,7 @@ static void opj_dwt_decode_v_func(void* user_data, opj_tls_t* tls) +@@ -2275,7 +2280,7 @@ static void opj_dwt_decode_v_func(void* user_data, opj_tls_t* tls) /* Inverse wavelet transform in 2-D. */ /* </summary> */ static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, @@ -85,7 +85,7 @@ { opj_dwt_t h; opj_dwt_t v; -@@ -2084,22 +2089,23 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, +@@ -2299,22 +2304,23 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, return OPJ_TRUE; } num_threads = opj_thread_pool_get_thread_count(tp); @@ -112,7 +112,7 @@ v.mem = h.mem; while (--numres) { -@@ -2277,7 +2283,8 @@ static void opj_dwt_interleave_partial_v(OPJ_INT32 *dest, +@@ -2492,7 +2498,8 @@ static void opj_dwt_interleave_partial_v(OPJ_INT32 *dest, OPJ_UNUSED(ret); } @@ -122,7 +122,7 @@ OPJ_INT32 cas, OPJ_INT32 win_l_x0, OPJ_INT32 win_l_x1, -@@ -2657,16 +2664,16 @@ static OPJ_BOOL opj_dwt_decode_partial_tile( +@@ -2880,16 +2887,16 @@ static OPJ_BOOL opj_dwt_decode_partial_tile( opj_sparse_array_int32_free(sa); return OPJ_TRUE; } @@ -142,7 +142,7 @@ h.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); if (! h.mem) { /* FIXME event manager error callback */ -@@ -2674,6 +2681,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile( +@@ -2897,6 +2904,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile( return OPJ_FALSE; } @@ -150,7 +150,7 @@ v.mem = h.mem; for (resno = 1; resno < numres; resno ++) { -@@ -2784,7 +2792,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile( +@@ -3007,7 +3015,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile( win_ll_x1, win_hl_x0, win_hl_x1);
diff --git a/third_party/libopenjpeg/0046-func-ptr-mixup.patch b/third_party/libopenjpeg/0046-func-ptr-mixup.patch index cdd2288..2df25f1 100644 --- a/third_party/libopenjpeg/0046-func-ptr-mixup.patch +++ b/third_party/libopenjpeg/0046-func-ptr-mixup.patch
@@ -1,8 +1,8 @@ diff --git a/third_party/libopenjpeg/j2k.c b/third_party/libopenjpeg/j2k.c -index 9b06e7ec8..e2e048760 100644 +index c56ec72c1..5e9d75076 100644 --- a/third_party/libopenjpeg/j2k.c +++ b/third_party/libopenjpeg/j2k.c -@@ -6685,8 +6685,9 @@ static OPJ_BOOL opj_j2k_read_cpf(opj_j2k_t *p_j2k, +@@ -6749,8 +6749,9 @@ static OPJ_BOOL opj_j2k_read_cpf(opj_j2k_t *p_j2k, /* J2K / JPT decoder interface */ /* ----------------------------------------------------------------------- */ @@ -13,7 +13,7 @@ if (j2k && parameters) { j2k->m_cp.m_specific_param.m_dec.m_layer = parameters->cp_layer; j2k->m_cp.m_specific_param.m_dec.m_reduce = parameters->cp_reduce; -@@ -6700,15 +6701,17 @@ void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters) +@@ -6764,8 +6765,9 @@ void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters) } } @@ -23,6 +23,8 @@ + opj_j2k_t* j2k = (opj_j2k_t*)p_j2k; if (j2k) { j2k->m_cp.strict = strict; + if (strict) { +@@ -6774,8 +6776,9 @@ void opj_j2k_decoder_set_strict_mode(opj_j2k_t *j2k, OPJ_BOOL strict) } } @@ -33,7 +35,7 @@ /* Currently we pass the thread-pool to the tcd, so we cannot re-set it */ /* afterwards */ if (opj_has_thread_support() && j2k->m_tcd == NULL) { -@@ -7613,11 +7616,12 @@ static OPJ_BOOL opj_j2k_is_imf_compliant(opj_cparameters_t *parameters, +@@ -7680,11 +7683,12 @@ static OPJ_BOOL opj_j2k_is_imf_compliant(opj_cparameters_t *parameters, } @@ -47,8 +49,8 @@ OPJ_UINT32 i, j, tileno, numpocs_tile; opj_cp_t *cp = 00; OPJ_UINT32 cblkw, cblkh; -@@ -7666,10 +7670,10 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, - return OPJ_FALSE; +@@ -7754,10 +7758,10 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, + } } - p_j2k->m_specific_param.m_encoder.m_nb_comps = image->numcomps; @@ -60,7 +62,7 @@ /* set default values for cp */ cp->tw = 1; -@@ -7834,7 +7838,7 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, +@@ -7922,7 +7926,7 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, } if (OPJ_IS_CINEMA(parameters->rsiz) || OPJ_IS_IMF(parameters->rsiz)) { @@ -69,7 +71,7 @@ } /* Manage profiles and applications and set RSIZ */ -@@ -8379,7 +8383,7 @@ static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno, +@@ -8478,7 +8482,7 @@ static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno, * ----------------------------------------------------------------------- */ @@ -78,7 +80,7 @@ opj_stream_private_t *p_stream, opj_event_mgr_t * p_manager ) -@@ -8391,10 +8395,11 @@ OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *p_j2k, +@@ -8490,10 +8494,11 @@ OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *p_j2k, } OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream, @@ -91,7 +93,7 @@ /* preconditions */ assert(p_j2k != 00); assert(p_stream != 00); -@@ -9178,8 +9183,9 @@ static const opj_dec_memory_marker_handler_t * opj_j2k_get_marker_handler( +@@ -9354,8 +9359,9 @@ static const opj_dec_memory_marker_handler_t * opj_j2k_get_marker_handler( return e; } @@ -102,7 +104,7 @@ if (p_j2k == 00) { return; } -@@ -9518,7 +9524,7 @@ static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t +@@ -9700,7 +9706,7 @@ static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t return OPJ_TRUE; } @@ -111,7 +113,7 @@ OPJ_UINT32 * p_tile_index, OPJ_UINT32 * p_data_size, OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, -@@ -9528,6 +9534,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, +@@ -9710,6 +9716,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, opj_stream_private_t *p_stream, opj_event_mgr_t * p_manager) { @@ -119,7 +121,7 @@ OPJ_UINT32 l_current_marker = J2K_MS_SOT; OPJ_UINT32 l_marker_size; const opj_dec_memory_marker_handler_t * l_marker_handler = 00; -@@ -9827,13 +9834,14 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, +@@ -10112,13 +10119,14 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, return OPJ_TRUE; } @@ -135,7 +137,7 @@ OPJ_UINT32 l_current_marker; OPJ_BYTE l_data [2]; opj_tcp_t * l_tcp; -@@ -10200,11 +10208,12 @@ static OPJ_BOOL opj_j2k_update_image_dimensions(opj_image_t* p_image, +@@ -10485,11 +10493,12 @@ static OPJ_BOOL opj_j2k_update_image_dimensions(opj_image_t* p_image, return OPJ_TRUE; } @@ -149,7 +151,7 @@ OPJ_UINT32 i; OPJ_BOOL* already_mapped; -@@ -10260,12 +10269,13 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k, +@@ -10545,12 +10554,13 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k, } @@ -164,7 +166,7 @@ opj_cp_t * l_cp = &(p_j2k->m_cp); opj_image_t * l_image = p_j2k->m_private_image; OPJ_BOOL ret; -@@ -11200,8 +11210,9 @@ static void opj_j2k_dump_tile_info(opj_tcp_t * l_default_tile, +@@ -11493,8 +11503,9 @@ static void opj_j2k_dump_tile_info(opj_tcp_t * l_default_tile, } } @@ -175,7 +177,7 @@ /* Check if the flag is compatible with j2k file*/ if ((flag & OPJ_JP2_INFO) || (flag & OPJ_JP2_IND)) { fprintf(out_stream, "Wrong flag\n"); -@@ -11391,8 +11402,9 @@ void j2k_dump_image_comp_header(opj_image_comp_t* comp_header, +@@ -11698,8 +11709,9 @@ void j2k_dump_image_comp_header(opj_image_comp_t* comp_header, } } @@ -186,7 +188,7 @@ OPJ_UINT32 compno; OPJ_UINT32 numcomps = p_j2k->m_private_image->numcomps; opj_tcp_t *l_default_tile; -@@ -11467,8 +11479,9 @@ opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k) +@@ -11774,8 +11786,9 @@ opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k) return cstr_info; } @@ -197,7 +199,7 @@ opj_codestream_index_t* l_cstr_index = (opj_codestream_index_t*) opj_calloc(1, sizeof(opj_codestream_index_t)); if (!l_cstr_index) { -@@ -11972,11 +11985,12 @@ static OPJ_BOOL opj_j2k_move_data_from_codec_to_output_image(opj_j2k_t * p_j2k, +@@ -12390,11 +12403,12 @@ static OPJ_BOOL opj_j2k_move_data_from_codec_to_output_image(opj_j2k_t * p_j2k, return OPJ_TRUE; } @@ -211,7 +213,7 @@ if (!p_image) { return OPJ_FALSE; } -@@ -12030,12 +12044,13 @@ OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k, +@@ -12448,12 +12462,13 @@ OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k, return opj_j2k_move_data_from_codec_to_output_image(p_j2k, p_image); } @@ -226,7 +228,7 @@ OPJ_UINT32 compno; OPJ_UINT32 l_tile_x, l_tile_y; opj_image_comp_t* l_img_comp; -@@ -12143,10 +12158,11 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k, +@@ -12561,10 +12576,11 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k, return opj_j2k_move_data_from_codec_to_output_image(p_j2k, p_image); } @@ -239,7 +241,7 @@ OPJ_UINT32 it_comp; p_j2k->m_cp.m_specific_param.m_dec.m_reduce = res_factor; -@@ -12177,10 +12193,11 @@ OPJ_BOOL opj_j2k_set_decoded_resolution_factor(opj_j2k_t *p_j2k, +@@ -12595,10 +12611,11 @@ OPJ_BOOL opj_j2k_set_decoded_resolution_factor(opj_j2k_t *p_j2k, /* ----------------------------------------------------------------------- */ OPJ_BOOL opj_j2k_encoder_set_extra_options( @@ -252,7 +254,7 @@ const char* const* p_option_iter; if (p_options == NULL) { -@@ -12239,10 +12256,11 @@ OPJ_BOOL opj_j2k_encoder_set_extra_options( +@@ -12657,10 +12674,11 @@ OPJ_BOOL opj_j2k_encoder_set_extra_options( /* ----------------------------------------------------------------------- */ @@ -265,7 +267,7 @@ OPJ_UINT32 i, j; OPJ_UINT32 l_nb_tiles; OPJ_SIZE_T l_max_tile_size = 0, l_current_tile_size; -@@ -12347,10 +12365,11 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k, +@@ -12765,10 +12783,11 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k, return OPJ_TRUE; } @@ -278,7 +280,7 @@ /* customization of the encoding */ if (! opj_j2k_setup_end_compress(p_j2k, p_manager)) { return OPJ_FALSE; -@@ -12363,11 +12382,12 @@ OPJ_BOOL opj_j2k_end_compress(opj_j2k_t *p_j2k, +@@ -12781,11 +12800,12 @@ OPJ_BOOL opj_j2k_end_compress(opj_j2k_t *p_j2k, return OPJ_TRUE; } @@ -292,7 +294,7 @@ /* preconditions */ assert(p_j2k != 00); assert(p_stream != 00); -@@ -13154,13 +13174,14 @@ static OPJ_BOOL opj_j2k_create_tcd(opj_j2k_t *p_j2k, +@@ -13571,13 +13591,14 @@ static OPJ_BOOL opj_j2k_create_tcd(opj_j2k_t *p_j2k, return OPJ_TRUE; } @@ -309,10 +311,10 @@ opj_event_msg(p_manager, EVT_ERROR, "Error while opj_j2k_pre_write_tile with tile index = %d\n", p_tile_index); diff --git a/third_party/libopenjpeg/j2k.h b/third_party/libopenjpeg/j2k.h -index 04fba645a..1d824c019 100644 +index bcf70a419..01baf4750 100644 --- a/third_party/libopenjpeg/j2k.h +++ b/third_party/libopenjpeg/j2k.h -@@ -621,15 +621,15 @@ opj_j2k_t; +@@ -658,15 +658,15 @@ opj_j2k_t; /** Setup the decoder decoding parameters using user parameters. @@ -333,7 +335,7 @@ /** * Creates a J2K compression structure -@@ -639,7 +639,7 @@ OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads); +@@ -676,7 +676,7 @@ OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads); opj_j2k_t* opj_j2k_create_compress(void); @@ -342,7 +344,7 @@ opj_cparameters_t *parameters, opj_image_t *image, opj_event_mgr_t * p_manager); -@@ -658,7 +658,7 @@ const char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order); +@@ -695,7 +695,7 @@ const char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order); * Ends the decompression procedures and possibiliy add data to be read after the * codestream. */ @@ -351,7 +353,7 @@ opj_stream_private_t *p_stream, opj_event_mgr_t * p_manager); -@@ -666,14 +666,14 @@ OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *j2k, +@@ -703,14 +703,14 @@ OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *j2k, * Reads a jpeg2000 codestream header structure. * * @param p_stream the stream to read data from. @@ -368,7 +370,7 @@ opj_image_t** p_image, opj_event_mgr_t* p_manager); -@@ -681,9 +681,9 @@ OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream, +@@ -718,9 +718,9 @@ OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream, /** * Destroys a jpeg2000 codec. * @@ -380,7 +382,7 @@ /** * Destroys a codestream index structure. -@@ -694,14 +694,14 @@ void j2k_destroy_cstr_index(opj_codestream_index_t *p_cstr_ind); +@@ -731,14 +731,14 @@ void j2k_destroy_cstr_index(opj_codestream_index_t *p_cstr_ind); /** * Decode tile data. @@ -397,7 +399,7 @@ OPJ_UINT32 p_tile_index, OPJ_BYTE * p_data, OPJ_UINT32 p_data_size, -@@ -710,7 +710,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, +@@ -747,7 +747,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, /** * Reads a tile header. @@ -406,7 +408,7 @@ * @param p_tile_index FIXME DOC * @param p_data_size FIXME DOC * @param p_tile_x0 FIXME DOC -@@ -722,7 +722,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, +@@ -759,7 +759,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ @@ -415,7 +417,7 @@ OPJ_UINT32 * p_tile_index, OPJ_UINT32 * p_data_size, OPJ_INT32 * p_tile_x0, -@@ -737,7 +737,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, +@@ -774,7 +774,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, /** Sets the indices of the components to decode. * @@ -424,7 +426,7 @@ * @param numcomps Number of components to decode. * @param comps_indices Array of num_compts indices (numbering starting at 0) * corresponding to the components to decode. -@@ -745,7 +745,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, +@@ -782,7 +782,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, * * @return OPJ_TRUE in case of success. */ @@ -433,7 +435,7 @@ OPJ_UINT32 numcomps, const OPJ_UINT32* comps_indices, opj_event_mgr_t * p_manager); -@@ -753,7 +753,7 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k, +@@ -790,7 +790,7 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k, /** * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. * @@ -442,7 +444,7 @@ * @param p_image FIXME DOC * @param p_start_x the left position of the rectangle to decode (in image coordinates). * @param p_start_y the up position of the rectangle to decode (in image coordinates). -@@ -763,7 +763,7 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k, +@@ -800,7 +800,7 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k, * * @return true if the area could be set. */ @@ -451,7 +453,7 @@ opj_image_t* p_image, OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, -@@ -780,12 +780,12 @@ opj_j2k_t* opj_j2k_create_decompress(void); +@@ -817,12 +817,12 @@ opj_j2k_t* opj_j2k_create_decompress(void); /** * Dump some elements from the J2K decompression structure . * @@ -466,7 +468,7 @@ -@@ -812,20 +812,20 @@ void j2k_dump_image_comp_header(opj_image_comp_t* comp, OPJ_BOOL dev_dump_flag, +@@ -849,20 +849,20 @@ void j2k_dump_image_comp_header(opj_image_comp_t* comp, OPJ_BOOL dev_dump_flag, /** * Get the codestream info from a JPEG2000 codec. * @@ -491,7 +493,7 @@ /** * Decode an image from a JPEG-2000 codestream -@@ -835,46 +835,46 @@ opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k); +@@ -872,46 +872,46 @@ opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k); * @param p_manager FIXME DOC * @return FIXME DOC */ @@ -545,7 +547,7 @@ OPJ_UINT32 p_tile_index, OPJ_BYTE * p_data, OPJ_UINT32 p_data_size, -@@ -884,21 +884,21 @@ OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k, +@@ -921,21 +921,21 @@ OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k, /** * Encodes an image into a JPEG-2000 codestream */ @@ -570,7 +572,7 @@ opj_stream_private_t *p_stream, opj_image_t * p_image, opj_event_mgr_t * p_manager); -@@ -907,7 +907,7 @@ OPJ_BOOL opj_j2k_start_compress(opj_j2k_t *p_j2k, +@@ -944,7 +944,7 @@ OPJ_BOOL opj_j2k_start_compress(opj_j2k_t *p_j2k, * Ends the compression procedures and possibiliy add data to be read after the * codestream. */ @@ -580,10 +582,10 @@ opj_event_mgr_t * p_manager); diff --git a/third_party/libopenjpeg/jp2.c b/third_party/libopenjpeg/jp2.c -index 44d0c98e5..6db728d18 100644 +index 9007c9736..6b4d5dbaa 100644 --- a/third_party/libopenjpeg/jp2.c +++ b/third_party/libopenjpeg/jp2.c -@@ -1609,11 +1609,12 @@ static OPJ_BOOL opj_jp2_read_colr(opj_jp2_t *jp2, +@@ -1643,11 +1643,12 @@ static OPJ_BOOL opj_jp2_apply_color_postprocessing(opj_jp2_t *jp2, return OPJ_TRUE; } @@ -597,7 +599,7 @@ if (!p_image) { return OPJ_FALSE; } -@@ -1905,8 +1906,9 @@ static OPJ_BOOL opj_jp2_write_jp(opj_jp2_t *jp2, +@@ -1891,8 +1892,9 @@ static OPJ_BOOL opj_jp2_write_jp(opj_jp2_t *jp2, /* JP2 decoder interface */ /* ----------------------------------------------------------------------- */ @@ -608,7 +610,7 @@ /* setup the J2K codec */ opj_j2k_setup_decoder(jp2->j2k, parameters); -@@ -1917,13 +1919,15 @@ void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) +@@ -1903,13 +1905,15 @@ void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; } @@ -626,7 +628,7 @@ return opj_j2k_set_threads(jp2->j2k, num_threads); } -@@ -1931,11 +1935,12 @@ OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads) +@@ -1917,11 +1921,12 @@ OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads) /* JP2 encoder interface */ /* ----------------------------------------------------------------------- */ @@ -640,7 +642,7 @@ OPJ_UINT32 i; OPJ_UINT32 depth_0; OPJ_UINT32 sign; -@@ -2118,18 +2123,20 @@ OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2, +@@ -2108,18 +2113,20 @@ OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2, return OPJ_TRUE; } @@ -663,7 +665,7 @@ /* preconditions */ assert(jp2 != 00); assert(cio != 00); -@@ -2148,11 +2155,12 @@ OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2, +@@ -2138,11 +2145,12 @@ OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2, return opj_j2k_end_decompress(jp2->j2k, cio, p_manager); } @@ -677,7 +679,7 @@ /* preconditions */ assert(jp2 != 00); assert(cio != 00); -@@ -2476,12 +2484,13 @@ static OPJ_BOOL opj_jp2_exec(opj_jp2_t * jp2, +@@ -2466,12 +2474,13 @@ static OPJ_BOOL opj_jp2_exec(opj_jp2_t * jp2, return l_result; } @@ -692,7 +694,7 @@ /* preconditions */ assert(jp2 != 00); assert(stream != 00); -@@ -2849,11 +2849,12 @@ static OPJ_BOOL opj_jp2_read_boxhdr_char(opj_jp2_box_t *box, +@@ -2844,11 +2853,12 @@ static OPJ_BOOL opj_jp2_read_boxhdr_char(opj_jp2_box_t *box, } OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream, @@ -706,7 +708,7 @@ int ret; /* preconditions */ -@@ -2981,7 +2991,7 @@ static OPJ_BOOL opj_jp2_setup_header_reading(opj_jp2_t *jp2, +@@ -2997,7 +3007,7 @@ static OPJ_BOOL opj_jp2_setup_header_reading(opj_jp2_t *jp2, return OPJ_TRUE; } @@ -715,7 +717,7 @@ OPJ_UINT32 * p_tile_index, OPJ_UINT32 * p_data_size, OPJ_INT32 * p_tile_x0, -@@ -2994,7 +3004,8 @@ OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2, +@@ -3010,7 +3020,8 @@ OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2, opj_event_mgr_t * p_manager ) { @@ -725,7 +727,7 @@ p_tile_index, p_data_size, p_tile_x0, p_tile_y0, -@@ -3005,7 +3016,7 @@ OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2, +@@ -3021,7 +3032,7 @@ OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2, p_manager); } @@ -734,7 +736,7 @@ OPJ_UINT32 p_tile_index, OPJ_BYTE * p_data, OPJ_UINT32 p_data_size, -@@ -3014,11 +3025,12 @@ OPJ_BOOL opj_jp2_write_tile(opj_jp2_t *p_jp2, +@@ -3030,11 +3041,12 @@ OPJ_BOOL opj_jp2_write_tile(opj_jp2_t *p_jp2, ) { @@ -749,7 +751,7 @@ OPJ_UINT32 p_tile_index, OPJ_BYTE * p_data, OPJ_UINT32 p_data_size, -@@ -3026,12 +3038,14 @@ OPJ_BOOL opj_jp2_decode_tile(opj_jp2_t * p_jp2, +@@ -3042,12 +3054,14 @@ OPJ_BOOL opj_jp2_decode_tile(opj_jp2_t * p_jp2, opj_event_mgr_t * p_manager ) { @@ -766,7 +768,7 @@ if (jp2) { /* destroy the J2K codec */ opj_j2k_destroy(jp2->j2k); -@@ -3098,34 +3112,37 @@ void opj_jp2_destroy(opj_jp2_t *jp2) +@@ -3114,34 +3128,37 @@ void opj_jp2_destroy(opj_jp2_t *jp2) } } @@ -809,7 +811,7 @@ if (!p_image) { return OPJ_FALSE; } -@@ -3234,41 +3251,46 @@ opj_jp2_t* opj_jp2_create(OPJ_BOOL p_is_decoder) +@@ -3204,41 +3221,46 @@ opj_jp2_t* opj_jp2_create(OPJ_BOOL p_is_decoder) return jp2; } @@ -1118,10 +1120,10 @@ /*@}*/ diff --git a/third_party/libopenjpeg/openjpeg.c b/third_party/libopenjpeg/openjpeg.c -index 29d3ee528..9dd4256d7 100644 +index 382d8f4f0..b8a4bfb0d 100644 --- a/third_party/libopenjpeg/openjpeg.c +++ b/third_party/libopenjpeg/openjpeg.c -@@ -189,85 +189,48 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format) +@@ -194,85 +194,48 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format) switch (p_format) { case OPJ_CODEC_J2K: @@ -1223,7 +1225,7 @@ l_codec->m_codec = opj_j2k_create_decompress(); -@@ -280,85 +243,47 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format) +@@ -285,85 +248,47 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format) case OPJ_CODEC_JP2: /* get a JP2 decoder handle */ @@ -1325,7 +1327,7 @@ l_codec->m_codec = opj_jp2_create(OPJ_TRUE); -@@ -662,41 +587,25 @@ opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format) +@@ -667,41 +592,25 @@ opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format) switch (p_format) { case OPJ_CODEC_J2K: @@ -1386,7 +1388,7 @@ l_codec->m_codec = opj_j2k_create_compress(); if (! l_codec->m_codec) { -@@ -708,41 +617,25 @@ opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format) +@@ -713,41 +622,25 @@ opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format) case OPJ_CODEC_JP2: /* get a JP2 decoder handle */
diff --git a/third_party/libopenjpeg/0047-validate_opj_stream_read_data.patch b/third_party/libopenjpeg/0047-validate_opj_stream_read_data.patch deleted file mode 100644 index 25c3933..0000000 --- a/third_party/libopenjpeg/0047-validate_opj_stream_read_data.patch +++ /dev/null
@@ -1,24 +0,0 @@ -commit dea92eea8b6ab55f7eb542ea229b2c2124aa2124 -Author: Even Rouault <even.rouault@spatialys.com> -Date: Fri Jun 21 15:08:24 2024 +0200 - - opj_j2k_read_sod(): validate opj_stream_read_data() return to avoid potential later heap-buffer-overflow in in opj_t1_decode_cblk when disabling strict mode - - Fixes #1533 - -diff --git a/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c -index 293f7579..7cdeffd7 100644 ---- a/src/lib/openjp2/j2k.c -+++ b/src/lib/openjp2/j2k.c -@@ -5059,6 +5059,11 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k, - } - - if (l_current_read_size != p_j2k->m_specific_param.m_decoder.m_sot_length) { -+ if (l_current_read_size == (OPJ_SIZE_T)(-1)) { -+ /* Avoid issue of https://github.com/uclouvain/openjpeg/issues/1533 */ -+ opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); -+ return OPJ_FALSE; -+ } - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; - } else { - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT;
diff --git a/third_party/libopenjpeg/0048-check_corruption_non_strict_mode.patch b/third_party/libopenjpeg/0048-check_corruption_non_strict_mode.patch deleted file mode 100644 index f7e597f..0000000 --- a/third_party/libopenjpeg/0048-check_corruption_non_strict_mode.patch +++ /dev/null
@@ -1,118 +0,0 @@ -commit f3b28c5ee417df9f23ca590b0e949d8a309408a0 -Author: Even Rouault <even.rouault@spatialys.com> -Date: Mon Jun 24 21:11:21 2024 +0200 - - Avoid heap-buffer-overflow read on corrupted image in non-strict mode - - Fixes #1535 - -diff --git a/src/lib/openjp2/t1.c b/src/lib/openjp2/t1.c -index df14ffc1..b5adbf2f 100644 ---- a/src/lib/openjp2/t1.c -+++ b/src/lib/openjp2/t1.c -@@ -2006,10 +2006,16 @@ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, - opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); - -+ if (cblk->corrupted) { -+ assert(cblk->numchunks == 0); -+ return OPJ_TRUE; -+ } -+ - /* Even if we have a single chunk, in multi-threaded decoding */ - /* the insertion of our synthetic marker might potentially override */ - /* valid codestream of other codeblocks decoded in parallel. */ -- if (cblk->numchunks > 1 || t1->mustuse_cblkdatabuffer) { -+ if (cblk->numchunks > 1 || (t1->mustuse_cblkdatabuffer && -+ cblk->numchunks > 0)) { - OPJ_UINT32 i; - OPJ_UINT32 cblk_len; - -diff --git a/src/lib/openjp2/t2.c b/src/lib/openjp2/t2.c -index 57353bf1..22f2e623 100644 ---- a/src/lib/openjp2/t2.c -+++ b/src/lib/openjp2/t2.c -@@ -1407,18 +1407,21 @@ static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2, - l_nb_code_blocks = l_prc->cw * l_prc->ch; - l_cblk = l_prc->cblks.dec; - -- for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { -+ for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno, ++l_cblk) { - opj_tcd_seg_t *l_seg = 00; - -- // if we have a partial data stream, set numchunks to zero -- // since we have no data to actually decode. -- if (partial_buffer) { -- l_cblk->numchunks = 0; -- } -- - if (!l_cblk->numnewpasses) { - /* nothing to do */ -- ++l_cblk; -+ continue; -+ } -+ -+ if (partial_buffer || l_cblk->corrupted) { -+ /* if a previous segment in this packet couldn't be decoded, -+ * or if this code block was corrupted in a previous layer, -+ * then mark it as corrupted. -+ */ -+ l_cblk->numchunks = 0; -+ l_cblk->corrupted = OPJ_TRUE; - continue; - } - -@@ -1451,18 +1454,13 @@ static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2, - "read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", - l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, - p_pi->compno); -- // skip this codeblock since it is a partial read -+ /* skip this codeblock (and following ones in this -+ * packet) since it is a partial read -+ */ - partial_buffer = OPJ_TRUE; -+ l_cblk->corrupted = OPJ_TRUE; - l_cblk->numchunks = 0; -- -- l_seg->numpasses += l_seg->numnewpasses; -- l_cblk->numnewpasses -= l_seg->numnewpasses; -- if (l_cblk->numnewpasses > 0) { -- ++l_seg; -- ++l_cblk->numsegs; -- break; -- } -- continue; -+ break; - } - } - -@@ -1519,7 +1517,7 @@ static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2, - } while (l_cblk->numnewpasses > 0); - - l_cblk->real_num_segs = l_cblk->numsegs; -- ++l_cblk; -+ - } /* next code_block */ - - ++l_band; -@@ -1603,6 +1601,8 @@ static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2, - "skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", - l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, - p_pi->compno); -+ -+ *p_data_read = p_max_length; - return OPJ_TRUE; - } - } -diff --git a/src/lib/openjp2/tcd.h b/src/lib/openjp2/tcd.h -index cf4e0082..3371b08c 100644 ---- a/src/lib/openjp2/tcd.h -+++ b/src/lib/openjp2/tcd.h -@@ -141,6 +141,7 @@ typedef struct opj_tcd_cblk_dec { - OPJ_UINT32 numchunksalloc; /* Number of chunks item allocated */ - /* Decoded code-block. Only used for subtile decoding. Otherwise tilec->data is directly updated */ - OPJ_INT32* decoded_data; -+ OPJ_BOOL corrupted; /* whether the code block data is corrupted */ - } opj_tcd_cblk_dec_t; - - /** Precinct structure */
diff --git a/third_party/libopenjpeg/README.pdfium b/third_party/libopenjpeg/README.pdfium index 726574e..2bef41a 100644 --- a/third_party/libopenjpeg/README.pdfium +++ b/third_party/libopenjpeg/README.pdfium
@@ -1,12 +1,12 @@ Name: OpenJPEG URL: http://www.openjpeg.org/ -Version: 2.5.2 (also update in opj_config*) -Revision: 39e8c50a2f9bdcf36810ee3d41bcbf1cc78968ae +Version: 2.5.3 (also update in opj_config*) +Revision: 210a8a5690d0da66f02d49420d7176a21ef409dc Security Critical: yes Shipped: yes License: 2-clause BSD License File: LICENSE -CPEPrefix: cpe:/a:uclouvain:openjpeg:2.5.2 +CPEPrefix: cpe:/a:uclouvain:openjpeg:2.5.3 Description: JPEG 2000 library. @@ -32,5 +32,3 @@ 0039-opj_mqc_renorme.patch: Remove unused opj_mqc_renorme(). 0041-remove_opj_clock.patch: Remove unused opj_clock.h include. 0046-func-ptr-mixup.patch: Prevent mixing up function pointer types. -0047-validate_opj_stream_read_data.patch: Avoid potential heap-buffer-overflow in non-strict mode. -0048-check_corruption_non_strict_mode.patch: Avoid heap-buffer-overflow in non-strict mode.
diff --git a/third_party/libopenjpeg/dwt.c b/third_party/libopenjpeg/dwt.c index b6f0e48..731e7b2 100644 --- a/third_party/libopenjpeg/dwt.c +++ b/third_party/libopenjpeg/dwt.c
@@ -52,7 +52,7 @@ #ifdef __SSSE3__ #include <tmmintrin.h> #endif -#ifdef __AVX2__ +#if (defined(__AVX2__) || defined(__AVX512F__)) #include <immintrin.h> #endif @@ -63,7 +63,10 @@ /** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ /*@{*/ -#ifdef __AVX2__ +#if defined(__AVX512F__) +/** Number of int32 values in a AVX512 register */ +#define VREG_INT_COUNT 16 +#elif defined(__AVX2__) /** Number of int32 values in a AVX2 register */ #define VREG_INT_COUNT 8 #else @@ -336,6 +339,51 @@ #endif /* STANDARD_SLOW_VERSION */ +#if defined(__AVX512F__) +static int32_t loop_short_sse(int32_t len, const int32_t** lf_ptr, + const int32_t** hf_ptr, int32_t** out_ptr, + int32_t* prev_even) +{ + int32_t next_even; + __m128i odd, even_m1, unpack1, unpack2; + const int32_t batch = (len - 2) / 8; + const __m128i two = _mm_set1_epi32(2); + + for (int32_t i = 0; i < batch; i++) { + const __m128i lf_ = _mm_loadu_si128((__m128i*)(*lf_ptr + 1)); + const __m128i hf1_ = _mm_loadu_si128((__m128i*)(*hf_ptr)); + const __m128i hf2_ = _mm_loadu_si128((__m128i*)(*hf_ptr + 1)); + + __m128i even = _mm_add_epi32(hf1_, hf2_); + even = _mm_add_epi32(even, two); + even = _mm_srai_epi32(even, 2); + even = _mm_sub_epi32(lf_, even); + + next_even = _mm_extract_epi32(even, 3); + even_m1 = _mm_bslli_si128(even, 4); + even_m1 = _mm_insert_epi32(even_m1, *prev_even, 0); + + //out[0] + out[2] + odd = _mm_add_epi32(even_m1, even); + odd = _mm_srai_epi32(odd, 1); + odd = _mm_add_epi32(odd, hf1_); + + unpack1 = _mm_unpacklo_epi32(even_m1, odd); + unpack2 = _mm_unpackhi_epi32(even_m1, odd); + + _mm_storeu_si128((__m128i*)(*out_ptr + 0), unpack1); + _mm_storeu_si128((__m128i*)(*out_ptr + 4), unpack2); + + *prev_even = next_even; + + *out_ptr += 8; + *lf_ptr += 4; + *hf_ptr += 4; + } + return batch; +} +#endif + #if !defined(STANDARD_SLOW_VERSION) static void opj_idwt53_h_cas0(OPJ_INT32* tmp, const OPJ_INT32 sn, @@ -369,6 +417,145 @@ tmp[len - 1] = in_odd[(len - 1) / 2] + tmp[len - 2]; } #else +#if defined(__AVX512F__) + OPJ_INT32* out_ptr = tmp; + int32_t prev_even = in_even[0] - ((in_odd[0] + 1) >> 1); + + const __m512i permutevar_mask = _mm512_setr_epi32( + 0x10, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e); + const __m512i store1_perm = _mm512_setr_epi64(0x00, 0x01, 0x08, 0x09, 0x02, + 0x03, 0x0a, 0x0b); + const __m512i store2_perm = _mm512_setr_epi64(0x04, 0x05, 0x0c, 0x0d, 0x06, + 0x07, 0x0e, 0x0f); + + const __m512i two = _mm512_set1_epi32(2); + + int32_t simd_batch_512 = (len - 2) / 32; + int32_t leftover; + + for (i = 0; i < simd_batch_512; i++) { + const __m512i lf_avx2 = _mm512_loadu_si512((__m512i*)(in_even + 1)); + const __m512i hf1_avx2 = _mm512_loadu_si512((__m512i*)(in_odd)); + const __m512i hf2_avx2 = _mm512_loadu_si512((__m512i*)(in_odd + 1)); + int32_t next_even; + __m512i duplicate, even_m1, odd, unpack1, unpack2, store1, store2; + + __m512i even = _mm512_add_epi32(hf1_avx2, hf2_avx2); + even = _mm512_add_epi32(even, two); + even = _mm512_srai_epi32(even, 2); + even = _mm512_sub_epi32(lf_avx2, even); + + next_even = _mm_extract_epi32(_mm512_extracti32x4_epi32(even, 3), 3); + + duplicate = _mm512_set1_epi32(prev_even); + even_m1 = _mm512_permutex2var_epi32(even, permutevar_mask, duplicate); + + //out[0] + out[2] + odd = _mm512_add_epi32(even_m1, even); + odd = _mm512_srai_epi32(odd, 1); + odd = _mm512_add_epi32(odd, hf1_avx2); + + unpack1 = _mm512_unpacklo_epi32(even_m1, odd); + unpack2 = _mm512_unpackhi_epi32(even_m1, odd); + + store1 = _mm512_permutex2var_epi64(unpack1, store1_perm, unpack2); + store2 = _mm512_permutex2var_epi64(unpack1, store2_perm, unpack2); + + _mm512_storeu_si512(out_ptr, store1); + _mm512_storeu_si512(out_ptr + 16, store2); + + prev_even = next_even; + + out_ptr += 32; + in_even += 16; + in_odd += 16; + } + + leftover = len - simd_batch_512 * 32; + if (leftover > 8) { + leftover -= 8 * loop_short_sse(leftover, &in_even, &in_odd, &out_ptr, + &prev_even); + } + out_ptr[0] = prev_even; + + for (j = 1; j < (leftover - 2); j += 2) { + out_ptr[2] = in_even[1] - ((in_odd[0] + (in_odd[1]) + 2) >> 2); + out_ptr[1] = in_odd[0] + ((out_ptr[0] + out_ptr[2]) >> 1); + in_even++; + in_odd++; + out_ptr += 2; + } + + if (len & 1) { + out_ptr[2] = in_even[1] - ((in_odd[0] + 1) >> 1); + out_ptr[1] = in_odd[0] + ((out_ptr[0] + out_ptr[2]) >> 1); + } else { //!(len & 1) + out_ptr[1] = in_odd[0] + out_ptr[0]; + } +#elif defined(__AVX2__) + OPJ_INT32* out_ptr = tmp; + int32_t prev_even = in_even[0] - ((in_odd[0] + 1) >> 1); + + const __m256i reg_permutevar_mask_move_right = _mm256_setr_epi32(0x00, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + const __m256i two = _mm256_set1_epi32(2); + + int32_t simd_batch = (len - 2) / 16; + int32_t next_even; + __m256i even_m1, odd, unpack1_avx2, unpack2_avx2; + + for (i = 0; i < simd_batch; i++) { + const __m256i lf_avx2 = _mm256_loadu_si256((__m256i*)(in_even + 1)); + const __m256i hf1_avx2 = _mm256_loadu_si256((__m256i*)(in_odd)); + const __m256i hf2_avx2 = _mm256_loadu_si256((__m256i*)(in_odd + 1)); + + __m256i even = _mm256_add_epi32(hf1_avx2, hf2_avx2); + even = _mm256_add_epi32(even, two); + even = _mm256_srai_epi32(even, 2); + even = _mm256_sub_epi32(lf_avx2, even); + + next_even = _mm_extract_epi32(_mm256_extracti128_si256(even, 1), 3); + even_m1 = _mm256_permutevar8x32_epi32(even, reg_permutevar_mask_move_right); + even_m1 = _mm256_blend_epi32(even_m1, _mm256_set1_epi32(prev_even), (1 << 0)); + + //out[0] + out[2] + odd = _mm256_add_epi32(even_m1, even); + odd = _mm256_srai_epi32(odd, 1); + odd = _mm256_add_epi32(odd, hf1_avx2); + + unpack1_avx2 = _mm256_unpacklo_epi32(even_m1, odd); + unpack2_avx2 = _mm256_unpackhi_epi32(even_m1, odd); + + _mm_storeu_si128((__m128i*)(out_ptr + 0), _mm256_castsi256_si128(unpack1_avx2)); + _mm_storeu_si128((__m128i*)(out_ptr + 4), _mm256_castsi256_si128(unpack2_avx2)); + _mm_storeu_si128((__m128i*)(out_ptr + 8), _mm256_extracti128_si256(unpack1_avx2, + 0x1)); + _mm_storeu_si128((__m128i*)(out_ptr + 12), + _mm256_extracti128_si256(unpack2_avx2, 0x1)); + + prev_even = next_even; + + out_ptr += 16; + in_even += 8; + in_odd += 8; + } + out_ptr[0] = prev_even; + for (j = simd_batch * 16 + 1; j < (len - 2); j += 2) { + out_ptr[2] = in_even[1] - ((in_odd[0] + in_odd[1] + 2) >> 2); + out_ptr[1] = in_odd[0] + ((out_ptr[0] + out_ptr[2]) >> 1); + in_even++; + in_odd++; + out_ptr += 2; + } + + if (len & 1) { + out_ptr[2] = in_even[1] - ((in_odd[0] + 1) >> 1); + out_ptr[1] = in_odd[0] + ((out_ptr[0] + out_ptr[2]) >> 1); + } else { //!(len & 1) + out_ptr[1] = in_odd[0] + out_ptr[0]; + } +#else OPJ_INT32 d1c, d1n, s1n, s0c, s0n; assert(len > 1); @@ -402,7 +589,8 @@ } else { tmp[len - 1] = d1n + s0n; } -#endif +#endif /*(__AVX512F__ || __AVX2__)*/ +#endif /*TWO_PASS_VERSION*/ memcpy(tiledp, tmp, (OPJ_UINT32)len * sizeof(OPJ_INT32)); } @@ -516,10 +704,20 @@ #endif } -#if (defined(__SSE2__) || defined(__AVX2__)) && !defined(STANDARD_SLOW_VERSION) +#if (defined(__SSE2__) || defined(__AVX2__) || defined(__AVX512F__)) && !defined(STANDARD_SLOW_VERSION) /* Conveniency macros to improve the readability of the formulas */ -#if __AVX2__ +#if defined(__AVX512F__) +#define VREG __m512i +#define LOAD_CST(x) _mm512_set1_epi32(x) +#define LOAD(x) _mm512_loadu_si512((const VREG*)(x)) +#define LOADU(x) _mm512_loadu_si512((const VREG*)(x)) +#define STORE(x,y) _mm512_storeu_si512((VREG*)(x),(y)) +#define STOREU(x,y) _mm512_storeu_si512((VREG*)(x),(y)) +#define ADD(x,y) _mm512_add_epi32((x),(y)) +#define SUB(x,y) _mm512_sub_epi32((x),(y)) +#define SAR(x,y) _mm512_srai_epi32((x),(y)) +#elif defined(__AVX2__) #define VREG __m256i #define LOAD_CST(x) _mm256_set1_epi32(x) #define LOAD(x) _mm256_load_si256((const VREG*)(x)) @@ -581,7 +779,10 @@ const VREG two = LOAD_CST(2); assert(len > 1); -#if __AVX2__ +#if defined(__AVX512F__) + assert(PARALLEL_COLS_53 == 32); + assert(VREG_INT_COUNT == 16); +#elif defined(__AVX2__) assert(PARALLEL_COLS_53 == 16); assert(VREG_INT_COUNT == 8); #else @@ -589,10 +790,13 @@ assert(VREG_INT_COUNT == 4); #endif +//For AVX512 code aligned load/store is set to it's unaligned equivalents +#if !defined(__AVX512F__) /* Note: loads of input even/odd values must be done in a unaligned */ /* fashion. But stores in tmp can be done with aligned store, since */ /* the temporary buffer is properly aligned */ assert((OPJ_SIZE_T)tmp % (sizeof(OPJ_INT32) * VREG_INT_COUNT) == 0); +#endif s1n_0 = LOADU(in_even + 0); s1n_1 = LOADU(in_even + VREG_INT_COUNT); @@ -683,7 +887,10 @@ const OPJ_INT32* in_odd = &tiledp_col[0]; assert(len > 2); -#if __AVX2__ +#if defined(__AVX512F__) + assert(PARALLEL_COLS_53 == 32); + assert(VREG_INT_COUNT == 16); +#elif defined(__AVX2__) assert(PARALLEL_COLS_53 == 16); assert(VREG_INT_COUNT == 8); #else @@ -691,10 +898,13 @@ assert(VREG_INT_COUNT == 4); #endif +//For AVX512 code aligned load/store is set to it's unaligned equivalents +#if !defined(__AVX512F__) /* Note: loads of input even/odd values must be done in a unaligned */ /* fashion. But stores in tmp can be done with aligned store, since */ /* the temporary buffer is properly aligned */ assert((OPJ_SIZE_T)tmp % (sizeof(OPJ_INT32) * VREG_INT_COUNT) == 0); +#endif s1_0 = LOADU(in_even + stride); /* in_odd[0] - ((in_even[0] + s1 + 2) >> 2); */
diff --git a/third_party/libopenjpeg/ht_dec.c b/third_party/libopenjpeg/ht_dec.c index a554b24..2984f56 100644 --- a/third_party/libopenjpeg/ht_dec.c +++ b/third_party/libopenjpeg/ht_dec.c
@@ -901,7 +901,7 @@ * X controls this value. * * Unstuffing prevent sequences that are more than 0xFF7F from appearing - * in the conpressed sequence. So whenever a value of 0xFF is coded, the + * in the compressed sequence. So whenever a value of 0xFF is coded, the * MSB of the next byte is set 0 and must be ignored during decoding. * * Reading can go beyond the end of buffer by up to 3 bytes. @@ -1032,7 +1032,7 @@ //************************************************************************/ /** @brief Allocates T1 buffers * - * @param [in, out] t1 is codeblock cofficients storage + * @param [in, out] t1 is codeblock coefficients storage * @param [in] w is codeblock width * @param [in] h is codeblock height */ @@ -1120,7 +1120,7 @@ /** @brief Decodes one codeblock, processing the cleanup, siginificance * propagation, and magnitude refinement pass * - * @param [in, out] t1 is codeblock cofficients storage + * @param [in, out] t1 is codeblock coefficients storage * @param [in] cblk is codeblock properties * @param [in] orient is the subband to which the codeblock belongs (not needed) * @param [in] roishift is region of interest shift
diff --git a/third_party/libopenjpeg/j2k.c b/third_party/libopenjpeg/j2k.c index 8b077d0..5e9d750 100644 --- a/third_party/libopenjpeg/j2k.c +++ b/third_party/libopenjpeg/j2k.c
@@ -2484,6 +2484,11 @@ ++l_current_tile_param; } + /*Allocate and initialize some elements of codestrem index*/ + if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)) { + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MH; opj_image_comp_header_update(l_image, l_cp); @@ -3657,21 +3662,29 @@ opj_event_mgr_t * p_manager ) { - OPJ_UINT32 l_Ztlm, l_Stlm, l_ST, l_SP, l_tot_num_tp_remaining, l_quotient, - l_Ptlm_size; + OPJ_UINT32 l_Ztlm, l_Stlm, l_ST, l_SP, + l_Ptlm_size, l_entry_size, l_num_tileparts; + OPJ_UINT32 i; + opj_j2k_tlm_tile_part_info_t* l_tile_part_infos; + opj_j2k_tlm_info_t* l_tlm; + /* preconditions */ assert(p_header_data != 00); assert(p_j2k != 00); assert(p_manager != 00); - OPJ_UNUSED(p_j2k); + l_tlm = &(p_j2k->m_specific_param.m_decoder.m_tlm); if (p_header_size < 2) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); + opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker.\n"); return OPJ_FALSE; } p_header_size -= 2; + if (l_tlm->m_is_invalid) { + return OPJ_TRUE; + } + opj_read_bytes(p_header_data, &l_Ztlm, 1); /* Ztlm */ ++p_header_data; @@ -3680,27 +3693,83 @@ ++p_header_data; l_ST = ((l_Stlm >> 4) & 0x3); + if (l_ST == 3) { + l_tlm->m_is_invalid = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, + "opj_j2k_read_tlm(): ST = 3 is invalid.\n"); + return OPJ_TRUE; + } l_SP = (l_Stlm >> 6) & 0x1; l_Ptlm_size = (l_SP + 1) * 2; - l_quotient = l_Ptlm_size + l_ST; + l_entry_size = l_Ptlm_size + l_ST; - l_tot_num_tp_remaining = p_header_size % l_quotient; - - if (l_tot_num_tp_remaining != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); - return OPJ_FALSE; + if ((p_header_size % l_entry_size) != 0) { + l_tlm->m_is_invalid = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, + "opj_j2k_read_tlm(): TLM marker not of expected size.\n"); + return OPJ_TRUE; } - /* FIXME Do not care of this at the moment since only local variables are set here */ - /* - for - (i = 0; i < l_tot_num_tp; ++i) - { - opj_read_bytes(p_header_data,&l_Ttlm_i,l_ST); // Ttlm_i + + l_num_tileparts = p_header_size / l_entry_size; + if (l_num_tileparts == 0) { + /* not totally sure if this is valid... */ + return OPJ_TRUE; + } + + /* Highly unlikely, unless there are gazillions of TLM markers */ + if (l_tlm->m_entries_count > UINT32_MAX - l_num_tileparts || + l_tlm->m_entries_count + l_num_tileparts > UINT32_MAX / sizeof( + opj_j2k_tlm_tile_part_info_t)) { + l_tlm->m_is_invalid = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, + "opj_j2k_read_tlm(): too many TLM markers.\n"); + return OPJ_TRUE; + } + + l_tile_part_infos = (opj_j2k_tlm_tile_part_info_t*)opj_realloc( + l_tlm->m_tile_part_infos, + (l_tlm->m_entries_count + l_num_tileparts) * sizeof( + opj_j2k_tlm_tile_part_info_t)); + if (!l_tile_part_infos) { + l_tlm->m_is_invalid = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, + "opj_j2k_read_tlm(): cannot allocate m_tile_part_infos.\n"); + return OPJ_TRUE; + } + + l_tlm->m_tile_part_infos = l_tile_part_infos; + + for (i = 0; i < l_num_tileparts; ++ i) { + OPJ_UINT32 l_tile_index; + OPJ_UINT32 l_length; + + /* Read Ttlm_i */ + if (l_ST == 0) { + l_tile_index = l_tlm->m_entries_count; + } else { + opj_read_bytes(p_header_data, &l_tile_index, l_ST); p_header_data += l_ST; - opj_read_bytes(p_header_data,&l_Ptlm_i,l_Ptlm_size); // Ptlm_i - p_header_data += l_Ptlm_size; - }*/ + } + + if (l_tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th) { + l_tlm->m_is_invalid = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, + "opj_j2k_read_tlm(): invalid tile number %d\n", + l_tile_index); + return OPJ_TRUE; + } + + /* Read Ptlm_i */ + opj_read_bytes(p_header_data, &l_length, l_Ptlm_size); + p_header_data += l_Ptlm_size; + + l_tile_part_infos[l_tlm->m_entries_count].m_tile_index = + (OPJ_UINT16)l_tile_index; + l_tile_part_infos[l_tlm->m_entries_count].m_length = l_length; + ++l_tlm->m_entries_count; + } + return OPJ_TRUE; } @@ -4583,14 +4652,26 @@ } /* Index */ - if (p_j2k->cstr_index) { + { assert(p_j2k->cstr_index->tile_index != 00); p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tileno = p_j2k->m_current_tile_number; p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno = l_current_part; - if (l_num_parts != 0) { + if (!p_j2k->m_specific_param.m_decoder.m_tlm.m_is_invalid && + l_num_parts > + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].nb_tps) { + opj_event_msg(p_manager, EVT_WARNING, + "SOT marker for tile %u declares more tile-parts than found in TLM marker.", + p_j2k->m_current_tile_number); + p_j2k->m_specific_param.m_decoder.m_tlm.m_is_invalid = OPJ_TRUE; + } + + if (!p_j2k->m_specific_param.m_decoder.m_tlm.m_is_invalid) { + /* do nothing */ + } else if (l_num_parts != 0) { + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].nb_tps = l_num_parts; p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = @@ -4661,33 +4742,6 @@ } - /* FIXME move this onto a separate method to call before reading any SOT, remove part about main_end header, use a index struct inside p_j2k */ - /* if (p_j2k->cstr_info) { - if (l_tcp->first) { - if (tileno == 0) { - p_j2k->cstr_info->main_head_end = p_stream_tell(p_stream) - 13; - } - - p_j2k->cstr_info->tile[tileno].tileno = tileno; - p_j2k->cstr_info->tile[tileno].start_pos = p_stream_tell(p_stream) - 12; - p_j2k->cstr_info->tile[tileno].end_pos = p_j2k->cstr_info->tile[tileno].start_pos + totlen - 1; - p_j2k->cstr_info->tile[tileno].num_tps = numparts; - - if (numparts) { - p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(numparts * sizeof(opj_tp_info_t)); - } - else { - p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(10 * sizeof(opj_tp_info_t)); // Fixme (10) - } - } - else { - p_j2k->cstr_info->tile[tileno].end_pos += totlen; - } - - p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos = p_stream_tell(p_stream) - 12; - p_j2k->cstr_info->tile[tileno].tp[partno].tp_end_pos = - p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos + totlen - 1; - }*/ return OPJ_TRUE; } @@ -5023,7 +5077,7 @@ /* Index */ l_cstr_index = p_j2k->cstr_index; - if (l_cstr_index) { + { OPJ_OFF_T l_current_pos = opj_stream_tell(p_stream) - 2; OPJ_UINT32 l_current_tile_part = @@ -6716,6 +6770,9 @@ opj_j2k_t* j2k = (opj_j2k_t*)p_j2k; if (j2k) { j2k->m_cp.strict = strict; + if (strict) { + j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1; + } } } @@ -8264,7 +8321,14 @@ tccp->qmfbid = parameters->irreversible ? 0 : 1; tccp->qntsty = parameters->irreversible ? J2K_CCP_QNTSTY_SEQNT : J2K_CCP_QNTSTY_NOQNT; - tccp->numgbits = 2; + + if (OPJ_IS_CINEMA(parameters->rsiz) && + parameters->rsiz == OPJ_PROFILE_CINEMA_2K) { + /* From https://github.com/uclouvain/openjpeg/issues/1340 */ + tccp->numgbits = 1; + } else { + tccp->numgbits = 2; + } if ((OPJ_INT32)i == parameters->roi_compno) { tccp->roishift = parameters->roi_shift; @@ -8403,7 +8467,8 @@ if (type == J2K_MS_SOT) { OPJ_UINT32 l_current_tile_part = cstr_index->tile_index[tileno].current_tpsno; - if (cstr_index->tile_index[tileno].tp_index) { + if (cstr_index->tile_index[tileno].tp_index && + l_current_tile_part < cstr_index->tile_index[tileno].nb_tps) { cstr_index->tile_index[tileno].tp_index[l_current_tile_part].start_pos = pos; } @@ -8481,13 +8546,6 @@ /* Copy codestream image information to the output image */ opj_copy_image_header(p_j2k->m_private_image, *p_image); - /*Allocate and initialize some elements of codestrem index*/ - if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)) { - opj_image_destroy(*p_image); - *p_image = NULL; - return OPJ_FALSE; - } - return OPJ_TRUE; } @@ -8839,6 +8897,87 @@ return l_is_valid; } +/** Fill p_j2k->cstr_index->tp_index[].start_pos/end_pos fields from TLM marker segments */ +static void opj_j2k_build_tp_index_from_tlm(opj_j2k_t* p_j2k, + opj_event_mgr_t * p_manager) +{ + opj_j2k_tlm_info_t* l_tlm; + OPJ_UINT32 i; + OPJ_OFF_T l_cur_offset; + + assert(p_j2k->cstr_index->main_head_end > 0); + assert(p_j2k->cstr_index->nb_of_tiles > 0); + assert(p_j2k->cstr_index->tile_index != NULL); + + l_tlm = &(p_j2k->m_specific_param.m_decoder.m_tlm); + + if (l_tlm->m_entries_count == 0) { + l_tlm->m_is_invalid = OPJ_TRUE; + return; + } + + if (l_tlm->m_is_invalid) { + return; + } + + /* Initial pass to count the number of tile-parts per tile */ + for (i = 0; i < l_tlm->m_entries_count; ++i) { + OPJ_UINT32 l_tile_index_no = l_tlm->m_tile_part_infos[i].m_tile_index; + assert(l_tile_index_no < p_j2k->cstr_index->nb_of_tiles); + p_j2k->cstr_index->tile_index[l_tile_index_no].tileno = l_tile_index_no; + ++p_j2k->cstr_index->tile_index[l_tile_index_no].current_nb_tps; + } + + /* Now check that all tiles have at least one tile-part */ + for (i = 0; i < p_j2k->cstr_index->nb_of_tiles; ++i) { + if (p_j2k->cstr_index->tile_index[i].current_nb_tps == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_j2k_build_tp_index_from_tlm(): tile %d has no " + "registered tile-part in TLM marker segments.\n", i); + goto error; + } + } + + /* Final pass to fill p_j2k->cstr_index */ + l_cur_offset = p_j2k->cstr_index->main_head_end; + for (i = 0; i < l_tlm->m_entries_count; ++i) { + OPJ_UINT32 l_tile_index_no = l_tlm->m_tile_part_infos[i].m_tile_index; + opj_tile_index_t* l_tile_index = & + (p_j2k->cstr_index->tile_index[l_tile_index_no]); + if (!l_tile_index->tp_index) { + l_tile_index->tp_index = (opj_tp_index_t *) opj_calloc( + l_tile_index->current_nb_tps, sizeof(opj_tp_index_t)); + if (! l_tile_index->tp_index) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_j2k_build_tp_index_from_tlm(): tile index allocation failed\n"); + goto error; + } + } + + assert(l_tile_index->nb_tps < l_tile_index->current_nb_tps); + l_tile_index->tp_index[l_tile_index->nb_tps].start_pos = l_cur_offset; + /* We don't know how to set the tp_index[].end_header field, but this is not really needed */ + /* If there would be no markers between SOT and SOD, that would be : */ + /* l_tile_index->tp_index[l_tile_index->nb_tps].end_header = l_cur_offset + 12; */ + l_tile_index->tp_index[l_tile_index->nb_tps].end_pos = l_cur_offset + + l_tlm->m_tile_part_infos[i].m_length; + ++l_tile_index->nb_tps; + + l_cur_offset += l_tlm->m_tile_part_infos[i].m_length; + } + + return; + +error: + l_tlm->m_is_invalid = OPJ_TRUE; + for (i = 0; i < l_tlm->m_entries_count; ++i) { + OPJ_UINT32 l_tile_index = l_tlm->m_tile_part_infos[i].m_tile_index; + p_j2k->cstr_index->tile_index[l_tile_index].current_nb_tps = 0; + opj_free(p_j2k->cstr_index->tile_index[l_tile_index].tp_index); + p_j2k->cstr_index->tile_index[l_tile_index].tp_index = NULL; + } +} + static OPJ_BOOL opj_j2k_read_header_procedure(opj_j2k_t *p_j2k, opj_stream_private_t *p_stream, opj_event_mgr_t * p_manager) @@ -9018,6 +9157,9 @@ /* Position of the last element if the main header */ p_j2k->cstr_index->main_head_end = (OPJ_UINT32) opj_stream_tell(p_stream) - 2; + /* Build tile-part index from TLM information */ + opj_j2k_build_tp_index_from_tlm(p_j2k, p_manager); + /* Next step: read a tile-part header */ p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; @@ -9242,6 +9384,12 @@ p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode = 00; p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode = 0; + opj_free(p_j2k->m_specific_param.m_decoder.m_tlm.m_tile_part_infos); + p_j2k->m_specific_param.m_decoder.m_tlm.m_tile_part_infos = NULL; + + opj_free(p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset); + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset = NULL; + } else { if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) { @@ -9593,6 +9741,39 @@ while ((!p_j2k->m_specific_param.m_decoder.m_can_decode) && (l_current_marker != J2K_MS_EOC)) { + if (p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts > 0 && + p_j2k->m_specific_param.m_decoder.m_idx_intersecting_tile_parts < + p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts) { + OPJ_OFF_T next_tp_sot_pos; + + next_tp_sot_pos = + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset[p_j2k->m_specific_param.m_decoder.m_idx_intersecting_tile_parts]; + ++p_j2k->m_specific_param.m_decoder.m_idx_intersecting_tile_parts; + if (!(opj_stream_read_seek(p_stream, + next_tp_sot_pos, + p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); + return OPJ_FALSE; + } + + /* Try to read 2 bytes (the marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes from the buffer as the marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, + 2); + + if (l_current_marker != J2K_MS_SOT) { + opj_event_msg(p_manager, EVT_ERROR, "Did not get expected SOT marker\n"); + return OPJ_FALSE; + } + } + /* Try to read until the Start Of Data is detected */ while (l_current_marker != J2K_MS_SOD) { @@ -9626,7 +9807,13 @@ } /* Why this condition? FIXME */ - if (p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_TPH) { + if ((p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_TPH) && + p_j2k->m_specific_param.m_decoder.m_sot_length != 0) { + if (p_j2k->m_specific_param.m_decoder.m_sot_length < l_marker_size + 2) { + opj_event_msg(p_manager, EVT_ERROR, + "Sot length is less than marker size + marker ID\n"); + return OPJ_FALSE; + } p_j2k->m_specific_param.m_decoder.m_sot_length -= (l_marker_size + 2); } l_marker_size -= 2; /* Subtract the size of the marker ID already read */ @@ -9736,14 +9923,78 @@ if (! opj_j2k_read_sod(p_j2k, p_stream, p_manager)) { return OPJ_FALSE; } + + /* Check if we can use the TLM index to access the next tile-part */ + if (!p_j2k->m_specific_param.m_decoder.m_can_decode && + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec >= 0 && + p_j2k->m_current_tile_number == (OPJ_UINT32) + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec && + !p_j2k->m_specific_param.m_decoder.m_tlm.m_is_invalid && + opj_stream_has_seek(p_stream)) { + l_tcp = p_j2k->m_cp.tcps + p_j2k->m_current_tile_number; + if (l_tcp->m_nb_tile_parts == + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].nb_tps && + (OPJ_UINT32)l_tcp->m_current_tile_part_number + 1 < l_tcp->m_nb_tile_parts) { + const OPJ_OFF_T next_tp_sot_pos = p_j2k->cstr_index->tile_index[ + p_j2k->m_current_tile_number].tp_index[l_tcp->m_current_tile_part_number + + 1].start_pos; + + if (next_tp_sot_pos != opj_stream_tell(p_stream)) { +#if 0 + opj_event_msg(p_manager, EVT_INFO, + "opj_j2k_read_tile_header(tile=%u): seek to tile part %u at %" PRId64 "\n", + p_j2k->m_current_tile_number, + l_tcp->m_current_tile_part_number + 1, + next_tp_sot_pos); +#endif + + if (!(opj_stream_read_seek(p_stream, + next_tp_sot_pos, + p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); + return OPJ_FALSE; + } + } + + /* Try to read 2 bytes (the marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes from the buffer as the marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, + 2); + + if (l_current_marker != J2K_MS_SOT) { + opj_event_msg(p_manager, EVT_ERROR, "Did not get expected SOT marker\n"); + return OPJ_FALSE; + } + + continue; + } + } + if (p_j2k->m_specific_param.m_decoder.m_can_decode && !p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked) { /* Issue 254 */ - OPJ_BOOL l_correction_needed; + OPJ_BOOL l_correction_needed = OPJ_FALSE; p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1; - if (!opj_j2k_need_nb_tile_parts_correction(p_stream, - p_j2k->m_current_tile_number, &l_correction_needed, p_manager)) { + if (p_j2k->m_cp.tcps[p_j2k->m_current_tile_number].m_nb_tile_parts == 1) { + /* Skip opj_j2k_need_nb_tile_parts_correction() if there is + * only a single tile part declared. The + * opj_j2k_need_nb_tile_parts_correction() hack was needed + * for files with 5 declared tileparts (where they were + * actually 6). + * Doing it systematically hurts performance when reading + * Sentinel2 L1C JPEG2000 files as explained in + * https://lists.osgeo.org/pipermail/gdal-dev/2024-November/059805.html + */ + } else if (!opj_j2k_need_nb_tile_parts_correction(p_stream, + p_j2k->m_current_tile_number, &l_correction_needed, p_manager)) { opj_event_msg(p_manager, EVT_ERROR, "opj_j2k_apply_nb_tile_parts_correction error\n"); return OPJ_FALSE; @@ -11335,6 +11586,17 @@ OPJ_UINT32 l_acc_nb_of_tile_part = 0; for (it_tile = 0; it_tile < cstr_index->nb_of_tiles ; it_tile++) { l_acc_nb_of_tile_part += cstr_index->tile_index[it_tile].nb_tps; + + /* To avoid regenerating expected opj_dump results from the test */ + /* suite when there is a TLM marker present */ + if (cstr_index->tile_index[it_tile].nb_tps && + cstr_index->tile_index[it_tile].tp_index && + cstr_index->tile_index[it_tile].tp_index[0].start_pos > 0 && + cstr_index->tile_index[it_tile].tp_index[0].end_header == 0 && + getenv("OJP_DO_NOT_DISPLAY_TILE_INDEX_IF_TLM") != NULL) { + l_acc_nb_of_tile_part = 0; + break; + } } if (l_acc_nb_of_tile_part) { @@ -11700,6 +11962,18 @@ return OPJ_TRUE; } +static int CompareOffT(const void* a, const void* b) +{ + const OPJ_OFF_T offA = *(const OPJ_OFF_T*)a; + const OPJ_OFF_T offB = *(const OPJ_OFF_T*)b; + if (offA < offB) { + return -1; + } + if (offA == offB) { + return 0; + } + return 1; +} static OPJ_BOOL opj_j2k_decode_tiles(opj_j2k_t *p_j2k, opj_stream_private_t *p_stream, @@ -11710,6 +11984,7 @@ OPJ_INT32 l_tile_x0, l_tile_y0, l_tile_x1, l_tile_y1; OPJ_UINT32 l_nb_comps; OPJ_UINT32 nr_tiles = 0; + OPJ_OFF_T end_pos = 0; /* Particular case for whole single tile decoding */ /* We can avoid allocating intermediate tile buffers */ @@ -11732,8 +12007,9 @@ return OPJ_FALSE; } - if (! opj_j2k_decode_tile(p_j2k, l_current_tile_no, NULL, 0, - p_stream, p_manager)) { + if (!l_go_on || + ! opj_j2k_decode_tile(p_j2k, l_current_tile_no, NULL, 0, + p_stream, p_manager)) { opj_event_msg(p_manager, EVT_ERROR, "Failed to decode tile 1/1\n"); return OPJ_FALSE; } @@ -11751,6 +12027,77 @@ return OPJ_TRUE; } + p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts = 0; + p_j2k->m_specific_param.m_decoder.m_idx_intersecting_tile_parts = 0; + opj_free(p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset); + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset = NULL; + + /* If the area to decode only intersects a subset of tiles, and we have + * valid TLM information, then use it to plan the tilepart offsets to + * seek to. + */ + if (!(p_j2k->m_specific_param.m_decoder.m_start_tile_x == 0 && + p_j2k->m_specific_param.m_decoder.m_start_tile_y == 0 && + p_j2k->m_specific_param.m_decoder.m_end_tile_x == p_j2k->m_cp.tw && + p_j2k->m_specific_param.m_decoder.m_end_tile_y == p_j2k->m_cp.th) && + !p_j2k->m_specific_param.m_decoder.m_tlm.m_is_invalid && + opj_stream_has_seek(p_stream)) { + OPJ_UINT32 m_num_intersecting_tile_parts = 0; + + OPJ_UINT32 j; + for (j = 0; j < p_j2k->m_cp.tw * p_j2k->m_cp.th; ++j) { + if (p_j2k->cstr_index->tile_index[j].nb_tps > 0 && + p_j2k->cstr_index->tile_index[j].tp_index[ + p_j2k->cstr_index->tile_index[j].nb_tps - 1].end_pos > end_pos) { + end_pos = p_j2k->cstr_index->tile_index[j].tp_index[ + p_j2k->cstr_index->tile_index[j].nb_tps - 1].end_pos; + } + } + + for (j = p_j2k->m_specific_param.m_decoder.m_start_tile_y; + j < p_j2k->m_specific_param.m_decoder.m_end_tile_y; ++j) { + OPJ_UINT32 i; + for (i = p_j2k->m_specific_param.m_decoder.m_start_tile_x; + i < p_j2k->m_specific_param.m_decoder.m_end_tile_x; ++i) { + const OPJ_UINT32 tile_number = j * p_j2k->m_cp.tw + i; + m_num_intersecting_tile_parts += + p_j2k->cstr_index->tile_index[tile_number].nb_tps; + } + } + + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset = + (OPJ_OFF_T*) + opj_malloc(m_num_intersecting_tile_parts * sizeof(OPJ_OFF_T)); + if (m_num_intersecting_tile_parts > 0 && + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset) { + OPJ_UINT32 idx = 0; + for (j = p_j2k->m_specific_param.m_decoder.m_start_tile_y; + j < p_j2k->m_specific_param.m_decoder.m_end_tile_y; ++j) { + OPJ_UINT32 i; + for (i = p_j2k->m_specific_param.m_decoder.m_start_tile_x; + i < p_j2k->m_specific_param.m_decoder.m_end_tile_x; ++i) { + const OPJ_UINT32 tile_number = j * p_j2k->m_cp.tw + i; + OPJ_UINT32 k; + for (k = 0; k < p_j2k->cstr_index->tile_index[tile_number].nb_tps; ++k) { + const OPJ_OFF_T next_tp_sot_pos = + p_j2k->cstr_index->tile_index[tile_number].tp_index[k].start_pos; + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset[idx] = + next_tp_sot_pos; + ++idx; + } + } + } + + p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts = idx; + + /* Sort by increasing offset */ + qsort(p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset, + p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts, + sizeof(OPJ_OFF_T), + CompareOffT); + } + } + for (;;) { if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 && p_j2k->m_cp.tcps[0].m_data != NULL) { @@ -11810,6 +12157,12 @@ if (++nr_tiles == p_j2k->m_cp.th * p_j2k->m_cp.tw) { break; } + if (p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts > 0 && + p_j2k->m_specific_param.m_decoder.m_idx_intersecting_tile_parts == + p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts) { + opj_stream_seek(p_stream, end_pos + 2, p_manager); + break; + } } if (! opj_j2k_are_all_used_components_decoded(p_j2k, p_manager)) { @@ -11853,12 +12206,6 @@ OPJ_UINT32 l_nb_tiles; OPJ_UINT32 i; - /*Allocate and initialize some elements of codestrem index if not already done*/ - if (!p_j2k->cstr_index->tile_index) { - if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)) { - return OPJ_FALSE; - } - } /* Move into the codestream to the first SOT used to decode the desired tile */ l_tile_no_to_dec = (OPJ_UINT32) p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec; @@ -11873,12 +12220,38 @@ return OPJ_FALSE; } } else { + OPJ_OFF_T sot_pos = + p_j2k->cstr_index->tile_index[l_tile_no_to_dec].tp_index[0].start_pos; + OPJ_UINT32 l_marker; + +#if 0 + opj_event_msg(p_manager, EVT_INFO, + "opj_j2k_decode_one_tile(%u): seek to %" PRId64 "\n", + l_tile_no_to_dec, + sot_pos); +#endif if (!(opj_stream_read_seek(p_stream, - p_j2k->cstr_index->tile_index[l_tile_no_to_dec].tp_index[0].start_pos + 2, + sot_pos, p_manager))) { opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); return OPJ_FALSE; } + + /* Try to read 2 bytes (the marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes from the buffer as the marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, &l_marker, + 2); + + if (l_marker != J2K_MS_SOT) { + opj_event_msg(p_manager, EVT_ERROR, "Did not get expected SOT marker\n"); + return OPJ_FALSE; + } } /* Special case if we have previously read the EOC marker (if the previous tile getted is the last ) */ if (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC) {
diff --git a/third_party/libopenjpeg/j2k.h b/third_party/libopenjpeg/j2k.h index 08dc35a..01baf47 100644 --- a/third_party/libopenjpeg/j2k.h +++ b/third_party/libopenjpeg/j2k.h
@@ -466,6 +466,24 @@ /* <<UniPG */ } opj_cp_t; +/** Entry of a TLM marker segment */ +typedef struct opj_j2k_tlm_tile_part_info { + /** Tile index of the tile part. Ttlmi field */ + OPJ_UINT16 m_tile_index; + /** Length in bytes, from the beginning of the SOT marker to the end of + * the bit stream data for that tile-part. Ptlmi field */ + OPJ_UINT32 m_length; +} opj_j2k_tlm_tile_part_info_t; + +/** Information got from the concatenation of TLM marker semgnets. */ +typedef struct opj_j2k_tlm_info { + /** Number of entries in m_tile_part_infos. */ + OPJ_UINT32 m_entries_count; + /** Array of m_entries_count values. */ + opj_j2k_tlm_tile_part_info_t* m_tile_part_infos; + + OPJ_BOOL m_is_invalid; +} opj_j2k_tlm_info_t; typedef struct opj_j2k_dec { /** locate in which part of the codestream the decoder is (main header, tile header, end) */ @@ -499,6 +517,18 @@ OPJ_UINT32 m_numcomps_to_decode; OPJ_UINT32 *m_comps_indices_to_decode; + opj_j2k_tlm_info_t m_tlm; + + /** Below if used when there's TLM information available and we use + * opj_set_decoded_area() to a subset of all tiles. + */ + /* Current index in m_intersecting_tile_parts_offset[] to seek to */ + OPJ_UINT32 m_idx_intersecting_tile_parts; + /* Number of elements of m_intersecting_tile_parts_offset[] */ + OPJ_UINT32 m_num_intersecting_tile_parts; + /* Start offset of contributing tile parts */ + OPJ_OFF_T* m_intersecting_tile_parts_offset; + /** to tell that a tile can be decoded. */ OPJ_BITFIELD m_can_decode : 1; OPJ_BITFIELD m_discard_tiles : 1;
diff --git a/third_party/libopenjpeg/jp2.c b/third_party/libopenjpeg/jp2.c index d69178b..6b4d5db 100644 --- a/third_party/libopenjpeg/jp2.c +++ b/third_party/libopenjpeg/jp2.c
@@ -2010,12 +2010,16 @@ jp2->enumcs = 0; } else { jp2->meth = 1; - if (image->color_space == 1) { + if (image->color_space == OPJ_CLRSPC_SRGB) { jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2-1 */ - } else if (image->color_space == 2) { - jp2->enumcs = 17; /* greyscale */ - } else if (image->color_space == 3) { + } else if (image->color_space == OPJ_CLRSPC_GRAY) { + jp2->enumcs = 17; + } else if (image->color_space == OPJ_CLRSPC_SYCC) { jp2->enumcs = 18; /* YUV */ + } else if (image->color_space == OPJ_CLRSPC_EYCC) { + jp2->enumcs = 24; + } else if (image->color_space == OPJ_CLRSPC_CMYK) { + jp2->enumcs = 12; } }
diff --git a/third_party/libopenjpeg/openjpeg.h b/third_party/libopenjpeg/openjpeg.h index 67d168b..59abd32 100644 --- a/third_party/libopenjpeg/openjpeg.h +++ b/third_party/libopenjpeg/openjpeg.h
@@ -546,7 +546,7 @@ } opj_cparameters_t; #define OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG 0x0001 -#define OPJ_DPARAMETERS_DUMP_FLAG 0x0002 +#define OPJ_DPARAMETERS_DUMP_FLAG 0x0002 /** * Decompression parameters @@ -772,7 +772,7 @@ OPJ_OFF_T end_ph_pos; /** packet end position */ OPJ_OFF_T end_pos; - /** packet distorsion */ + /** packet distortion */ double disto; } opj_packet_info_t; @@ -1348,9 +1348,13 @@ opj_dparameters_t *parameters); /** - * Set strict decoding parameter for this decoder. If strict decoding is enabled, partial bit - * streams will fail to decode. If strict decoding is disabled, the decoder will decode partial - * bitstreams as much as possible without erroring + * Set strict decoding parameter for this decoder. + * If strict decoding is enabled, partial bit streams will fail to decode, and + * the check for invalid TPSOT values added in https://github.com/uclouvain/openjpeg/pull/514 + * will be disabled. + * If strict decoding is disabled, the decoder will decode partial + * bitstreams as much as possible without erroring, and the TPSOT fixing logic + * will be enabled. * * @param p_codec decompressor handler * @param strict OPJ_TRUE to enable strict decoding, OPJ_FALSE to disable
diff --git a/third_party/libopenjpeg/opj_common.h b/third_party/libopenjpeg/opj_common.h index ee8adf4..2923a35 100644 --- a/third_party/libopenjpeg/opj_common.h +++ b/third_party/libopenjpeg/opj_common.h
@@ -28,8 +28,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OPJ_COMMMON_H -#define OPJ_COMMMON_H +#ifndef OPJ_COMMON_H +#define OPJ_COMMON_H /* ========================================================== @@ -44,4 +44,4 @@ #define OPJ_COMP_PARAM_DEFAULT_PROG_ORDER OPJ_LRCP #define OPJ_COMP_PARAM_DEFAULT_NUMRESOLUTION 6 -#endif /* OPJ_COMMMON_H */ +#endif /* OPJ_COMMON_H */
diff --git a/third_party/libopenjpeg/opj_config.h b/third_party/libopenjpeg/opj_config.h index b0c616f..5aefbfe 100644 --- a/third_party/libopenjpeg/opj_config.h +++ b/third_party/libopenjpeg/opj_config.h
@@ -13,4 +13,4 @@ /* Version number. */ #define OPJ_VERSION_MAJOR 2 #define OPJ_VERSION_MINOR 5 -#define OPJ_VERSION_BUILD 2 +#define OPJ_VERSION_BUILD 3
diff --git a/third_party/libopenjpeg/opj_config_private.h b/third_party/libopenjpeg/opj_config_private.h index 85a2969..74a8845 100644 --- a/third_party/libopenjpeg/opj_config_private.h +++ b/third_party/libopenjpeg/opj_config_private.h
@@ -7,7 +7,7 @@ /* create opj_config_private.h for CMake */ #define OPJ_HAVE_INTTYPES_H 1 -#define OPJ_PACKAGE_VERSION "2.5.2" +#define OPJ_PACKAGE_VERSION "2.5.3" /* Not used by openjp2*/ /*#define HAVE_MEMORY_H 1*/
diff --git a/third_party/libopenjpeg/t1.c b/third_party/libopenjpeg/t1.c index ecc3355..98dce47 100644 --- a/third_party/libopenjpeg/t1.c +++ b/third_party/libopenjpeg/t1.c
@@ -47,6 +47,9 @@ #ifdef __SSE2__ #include <emmintrin.h> #endif +#if (defined(__AVX2__) || defined(__AVX512F__)) +#include <immintrin.h> +#endif #if defined(__GNUC__) #pragma GCC poison malloc calloc realloc free @@ -1796,6 +1799,39 @@ OPJ_INT32* OPJ_RESTRICT tiledp = &tilec->data[(OPJ_SIZE_T)y * tile_w + (OPJ_SIZE_T)x]; for (j = 0; j < cblk_h; ++j) { + //positive -> round down aka. (83)/2 = 41.5 -> 41 + //negative -> round up aka. (-83)/2 = -41.5 -> -41 +#if defined(__AVX512F__) + OPJ_INT32* ptr_in = datap + (j * cblk_w); + OPJ_INT32* ptr_out = tiledp + (j * (OPJ_SIZE_T)tile_w); + for (i = 0; i < cblk_w / 16; ++i) { + __m512i in_avx = _mm512_loadu_si512((__m512i*)(ptr_in)); + const __m512i add_avx = _mm512_srli_epi32(in_avx, 31); + in_avx = _mm512_add_epi32(in_avx, add_avx); + _mm512_storeu_si512((__m512i*)(ptr_out), _mm512_srai_epi32(in_avx, 1)); + ptr_in += 16; + ptr_out += 16; + } + + for (i = 0; i < cblk_w % 16; ++i) { + ptr_out[i] = ptr_in[i] / 2; + } +#elif defined(__AVX2__) + OPJ_INT32* ptr_in = datap + (j * cblk_w); + OPJ_INT32* ptr_out = tiledp + (j * (OPJ_SIZE_T)tile_w); + for (i = 0; i < cblk_w / 8; ++i) { + __m256i in_avx = _mm256_loadu_si256((__m256i*)(ptr_in)); + const __m256i add_avx = _mm256_srli_epi32(in_avx, 31); + in_avx = _mm256_add_epi32(in_avx, add_avx); + _mm256_storeu_si256((__m256i*)(ptr_out), _mm256_srai_epi32(in_avx, 1)); + ptr_in += 8; + ptr_out += 8; + } + + for (i = 0; i < cblk_w % 8; ++i) { + ptr_out[i] = ptr_in[i] / 2; + } +#else i = 0; for (; i < (cblk_w & ~(OPJ_UINT32)3U); i += 4U) { OPJ_INT32 tmp0 = datap[(j * cblk_w) + i + 0U]; @@ -1811,6 +1847,7 @@ OPJ_INT32 tmp = datap[(j * cblk_w) + i]; ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i] = tmp / 2; } +#endif } } else { /* if (tccp->qmfbid == 0) */ const float stepsize = 0.5f * band->stepsize; @@ -2130,7 +2167,7 @@ opj_mutex_lock(p_manager_mutex); } opj_event_msg(p_manager, EVT_WARNING, - "PTERM check failure: %d synthetized 0xFF markers read\n", + "PTERM check failure: %d synthesized 0xFF markers read\n", mqc->end_of_byte_stream_counter); if (p_manager_mutex) { opj_mutex_unlock(p_manager_mutex); @@ -2233,6 +2270,111 @@ OPJ_UINT32* OPJ_RESTRICT t1data = (OPJ_UINT32*) t1->data; /* Change from "natural" order to "zigzag" order of T1 passes */ for (j = 0; j < (cblk_h & ~3U); j += 4) { +#if defined(__AVX512F__) + const __m512i perm1 = _mm512_setr_epi64(2, 3, 10, 11, 4, 5, 12, 13); + const __m512i perm2 = _mm512_setr_epi64(6, 7, 14, 15, 0, 0, 0, 0); + OPJ_UINT32* ptr = tiledp_u; + for (i = 0; i < cblk_w / 16; ++i) { + // INPUT OUTPUT + // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00 10 20 30 01 11 21 31 02 12 22 32 03 13 23 33 + // 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 04 14 24 34 05 15 25 35 06 16 26 36 07 17 27 37 + // 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 08 18 28 38 09 19 29 39 0A 1A 2A 3A 0B 1B 2B 3B + // 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 0C 1C 2C 3C 0D 1D 2D 3D 0E 1E 2E 3E 0F 1F 2F 3F + __m512i in1 = _mm512_slli_epi32(_mm512_loadu_si512((__m512i*)(ptr + + (j + 0) * tile_w)), T1_NMSEDEC_FRACBITS); + __m512i in2 = _mm512_slli_epi32(_mm512_loadu_si512((__m512i*)(ptr + + (j + 1) * tile_w)), T1_NMSEDEC_FRACBITS); + __m512i in3 = _mm512_slli_epi32(_mm512_loadu_si512((__m512i*)(ptr + + (j + 2) * tile_w)), T1_NMSEDEC_FRACBITS); + __m512i in4 = _mm512_slli_epi32(_mm512_loadu_si512((__m512i*)(ptr + + (j + 3) * tile_w)), T1_NMSEDEC_FRACBITS); + + __m512i tmp1 = _mm512_unpacklo_epi32(in1, in2); + __m512i tmp2 = _mm512_unpacklo_epi32(in3, in4); + __m512i tmp3 = _mm512_unpackhi_epi32(in1, in2); + __m512i tmp4 = _mm512_unpackhi_epi32(in3, in4); + + in1 = _mm512_unpacklo_epi64(tmp1, tmp2); + in2 = _mm512_unpacklo_epi64(tmp3, tmp4); + in3 = _mm512_unpackhi_epi64(tmp1, tmp2); + in4 = _mm512_unpackhi_epi64(tmp3, tmp4); + + _mm_storeu_si128((__m128i*)(t1data + 0), _mm512_castsi512_si128(in1)); + _mm_storeu_si128((__m128i*)(t1data + 4), _mm512_castsi512_si128(in3)); + _mm_storeu_si128((__m128i*)(t1data + 8), _mm512_castsi512_si128(in2)); + _mm_storeu_si128((__m128i*)(t1data + 12), _mm512_castsi512_si128(in4)); + + tmp1 = _mm512_permutex2var_epi64(in1, perm1, in3); + tmp2 = _mm512_permutex2var_epi64(in2, perm1, in4); + + _mm256_storeu_si256((__m256i*)(t1data + 16), _mm512_castsi512_si256(tmp1)); + _mm256_storeu_si256((__m256i*)(t1data + 24), _mm512_castsi512_si256(tmp2)); + _mm256_storeu_si256((__m256i*)(t1data + 32), _mm512_extracti64x4_epi64(tmp1, + 0x1)); + _mm256_storeu_si256((__m256i*)(t1data + 40), _mm512_extracti64x4_epi64(tmp2, + 0x1)); + _mm256_storeu_si256((__m256i*)(t1data + 48), + _mm512_castsi512_si256(_mm512_permutex2var_epi64(in1, perm2, in3))); + _mm256_storeu_si256((__m256i*)(t1data + 56), + _mm512_castsi512_si256(_mm512_permutex2var_epi64(in2, perm2, in4))); + t1data += 64; + ptr += 16; + } + for (i = 0; i < cblk_w % 16; ++i) { + t1data[0] = ptr[(j + 0) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[1] = ptr[(j + 1) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[2] = ptr[(j + 2) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[3] = ptr[(j + 3) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data += 4; + ptr += 1; + } +#elif defined(__AVX2__) + OPJ_UINT32* ptr = tiledp_u; + for (i = 0; i < cblk_w / 8; ++i) { + // INPUT OUTPUT + // 00 01 02 03 04 05 06 07 00 10 20 30 01 11 21 31 + // 10 11 12 13 14 15 16 17 02 12 22 32 03 13 23 33 + // 20 21 22 23 24 25 26 27 04 14 24 34 05 15 25 35 + // 30 31 32 33 34 35 36 37 06 16 26 36 07 17 27 37 + __m256i in1 = _mm256_slli_epi32(_mm256_loadu_si256((__m256i*)(ptr + + (j + 0) * tile_w)), T1_NMSEDEC_FRACBITS); + __m256i in2 = _mm256_slli_epi32(_mm256_loadu_si256((__m256i*)(ptr + + (j + 1) * tile_w)), T1_NMSEDEC_FRACBITS); + __m256i in3 = _mm256_slli_epi32(_mm256_loadu_si256((__m256i*)(ptr + + (j + 2) * tile_w)), T1_NMSEDEC_FRACBITS); + __m256i in4 = _mm256_slli_epi32(_mm256_loadu_si256((__m256i*)(ptr + + (j + 3) * tile_w)), T1_NMSEDEC_FRACBITS); + + __m256i tmp1 = _mm256_unpacklo_epi32(in1, in2); + __m256i tmp2 = _mm256_unpacklo_epi32(in3, in4); + __m256i tmp3 = _mm256_unpackhi_epi32(in1, in2); + __m256i tmp4 = _mm256_unpackhi_epi32(in3, in4); + + in1 = _mm256_unpacklo_epi64(tmp1, tmp2); + in2 = _mm256_unpacklo_epi64(tmp3, tmp4); + in3 = _mm256_unpackhi_epi64(tmp1, tmp2); + in4 = _mm256_unpackhi_epi64(tmp3, tmp4); + + _mm_storeu_si128((__m128i*)(t1data + 0), _mm256_castsi256_si128(in1)); + _mm_storeu_si128((__m128i*)(t1data + 4), _mm256_castsi256_si128(in3)); + _mm_storeu_si128((__m128i*)(t1data + 8), _mm256_castsi256_si128(in2)); + _mm_storeu_si128((__m128i*)(t1data + 12), _mm256_castsi256_si128(in4)); + _mm256_storeu_si256((__m256i*)(t1data + 16), _mm256_permute2x128_si256(in1, in3, + 0x31)); + _mm256_storeu_si256((__m256i*)(t1data + 24), _mm256_permute2x128_si256(in2, in4, + 0x31)); + t1data += 32; + ptr += 8; + } + for (i = 0; i < cblk_w % 8; ++i) { + t1data[0] = ptr[(j + 0) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[1] = ptr[(j + 1) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[2] = ptr[(j + 2) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[3] = ptr[(j + 3) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data += 4; + ptr += 1; + } +#else for (i = 0; i < cblk_w; ++i) { t1data[0] = tiledp_u[(j + 0) * tile_w + i] << T1_NMSEDEC_FRACBITS; t1data[1] = tiledp_u[(j + 1) * tile_w + i] << T1_NMSEDEC_FRACBITS; @@ -2240,6 +2382,7 @@ t1data[3] = tiledp_u[(j + 3) * tile_w + i] << T1_NMSEDEC_FRACBITS; t1data += 4; } +#endif } if (j < cblk_h) { for (i = 0; i < cblk_w; ++i) {
diff --git a/third_party/libopenjpeg/t2.c b/third_party/libopenjpeg/t2.c index 657ded7..4e8cf60 100644 --- a/third_party/libopenjpeg/t2.c +++ b/third_party/libopenjpeg/t2.c
@@ -1111,6 +1111,7 @@ /* SOP markers */ if (p_tcp->csty & J2K_CP_CSTY_SOP) { + /* SOP markers are allowed (i.e. optional), just warn */ if (p_max_length < 6) { opj_event_msg(p_manager, EVT_WARNING, "Not enough space for expected SOP marker\n"); @@ -1163,12 +1164,15 @@ /* EPH markers */ if (p_tcp->csty & J2K_CP_CSTY_EPH) { + /* EPH markers are required */ if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - *l_header_data_start)) < 2U) { - opj_event_msg(p_manager, EVT_WARNING, - "Not enough space for expected EPH marker\n"); + opj_event_msg(p_manager, EVT_ERROR, + "Not enough space for required EPH marker\n"); + return OPJ_FALSE; } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { - opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n"); + opj_event_msg(p_manager, EVT_ERROR, "Expected EPH marker\n"); + return OPJ_FALSE; } else { l_header_data += 2; } @@ -1340,12 +1344,15 @@ /* EPH markers */ if (p_tcp->csty & J2K_CP_CSTY_EPH) { + /* EPH markers are required */ if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - *l_header_data_start)) < 2U) { - opj_event_msg(p_manager, EVT_WARNING, - "Not enough space for expected EPH marker\n"); + opj_event_msg(p_manager, EVT_ERROR, + "Not enough space for required EPH marker\n"); + return OPJ_FALSE; } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { - opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n"); + opj_event_msg(p_manager, EVT_ERROR, "Expected EPH marker\n"); + return OPJ_FALSE; } else { l_header_data += 2; } @@ -1353,6 +1360,9 @@ l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start); JAS_FPRINTF(stderr, "hdrlen=%d \n", l_header_length); + if (!l_header_length) { + return OPJ_FALSE; + } JAS_FPRINTF(stderr, "packet body\n"); *l_modified_length_ptr -= l_header_length; *l_header_data_start += l_header_length;
diff --git a/third_party/libopenjpeg/tcd.c b/third_party/libopenjpeg/tcd.c index 981d90c..0957b6e 100644 --- a/third_party/libopenjpeg/tcd.c +++ b/third_party/libopenjpeg/tcd.c
@@ -243,7 +243,7 @@ /* ----------------------------------------------------------------------- */ /** Returns OPJ_TRUE if the layer allocation is unchanged w.r.t to the previous - * invokation with a different threshold */ + * invocation with a different threshold */ static OPJ_BOOL opj_tcd_makelayer(opj_tcd_t *tcd, OPJ_UINT32 layno, @@ -2869,12 +2869,12 @@ return intersects; } -/** Returns whether a tile componenent is fully decoded, taking into account +/** Returns whether a tile component is fully decoded, taking into account * p_tcd->win_* members. * * @param p_tcd TCD handle. * @param compno Component number - * @return OPJ_TRUE whether the tile componenent is fully decoded + * @return OPJ_TRUE whether the tile component is fully decoded */ static OPJ_BOOL opj_tcd_is_whole_tilecomp_decoding(opj_tcd_t *p_tcd, OPJ_UINT32 compno)
diff --git a/third_party/libopenjpeg/tcd.h b/third_party/libopenjpeg/tcd.h index 4ab2271..3371b08 100644 --- a/third_party/libopenjpeg/tcd.h +++ b/third_party/libopenjpeg/tcd.h
@@ -313,7 +313,7 @@ /** Dump the content of a tcd structure */ -/*void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t *img);*/ /* TODO MSD shoul use the new v2 structures */ +/*void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t *img);*/ /* TODO MSD should use the new v2 structures */ /** Create a new TCD handle @@ -444,7 +444,7 @@ OPJ_SIZE_T opj_tcd_get_encoder_input_buffer_size(opj_tcd_t *p_tcd); /** - * Initialize the tile coder and may reuse some meory. + * Initialize the tile coder and may reuse some memory. * * @param p_tcd TCD handle. * @param p_tile_no current tile index to encode. @@ -492,7 +492,7 @@ * @param y0 Upper left y in subband coordinates * @param x1 Lower right x in subband coordinates * @param y1 Lower right y in subband coordinates - * @return OPJ_TRUE whether the sub-band region contributs to the area of + * @return OPJ_TRUE whether the sub-band region contributes to the area of * interest. */ OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd,