+ break;
+ case JPEG2000_PGOD_RPCL:
+ for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) {
+ int precno;
+ step_x = 30;
+ step_y = 30;
+ for (compno = 0; compno < s->ncomponents; compno++) {
+ Jpeg2000Component *comp = tile->comp + compno;
+ if (reslevelno < codsty->nreslevels) {
+ uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r
+ Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
+ step_x = FFMIN(step_x, rlevel->log2_prec_width + reducedresno);
+ step_y = FFMIN(step_y, rlevel->log2_prec_height + reducedresno);
+ }
+ }
+
+ step_x = 1<<step_x;
+ step_y = 1<<step_y;
+ for (y = tile_coord[1][0]; y < tile_coord[1][1]; y = (y/step_y + 1)*step_y) {
+ for (x = tile_coord[0][0]; x < tile_coord[0][1]; x = (x/step_x + 1)*step_x) {
+ for (compno = 0; compno < s->ncomponents; compno++) {
+ Jpeg2000Component *comp = tile->comp + compno;
+ uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r
+ Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
+ int log_subsampling[2] = { compno?s->chroma_shift[0]:0, compno?s->chroma_shift[1]:0};
+ unsigned prcx, prcy;
+ int trx0, try0;
+
+ trx0 = ff_jpeg2000_ceildivpow2(tile_coord[0][0], log_subsampling[0] + reducedresno);
+ try0 = ff_jpeg2000_ceildivpow2(tile_coord[1][0], log_subsampling[1] + reducedresno);
+
+ if (!(y % ((uint64_t)1 << (reslevel->log2_prec_height + reducedresno + log_subsampling[1])) == 0 ||
+ (y == tile_coord[1][0] && (try0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_height)))))
+ continue;
+
+ if (!(x % ((uint64_t)1 << (reslevel->log2_prec_width + reducedresno + log_subsampling[0])) == 0 ||
+ (x == tile_coord[0][0] && (trx0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_width)))))
+ continue;
+
+ // check if a precinct exists
+ prcx = ff_jpeg2000_ceildivpow2(x, log_subsampling[0] + reducedresno) >> reslevel->log2_prec_width;
+ prcy = ff_jpeg2000_ceildivpow2(y, log_subsampling[1] + reducedresno) >> reslevel->log2_prec_height;
+ prcx -= ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], reducedresno) >> reslevel->log2_prec_width;
+ prcy -= ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], reducedresno) >> reslevel->log2_prec_height;
+ precno = prcx + reslevel->num_precincts_x * prcy;
+
+ if (prcx >= reslevel->num_precincts_x || prcy >= reslevel->num_precincts_y) {
+ av_log(s->avctx, AV_LOG_WARNING, "prc %d %d outside limits %d %d\n",
+ prcx, prcy, reslevel->num_precincts_x, reslevel->num_precincts_y);
+ continue;
+ }
+ 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;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case JPEG2000_PGOD_PCRL:
+ step_x = 32;
+ step_y = 32;
+ for (compno = 0; compno < s->ncomponents; compno++) {
+ Jpeg2000Component *comp = tile->comp + compno;
+
+ for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) {
+ uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r
+ Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
+ step_x = FFMIN(step_x, rlevel->log2_prec_width + reducedresno);
+ step_y = FFMIN(step_y, rlevel->log2_prec_height + reducedresno);
+ }
+ }
+ if (step_x >= 31 || step_y >= 31){
+ avpriv_request_sample(s->avctx, "PCRL with large step");
+ return AVERROR_PATCHWELCOME;
+ }
+ step_x = 1<<step_x;
+ step_y = 1<<step_y;
+
+ for (y = tile_coord[1][0]; y < tile_coord[1][1]; y = (y/step_y + 1)*step_y) {
+ for (x = tile_coord[0][0]; x < tile_coord[0][1]; x = (x/step_x + 1)*step_x) {
+ for (compno = 0; compno < s->ncomponents; compno++) {
+ Jpeg2000Component *comp = tile->comp + compno;
+ int log_subsampling[2] = { compno?s->chroma_shift[0]:0, compno?s->chroma_shift[1]:0};
+
+ for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) {
+ unsigned prcx, prcy;
+ int precno;
+ uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r
+ Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
+ int trx0, try0;
+
+ trx0 = ff_jpeg2000_ceildivpow2(tile_coord[0][0], log_subsampling[0] + reducedresno);
+ try0 = ff_jpeg2000_ceildivpow2(tile_coord[1][0], log_subsampling[1] + reducedresno);
+
+ if (!(y % ((uint64_t)1 << (reslevel->log2_prec_height + reducedresno + log_subsampling[1])) == 0 ||
+ (y == tile_coord[1][0] && (try0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_height)))))
+ continue;
+
+ if (!(x % ((uint64_t)1 << (reslevel->log2_prec_width + reducedresno + log_subsampling[0])) == 0 ||
+ (x == tile_coord[0][0] && (trx0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_width)))))
+ continue;
+
+ // check if a precinct exists
+ prcx = ff_jpeg2000_ceildivpow2(x, log_subsampling[0] + reducedresno) >> reslevel->log2_prec_width;
+ prcy = ff_jpeg2000_ceildivpow2(y, log_subsampling[1] + reducedresno) >> reslevel->log2_prec_height;
+ prcx -= ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], reducedresno) >> reslevel->log2_prec_width;
+ prcy -= ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], reducedresno) >> reslevel->log2_prec_height;
+
+ precno = prcx + reslevel->num_precincts_x * prcy;
+
+ if (prcx >= reslevel->num_precincts_x || prcy >= reslevel->num_precincts_y) {
+ av_log(s->avctx, AV_LOG_WARNING, "prc %d %d outside limits %d %d\n",
+ prcx, prcy, reslevel->num_precincts_x, reslevel->num_precincts_y);
+ continue;
+ }
+ 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;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case JPEG2000_PGOD_CPRL:
+ for (compno = 0; compno < s->ncomponents; compno++) {
+ Jpeg2000Component *comp = tile->comp + compno;
+ int log_subsampling[2] = { compno?s->chroma_shift[0]:0, compno?s->chroma_shift[1]:0};
+ step_x = 32;
+ step_y = 32;
+
+ for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) {
+ uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r
+ Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
+ step_x = FFMIN(step_x, rlevel->log2_prec_width + reducedresno);
+ step_y = FFMIN(step_y, rlevel->log2_prec_height + reducedresno);
+ }
+ if (step_x >= 31 || step_y >= 31){
+ avpriv_request_sample(s->avctx, "CPRL with large step");
+ return AVERROR_PATCHWELCOME;
+ }
+ step_x = 1<<step_x;
+ step_y = 1<<step_y;
+
+ for (y = tile_coord[1][0]; y < tile_coord[1][1]; y = (y/step_y + 1)*step_y) {
+ for (x = tile_coord[0][0]; x < tile_coord[0][1]; x = (x/step_x + 1)*step_x) {
+ for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) {
+ unsigned prcx, prcy;
+ int precno;
+ int trx0, try0;
+ uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r
+ Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
+
+ trx0 = ff_jpeg2000_ceildivpow2(tile_coord[0][0], log_subsampling[0] + reducedresno);
+ try0 = ff_jpeg2000_ceildivpow2(tile_coord[1][0], log_subsampling[1] + reducedresno);
+
+ if (!(y % ((uint64_t)1 << (reslevel->log2_prec_height + reducedresno + log_subsampling[1])) == 0 ||
+ (y == tile_coord[1][0] && (try0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_height)))))
+ continue;
+
+ if (!(x % ((uint64_t)1 << (reslevel->log2_prec_width + reducedresno + log_subsampling[0])) == 0 ||
+ (x == tile_coord[0][0] && (trx0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_width)))))
+ continue;
+
+ // check if a precinct exists
+ prcx = ff_jpeg2000_ceildivpow2(x, log_subsampling[0] + reducedresno) >> reslevel->log2_prec_width;
+ prcy = ff_jpeg2000_ceildivpow2(y, log_subsampling[1] + reducedresno) >> reslevel->log2_prec_height;
+ prcx -= ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], reducedresno) >> reslevel->log2_prec_width;
+ prcy -= ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], reducedresno) >> reslevel->log2_prec_height;
+
+ precno = prcx + reslevel->num_precincts_x * prcy;
+
+ if (prcx >= reslevel->num_precincts_x || prcy >= reslevel->num_precincts_y) {
+ av_log(s->avctx, AV_LOG_WARNING, "prc %d %d outside limits %d %d\n",
+ prcx, prcy, reslevel->num_precincts_x, reslevel->num_precincts_y);
+ continue;
+ }
+ 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;
+ }
+ }
+ }
+ }
+ }
+
+ }
+