On Wed, Aug 19, 2020 at 5:51 PM <gautamr...@gmail.com> wrote: > > From: Gautam Ramakrishnan <gautamr...@gmail.com> > > This patch allows setting a compression ratio and to > set multiple layers. The user has to input a compression > ratio for each layer. > The per layer compression ration can be set as follows: > -layer_rates "r1,r2,...rn" > for to create 'n' layers. > --- > libavcodec/j2kenc.c | 443 ++++++++++++++++++++++++++++++++++-------- > libavcodec/jpeg2000.c | 13 +- > libavcodec/jpeg2000.h | 10 + > 3 files changed, 384 insertions(+), 82 deletions(-) > > diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c > index 8699296434..b09db36c14 100644 > --- a/libavcodec/j2kenc.c > +++ b/libavcodec/j2kenc.c > @@ -32,6 +32,7 @@ > * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe > * Copyright (c) 2005, Herve Drolon, FreeImage Team > * Copyright (c) 2007, Callum Lerwick <s...@haxxed.com> > + * Copyright (c) 2020, Gautam Ramakrishnan <gautamr...@gmail.com> > * All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > @@ -100,6 +101,7 @@ static const int dwt_norms[2][4][10] = { // > [dwt_type][band][rlevel] (multiplied > > typedef struct { > Jpeg2000Component *comp; > + double *layer_rates; > } Jpeg2000Tile; > > typedef struct { > @@ -126,12 +128,15 @@ typedef struct { > Jpeg2000QuantStyle qntsty; > > Jpeg2000Tile *tile; > + int layer_rates[100]; > > int format; > int pred; > int sop; > int eph; > int prog; > + int nlayers; > + char *lr_str; > } Jpeg2000EncoderContext; > > > @@ -332,7 +337,7 @@ static int put_cod(Jpeg2000EncoderContext *s) > bytestream_put_byte(&s->buf, scod); // Scod > // SGcod > bytestream_put_byte(&s->buf, s->prog); // progression level > - bytestream_put_be16(&s->buf, 1); // num of layers > + bytestream_put_be16(&s->buf, s->nlayers); // num of layers > if(s->avctx->pix_fmt == AV_PIX_FMT_YUV444P){ > bytestream_put_byte(&s->buf, 0); // unspecified > }else{ > @@ -411,6 +416,31 @@ static uint8_t *put_sot(Jpeg2000EncoderContext *s, int > tileno) > return psotptr; > } > > +static void compute_rates(Jpeg2000EncoderContext* s) > +{ > + int i, j; > + int layno, compno; > + for (i = 0; i < s->numYtiles; i++) { > + for (j = 0; j < s->numXtiles; j++) { > + Jpeg2000Tile *tile = &s->tile[s->numXtiles * i + j]; > + for (compno = 0; compno < s->ncomponents; compno++) { > + int tilew = tile->comp[compno].coord[0][1] - > tile->comp[compno].coord[0][0]; > + int tileh = tile->comp[compno].coord[1][1] - > tile->comp[compno].coord[1][0]; > + int scale = (compno?1 << s->chroma_shift[0]:1) * (compno?1 > << s->chroma_shift[1]:1); > + for (layno = 0; layno < s->nlayers; layno++) { > + if (s->layer_rates[layno] > 0.0f) { > + tile->layer_rates[layno] += (double)(tilew * tileh) > * s->ncomponents * s->cbps[compno] / > + > (double)(s->layer_rates[layno] * 8 * scale); > + } else { > + tile->layer_rates[layno] = 0.0f; > + } > + } > + } > + } > + } > + > +} > + > /** > * compute the sizes of tiles, resolution levels, bands, etc. > * allocate memory for them > @@ -448,6 +478,10 @@ static int init_tiles(Jpeg2000EncoderContext *s) > for (j = 0; j < 2; j++) > comp->coord[i][j] = comp->coord_o[i][j] = > ff_jpeg2000_ceildivpow2(comp->coord[i][j], s->chroma_shift[i]); > > + tile->layer_rates = av_mallocz_array(s->ncomponents, > sizeof(*tile->layer_rates)); > + if (!tile->layer_rates) > + return AVERROR(ENOMEM); > + > if ((ret = ff_jpeg2000_init_component(comp, > codsty, > qntsty, > @@ -459,6 +493,7 @@ static int init_tiles(Jpeg2000EncoderContext *s) > return ret; > } > } > + compute_rates(s); > return 0; > } > > @@ -701,6 +736,8 @@ static void encode_cblk(Jpeg2000EncoderContext *s, > Jpeg2000T1Context *t1, Jpeg20 > } > > cblk->passes[passno].rate = ff_mqc_flush_to(&t1->mqc, > cblk->passes[passno].flushed, &cblk->passes[passno].flushed_len); > + cblk->passes[passno].rate -= cblk->passes[passno].flushed_len; > + > wmsedec += (int64_t)nmsedec << (2*bpno); > cblk->passes[passno].disto = wmsedec; > > @@ -733,10 +770,12 @@ static void putnumpasses(Jpeg2000EncoderContext *s, int > n) > } > > > -static int encode_packet(Jpeg2000EncoderContext *s, Jpeg2000ResLevel > *rlevel, int precno, > - uint8_t *expn, int numgbits, int packetno) > +static int encode_packet(Jpeg2000EncoderContext *s, Jpeg2000ResLevel > *rlevel, int layno, > + int precno, uint8_t *expn, int numgbits, int > packetno, > + int nlayers) > { > int bandno, empty = 1; > + int i; > // init bitstream > *s->buf = 0; > s->bit_index = 0; > @@ -748,18 +787,61 @@ static int encode_packet(Jpeg2000EncoderContext *s, > Jpeg2000ResLevel *rlevel, in > } > // header > > + if (!layno) { > + for (bandno = 0; bandno < rlevel->nbands; bandno++){ > + Jpeg2000Band *band = rlevel->band + bandno; > + if (rlevel->band[bandno].coord[0][0] < > rlevel->band[bandno].coord[0][1] > + && rlevel->band[bandno].coord[1][0] < > rlevel->band[bandno].coord[1][1]){ > + Jpeg2000Prec *prec = band->prec + precno; > + int nb_cblks = prec->nb_codeblocks_height * > prec->nb_codeblocks_width; > + int pos; > + ff_tag_tree_zero(prec->zerobits, prec->nb_codeblocks_width, > prec->nb_codeblocks_height); > + ff_tag_tree_zero(prec->cblkincl, prec->nb_codeblocks_width, > prec->nb_codeblocks_height); > + for (pos = 0; pos < nb_cblks; pos++) { > + Jpeg2000Cblk *cblk = &prec->cblk[pos]; > + prec->zerobits[pos].val = expn[bandno] + numgbits - 1 - > cblk->nonzerobits; > + cblk->incl = 0; > + cblk->lblock = 3; > + tag_tree_update(prec->zerobits + pos); > + for (i = 0; i < nlayers; i++) { > + if (cblk->layers[i].npasses > 0) { > + prec->cblkincl[pos].val = i; > + break; > + } > + } > + if (i == nlayers) > + prec->cblkincl[pos].val = i; > + tag_tree_update(prec->cblkincl + pos); > + } > + } > + } > + } > + > // is the packet empty? > for (bandno = 0; bandno < rlevel->nbands; bandno++){ > + Jpeg2000Band *band = rlevel->band + bandno; > if (rlevel->band[bandno].coord[0][0] < > rlevel->band[bandno].coord[0][1] > && rlevel->band[bandno].coord[1][0] < > rlevel->band[bandno].coord[1][1]){ > - empty = 0; > - break; > + Jpeg2000Prec *prec = band->prec + precno; > + int nb_cblks = prec->nb_codeblocks_height * > prec->nb_codeblocks_width; > + int pos; > + for (pos = 0; pos < nb_cblks; pos++) { > + Jpeg2000Cblk *cblk = &prec->cblk[pos]; > + if (cblk->layers[layno].npasses) { > + empty = 0; > + break; > + } > + } > + if (!empty) > + break; > } > } > > put_bits(s, !empty, 1); > if (empty){ > j2k_flush(s); > + if (s->eph) > + bytestream_put_be16(&s->buf, JPEG2000_EPH); > return 0; > } > > @@ -775,40 +857,44 @@ static int encode_packet(Jpeg2000EncoderContext *s, > Jpeg2000ResLevel *rlevel, in > > for (pos=0, yi = 0; yi < prec->nb_codeblocks_height; yi++){ > for (xi = 0; xi < cblknw; xi++, pos++){ > - prec->cblkincl[pos].val = prec->cblk[yi * cblknw + > xi].ninclpasses == 0; > - tag_tree_update(prec->cblkincl + pos); > - prec->zerobits[pos].val = expn[bandno] + numgbits - 1 - > prec->cblk[yi * cblknw + xi].nonzerobits; > - tag_tree_update(prec->zerobits + pos); > - } > - } > - > - for (pos=0, yi = 0; yi < prec->nb_codeblocks_height; yi++){ > - for (xi = 0; xi < cblknw; xi++, pos++){ > - int pad = 0, llen, length; > + int llen = 0, length; > Jpeg2000Cblk *cblk = prec->cblk + yi * cblknw + xi; > > if (s->buf_end - s->buf < 20) // approximately > return -1; > > // inclusion information > - tag_tree_code(s, prec->cblkincl + pos, 1); > - if (!cblk->ninclpasses) > + if (!cblk->incl) > + tag_tree_code(s, prec->cblkincl + pos, layno + 1); > + else { > + put_bits(s, cblk->layers[layno].npasses > 0, 1); > + } > + > + if (!cblk->layers[layno].npasses) > continue; > + > // zerobits information > - tag_tree_code(s, prec->zerobits + pos, 100); > + if (!cblk->incl) { > + tag_tree_code(s, prec->zerobits + pos, 100); > + cblk->incl = 1; > + } > + > // number of passes > - putnumpasses(s, cblk->ninclpasses); > + putnumpasses(s, cblk->layers[layno].npasses); > > - length = cblk->passes[cblk->ninclpasses-1].rate; > - llen = av_log2(length) - av_log2(cblk->ninclpasses) - 2; > - if (llen < 0){ > - pad = -llen; > - llen = 0; > + length = cblk->layers[layno].data_len; > + if (layno == nlayers - 1 && cblk->layers->cum_passes){ > + length += > cblk->passes[cblk->layers->cum_passes-1].flushed_len; > } > + if (cblk->lblock + av_log2(cblk->layers[layno].npasses) < > av_log2(length) + 1) { > + llen = av_log2(length) + 1 - cblk->lblock - > av_log2(cblk->layers[layno].npasses); > + } > + > // length of code block > + cblk->lblock += llen; > put_bits(s, 1, llen); > put_bits(s, 0, 1); > - put_num(s, length, av_log2(length)+1+pad); > + put_num(s, length, cblk->lblock + > av_log2(cblk->layers[layno].npasses)); > } > } > } > @@ -825,13 +911,14 @@ static int encode_packet(Jpeg2000EncoderContext *s, > Jpeg2000ResLevel *rlevel, in > int xi; > for (xi = 0; xi < cblknw; xi++){ > Jpeg2000Cblk *cblk = prec->cblk + yi * cblknw + xi; > - if (cblk->ninclpasses){ > - if (s->buf_end - s->buf < > cblk->passes[cblk->ninclpasses-1].rate) > + if (cblk->layers[layno].npasses){ > + if (s->buf_end - s->buf < cblk->layers[layno].data_len + > 2) > return -1; > - bytestream_put_buffer(&s->buf, cblk->data + 1, > cblk->passes[cblk->ninclpasses-1].rate > - - > cblk->passes[cblk->ninclpasses-1].flushed_len); > - bytestream_put_buffer(&s->buf, > cblk->passes[cblk->ninclpasses-1].flushed, > - > cblk->passes[cblk->ninclpasses-1].flushed_len); > + bytestream_put_buffer(&s->buf, > cblk->layers[layno].data_start + 1, cblk->layers[layno].data_len); > + if (layno == nlayers - 1 && cblk->layers->cum_passes){ > + bytestream_put_buffer(&s->buf, > cblk->passes[cblk->layers->cum_passes-1].flushed, > + > cblk->passes[cblk->layers->cum_passes-1].flushed_len); > + } > } > } > } > @@ -839,9 +926,9 @@ static int encode_packet(Jpeg2000EncoderContext *s, > Jpeg2000ResLevel *rlevel, in > return 0; > } > > -static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int > tileno) > +static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int > tileno, int nlayers) > { > - int compno, reslevelno, ret; > + int compno, reslevelno, layno, ret; > Jpeg2000CodingStyle *codsty = &s->codsty; > Jpeg2000QuantStyle *qntsty = &s->qntsty; > int packetno = 0; > @@ -858,29 +945,33 @@ static int encode_packets(Jpeg2000EncoderContext *s, > Jpeg2000Tile *tile, int til > > av_log(s->avctx, AV_LOG_DEBUG, "tier2\n"); > // lay-rlevel-comp-pos progression > - switch (s->prog) { > + switch (s->prog) { > case JPEG2000_PGOD_LRCP: > - for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ > - for (compno = 0; compno < s->ncomponents; compno++){ > - int precno; > - Jpeg2000ResLevel *reslevel = > s->tile[tileno].comp[compno].reslevel + reslevelno; > - for (precno = 0; precno < reslevel->num_precincts_x * > reslevel->num_precincts_y; precno++){ > - if ((ret = encode_packet(s, reslevel, precno, qntsty->expn + > (reslevelno ? 3*reslevelno-2 : 0), > - qntsty->nguardbits, packetno++)) < 0) > - return ret; > + for (layno = 0; layno < nlayers; layno++){ > + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ > + for (compno = 0; compno < s->ncomponents; compno++){ > + int precno; > + Jpeg2000ResLevel *reslevel = > s->tile[tileno].comp[compno].reslevel + reslevelno; > + for (precno = 0; precno < reslevel->num_precincts_x * > reslevel->num_precincts_y; precno++){ > + if ((ret = encode_packet(s, reslevel, layno, precno, > qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), > + qntsty->nguardbits, packetno++, nlayers)) < > 0) > + return ret; > + } > } > } > } > break; > case JPEG2000_PGOD_RLCP: > for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ > - for (compno = 0; compno < s->ncomponents; compno++){ > - int precno; > - Jpeg2000ResLevel *reslevel = > s->tile[tileno].comp[compno].reslevel + reslevelno; > - for (precno = 0; precno < reslevel->num_precincts_x * > reslevel->num_precincts_y; precno++){ > - if ((ret = encode_packet(s, reslevel, precno, qntsty->expn + > (reslevelno ? 3*reslevelno-2 : 0), > - qntsty->nguardbits, packetno++)) < 0) > - return ret; > + for (layno = 0; layno < nlayers; layno++){ > + for (compno = 0; compno < s->ncomponents; compno++){ > + int precno; > + Jpeg2000ResLevel *reslevel = > s->tile[tileno].comp[compno].reslevel + reslevelno; > + for (precno = 0; precno < reslevel->num_precincts_x * > reslevel->num_precincts_y; precno++){ > + if ((ret = encode_packet(s, reslevel, layno, precno, > qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), > + qntsty->nguardbits, packetno++, nlayers)) < > 0) > + return ret; > + } > } > } > } > @@ -935,10 +1026,11 @@ static int encode_packets(Jpeg2000EncoderContext *s, > Jpeg2000Tile *tile, int til > prcx, prcy, reslevel->num_precincts_x, > reslevel->num_precincts_y); > continue; > } > - > - if ((ret = encode_packet(s, reslevel, precno, > qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), > - qntsty->nguardbits, packetno++)) < 0) > - return ret; > + for (layno = 0; layno < nlayers; layno++){ > + if ((ret = encode_packet(s, reslevel, layno, precno, > qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), > + qntsty->nguardbits, packetno++, nlayers)) < > 0) > + return ret; > + } > } > } > } > @@ -1001,9 +1093,11 @@ static int encode_packets(Jpeg2000EncoderContext *s, > Jpeg2000Tile *tile, int til > prcx, prcy, reslevel->num_precincts_x, > reslevel->num_precincts_y); > continue; > } > - if ((ret = encode_packet(s, reslevel, precno, > qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), > - qntsty->nguardbits, packetno++)) < 0) > - return ret; > + for (layno = 0; layno < nlayers; layno++){ > + if ((ret = encode_packet(s, reslevel, layno, > precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), > + qntsty->nguardbits, packetno++, > nlayers)) < 0) > + return ret; > + } > } > } > } > @@ -1062,9 +1156,11 @@ static int encode_packets(Jpeg2000EncoderContext *s, > Jpeg2000Tile *tile, int til > prcx, prcy, reslevel->num_precincts_x, > reslevel->num_precincts_y); > continue; > } > - if ((ret = encode_packet(s, reslevel, precno, > qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), > - qntsty->nguardbits, packetno++)) < 0) > - return ret; > + for (layno = 0; layno < nlayers; layno++){ > + if ((ret = encode_packet(s, reslevel, layno, > precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), > + qntsty->nguardbits, packetno++, > nlayers)) < 0) > + return ret; > + } > } > } > } > @@ -1076,27 +1172,98 @@ static int encode_packets(Jpeg2000EncoderContext *s, > Jpeg2000Tile *tile, int til > return 0; > } > > -static int getcut(Jpeg2000Cblk *cblk, int64_t lambda, int dwt_norm) > +static void makelayer(Jpeg2000EncoderContext *s, int layno, double thresh, > Jpeg2000Tile* tile, int final) > { > - int passno, res = 0; > - for (passno = 0; passno < cblk->npasses; passno++){ > - int dr; > - int64_t dd; > - > - dr = cblk->passes[passno].rate > - - (res ? cblk->passes[res-1].rate:0); > - dd = cblk->passes[passno].disto > - - (res ? cblk->passes[res-1].disto:0); > - > - if (((dd * dwt_norm) >> WMSEDEC_SHIFT) * dwt_norm >= dr * lambda) > - res = passno+1; > + int compno, resno, bandno, precno, cblkno; > + int passno; > + > + for (compno = 0; compno < s->ncomponents; compno++) { > + Jpeg2000Component *comp = &tile->comp[compno]; > + > + for (resno = 0; resno < s->codsty.nreslevels; resno++) { > + Jpeg2000ResLevel *reslevel = comp->reslevel + resno; > + > + for (precno = 0; precno < reslevel->num_precincts_x * > reslevel->num_precincts_y; precno++){ > + for (bandno = 0; bandno < reslevel->nbands ; bandno++){ > + Jpeg2000Band *band = reslevel->band + bandno; > + Jpeg2000Prec *prec = band->prec + precno; > + > + for (cblkno = 0; cblkno < prec->nb_codeblocks_height * > prec->nb_codeblocks_width; cblkno++){ > + Jpeg2000Cblk *cblk = prec->cblk + cblkno; > + Jpeg2000Layer *layer = &cblk->layers[layno]; > + int n; > + > + if (layno == 0) { > + cblk->ninclpasses = 0; > + } > + > + n = cblk->ninclpasses; > + > + if (thresh < 0) { > + n = cblk->npasses; > + } else { > + for (passno = cblk->ninclpasses; passno < > cblk->npasses; passno++) { > + int32_t dr; > + double dd; > + Jpeg2000Pass *pass = &cblk->passes[passno]; > + > + if (n == 0) { > + dr = pass->rate; > + dd = (double)pass->disto; > + } else { > + dr = pass->rate - cblk->passes[n - > 1].rate; > + dd = (double)pass->disto - > (double)cblk->passes[n-1].disto; > + } > + > + if (!dr) { > + if (dd) { > + n = passno + 1; > + } > + continue; > + } > + > + if (thresh - (dd / dr) < DBL_EPSILON) > + n = passno + 1; > + } > + } > + layer->npasses = n - cblk->ninclpasses; > + layer->cum_passes = n; > + > + if (layer->npasses == 0) { > + layer->disto = 0; > + layer->data_len = 0; > + continue; > + } > + > + if (cblk->ninclpasses == 0) { > + layer->data_len = cblk->passes[n - 1].rate; > + layer->data_start = cblk->data; > + layer->disto = cblk->passes[n - 1].disto; > + } else { > + layer->data_len = cblk->passes[n - 1].rate - > cblk->passes[cblk->ninclpasses - 1].rate; > + layer->data_start = cblk->data + > cblk->passes[cblk->ninclpasses - 1].rate; > + layer->disto = cblk->passes[n - 1].disto - > + cblk->passes[cblk->ninclpasses - > 1].disto; > + } > + if (final) { > + cblk->ninclpasses = n; > + } > + } > + } > + } > + } > } > - return res; > } > > -static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile) > +static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile) > { > - int precno, compno, reslevelno, bandno, cblkno, lev; > + int precno, compno, reslevelno, bandno, cblkno, lev, passno, layno; > + int i; > + double min = DBL_MAX; > + double max = 0; > + double thresh; > + int tile_disto = 0; > + > Jpeg2000CodingStyle *codsty = &s->codsty; > > for (compno = 0; compno < s->ncomponents; compno++){ > @@ -1107,20 +1274,70 @@ static void truncpasses(Jpeg2000EncoderContext *s, > Jpeg2000Tile *tile) > > for (precno = 0; precno < reslevel->num_precincts_x * > reslevel->num_precincts_y; precno++){ > for (bandno = 0; bandno < reslevel->nbands ; bandno++){ > - int bandpos = bandno + (reslevelno > 0); > Jpeg2000Band *band = reslevel->band + bandno; > Jpeg2000Prec *prec = band->prec + precno; > > for (cblkno = 0; cblkno < prec->nb_codeblocks_height * > prec->nb_codeblocks_width; cblkno++){ > Jpeg2000Cblk *cblk = prec->cblk + cblkno; > + for (passno = 0; passno < cblk->npasses; passno++) { > + Jpeg2000Pass *pass = &cblk->passes[passno]; > + int dr; > + double dd, drslope; > + > + tile_disto += pass->disto; > + if (passno == 0) { > + dr = (int32_t)pass->rate; > + dd = (double)pass->disto; > + } else { > + dr = (int32_t)(pass->rate) - > cblk->passes[passno - 1].rate; > + dd = (double)pass->disto - > (double)cblk->passes[passno - 1].disto; > + } > + > + if (dr <= 0) > + continue; > > - cblk->ninclpasses = getcut(cblk, s->lambda, > - (int64_t)dwt_norms[codsty->transform == > FF_DWT53][bandpos][lev] * (int64_t)band->i_stepsize >> 15); > + drslope = dd / dr; > + if (drslope < min) > + min = drslope; > + > + if (drslope > max) > + max = drslope; > + } > } > } > } > } > } > + > + for (layno = 0; layno < s->nlayers; layno++) { > + double lo = min; > + double hi = max; > + double stable_thresh = 0; > + double good_thresh = 0; > + if (!s->layer_rates[layno]) { > + good_thresh = -1; > + } else { > + for (i = 0; i < 128; i++) { > + uint8_t *stream_pos = s->buf; > + int ret; > + thresh = (lo + hi) / 2; > + makelayer(s, layno, thresh, tile, 0); > + ret = encode_packets(s, tile, (int)(tile - s->tile), layno + > 1); > + memset(stream_pos, 0, s->buf - stream_pos); > + if ((s->buf - stream_pos > ceil(tile->layer_rates[layno])) > || ret < 0) { > + lo = thresh; > + s->buf = stream_pos; > + continue; > + } > + hi = thresh; > + stable_thresh = thresh; > + s->buf = stream_pos; > + } > + } > + if (good_thresh >= 0) > + good_thresh = stable_thresh == 0 ? thresh : stable_thresh; > + makelayer(s, layno, good_thresh, tile, 1); > + } > } > > static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int > tileno) > @@ -1203,8 +1420,8 @@ static int encode_tile(Jpeg2000EncoderContext *s, > Jpeg2000Tile *tile, int tileno > } > > av_log(s->avctx, AV_LOG_DEBUG, "rate control\n"); > - truncpasses(s, tile); > - if ((ret = encode_packets(s, tile, tileno)) < 0) > + makelayers(s, tile); > + if ((ret = encode_packets(s, tile, tileno, s->nlayers)) < 0) > return ret; > av_log(s->avctx, AV_LOG_DEBUG, "after rate control\n"); > return 0; > @@ -1221,6 +1438,7 @@ static void cleanup(Jpeg2000EncoderContext *s) > ff_jpeg2000_cleanup(comp, codsty, 1); > } > av_freep(&s->tile[tileno].comp); > + av_freep(&s->tile[tileno].layer_rates); > } > av_freep(&s->tile); > } > @@ -1379,6 +1597,64 @@ static int encode_frame(AVCodecContext *avctx, > AVPacket *pkt, > return 0; > } > > +static int inline check_number(char* st, int* ret) { > + int stlen = strlen(st); > + int i; > + *ret = 0; > + if (stlen <= 0) { > + return AVERROR_INVALIDDATA; > + } > + for (i = 0; i < stlen; i++) { > + if (st[i] >= '0' && st[i] <= '9') { > + *ret = (*ret) * 10 + (st[i] - '0'); > + } else { > + return AVERROR_INVALIDDATA; > + } > + } > + return 0; > +} > + > +static int parse_layer_rates(Jpeg2000EncoderContext *s) > +{ > + int i; > + char* token; > + int rate; > + int nlayers = 0; > + if (!s->lr_str) { > + s->nlayers = 1; > + s->layer_rates[0] = 0; > + return 0; > + } > + > + token = strtok(s->lr_str, ","); > + if (!check_number(token, &rate)) { > + s->layer_rates[0] = rate <= 1 ? 0:rate; > + nlayers++; > + } else { > + return AVERROR_INVALIDDATA; > + } > + > + while (1) { > + token = strtok(NULL, ","); > + if (!token) > + break; > + if (!check_number(token, &rate)) { > + s->layer_rates[nlayers] = rate <= 1 ? 0:rate; > + nlayers++; > + } else { > + return AVERROR_INVALIDDATA; > + } > + } > + > + for (i = 1; i < nlayers; i++) { > + if (s->layer_rates[i] >= s->layer_rates[i-1]) { > + return AVERROR_INVALIDDATA; > + } > + } > + s->nlayers = nlayers; > + return 0; > +} > + > static av_cold int j2kenc_init(AVCodecContext *avctx) > { > int i, ret; > @@ -1388,6 +1664,11 @@ static av_cold int j2kenc_init(AVCodecContext *avctx) > > s->avctx = avctx; > av_log(s->avctx, AV_LOG_DEBUG, "init\n"); > + if (parse_layer_rates(s)) { > + av_log(s, AV_LOG_WARNING, "Layer rates invalid. Shall encode with 1 > layer.\n"); > + s->nlayers = 1; > + s->layer_rates[0] = 0; > + } > > #if FF_API_PRIVATE_OPT > FF_DISABLE_DEPRECATION_WARNINGS > @@ -1408,6 +1689,7 @@ FF_ENABLE_DEPRECATION_WARNINGS > memset(codsty->log2_prec_heights, 15, sizeof(codsty->log2_prec_heights)); > codsty->nreslevels2decode= > codsty->nreslevels = 7; > + codsty->nlayers = s->nlayers; > codsty->log2_cblk_width = 4; > codsty->log2_cblk_height = 4; > codsty->transform = s->pred ? FF_DWT53 : FF_DWT97_INT; > @@ -1489,6 +1771,7 @@ static const AVOption options[] = { > { "rpcl", NULL, OFFSET(prog), > AV_OPT_TYPE_CONST, { .i64 = JPEG2000_PGOD_RPCL }, 0, 0, > VE, "prog" }, > { "pcrl", NULL, OFFSET(prog), > AV_OPT_TYPE_CONST, { .i64 = JPEG2000_PGOD_PCRL }, 0, 0, > VE, "prog" }, > { "cprl", NULL, OFFSET(prog), > AV_OPT_TYPE_CONST, { .i64 = JPEG2000_PGOD_CPRL }, 0, 0, > VE, "prog" }, > + { "layer_rates", "Layer Rates", OFFSET(lr_str), > AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, > { NULL } > }; > > diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c > index 70c25a0ca2..1c294ad9e6 100644 > --- a/libavcodec/jpeg2000.c > +++ b/libavcodec/jpeg2000.c > @@ -261,9 +261,11 @@ static void init_band_stepsize(AVCodecContext *avctx, > band->f_stepsize *= 0.5; > } > > -static int init_prec(Jpeg2000Band *band, > +static int init_prec(AVCodecContext *avctx, > + Jpeg2000Band *band, > Jpeg2000ResLevel *reslevel, > Jpeg2000Component *comp, > + Jpeg2000CodingStyle *codsty, > int precno, int bandno, int reslevelno, > int log2_band_prec_width, > int log2_band_prec_height) > @@ -366,6 +368,11 @@ static int init_prec(Jpeg2000Band *band, > cblk->lblock = 3; > cblk->length = 0; > cblk->npasses = 0; > + if (av_codec_is_encoder(avctx->codec)) { > + cblk->layers = av_mallocz_array(codsty->nlayers, > sizeof(*cblk->layers)); > + if (!cblk->layers) > + return AVERROR(ENOMEM); > + } > } > > return 0; > @@ -439,7 +446,7 @@ static int init_band(AVCodecContext *avctx, > return AVERROR(ENOMEM); > > for (precno = 0; precno < nb_precincts; precno++) { > - ret = init_prec(band, reslevel, comp, > + ret = init_prec(avctx, band, reslevel, comp, codsty, > precno, bandno, reslevelno, > log2_band_prec_width, log2_band_prec_height); > if (ret < 0) > @@ -614,6 +621,8 @@ void ff_jpeg2000_cleanup(Jpeg2000Component *comp, > Jpeg2000CodingStyle *codsty, i > av_freep(&cblk->passes); > av_freep(&cblk->lengthinc); > av_freep(&cblk->data_start); > + if (isencoder) > + av_freep(&cblk->layers); > } > av_freep(&prec->cblk); > } > diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h > index fee9607e86..3c6e8ede16 100644 > --- a/libavcodec/jpeg2000.h > +++ b/libavcodec/jpeg2000.h > @@ -162,10 +162,19 @@ typedef struct Jpeg2000Pass { > int flushed_len; > } Jpeg2000Pass; > > +typedef struct Jpeg2000Layer { > + uint8_t *data_start; > + int data_len; > + int npasses; > + double disto; > + int cum_passes; > +} Jpeg2000Layer; > + > typedef struct Jpeg2000Cblk { > uint8_t npasses; > uint8_t ninclpasses; // number coding of passes included in codestream > uint8_t nonzerobits; > + uint8_t incl; > uint16_t length; > uint16_t *lengthinc; > uint8_t nb_lengthinc; > @@ -176,6 +185,7 @@ typedef struct Jpeg2000Cblk { > int nb_terminationsinc; > int *data_start; > Jpeg2000Pass *passes; > + Jpeg2000Layer *layers; > int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} > } Jpeg2000Cblk; // code block > > -- > 2.17.1 >
This patch seems to be breaking FATE. I believe that the error is because the patch modifies the encoder such that the encoded files will be slightly different now. How can this be handled? -- ------------- Gautam | _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".