From patchwork Thu Aug 6 17:39:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gautam Ramakrishnan X-Patchwork-Id: 21517 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 53F2A44AF4B for ; Thu, 6 Aug 2020 21:31:56 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 29B2868B6D3; Thu, 6 Aug 2020 21:31:56 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pl1-f194.google.com (mail-pl1-f194.google.com [209.85.214.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7F40C68B4B2 for ; Thu, 6 Aug 2020 21:31:49 +0300 (EEST) Received: by mail-pl1-f194.google.com with SMTP id g19so15651184plq.0 for ; Thu, 06 Aug 2020 11:31:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=UIKGMgBGXONpOSIY6EUYRlGzmum1EQ3myhhWYOFXhEY=; b=o0WY/gfq/GIgzyv0D0vqOVXKsvJGOecPF4LJ6HF2/sbXvGTqbIQ4rUQTMIf850V5py Aq7jFIPeHpz/dv9WzfYp+hoHoax4yMtlQekxrFfzNqMKCZ+6T/Lj9m3PtoX0ou076GaJ FOoED39ul+dagPrEA1QTvDpUDbuucuMz8U3wKxdmwPUwSY93ThOg+RCVSQk84f71uNYu 9y9KS8CEjtVjTGhg435NXEQCoZqdI07waAn6WXQfT6+uedV3Qq9F/YnQnSXOUXRbj4bg o/BxUl1vu3pxAJXYHtyKBQis1EEXSEVaOFkl/F9AZWoHYeetVdLKn7Uu9BXeFBhMvS4N lUHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=UIKGMgBGXONpOSIY6EUYRlGzmum1EQ3myhhWYOFXhEY=; b=t5dvNVpkG0tGiHxPlXTx9uQbimHvw/HSZMPk4Aszrug81R2qE00tUHmGhZ1ugjuBa3 r8LWOGdwV9UFbyH1biooIvbmfFXnn35Irsierqn73nlY4yyQwn3xeoVgPWfYoE+Lup/l 9OCwXRIHu49X1Y9TYZnRL7cE1LZp1nS7CcTH6Mu0wN/BMb4dBDt6YTGkNTKrnCiAJG+J EFUaIaP79W+YIZniRnM6cXHJWIYsxRglyj/lxy16WXR5J0q5WYMqGia/VHbTPUyNn25D STKRYDOp+zbB5WRur5tsLuUJKRMFRHtXjxp1zBhtbxoVdqKUqfjOkscxECwfer3uZo7A k8dA== X-Gm-Message-State: AOAM53043Y0SFSBLeS1kp0sijzFWKZuaG3ZbIzPFk9f4+o5HHFlLswpt +jHV8CkZABb0Vgp/qUwFxYx98LHrM25nTw== X-Google-Smtp-Source: ABdhPJxMzWfETRBCVyzLu2wplQeJVBUk3VSf2/msOkp8LG0LuKzYv5rK1eqtuQ05ro/eEmCezvjTSA== X-Received: by 2002:a62:19d4:: with SMTP id 203mr9052816pfz.127.1596735586766; Thu, 06 Aug 2020 10:39:46 -0700 (PDT) Received: from localhost.localdomain ([223.235.235.63]) by smtp.gmail.com with ESMTPSA id w12sm7904725pjb.18.2020.08.06.10.39.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Aug 2020 10:39:46 -0700 (PDT) From: gautamramk@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Thu, 6 Aug 2020 23:09:32 +0530 Message-Id: <20200806173932.19843-1-gautamramk@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH] libavcodec/j2kenc: Support for all Progression orders X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Gautam Ramakrishnan MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Gautam Ramakrishnan 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(-) 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<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<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<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 } };