diff mbox series

[FFmpeg-devel] libavcodec/j2kenc: Support for all Progression orders

Message ID 20200806173932.19843-1-gautamramk@gmail.com
State Accepted
Commit 9ce787d61eefffb3fd3e00d399c212267c5b1c75
Headers show
Series [FFmpeg-devel] libavcodec/j2kenc: Support for all Progression orders | expand

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Gautam Ramakrishnan Aug. 6, 2020, 5:39 p.m. UTC
From: Gautam Ramakrishnan <gautamramk@gmail.com>

This patch allows for selecting the progression order
in the j2k encoder. However, all components and resolution
levels will use the same progression order and will not
feature the use of progression order change markers.
---
 libavcodec/j2kenc.c | 223 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 222 insertions(+), 1 deletion(-)

Comments

Michael Niedermayer Aug. 9, 2020, 1:26 p.m. UTC | #1
On Thu, Aug 06, 2020 at 11:09:32PM +0530, gautamramk@gmail.com wrote:
> From: Gautam Ramakrishnan <gautamramk@gmail.com>
> 
> This patch allows for selecting the progression order
> in the j2k encoder. However, all components and resolution
> levels will use the same progression order and will not
> feature the use of progression order change markers.
> ---
>  libavcodec/j2kenc.c | 223 +++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 222 insertions(+), 1 deletion(-)

will apply

thx

[...]
diff mbox series

Patch

diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
index fad013521b..16863f8e8c 100644
--- a/libavcodec/j2kenc.c
+++ b/libavcodec/j2kenc.c
@@ -131,6 +131,7 @@  typedef struct {
     int pred;
     int sop;
     int eph;
+    int prog;
 } Jpeg2000EncoderContext;
 
 
@@ -323,7 +324,7 @@  static int put_cod(Jpeg2000EncoderContext *s)
         scod |= JPEG2000_CSTY_EPH;
     bytestream_put_byte(&s->buf, scod);  // Scod
     // SGcod
-    bytestream_put_byte(&s->buf, 0); // progression level
+    bytestream_put_byte(&s->buf, s->prog); // progression level
     bytestream_put_be16(&s->buf, 1); // num of layers
     if(s->avctx->pix_fmt == AV_PIX_FMT_YUV444P){
         bytestream_put_byte(&s->buf, 0); // unspecified
@@ -837,8 +838,21 @@  static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int til
     Jpeg2000CodingStyle *codsty = &s->codsty;
     Jpeg2000QuantStyle  *qntsty = &s->qntsty;
     int packetno = 0;
+    int step_x, step_y;
+    int x, y;
+    int tile_coord[2][2];
+    int col = tileno % s->numXtiles;
+    int row = tileno / s->numXtiles;
+
+    tile_coord[0][0] = col * s->tile_width;
+    tile_coord[0][1] = FFMIN(tile_coord[0][0] + s->tile_width, s->width);
+    tile_coord[1][0] = row * s->tile_height;
+    tile_coord[1][1] = FFMIN(tile_coord[1][0] + s->tile_height, s->height);
+
     av_log(s->avctx, AV_LOG_DEBUG, "tier2\n");
     // lay-rlevel-comp-pos progression
+    switch (s->prog) {
+    case JPEG2000_PGOD_LRCP:
     for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){
         for (compno = 0; compno < s->ncomponents; compno++){
             int precno;
@@ -850,6 +864,207 @@  static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int til
             }
         }
     }
+    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;
+            }
+        }
+    }
+    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;
+                    }
+
+                    if ((ret = encode_packet(s, reslevel, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0),
+                              qntsty->nguardbits, packetno++)) < 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;
+                        }
+                        if ((ret = encode_packet(s, reslevel, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0),
+                                  qntsty->nguardbits, packetno++)) < 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;
+                        }
+                        if ((ret = encode_packet(s, reslevel, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0),
+                                  qntsty->nguardbits, packetno++)) < 0)
+                            return ret;
+                    }
+                }
+            }
+        }
+
+    }
+
     av_log(s->avctx, AV_LOG_DEBUG, "after tier2\n");
     return 0;
 }
@@ -1261,6 +1476,12 @@  static const AVOption options[] = {
     { "dwt53",         NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = 0           }, INT_MIN, INT_MAX,       VE, "pred"        },
     { "sop",           "SOP marker",        OFFSET(sop),           AV_OPT_TYPE_INT,   { .i64 = 0           }, 0,         1,           VE, },
     { "eph",           "EPH marker",        OFFSET(eph),           AV_OPT_TYPE_INT,   { .i64 = 0           }, 0,         1,           VE, },
+    { "prog",          "Progression Order", OFFSET(prog),          AV_OPT_TYPE_INT,   { .i64 = 0           }, JPEG2000_PGOD_LRCP,         JPEG2000_PGOD_CPRL,           VE, "prog" },
+    { "lrcp",          NULL,                OFFSET(prog),          AV_OPT_TYPE_CONST,   { .i64 = JPEG2000_PGOD_LRCP           }, 0,         0,           VE, "prog" },
+    { "rlcp",          NULL,                OFFSET(prog),          AV_OPT_TYPE_CONST,   { .i64 = JPEG2000_PGOD_RLCP            }, 0,         0,           VE, "prog" },
+    { "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" },
     { NULL }
 };