From 324b075fb756c7e9d1c90fc3610ce28632e892ba Mon Sep 17 00:00:00 2001 From: Aaron Boxer Date: Thu, 26 Nov 2015 22:46:13 -0500 Subject: [PATCH] improved rate control --- src/lib/openjp2/t2.c | 425 +++++++++++++++++++++++++++++++++--------- src/lib/openjp2/t2.h | 29 ++- src/lib/openjp2/tcd.c | 23 ++- 3 files changed, 375 insertions(+), 102 deletions(-) diff --git a/src/lib/openjp2/t2.c b/src/lib/openjp2/t2.c index ebc26b2d..5615a12a 100644 --- a/src/lib/openjp2/t2.c +++ b/src/lib/openjp2/t2.c @@ -77,6 +77,27 @@ static OPJ_BOOL opj_t2_encode_packet( OPJ_UINT32 tileno, OPJ_UINT32 len, opj_codestream_info_t *cstr_info); +/** +Encode a packet of a tile to a destination buffer +@param tileno Number of the tile encoded +@param tile Tile for which to write the packets +@param tcp Tile coding parameters +@param pi Packet identity +@param dest Destination buffer +@param p_data_written FIXME DOC +@param len Length of the destination buffer +@param cstr_info Codestream information structure +@return +*/ +static OPJ_BOOL opj_t2_encode_packet_thresh(OPJ_UINT32 tileno, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + opj_pi_iterator_t *pi, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 len); + + + /** Decode a packet of a tile from a source buffer @param t2 T2 handle @@ -211,13 +232,10 @@ OPJ_BOOL opj_t2_encode_packets( opj_t2_t* p_t2, opj_codestream_info_t *cstr_info, OPJ_UINT32 p_tp_num, OPJ_INT32 p_tp_pos, - OPJ_UINT32 p_pino, - J2K_T2_MODE p_t2_mode) + OPJ_UINT32 p_pino) { OPJ_BYTE *l_current_data = p_dest; OPJ_UINT32 l_nb_bytes = 0; - OPJ_UINT32 compno; - OPJ_UINT32 poc; opj_pi_iterator_t *l_pi = 00; opj_pi_iterator_t *l_current_pi = 00; opj_image_t *l_image = p_t2->image; @@ -227,110 +245,138 @@ OPJ_BOOL opj_t2_encode_packets( opj_t2_t* p_t2, OPJ_UINT32 l_max_comp = l_cp->m_specific_param.m_enc.m_max_comp_size > 0 ? l_image->numcomps : 1; OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1; - l_pi = opj_pi_initialise_encode(l_image, l_cp, p_tile_no, p_t2_mode); + l_pi = opj_pi_initialise_encode(l_image, l_cp, p_tile_no, FINAL_PASS); if (!l_pi) { return OPJ_FALSE; } * p_data_written = 0; - if (p_t2_mode == THRESH_CALC ){ /* Calculating threshold */ - l_current_pi = l_pi; + opj_pi_create_encode(l_pi, l_cp,p_tile_no,p_pino,p_tp_num,p_tp_pos, FINAL_PASS); - for (compno = 0; compno < l_max_comp; ++compno) { - OPJ_UINT32 l_comp_len = 0; - l_current_pi = l_pi; + l_current_pi = &l_pi[p_pino]; + 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; + } + while (opj_pi_next(l_current_pi)) { + if (l_current_pi->layno < p_maxlayers) { + l_nb_bytes=0; - for (poc = 0; poc < pocno ; ++poc) { - OPJ_UINT32 l_tp_num = compno; - - /* TODO MSD : check why this function cannot fail (cf. v1) */ - opj_pi_create_encode(l_pi, l_cp,p_tile_no,poc,l_tp_num,p_tp_pos,p_t2_mode); - - if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { - /* TODO ADE : add an error */ + if (! opj_t2_encode_packet(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) { opj_pi_destroy(l_pi, l_nb_pocs); return OPJ_FALSE; - } - while (opj_pi_next(l_current_pi)) { - if (l_current_pi->layno < p_maxlayers) { - l_nb_bytes = 0; + } - if (! opj_t2_encode_packet(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) { - opj_pi_destroy(l_pi, l_nb_pocs); - return OPJ_FALSE; - } + l_current_data += l_nb_bytes; + p_max_len -= l_nb_bytes; - l_comp_len += l_nb_bytes; - l_current_data += l_nb_bytes; - p_max_len -= l_nb_bytes; + * p_data_written += l_nb_bytes; - * p_data_written += l_nb_bytes; - } - } - - if (l_cp->m_specific_param.m_enc.m_max_comp_size) { - if (l_comp_len > l_cp->m_specific_param.m_enc.m_max_comp_size) { - opj_pi_destroy(l_pi, l_nb_pocs); - return OPJ_FALSE; - } - } - - ++l_current_pi; - } - } - } - else { /* t2_mode == FINAL_PASS */ - opj_pi_create_encode(l_pi, l_cp,p_tile_no,p_pino,p_tp_num,p_tp_pos,p_t2_mode); - - l_current_pi = &l_pi[p_pino]; - 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; - } - while (opj_pi_next(l_current_pi)) { - if (l_current_pi->layno < p_maxlayers) { - l_nb_bytes=0; - - if (! opj_t2_encode_packet(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) { - opj_pi_destroy(l_pi, l_nb_pocs); - return OPJ_FALSE; - } - - l_current_data += l_nb_bytes; - p_max_len -= l_nb_bytes; - - * p_data_written += l_nb_bytes; - - /* INDEX >> */ - if(cstr_info) { - if(cstr_info->index_write) { - opj_tile_info_t *info_TL = &cstr_info->tile[p_tile_no]; - opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno]; - if (!cstr_info->packno) { - info_PK->start_pos = info_TL->end_header + 1; - } else { - info_PK->start_pos = ((l_cp->m_specific_param.m_enc.m_tp_on | l_tcp->POC)&& info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1; - } - info_PK->end_pos = info_PK->start_pos + l_nb_bytes - 1; - info_PK->end_ph_pos += info_PK->start_pos - 1; /* End of packet header which now only represents the distance - to start of packet is incremented by value of start of packet*/ - } - - cstr_info->packno++; - } - /* << INDEX */ - ++p_tile->packno; - } - } - } + /* INDEX >> */ + if(cstr_info) { + if(cstr_info->index_write) { + opj_tile_info_t *info_TL = &cstr_info->tile[p_tile_no]; + opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno]; + if (!cstr_info->packno) { + info_PK->start_pos = info_TL->end_header + 1; + } else { + info_PK->start_pos = ((l_cp->m_specific_param.m_enc.m_tp_on | l_tcp->POC)&& info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1; + } + info_PK->end_pos = info_PK->start_pos + l_nb_bytes - 1; + info_PK->end_ph_pos += info_PK->start_pos - 1; /* End of packet header which now only represents the distance + to start of packet is incremented by value of start of packet*/ + } + cstr_info->packno++; + } + /* << INDEX */ + ++p_tile->packno; + } + } + opj_pi_destroy(l_pi, l_nb_pocs); return OPJ_TRUE; } + +OPJ_BOOL opj_t2_encode_packets_thresh(opj_t2_t* p_t2, + OPJ_UINT32 p_tile_no, + opj_tcd_tile_t *p_tile, + OPJ_UINT32 p_maxlayers, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_len, + opj_codestream_info_t *cstr_info, + OPJ_UINT32 p_tp_num, + OPJ_INT32 p_tp_pos, + OPJ_UINT32 p_pino) +{ + OPJ_UINT32 l_nb_bytes = 0; + OPJ_UINT32 compno; + OPJ_UINT32 poc; + opj_pi_iterator_t *l_pi = 00; + opj_pi_iterator_t *l_current_pi = 00; + opj_image_t *l_image = p_t2->image; + opj_cp_t *l_cp = p_t2->cp; + opj_tcp_t *l_tcp = l_cp->tcps + p_tile_no; + OPJ_UINT32 pocno = (l_cp->rsiz == OPJ_PROFILE_CINEMA_4K) ? 2 : 1; + OPJ_UINT32 l_max_comp = l_cp->m_specific_param.m_enc.m_max_comp_size > 0 ? l_image->numcomps : 1; + OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1; + + l_pi = opj_pi_initialise_encode(l_image, l_cp, p_tile_no, THRESH_CALC); + if (!l_pi) { + return OPJ_FALSE; + } + *p_data_written = 0; + l_current_pi = l_pi; + + for (compno = 0; compno < l_max_comp; ++compno) { + OPJ_UINT32 l_comp_len = 0; + l_current_pi = l_pi; + + for (poc = 0; poc < pocno; ++poc) { + OPJ_UINT32 l_tp_num = compno; + + /* TODO MSD : check why this function cannot fail (cf. v1) */ + opj_pi_create_encode(l_pi, l_cp, p_tile_no, poc, l_tp_num, p_tp_pos, THRESH_CALC); + + 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; + } + while (opj_pi_next(l_current_pi)) { + if (l_current_pi->layno < p_maxlayers) { + l_nb_bytes = 0; + + if (!opj_t2_encode_packet_thresh(p_tile_no, p_tile, l_tcp, l_current_pi, &l_nb_bytes, p_max_len)) { + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + + l_comp_len += l_nb_bytes; + p_max_len -= l_nb_bytes; + + *p_data_written += l_nb_bytes; + } + } + + if (l_cp->m_specific_param.m_enc.m_max_comp_size) { + if (l_comp_len > l_cp->m_specific_param.m_enc.m_max_comp_size) { + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + } + + ++l_current_pi; + } + } + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_TRUE; +} + /* see issue 80 */ #if 0 #define JAS_FPRINTF fprintf @@ -793,6 +839,207 @@ static OPJ_BOOL opj_t2_encode_packet( OPJ_UINT32 tileno, return OPJ_TRUE; } + +static OPJ_BOOL opj_t2_encode_packet_thresh(OPJ_UINT32 tileno, + opj_tcd_tile_t * tile, + opj_tcp_t * tcp, + opj_pi_iterator_t *pi, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 length) +{ + OPJ_UINT32 bandno, cblkno; + OPJ_UINT32 l_nb_bytes; + OPJ_UINT32 compno = pi->compno; /* component value */ + OPJ_UINT32 resno = pi->resno; /* resolution level value */ + OPJ_UINT32 precno = pi->precno; /* precinct value */ + OPJ_UINT32 layno = pi->layno; /* quality layer value */ + OPJ_UINT32 l_nb_blocks; + opj_tcd_band_t *band = 00; + opj_tcd_cblk_enc_t* cblk = 00; + opj_tcd_pass_t *pass = 00; + + opj_tcd_tilecomp_t *tilec = tile->comps + compno; + opj_tcd_resolution_t *res = tilec->resolutions + resno; + + opj_bio_t *bio = 00; /* BIO component */ + OPJ_INT32 packet_bytes_written = 0; + + /* */ + if (tcp->csty & J2K_CP_CSTY_SOP) { + length -= 6; + packet_bytes_written += 6; + } + /* */ + + if (!layno) { + band = res->bands; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_precinct_t *prc = band->precincts + precno; + + opj_tgt_reset(prc->incltree); + opj_tgt_reset(prc->imsbtree); + + l_nb_blocks = prc->cw * prc->ch; + for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { + cblk = prc->cblks.enc+cblkno; + + cblk->numpasses = 0; + opj_tgt_setvalue(prc->imsbtree, cblkno, band->numbps - (OPJ_INT32)cblk->numbps); + } + ++band; + } + } + + bio = opj_bio_create(); + if (!bio) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + opj_bio_init_enc(bio, 0, length); + opj_bio_write(bio, 1, 1); /* Empty header bit */ + bio->simOut = OPJ_TRUE; + + /* Writing Packet header */ + band = res->bands; + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_precinct_t *prc = band->precincts + precno; + + l_nb_blocks = prc->cw * prc->ch; + cblk = prc->cblks.enc; + + for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { + opj_tcd_layer_t *layer = cblk->layers + layno; + + if (!cblk->numpasses && layer->numpasses) { + opj_tgt_setvalue(prc->incltree, cblkno, (OPJ_INT32)layno); + } + + ++cblk; + } + + cblk = prc->cblks.enc; + for (cblkno = 0; cblkno < l_nb_blocks; cblkno++) { + opj_tcd_layer_t *layer = cblk->layers + layno; + OPJ_UINT32 increment = 0; + OPJ_UINT32 nump = 0; + OPJ_UINT32 len = 0, passno; + OPJ_UINT32 l_nb_passes; + + /* cblk inclusion bits */ + if (!cblk->numpasses) { + opj_tgt_encode(bio, prc->incltree, cblkno, (OPJ_INT32)(layno + 1)); + } + else { + opj_bio_write(bio, layer->numpasses != 0, 1); + } + + /* if cblk not included, go to the next cblk */ + if (!layer->numpasses) { + ++cblk; + continue; + } + + /* if first instance of cblk --> zero bit-planes information */ + if (!cblk->numpasses) { + cblk->numlenbits = 3; + opj_tgt_encode(bio, prc->imsbtree, cblkno, 999); + } + + /* number of coding passes included */ + opj_t2_putnumpasses(bio, layer->numpasses); + l_nb_passes = cblk->numpasses + layer->numpasses; + pass = cblk->passes + cblk->numpasses; + + /* computation of the increase of the length indicator and insertion in the header */ + for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) { + ++nump; + len += pass->len; + + if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) { + increment = (OPJ_UINT32)opj_int_max((OPJ_INT32)increment, opj_int_floorlog2((OPJ_INT32)len) + 1 + - ((OPJ_INT32)cblk->numlenbits + opj_int_floorlog2((OPJ_INT32)nump))); + len = 0; + nump = 0; + } + + ++pass; + } + opj_t2_putcommacode(bio, (OPJ_INT32)increment); + + /* computation of the new Length indicator */ + cblk->numlenbits += increment; + + pass = cblk->passes + cblk->numpasses; + /* insertion of the codeword segment length */ + for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) { + nump++; + len += pass->len; + + if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) { + opj_bio_write(bio, (OPJ_UINT32)len, cblk->numlenbits + (OPJ_UINT32)opj_int_floorlog2((OPJ_INT32)nump)); + len = 0; + nump = 0; + } + ++pass; + } + + ++cblk; + } + + ++band; + } + + if (!opj_bio_flush(bio)) { + opj_bio_destroy(bio); + return OPJ_FALSE; + } + + l_nb_bytes = (OPJ_UINT32)opj_bio_numbytes(bio); + packet_bytes_written += l_nb_bytes; + length -= l_nb_bytes; + + opj_bio_destroy(bio); + + /* */ + if (tcp->csty & J2K_CP_CSTY_EPH) { + length -= 2; + packet_bytes_written += 2; + } + /* */ + + + /* Writing the packet body */ + band = res->bands; + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_precinct_t *prc = band->precincts + precno; + + l_nb_blocks = prc->cw * prc->ch; + cblk = prc->cblks.enc; + + for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { + opj_tcd_layer_t *layer = cblk->layers + layno; + + if (!layer->numpasses) { + ++cblk; + continue; + } + + if (layer->len > length) { + return OPJ_FALSE; + } + + cblk->numpasses += layer->numpasses; + packet_bytes_written += layer->len; + length -= layer->len; + ++cblk; + } + ++band; + } + *p_data_written += packet_bytes_written; + + return OPJ_TRUE; +} static OPJ_BOOL opj_t2_skip_packet( opj_t2_t* p_t2, opj_tcd_tile_t *p_tile, opj_tcp_t *p_tcp, diff --git a/src/lib/openjp2/t2.h b/src/lib/openjp2/t2.h index 3b652eea..b505418b 100644 --- a/src/lib/openjp2/t2.h +++ b/src/lib/openjp2/t2.h @@ -75,7 +75,6 @@ Encode the packets of a tile to a destination buffer @param tpnum Tile part number of the current tile @param tppos The position of the tile part flag in the progression order @param pino FIXME DOC -@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass */ OPJ_BOOL opj_t2_encode_packets( opj_t2_t* t2, OPJ_UINT32 tileno, @@ -87,8 +86,32 @@ OPJ_BOOL opj_t2_encode_packets( opj_t2_t* t2, opj_codestream_info_t *cstr_info, OPJ_UINT32 tpnum, OPJ_INT32 tppos, - OPJ_UINT32 pino, - J2K_T2_MODE t2_mode); + OPJ_UINT32 pino); + +/** +Encode the packets of a tile to a destination buffer +@param t2 T2 handle +@param tileno number of the tile encoded +@param tile the tile for which to write the packets +@param maxlayers maximum number of layers +@param p_data_written FIXME DOC +@param len the length of the destination buffer +@param cstr_info Codestream information structure +@param tpnum Tile part number of the current tile +@param tppos The position of the tile part flag in the progression order +@param pino FIXME DOC +*/ +OPJ_BOOL opj_t2_encode_packets_thresh(opj_t2_t* t2, + OPJ_UINT32 tileno, + opj_tcd_tile_t *tile, + OPJ_UINT32 maxlayers, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 len, + opj_codestream_info_t *cstr_info, + OPJ_UINT32 tpnum, + OPJ_INT32 tppos, + OPJ_UINT32 pino); + /** Decode the packets of a tile from a source buffer diff --git a/src/lib/openjp2/tcd.c b/src/lib/openjp2/tcd.c index af6c044b..7ab4c7a3 100644 --- a/src/lib/openjp2/tcd.c +++ b/src/lib/openjp2/tcd.c @@ -232,20 +232,20 @@ void opj_tcd_makelayer( opj_tcd_t *tcd, tcd_tile->distolayer[layno] = 0; /* fixed_quality */ for (compno = 0; compno < tcd_tile->numcomps; compno++) { - opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + opj_tcd_tilecomp_t *tilec = tcd_tile->comps+compno; for (resno = 0; resno < tilec->numresolutions; resno++) { - opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + opj_tcd_resolution_t *res = tilec->resolutions+resno; for (bandno = 0; bandno < res->numbands; bandno++) { - opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_band_t *band = res->bands+bandno; for (precno = 0; precno < res->pw * res->ph; precno++) { - opj_tcd_precinct_t *prc = &band->precincts[precno]; + opj_tcd_precinct_t *prc = band->precincts+precno; for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { - opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; - opj_tcd_layer_t *layer = &cblk->layers[layno]; + opj_tcd_cblk_enc_t *cblk = prc->cblks.enc+cblkno; + opj_tcd_layer_t *layer = cblk->layers+layno; OPJ_UINT32 n; if (layno == 0) { @@ -494,6 +494,7 @@ OPJ_BOOL opj_tcd_rateallocate( opj_tcd_t *tcd, OPJ_UINT32 maxlen = tcd_tcp->rates[layno] ? opj_uint_min(((OPJ_UINT32) ceil(tcd_tcp->rates[layno])), len) : len; OPJ_FLOAT64 goodthresh = 0; OPJ_FLOAT64 stable_thresh = 0; + OPJ_FLOAT64 old_thresh = -1; OPJ_UINT32 i; OPJ_FLOAT64 distotarget; /* fixed_quality */ @@ -518,10 +519,13 @@ OPJ_BOOL opj_tcd_rateallocate( opj_tcd_t *tcd, thresh = (lo + hi) / 2; opj_tcd_makelayer(tcd, layno, thresh, 0); + if ((fabs(old_thresh - thresh)) < 0.001) + break; + old_thresh = thresh; if (cp->m_specific_param.m_enc.m_fixed_quality) { /* fixed_quality */ if(OPJ_IS_CINEMA(cp->rsiz)){ - if (! opj_t2_encode_packets(t2,tcd->tcd_tileno, tcd_tile, layno + 1, dest, p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC)) { + if (! opj_t2_encode_packets_thresh(t2,tcd->tcd_tileno, tcd_tile, layno + 1, p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino)) { lo = thresh; continue; @@ -550,7 +554,7 @@ OPJ_BOOL opj_tcd_rateallocate( opj_tcd_t *tcd, lo = thresh; } } else { - if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest,p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC)) + if (! opj_t2_encode_packets_thresh(t2, tcd->tcd_tileno, tcd_tile, layno + 1, p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino)) { /* TODO: what to do with l ??? seek / tell ??? */ /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */ @@ -2055,8 +2059,7 @@ static OPJ_BOOL opj_tcd_t2_encode (opj_tcd_t *p_tcd, p_cstr_info, p_tcd->tp_num, p_tcd->tp_pos, - p_tcd->cur_pino, - FINAL_PASS)) + p_tcd->cur_pino)) { opj_t2_destroy(l_t2); return OPJ_FALSE;