X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Flib%2Fopenjp2%2Ft1.c;h=ce0fb7d13d8fa7facaf421a1d23475bf69aaffd8;hb=9cbc9903c3034d1a101d0521402503ead0abcff0;hp=e9d44e01d27680f7f054df4d6d7dc4304ea4402f;hpb=9a9b06911e164bdc854cf6b9c3bc5b6e751bf46d;p=openjpeg.git diff --git a/src/lib/openjp2/t1.c b/src/lib/openjp2/t1.c index e9d44e01..ce0fb7d1 100644 --- a/src/lib/openjp2/t1.c +++ b/src/lib/openjp2/t1.c @@ -1885,8 +1885,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]; @@ -1966,6 +1972,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, @@ -1993,6 +2030,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; @@ -2017,10 +2059,18 @@ 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); @@ -2042,35 +2092,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) { @@ -2078,43 +2125,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 }