X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fopenjp2%2Ft1.c;h=0277f8cc73260dd287ac9d96459408b171afefba;hb=0ae3cba3404674bbe2028ea9a801301a4c951b33;hp=d5fba6f918959316ff6cc0ac5eb0c56f0065a3ec;hpb=a0861855c11bcb8c93f399ca51e766b5c8ef9e33;p=openjpeg.git diff --git a/src/lib/openjp2/t1.c b/src/lib/openjp2/t1.c index d5fba6f9..0277f8cc 100644 --- a/src/lib/openjp2/t1.c +++ b/src/lib/openjp2/t1.c @@ -46,6 +46,8 @@ #define T1_FLAGS(x, y) (t1->flags[x + 1 + ((y / 4) + 1) * (t1->w+2)]) +#define opj_t1_setcurctx(curctx, ctxno) curctx = &(mqc)->ctxs[(OPJ_UINT32)(ctxno)] + /** @name Local static functions */ /*@{*/ @@ -54,7 +56,8 @@ static INLINE OPJ_UINT32 opj_t1_getctxno_mag(OPJ_UINT32 f); static OPJ_INT16 opj_t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos); static OPJ_INT16 opj_t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos); static INLINE void opj_t1_update_flags(opj_flag_t *flagsp, OPJ_UINT32 ci, - OPJ_UINT32 s, OPJ_UINT32 stride); + OPJ_UINT32 s, OPJ_UINT32 stride, + OPJ_UINT32 vsc); /** @@ -66,7 +69,7 @@ static INLINE void opj_t1_dec_sigpass_step_raw( opj_flag_t *flagsp, OPJ_INT32 *datap, OPJ_INT32 oneplushalf, - OPJ_INT32 vsc, + OPJ_UINT32 vsc, OPJ_UINT32 row); static INLINE void opj_t1_dec_sigpass_step_mqc( opj_t1_t *t1, @@ -74,15 +77,8 @@ static INLINE void opj_t1_dec_sigpass_step_mqc( OPJ_INT32 *datap, OPJ_INT32 oneplushalf, OPJ_UINT32 row, - OPJ_UINT32 flags_stride); -static INLINE void opj_t1_dec_sigpass_step_mqc_vsc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 oneplushalf, - OPJ_INT32 vsc, - OPJ_UINT32 row); - + OPJ_UINT32 flags_stride, + OPJ_UINT32 vsc); /** Encode significant pass @@ -100,11 +96,6 @@ static void opj_t1_dec_sigpass_raw( opj_t1_t *t1, OPJ_INT32 bpno, OPJ_INT32 cblksty); -static void opj_t1_dec_sigpass_mqc_vsc( - opj_t1_t *t1, - OPJ_INT32 bpno); - - /** Encode refinement pass @@ -112,8 +103,7 @@ Encode refinement pass static void opj_t1_enc_refpass(opj_t1_t *t1, OPJ_INT32 bpno, OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 cblksty); + OPJ_BYTE type); /** Decode refinement pass @@ -121,9 +111,6 @@ Decode refinement pass static void opj_t1_dec_refpass_raw( opj_t1_t *t1, OPJ_INT32 bpno); -static void opj_t1_dec_refpass_mqc_vsc( - opj_t1_t *t1, - OPJ_INT32 bpno); /** @@ -142,38 +129,20 @@ static INLINE void opj_t1_dec_refpass_step_mqc( OPJ_INT32 *datap, OPJ_INT32 poshalf, OPJ_UINT32 row); -static INLINE void opj_t1_dec_refpass_step_mqc_vsc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 vsc, - OPJ_UINT32 row); /** Decode clean-up pass */ -static void opj_t1_dec_clnpass_step_partial( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 oneplushalf, - OPJ_UINT32 row); + static void opj_t1_dec_clnpass_step( opj_t1_t *t1, opj_flag_t *flagsp, OPJ_INT32 *datap, OPJ_INT32 oneplushalf, - OPJ_UINT32 row); -static void opj_t1_dec_clnpass_step_vsc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 oneplushalf, - OPJ_INT32 partial, - OPJ_INT32 vsc, - OPJ_UINT32 row); + OPJ_UINT32 row, + OPJ_UINT32 vsc); + /** Encode clean-up pass */ @@ -215,12 +184,18 @@ Decode 1 code-block @param orient @param roishift Region of interest shifting value @param cblksty Code-block style +@param p_manager the event manager +@param p_manager_mutex mutex for the event manager +@param check_pterm whether PTERM correct termination should be checked */ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, opj_tcd_cblk_dec_t* cblk, OPJ_UINT32 orient, OPJ_UINT32 roishift, - OPJ_UINT32 cblksty); + OPJ_UINT32 cblksty, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm); static OPJ_BOOL opj_t1_allocate_buffers(opj_t1_t *t1, OPJ_UINT32 w, @@ -302,62 +277,40 @@ static OPJ_INT16 opj_t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos) return lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; } +#define opj_t1_update_flags_macro(flags, flagsp, ci, s, stride, vsc) \ +{ \ + /* east */ \ + flagsp[-1] |= T1_SIGMA_5 << (3U * ci); \ + \ + /* mark target as significant */ \ + flags |= ((s << T1_CHI_1_I) | T1_SIGMA_4) << (3U * ci); \ + \ + /* west */ \ + flagsp[1] |= T1_SIGMA_3 << (3U * ci); \ + \ + /* north-west, north, north-east */ \ + if (ci == 0U && !(vsc)) { \ + opj_flag_t* north = flagsp - (stride); \ + *north |= (s << T1_CHI_5_I) | T1_SIGMA_16; \ + north[-1] |= T1_SIGMA_17; \ + north[1] |= T1_SIGMA_15; \ + } \ + \ + /* south-west, south, south-east */ \ + if (ci == 3U) { \ + opj_flag_t* south = flagsp + (stride); \ + *south |= (s << T1_CHI_0_I) | T1_SIGMA_1; \ + south[-1] |= T1_SIGMA_2; \ + south[1] |= T1_SIGMA_0; \ + } \ +} + static INLINE void opj_t1_update_flags(opj_flag_t *flagsp, OPJ_UINT32 ci, - OPJ_UINT32 s, OPJ_UINT32 stride) + OPJ_UINT32 s, OPJ_UINT32 stride, + OPJ_UINT32 vsc) { - /* set up to point to the north and south data points' flags words, if required */ - opj_flag_t* north; - opj_flag_t* south; - - /* mark target as significant */ - *flagsp |= T1_SIGMA_4 << (3U * ci); - - /* north-west, north, north-east */ - if (ci == 0U) { - north = flagsp - stride; - *north |= T1_SIGMA_16; - north[-1] |= T1_SIGMA_17; - north[1] |= T1_SIGMA_15; - } - - /* south-west, south, south-east */ - if (ci == 3U) { - south = flagsp + stride; - *south |= T1_SIGMA_1; - south[-1] |= T1_SIGMA_2; - south[1] |= T1_SIGMA_0; - } - - /* east */ - flagsp[-1] |= T1_SIGMA_5 << (3U * ci); - - /* west */ - flagsp[1] |= T1_SIGMA_3 << (3U * ci); - - if (s) { - switch (ci) { - case 0U: { - *flagsp |= T1_CHI_1; - north = flagsp - stride; - *north |= T1_CHI_5; - break; - } - case 1: - *flagsp |= T1_CHI_2; - break; - case 2: - *flagsp |= T1_CHI_3; - break; - case 3: { - *flagsp |= T1_CHI_4; - south = flagsp + stride; - *south |= T1_CHI_0; - break; - } - - } - } + opj_t1_update_flags_macro(*flagsp, flagsp, ci, s, stride, vsc); } /** @@ -371,16 +324,13 @@ static INLINE void opj_t1_enc_sigpass_step(opj_t1_t *t1, OPJ_INT32 *nmsedec, OPJ_BYTE type, OPJ_UINT32 ci, - OPJ_UINT32 vsc - ) + OPJ_UINT32 vsc) { OPJ_UINT32 v; opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ - OPJ_UINT32 vsc_mask = vsc ? ~((T1_SIGMA_SW | T1_SIGMA_S | T1_SIGMA_SE | - T1_CHI_S) << (ci * 3U)) : ~0U; - OPJ_UINT32 const flags = *flagsp & vsc_mask; + OPJ_UINT32 const flags = *flagsp; if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { @@ -396,14 +346,12 @@ static INLINE void opj_t1_enc_sigpass_step(opj_t1_t *t1, opj_mqc_encode(mqc, v); } if (v) { - /* Note: using flags instead of *flagsp & vsc_mask result */ - /* in slow down. Probably because of register pressure */ OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( - *flagsp & vsc_mask, - flagsp[-1] & vsc_mask, flagsp[1] & vsc_mask, + *flagsp, + flagsp[-1], flagsp[1], ci); OPJ_UINT32 ctxt2 = opj_t1_getctxno_sc(lu); - v = *datap < 0 ? 1 : 0; + v = *datap < 0 ? 1U : 0U; *nmsedec += opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)bpno); #ifdef DEBUG_ENC_SIG @@ -419,7 +367,7 @@ static INLINE void opj_t1_enc_sigpass_step(opj_t1_t *t1, #endif opj_mqc_encode(mqc, v ^ spb); } - opj_t1_update_flags(flagsp, ci, v, t1->w + 2); + opj_t1_update_flags(flagsp, ci, v, t1->w + 2, vsc); } *flagsp |= T1_PI_THIS << (ci * 3U); } @@ -430,97 +378,68 @@ static INLINE void opj_t1_dec_sigpass_step_raw( opj_flag_t *flagsp, OPJ_INT32 *datap, OPJ_INT32 oneplushalf, - OPJ_INT32 vsc, + OPJ_UINT32 vsc, OPJ_UINT32 ci) { OPJ_UINT32 v; - opj_raw_t *raw = &(t1->raw); /* RAW component */ + opj_mqc_t *mqc = &(t1->mqc); /* RAW component */ - OPJ_UINT32 vsc_mask = vsc ? ~((T1_SIGMA_SW | T1_SIGMA_S | T1_SIGMA_SE | - T1_CHI_S) << (ci * 3U)) : ~0U; - OPJ_UINT32 const flags = *flagsp & vsc_mask; + OPJ_UINT32 const flags = *flagsp; if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { - if (opj_raw_decode(raw)) { - v = opj_raw_decode(raw); + if (opj_mqc_raw_decode(mqc)) { + v = opj_mqc_raw_decode(mqc); *datap = v ? -oneplushalf : oneplushalf; - opj_t1_update_flags(flagsp, ci, v, t1->w + 2); + opj_t1_update_flags(flagsp, ci, v, t1->w + 2, vsc); } *flagsp |= T1_PI_THIS << (ci * 3U); } } -static INLINE void opj_t1_dec_sigpass_step_mqc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 oneplushalf, - OPJ_UINT32 ci, - OPJ_UINT32 flags_stride) -{ - OPJ_UINT32 v; - - opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ - OPJ_UINT32 const flags = *flagsp; - - if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && - (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { - OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( - *flagsp, - flagsp[-1], flagsp[1], - ci); - OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); - opj_mqc_setcurctx(mqc, ctxt1); - if (opj_mqc_decode(mqc)) { - OPJ_UINT32 ctxt2 = opj_t1_getctxno_sc(lu); - OPJ_UINT32 spb = opj_t1_getspb(lu); - opj_mqc_setcurctx(mqc, ctxt2); - v = opj_mqc_decode(mqc) ^ spb; - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_update_flags(flagsp, ci, v, flags_stride); - } - *flagsp |= T1_PI_THIS << (ci * 3U); - } +#define opj_t1_dec_sigpass_step_mqc_macro(flags, flagsp, flags_stride, data, \ + data_stride, ci, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc) \ +{ \ + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && \ + (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { \ + OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); \ + opj_t1_setcurctx(curctx, ctxt1); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + if (v) { \ + OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( \ + flags, \ + flagsp[-1], flagsp[1], \ + ci); \ + OPJ_UINT32 ctxt2 = opj_t1_getctxno_sc(lu); \ + OPJ_UINT32 spb = opj_t1_getspb(lu); \ + opj_t1_setcurctx(curctx, ctxt2); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + v = v ^ spb; \ + data[ci*data_stride] = v ? -oneplushalf : oneplushalf; \ + opj_t1_update_flags_macro(flags, flagsp, ci, v, flags_stride, vsc); \ + } \ + flags |= T1_PI_THIS << (ci * 3U); \ + } \ } -static INLINE void opj_t1_dec_sigpass_step_mqc_vsc( +static INLINE void opj_t1_dec_sigpass_step_mqc( opj_t1_t *t1, opj_flag_t *flagsp, OPJ_INT32 *datap, OPJ_INT32 oneplushalf, - OPJ_INT32 vsc, - OPJ_UINT32 ci) + OPJ_UINT32 ci, + OPJ_UINT32 flags_stride, + OPJ_UINT32 vsc) { OPJ_UINT32 v; opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ - - OPJ_UINT32 vsc_mask = vsc ? ~((T1_SIGMA_SW | T1_SIGMA_S | T1_SIGMA_SE | - T1_CHI_S) << (ci * 3U)) : ~0U; - OPJ_UINT32 const flags = *flagsp & vsc_mask; - - if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && - (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { - OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( - *flagsp & vsc_mask, - flagsp[-1] & vsc_mask, flagsp[1] & vsc_mask, - ci); - OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); - opj_mqc_setcurctx(mqc, ctxt1); - if (opj_mqc_decode(mqc)) { - OPJ_UINT32 ctxt2 = opj_t1_getctxno_sc(lu); - OPJ_UINT32 spb = opj_t1_getspb(lu); - opj_mqc_setcurctx(mqc, ctxt2); - v = opj_mqc_decode(mqc) ^ spb; - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_update_flags(flagsp, ci, v, t1->w + 2); - } - *flagsp |= T1_PI_THIS << (ci * 3U); - } + opj_t1_dec_sigpass_step_mqc_macro(*flagsp, flagsp, flags_stride, datap, + 0, ci, mqc, mqc->curctx, + v, mqc->a, mqc->c, mqc->ct, oneplushalf, vsc); } - static void opj_t1_enc_sigpass(opj_t1_t *t1, OPJ_INT32 bpno, OPJ_INT32 *nmsedec, @@ -558,7 +477,7 @@ static void opj_t1_enc_sigpass(opj_t1_t *t1, one, nmsedec, type, - 0, 0); + 0, cblksty & J2K_CCP_CBLKSTY_VSC); opj_t1_enc_sigpass_step( t1, f, @@ -585,7 +504,7 @@ static void opj_t1_enc_sigpass(opj_t1_t *t1, one, nmsedec, type, - 3, cblksty & J2K_CCP_CBLKSTY_VSC); + 3, 0); ++f; } f += extra; @@ -615,7 +534,7 @@ static void opj_t1_enc_sigpass(opj_t1_t *t1, nmsedec, type, j - k, - (j == t1->h - 1 && (cblksty & J2K_CCP_CBLKSTY_VSC) != 0)); + (j == k && (cblksty & J2K_CCP_CBLKSTY_VSC) != 0)); } ++f; } @@ -629,188 +548,157 @@ static void opj_t1_dec_sigpass_raw( { OPJ_INT32 one, half, oneplushalf; OPJ_UINT32 i, j, k; + OPJ_INT32 *data = t1->data; opj_flag_t *flagsp = &T1_FLAGS(0, 0); + const OPJ_UINT32 l_w = t1->w; one = 1 << bpno; half = one >> 1; oneplushalf = one | half; - if ((cblksty & J2K_CCP_CBLKSTY_VSC)) { - OPJ_INT32 *data1 = t1->data; - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - OPJ_INT32* data2 = data1 + i; - for (j = k; j < k + 4 && j < t1->h; ++j) { - OPJ_INT32 vsc = (j == k + 3 || j == t1->h - 1) ? 1 : 0; - opj_t1_dec_sigpass_step_raw( - t1, - flagsp, - data2, - oneplushalf, - vsc, - j - k); - data2 += t1->w; - } - flagsp ++; - } - data1 += t1->w << 2; - flagsp += 2; - } - } else { - OPJ_INT32 *data1 = t1->data; - for (k = 0; k < (t1->h & ~3U); k += 4) { - for (i = 0; i < t1->w; ++i) { - OPJ_INT32* data2 = data1 + i; + + for (k = 0; k < (t1->h & ~3U); k += 4, flagsp += 2, data += 3 * l_w) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + opj_flag_t flags = *flagsp; + if (flags != 0) { opj_t1_dec_sigpass_step_raw( t1, flagsp, - data2, + data, oneplushalf, - 0, /* vsc */ + cblksty & J2K_CCP_CBLKSTY_VSC, /* vsc */ 0U); - data2 += t1->w; opj_t1_dec_sigpass_step_raw( t1, flagsp, - data2, + data + l_w, oneplushalf, - 0, /* vsc */ + OPJ_FALSE, /* vsc */ 1U); - data2 += t1->w; opj_t1_dec_sigpass_step_raw( t1, flagsp, - data2, + data + 2 * l_w, oneplushalf, - 0, /* vsc */ + OPJ_FALSE, /* vsc */ 2U); - data2 += t1->w; opj_t1_dec_sigpass_step_raw( t1, flagsp, - data2, + data + 3 * l_w, oneplushalf, - 0, /* vsc */ + OPJ_FALSE, /* vsc */ 3U); - data2 += t1->w; - flagsp ++; } - data1 += t1->w << 2; - flagsp += 2; } - if (k < t1->h) { - for (i = 0; i < t1->w; ++i) { - OPJ_INT32* data2 = data1 + i; - for (j = 0; j < t1->h - k; ++j) { - opj_t1_dec_sigpass_step_raw( - t1, - flagsp, - data2, - oneplushalf, - 0, /* vsc */ - j); - data2 += t1->w; - } - flagsp ++; + } + if (k < t1->h) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + for (j = 0; j < t1->h - k; ++j) { + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data + j * l_w, + oneplushalf, + cblksty & J2K_CCP_CBLKSTY_VSC, /* vsc */ + j); } } } } -#define opj_t1_dec_sigpass_mqc_internal(t1, bpno, w, h, flags_stride) \ +#define opj_t1_dec_sigpass_mqc_internal(t1, bpno, vsc, w, h, flags_stride) \ { \ OPJ_INT32 one, half, oneplushalf; \ OPJ_UINT32 i, j, k; \ - OPJ_INT32 *data1 = t1->data; \ - opj_flag_t *flagsp = &t1->flags[flags_stride + 1]; \ + register OPJ_INT32 *data = t1->data; \ + register opj_flag_t *flagsp = &t1->flags[(flags_stride) + 1]; \ + const OPJ_UINT32 l_w = w; \ + opj_mqc_t* mqc = &(t1->mqc); \ + DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + register OPJ_UINT32 v; \ one = 1 << bpno; \ half = one >> 1; \ oneplushalf = one | half; \ - for (k = 0; k < (h & ~3u); k += 4) { \ - for (i = 0; i < w; ++i) { \ - OPJ_INT32 *data2 = data1 + i; \ - if( *flagsp != 0 ) { \ - opj_t1_dec_sigpass_step_mqc(t1, flagsp, data2, oneplushalf, 0U, flags_stride); \ - data2 += w; \ - opj_t1_dec_sigpass_step_mqc(t1, flagsp, data2, oneplushalf, 1U, flags_stride); \ - data2 += w; \ - opj_t1_dec_sigpass_step_mqc(t1, flagsp, data2, oneplushalf, 2U, flags_stride); \ - data2 += w; \ - opj_t1_dec_sigpass_step_mqc(t1, flagsp, data2, oneplushalf, 3U, flags_stride); \ - data2 += w; \ + for (k = 0; k < (h & ~3u); k += 4, data += 3*l_w, flagsp += 2) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + opj_flag_t flags = *flagsp; \ + if( flags != 0 ) { \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 0, mqc, curctx, v, a, c, ct, oneplushalf, vsc); \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 1, mqc, curctx, v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 2, mqc, curctx, v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 3, mqc, curctx, v, a, c, ct, oneplushalf, OPJ_FALSE); \ + *flagsp = flags; \ } \ - flagsp ++; \ } \ - data1 += w << 2; \ - flagsp += 2; \ } \ - for (i = 0; i < w; ++i) { \ - OPJ_INT32 *data2 = data1 + i; \ - for (j = k; j < h; ++j) { \ - opj_t1_dec_sigpass_step_mqc(t1, flagsp, data2, oneplushalf, j - k, flags_stride); \ - data2 += w; \ + UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + if( k < h ) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + for (j = 0; j < h - k; ++j) { \ + opj_t1_dec_sigpass_step_mqc(t1, flagsp, \ + data + j * l_w, oneplushalf, j, flags_stride, vsc); \ } \ - flagsp ++; \ + } \ } \ } -static void opj_t1_dec_sigpass_mqc_64x64( +static void opj_t1_dec_sigpass_mqc_64x64_novsc( opj_t1_t *t1, OPJ_INT32 bpno) { - opj_t1_dec_sigpass_mqc_internal(t1, bpno, 64, 64, 66); + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_FALSE, 64, 64, 66); } -static void opj_t1_dec_sigpass_mqc_generic( +static void opj_t1_dec_sigpass_mqc_64x64_vsc( opj_t1_t *t1, OPJ_INT32 bpno) { - opj_t1_dec_sigpass_mqc_internal(t1, bpno, t1->w, t1->h, t1->w + 2); + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_TRUE, 64, 64, 66); } -static void opj_t1_dec_sigpass_mqc_vsc( +static void opj_t1_dec_sigpass_mqc_generic_novsc( opj_t1_t *t1, OPJ_INT32 bpno) { - OPJ_INT32 one, half, oneplushalf, vsc; - OPJ_UINT32 i, j, k; - OPJ_INT32 *data1 = t1->data; - opj_flag_t *flagsp = &T1_FLAGS(0, 0); - one = 1 << bpno; - half = one >> 1; - oneplushalf = one | half; - for (k = 0; k < (t1->h & ~3U); k += 4U) { - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - opj_t1_dec_sigpass_step_mqc_vsc(t1, flagsp, data2, oneplushalf, 0, 0U); - data2 += t1->w; - opj_t1_dec_sigpass_step_mqc_vsc(t1, flagsp, data2, oneplushalf, 0, 1U); - data2 += t1->w; - opj_t1_dec_sigpass_step_mqc_vsc(t1, flagsp, data2, oneplushalf, 0, 2U); - data2 += t1->w; - opj_t1_dec_sigpass_step_mqc_vsc(t1, flagsp, data2, oneplushalf, 1, 3U); - data2 += t1->w; - flagsp ++; + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_FALSE, t1->w, t1->h, + t1->w + 2U); +} + +static void opj_t1_dec_sigpass_mqc_generic_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_TRUE, t1->w, t1->h, + t1->w + 2U); +} + +static void opj_t1_dec_sigpass_mqc( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 cblksty) +{ + if (t1->w == 64 && t1->h == 64) { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_sigpass_mqc_64x64_vsc(t1, bpno); + } else { + opj_t1_dec_sigpass_mqc_64x64_novsc(t1, bpno); } - data1 += t1->w << 2; - flagsp += 2; - } - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - for (j = k; j < t1->h; ++j) { - vsc = (j == t1->h - 1) ? 1 : 0; - opj_t1_dec_sigpass_step_mqc_vsc( - t1, - flagsp, - data2, - oneplushalf, - vsc, - j - k); - data2 += t1->w; + } else { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_sigpass_mqc_generic_vsc(t1, bpno); + } else { + opj_t1_dec_sigpass_mqc_generic_novsc(t1, bpno); } - flagsp ++; } } - /** Encode refinement pass step */ @@ -821,17 +709,13 @@ static INLINE void opj_t1_enc_refpass_step(opj_t1_t *t1, OPJ_INT32 one, OPJ_INT32 *nmsedec, OPJ_BYTE type, - OPJ_UINT32 ci, - OPJ_UINT32 vsc) + OPJ_UINT32 ci) { OPJ_UINT32 v; opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ OPJ_UINT32 const shift_flags = - vsc ? - ((*flagsp >> (ci * 3U)) & ~(T1_SIGMA_SW | T1_SIGMA_S | T1_SIGMA_SE | T1_CHI_S)) - : (*flagsp >> (ci * 3U)); if ((shift_flags & (T1_SIGMA_THIS | T1_PI_THIS)) == T1_SIGMA_THIS) { @@ -862,71 +746,49 @@ static INLINE void opj_t1_dec_refpass_step_raw( { OPJ_UINT32 v; - opj_raw_t *raw = &(t1->raw); /* RAW component */ + opj_mqc_t *mqc = &(t1->mqc); /* RAW component */ if ((*flagsp & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == (T1_SIGMA_THIS << (ci * 3U))) { - v = opj_raw_decode(raw); + v = opj_mqc_raw_decode(mqc); *datap += (v ^ (*datap < 0)) ? poshalf : -poshalf; *flagsp |= T1_MU_THIS << (ci * 3U); } } -static INLINE void opj_t1_dec_refpass_step_mqc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_UINT32 ci) -{ - OPJ_UINT32 v; - - opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ - - if ((*flagsp & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == - (T1_SIGMA_THIS << (ci * 3U))) { - OPJ_UINT32 ctxt = opj_t1_getctxno_mag(*flagsp >> (ci * 3U)); - opj_mqc_setcurctx(mqc, ctxt); - v = opj_mqc_decode(mqc); - *datap += (v ^ (*datap < 0)) ? poshalf : -poshalf; - *flagsp |= T1_MU_THIS << (ci * 3U); - } +#define opj_t1_dec_refpass_step_mqc_macro(flags, data, data_stride, ci, \ + mqc, curctx, v, a, c, ct, poshalf) \ +{ \ + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == \ + (T1_SIGMA_THIS << (ci * 3U))) { \ + OPJ_UINT32 ctxt = opj_t1_getctxno_mag(flags >> (ci * 3U)); \ + opj_t1_setcurctx(curctx, ctxt); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + data[ci*data_stride] += (v ^ (data[ci*data_stride] < 0)) ? poshalf : -poshalf; \ + flags |= T1_MU_THIS << (ci * 3U); \ + } \ } -static INLINE void opj_t1_dec_refpass_step_mqc_vsc( +static INLINE void opj_t1_dec_refpass_step_mqc( opj_t1_t *t1, opj_flag_t *flagsp, OPJ_INT32 *datap, OPJ_INT32 poshalf, - OPJ_INT32 vsc, OPJ_UINT32 ci) { OPJ_UINT32 v; opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ - - OPJ_UINT32 const shift_flags = - vsc ? - ((*flagsp >> (ci * 3U)) & ~(T1_SIGMA_SW | T1_SIGMA_S | T1_SIGMA_SE | T1_CHI_S)) - : - (*flagsp >> (ci * 3U)); - - - if ((shift_flags & (T1_SIGMA_THIS | T1_PI_THIS)) == T1_SIGMA_THIS) { - OPJ_UINT32 ctxt = opj_t1_getctxno_mag(shift_flags); - opj_mqc_setcurctx(mqc, ctxt); - v = opj_mqc_decode(mqc); - *datap += (v ^ (*datap < 0)) ? poshalf : -poshalf; - *flagsp |= T1_MU_THIS << (ci * 3U); - } + opj_t1_dec_refpass_step_mqc_macro(*flagsp, datap, 0, ci, + mqc, mqc->curctx, v, mqc->a, mqc->c, + mqc->ct, poshalf); } static void opj_t1_enc_refpass( opj_t1_t *t1, OPJ_INT32 bpno, OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 cblksty) + OPJ_BYTE type) { OPJ_UINT32 i, k; const OPJ_INT32 one = 1 << (bpno + T1_NMSEDEC_FRACBITS); @@ -965,7 +827,7 @@ static void opj_t1_enc_refpass( one, nmsedec, type, - 0, 0); + 0); opj_t1_enc_refpass_step( t1, f, @@ -974,7 +836,7 @@ static void opj_t1_enc_refpass( one, nmsedec, type, - 1, 0); + 1); opj_t1_enc_refpass_step( t1, f, @@ -983,7 +845,7 @@ static void opj_t1_enc_refpass( one, nmsedec, type, - 2, 0); + 2); opj_t1_enc_refpass_step( t1, f, @@ -992,7 +854,7 @@ static void opj_t1_enc_refpass( one, nmsedec, type, - 3, cblksty & J2K_CCP_CBLKSTY_VSC); + 3); ++f; } f += extra; @@ -1021,8 +883,7 @@ static void opj_t1_enc_refpass( one, nmsedec, type, - j - k, - (j == t1->h - 1 && (cblksty & J2K_CCP_CBLKSTY_VSC) != 0)); + j - k); } ++f; } @@ -1036,59 +897,52 @@ static void opj_t1_dec_refpass_raw( { OPJ_INT32 one, poshalf; OPJ_UINT32 i, j, k; - OPJ_INT32 *data1 = t1->data; + OPJ_INT32 *data = t1->data; opj_flag_t *flagsp = &T1_FLAGS(0, 0); + const OPJ_UINT32 l_w = t1->w; one = 1 << bpno; poshalf = one >> 1; - for (k = 0; k < (t1->h & ~3U); k += 4) { - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - opj_t1_dec_refpass_step_raw( - t1, - flagsp, - data2, - poshalf, - 0U); - data2 += t1->w; - opj_t1_dec_refpass_step_raw( - t1, - flagsp, - data2, - poshalf, - 1U); - data2 += t1->w; - opj_t1_dec_refpass_step_raw( - t1, - flagsp, - data2, - poshalf, - 2U); - data2 += t1->w; - opj_t1_dec_refpass_step_raw( - t1, - flagsp, - data2, - poshalf, - 3U); - data2 += t1->w; - flagsp ++; + for (k = 0; k < (t1->h & ~3U); k += 4, flagsp += 2, data += 3 * l_w) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + opj_flag_t flags = *flagsp; + if (flags != 0) { + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data, + poshalf, + 0U); + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + l_w, + poshalf, + 1U); + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + 2 * l_w, + poshalf, + 2U); + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + 3 * l_w, + poshalf, + 3U); + } } - data1 += t1->w << 2; - flagsp += 2; } if (k < t1->h) { - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - for (j = k; j < t1->h; ++j) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + for (j = 0; j < t1->h - k; ++j) { opj_t1_dec_refpass_step_raw( t1, flagsp, - data2, + data + j * l_w, poshalf, - j - k); - data2 += t1->w; + j); } - flagsp ++; } } } @@ -1097,35 +951,41 @@ static void opj_t1_dec_refpass_raw( { \ OPJ_INT32 one, poshalf; \ OPJ_UINT32 i, j, k; \ - OPJ_INT32 *data1 = t1->data; \ - opj_flag_t *flagsp = &t1->flags[flags_stride + 1]; \ + register OPJ_INT32 *data = t1->data; \ + register opj_flag_t *flagsp = &t1->flags[flags_stride + 1]; \ + const OPJ_UINT32 l_w = w; \ + opj_mqc_t* mqc = &(t1->mqc); \ + DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + register OPJ_UINT32 v; \ one = 1 << bpno; \ poshalf = one >> 1; \ - for (k = 0; k < (h & ~3u); k += 4) { \ - for (i = 0; i < w; ++i) { \ - OPJ_INT32 *data2 = data1 + i; \ - if( *flagsp != 0 ) { \ - opj_t1_dec_refpass_step_mqc(t1, flagsp, data2, poshalf, 0U); \ - data2 += w; \ - opj_t1_dec_refpass_step_mqc(t1, flagsp, data2, poshalf, 1U); \ - data2 += w; \ - opj_t1_dec_refpass_step_mqc(t1, flagsp, data2, poshalf, 2U); \ - data2 += w; \ - opj_t1_dec_refpass_step_mqc(t1, flagsp, data2, poshalf, 3U); \ - data2 += w; \ + for (k = 0; k < (h & ~3u); k += 4, data += 3*l_w, flagsp += 2) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + opj_flag_t flags = *flagsp; \ + if( flags != 0 ) { \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 0, \ + mqc, curctx, v, a, c, ct, poshalf); \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 1, \ + mqc, curctx, v, a, c, ct, poshalf); \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 2, \ + mqc, curctx, v, a, c, ct, poshalf); \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 3, \ + mqc, curctx, v, a, c, ct, poshalf); \ + *flagsp = flags; \ } \ - flagsp ++; \ } \ - data1 += w << 2; \ - flagsp += 2; \ } \ - for (i = 0; i < w; ++i) { \ - OPJ_INT32 *data2 = data1 + i; \ - for (j = k; j < h; ++j) { \ - opj_t1_dec_refpass_step_mqc(t1, flagsp, data2, poshalf, j - k); \ - data2 += w; \ + UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + if( k < h ) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + for (j = 0; j < h - k; ++j) { \ + opj_t1_dec_refpass_step_mqc(t1, flagsp, data + j * l_w, poshalf, j); \ } \ - flagsp ++; \ + } \ } \ } @@ -1143,51 +1003,14 @@ static void opj_t1_dec_refpass_mqc_generic( opj_t1_dec_refpass_mqc_internal(t1, bpno, t1->w, t1->h, t1->w + 2U); } -static void opj_t1_dec_refpass_mqc_vsc( +static void opj_t1_dec_refpass_mqc( opj_t1_t *t1, OPJ_INT32 bpno) { - OPJ_INT32 one, poshalf; - OPJ_UINT32 i, j, k; - OPJ_INT32 vsc; - OPJ_INT32 *data1 = t1->data; - opj_flag_t *flagsp = &T1_FLAGS(0, 0); - one = 1 << bpno; - poshalf = one >> 1; - for (k = 0; k < (t1->h & ~(OPJ_UINT32)3U); k += 4U) { - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - opj_t1_dec_refpass_step_mqc_vsc(t1, flagsp, data2, poshalf, - 0, 0U); - data2 += t1->w; - opj_t1_dec_refpass_step_mqc_vsc(t1, flagsp, data2, poshalf, - 0, 1U); - data2 += t1->w; - opj_t1_dec_refpass_step_mqc_vsc(t1, flagsp, data2, poshalf, - 0, 2U); - data2 += t1->w; - opj_t1_dec_refpass_step_mqc_vsc(t1, flagsp, data2, poshalf, - 1, 3U); - data2 += t1->w; - flagsp ++; - } - data1 += t1->w << 2; - flagsp += 2U; - } - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - for (j = k; j < t1->h; ++j) { - vsc = (j == t1->h - 1) ? 1 : 0; - opj_t1_dec_refpass_step_mqc_vsc( - t1, - flagsp, - data2, - poshalf, - vsc, - j - k); - data2 += t1->w; - } - flagsp ++; + if (t1->w == 64 && t1->h == 64) { + opj_t1_dec_refpass_mqc_64x64(t1, bpno); + } else { + opj_t1_dec_refpass_mqc_generic(t1, bpno); } } @@ -1228,13 +1051,9 @@ static void opj_t1_enc_clnpass_step( for (ci = runlen; ci < lim; ++ci) { OPJ_UINT32 vsc; - OPJ_UINT32 vsc_mask; opj_flag_t flags; - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (ci == lim - 1)) ? 1 : 0; - vsc_mask = vsc ? ~((T1_SIGMA_SW | T1_SIGMA_S | T1_SIGMA_SE | T1_CHI_S) << - (ci * 3U)) : ~0U; - flags = *flagsp & vsc_mask; + flags = *flagsp; if ((agg != 0) && (ci == runlen)) { goto LABEL_PARTIAL; @@ -1252,11 +1071,9 @@ static void opj_t1_enc_clnpass_step( OPJ_UINT32 ctxt2, spb; OPJ_UINT32 lu; LABEL_PARTIAL: - /* Note: using flags instead of *flagsp & vsc_mask result */ - /* in slow down. Probably because of register pressure */ lu = opj_t1_getctxtno_sc_or_spb_index( - *flagsp & vsc_mask, - flagsp[-1] & vsc_mask, flagsp[1] & vsc_mask, + *flagsp, + flagsp[-1], flagsp[1], ci); *nmsedec += opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)bpno); @@ -1266,13 +1083,14 @@ LABEL_PARTIAL: #endif opj_mqc_setcurctx(mqc, ctxt2); - v = *datap < 0 ? 1 : 0; + v = *datap < 0 ? 1U : 0U; spb = opj_t1_getspb(lu); #ifdef DEBUG_ENC_CLN printf(" spb=%d\n", spb); #endif opj_mqc_encode(mqc, v ^ spb); - opj_t1_update_flags(flagsp, ci, v, t1->w + 2U); + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (ci == 0)) ? 1 : 0; + opj_t1_update_flags(flagsp, ci, v, t1->w + 2U, vsc); } } *flagsp &= ~(T1_PI_THIS << (3U * ci)); @@ -1280,115 +1098,49 @@ LABEL_PARTIAL: } } - -static void opj_t1_dec_clnpass_step_partial( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 oneplushalf, - OPJ_UINT32 ci) -{ - OPJ_UINT32 v; - opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ - - OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( - *flagsp, flagsp[-1], flagsp[1], - ci); - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc(lu)); - v = opj_mqc_decode(mqc) ^ opj_t1_getspb(lu); - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_update_flags(flagsp, ci, v, t1->w + 2U); - /* *flagsp &= ~(T1_PI_THIS << (3U * ci)); */ +#define opj_t1_dec_clnpass_step_macro(check_flags, partial, \ + flags, flagsp, flags_stride, data, \ + data_stride, ci, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc) \ +{ \ + if ( !check_flags || !(flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U)))) {\ + do { \ + if( !partial ) { \ + OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); \ + opj_t1_setcurctx(curctx, ctxt1); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + if( !v ) \ + break; \ + } \ + { \ + OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( \ + flags, flagsp[-1], flagsp[1], \ + ci); \ + opj_t1_setcurctx(curctx, opj_t1_getctxno_sc(lu)); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + v = v ^ opj_t1_getspb(lu); \ + data[ci*data_stride] = v ? -oneplushalf : oneplushalf; \ + opj_t1_update_flags_macro(flags, flagsp, ci, v, flags_stride, vsc); \ + } \ + } while(0); \ + } \ } static void opj_t1_dec_clnpass_step( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 oneplushalf, - OPJ_UINT32 ci) -{ - OPJ_UINT32 v; - - opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ - if (!(*flagsp & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U)))) { - OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, *flagsp >> (ci * 3U)); - opj_mqc_setcurctx(mqc, ctxt1); - if (opj_mqc_decode(mqc)) { - OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( - *flagsp, flagsp[-1], flagsp[1], - ci); - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc(lu)); - v = opj_mqc_decode(mqc) ^ opj_t1_getspb(lu); - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_update_flags(flagsp, ci, v, t1->w + 2U); - } - } - /* *flagsp &= ~(T1_PI_THIS << (3U * ci)); */ -} - -static void opj_t1_dec_clnpass_step_only_if_flag_not_sig_visit( opj_t1_t *t1, opj_flag_t *flagsp, OPJ_INT32 *datap, OPJ_INT32 oneplushalf, OPJ_UINT32 ci, - OPJ_UINT32 flags_stride) + OPJ_UINT32 vsc) { OPJ_UINT32 v; opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ - - OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, *flagsp >> (ci * 3U)); - opj_mqc_setcurctx(mqc, ctxt1); - if (opj_mqc_decode(mqc)) { - OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( - *flagsp, flagsp[-1], flagsp[1], - ci); - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc(lu)); - v = opj_mqc_decode(mqc) ^ opj_t1_getspb(lu); - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_update_flags(flagsp, ci, v, flags_stride); - } -} - -static void opj_t1_dec_clnpass_step_vsc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 oneplushalf, - OPJ_INT32 partial, - OPJ_INT32 vsc, - OPJ_UINT32 ci) -{ - OPJ_UINT32 v; - - opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ - - OPJ_UINT32 vsc_mask = vsc ? ~((T1_SIGMA_SW | T1_SIGMA_S | T1_SIGMA_SE | - T1_CHI_S) << - (ci * 3U)) : ~0U; - OPJ_UINT32 flags = *flagsp & vsc_mask; - if (partial) { - goto LABEL_PARTIAL; - } - if (!(flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U)))) { - OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); - opj_mqc_setcurctx(mqc, ctxt1); - if (opj_mqc_decode(mqc)) { - OPJ_UINT32 lu; -LABEL_PARTIAL: - lu = opj_t1_getctxtno_sc_or_spb_index( - *flagsp & vsc_mask, flagsp[-1] & vsc_mask, - flagsp[1] & vsc_mask, - ci); - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc(lu)); - v = opj_mqc_decode(mqc) ^ opj_t1_getspb(lu); - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_update_flags(flagsp, ci, v, t1->w + 2U); - } - } - /* *flagsp &= ~(T1_PI_THIS << (3U * ci)); */ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, + *flagsp, flagsp, t1->w + 2U, datap, + 0, ci, mqc, mqc->curctx, + v, mqc->a, mqc->c, mqc->ct, oneplushalf, vsc); } static void opj_t1_enc_clnpass( @@ -1403,10 +1155,6 @@ static void opj_t1_enc_clnpass( opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ - const OPJ_UINT32 agg_mask = (cblksty & J2K_CCP_CBLKSTY_VSC) ? - ~(T1_SIGMA_15 | T1_SIGMA_16 | T1_SIGMA_17 | T1_CHI_5) : - ~0U; - *nmsedec = 0; #ifdef DEBUG_ENC_CLN printf("enc_clnpass: bpno=%d\n", bpno); @@ -1419,7 +1167,7 @@ static void opj_t1_enc_clnpass( #ifdef DEBUG_ENC_CLN printf(" i=%d\n", i); #endif - agg = !(T1_FLAGS(i, k) & agg_mask); + agg = !(T1_FLAGS(i, k)); #ifdef DEBUG_ENC_CLN printf(" agg=%d\n", agg); #endif @@ -1479,142 +1227,165 @@ static void opj_t1_enc_clnpass( } } -#define opj_t1_dec_clnpass_internal(t1, bpno, cblksty, w, h, flags_stride) \ +#define opj_t1_dec_clnpass_internal(t1, bpno, vsc, w, h, flags_stride) \ { \ - OPJ_INT32 one, half, oneplushalf, agg, vsc; \ + OPJ_INT32 one, half, oneplushalf; \ OPJ_UINT32 runlen; \ OPJ_UINT32 i, j, k; \ - OPJ_INT32 segsym = cblksty & J2K_CCP_CBLKSTY_SEGSYM; \ - \ - opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ \ - \ + const OPJ_UINT32 l_w = w; \ + opj_mqc_t* mqc = &(t1->mqc); \ + register OPJ_INT32 *data = t1->data; \ + register opj_flag_t *flagsp = &t1->flags[flags_stride + 1]; \ + DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + register OPJ_UINT32 v; \ one = 1 << bpno; \ half = one >> 1; \ oneplushalf = one | half; \ - if (cblksty & J2K_CCP_CBLKSTY_VSC) { \ - opj_flag_t *flagsp1 = &t1->flags[flags_stride + 1]; \ - const OPJ_UINT32 agg_mask = ~(T1_SIGMA_15 | T1_SIGMA_16 | T1_SIGMA_17 | T1_CHI_5); \ - for (k = 0; k < h; k += 4) { \ - for (i = 0; i < w; ++i) { \ - opj_flag_t *flagsp2 = flagsp1 + i; \ - if (k + 3 < h) { \ - agg = !(*flagsp2 & agg_mask); \ - } else { \ - agg = 0; \ - } \ - if (agg) { \ - opj_mqc_setcurctx(mqc, T1_CTXNO_AGG); \ - if (!opj_mqc_decode(mqc)) { \ + for (k = 0; k < (h & ~3u); k += 4, data += 3*l_w, flagsp += 2) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + opj_flag_t flags = *flagsp; \ + if (flags == 0) { \ + OPJ_UINT32 partial = OPJ_TRUE; \ + opj_t1_setcurctx(curctx, T1_CTXNO_AGG); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + if (!v) { \ continue; \ } \ - opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); \ - runlen = opj_mqc_decode(mqc); \ - runlen = (runlen << 1) | opj_mqc_decode(mqc); \ + opj_t1_setcurctx(curctx, T1_CTXNO_UNI); \ + opj_mqc_decode_macro(runlen, mqc, curctx, a, c, ct); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + runlen = (runlen << 1) | v; \ + switch(runlen) { \ + case 0: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, OPJ_TRUE,\ + flags, flagsp, flags_stride, data, \ + l_w, 0, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc); \ + partial = OPJ_FALSE; \ + /* FALLTHRU */ \ + case 1: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, partial,\ + flags, flagsp, flags_stride, data, \ + l_w, 1, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + partial = OPJ_FALSE; \ + /* FALLTHRU */ \ + case 2: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, partial,\ + flags, flagsp, flags_stride, data, \ + l_w, 2, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + partial = OPJ_FALSE; \ + /* FALLTHRU */ \ + case 3: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, partial,\ + flags, flagsp, flags_stride, data, \ + l_w, 3, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + break; \ + } \ } else { \ - runlen = 0; \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 0, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc); \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 1, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 2, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 3, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ } \ - for (j = k + runlen; j < k + 4 && j < h; ++j) { \ - vsc = (j == k + 3 || j == h - 1) ? 1 : 0; \ - opj_t1_dec_clnpass_step_vsc( \ - t1, \ - flagsp2, \ - &t1->data[(j * w) + i], \ - oneplushalf, \ - agg && (j == k + runlen), \ - vsc, j - k); \ - } \ - *flagsp2 &= ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ + *flagsp = flags & ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ } \ - flagsp1 += flags_stride; \ } \ - } else { \ - OPJ_INT32 *data1 = t1->data; \ - opj_flag_t *flagsp1 = &t1->flags[flags_stride + 1]; \ - for (k = 0; k < (h & ~3u); k += 4) { \ - for (i = 0; i < w; ++i) { \ - OPJ_INT32 *data2 = data1 + i; \ - opj_flag_t *flagsp2 = flagsp1 + i; \ - if (*flagsp2 == 0) { \ - opj_mqc_setcurctx(mqc, T1_CTXNO_AGG); \ - if (!opj_mqc_decode(mqc)) { \ - continue; \ - } \ - opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); \ - runlen = opj_mqc_decode(mqc); \ - runlen = (runlen << 1) | opj_mqc_decode(mqc); \ - data2 += runlen * w; \ - for (j = runlen; j < 4; ++j) { \ - if (j == runlen) { \ - opj_t1_dec_clnpass_step_partial(t1, flagsp2, data2, oneplushalf, j); \ - } else { \ - opj_t1_dec_clnpass_step(t1, flagsp2, data2, oneplushalf, j); \ - } \ - data2 += w; \ - } \ - } else { \ - if (!(*flagsp2 & ((T1_SIGMA_THIS | T1_PI_THIS) << (0 * 3U)))) {\ - opj_t1_dec_clnpass_step_only_if_flag_not_sig_visit(t1, flagsp2, data2, oneplushalf, 0U, flags_stride); \ - } \ - data2 += w; \ - if (!(*flagsp2 & ((T1_SIGMA_THIS | T1_PI_THIS) << (1 * 3U)))) {\ - opj_t1_dec_clnpass_step_only_if_flag_not_sig_visit(t1, flagsp2, data2, oneplushalf, 1U, flags_stride); \ - } \ - data2 += w; \ - if (!(*flagsp2 & ((T1_SIGMA_THIS | T1_PI_THIS) << (2 * 3U)))) {\ - opj_t1_dec_clnpass_step_only_if_flag_not_sig_visit(t1, flagsp2, data2, oneplushalf, 2U, flags_stride); \ - } \ - data2 += w; \ - if (!(*flagsp2 & ((T1_SIGMA_THIS | T1_PI_THIS) << (3 * 3U)))) {\ - opj_t1_dec_clnpass_step_only_if_flag_not_sig_visit(t1, flagsp2, data2, oneplushalf, 3U, flags_stride); \ - } \ - data2 += w; \ - } \ - *flagsp2 &= ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ - } \ - data1 += w << 2; \ - flagsp1 += flags_stride; \ - } \ - for (i = 0; i < w; ++i) { \ - OPJ_INT32 *data2 = data1 + i; \ - opj_flag_t *flagsp2 = flagsp1 + i; \ - for (j = k; j < h; ++j) { \ - opj_t1_dec_clnpass_step(t1, flagsp2, data2, oneplushalf, j - k); \ - data2 += w; \ + UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + if( k < h ) { \ + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { \ + for (j = 0; j < h - k; ++j) { \ + opj_t1_dec_clnpass_step(t1, flagsp, data + j * l_w, oneplushalf, j, vsc); \ } \ - *flagsp2 &= ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ + *flagsp &= ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ } \ } \ - \ - if (segsym) { \ - OPJ_UINT32 v = 0; \ - opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); \ - v = opj_mqc_decode(mqc); \ - v = (v << 1) | opj_mqc_decode(mqc); \ - v = (v << 1) | opj_mqc_decode(mqc); \ - v = (v << 1) | opj_mqc_decode(mqc); \ - /* \ - if (v!=0xa) { \ - opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v); \ - } \ - */ \ - } \ } -static void opj_t1_dec_clnpass_64x64( +static void opj_t1_dec_clnpass_check_segsym(opj_t1_t *t1, OPJ_INT32 cblksty) +{ + if (cblksty & J2K_CCP_CBLKSTY_SEGSYM) { + opj_mqc_t* mqc = &(t1->mqc); + OPJ_UINT32 v, v2; + opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); + opj_mqc_decode(v, mqc); + opj_mqc_decode(v2, mqc); + v = (v << 1) | v2; + opj_mqc_decode(v2, mqc); + v = (v << 1) | v2; + opj_mqc_decode(v2, mqc); + v = (v << 1) | v2; + /* + if (v!=0xa) { + opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v); + } + */ + } +} + +static void opj_t1_dec_clnpass_64x64_novsc( opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 cblksty) + OPJ_INT32 bpno) +{ + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_FALSE, 64, 64, 66); +} + +static void opj_t1_dec_clnpass_64x64_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_TRUE, 64, 64, 66); +} + +static void opj_t1_dec_clnpass_generic_novsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_FALSE, t1->w, t1->h, + t1->w + 2U); +} + +static void opj_t1_dec_clnpass_generic_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) { - opj_t1_dec_clnpass_internal(t1, bpno, cblksty, 64, 64, 66); + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_TRUE, t1->w, t1->h, + t1->w + 2U); } -static void opj_t1_dec_clnpass_generic( +static void opj_t1_dec_clnpass( opj_t1_t *t1, OPJ_INT32 bpno, OPJ_INT32 cblksty) { - opj_t1_dec_clnpass_internal(t1, bpno, cblksty, t1->w, t1->h, - t1->w + 2U); + if (t1->w == 64 && t1->h == 64) { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_clnpass_64x64_vsc(t1, bpno); + } else { + opj_t1_dec_clnpass_64x64_novsc(t1, bpno); + } + } else { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_clnpass_generic_vsc(t1, bpno); + } else { + opj_t1_dec_clnpass_generic_novsc(t1, bpno); + } + } + opj_t1_dec_clnpass_check_segsym(t1, cblksty); } @@ -1655,27 +1426,18 @@ static OPJ_BOOL opj_t1_allocate_buffers( OPJ_UINT32 w, OPJ_UINT32 h) { - size_t flagssize; + OPJ_UINT32 flagssize; OPJ_UINT32 flags_stride; + /* No risk of overflow. Prior checks ensure those assert are met */ + /* They are per the specification */ + assert(w <= 1024); + assert(h <= 1024); + assert(w * h <= 4096); + /* encoder uses tile buffer, so no need to allocate */ if (!t1->encoder) { - size_t datasize; - -#if (SIZE_MAX / 0xFFFFFFFFU) < 0xFFFFFFFFU /* UINT32_MAX */ - /* Overflow check */ - if ((w > 0U) && ((size_t)h > (SIZE_MAX / (size_t)w))) { - /* FIXME event manager error callback */ - return OPJ_FALSE; - } -#endif - datasize = (size_t)w * h; - - /* Overflow check */ - if (datasize > (SIZE_MAX / sizeof(OPJ_INT32))) { - /* FIXME event manager error callback */ - return OPJ_FALSE; - } + OPJ_UINT32 datasize = w * h; if (datasize > (size_t)t1->datasize) { opj_aligned_free(t1->data); @@ -1684,15 +1446,7 @@ static OPJ_BOOL opj_t1_allocate_buffers( /* FIXME event manager error callback */ return OPJ_FALSE; } -#if SIZE_MAX > 0xFFFFFFFFU /* UINT32_MAX */ - /* TODO remove this if t1->datasize type changes to size_t */ - /* Overflow check */ - if (datasize > (size_t)0xFFFFFFFFU /* UINT32_MAX */) { - /* FIXME event manager error callback */ - return OPJ_FALSE; - } -#endif - t1->datasize = (OPJ_UINT32)datasize; + t1->datasize = datasize; } /* memset first arg is declared to never be null by gcc */ if (t1->data != NULL) { @@ -1700,40 +1454,18 @@ static OPJ_BOOL opj_t1_allocate_buffers( } } - /* Overflow check */ - if (w > (0xFFFFFFFFU /* UINT32_MAX */ - 2U)) { - /* FIXME event manager error callback */ - return OPJ_FALSE; - } flags_stride = w + 2U; /* can't be 0U */ -#if (SIZE_MAX - 3U) < 0xFFFFFFFFU /* UINT32_MAX */ - /* Overflow check */ - if (h > (0xFFFFFFFFU /* UINT32_MAX */ - 3U)) { - /* FIXME event manager error callback */ - return OPJ_FALSE; - } -#endif flagssize = (h + 3U) / 4U + 2U; - /* Overflow check */ - if (flagssize > (SIZE_MAX / (size_t)flags_stride)) { - /* FIXME event manager error callback */ - return OPJ_FALSE; - } - flagssize *= (size_t)flags_stride; + flagssize *= flags_stride; { - /* BIG FAT XXX */ opj_flag_t* p; OPJ_UINT32 x; OPJ_UINT32 flags_height = (h + 3U) / 4U; - if (flagssize > (size_t)t1->flagssize) { - /* Overflow check */ - if (flagssize > (SIZE_MAX / sizeof(opj_flag_t))) { - /* FIXME event manager error callback */ - return OPJ_FALSE; - } + if (flagssize > t1->flagssize) { + opj_aligned_free(t1->flags); t1->flags = (opj_flag_t*) opj_aligned_malloc(flagssize * sizeof( opj_flag_t)); @@ -1741,16 +1473,8 @@ static OPJ_BOOL opj_t1_allocate_buffers( /* FIXME event manager error callback */ return OPJ_FALSE; } -#if SIZE_MAX > 0xFFFFFFFFU /* UINT32_MAX */ - /* TODO remove this if t1->flagssize type changes to size_t */ - /* Overflow check */ - if (flagssize > (size_t)0xFFFFFFFFU /* UINT32_MAX */) { - /* FIXME event manager error callback */ - return OPJ_FALSE; - } -#endif } - t1->flagssize = (OPJ_UINT32)flagssize; + t1->flagssize = flagssize; memset(t1->flags, 0, flagssize * sizeof(opj_flag_t)); @@ -1833,6 +1557,8 @@ void opj_t1_destroy(opj_t1_t *p_t1) p_t1->flags = 00; } + opj_free(p_t1->cblkdatabuffer); + opj_free(p_t1); } @@ -1842,7 +1568,11 @@ typedef struct { opj_tcd_band_t* band; opj_tcd_tilecomp_t* tilec; opj_tccp_t* tccp; + OPJ_BOOL mustuse_cblkdatabuffer; volatile OPJ_BOOL* pret; + opj_event_mgr_t *p_manager; + opj_mutex_t* p_manager_mutex; + OPJ_BOOL check_pterm; } opj_t1_cblk_decode_processing_job_t; static void opj_t1_destroy_wrapper(void* t1) @@ -1871,7 +1601,9 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls) band = job->band; tilec = job->tilec; tccp = job->tccp; - tile_w = (OPJ_UINT32)(tilec->x1 - tilec->x0); + tile_w = (OPJ_UINT32)(tilec->resolutions[tilec->minimum_num_resolutions - 1].x1 + - + tilec->resolutions[tilec->minimum_num_resolutions - 1].x0); if (!*(job->pret)) { opj_free(job); @@ -1883,13 +1615,17 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls) t1 = opj_t1_create(OPJ_FALSE); opj_tls_set(tls, OPJ_TLS_KEY_T1, t1, opj_t1_destroy_wrapper); } + t1->mustuse_cblkdatabuffer = job->mustuse_cblkdatabuffer; if (OPJ_FALSE == opj_t1_decode_cblk( t1, cblk, band->bandno, (OPJ_UINT32)tccp->roishift, - tccp->cblksty)) { + tccp->cblksty, + job->p_manager, + job->p_manager_mutex, + job->check_pterm)) { *(job->pret) = OPJ_FALSE; opj_free(job); return; @@ -1906,26 +1642,67 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls) y += pres->y1 - pres->y0; } - datap = t1->data; + datap = cblk->decoded_data ? cblk->decoded_data : t1->data; cblk_w = t1->w; cblk_h = t1->h; if (tccp->roishift) { - OPJ_INT32 thresh = 1 << tccp->roishift; - for (j = 0; j < cblk_h; ++j) { - for (i = 0; i < cblk_w; ++i) { - OPJ_INT32 val = datap[(j * cblk_w) + i]; - OPJ_INT32 mag = abs(val); - if (mag >= thresh) { - mag >>= tccp->roishift; - datap[(j * cblk_w) + i] = val < 0 ? -mag : mag; + if (tccp->roishift >= 31) { + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + datap[(j * cblk_w) + i] = 0; + } + } + } else { + OPJ_INT32 thresh = 1 << tccp->roishift; + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + OPJ_INT32 val = datap[(j * cblk_w) + i]; + OPJ_INT32 mag = abs(val); + if (mag >= thresh) { + mag >>= tccp->roishift; + datap[(j * cblk_w) + i] = val < 0 ? -mag : mag; + } } } } } - if (tccp->qmfbid == 1) { - OPJ_INT32* OPJ_RESTRICT tiledp = &tilec->data[(OPJ_UINT32)y * tile_w + - (OPJ_UINT32)x]; + + /* Both can be non NULL if for example decoding a full tile and then */ + /* partially a tile. In which case partial decoding should be the */ + /* priority */ + assert((cblk->decoded_data != NULL) || (tilec->data != NULL)); + + if (cblk->decoded_data) { + if (tccp->qmfbid == 1) { + for (j = 0; j < cblk_h; ++j) { + i = 0; + for (; i < (cblk_w & ~(OPJ_UINT32)3U); i += 4U) { + OPJ_INT32 tmp0 = datap[(j * cblk_w) + i + 0U]; + OPJ_INT32 tmp1 = datap[(j * cblk_w) + i + 1U]; + OPJ_INT32 tmp2 = datap[(j * cblk_w) + i + 2U]; + OPJ_INT32 tmp3 = datap[(j * cblk_w) + i + 3U]; + datap[(j * cblk_w) + i + 0U] = tmp0 / 2; + datap[(j * cblk_w) + i + 1U] = tmp1 / 2; + datap[(j * cblk_w) + i + 2U] = tmp2 / 2; + datap[(j * cblk_w) + i + 3U] = tmp3 / 2; + } + for (; i < cblk_w; ++i) { + datap[(j * cblk_w) + i] /= 2; + } + } + } else { /* if (tccp->qmfbid == 0) */ + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + OPJ_FLOAT32 tmp = ((OPJ_FLOAT32)(*datap)) * band->stepsize; + memcpy(datap, &tmp, sizeof(tmp)); + datap++; + } + } + } + } else if (tccp->qmfbid == 1) { + OPJ_INT32* OPJ_RESTRICT tiledp = &tilec->data[(size_t)y * tile_w + + (size_t)x]; for (j = 0; j < cblk_h; ++j) { i = 0; for (; i < (cblk_w & ~(OPJ_UINT32)3U); i += 4U) { @@ -1933,19 +1710,19 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls) OPJ_INT32 tmp1 = datap[(j * cblk_w) + i + 1U]; OPJ_INT32 tmp2 = datap[(j * cblk_w) + i + 2U]; OPJ_INT32 tmp3 = datap[(j * cblk_w) + i + 3U]; - ((OPJ_INT32*)tiledp)[(j * tile_w) + i + 0U] = tmp0 / 2; - ((OPJ_INT32*)tiledp)[(j * tile_w) + i + 1U] = tmp1 / 2; - ((OPJ_INT32*)tiledp)[(j * tile_w) + i + 2U] = tmp2 / 2; - ((OPJ_INT32*)tiledp)[(j * tile_w) + i + 3U] = tmp3 / 2; + ((OPJ_INT32*)tiledp)[(j * (size_t)tile_w) + i + 0U] = tmp0 / 2; + ((OPJ_INT32*)tiledp)[(j * (size_t)tile_w) + i + 1U] = tmp1 / 2; + ((OPJ_INT32*)tiledp)[(j * (size_t)tile_w) + i + 2U] = tmp2 / 2; + ((OPJ_INT32*)tiledp)[(j * (size_t)tile_w) + i + 3U] = tmp3 / 2; } for (; i < cblk_w; ++i) { OPJ_INT32 tmp = datap[(j * cblk_w) + i]; - ((OPJ_INT32*)tiledp)[(j * tile_w) + i] = tmp / 2; + ((OPJ_INT32*)tiledp)[(j * (size_t)tile_w) + i] = tmp / 2; } } } else { /* if (tccp->qmfbid == 0) */ - OPJ_FLOAT32* OPJ_RESTRICT tiledp = (OPJ_FLOAT32*) &tilec->data[(OPJ_UINT32)y * - tile_w + (OPJ_UINT32)x]; + OPJ_FLOAT32* OPJ_RESTRICT tiledp = (OPJ_FLOAT32*) &tilec->data[(size_t)y * + tile_w + (size_t)x]; for (j = 0; j < cblk_h; ++j) { OPJ_FLOAT32* OPJ_RESTRICT tiledp2 = tiledp; for (i = 0; i < cblk_w; ++i) { @@ -1962,12 +1739,16 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls) } -void opj_t1_decode_cblks(opj_thread_pool_t* tp, +void opj_t1_decode_cblks(opj_tcd_t* tcd, volatile OPJ_BOOL* pret, opj_tcd_tilecomp_t* tilec, - opj_tccp_t* tccp + opj_tccp_t* tccp, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm ) { + opj_thread_pool_t* tp = tcd->thread_pool; OPJ_UINT32 resno, bandno, precno, cblkno; for (resno = 0; resno < tilec->minimum_num_resolutions; ++resno) { @@ -1979,10 +1760,89 @@ void opj_t1_decode_cblks(opj_thread_pool_t* tp, for (precno = 0; precno < res->pw * res->ph; ++precno) { opj_tcd_precinct_t* precinct = &band->precincts[precno]; + if (!opj_tcd_is_subband_area_of_interest(tcd, + tilec->compno, + resno, + band->bandno, + (OPJ_UINT32)precinct->x0, + (OPJ_UINT32)precinct->y0, + (OPJ_UINT32)precinct->x1, + (OPJ_UINT32)precinct->y1)) { + for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; + if (cblk->decoded_data) { +#ifdef DEBUG_VERBOSE + printf("Discarding codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + opj_free(cblk->decoded_data); + cblk->decoded_data = NULL; + } + } + continue; + } + for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; opj_t1_cblk_decode_processing_job_t* job; + if (!opj_tcd_is_subband_area_of_interest(tcd, + tilec->compno, + resno, + band->bandno, + (OPJ_UINT32)cblk->x0, + (OPJ_UINT32)cblk->y0, + (OPJ_UINT32)cblk->x1, + (OPJ_UINT32)cblk->y1)) { + if (cblk->decoded_data) { +#ifdef DEBUG_VERBOSE + printf("Discarding codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + opj_free(cblk->decoded_data); + cblk->decoded_data = NULL; + } + continue; + } + + if (!tcd->whole_tile_decoding) { + OPJ_UINT32 cblk_w = (OPJ_UINT32)(cblk->x1 - cblk->x0); + OPJ_UINT32 cblk_h = (OPJ_UINT32)(cblk->y1 - cblk->y0); + if (cblk->decoded_data != NULL) { +#ifdef DEBUG_VERBOSE + printf("Reusing codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + continue; + } + if (cblk_w == 0 || cblk_h == 0) { + continue; + } +#ifdef DEBUG_VERBOSE + printf("Decoding codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + /* Zero-init required */ + cblk->decoded_data = opj_calloc(1, cblk_w * cblk_h * sizeof(OPJ_INT32)); + if (cblk->decoded_data == NULL) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, + "Cannot allocate cblk->decoded_data\n"); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + *pret = OPJ_FALSE; + return; + } + } else if (cblk->decoded_data) { + /* Not sure if that code path can happen, but better be */ + /* safe than sorry */ + opj_free(cblk->decoded_data); + cblk->decoded_data = NULL; + } + job = (opj_t1_cblk_decode_processing_job_t*) opj_calloc(1, sizeof(opj_t1_cblk_decode_processing_job_t)); if (!job) { @@ -1995,6 +1855,10 @@ void opj_t1_decode_cblks(opj_thread_pool_t* tp, job->tilec = tilec; job->tccp = tccp; job->pret = pret; + job->p_manager_mutex = p_manager_mutex; + job->p_manager = p_manager; + job->check_pterm = check_pterm; + job->mustuse_cblkdatabuffer = opj_thread_pool_get_thread_count(tp) > 1; opj_thread_pool_submit_job(tp, opj_t1_clbl_decode_processor, job); if (!(*pret)) { return; @@ -2012,15 +1876,20 @@ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, opj_tcd_cblk_dec_t* cblk, OPJ_UINT32 orient, OPJ_UINT32 roishift, - OPJ_UINT32 cblksty) + OPJ_UINT32 cblksty, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm) { - opj_raw_t *raw = &(t1->raw); /* RAW component */ opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ OPJ_INT32 bpno_plus_one; OPJ_UINT32 passtype; OPJ_UINT32 segno, passno; + OPJ_BYTE* cblkdata = NULL; + OPJ_UINT32 cblkdataindex = 0; OPJ_BYTE type = T1_TYPE_MQ; /* BYPASS mode */ + OPJ_INT32* original_t1_data = NULL; mqc->lut_ctxno_zc_orient = lut_ctxno_zc + (orient << 9); @@ -2032,6 +1901,18 @@ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, } bpno_plus_one = (OPJ_INT32)(roishift + cblk->numbps); + if (bpno_plus_one >= 31) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_WARNING, + "opj_t1_decode_cblk(): unsupported bpno_plus_one = %d >= 31\n", + bpno_plus_one); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } passtype = 2; opj_mqc_resetstates(mqc); @@ -2039,111 +1920,133 @@ 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); + /* 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) { + OPJ_UINT32 i; + OPJ_UINT32 cblk_len; + + /* Compute whole codeblock length from chunk lengths */ + cblk_len = 0; + for (i = 0; i < cblk->numchunks; i++) { + cblk_len += cblk->chunks[i].len; + } + + /* Allocate temporary memory if needed */ + if (cblk_len + OPJ_COMMON_CBLK_DATA_EXTRA > t1->cblkdatabuffersize) { + cblkdata = (OPJ_BYTE*)opj_realloc(t1->cblkdatabuffer, + cblk_len + OPJ_COMMON_CBLK_DATA_EXTRA); + if (cblkdata == NULL) { + return OPJ_FALSE; + } + t1->cblkdatabuffer = cblkdata; + memset(t1->cblkdatabuffer + cblk_len, 0, OPJ_COMMON_CBLK_DATA_EXTRA); + t1->cblkdatabuffersize = cblk_len + OPJ_COMMON_CBLK_DATA_EXTRA; + } + + /* Concatenate all chunks */ + cblkdata = t1->cblkdatabuffer; + cblk_len = 0; + for (i = 0; i < cblk->numchunks; i++) { + memcpy(cblkdata + cblk_len, cblk->chunks[i].data, cblk->chunks[i].len); + cblk_len += cblk->chunks[i].len; + } + } else if (cblk->numchunks == 1) { + cblkdata = cblk->chunks[0].data; + } + + /* For subtile decoding, directly decode in the decoded_data buffer of */ + /* the code-block. Hack t1->data to point to it, and restore it later */ + if (cblk->decoded_data) { + original_t1_data = t1->data; + t1->data = cblk->decoded_data; + } + for (segno = 0; segno < cblk->real_num_segs; ++segno) { opj_tcd_seg_t *seg = &cblk->segs[segno]; /* BYPASS mode */ type = ((bpno_plus_one <= ((OPJ_INT32)(cblk->numbps)) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; - /* FIXME: slviewer gets here with a null pointer. Why? Partially downloaded and/or corrupt textures? */ - if (seg->data == 00) { - continue; - } + if (type == T1_TYPE_RAW) { - opj_raw_init_dec(raw, (*seg->data) + seg->dataindex, seg->len); + opj_mqc_raw_init_dec(mqc, cblkdata + cblkdataindex, seg->len, + OPJ_COMMON_CBLK_DATA_EXTRA); } else { - if (OPJ_FALSE == opj_mqc_init_dec(mqc, (*seg->data) + seg->dataindex, - seg->len)) { - return OPJ_FALSE; - } + opj_mqc_init_dec(mqc, cblkdata + cblkdataindex, seg->len, + OPJ_COMMON_CBLK_DATA_EXTRA); } + cblkdataindex += seg->len; - if (t1->w == 64 && t1->h == 64) { - for (passno = 0; (passno < seg->real_num_passes) && - (bpno_plus_one >= 1); ++passno) { - switch (passtype) { - case 0: - if (type == T1_TYPE_RAW) { - opj_t1_dec_sigpass_raw(t1, bpno_plus_one, (OPJ_INT32)cblksty); - } else { - if (cblksty & J2K_CCP_CBLKSTY_VSC) { - opj_t1_dec_sigpass_mqc_vsc(t1, bpno_plus_one); - } else { - opj_t1_dec_sigpass_mqc_64x64(t1, bpno_plus_one); - } - } - break; - case 1: - if (type == T1_TYPE_RAW) { - opj_t1_dec_refpass_raw(t1, bpno_plus_one); - } else { - if (cblksty & J2K_CCP_CBLKSTY_VSC) { - opj_t1_dec_refpass_mqc_vsc(t1, bpno_plus_one); - } else { - opj_t1_dec_refpass_mqc_64x64(t1, bpno_plus_one); - } - } - break; - case 2: - opj_t1_dec_clnpass_64x64(t1, bpno_plus_one, (OPJ_INT32)cblksty); - break; - } - - if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { - opj_mqc_resetstates(mqc); - opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); - opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + for (passno = 0; (passno < seg->real_num_passes) && + (bpno_plus_one >= 1); ++passno) { + switch (passtype) { + case 0: + if (type == T1_TYPE_RAW) { + opj_t1_dec_sigpass_raw(t1, bpno_plus_one, (OPJ_INT32)cblksty); + } else { + opj_t1_dec_sigpass_mqc(t1, bpno_plus_one, (OPJ_INT32)cblksty); } - if (++passtype == 3) { - passtype = 0; - bpno_plus_one--; + break; + case 1: + if (type == T1_TYPE_RAW) { + opj_t1_dec_refpass_raw(t1, bpno_plus_one); + } else { + opj_t1_dec_refpass_mqc(t1, bpno_plus_one); } + break; + case 2: + opj_t1_dec_clnpass(t1, bpno_plus_one, (OPJ_INT32)cblksty); + break; } - } else { - for (passno = 0; (passno < seg->real_num_passes) && - (bpno_plus_one >= 1); ++passno) { - switch (passtype) { - case 0: - if (type == T1_TYPE_RAW) { - opj_t1_dec_sigpass_raw(t1, bpno_plus_one, (OPJ_INT32)cblksty); - } else { - if (cblksty & J2K_CCP_CBLKSTY_VSC) { - opj_t1_dec_sigpass_mqc_vsc(t1, bpno_plus_one); - } else { - opj_t1_dec_sigpass_mqc_generic(t1, bpno_plus_one); - } - } - break; - case 1: - if (type == T1_TYPE_RAW) { - opj_t1_dec_refpass_raw(t1, bpno_plus_one); - } else { - if (cblksty & J2K_CCP_CBLKSTY_VSC) { - opj_t1_dec_refpass_mqc_vsc(t1, bpno_plus_one); - } else { - opj_t1_dec_refpass_mqc_generic(t1, bpno_plus_one); - } - } - break; - case 2: - opj_t1_dec_clnpass_generic(t1, bpno_plus_one, (OPJ_INT32)cblksty); - break; - } - if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { - opj_mqc_resetstates(mqc); - opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); - opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); - } - if (++passtype == 3) { - passtype = 0; - bpno_plus_one--; - } + if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { + opj_mqc_resetstates(mqc); + opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + } + if (++passtype == 3) { + passtype = 0; + bpno_plus_one--; } } + + opq_mqc_finish_dec(mqc); } + + if (check_pterm) { + if (mqc->bp + 2 < mqc->end) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_WARNING, + "PTERM check failure: %d remaining bytes in code block (%d used / %d)\n", + (int)(mqc->end - mqc->bp) - 2, + (int)(mqc->bp - mqc->start), + (int)(mqc->end - mqc->start)); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + } else if (mqc->end_of_byte_stream_counter > 2) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_WARNING, + "PTERM check failure: %d synthetized 0xFF markers read\n", + mqc->end_of_byte_stream_counter); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + } + } + + /* Restore original t1->data is needed */ + if (cblk->decoded_data) { + t1->data = original_t1_data; + } + return OPJ_TRUE; } @@ -2171,8 +2074,14 @@ OPJ_BOOL opj_t1_encode_cblks(opj_t1_t *t1, for (bandno = 0; bandno < res->numbands; ++bandno) { opj_tcd_band_t* OPJ_RESTRICT band = &res->bands[bandno]; - OPJ_INT32 bandconst = 8192 * 8192 / ((OPJ_INT32) floor(band->stepsize * 8192)); + OPJ_INT32 bandconst; + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + bandconst = 8192 * 8192 / ((OPJ_INT32) floor(band->stepsize * 8192)); for (precno = 0; precno < res->pw * res->ph; ++precno) { opj_tcd_precinct_t *prc = &band->precincts[precno]; @@ -2181,7 +2090,8 @@ OPJ_BOOL opj_t1_encode_cblks(opj_t1_t *t1, OPJ_INT32* OPJ_RESTRICT tiledp; OPJ_UINT32 cblk_w; OPJ_UINT32 cblk_h; - OPJ_UINT32 i, j, tileIndex = 0, tileLineAdvance; + OPJ_UINT32 i, j, tileLineAdvance; + size_t tileIndex = 0; OPJ_INT32 x = cblk->x0 - band->x0; OPJ_INT32 y = cblk->y0 - band->y0; @@ -2205,7 +2115,7 @@ OPJ_BOOL opj_t1_encode_cblks(opj_t1_t *t1, cblk_h = t1->h; tileLineAdvance = tile_w - cblk_w; - tiledp = &tilec->data[(OPJ_UINT32)y * tile_w + (OPJ_UINT32)x]; + tiledp = &tilec->data[(size_t)y * tile_w + (size_t)x]; t1->data = tiledp; t1->data_stride = tile_w; if (tccp->qmfbid == 1) { @@ -2252,6 +2162,37 @@ OPJ_BOOL opj_t1_encode_cblks(opj_t1_t *t1, return OPJ_TRUE; } +/* Returns whether the pass (bpno, passtype) is terminated */ +static int opj_t1_enc_is_term_pass(opj_tcd_cblk_enc_t* cblk, + OPJ_UINT32 cblksty, + OPJ_INT32 bpno, + OPJ_UINT32 passtype) +{ + /* Is it the last cleanup pass ? */ + if (passtype == 2 && bpno == 0) { + return OPJ_TRUE; + } + + if (cblksty & J2K_CCP_CBLKSTY_TERMALL) { + return OPJ_TRUE; + } + + if ((cblksty & J2K_CCP_CBLKSTY_LAZY)) { + /* For bypass arithmetic bypass, terminate the 4th cleanup pass */ + if ((bpno == ((OPJ_INT32)cblk->numbps - 4)) && (passtype == 2)) { + return OPJ_TRUE; + } + /* and beyond terminate all the magnitude refinement passes (in raw) */ + /* and cleanup passes (in MQC) */ + if ((bpno < ((OPJ_INT32)(cblk->numbps) - 4)) && (passtype > 0)) { + return OPJ_TRUE; + } + } + + return OPJ_FALSE; +} + + /** mod fixed_quality */ static void opj_t1_encode_cblk(opj_t1_t *t1, opj_tcd_cblk_enc_t* cblk, @@ -2279,6 +2220,11 @@ static void opj_t1_encode_cblk(opj_t1_t *t1, OPJ_BYTE type = T1_TYPE_MQ; OPJ_FLOAT64 tempwmsedec; +#ifdef EXTRA_DEBUG + printf("encode_cblk(x=%d,y=%d,x1=%d,y1=%d,orient=%d,compno=%d,level=%d\n", + cblk->x0, cblk->y0, cblk->x1, cblk->y1, orient, compno, level); +#endif + mqc->lut_ctxno_zc_orient = lut_ctxno_zc + (orient << 9); max = 0; @@ -2291,6 +2237,10 @@ static void opj_t1_encode_cblk(opj_t1_t *t1, cblk->numbps = max ? (OPJ_UINT32)((opj_int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS) : 0; + if (cblk->numbps == 0) { + cblk->totalpasses = 0; + return; + } bpno = (OPJ_INT32)(cblk->numbps - 1); passtype = 2; @@ -2303,16 +2253,24 @@ static void opj_t1_encode_cblk(opj_t1_t *t1, for (passno = 0; bpno >= 0; ++passno) { opj_tcd_pass_t *pass = &cblk->passes[passno]; - OPJ_UINT32 correction = 3; type = ((bpno < ((OPJ_INT32)(cblk->numbps) - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + /* If the previous pass was terminating, we need to reset the encoder */ + if (passno > 0 && cblk->passes[passno - 1].term) { + if (type == T1_TYPE_RAW) { + opj_mqc_bypass_init_enc(mqc); + } else { + opj_mqc_restart_init_enc(mqc); + } + } + switch (passtype) { case 0: opj_t1_enc_sigpass(t1, bpno, &nmsedec, type, cblksty); break; case 1: - opj_t1_enc_refpass(t1, bpno, &nmsedec, type, cblksty); + opj_t1_enc_refpass(t1, bpno, &nmsedec, type); break; case 2: opj_t1_enc_clnpass(t1, bpno, &nmsedec, cblksty); @@ -2328,35 +2286,32 @@ static void opj_t1_encode_cblk(opj_t1_t *t1, stepsize, numcomps, mct_norms, mct_numcomps) ; cumwmsedec += tempwmsedec; tile->distotile += tempwmsedec; + pass->distortiondec = cumwmsedec; - /* Code switch "RESTART" (i.e. TERMALL) */ - if ((cblksty & J2K_CCP_CBLKSTY_TERMALL) && !((passtype == 2) && - (bpno - 1 < 0))) { + if (opj_t1_enc_is_term_pass(cblk, cblksty, bpno, passtype)) { + /* If it is a terminated pass, terminate it */ if (type == T1_TYPE_RAW) { - opj_mqc_flush(mqc); - correction = 1; - /* correction = mqc_bypass_flush_enc(); */ - } else { /* correction = mqc_restart_enc(); */ - opj_mqc_flush(mqc); - correction = 1; + opj_mqc_bypass_flush_enc(mqc, cblksty & J2K_CCP_CBLKSTY_PTERM); + } else { + if (cblksty & J2K_CCP_CBLKSTY_PTERM) { + opj_mqc_erterm_enc(mqc); + } else { + opj_mqc_flush(mqc); + } } pass->term = 1; + pass->rate = opj_mqc_numbytes(mqc); } else { - if (((bpno < ((OPJ_INT32)(cblk->numbps) - 4) && (passtype > 0)) - || ((bpno == ((OPJ_INT32)cblk->numbps - 4)) && (passtype == 2))) && - (cblksty & J2K_CCP_CBLKSTY_LAZY)) { - if (type == T1_TYPE_RAW) { - opj_mqc_flush(mqc); - correction = 1; - /* correction = mqc_bypass_flush_enc(); */ - } else { /* correction = mqc_restart_enc(); */ - opj_mqc_flush(mqc); - correction = 1; - } - pass->term = 1; + /* Non terminated pass */ + OPJ_UINT32 rate_extra_bytes; + if (type == T1_TYPE_RAW) { + rate_extra_bytes = opj_mqc_bypass_get_extra_bytes( + mqc, (cblksty & J2K_CCP_CBLKSTY_PTERM)); } else { - pass->term = 0; + rate_extra_bytes = 3; } + pass->term = 0; + pass->rate = opj_mqc_numbytes(mqc) + rate_extra_bytes; } if (++passtype == 3) { @@ -2364,43 +2319,52 @@ static void opj_t1_encode_cblk(opj_t1_t *t1, bpno--; } - if (pass->term && bpno > 0) { - type = ((bpno < ((OPJ_INT32)(cblk->numbps) - 4)) && (passtype < 2) && - (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; - if (type == T1_TYPE_RAW) { - opj_mqc_bypass_init_enc(mqc); - } else { - opj_mqc_restart_init_enc(mqc); - } - } - - pass->distortiondec = cumwmsedec; - pass->rate = opj_mqc_numbytes(mqc) + correction; /* FIXME */ - /* Code-switch "RESET" */ if (cblksty & J2K_CCP_CBLKSTY_RESET) { opj_mqc_reset_enc(mqc); } } - /* Code switch "ERTERM" (i.e. PTERM) */ - if (cblksty & J2K_CCP_CBLKSTY_PTERM) { - opj_mqc_erterm_enc(mqc); - } else /* Default coding */ if (!(cblksty & J2K_CCP_CBLKSTY_LAZY)) { - opj_mqc_flush(mqc); - } - cblk->totalpasses = passno; + if (cblk->totalpasses) { + /* Make sure that pass rates are increasing */ + OPJ_UINT32 last_pass_rate = opj_mqc_numbytes(mqc); + for (passno = cblk->totalpasses; passno > 0;) { + opj_tcd_pass_t *pass = &cblk->passes[--passno]; + if (pass->rate > last_pass_rate) { + pass->rate = last_pass_rate; + } else { + last_pass_rate = pass->rate; + } + } + } + for (passno = 0; passno < cblk->totalpasses; passno++) { opj_tcd_pass_t *pass = &cblk->passes[passno]; - if (pass->rate > opj_mqc_numbytes(mqc)) { - pass->rate = opj_mqc_numbytes(mqc); - } - /*Preventing generation of FF as last data byte of a pass*/ - if ((pass->rate > 1) && (cblk->data[pass->rate - 1] == 0xFF)) { + + /* Prevent generation of FF as last data byte of a pass*/ + /* For terminating passes, the flushing procedure ensured this already */ + assert(pass->rate > 0); + if (cblk->data[pass->rate - 1] == 0xFF) { pass->rate--; } pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate); } + +#ifdef EXTRA_DEBUG + printf(" len=%d\n", (cblk->totalpasses) ? opj_mqc_numbytes(mqc) : 0); + + /* Check that there not 0xff >=0x90 sequences */ + if (cblk->totalpasses) { + OPJ_UINT32 i; + OPJ_UINT32 len = opj_mqc_numbytes(mqc); + for (i = 1; i < len; ++i) { + if (cblk->data[i - 1] == 0xff && cblk->data[i] >= 0x90) { + printf("0xff %02x at offset %d\n", cblk->data[i], i - 1); + abort(); + } + } + } +#endif }