On Thu, Aug 20, 2020 at 12:55 AM Paul B Mahol <one...@gmail.com> wrote: > > On 8/19/20, Gautam Ramakrishnan <gautamr...@gmail.com> wrote: > > 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? > > Run fate. Make sure that you have SAMPLES set and rsynced with server. > > make fate-name-of-target GEN=1 > > To generate new hashes for encodes. > > Please read http://ffmpeg.org/fate.html > > > > -- > > ------------- > > Gautam |
I made all the changes as per suggestions and tried to generate new hashes for the encodes. However, when I run make fate with GEN=1 for target fate-vsynth1-jpeg2000, the file tests/ref/vsynth/vsynth1-jpeg2000 becomes empty instead of being filled with new data. The file tests/data/fate/vsynth1-jpeg2000.avi, which is to be encoded by this test seems to be encoded correctly. What am I missing here? -- ------------- 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".