diff options
13 files changed, 485 insertions, 139 deletions
diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/bio.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/bio.c index 5d49580178..3ce6492753 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/bio.c +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/bio.c @@ -81,7 +81,7 @@ static OPJ_BOOL opj_bio_bytein(opj_bio_t *bio); OPJ_BOOL opj_bio_byteout(opj_bio_t *bio) { bio->buf = (bio->buf << 8) & 0xffff; bio->ct = bio->buf == 0xff00 ? 7 : 8; - if (bio->bp >= bio->end) { + if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) { return OPJ_FALSE; } *bio->bp++ = (OPJ_BYTE)(bio->buf >> 8); @@ -91,7 +91,7 @@ OPJ_BOOL opj_bio_byteout(opj_bio_t *bio) { OPJ_BOOL opj_bio_bytein(opj_bio_t *bio) { bio->buf = (bio->buf << 8) & 0xffff; bio->ct = bio->buf == 0xff00 ? 7 : 8; - if (bio->bp >= bio->end) { + if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) { return OPJ_FALSE; } bio->buf |= *bio->bp++; @@ -169,12 +169,10 @@ OPJ_UINT32 opj_bio_read(opj_bio_t *bio, OPJ_UINT32 n) { } OPJ_BOOL opj_bio_flush(opj_bio_t *bio) { - bio->ct = 0; if (! opj_bio_byteout(bio)) { return OPJ_FALSE; } if (bio->ct == 7) { - bio->ct = 0; if (! opj_bio_byteout(bio)) { return OPJ_FALSE; } @@ -183,12 +181,11 @@ OPJ_BOOL opj_bio_flush(opj_bio_t *bio) { } OPJ_BOOL opj_bio_inalign(opj_bio_t *bio) { - bio->ct = 0; if ((bio->buf & 0xff) == 0xff) { if (! opj_bio_bytein(bio)) { return OPJ_FALSE; } - bio->ct = 0; } + bio->ct = 0; return OPJ_TRUE; } diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/j2k.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/j2k.c index 4a1c103f4b..f944ad1afb 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/j2k.c +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/j2k.c @@ -1919,7 +1919,7 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, OPJ_UINT32 l_nb_comp_remain; OPJ_UINT32 l_remaining_size; OPJ_UINT32 l_nb_tiles; - OPJ_UINT32 l_tmp; + OPJ_UINT32 l_tmp, l_tx1, l_ty1; opj_image_t *l_image = 00; opj_cp_t *l_cp = 00; opj_image_comp_t * l_img_comp = 00; @@ -1981,8 +1981,9 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, } /* testcase 4035.pdf.SIGSEGV.d8b.3375 */ - if (l_image->x0 > l_image->x1 || l_image->y0 > l_image->y1) { - opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: negative image size (%d x %d)\n", l_image->x1 - l_image->x0, l_image->y1 - l_image->y0); + /* testcase issue427-null-image-size.jp2 */ + if ((l_image->x0 >= l_image->x1) || (l_image->y0 >= l_image->y1)) { + opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: negative or zero image size (%d x %d)\n", l_image->x1 - l_image->x0, l_image->y1 - l_image->y0); return OPJ_FALSE; } /* testcase 2539.pdf.SIGFPE.706.1712 (also 3622.pdf.SIGFPE.706.2916 and 4008.pdf.SIGFPE.706.3345 and maybe more) */ @@ -1997,6 +1998,20 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, return OPJ_FALSE; } + /* testcase issue427-illegal-tile-offset.jp2 */ + l_tx1 = l_cp->tx0 + l_cp->tdx; + if (l_tx1 < l_cp->tx0) { /* manage overflow */ + l_tx1 = 0xFFFFFFFFU; + } + l_ty1 = l_cp->ty0 + l_cp->tdy; + if (l_ty1 < l_cp->ty0) { /* manage overflow */ + l_ty1 = 0xFFFFFFFFU; + } + if ((l_cp->tx0 > l_image->x0) || (l_cp->ty0 > l_image->y0) || (l_tx1 <= l_image->x0) || (l_ty1 <= l_image->y0) ) { + opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: illegal tile offset\n"); + return OPJ_FALSE; + } + #ifdef USE_JPWL if (l_cp->correct) { /* if JPWL is on, we check whether TX errors have damaged @@ -5221,6 +5236,7 @@ static OPJ_BOOL opj_j2k_read_mct ( opj_j2k_t *p_j2k, } l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; + ++l_tcp->m_nb_mct_records; } if (l_mct_data->m_data) { @@ -5249,7 +5265,6 @@ static OPJ_BOOL opj_j2k_read_mct ( opj_j2k_t *p_j2k, memcpy(l_mct_data->m_data,p_header_data,p_header_size); l_mct_data->m_data_size = p_header_size; - ++l_tcp->m_nb_mct_records; return OPJ_TRUE; } @@ -6571,7 +6586,7 @@ OPJ_BOOL opj_j2k_setup_encoder( opj_j2k_t *p_j2k, } } else { - if(tcp->mct==1 && image->numcomps == 3) { /* RGB->YCC MCT is enabled */ + if(tcp->mct==1 && image->numcomps >= 3) { /* RGB->YCC MCT is enabled */ if ((image->comps[0].dx != image->comps[1].dx) || (image->comps[0].dx != image->comps[2].dx) || (image->comps[0].dy != image->comps[1].dy) || @@ -7059,21 +7074,20 @@ OPJ_BOOL opj_j2k_encoding_validation ( opj_j2k_t * p_j2k, /* make sure a validation list is present */ l_is_valid &= (p_j2k->m_validation_list != 00); - /* ISO 15444-1:2004 states between 1 & 33 (0 -> 32) */ - /* 33 (32) would always fail the 2 checks below (if a cast to 64bits was done) */ - /* 32 (31) would always fail the 2 checks below (if a cast to 64bits was done) */ - /* FIXME Shall we change OPJ_J2K_MAXRLVLS to 31 ? */ - if ((p_j2k->m_cp.tcps->tccps->numresolutions <= 0) || (p_j2k->m_cp.tcps->tccps->numresolutions > 31)) { + /* ISO 15444-1:2004 states between 1 & 33 (0 -> 32) */ + /* 33 (32) would always fail the check below (if a cast to 64bits was done) */ + /* FIXME Shall we change OPJ_J2K_MAXRLVLS to 32 ? */ + if ((p_j2k->m_cp.tcps->tccps->numresolutions <= 0) || (p_j2k->m_cp.tcps->tccps->numresolutions > 32)) { opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n"); return OPJ_FALSE; } - if ((p_j2k->m_cp.tdx) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) { + if ((p_j2k->m_cp.tdx) < (OPJ_UINT32) (1 << (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) { opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n"); return OPJ_FALSE; } - if ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) { + if ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) { opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n"); return OPJ_FALSE; } @@ -7151,7 +7165,7 @@ OPJ_BOOL opj_j2k_read_header_procedure( opj_j2k_t *p_j2k, /* Check if the current marker ID is valid */ if (l_current_marker < 0xff00) { - opj_event_msg(p_manager, EVT_ERROR, "We expected read a marker ID (0xff--) instead of %.8x\n", l_current_marker); + opj_event_msg(p_manager, EVT_ERROR, "A marker ID was expected (0xff--) instead of %.8x\n", l_current_marker); return OPJ_FALSE; } @@ -9776,7 +9790,7 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k, assert(p_j2k != 00); assert(p_stream != 00); assert(p_manager != 00); - + p_tcd = p_j2k->m_tcd; l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/jp2.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/jp2.c index 1830c11a19..aafbe199d6 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/jp2.c +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/jp2.c @@ -706,7 +706,7 @@ static OPJ_BYTE * opj_jp2_write_cdef(opj_jp2_t *jp2, OPJ_UINT32 * p_nb_bytes_wri assert(jp2->color.jp2_cdef->info != 00); assert(jp2->color.jp2_cdef->n > 0U); - l_cdef_size += 6 * jp2->color.jp2_cdef->n; + l_cdef_size += 6U * jp2->color.jp2_cdef->n; l_cdef_data = (OPJ_BYTE *) opj_malloc(l_cdef_size); if (l_cdef_data == 00) { @@ -714,7 +714,7 @@ static OPJ_BYTE * opj_jp2_write_cdef(opj_jp2_t *jp2, OPJ_UINT32 * p_nb_bytes_wri } l_current_cdef_ptr = l_cdef_data; - + opj_write_bytes(l_current_cdef_ptr,l_cdef_size,4); /* write box size */ l_current_cdef_ptr += 4; @@ -1184,16 +1184,16 @@ void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color) { opj_jp2_cdef_info_t *info; OPJ_UINT16 i, n, cn, asoc, acn; - + info = color->jp2_cdef->info; n = color->jp2_cdef->n; - + for(i = 0; i < n; ++i) { /* WATCH: acn = asoc - 1 ! */ asoc = info[i].asoc; cn = info[i].cn; - + if( cn >= image->numcomps) { fprintf(stderr, "cn=%d, numcomps=%d\n", cn, image->numcomps); @@ -1204,26 +1204,26 @@ void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color) image->comps[cn].alpha = info[i].typ; continue; } - + acn = (OPJ_UINT16)(asoc - 1); if( acn >= image->numcomps ) { fprintf(stderr, "acn=%d, numcomps=%d\n", acn, image->numcomps); continue; } - + /* Swap only if color channel */ if((cn != acn) && (info[i].typ == 0)) { opj_image_comp_t saved; OPJ_UINT16 j; - + memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t)); memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t)); memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t)); - + /* Swap channels in following channel definitions, don't bother with j <= i that are already processed */ - for (j = i + 1; j < n ; ++j) + for (j = (OPJ_UINT16)(i + 1U); j < n ; ++j) { if (info[j].cn == cn) { info[j].cn = acn; @@ -1234,14 +1234,14 @@ void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color) /* asoc is related to color index. Do not update. */ } } - + image->comps[cn].alpha = info[i].typ; } - + if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info); - + opj_free(color->jp2_cdef); color->jp2_cdef = NULL; - + }/* jp2_apply_cdef() */ OPJ_BOOL opj_jp2_read_cdef( opj_jp2_t * jp2, @@ -1487,7 +1487,7 @@ OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2, l_writers[l_nb_pass].handler = opj_jp2_write_cdef; l_nb_pass++; } - + /* write box header */ /* write JP2H type */ opj_write_bytes(l_jp2h_data+4,JP2_JP2H,4); @@ -1693,7 +1693,7 @@ OPJ_BOOL opj_jp2_setup_encoder( opj_jp2_t *jp2, OPJ_UINT32 alpha_count; OPJ_UINT32 color_channels = 0U; OPJ_UINT32 alpha_channel = 0U; - + if(!jp2 || !parameters || !image) return OPJ_FALSE; @@ -1969,7 +1969,7 @@ OPJ_BOOL opj_jp2_default_validation ( opj_jp2_t * jp2, l_is_valid &= (jp2->w > 0); /* precision */ for (i = 0; i < jp2->numcomps; ++i) { - l_is_valid &= (jp2->comps[i].bpcc > 0); + l_is_valid &= ((jp2->comps[i].bpcc & 0x7FU) < 38U); /* 0 is valid, ignore sign for check */ } /* METH */ @@ -2066,6 +2066,16 @@ OPJ_BOOL opj_jp2_read_header_procedure( opj_jp2_t *jp2, } } else { + if (!(jp2->jp2_state & JP2_STATE_SIGNATURE)) { + opj_event_msg(p_manager, EVT_ERROR, "Malformed JP2 file format: first box must be JPEG 2000 signature box\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + if (!(jp2->jp2_state & JP2_STATE_FILE_TYPE)) { + opj_event_msg(p_manager, EVT_ERROR, "Malformed JP2 file format: second box must be file type box\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } jp2->jp2_state |= JP2_STATE_UNKNOWN; if (opj_stream_skip(stream,l_current_data_size,p_manager) != l_current_data_size) { opj_event_msg(p_manager, EVT_ERROR, "Problem with skipping JPEG2000 box, stream error\n"); @@ -2719,7 +2729,7 @@ OPJ_BOOL opj_jp2_get_tile( opj_jp2_t *p_jp2, else opj_jp2_apply_pclr(p_image, &(p_jp2->color)); } - + /* Apply the color space if needed */ if(p_jp2->color.jp2_cdef) { opj_jp2_apply_cdef(p_image, &(p_jp2->color)); diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/mct.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/mct.c index 60ee0969d5..a0da099660 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/mct.c +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/mct.c @@ -40,6 +40,12 @@ #ifdef __SSE__ #include <xmmintrin.h> #endif +#ifdef __SSE2__ +#include <emmintrin.h> +#endif +#ifdef __SSE4_1__ +#include <smmintrin.h> +#endif #include "opj_includes.h" @@ -66,14 +72,33 @@ const OPJ_FLOAT64 * opj_mct_get_mct_norms_real () /* <summary> */ /* Foward reversible MCT. */ /* </summary> */ +#ifdef __SSE2__ void opj_mct_encode( OPJ_INT32* restrict c0, OPJ_INT32* restrict c1, OPJ_INT32* restrict c2, OPJ_UINT32 n) { - OPJ_UINT32 i; - for(i = 0; i < n; ++i) { + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + + for(i = 0; i < (len & ~3U); i += 4) { + __m128i y, u, v; + __m128i r = _mm_load_si128((const __m128i *)&(c0[i])); + __m128i g = _mm_load_si128((const __m128i *)&(c1[i])); + __m128i b = _mm_load_si128((const __m128i *)&(c2[i])); + y = _mm_add_epi32(g, g); + y = _mm_add_epi32(y, b); + y = _mm_add_epi32(y, r); + y = _mm_srai_epi32(y, 2); + u = _mm_sub_epi32(b, g); + v = _mm_sub_epi32(r, g); + _mm_store_si128((__m128i *)&(c0[i]), y); + _mm_store_si128((__m128i *)&(c1[i]), u); + _mm_store_si128((__m128i *)&(c2[i]), v); + } + + for(; i < len; ++i) { OPJ_INT32 r = c0[i]; OPJ_INT32 g = c1[i]; OPJ_INT32 b = c2[i]; @@ -85,10 +110,69 @@ void opj_mct_encode( c2[i] = v; } } +#else +void opj_mct_encode( + OPJ_INT32* restrict c0, + OPJ_INT32* restrict c1, + OPJ_INT32* restrict c2, + OPJ_UINT32 n) +{ + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + + for(i = 0; i < len; ++i) { + OPJ_INT32 r = c0[i]; + OPJ_INT32 g = c1[i]; + OPJ_INT32 b = c2[i]; + OPJ_INT32 y = (r + (g * 2) + b) >> 2; + OPJ_INT32 u = b - g; + OPJ_INT32 v = r - g; + c0[i] = y; + c1[i] = u; + c2[i] = v; + } +} +#endif /* <summary> */ /* Inverse reversible MCT. */ /* </summary> */ +#ifdef __SSE2__ +void opj_mct_decode( + OPJ_INT32* restrict c0, + OPJ_INT32* restrict c1, + OPJ_INT32* restrict c2, + OPJ_UINT32 n) +{ + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + + for(i = 0; i < (len & ~3U); i += 4) { + __m128i r, g, b; + __m128i y = _mm_load_si128((const __m128i *)&(c0[i])); + __m128i u = _mm_load_si128((const __m128i *)&(c1[i])); + __m128i v = _mm_load_si128((const __m128i *)&(c2[i])); + g = y; + g = _mm_sub_epi32(g, _mm_srai_epi32(_mm_add_epi32(u, v), 2)); + r = _mm_add_epi32(v, g); + b = _mm_add_epi32(u, g); + _mm_store_si128((__m128i *)&(c0[i]), r); + _mm_store_si128((__m128i *)&(c1[i]), g); + _mm_store_si128((__m128i *)&(c2[i]), b); + } + for (; i < len; ++i) { + OPJ_INT32 y = c0[i]; + OPJ_INT32 u = c1[i]; + OPJ_INT32 v = c2[i]; + OPJ_INT32 g = y - ((u + v) >> 2); + OPJ_INT32 r = v + g; + OPJ_INT32 b = u + g; + c0[i] = r; + c1[i] = g; + c2[i] = b; + } +} +#else void opj_mct_decode( OPJ_INT32* restrict c0, OPJ_INT32* restrict c1, @@ -108,6 +192,7 @@ void opj_mct_decode( c2[i] = b; } } +#endif /* <summary> */ /* Get norm of basis function of reversible MCT. */ @@ -119,6 +204,148 @@ OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno) { /* <summary> */ /* Foward irreversible MCT. */ /* </summary> */ +#ifdef __SSE4_1__ +void opj_mct_encode_real( + OPJ_INT32* restrict c0, + OPJ_INT32* restrict c1, + OPJ_INT32* restrict c2, + OPJ_UINT32 n) +{ + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + + const __m128i ry = _mm_set1_epi32(2449); + const __m128i gy = _mm_set1_epi32(4809); + const __m128i by = _mm_set1_epi32(934); + const __m128i ru = _mm_set1_epi32(1382); + const __m128i gu = _mm_set1_epi32(2714); + /* const __m128i bu = _mm_set1_epi32(4096); */ + /* const __m128i rv = _mm_set1_epi32(4096); */ + const __m128i gv = _mm_set1_epi32(3430); + const __m128i bv = _mm_set1_epi32(666); + const __m128i mulround = _mm_shuffle_epi32(_mm_cvtsi32_si128(4096), _MM_SHUFFLE(1, 0, 1, 0)); + + for(i = 0; i < (len & ~3U); i += 4) { + __m128i lo, hi; + __m128i y, u, v; + __m128i r = _mm_load_si128((const __m128i *)&(c0[i])); + __m128i g = _mm_load_si128((const __m128i *)&(c1[i])); + __m128i b = _mm_load_si128((const __m128i *)&(c2[i])); + + lo = r; + hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, ry); + hi = _mm_mul_epi32(hi, ry); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32-13); + y = _mm_blend_epi16(lo, hi, 0xCC); + + lo = g; + hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, gy); + hi = _mm_mul_epi32(hi, gy); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32-13); + y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC)); + + lo = b; + hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, by); + hi = _mm_mul_epi32(hi, by); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32-13); + y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC)); + _mm_store_si128((__m128i *)&(c0[i]), y); + + /*lo = b; + hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, mulround); + hi = _mm_mul_epi32(hi, mulround);*/ + lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 2, 0))); + hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 3, 1))); + lo = _mm_slli_epi64(lo, 12); + hi = _mm_slli_epi64(hi, 12); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32-13); + u = _mm_blend_epi16(lo, hi, 0xCC); + + lo = r; + hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, ru); + hi = _mm_mul_epi32(hi, ru); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32-13); + u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC)); + + lo = g; + hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, gu); + hi = _mm_mul_epi32(hi, gu); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32-13); + u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC)); + _mm_store_si128((__m128i *)&(c1[i]), u); + + /*lo = r; + hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, mulround); + hi = _mm_mul_epi32(hi, mulround);*/ + lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 2, 0))); + hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 3, 1))); + lo = _mm_slli_epi64(lo, 12); + hi = _mm_slli_epi64(hi, 12); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32-13); + v = _mm_blend_epi16(lo, hi, 0xCC); + + lo = g; + hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, gv); + hi = _mm_mul_epi32(hi, gv); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32-13); + v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC)); + + lo = b; + hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, bv); + hi = _mm_mul_epi32(hi, bv); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32-13); + v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC)); + _mm_store_si128((__m128i *)&(c2[i]), v); + } + for(; i < len; ++i) { + OPJ_INT32 r = c0[i]; + OPJ_INT32 g = c1[i]; + OPJ_INT32 b = c2[i]; + OPJ_INT32 y = opj_int_fix_mul(r, 2449) + opj_int_fix_mul(g, 4809) + opj_int_fix_mul(b, 934); + OPJ_INT32 u = -opj_int_fix_mul(r, 1382) - opj_int_fix_mul(g, 2714) + opj_int_fix_mul(b, 4096); + OPJ_INT32 v = opj_int_fix_mul(r, 4096) - opj_int_fix_mul(g, 3430) - opj_int_fix_mul(b, 666); + c0[i] = y; + c1[i] = u; + c2[i] = v; + } +} +#else void opj_mct_encode_real( OPJ_INT32* restrict c0, OPJ_INT32* restrict c1, @@ -138,6 +365,7 @@ void opj_mct_encode_real( c2[i] = v; } } +#endif /* <summary> */ /* Inverse irreversible MCT. */ diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/openjpeg.h b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/openjpeg.h index b1e1c294c8..4a8e75ce5a 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/openjpeg.h +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/openjpeg.h @@ -76,10 +76,36 @@ Most compilers implement their own version of this keyword ... #define OPJ_DEPRECATED(func) func #endif -// PDFium doesn't need to export any of these methods. -#define OPJ_API -#define OPJ_LOCAL -#define OPJ_CALLCONV +#if defined(OPJ_STATIC) || !defined(_WIN32) +/* http://gcc.gnu.org/wiki/Visibility */ +# if __GNUC__ >= 4 +# if defined(OPJ_STATIC) /* static library uses "hidden" */ +# define OPJ_API __attribute__ ((visibility ("hidden"))) +# else +# define OPJ_API __attribute__ ((visibility ("default"))) +# endif +# define OPJ_LOCAL __attribute__ ((visibility ("hidden"))) +# else +# define OPJ_API +# define OPJ_LOCAL +# endif +# define OPJ_CALLCONV +#else +# define OPJ_CALLCONV __stdcall +/* +The following ifdef block is the standard way of creating macros which make exporting +from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS +symbol defined on the command line. this symbol should not be defined on any project +that uses this DLL. This way any other project whose source files include this file see +OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols +defined with this macro as being exported. +*/ +# if defined(OPJ_EXPORTS) || defined(DLL_EXPORT) +# define OPJ_API __declspec(dllexport) +# else +# define OPJ_API __declspec(dllimport) +# endif /* OPJ_EXPORTS */ +#endif /* !OPJ_STATIC || !_WIN32 */ typedef int OPJ_BOOL; #define OPJ_TRUE 1 diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_includes.h b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_includes.h index d9238b1bfd..e3d4686488 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_includes.h +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_includes.h @@ -136,6 +136,10 @@ static INLINE long lrintf(float f){ } #endif +#if defined(_MSC_VER) && (_MSC_VER < 1400) + #define vsnprintf _vsnprintf +#endif + #include "opj_inttypes.h" #include "opj_clock.h" #include "opj_malloc.h" diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_intmath.h b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_intmath.h index dc89895301..4e299469de 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_intmath.h +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/opj_intmath.h @@ -82,6 +82,15 @@ static INLINE OPJ_UINT32 opj_uint_max(OPJ_UINT32 a, OPJ_UINT32 b) { } /** + Get the saturated sum of two unsigned integers + @return Returns saturated sum of a+b + */ +static INLINE OPJ_UINT32 opj_uint_adds(OPJ_UINT32 a, OPJ_UINT32 b) { + OPJ_UINT64 sum = (OPJ_UINT64)a + (OPJ_UINT64)b; + return -(OPJ_UINT32)(sum >> 32) | (OPJ_UINT32)sum; +} + +/** Clamp an integer inside an interval @return <ul> @@ -108,7 +117,7 @@ Divide an integer and round upwards @return Returns a divided by b */ static INLINE OPJ_INT32 opj_int_ceildiv(OPJ_INT32 a, OPJ_INT32 b) { - assert(b); + assert(b); return (a + b - 1) / b; } @@ -117,6 +126,7 @@ Divide an integer and round upwards @return Returns a divided by b */ static INLINE OPJ_UINT32 opj_uint_ceildiv(OPJ_UINT32 a, OPJ_UINT32 b) { + assert(b); return (a + b - 1) / b; } @@ -165,9 +175,19 @@ Multiply two fixed-precision rational numbers. @return Returns a * b */ static INLINE OPJ_INT32 opj_int_fix_mul(OPJ_INT32 a, OPJ_INT32 b) { - OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; - temp += temp & 4096; - return (OPJ_INT32) (temp >> 13) ; + OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; + temp += 4096; + assert((temp >> 13) <= (OPJ_INT64)0x7FFFFFFF); + assert((temp >> 13) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1)); + return (OPJ_INT32) (temp >> 13); +} + +static INLINE OPJ_INT32 opj_int_fix_mul_t1(OPJ_INT32 a, OPJ_INT32 b) { + OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; + temp += 4096; + assert((temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) <= (OPJ_INT64)0x7FFFFFFF); + assert((temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1)); + return (OPJ_INT32) (temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) ; } /* ----------------------------------------------------------------------- */ diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/pi.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/pi.c index 65ff6263e0..393a1e5540 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/pi.c +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/pi.c @@ -693,6 +693,9 @@ void opj_get_all_encoding_parameters( const opj_image_t *p_image, /* position in x and y of tile*/ OPJ_UINT32 p, q; + /* non-corrected (in regard to image offset) tile offset */ + OPJ_UINT32 l_tx0, l_ty0; + /* preconditions in debug*/ assert(p_cp != 00); assert(p_image != 00); @@ -708,10 +711,12 @@ void opj_get_all_encoding_parameters( const opj_image_t *p_image, q = tileno / p_cp->tw; /* here calculation of tx0, tx1, ty0, ty1, maxprec, l_dx and l_dy */ - *p_tx0 = opj_int_max((OPJ_INT32)(p_cp->tx0 + p * p_cp->tdx), (OPJ_INT32)p_image->x0); - *p_tx1 = opj_int_min((OPJ_INT32)(p_cp->tx0 + (p + 1) * p_cp->tdx), (OPJ_INT32)p_image->x1); - *p_ty0 = opj_int_max((OPJ_INT32)(p_cp->ty0 + q * p_cp->tdy), (OPJ_INT32)p_image->y0); - *p_ty1 = opj_int_min((OPJ_INT32)(p_cp->ty0 + (q + 1) * p_cp->tdy), (OPJ_INT32)p_image->y1); + l_tx0 = p_cp->tx0 + p * p_cp->tdx; /* can't be greater than p_image->x1 so won't overflow */ + *p_tx0 = (OPJ_INT32)opj_uint_max(l_tx0, p_image->x0); + *p_tx1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, p_cp->tdx), p_image->x1); + l_ty0 = p_cp->ty0 + q * p_cp->tdy; /* can't be greater than p_image->y1 so won't overflow */ + *p_ty0 = (OPJ_INT32)opj_uint_max(l_ty0, p_image->y0); + *p_ty1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, p_cp->tdy), p_image->y1); /* max precision and resolution is 0 (can only grow)*/ *p_max_prec = 0; diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.c index 11b72a33ff..8cb230f48e 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.c +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.c @@ -265,7 +265,8 @@ static OPJ_FLOAT64 opj_t1_getwmsedec( OPJ_UINT32 qmfbid, OPJ_FLOAT64 stepsize, OPJ_UINT32 numcomps, - const OPJ_FLOAT64 * mct_norms); + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps); static void opj_t1_encode_cblk( opj_t1_t *t1, opj_tcd_cblk_enc_t* cblk, @@ -277,7 +278,8 @@ static void opj_t1_encode_cblk( opj_t1_t *t1, OPJ_UINT32 cblksty, OPJ_UINT32 numcomps, opj_tcd_tile_t * tile, - const OPJ_FLOAT64 * mct_norms); + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps); /** Decode 1 code-block @@ -1137,12 +1139,13 @@ static OPJ_FLOAT64 opj_t1_getwmsedec( OPJ_UINT32 qmfbid, OPJ_FLOAT64 stepsize, OPJ_UINT32 numcomps, - const OPJ_FLOAT64 * mct_norms) + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps) { OPJ_FLOAT64 w1 = 1, w2, wmsedec; - OPJ_ARG_NOT_USED(numcomps); + OPJ_ARG_NOT_USED(numcomps); - if (mct_norms) { + if (mct_norms && (compno < mct_numcomps)) { w1 = mct_norms[compno]; } @@ -1462,7 +1465,8 @@ OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, OPJ_BOOL opj_t1_encode_cblks( opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp, - const OPJ_FLOAT64 * mct_norms + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps ) { OPJ_UINT32 compno, resno, bandno, precno, cblkno; @@ -1530,9 +1534,9 @@ OPJ_BOOL opj_t1_encode_cblks( opj_t1_t *t1, for (i = 0; i < cblk_w; ++i) { OPJ_INT32 tmp = tiledp[tileIndex]; tiledp[tileIndex] = - opj_int_fix_mul( + opj_int_fix_mul_t1( tmp, - bandconst) >> (11 - T1_NMSEDEC_FRACBITS); + bandconst); tileIndex++; } tileIndex += tileLineAdvance; @@ -1550,7 +1554,8 @@ OPJ_BOOL opj_t1_encode_cblks( opj_t1_t *t1, tccp->cblksty, tile->numcomps, tile, - mct_norms); + mct_norms, + mct_numcomps); } /* cblkno */ } /* precno */ @@ -1571,7 +1576,8 @@ void opj_t1_encode_cblk(opj_t1_t *t1, OPJ_UINT32 cblksty, OPJ_UINT32 numcomps, opj_tcd_tile_t * tile, - const OPJ_FLOAT64 * mct_norms) + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps) { OPJ_FLOAT64 cumwmsedec = 0.0; @@ -1626,7 +1632,7 @@ void opj_t1_encode_cblk(opj_t1_t *t1, } /* fixed_quality */ - tempwmsedec = opj_t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps,mct_norms) ; + tempwmsedec = opj_t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps,mct_norms, mct_numcomps) ; cumwmsedec += tempwmsedec; tile->distotile += tempwmsedec; diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.h b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.h index e1d41ed56f..3bc0ad9ea7 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.h +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t1.h @@ -126,11 +126,13 @@ Encode the code-blocks of a tile @param tile The tile to encode @param tcp Tile coding parameters @param mct_norms FIXME DOC +@param mct_numcomps Number of components used for MCT */ OPJ_BOOL opj_t1_encode_cblks( opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp, - const OPJ_FLOAT64 * mct_norms); + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps); /** Decode the code-blocks of a tile diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t2.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t2.c index d0d63d2bd0..6f0ac91569 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t2.c +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/t2.c @@ -388,13 +388,13 @@ OPJ_BOOL opj_t2_decode_packets( opj_t2_t *p_t2, * and no l_img_comp->resno_decoded are computed */ OPJ_BOOL* first_pass_failed = NULL; - + if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { /* TODO ADE : add an error */ opj_pi_destroy(l_pi, l_nb_pocs); return OPJ_FALSE; } - + first_pass_failed = (OPJ_BOOL*)opj_malloc(l_image->numcomps * sizeof(OPJ_BOOL)); if (!first_pass_failed) { diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.c b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.c index 6c04f3d8b7..f62312027d 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.c +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.c @@ -120,11 +120,16 @@ static OPJ_BOOL opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_blo static void opj_tcd_code_block_dec_deallocate (opj_tcd_precinct_t * p_precinct); /** - * Allocates memory for an encoding code block. + * Allocates memory for an encoding code block (but not data). */ static OPJ_BOOL opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block); /** + * Allocates data for an encoding code block + */ +static OPJ_BOOL opj_tcd_code_block_enc_allocate_data (opj_tcd_cblk_enc_t * p_code_block); + +/** * Deallocates the encoding data of the given precinct. */ static void opj_tcd_code_block_enc_deallocate (opj_tcd_precinct_t * p_precinct); @@ -670,6 +675,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_UINT32 l_pdx, l_pdy; OPJ_UINT32 l_gain; OPJ_INT32 l_x0b, l_y0b; + OPJ_UINT32 l_tx0, l_ty0; /* extent of precincts , top left, bottom right**/ OPJ_INT32 l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end, l_br_prc_y_end; /* number of precinct for a resolution */ @@ -682,7 +688,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_UINT32 l_nb_code_blocks_size; /* size of data for a tile */ OPJ_UINT32 l_data_size; - + l_cp = p_tcd->cp; l_tcp = &(l_cp->tcps[p_tile_no]); l_tile = p_tcd->tcd_image->tiles; @@ -690,23 +696,26 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_tilec = l_tile->comps; l_image = p_tcd->image; l_image_comp = p_tcd->image->comps; - + p = p_tile_no % l_cp->tw; /* tile coordinates */ q = p_tile_no / l_cp->tw; /*fprintf(stderr, "Tile coordinate = %d,%d\n", p, q);*/ - + /* 4 borders of the tile rescale on the image if necessary */ - l_tile->x0 = opj_int_max((OPJ_INT32)(l_cp->tx0 + p * l_cp->tdx), (OPJ_INT32)l_image->x0); - l_tile->y0 = opj_int_max((OPJ_INT32)(l_cp->ty0 + q * l_cp->tdy), (OPJ_INT32)l_image->y0); - l_tile->x1 = opj_int_min((OPJ_INT32)(l_cp->tx0 + (p + 1) * l_cp->tdx), (OPJ_INT32)l_image->x1); - l_tile->y1 = opj_int_min((OPJ_INT32)(l_cp->ty0 + (q + 1) * l_cp->tdy), (OPJ_INT32)l_image->y1); + l_tx0 = l_cp->tx0 + p * l_cp->tdx; /* can't be greater than l_image->x1 so won't overflow */ + l_tile->x0 = (OPJ_INT32)opj_uint_max(l_tx0, l_image->x0); + l_tile->x1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, l_cp->tdx), l_image->x1); + l_ty0 = l_cp->ty0 + q * l_cp->tdy; /* can't be greater than l_image->y1 so won't overflow */ + l_tile->y0 = (OPJ_INT32)opj_uint_max(l_ty0, l_image->y0); + l_tile->y1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, l_cp->tdy), l_image->y1); + /* testcase 1888.pdf.asan.35.988 */ if (l_tccp->numresolutions == 0) { fprintf(stderr, "tiles require at least one resolution\n"); return OPJ_FALSE; } /*fprintf(stderr, "Tile border = %d,%d,%d,%d\n", l_tile->x0, l_tile->y0,l_tile->x1,l_tile->y1);*/ - + /*tile->numcomps = image->numcomps; */ for (compno = 0; compno < l_tile->numcomps; ++compno) { /*fprintf(stderr, "compno = %d/%d\n", compno, l_tile->numcomps);*/ @@ -717,7 +726,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_tilec->x1 = opj_int_ceildiv(l_tile->x1, (OPJ_INT32)l_image_comp->dx); l_tilec->y1 = opj_int_ceildiv(l_tile->y1, (OPJ_INT32)l_image_comp->dy); /*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/ - + /* compute l_data_size with overflow check */ l_data_size = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0); if ((((OPJ_UINT32)-1) / l_data_size) < (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0)) { @@ -725,7 +734,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, return OPJ_FALSE; } l_data_size = l_data_size * (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0); - + if ((((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(OPJ_UINT32)) < l_data_size) { /* TODO event */ return OPJ_FALSE; @@ -738,14 +747,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, else { l_tilec->minimum_num_resolutions = l_tccp->numresolutions - l_cp->m_specific_param.m_dec.m_reduce; } - + l_tilec->data_size_needed = l_data_size; if (p_tcd->m_is_decoder && !opj_alloc_tile_component_data(l_tilec)) { return OPJ_FALSE; } - + l_data_size = l_tilec->numresolutions * (OPJ_UINT32)sizeof(opj_tcd_resolution_t); - + if (l_tilec->resolutions == 00) { l_tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(l_data_size); if (! l_tilec->resolutions ) { @@ -770,7 +779,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, memset(((OPJ_BYTE*) l_tilec->resolutions)+l_tilec->resolutions_size,0,l_data_size - l_tilec->resolutions_size); l_tilec->resolutions_size = l_data_size; } - + l_level_no = l_tilec->numresolutions - 1; l_res = l_tilec->resolutions; l_step_size = l_tccp->stepsizes; @@ -781,13 +790,13 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_gain_ptr = &opj_dwt_getgain; } /*fprintf(stderr, "\tlevel_no=%d\n",l_level_no);*/ - + for (resno = 0; resno < l_tilec->numresolutions; ++resno) { /*fprintf(stderr, "\t\tresno = %d/%d\n", resno, l_tilec->numresolutions);*/ OPJ_INT32 tlcbgxstart, tlcbgystart /*, brcbgxend, brcbgyend*/; OPJ_UINT32 cbgwidthexpn, cbgheightexpn; OPJ_UINT32 cblkwidthexpn, cblkheightexpn; - + /* border for each resolution level (global) */ l_res->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no); l_res->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no); @@ -804,11 +813,11 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_br_prc_x_end = opj_int_ceildivpow2(l_res->x1, (OPJ_INT32)l_pdx) << l_pdx; l_br_prc_y_end = opj_int_ceildivpow2(l_res->y1, (OPJ_INT32)l_pdy) << l_pdy; /*fprintf(stderr, "\t\t\tprc_x_start=%d, prc_y_start=%d, br_prc_x_end=%d, br_prc_y_end=%d \n", l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end ,l_br_prc_y_end );*/ - + l_res->pw = (l_res->x0 == l_res->x1) ? 0 : (OPJ_UINT32)((l_br_prc_x_end - l_tl_prc_x_start) >> l_pdx); l_res->ph = (l_res->y0 == l_res->y1) ? 0 : (OPJ_UINT32)((l_br_prc_y_end - l_tl_prc_y_start) >> l_pdy); /*fprintf(stderr, "\t\t\tres_pw=%d, res_ph=%d\n", l_res->pw, l_res->ph );*/ - + l_nb_precincts = l_res->pw * l_res->ph; l_nb_precinct_size = l_nb_precincts * (OPJ_UINT32)sizeof(opj_tcd_precinct_t); if (resno == 0) { @@ -829,15 +838,15 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, cbgheightexpn = l_pdy - 1; l_res->numbands = 3; } - + cblkwidthexpn = opj_uint_min(l_tccp->cblkw, cbgwidthexpn); cblkheightexpn = opj_uint_min(l_tccp->cblkh, cbgheightexpn); l_band = l_res->bands; - + for (bandno = 0; bandno < l_res->numbands; ++bandno) { OPJ_INT32 numbps; /*fprintf(stderr, "\t\t\tband_no=%d/%d\n", bandno, l_res->numbands );*/ - + if (resno == 0) { l_band->bandno = 0 ; l_band->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no); @@ -857,13 +866,13 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_band->x1 = opj_int_ceildivpow2(l_tilec->x1 - (1 << l_level_no) * l_x0b, (OPJ_INT32)(l_level_no + 1)); l_band->y1 = opj_int_ceildivpow2(l_tilec->y1 - (1 << l_level_no) * l_y0b, (OPJ_INT32)(l_level_no + 1)); } - + /** avoid an if with storing function pointer */ l_gain = (*l_gain_ptr) (l_band->bandno); numbps = (OPJ_INT32)(l_image_comp->prec + l_gain); l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0, (OPJ_INT32) (numbps - l_step_size->expn)))) * fraction; l_band->numbps = l_step_size->expn + (OPJ_INT32)l_tccp->numgbits - 1; /* WHY -1 ? */ - + if (! l_band->precincts) { l_band->precincts = (opj_tcd_precinct_t *) opj_malloc( /*3 * */ l_nb_precinct_size); if (! l_band->precincts) { @@ -874,7 +883,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_band->precincts_data_size = l_nb_precinct_size; } else if (l_band->precincts_data_size < l_nb_precinct_size) { - + opj_tcd_precinct_t * new_precincts = (opj_tcd_precinct_t *) opj_realloc(l_band->precincts,/*3 * */ l_nb_precinct_size); if (! new_precincts) { /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle band precints\n"); */ @@ -889,7 +898,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, memset(((OPJ_BYTE *) l_band->precincts) + l_band->precincts_data_size,0,l_nb_precinct_size - l_band->precincts_data_size); l_band->precincts_data_size = l_nb_precinct_size; } - + l_current_precinct = l_band->precincts; for (precno = 0; precno < l_nb_precincts; ++precno) { OPJ_INT32 tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; @@ -899,16 +908,16 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_INT32 cbgyend = cbgystart + (1 << cbgheightexpn); /*fprintf(stderr, "\t precno=%d; bandno=%d, resno=%d; compno=%d\n", precno, bandno , resno, compno);*/ /*fprintf(stderr, "\t tlcbgxstart(=%d) + (precno(=%d) percent res->pw(=%d)) * (1 << cbgwidthexpn(=%d)) \n",tlcbgxstart,precno,l_res->pw,cbgwidthexpn);*/ - + /* precinct size (global) */ /*fprintf(stderr, "\t cbgxstart=%d, l_band->x0 = %d \n",cbgxstart, l_band->x0);*/ - + l_current_precinct->x0 = opj_int_max(cbgxstart, l_band->x0); l_current_precinct->y0 = opj_int_max(cbgystart, l_band->y0); l_current_precinct->x1 = opj_int_min(cbgxend, l_band->x1); l_current_precinct->y1 = opj_int_min(cbgyend, l_band->y1); /*fprintf(stderr, "\t prc_x0=%d; prc_y0=%d, prc_x1=%d; prc_y1=%d\n",l_current_precinct->x0, l_current_precinct->y0 ,l_current_precinct->x1, l_current_precinct->y1);*/ - + tlcblkxstart = opj_int_floordivpow2(l_current_precinct->x0, (OPJ_INT32)cblkwidthexpn) << cblkwidthexpn; /*fprintf(stderr, "\t tlcblkxstart =%d\n",tlcblkxstart );*/ tlcblkystart = opj_int_floordivpow2(l_current_precinct->y0, (OPJ_INT32)cblkheightexpn) << cblkheightexpn; @@ -919,20 +928,20 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, /*fprintf(stderr, "\t brcblkyend =%d\n",brcblkyend );*/ l_current_precinct->cw = (OPJ_UINT32)((brcblkxend - tlcblkxstart) >> cblkwidthexpn); l_current_precinct->ch = (OPJ_UINT32)((brcblkyend - tlcblkystart) >> cblkheightexpn); - + l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch; /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",l_current_precinct->cw, l_current_precinct->ch); */ l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block; - + if (! l_current_precinct->cblks.blocks) { l_current_precinct->cblks.blocks = opj_malloc(l_nb_code_blocks_size); if (! l_current_precinct->cblks.blocks ) { return OPJ_FALSE; } /*fprintf(stderr, "\t\t\t\tAllocate cblks of a precinct (opj_tcd_cblk_dec_t): %d\n",l_nb_code_blocks_size);*/ - + memset(l_current_precinct->cblks.blocks,0,l_nb_code_blocks_size); - + l_current_precinct->block_size = l_nb_code_blocks_size; } else if (l_nb_code_blocks_size > l_current_precinct->block_size) { @@ -947,14 +956,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, } l_current_precinct->cblks.blocks = new_blocks; /*fprintf(stderr, "\t\t\t\tReallocate cblks of a precinct (opj_tcd_cblk_dec_t): from %d to %d\n",l_current_precinct->block_size, l_nb_code_blocks_size); */ - + memset(((OPJ_BYTE *) l_current_precinct->cblks.blocks) + l_current_precinct->block_size ,0 ,l_nb_code_blocks_size - l_current_precinct->block_size); - + l_current_precinct->block_size = l_nb_code_blocks_size; } - + if (! l_current_precinct->incltree) { l_current_precinct->incltree = opj_tgt_create(l_current_precinct->cw, l_current_precinct->ch); @@ -992,10 +1001,10 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_INT32 cblkystart = tlcblkystart + (OPJ_INT32)(cblkno / l_current_precinct->cw) * (1 << cblkheightexpn); OPJ_INT32 cblkxend = cblkxstart + (1 << cblkwidthexpn); OPJ_INT32 cblkyend = cblkystart + (1 << cblkheightexpn); - + if (isEncoder) { opj_tcd_cblk_enc_t* l_code_block = l_current_precinct->cblks.enc + cblkno; - + if (! opj_tcd_code_block_enc_allocate(l_code_block)) { return OPJ_FALSE; } @@ -1004,9 +1013,13 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_code_block->y0 = opj_int_max(cblkystart, l_current_precinct->y0); l_code_block->x1 = opj_int_min(cblkxend, l_current_precinct->x1); l_code_block->y1 = opj_int_min(cblkyend, l_current_precinct->y1); + + if (! opj_tcd_code_block_enc_allocate_data(l_code_block)) { + return OPJ_FALSE; + } } else { opj_tcd_cblk_dec_t* l_code_block = l_current_precinct->cblks.dec + cblkno; - + if (! opj_tcd_code_block_dec_allocate(l_code_block)) { return OPJ_FALSE; } @@ -1043,39 +1056,56 @@ OPJ_BOOL opj_tcd_init_decode_tile (opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no) } /** - * Allocates memory for an encoding code block. + * Allocates memory for an encoding code block (but not data memory). */ -OPJ_BOOL opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block) +static OPJ_BOOL opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block) { - if (! p_code_block->data) { - - p_code_block->data = (OPJ_BYTE*) opj_malloc(OPJ_J2K_DEFAULT_CBLK_DATA_SIZE*2); /*why +1 ?*/ - if(! p_code_block->data) { - return OPJ_FALSE; - } - - p_code_block->data[0] = 0; - p_code_block->data+=1; - - /* no memset since data */ - p_code_block->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t)); - if (! p_code_block->layers) { - return OPJ_FALSE; - } - - p_code_block->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t)); - if (! p_code_block->passes) { - return OPJ_FALSE; - } - } + if (! p_code_block->layers) { + /* no memset since data */ + p_code_block->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t)); + if (! p_code_block->layers) { + return OPJ_FALSE; + } + } + if (! p_code_block->passes) { + p_code_block->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t)); + if (! p_code_block->passes) { + return OPJ_FALSE; + } + } + return OPJ_TRUE; +} - return OPJ_TRUE; +/** + * Allocates data memory for an encoding code block. + */ +static OPJ_BOOL opj_tcd_code_block_enc_allocate_data (opj_tcd_cblk_enc_t * p_code_block) +{ + OPJ_UINT32 l_data_size; + + l_data_size = (OPJ_UINT32)((p_code_block->x1 - p_code_block->x0) * (p_code_block->y1 - p_code_block->y0) * (OPJ_INT32)sizeof(OPJ_UINT32)); + + if (l_data_size > p_code_block->data_size) { + if (p_code_block->data) { + opj_free(p_code_block->data - 1); /* again, why -1 */ + } + p_code_block->data = (OPJ_BYTE*) opj_malloc(l_data_size); + if(! p_code_block->data) { + p_code_block->data_size = 0U; + return OPJ_FALSE; + } + p_code_block->data_size = l_data_size; + + p_code_block->data[0] = 0; + p_code_block->data+=1; /*why +1 ?*/ + } + return OPJ_TRUE; } /** * Allocates memory for a decoding code block. */ -OPJ_BOOL opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block) +static OPJ_BOOL opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block) { if (! p_code_block->data) { @@ -1989,6 +2019,7 @@ OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd ) { opj_t1_t * l_t1; const OPJ_FLOAT64 * l_mct_norms; + OPJ_UINT32 l_mct_numcomps = 0U; opj_tcp_t * l_tcp = p_tcd->tcp; l_t1 = opj_t1_create(OPJ_TRUE); @@ -1997,6 +2028,7 @@ OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd ) } if (l_tcp->mct == 1) { + l_mct_numcomps = 3U; /* irreversible encoding */ if (l_tcp->tccps->qmfbid == 0) { l_mct_norms = opj_mct_get_mct_norms_real(); @@ -2006,10 +2038,11 @@ OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd ) } } else { + l_mct_numcomps = p_tcd->image->numcomps; l_mct_norms = (const OPJ_FLOAT64 *) (l_tcp->mct_norms); } - if (! opj_t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles , l_tcp, l_mct_norms)) { + if (! opj_t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles , l_tcp, l_mct_norms, l_mct_numcomps)) { opj_t1_destroy(l_t1); return OPJ_FALSE; } diff --git a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.h b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.h index 3cb38d26c5..9bef0fe7d9 100644 --- a/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.h +++ b/core/src/fxcodec/fx_libopenjpeg/libopenjpeg20/tcd.h @@ -87,15 +87,16 @@ typedef struct opj_tcd_layer { FIXME DOC */ typedef struct opj_tcd_cblk_enc { - OPJ_BYTE* data; /* Data */ - opj_tcd_layer_t* layers; /* layer information */ - opj_tcd_pass_t* passes; /* information about the passes */ - OPJ_INT32 x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_BYTE* data; /* Data */ + opj_tcd_layer_t* layers; /* layer information */ + opj_tcd_pass_t* passes; /* information about the passes */ + OPJ_INT32 x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ OPJ_UINT32 numbps; OPJ_UINT32 numlenbits; - OPJ_UINT32 numpasses; /* number of pass already done for the code-blocks */ - OPJ_UINT32 numpassesinlayers; /* number of passes in the layer */ - OPJ_UINT32 totalpasses; /* total number of passes */ + OPJ_UINT32 data_size; /* Size of allocated data buffer */ + OPJ_UINT32 numpasses; /* number of pass already done for the code-blocks */ + OPJ_UINT32 numpassesinlayers; /* number of passes in the layer */ + OPJ_UINT32 totalpasses; /* total number of passes */ } opj_tcd_cblk_enc_t; @@ -105,7 +106,7 @@ typedef struct opj_tcd_cblk_dec { OPJ_INT32 x0, y0, x1, y1; /* position of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ OPJ_UINT32 numbps; OPJ_UINT32 numlenbits; - OPJ_UINT32 data_max_size; /* Size of allocated data buffer */ + OPJ_UINT32 data_max_size; /* Size of allocated data buffer */ OPJ_UINT32 data_current_size; /* Size of used data buffer */ OPJ_UINT32 numnewpasses; /* number of pass added to the code-blocks */ OPJ_UINT32 numsegs; /* number of segments */ |