From patchwork Tue Jul 14 16:43:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gautam Ramakrishnan X-Patchwork-Id: 21013 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 175B944AD8E for ; Tue, 14 Jul 2020 19:43:48 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id ECE2E68B2B1; Tue, 14 Jul 2020 19:43:47 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pj1-f67.google.com (mail-pj1-f67.google.com [209.85.216.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 73D5A68B302 for ; Tue, 14 Jul 2020 19:43:41 +0300 (EEST) Received: by mail-pj1-f67.google.com with SMTP id b92so1782203pjc.4 for ; Tue, 14 Jul 2020 09:43:41 -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:in-reply-to:references; bh=JucBMfKO30ZgNEhquw4QeCEWNCBZ0Ad9mamO1NPr2eU=; b=UQY/NhNLiy8MN9Ks5/zgROx8SSO5d2W9vaJj1OPbkKFU/Emp12ViK0kYpEzX3ynkVy Gx/eYexL8aK2B8QHZnXZ8EFJGxvFhjDVuBcp54yMx4gDgNzTmj7Gt23LVBNnfoTgZcUQ eOWgVFd2IyPhTCMUuFEmceUogCaxK3/1C5IHHmssiw8EgQC/J7AHVZguZ4mEmuPRuWdf 4/eR0WQuBYVMrO26XGrzbhQ0L/FJbkWkCxXmPGM4824GauWgTEF6fgqmkCLwt29aL9pN Wrxz5ZO0ZojLoTyxOSnmoOzP3nr8weZUKjdwAF6w/wdbS7fTtTfA/5gFC345ztA+cEOO BRPg== 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:in-reply-to :references; bh=JucBMfKO30ZgNEhquw4QeCEWNCBZ0Ad9mamO1NPr2eU=; b=CXp+6KMYY07agulSIL5o2ULIR7PZVPF9zNpJhVInVmXkiAKtheIj2zRaKzwAR28aJR Z3kiin3RhegvNSXe/fmCN0sk/zsE3B+SIJpDp0sYnCe2lNF62dWNgID5jayd59TYWz5/ z7QBvC2kNsyBRcw1gOaeTVah9Vzc34tz3Z3G/GxqQcwt8qNgSyLGVGP/7Ux9oKXUStYh omLf7vYJPx67jGBjDwVVHCGBNx4gkIh/mI44ls1b0/169UyvxytpLfaoumyVF0e+5pH4 yuMceOAIGiBrk9w2KlcHr5ROgs3ZJl9wFEjZMh2/JrxP6bhbVJx5FlAzj/GNntK5vIba t/vQ== X-Gm-Message-State: AOAM530t8NCjpthaP8c4AEXPenWy3YHsSvBNrs4vLF+oi/KkkSJO1au4 FKWy/01NMppVe45nfDgOl1QPOlrRZ4vcPg== X-Google-Smtp-Source: ABdhPJzIfibZJIoQWBvuNX9JTRmFgJT/lhOH8J4DT9hiFhukH71tfxyQkPhA44PyqvwkTdoVOit6Yw== X-Received: by 2002:a17:90a:3f88:: with SMTP id m8mr5209194pjc.26.1594745019428; Tue, 14 Jul 2020 09:43:39 -0700 (PDT) Received: from localhost.localdomain ([122.172.60.196]) by smtp.gmail.com with ESMTPSA id c1sm3295983pje.9.2020.07.14.09.43.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jul 2020 09:43:38 -0700 (PDT) From: gautamramk@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Tue, 14 Jul 2020 22:13:16 +0530 Message-Id: <20200714164316.32120-4-gautamramk@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200714164316.32120-1-gautamramk@gmail.com> References: <20200714164316.32120-1-gautamramk@gmail.com> Subject: [FFmpeg-devel] [PATCH v2 4/4] libavcodec/jpeg2000dec: Support for PPM marker 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 adds support for PPM marker for JPEG2000 decoder. It allows the samples p1_03.j2k and p1_05.j2k to be decoded. --- libavcodec/jpeg2000dec.c | 111 +++++++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 10 deletions(-) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 5ea6fd0b9a..4f3a5af20e 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -71,6 +71,7 @@ typedef struct Jpeg2000POC { typedef struct Jpeg2000TilePart { uint8_t tile_index; // Tile index who refers the tile-part const uint8_t *tp_end; + GetByteContext header_tpg; // bit stream of header if PPM header is used GetByteContext tpg; // bit stream in tile-part } Jpeg2000TilePart; @@ -102,6 +103,13 @@ typedef struct Jpeg2000DecoderContext { uint8_t cbps[4]; // bits per sample in particular components uint8_t sgnd[4]; // if a component is signed uint8_t properties[4]; + + uint8_t has_ppm; + uint8_t *packed_headers; // contains packed headers. Used only along with PPM marker + int packed_headers_size; + GetByteContext packed_headers_stream; + uint8_t in_tile_headers; + int cdx[4], cdy[4]; int precision; int ncomponents; @@ -928,6 +936,31 @@ static int get_plt(Jpeg2000DecoderContext *s, int n) return 0; } +static int get_ppm(Jpeg2000DecoderContext *s, int n) +{ + void *new; + + if (n < 3) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid length for PPM data.\n"); + return AVERROR_INVALIDDATA; + } + s->has_ppm = 1; + bytestream2_get_byte(&s->g); //Zppm is skipped and not used + new = av_realloc(s->packed_headers, + s->packed_headers_size + n - 3); + if (new) { + s->packed_headers = new; + } else + return AVERROR(ENOMEM); + memset(&s->packed_headers_stream, 0, sizeof(s->packed_headers_stream)); + memcpy(s->packed_headers + s->packed_headers_size, + s->g.buffer, n - 3); + s->packed_headers_size += n - 3; + bytestream2_skip(&s->g, n - 3); + + return 0; +} + static int get_ppt(Jpeg2000DecoderContext *s, int n) { Jpeg2000Tile *tile; @@ -1039,8 +1072,19 @@ static int getlblockinc(Jpeg2000DecoderContext *s) return res; } -static inline void select_stream(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, +static inline void select_header(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, int *tp_index) +{ + s->g = tile->tile_part[*tp_index].header_tpg; + if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) { + if (*tp_index < FF_ARRAY_ELEMS(tile->tile_part) - 1) { + s->g = tile->tile_part[++(*tp_index)].tpg; + } + } +} + +static inline void select_stream(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, + int *tp_index, Jpeg2000CodingStyle *codsty) { s->g = tile->tile_part[*tp_index].tpg; if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) { @@ -1048,8 +1092,12 @@ static inline void select_stream(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, s->g = tile->tile_part[++(*tp_index)].tpg; } } - if (bytestream2_peek_be32(&s->g) == JPEG2000_SOP_FIXED_BYTES) - bytestream2_skip(&s->g, JPEG2000_SOP_BYTE_LENGTH); + if (codsty->csty & JPEG2000_CSTY_SOP) { + if (bytestream2_peek_be32(&s->g) == JPEG2000_SOP_FIXED_BYTES) + bytestream2_skip(&s->g, JPEG2000_SOP_BYTE_LENGTH); + else + av_log(s->avctx, AV_LOG_ERROR, "SOP marker not found. instead %X\n", bytestream2_peek_be32(&s->g)); + } } static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, int *tp_index, @@ -1064,10 +1112,12 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, return 0; rlevel->band[0].prec[precno].decoded_layers = layno + 1; // Select stream to read from - if (tile->has_ppt) + if (s->has_ppm) + select_header(s, tile, tp_index); + else if (tile->has_ppt) s->g = tile->packed_headers_stream; else - select_stream(s, tile, tp_index); + select_stream(s, tile, tp_index, codsty); if (!(ret = get_bits(s, 1))) { jpeg2000_flush(s); @@ -1178,9 +1228,12 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, } // Save state of stream - if (tile->has_ppt) { + if (s->has_ppm) { + tile->tile_part[*tp_index].header_tpg = s->g; + select_stream(s, tile, tp_index, codsty); + } else if (tile->has_ppt) { tile->packed_headers_stream = s->g; - select_stream(s, tile, tp_index); + select_stream(s, tile, tp_index, codsty); } for (bandno = 0; bandno < rlevel->nbands; bandno++) { Jpeg2000Band *band = rlevel->band + bandno; @@ -1228,10 +1281,20 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, return 0; skip_data: - if (tile->has_ppt) + if (codsty->csty & JPEG2000_CSTY_EPH) { + if (bytestream2_peek_be16(&s->g) == JPEG2000_EPH) + bytestream2_skip(&s->g, 2); + else + av_log(s->avctx, AV_LOG_ERROR, "EPH marker not found. instead %X\n", bytestream2_peek_be32(&s->g)); + } + if (s->has_ppm) { + tile->tile_part[*tp_index].header_tpg = s->g; + select_stream(s, tile, tp_index, codsty); + } else if (tile->has_ppt) { tile->packed_headers_stream = s->g; - else - tile->tile_part[*tp_index].tpg = s->g; + select_stream(s, tile, tp_index, codsty); + } + tile->tile_part[*tp_index].tpg = s->g; return 0; } @@ -2064,6 +2127,9 @@ static void jpeg2000_dec_cleanup(Jpeg2000DecoderContext *s) s->tile[tileno].packed_headers_size = 0; } } + av_freep(&s->packed_headers); + s->packed_headers_size = 0; + memset(&s->packed_headers_stream, 0, sizeof(s->packed_headers_stream)); av_freep(&s->tile); memset(s->codsty, 0, sizeof(s->codsty)); memset(s->qntsty, 0, sizeof(s->qntsty)); @@ -2113,6 +2179,11 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) return AVERROR_INVALIDDATA; } + if (s->has_ppm) { + uint32_t tp_header_size = bytestream2_get_be32u(&s->packed_headers_stream); + bytestream2_init(&tp->header_tpg, s->packed_headers_stream.buffer, tp_header_size); + bytestream2_skip(&s->packed_headers_stream, tp_header_size); + } if (tile->has_ppt && tile->tp_idx == 0) { bytestream2_init(&tile->packed_headers_stream, tile->packed_headers, tile->packed_headers_size); } @@ -2164,6 +2235,12 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) ret = get_poc(s, len, poc); break; case JPEG2000_SOT: + if (!s->in_tile_headers) { + s->in_tile_headers = 1; + if (s->has_ppm) { + bytestream2_init(&s->packed_headers_stream, s->packed_headers, s->packed_headers_size); + } + } if (!(ret = get_sot(s, len))) { av_assert1(s->curtileno >= 0); codsty = s->tile[s->curtileno].codsty; @@ -2189,8 +2266,22 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) // Packet length, tile-part header ret = get_plt(s, len); break; + case JPEG2000_PPM: + // Packed headers, main header + if (s->in_tile_headers) { + av_log(s->avctx, AV_LOG_ERROR, "PPM Marker can only be in Main header\n"); + return AVERROR_INVALIDDATA; + } + ret = get_ppm(s, len); + break; case JPEG2000_PPT: // Packed headers, tile-part header + if (s->has_ppm) { + av_log(s->avctx, AV_LOG_ERROR, + "Cannot have both PPT and PPM marker.\n"); + return AVERROR_INVALIDDATA; + } + ret = get_ppt(s, len); break; default: