avcodec/jpeg2000dec: Support RPCL
authorMichael Niedermayer <michaelni@gmx.at>
Sun, 14 Jun 2015 00:41:53 +0000 (02:41 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Sun, 14 Jun 2015 00:53:51 +0000 (02:53 +0200)
Fixes Ticket 2792

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavcodec/jpeg2000dec.c

index 56332e6..f4df5c9 100644 (file)
@@ -1025,8 +1025,78 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
         break;
 
     case JPEG2000_PGOD_RPCL:
-        avpriv_request_sample(s->avctx, "Progression order RPCL");
-        ret = AVERROR_PATCHWELCOME;
+        av_log(s->avctx, AV_LOG_WARNING, "Progression order RPCL\n");
+        ok_reslevel = 1;
+        for (reslevelno = 0; ok_reslevel; reslevelno++) {
+            ok_reslevel = 0;
+
+            step_x = 32;
+            step_y = 32;
+            for (compno = 0; compno < s->ncomponents; compno++) {
+                Jpeg2000Component *comp     = tile->comp + compno;
+                Jpeg2000CodingStyle *codsty = tile->codsty + 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;
+
+            //FIXME we could iterate over less than the whole image
+            for (y = 0; y < s->height; y += step_y) {
+                for (x = 0; x < s->width; x += step_x) {
+                    for (compno = 0; compno < s->ncomponents; compno++) {
+                        Jpeg2000Component *comp     = tile->comp + compno;
+                        Jpeg2000CodingStyle *codsty = tile->codsty + compno;
+                        Jpeg2000QuantStyle *qntsty  = tile->qntsty + compno;
+                        uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; //  ==> N_L - r
+                        Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
+                        unsigned prcx, prcy;
+
+                        int xc = x / s->cdx[compno];
+                        int yc = y / s->cdy[compno];
+
+                        if (yc % (1 << (rlevel->log2_prec_height + reducedresno)))
+                            continue;
+
+                        if (xc % (1 << (rlevel->log2_prec_width + reducedresno)))
+                            continue;
+
+                        // check if a precinct exists
+                        prcx   = ff_jpeg2000_ceildivpow2(xc, reducedresno) >> rlevel->log2_prec_width;
+                        prcy   = ff_jpeg2000_ceildivpow2(yc, reducedresno) >> rlevel->log2_prec_height;
+                        prcx  -= ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], reducedresno) >> rlevel->log2_prec_width;
+                        prcy  -= ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], reducedresno) >> rlevel->log2_prec_height;
+
+                        precno = prcx + rlevel->num_precincts_x * prcy;
+
+                        if (prcx >= rlevel->num_precincts_x || prcy >= rlevel->num_precincts_y) {
+                            av_log(s->avctx, AV_LOG_WARNING, "prc %d %d outside limits %d %d\n",
+                                   prcx, prcy, rlevel->num_precincts_x, rlevel->num_precincts_y);
+                            continue;
+                        }
+
+                        if (reslevelno < codsty->nreslevels) {
+                            Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel +
+                                                    reslevelno;
+                            ok_reslevel = 1;
+                            for (layno = 0; layno < tile->codsty[0].nlayers; layno++) {
+                                if ((ret = jpeg2000_decode_packet(s, tile, &tp_index,
+                                                                codsty, rlevel,
+                                                                precno, layno,
+                                                                qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+                                                                qntsty->nguardbits)) < 0)
+                                    return ret;
+                            }
+                        }
+                    }
+                }
+            }
+        }
         break;
 
     case JPEG2000_PGOD_PCRL: