improved rate control

This commit is contained in:
Aaron Boxer 2015-11-26 22:46:13 -05:00
parent 269c40c544
commit 324b075fb7
3 changed files with 375 additions and 102 deletions

View File

@ -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,61 +245,14 @@ 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;
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,p_t2_mode);
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_comp_len += l_nb_bytes;
l_current_data += 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;
}
}
}
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);
opj_pi_create_encode(l_pi, l_cp,p_tile_no,p_pino,p_tp_num,p_tp_pos, FINAL_PASS);
l_current_pi = &l_pi[p_pino];
if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) {
@ -324,13 +295,88 @@ OPJ_BOOL opj_t2_encode_packets( opj_t2_t* p_t2,
++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;
/* <SOP 0xff91> */
if (tcp->csty & J2K_CP_CSTY_SOP) {
length -= 6;
packet_bytes_written += 6;
}
/* </SOP> */
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);
/* <EPH 0xff92> */
if (tcp->csty & J2K_CP_CSTY_EPH) {
length -= 2;
packet_bytes_written += 2;
}
/* </EPH> */
/* 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,

View File

@ -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

View File

@ -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;