From patchwork Tue Jul 21 18:07:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gautam Ramakrishnan X-Patchwork-Id: 21217 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 5D49F4490CD for ; Tue, 21 Jul 2020 21:15:43 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 375E968B644; Tue, 21 Jul 2020 21:15:43 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pg1-f194.google.com (mail-pg1-f194.google.com [209.85.215.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5533468B5C3 for ; Tue, 21 Jul 2020 21:15:37 +0300 (EEST) Received: by mail-pg1-f194.google.com with SMTP id s189so12298444pgc.13 for ; Tue, 21 Jul 2020 11:15:37 -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=i7R7+SUJs4zG00atUX2A8sHTeAHutYLvE5asXLdNGDU=; b=cKYfFv9vboWFzrPw+Tm76MCxTjrbtia/lxCK2BZkVqU9xuXI1eGxCHhldcs8flVMdm BayQ/aNiCM9iLI3KaJ+29eED6CucE+oWvhUGgniCktM6Rq5UxC7cQxDnY7jY4/qVYW8B 9U8e1f0qDhN/bK92Jc92lY6/hlbRsTXaZt39u1fphX6p3mmZBgpUFPzW6nak35rsuvdY XC09UTeCzZSJYU6bDewwZiJEwQEzvc1Q5ulHrUCX4TdmGMO8fwGT5CPLyjZgUzzf4+Jm VaG3ZWRJREwLieluiHbFb0N18iqvj31XXdF3rJGLC/snMibciSvtWGGMF5mmIuXgU86n tSbA== 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=i7R7+SUJs4zG00atUX2A8sHTeAHutYLvE5asXLdNGDU=; b=DIpVW0iyks2ekitdsRQ8WAwDK4O5wtlMyPJR2G0GyPlzNseK5zmUOdU4GGPWREetz9 JKIrTbzTyrrDZGk1Ub5YpZAEVQUiFDVQoN4iRcixtvqmTBuqX6EZS4CwJZlC3JrAlEh8 V8lWI+HOXAx7d/gkl9pp4r/Nr9ehgQBQaUbiq7Ba1XM58dPR7HKcrfK7NFCayMf5QXIw KAgW3Plz3R5vZJnht08wYnCRmtqP30nqC5qkalFPfOoW9KccUk3xOYm40TMkUwtXu6s8 rd/XR34TlOaN8G6r+j/B9+cumgx0wKlPUmLDTtYLysE8nzlp5V0jKpDpC+OcaTq34HmG /Kag== X-Gm-Message-State: AOAM5314JdZic+p5bdfbnb5xQVNGCafLX1g31tX1XKpmi4RmVd64U0HR 5DuUdQz8z7oPIpU87ypnhcsyBGdIN27rsg== X-Google-Smtp-Source: ABdhPJxT8WVCIrAz7fv2yLjMy8e0W7OWY0+cocTKRanWkffQCJA24QW7zYobOWIzzF61ykR7YuHySg== X-Received: by 2002:a65:6883:: with SMTP id e3mr23931706pgt.5.1595354844922; Tue, 21 Jul 2020 11:07:24 -0700 (PDT) Received: from localhost.localdomain ([122.172.60.196]) by smtp.gmail.com with ESMTPSA id u2sm21543700pfl.21.2020.07.21.11.07.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Jul 2020 11:07:24 -0700 (PDT) From: gautamramk@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Tue, 21 Jul 2020 23:37:15 +0530 Message-Id: <20200721180715.19237-3-gautamramk@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200721180715.19237-1-gautamramk@gmail.com> References: <20200721180715.19237-1-gautamramk@gmail.com> Subject: [FFmpeg-devel] [PATCH v3 3/3] 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 | 107 +++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 10 deletions(-) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 23792c15b2..0bc29633ff 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,7 +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; @@ -929,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; + } + 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); + s->has_ppm = 1; + 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; @@ -1040,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) { @@ -1049,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, @@ -1065,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); @@ -1179,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; @@ -1229,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; } @@ -2065,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)); @@ -2115,6 +2180,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); } @@ -2168,6 +2238,9 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) 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); @@ -2194,8 +2267,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: