From patchwork Mon Jul 13 17:20:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gautam Ramakrishnan X-Patchwork-Id: 20996 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 32F3A449514 for ; Mon, 13 Jul 2020 20:28:05 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 19B6068A616; Mon, 13 Jul 2020 20:28:05 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-oi1-f193.google.com (mail-oi1-f193.google.com [209.85.167.193]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E515668A2D7 for ; Mon, 13 Jul 2020 20:27:58 +0300 (EEST) Received: by mail-oi1-f193.google.com with SMTP id x83so11601329oif.10 for ; Mon, 13 Jul 2020 10:27:58 -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=5acCDuOMG5I4e5YlTAsk/MS99XgcTCDu27h5PUNnZ80=; b=ccxsz33J+MfBIvdr4WUNAH8XehuxpEU6W9w2jiI4i7yexLZFPYsQB8arfwdFMewHui v+wldavbf7qvGY22ZQOr0zELJDTv+D1SJRSstFkMJdmZCGcwiNC+iSdj/A1hTgaO3fv2 fI5/DubnkuUcmIQt5ZktuyZ+rdYHzimBJW4tv3ANORgLUYGNHVFBO7TBH1VYA6oPt2nk ChteGcoobMZEpfQQUlzNHENzYViKM2Zo/mhkOg8G2jKo9g278ve6a9lmzvhAsh0Pd8dC 7PvIgHhBxMfAcRwBNSd1wP5SeKmqzZQiKE03Yd8HLtc6ojtrqUPFzz7rzgPEjM5mUpMM a5ZQ== 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=5acCDuOMG5I4e5YlTAsk/MS99XgcTCDu27h5PUNnZ80=; b=fsKlaSgZ7dndDXCO+TnTJmF47KLKr6QPh3xz9ME3b785cwbQh+zSFGu9/VJP5zKVEL hBAA0CXZkKEfx0qkUkUIlGTsOcg2s3XVLg0zTV52ijQgWb4HVj3qmJOzt5VFivbpUr8D 1IhmM48IxJJu4cLi3fL5vxgs1PIoRPThtYy+iSYbovs41x+wEv8/D3KMm5jEYJ95heGp pt6W7+dnmLUE/hTAaVpUvX0JcMG397POOlro1PosMmOKxjL28vLMV4vG1Nvk3fYn+geV De4CJPQP1eWn4QLstYnZLVENwT9R1xJ4GhOyvGXcTgwZhMi66CfpTtdY8fT6l8U0yWGH D1YQ== X-Gm-Message-State: AOAM532SMxxwjRB6BiiIjzlcBZSjF3V2yYUVS6m60KdlcEhIeXPRrpg8 opIPiwhZoWkmTWbG1sewvckveKjTxXAGNA== X-Google-Smtp-Source: ABdhPJxFUi320PkE03mENhIvw7h46afuixpsjCrA3KuI9Sqn+vNn+eCJa/aKNqFxDococKpT/6FdxQ== X-Received: by 2002:a17:90a:1b2c:: with SMTP id q41mr382191pjq.195.1594660815131; Mon, 13 Jul 2020 10:20:15 -0700 (PDT) Received: from localhost.localdomain ([122.172.60.196]) by smtp.gmail.com with ESMTPSA id 17sm168440pjl.30.2020.07.13.10.20.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jul 2020 10:20:14 -0700 (PDT) From: gautamramk@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Mon, 13 Jul 2020 22:50:02 +0530 Message-Id: <20200713172002.14158-4-gautamramk@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200713172002.14158-1-gautamramk@gmail.com> References: <20200713172002.14158-1-gautamramk@gmail.com> Subject: [FFmpeg-devel] [PATCH 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 | 107 +++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 10 deletions(-) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 5ea6fd0b9a..f6200a81ed 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,18 @@ 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 + 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: