From patchwork Tue Apr 11 18:28:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre-Anthony Lemieux X-Patchwork-Id: 41084 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4645:b0:e3:3194:9d20 with SMTP id eb5csp3094555pzb; Tue, 11 Apr 2023 11:28:44 -0700 (PDT) X-Google-Smtp-Source: AKy350aouBPA3RIG2LxMJHdBU2v/J/6vVSg3lgPz9is0ritjjgWPoyGhPulshelaj1rTRIzVSmEU X-Received: by 2002:a17:906:6447:b0:930:f953:9608 with SMTP id l7-20020a170906644700b00930f9539608mr13644670ejn.0.1681237724338; Tue, 11 Apr 2023 11:28:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681237724; cv=none; d=google.com; s=arc-20160816; b=c4clVWUtvdC7MuQuQw8AYitAQ5tt3bTzyaWO3H4rOLbqmmV79PME+l6AFKveT0pFO2 +75YjiUXTyqUOnOzTH2muHWWyMu3ut6ZNMe3UTaWTiyk3CPLG9/glQPDsRGJtRmEH7+6 M6ZKALu2oNaKiHp3OOKpW7V+4a4ztLvmxd+bvKQwi9QUwFLQtuqfkHyJYr71JP8cG8ci b82JSop3lKy8Z8NfIDOyNWaWL1NjcCACeC+bYYq1jV09Kjso+5cSCYkhwxdtE1+IBegi 0v1DycJh7R1J6ZAtzVGUtNsJIUbtUh1J2QBRTEuRvWFrDztHGwX5HWXG9gvJrV1OZbc+ UXYw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:message-id:date:to:from :delivered-to; bh=7hvc+f9MMgfV8obWtHpL02BB4gZ0xTq3GEHP1rQk4YQ=; b=MlhvFBlrH6HJRJwl4SOHExu9CKU9He7+npIEUGZ/ufClZ1icR6t2PI7N1orhWcvD8W ow5m476woJY7nPIl4SMwFee1zDvLWLroKqPX6X/6rfT9NKXsYq6w6JM1bds7VXgjBlyz t6pjH2EED/BJipJlPhdAJzW35YQVqfccbibnOiE2lgH7vbm22Gp/a4QCZFE0bIZTtAZG YqGBfef5SdDNL7yWMX64vcaDFverc1et8OixTaGqbhv7GEw/KoEAQuvVJGWY7djWw76+ 8JQK/elhNxa+U9F+ge94zvcysysgF5qYIwfQClAbfsAUiypZWM+Z7FPCh1UbdJGInCFU QljQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id he6-20020a1709073d8600b0094a80df8722si2322568ejc.797.2023.04.11.11.28.40; Tue, 11 Apr 2023 11:28:44 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2BCB868A8CB; Tue, 11 Apr 2023 21:28:37 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pj1-f51.google.com (mail-pj1-f51.google.com [209.85.216.51]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A9E66689B83 for ; Tue, 11 Apr 2023 21:28:30 +0300 (EEST) Received: by mail-pj1-f51.google.com with SMTP id f2so318690pjs.3 for ; Tue, 11 Apr 2023 11:28:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681237708; x=1683829708; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=sArIdNTJOjXItMgBwQmenwgeLiLShBfLtcxgL/N6yH8=; b=BZJJFFyCCLlzvzKtQTgTg+1/qszm4iV0OMBZc01NQwTKBj0c4Orvi452Eldhf/kJZc 4FUtHgOf2MiawOYQqaYOBvIRF+dF55q28GfniKNPc8ToXBq7oVsxPLO30lPPiojYU4AM 8FBqrGLdzjzVqIexP1KiQJycSd9oEC2CQNKbiyDKyPm/75dQyaetXhUrtI61NjL/XHiv H7QJe4Wb2EcoD0EyhgaxHzraNXiFndvBGJWxO4/4DZVjuu/7J7NpkDYl7iMxeWJ9NT9x 9J1LKpsrITeH0lue25YDT45+Uocuhl+SFkSlkKPG9FpjeEUfZVVAdLBy/pqAVVoq3V4v mfig== X-Gm-Message-State: AAQBX9eEDi5VQ6jVblmsTxyU7XJCuh2ooEDAdXoFK9Q5kEB9VyFTfnh+ kl1lQYOfjGwsqpWVPK6fFaLN04QPSPg= X-Received: by 2002:a05:6a20:8014:b0:d9:4269:4d23 with SMTP id e20-20020a056a20801400b000d942694d23mr15494539pza.48.1681237707763; Tue, 11 Apr 2023 11:28:27 -0700 (PDT) Received: from localhost (76-14-89-2.sf-cable.astound.net. [76.14.89.2]) by smtp.gmail.com with ESMTPSA id d2-20020aa78e42000000b00627f054a3cdsm6473509pfr.31.2023.04.11.11.28.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Apr 2023 11:28:26 -0700 (PDT) Received: by localhost (sSMTP sendmail emulation); Tue, 11 Apr 2023 11:28:23 -0700 From: pal@sandflow.com To: ffmpeg-devel@ffmpeg.org Date: Tue, 11 Apr 2023 11:28:20 -0700 Message-Id: <20230411182822.28859-1-pal@sandflow.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 1/3] avcodec/jpeg2000dec: move decoder structs to a header file X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: caleb Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: fST7ZEF8tmcK From: caleb Adds support for HT code-blocks to jpeg2000dec Addresses comments against https://patchwork.ffmpeg.org/project/ffmpeg/list/?series=8661 * simplify loop using av_log2() * document and simplify asserts * fix big endian and 32-bit builds * allow codestreams with both Part 1 and Part 15 code-blocks --- libavcodec/jpeg2000dec.c | 88 +--------------------------- libavcodec/jpeg2000dec.h | 121 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 87 deletions(-) create mode 100644 libavcodec/jpeg2000dec.h diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index c2b81ec103..5994e29ae3 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -42,6 +42,7 @@ #include "jpeg2000.h" #include "jpeg2000dsp.h" #include "profiles.h" +#include "jpeg2000dec.h" #define JP2_SIG_TYPE 0x6A502020 #define JP2_SIG_VALUE 0x0D0A870A @@ -51,93 +52,6 @@ #define HAD_COC 0x01 #define HAD_QCC 0x02 -#define MAX_POCS 32 - -typedef struct Jpeg2000POCEntry { - uint16_t LYEpoc; - uint16_t CSpoc; - uint16_t CEpoc; - uint8_t RSpoc; - uint8_t REpoc; - uint8_t Ppoc; -} Jpeg2000POCEntry; - -typedef struct Jpeg2000POC { - Jpeg2000POCEntry poc[MAX_POCS]; - int nb_poc; - int is_default; -} 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; - -/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile - * one per component, so tile_part elements have a size of 3 */ -typedef struct Jpeg2000Tile { - Jpeg2000Component *comp; - uint8_t properties[4]; - Jpeg2000CodingStyle codsty[4]; - Jpeg2000QuantStyle qntsty[4]; - Jpeg2000POC poc; - Jpeg2000TilePart tile_part[32]; - uint8_t has_ppt; // whether this tile has a ppt marker - uint8_t *packed_headers; // contains packed headers. Used only along with PPT marker - int packed_headers_size; // size in bytes of the packed headers - GetByteContext packed_headers_stream; // byte context corresponding to packed headers - uint16_t tp_idx; // Tile-part index - int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} -} Jpeg2000Tile; - -typedef struct Jpeg2000DecoderContext { - AVClass *class; - AVCodecContext *avctx; - GetByteContext g; - - int width, height; - int image_offset_x, image_offset_y; - int tile_offset_x, tile_offset_y; - 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; - int colour_space; - uint32_t palette[256]; - int8_t pal8; - int cdef[4]; - int tile_width, tile_height; - unsigned numXtiles, numYtiles; - int maxtilelen; - AVRational sar; - - Jpeg2000CodingStyle codsty[4]; - Jpeg2000QuantStyle qntsty[4]; - Jpeg2000POC poc; - uint8_t roi_shift[4]; - - int bit_index; - - int curtileno; - - Jpeg2000Tile *tile; - Jpeg2000DSPContext dsp; - - /*options parameters*/ - int reduction_factor; -} Jpeg2000DecoderContext; - /* get_bits functions for JPEG2000 packet bitstream * It is a get_bit function with a bit-stuffing routine. If the value of the * byte is 0xFF, the next byte includes an extra zero bit stuffed into the MSB. diff --git a/libavcodec/jpeg2000dec.h b/libavcodec/jpeg2000dec.h new file mode 100644 index 0000000000..c148416889 --- /dev/null +++ b/libavcodec/jpeg2000dec.h @@ -0,0 +1,121 @@ +/* + * JPEG 2000 image decoder + * Copyright (c) 2007 Kamil Nowosad + * Copyright (c) 2013 Nicolas Bertrand + * Copyright (c) 2022 Caleb Etemesi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_JPEG2000DEC_H +#define AVCODEC_JPEG2000DEC_H + +#include "bytestream.h" +#include "jpeg2000.h" +#include "jpeg2000dsp.h" + + +#define MAX_POCS 32 + +typedef struct Jpeg2000POCEntry { + uint16_t LYEpoc; + uint16_t CSpoc; + uint16_t CEpoc; + uint8_t RSpoc; + uint8_t REpoc; + uint8_t Ppoc; +} Jpeg2000POCEntry; + +typedef struct Jpeg2000POC { + Jpeg2000POCEntry poc[MAX_POCS]; + int nb_poc; + int is_default; +} 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; + +/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile + * one per component, so tile_part elements have a size of 3 */ +typedef struct Jpeg2000Tile { + Jpeg2000Component *comp; + uint8_t properties[4]; + Jpeg2000CodingStyle codsty[4]; + Jpeg2000QuantStyle qntsty[4]; + Jpeg2000POC poc; + Jpeg2000TilePart tile_part[32]; + uint8_t has_ppt; // whether this tile has a ppt marker + uint8_t *packed_headers; // contains packed headers. Used only along with PPT marker + int packed_headers_size; // size in bytes of the packed headers + GetByteContext packed_headers_stream; // byte context corresponding to packed headers + uint16_t tp_idx; // Tile-part index + int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} +} Jpeg2000Tile; + +typedef struct Jpeg2000DecoderContext { + AVClass *class; + AVCodecContext *avctx; + GetByteContext g; + + int width, height; + int image_offset_x, image_offset_y; + int tile_offset_x, tile_offset_y; + 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; + int colour_space; + uint32_t palette[256]; + int8_t pal8; + int cdef[4]; + int tile_width, tile_height; + unsigned numXtiles, numYtiles; + int maxtilelen; + AVRational sar; + + Jpeg2000CodingStyle codsty[4]; + Jpeg2000QuantStyle qntsty[4]; + Jpeg2000POC poc; + uint8_t roi_shift[4]; + + int bit_index; + + int curtileno; + + Jpeg2000Tile *tile; + Jpeg2000DSPContext dsp; + + /*options parameters*/ + int reduction_factor; + /*HTJ2K params*/ + uint8_t is_htj2k; +} Jpeg2000DecoderContext; + +#endif //AVCODEC_JPEG2000DEC_H From patchwork Tue Apr 11 18:28:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Pierre-Anthony Lemieux X-Patchwork-Id: 41085 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4645:b0:e3:3194:9d20 with SMTP id eb5csp3094619pzb; Tue, 11 Apr 2023 11:28:51 -0700 (PDT) X-Google-Smtp-Source: AKy350Y/HgoIiwyvJBJIjZblS/lhG5UK/7EPAkn0A3oKK0EOk+OGd6uQRinsgif2VWzXQJ8dtBV4 X-Received: by 2002:a17:907:16a0:b0:94a:8f3a:1a65 with SMTP id hc32-20020a17090716a000b0094a8f3a1a65mr4281038ejc.5.1681237730836; Tue, 11 Apr 2023 11:28:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681237730; cv=none; d=google.com; s=arc-20160816; b=IkBRGqakprzuowBgpgJ9ckWvLwtkOpxc4AV7W5uE+Z11vTIeF4ewvwU9eX3qFiAl8d SKxUEcUOrJhrQrpXl+TkaxabmlFVaWheCMO8fB8/eaJ96MAHXpR4c4/ySTc1M5fVquI+ Dr9mZTRRX4x3OfFDazvrgg7Lc9IZPS4WNTT4FeXP/CUb2oMOJ+luq9FyN7t7jCbez2Si hWeKnVOkRqGhyWniW9kJ/SznDOGLq1/55OnmyAIDgOkqU/vQ3lMLeWsNts0eG8DvPNNg 0W3de5G2ns94iVp0a+hWxBgov5xfohGT8z0pYUdJjXgYmABGybhMU2wQy2tMAXvoTzwj dFXA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=dJ9JQQSGhei4aa89N+UtvVWk4xHrX/jJcjYsAg957no=; b=rjcrHtELysoW+zhZCAkse7ZGrxnFkGHcxAiqotv61IjJoIG5RBLD/XGQrK3BcR8Lqw fSoH+CPLhpPaKmCEtTmZTBg2tp2EqGCWuB7jXDQCCsdang93p54RNjcEaV0FXEDSIwCd Np3Gp8JChR5YtJVosmlIZMKrk2Eq6nDe77Z/bSJ0kgfyd7yFfWd04vh3RYIvuStXH3Jv ETAJp5aPqqEUnyGWWsCLJF4imBJ32+g/TmDh/4718ZMP32smZn3P8Jd00YLwRUZnOxPn 6E2xyBamFJQYqw2JtDifkxxq0wUMShQTIr7CjmclUNhahSmUnp3uqxW3hIuRJw53Fn0Z 37+g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id g2-20020a170906198200b0094a88aae22fsi2066912ejd.856.2023.04.11.11.28.50; Tue, 11 Apr 2023 11:28:50 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7461068ABCF; Tue, 11 Apr 2023 21:28:42 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 90F7368A279 for ; Tue, 11 Apr 2023 21:28:34 +0300 (EEST) Received: by mail-pl1-f170.google.com with SMTP id ik20so8591573plb.3 for ; Tue, 11 Apr 2023 11:28:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681237712; x=1683829712; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=od0HyPwi595sulwDqVBAc23epM5/+s+YtbzkcBgoCQc=; b=j/lYhY7jjY5mAvp4Gxx1ltbf7CcyCI1ofUmnKS2Ld/3CBKNQptJ3vzTANfGmIOmGvJ /UJhjWxOt9I6rZ0sWblu76FG3bOu8HZVqD7HM4GyMgJ0pWYd/xdazray+UwIRGuz5MKi R1P9xUPQ3kkqwDuBZVRLjKzukgurloJwNMJg8GPSWpjKxSHm2oNfUNtx+Ou8GOe6I0k8 y7WFxoeCDV+iEnKPgej8y2mBhENyObWCPaWGLGKipsM1mBw4GlCghcUF8U2ElNtgNKIp u0idbUiwZEEI73rOrLwboKyCjiSindKFDl4CP7bl1ev8X6W4q3oYONURdZeyxyQtg020 N6iA== X-Gm-Message-State: AAQBX9fJcMeLKb8azjkXJvcjYU9N0H3ePu6lg3lIt65K77npj3hczak2 hUSzkcmkkeUA/OTKyJNjRdIelHWPbQI= X-Received: by 2002:a17:90b:1809:b0:246:bb61:4a6a with SMTP id lw9-20020a17090b180900b00246bb614a6amr7735163pjb.1.1681237711210; Tue, 11 Apr 2023 11:28:31 -0700 (PDT) Received: from localhost (76-14-89-2.sf-cable.astound.net. [76.14.89.2]) by smtp.gmail.com with ESMTPSA id y7-20020a17090a154700b00246a770310esm124261pja.11.2023.04.11.11.28.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Apr 2023 11:28:30 -0700 (PDT) Received: by localhost (sSMTP sendmail emulation); Tue, 11 Apr 2023 11:28:27 -0700 From: pal@sandflow.com To: ffmpeg-devel@ffmpeg.org Date: Tue, 11 Apr 2023 11:28:21 -0700 Message-Id: <20230411182822.28859-2-pal@sandflow.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230411182822.28859-1-pal@sandflow.com> References: <20230411182822.28859-1-pal@sandflow.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 2/3] avcodec/jpeg2000dec: add support for HTJ2K block decoding X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: caleb Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: +fGFJF/Tr8xR From: caleb --- libavcodec/Makefile | 2 +- libavcodec/jpeg2000.h | 5 +- libavcodec/jpeg2000dec.c | 67 +- libavcodec/jpeg2000htdec.c | 1451 ++++++++++++++++++++++++++++++++++++ libavcodec/jpeg2000htdec.h | 34 + 5 files changed, 1540 insertions(+), 19 deletions(-) create mode 100644 libavcodec/jpeg2000htdec.c create mode 100644 libavcodec/jpeg2000htdec.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index aa10fbfcf8..053c074f2f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -469,7 +469,7 @@ OBJS-$(CONFIG_JACOSUB_DECODER) += jacosubdec.o ass.o OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o jpeg2000.o \ jpeg2000dwt.o OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o jpeg2000dsp.o \ - jpeg2000dwt.o mqcdec.o mqc.o + jpeg2000dwt.o mqcdec.o mqc.o jpeg2000htdec.o OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o OBJS-$(CONFIG_JPEGLS_ENCODER) += jpeglsenc.o jpegls.o OBJS-$(CONFIG_JV_DECODER) += jvdec.o diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h index e5ecb4cbf9..d004c08f10 100644 --- a/libavcodec/jpeg2000.h +++ b/libavcodec/jpeg2000.h @@ -111,7 +111,7 @@ enum Jpeg2000Quantsty { // quantization style #define JPEG2000_CSTY_SOP 0x02 // SOP marker present #define JPEG2000_CSTY_EPH 0x04 // EPH marker present #define JPEG2000_CTSY_HTJ2K_F 0x40 // Only HT code-blocks (Rec. ITU-T T.814 | ISO/IEC 15444-15) are present -#define JPEG2000_CTSY_HTJ2K_M 0xC0 // HT code blocks (Rec. ITU-T T.814 | ISO/IEC 15444-15) can be present +#define JPEG2000_CTSY_HTJ2K_M 0xC0 // HT code-blocks (Rec. ITU-T T.814 | ISO/IEC 15444-15) can be present // Progression orders #define JPEG2000_PGOD_LRCP 0x00 // Layer-resolution level-component-position progression @@ -189,6 +189,9 @@ typedef struct Jpeg2000Cblk { Jpeg2000Pass *passes; Jpeg2000Layer *layers; int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} + /* specific to HT code-blocks */ + int zbp; + int pass_lengths[2]; } Jpeg2000Cblk; // code block typedef struct Jpeg2000Prec { diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 5994e29ae3..9f792051b0 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -43,6 +43,7 @@ #include "jpeg2000dsp.h" #include "profiles.h" #include "jpeg2000dec.h" +#include "jpeg2000htdec.h" #define JP2_SIG_TYPE 0x6A502020 #define JP2_SIG_VALUE 0x0D0A870A @@ -436,12 +437,13 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) c->cblk_style = bytestream2_get_byteu(&s->g); if (c->cblk_style != 0) { // cblk style if (c->cblk_style & JPEG2000_CTSY_HTJ2K_M || c->cblk_style & JPEG2000_CTSY_HTJ2K_F) { - av_log(s->avctx, AV_LOG_ERROR, "Support for High throughput JPEG 2000 is not yet available\n"); - return AVERROR_PATCHWELCOME; + av_log(s->avctx,AV_LOG_TRACE,"High Throughput jpeg 2000 codestream.\n"); + s->is_htj2k = 1; + } else { + av_log(s->avctx, AV_LOG_WARNING, "extra cblk styles %X\n", c->cblk_style); + if (c->cblk_style & JPEG2000_CBLK_BYPASS) + av_log(s->avctx, AV_LOG_WARNING, "Selective arithmetic coding bypass\n"); } - av_log(s->avctx, AV_LOG_WARNING, "extra cblk styles %X\n", c->cblk_style); - if (c->cblk_style & JPEG2000_CBLK_BYPASS) - av_log(s->avctx, AV_LOG_WARNING, "Selective arithmetic coding bypass\n"); } c->transform = bytestream2_get_byteu(&s->g); // DWT transformation type /* set integer 9/7 DWT in case of BITEXACT flag */ @@ -1066,13 +1068,15 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, return incl; if (!cblk->npasses) { - int v = expn[bandno] + numgbits - 1 - - tag_tree_decode(s, prec->zerobits + cblkno, 100); + int zbp = tag_tree_decode(s, prec->zerobits + cblkno, 100); + int v = expn[bandno] + numgbits - 1 - zbp; + if (v < 0 || v > 30) { av_log(s->avctx, AV_LOG_ERROR, "nonzerobits %d invalid or unsupported\n", v); return AVERROR_INVALIDDATA; } + cblk->zbp = zbp; cblk->nonzerobits = v; } if ((newpasses = getnpasses(s)) < 0) @@ -1113,8 +1117,23 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, } } - if ((ret = get_bits(s, av_log2(newpasses1) + cblk->lblock)) < 0) - return ret; + if (newpasses > 1 && s->is_htj2k) { + // Retrieve pass lengths for each pass + int href_passes = (cblk->npasses + newpasses - 1) % 3; + int eb = av_log2(newpasses - href_passes); + int extra_bit = newpasses > 2 ? 1 : 0; + if ((ret = get_bits(s, llen + eb + 3)) < 0) + return ret; + cblk->pass_lengths[0] = ret; + if ((ret = get_bits(s, llen + 3 + extra_bit)) < 0) + return ret; + cblk->pass_lengths[1] = ret; + ret = cblk->pass_lengths[0] + cblk->pass_lengths[1]; + } else { + if ((ret = get_bits(s, av_log2(newpasses1) + cblk->lblock)) < 0) + return ret; + cblk->pass_lengths[0] = ret; + } if (ret > cblk->data_allocated) { size_t new_size = FFMAX(2*cblk->data_allocated, ret); void *new = av_realloc(cblk->data, new_size); @@ -1863,9 +1882,12 @@ static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile /* Loop on tile components */ for (compno = 0; compno < s->ncomponents; compno++) { - Jpeg2000Component *comp = tile->comp + compno; - Jpeg2000CodingStyle *codsty = tile->codsty + compno; + Jpeg2000Component *comp = tile->comp + compno; + Jpeg2000CodingStyle *codsty = tile->codsty + compno; + Jpeg2000QuantStyle *quantsty = tile->qntsty + compno; + int coded = 0; + int subbandno = 0; t1.stride = (1<log2_cblk_width) + 2; @@ -1873,7 +1895,7 @@ static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile for (reslevelno = 0; reslevelno < codsty->nreslevels2decode; reslevelno++) { Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno; /* Loop on bands */ - for (bandno = 0; bandno < rlevel->nbands; bandno++) { + for (bandno = 0; bandno < rlevel->nbands; bandno++, subbandno++) { int nb_precincts, precno; Jpeg2000Band *band = rlevel->band + bandno; int cblkno = 0, bandpos; @@ -1893,12 +1915,23 @@ static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile for (cblkno = 0; cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height; cblkno++) { - int x, y; + int x, y, ret; + /* See Rec. ITU-T T.800, Equation E-2 */ + int magp = quantsty->expn[subbandno] + quantsty->nguardbits - 1; + Jpeg2000Cblk *cblk = prec->cblk + cblkno; - int ret = decode_cblk(s, codsty, &t1, cblk, - cblk->coord[0][1] - cblk->coord[0][0], - cblk->coord[1][1] - cblk->coord[1][0], - bandpos, comp->roi_shift); + + if (codsty->cblk_style & JPEG2000_CTSY_HTJ2K_F) + ret = ff_jpeg2000_decode_htj2k(s, codsty, &t1, cblk, + cblk->coord[0][1] - cblk->coord[0][0], + cblk->coord[1][1] - cblk->coord[1][0], + magp, comp->roi_shift); + else + ret = decode_cblk(s, codsty, &t1, cblk, + cblk->coord[0][1] - cblk->coord[0][0], + cblk->coord[1][1] - cblk->coord[1][0], + bandpos, comp->roi_shift); + if (ret) coded = 1; else diff --git a/libavcodec/jpeg2000htdec.c b/libavcodec/jpeg2000htdec.c new file mode 100644 index 0000000000..51cd96e0f1 --- /dev/null +++ b/libavcodec/jpeg2000htdec.c @@ -0,0 +1,1451 @@ +/* + * Copyright (c) 2022 Caleb Etemesi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Copyright 2019 - 2021, Osamu Watanabe + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/avassert.h" +#include "jpeg2000htdec.h" +#include "jpeg2000.h" +#include "jpeg2000dec.h" + +#define J2K_Q1 0 +#define J2K_Q2 1 + +#define HT_SHIFT_SIGMA 0 +#define HT_SHIFT_SCAN 4 +#define HT_SHIFT_REF 3 +#define HT_SHIFT_REF_IND 2 + +/* See Rec. ITU-T T.800, Table 2 */ +const static uint8_t mel_e[13] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5 }; + +static const uint16_t dec_cxt_vlc_table1[1024]; +static const uint16_t dec_cxt_vlc_table0[1024]; + +typedef struct StateVars { + int32_t pos; + uint32_t bits; + uint32_t tmp; + uint32_t last; + uint8_t bits_left; + uint64_t bit_buf; +} StateVars; + +typedef struct MelDecoderState { + uint8_t k; + uint8_t run; + uint8_t one; +} MelDecoderState; + +/** + * Given a precomputed c, checks whether n % d == 0. c is precomputed from d + * using precompute_c(). + */ +av_always_inline +static uint32_t is_divisible(uint32_t n, uint64_t c) +{ + return n * c <= c - 1; +} + +/** + * Precompute the number c used by is_divisible(). + */ +av_always_inline +static uint64_t precompute_c(uint32_t d) +{ + return 1 + (0xffffffffffffffffull / d); +} + +static void jpeg2000_init_zero(StateVars *s) +{ + s->bits_left = 0; + s->bit_buf = 0; + s->tmp = 0; + s->bits = 0; + s->pos = 0; + s->last = 0; +} + +static void jpeg2000_init_mel(StateVars *s, uint32_t Pcup) +{ + jpeg2000_init_zero(s); + s->pos = Pcup; +} + +static void jpeg2000_init_mag_ref(StateVars *s, uint32_t Lref) +{ + s->pos = Lref - 2; + s->bits = 0; + s->last = 0xFF; + s->tmp = 0; + s->bits_left = 0; + s->bit_buf = 0; +} + +static void jpeg2000_init_mel_decoder(MelDecoderState *mel_state) +{ + mel_state->k = 0; + mel_state->run = 0; + mel_state->one = 0; +} + +/** + * Refill the buffer backwards in little endian while skipping over stuffing + * bits. Stuffing bits are those that appear in the position of any byte whose + * LSBs are all 1's if the last consumed byte was larger than 0x8F. + */ +static int jpeg2000_bitbuf_refill_backwards(StateVars *buffer, const uint8_t *array) +{ + uint64_t tmp = 0; + int32_t position = buffer->pos; + uint32_t new_bits = 32; + + if (buffer->bits_left >= 32) + return 0; // enough data, no need to pull in more bits + + /** + * We are reading bytes from end to start and need to handle being close to + * the end. Subtracting by 4 means we will read some of the bytes of the MEL + * byte stream since the MEL byte stream ends at the start of the VLC byte + * stream. This is okay as they are masked away since we check for cases + * where that occurs (when the position is less than 4). + */ + position -= 4; + + tmp = AV_RB32(&array[position + 1]); + + if (buffer->pos < 4){ + /* mask un-needed bits if we are close to input end */ + uint64_t mask = (1ull << (buffer->pos + 1) * 8) - 1; + tmp &= mask; + } + + /** + * Unstuff bits. Load a temporary byte, which precedes the position we + * currently at, to ensure that we can also un-stuff if the stuffed bit is + * the bottom most bits. + */ + tmp <<= 8; + tmp |= array[buffer->pos + 1]; + + if ((tmp & 0x7FFF000000) > 0x7F8F000000) { + tmp &= 0x7FFFFFFFFF; + new_bits--; + } + if ((tmp & 0x007FFF0000) > 0x007F8F0000) { + tmp = (tmp & 0x007FFFFFFF) + ((tmp & 0xFF00000000) >> 1); + new_bits--; + } + if ((tmp & 0x00007FFF00) > 0x00007F8F00) { + tmp = (tmp & 0x00007FFFFF) + ((tmp & 0xFFFF000000) >> 1); + new_bits--; + } + if ((tmp & 0x0000007FFF) > 0x0000007F8F) { + tmp = (tmp & 0x0000007FFF) + ((tmp & 0xFFFFFF0000) >> 1); + new_bits--; + } + + tmp >>= 8; // Remove temporary byte loaded + + /* Add bits to the MSB of the bit buffer */ + buffer->bit_buf |= tmp << buffer->bits_left; + buffer->bits_left += new_bits; + buffer->pos = FFMAX(0, position); + return 0; +} + +/** + * Refill the bit-buffer reading new bits going forward + * in the stream while skipping over stuffed bits. + */ +static void jpeg2000_bitbuf_refill_forward(StateVars *buffer, const uint8_t *array, + uint32_t length) +{ + while (buffer->bits_left < 32) { + buffer->tmp = 0xFF; + buffer->bits = (buffer->last == 0xFF) ? 7 : 8; + if (buffer->pos <= length) { + buffer->tmp = array[buffer->pos]; + buffer->pos += 1; + buffer->last = buffer->tmp; + } + buffer->bit_buf |= ((uint64_t) buffer->tmp) << buffer->bits_left; + buffer->bits_left += buffer->bits; + } +} + +/** + * Drops bits from lower bits in the bit buffer. buf contains the bit buffers. + * nbits is the number of bits to remove. + */ +av_always_inline +static void jpeg2000_bitbuf_drop_bits_lsb(StateVars *buf, uint8_t nbits) +{ + av_assert2(buf->bits_left >= nbits); // cannot read more bits than available + buf->bit_buf >>= nbits; + buf->bits_left -= nbits; +} + +/** + * Get bits from the bit buffer reading them from the least significant bits + * moving to the most significant bits. In case there are fewer bits, refill + * from buf moving backwards. + */ +av_always_inline +static uint64_t jpeg2000_bitbuf_get_bits_lsb(StateVars *bit_stream, uint8_t nbits, + const uint8_t *buf) +{ + uint64_t bits; + uint64_t mask = (1ull << nbits) - 1; + if (bit_stream->bits_left < nbits) + jpeg2000_bitbuf_refill_backwards(bit_stream, buf); + bits = bit_stream->bit_buf & mask; + jpeg2000_bitbuf_drop_bits_lsb(bit_stream, nbits); + return bits; +} + +/** + * Get bits from the bit buffer reading them from the least significant bits + * moving to the most significant bits. In case there are fewer bits, refill from + * buf moving forward. + */ +av_always_inline +static uint64_t jpeg2000_bitbuf_get_bits_lsb_forward(StateVars *bit_stream, + uint8_t nbits, const uint8_t *buf, + uint32_t length) +{ + uint64_t bits; + uint64_t mask = (1ull << nbits) - 1; + + if (bit_stream->bits_left <= nbits) + jpeg2000_bitbuf_refill_forward(bit_stream, buf, length); + bits = bit_stream->bit_buf & mask; + jpeg2000_bitbuf_drop_bits_lsb(bit_stream, nbits); + return bits; +} + +/** + * Look ahead bit buffer without discarding bits. + */ +av_always_inline +static uint64_t jpeg2000_bitbuf_peek_bits_lsb(StateVars *stream, uint8_t nbits) +{ + uint64_t mask = (1ull << nbits) - 1; + return stream->bit_buf & mask; +} + +static void jpeg2000_init_vlc(StateVars *s, uint32_t Lcup, uint32_t Pcup, + const uint8_t *Dcup) +{ + s->bits_left = 0; + s->bit_buf = 0; + s->pos = Lcup - 2 - Pcup; + s->last = Dcup[Lcup - 2]; + s->tmp = (s->last) >> 4; + s->bits = ((s->tmp & 7) < 7) ? 4 : 3; + + jpeg2000_bitbuf_refill_backwards(s, Dcup + Pcup); + jpeg2000_bitbuf_drop_bits_lsb(s, 4); +} + +/** + * Decode prefix codes for VLC segment. See Rec. ITU-T T.814, 7.3.5. + */ +av_always_inline +static int jpeg2000_decode_ctx_vlc(const Jpeg2000DecoderContext *s, + StateVars *vlc_stream, const uint16_t *table, + const uint8_t *Dcup, uint8_t *sig_pat, + uint8_t *res_off, uint8_t *emb_pat_k, + uint8_t *emb_pat_1, uint8_t pos, + uint32_t Pcup, uint16_t context) +{ + uint32_t value; + uint8_t len; + uint64_t index; + uint64_t code_word; + + jpeg2000_bitbuf_refill_backwards(vlc_stream, Dcup + Pcup); + + code_word = vlc_stream->bit_buf & 0x7f; + index = code_word + (context << 7); + + av_assert0(index < 1024); // The CxtVLC table has 1024 entries. + + value = table[index]; + + len = (value & 0x000F) >> 1; + + res_off[pos] = (uint8_t) (value & 1); + sig_pat[pos] = (uint8_t) ((value & 0x00F0) >> 4); + emb_pat_k[pos] = (uint8_t) ((value & 0x0F00) >> 8); + emb_pat_1[pos] = (uint8_t) ((value & 0xF000) >> 12); + + jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, len); + return 0; +} + +/** + * Decode variable length u-vlc prefix. See decodeUPrefix procedure at Rec. + * ITU-T T.814, 7.3.6. + */ +av_always_inline +static uint8_t vlc_decode_u_prefix(StateVars *vlc_stream, const uint8_t *refill_array) +{ + static const uint8_t return_value[8] = { 5, 1, 2, 1, 3, 1, 2, 1 }; + static const uint8_t drop_bits[8] = { 3, 1, 2, 1, 3, 1, 2, 1 }; + + uint8_t bits; + + if (vlc_stream->bits_left < 3) + jpeg2000_bitbuf_refill_backwards(vlc_stream, refill_array); + + bits = jpeg2000_bitbuf_peek_bits_lsb(vlc_stream, 3); + + jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, drop_bits[bits]); + return return_value[bits]; +} + +/** + * Decode variable length u-vlc suffix. See decodeUSuffix procedure at Rec. + * ITU-T T.814, 7.3.6. + */ +av_always_inline +static uint8_t vlc_decode_u_suffix(StateVars *vlc_stream, uint8_t suffix, + const uint8_t *refill_array) +{ + static const int mask[] = { 1, 31 }; + static const int drop_bits[] = { 1, 5 }; + + uint8_t bits; + int cond = suffix != 3; + if (suffix < 3) + return 0; + + if (vlc_stream->bits_left < 5) + jpeg2000_bitbuf_refill_backwards(vlc_stream, refill_array); + + bits = jpeg2000_bitbuf_peek_bits_lsb(vlc_stream, 5); + + jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, drop_bits[cond]); + return bits & mask[cond]; +} + +/** + * Decode u-vlc extension values. See decodeUExtension procedure at Rec. ITU-T + * T.814, 7.3.6. + */ +av_always_inline +static uint8_t vlc_decode_u_extension(StateVars *vlc_stream, uint8_t suffix, + const uint8_t *refill_array) +{ + return jpeg2000_bitbuf_get_bits_lsb(vlc_stream, 4 * (suffix >= 28), refill_array); +} + +/** + * Magnitude and Sign decode procedures. See decodeMagSgnValue procedure at Rec. + * ITU-T T.814, 7.3.8. + */ +av_always_inline +static int32_t jpeg2000_decode_mag_sgn(StateVars *mag_sgn_stream, int32_t m_n, + int32_t i_n, const uint8_t *buf, uint32_t length) +{ + int32_t val = 0; + if (m_n > 0) { + val = jpeg2000_bitbuf_get_bits_lsb_forward(mag_sgn_stream,m_n,buf,length); + val += (i_n << m_n); + } + return val; +} + +av_always_inline +static void recover_mag_sgn(StateVars *mag_sgn, uint8_t pos, uint16_t q, int32_t m_n[2], + int32_t known_1[2], const uint8_t emb_pat_1[2], + int32_t v[2][4], int32_t m[2][4], uint8_t *E, + uint32_t *mu_n, const uint8_t *Dcup, uint32_t Pcup, + uint32_t pLSB) +{ + for (int i = 0; i < 4; i++) { + int32_t n = 4 * q + i; + m_n[pos] = m[pos][i]; + known_1[pos] = (emb_pat_1[pos] >> i) & 1; + v[pos][i] = jpeg2000_decode_mag_sgn(mag_sgn, m_n[pos], known_1[pos], Dcup, Pcup); + + if (m_n[pos] != 0) { + E[n] = 32 - ff_clz(v[pos][i] | 1); + mu_n[n] = (v[pos][i] >> 1) + 1; + mu_n[n] <<= pLSB; + mu_n[n] |= ((uint32_t) (v[pos][i] & 1)) << 31; // sign bit. + } + } +} + +static int jpeg2000_import_bit(StateVars *stream, const uint8_t *array, uint32_t length) +{ + int cond = stream->pos <= length; + int pos = FFMIN(stream->pos, length); + if (stream->bits == 0) { + stream->bits = (stream->tmp == 0xFF) ? 7 : 8; + stream->pos += cond; + stream->tmp = cond ? array[pos] : 0xFF; + } + stream->bits -= 1; + return (stream->tmp >> stream->bits) & 1; +} + +static int jpeg2000_peek_bit(StateVars *stream, const uint8_t *array, uint32_t length) +{ + if (stream->bits == 0) { + int cond = stream->pos <= length; + int pos = FFMIN(stream->pos, length); + stream->bits = (stream->tmp == 0xFF) ? 7 : 8; + stream->pos += cond; + stream->tmp = cond ? array[pos] : 0xFF; + } + return (stream->tmp >> stream->bits) & 1; +} + +static int jpeg2000_decode_mel_sym(MelDecoderState *mel_state, + StateVars *mel_stream, + const uint8_t *Dcup, + uint32_t Lcup) +{ + + if (mel_state->run == 0 && mel_state->one == 0) { + uint8_t eval; + uint8_t bit; + + eval = mel_e[mel_state->k]; + bit = jpeg2000_import_bit(mel_stream, Dcup, Lcup); + if (bit == 1) { + mel_state->run = 1 << eval; + mel_state->k = FFMIN(12, mel_state->k + 1); + } else { + mel_state->run = 0; + while (eval > 0) { + bit = jpeg2000_import_bit(mel_stream, Dcup, Lcup); + mel_state->run = (2 * (mel_state->run)) + bit; + eval -= 1; + } + mel_state->k = FFMAX(0, mel_state->k - 1); + mel_state->one = 1; + } + } + if (mel_state->run > 0) { + mel_state->run -= 1; + return 0; + } else { + mel_state->one = 0; + return 1; + } +} + +/** + * Magref decoding procedures. + */ +av_always_inline +static int jpeg2000_import_magref_bit(StateVars *stream, const uint8_t *array, + uint32_t length) +{ + return jpeg2000_bitbuf_get_bits_lsb(stream, 1, array); +} + +/** + * Signal EMB decode. + */ +static int jpeg2000_decode_sig_emb(const Jpeg2000DecoderContext *s, MelDecoderState *mel_state, + StateVars *mel_stream, StateVars *vlc_stream, + const uint16_t *vlc_table, const uint8_t *Dcup, + uint8_t *sig_pat, uint8_t *res_off, uint8_t *emb_pat_k, + uint8_t *emb_pat_1, uint8_t pos, uint16_t context, + uint32_t Lcup, uint32_t Pcup) +{ + if (context == 0) { + uint8_t sym; + sym = jpeg2000_decode_mel_sym(mel_state, mel_stream, Dcup, Lcup); + if (sym == 0) { + sig_pat[pos] = 0; + res_off[pos] = 0; + emb_pat_k[pos] = 0; + emb_pat_1[pos] = 0; + return 0; + } + } + return jpeg2000_decode_ctx_vlc(s, vlc_stream, vlc_table, Dcup, sig_pat, + res_off, emb_pat_k, emb_pat_1, pos, Pcup, + context); +} + +av_always_inline +static int jpeg2000_get_state(int x1, int x2, int width, int shift_by, + const uint8_t *block_states) +{ + return (block_states[(x1 + 1) * (width + 2) + (x2 + 1)] >> shift_by) & 1; +} + +av_always_inline +static void jpeg2000_modify_state(int x1, int x2, int width, + int value, uint8_t *block_states) +{ + block_states[(x1 + 1) * (width + 2) + (x2 + 1)] |= value; +} + +av_always_inline +static int jpeg2000_decode_ht_cleanup_segment(const Jpeg2000DecoderContext *s, + Jpeg2000Cblk *cblk, Jpeg2000T1Context *t1, + MelDecoderState *mel_state, + StateVars *mel_stream, StateVars *vlc_stream, + StateVars *mag_sgn_stream, const uint8_t *Dcup, + uint32_t Lcup, uint32_t Pcup, uint8_t pLSB, + int width, int height, int32_t *sample_buf, + uint8_t *block_states) +{ + uint16_t q = 0; // Represents current quad position + uint16_t q1, q2; + uint16_t context1, context2; + uint16_t context = 0; + + uint8_t sig_pat[2] = { 0 }; // significance pattern + uint8_t res_off[2] = { 0 }; // residual offset + uint8_t emb_pat_k[2] = { 0 }; // exponent Max Bound pattern K + uint8_t emb_pat_1[2] = { 0 }; // exponent Max Bound pattern 1 + uint8_t gamma[2] = { 0 }; + + uint8_t E_n[2] = { 0 }; + uint8_t E_ne[2] = { 0 }; + uint8_t E_nw[2] = { 0 }; + uint8_t E_nf[2] = { 0 }; + + uint8_t max_e[2] = { 0 }; + uint8_t u_pfx[2] = { 0 }; + uint8_t u_sfx[2] = { 0 }; + uint8_t u_ext[2] = { 0 }; + + int32_t u[2] = { 0 }; + int32_t U[2] = { 0 }; // exponent bound + int32_t m_n[2] = { 0 }; + int32_t known_1[2] = { 0 }; + + int32_t m[2][4] = { 0 }; + int32_t v[2][4] = { 0 }; + + uint8_t kappa[2] = { 1, 1 }; + + int ret = 0; + + int sp; + + uint64_t c; + + uint8_t *sigma; + uint32_t *mu; + + const uint8_t *vlc_buf = Dcup + Pcup; + + /* convert to raster-scan */ + const uint16_t is_border_x = width % 2; + const uint16_t is_border_y = height % 2; + + const uint16_t quad_width = ff_jpeg2000_ceildivpow2(width, 1); + const uint16_t quad_height = ff_jpeg2000_ceildivpow2(height, 1); + + size_t buf_size = 4 * quad_width * quad_height; + + uint8_t *sigma_n = av_calloc(buf_size, sizeof(uint8_t)); + uint8_t *E = av_calloc(buf_size, sizeof(uint8_t)); + uint32_t *mu_n = av_calloc(buf_size, sizeof(uint32_t)); + + if (!sigma_n || !E || !mu_n) { + ret = AVERROR(ENOMEM); + goto free; + } + + sigma = sigma_n; + mu = mu_n; + + while (q < quad_width - 1) { + q1 = q; + q2 = q1 + 1; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table0, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q1, context, Lcup, + Pcup)) < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1; + + /* calculate context */ + context = sigma_n[4 * q1]; // f + context |= sigma_n[4 * q1 + 1]; // sf + context += sigma_n[4 * q1 + 2] << 1; // w << 1 + context += sigma_n[4 * q1 + 3] << 2; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table0, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q2, context, Lcup, + Pcup)) < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q2 + i] = (sig_pat[J2K_Q2] >> i) & 1; + + /* calculate context for the next quad */ + context = sigma_n[4 * q2]; // f + context |= sigma_n[4 * q2 + 1]; // sf + context += sigma_n[4 * q2 + 2] << 1; // w << 1 + context += sigma_n[4 * q2 + 3] << 2; // sw << 2 + + u[0] = 0; + u[1] = 0; + + jpeg2000_bitbuf_refill_backwards(vlc_stream, vlc_buf); + + if (res_off[J2K_Q1] == 1 && res_off[J2K_Q2] == 1) { + + if (jpeg2000_decode_mel_sym(mel_state, mel_stream, Dcup, Lcup) == 1) { + + u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_pfx[J2K_Q2] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_sfx[J2K_Q2] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q2], vlc_buf); + + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q2] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q2], vlc_buf); + + u[J2K_Q1] = 2 + u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] * 4); + u[J2K_Q2] = 2 + u_pfx[J2K_Q2] + u_sfx[J2K_Q2] + (u_ext[J2K_Q2] * 4); + + } else { + u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + + if (u_pfx[J2K_Q1] > 2) { + u[J2K_Q2] = jpeg2000_bitbuf_get_bits_lsb(vlc_stream, 1, vlc_buf) + 1; + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + } else { + u_pfx[J2K_Q2] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_sfx[J2K_Q2] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q2], vlc_buf); + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q2] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q2], vlc_buf); + u[J2K_Q2] = u_pfx[J2K_Q2] + u_sfx[J2K_Q2] + (u_ext[J2K_Q2] * 4); + } + /* See Rec. ITU-T T.814, 7.3.6(3) */ + u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] * 4); + } + + } else if (res_off[J2K_Q1] == 1 || res_off[J2K_Q2] == 1) { + uint8_t pos = res_off[J2K_Q1] == 1 ? 0 : 1; + u_pfx[pos] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_sfx[pos] = vlc_decode_u_suffix(vlc_stream, u_pfx[pos], vlc_buf); + u_ext[pos] = vlc_decode_u_extension(vlc_stream, u_sfx[pos], vlc_buf); + u[pos] = u_pfx[pos] + u_sfx[pos] + (u_ext[pos] * 4); + } + U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1]; + U[J2K_Q2] = kappa[J2K_Q2] + u[J2K_Q2]; + + for (int i = 0; i < 4; i++) { + m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1); + m[J2K_Q2][i] = sigma_n[4 * q2 + i] * U[J2K_Q2] - ((emb_pat_k[J2K_Q2] >> i) & 1); + } + + recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + + recover_mag_sgn(mag_sgn_stream, J2K_Q2, q2, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + + q += 2; // Move to the next quad pair + } + + if (quad_width % 2 == 1) { + q1 = q; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table0, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q1, context, Lcup, + Pcup)) < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1; + + u[J2K_Q1] = 0; + + if (res_off[J2K_Q1] == 1) { + u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] * 4); + } + + U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1]; + + for (int i = 0; i < 4; i++) + m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1); + + recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + + q++; // move to next quad pair + } + + /** + * Initial line pair end. As an optimization, we can replace modulo + * operations with checking if a number is divisible , since that's the only + * thing we need. This is paired with is_divisible. Credits to Daniel Lemire + * blog post [1]. + * + * [1] + * https://lemire.me/blog/2019/02/08/faster-remainders-when-the-divisor-is-a-constant-beating-compilers-and-libdivide/ + * + * It's UB on zero, but the spec doesn't allow a quad being zero, so we + * error out early in case that's the case. + */ + c = precompute_c(quad_width); + + for (int row = 1; row < quad_height; row++) { + while ((q - (row * quad_width)) < quad_width - 1 && q < (quad_height * quad_width)) { + q1 = q; + q2 = q + 1; + context1 = sigma_n[4 * (q1 - quad_width) + 1]; + context1 += sigma_n[4 * (q1 - quad_width) + 3] << 2; // ne + + if (!is_divisible(q1, c)) { + context1 |= sigma_n[4 * (q1 - quad_width) - 1]; // nw + context1 += (sigma_n[4 * q1 - 1] | sigma_n[4 * q1 - 2]) << 1; // sw | q + } + if (!is_divisible(q1 + 1, c)) + context1 |= sigma_n[4 * (q1 - quad_width) + 5] << 2; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table1, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q1, context1, Lcup, + Pcup)) + < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1; + + context2 = sigma_n[4 * (q2 - quad_width) + 1]; + context2 += sigma_n[4 * (q2 - quad_width) + 3] << 2; + + if (!is_divisible(q2, c)) { + context2 |= sigma_n[4 * (q2 - quad_width) - 1]; + context2 += (sigma_n[4 * q2 - 1] | sigma_n[4 * q2 - 2]) << 1; + } + if (!is_divisible(q2 + 1, c)) + context2 |= sigma_n[4 * (q2 - quad_width) + 5] << 2; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table1, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q2, context2, Lcup, + Pcup)) + < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q2 + i] = (sig_pat[J2K_Q2] >> i) & 1; + + u[J2K_Q1] = 0; + u[J2K_Q2] = 0; + + jpeg2000_bitbuf_refill_backwards(vlc_stream, vlc_buf); + + if (res_off[J2K_Q1] == 1 && res_off[J2K_Q2] == 1) { + u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_pfx[J2K_Q2] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_sfx[J2K_Q2] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q2], vlc_buf); + + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q2] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q2], vlc_buf); + + u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] << 2); + u[J2K_Q2] = u_pfx[J2K_Q2] + u_sfx[J2K_Q2] + (u_ext[J2K_Q2] << 2); + + } else if (res_off[J2K_Q1] == 1 || res_off[J2K_Q2] == 1) { + uint8_t pos = res_off[J2K_Q1] == 1 ? 0 : 1; + + u_pfx[pos] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_sfx[pos] = vlc_decode_u_suffix(vlc_stream, u_pfx[pos], vlc_buf); + u_ext[pos] = vlc_decode_u_extension(vlc_stream, u_sfx[pos], vlc_buf); + + u[pos] = u_pfx[pos] + u_sfx[pos] + (u_ext[pos] << 2); + } + sp = sig_pat[J2K_Q1]; + + gamma[J2K_Q1] = 1; + + if (sp == 0 || sp == 1 || sp == 2 || sp == 4 || sp == 8) + gamma[J2K_Q1] = 0; + + sp = sig_pat[J2K_Q2]; + + gamma[J2K_Q2] = 1; + + if (sp == 0 || sp == 1 || sp == 2 || sp == 4 || sp == 8) + gamma[J2K_Q2] = 0; + + E_n[J2K_Q1] = E[4 * (q1 - quad_width) + 1]; + E_n[J2K_Q2] = E[4 * (q2 - quad_width) + 1]; + + E_ne[J2K_Q1] = E[4 * (q1 - quad_width) + 3]; + E_ne[J2K_Q2] = E[4 * (q2 - quad_width) + 3]; + + E_nw[J2K_Q1] = (!is_divisible(q1, c)) * E[FFMAX((4 * (q1 - quad_width) - 1), 0)]; + E_nw[J2K_Q2] = (!is_divisible(q2, c)) * E[FFMAX((4 * (q2 - quad_width) - 1), 0)]; + + E_nf[J2K_Q1] = (!is_divisible(q1 + 1, c)) * E[4 * (q1 - quad_width) + 5]; + E_nf[J2K_Q2] = (!is_divisible(q2 + 1, c)) * E[4 * (q2 - quad_width) + 5]; + + max_e[J2K_Q1] = FFMAX(E_nw[J2K_Q1], FFMAX3(E_n[J2K_Q1], E_ne[J2K_Q1], E_nf[J2K_Q1])); + max_e[J2K_Q2] = FFMAX(E_nw[J2K_Q2], FFMAX3(E_n[J2K_Q2], E_ne[J2K_Q2], E_nf[J2K_Q2])); + + kappa[J2K_Q1] = FFMAX(1, gamma[J2K_Q1] * (max_e[J2K_Q1] - 1)); + kappa[J2K_Q2] = FFMAX(1, gamma[J2K_Q2] * (max_e[J2K_Q2] - 1)); + + U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1]; + U[J2K_Q2] = kappa[J2K_Q2] + u[J2K_Q2]; + + for (int i = 0; i < 4; i++) { + m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1); + m[J2K_Q2][i] = sigma_n[4 * q2 + i] * U[J2K_Q2] - ((emb_pat_k[J2K_Q2] >> i) & 1); + } + recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + + recover_mag_sgn(mag_sgn_stream, J2K_Q2, q2, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + + q += 2; // Move to the next quad pair + } + + if (quad_width % 2 == 1) { + q1 = q; + + /* calculate context for current quad */ + context1 = sigma_n[4 * (q1 - quad_width) + 1]; + context1 += (sigma_n[4 * (q1 - quad_width) + 3] << 2); + + if (!is_divisible(q1, c)) { + context1 |= sigma_n[4 * (q1 - quad_width) - 1]; + context1 += (sigma_n[4 * q1 - 1] | sigma_n[4 * q1 - 2]) << 1; + } + if (!is_divisible(q1 + 1, c)) + context1 |= sigma_n[4 * (q1 - quad_width) + 5] << 2; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table1, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q1, context1, Lcup, + Pcup)) < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1; + + u[J2K_Q1] = 0; + + /* Recover mag_sgn value */ + if (res_off[J2K_Q1] == 1) { + u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + + u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] << 2); + } + + sp = sig_pat[J2K_Q1]; + + gamma[J2K_Q1] = 1; + + if (sp == 0 || sp == 1 || sp == 2 || sp == 4 || sp == 8) + gamma[J2K_Q1] = 0; + + E_n[J2K_Q1] = E[4 * (q1 - quad_width) + 1]; + + E_ne[J2K_Q1] = E[4 * (q1 - quad_width) + 3]; + + E_nw[J2K_Q1] = (!is_divisible(q1, c)) * E[FFMAX((4 * (q1 - quad_width) - 1), 0)]; + + E_nf[J2K_Q1] = (!is_divisible(q1 + 1, c)) * E[4 * (q1 - quad_width) + 5]; + + max_e[J2K_Q1] = FFMAX(E_nw[J2K_Q1], FFMAX3(E_n[J2K_Q1], E_ne[J2K_Q1], E_nf[J2K_Q1])); + + kappa[J2K_Q1] = FFMAX(1, gamma[J2K_Q1] * (max_e[J2K_Q1] - 1)); + + U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1]; + + for (int i = 0; i < 4; i++) + m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1); + + recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + q += 1; + } + } + + // convert to raster-scan + for (int y = 0; y < quad_height; y++) { + for (int x = 0; x < quad_width; x++) { + int j1, j2; + int x1, x2 , x3; + + j1 = 2 * y; + j2 = 2 * x; + + sample_buf[j2 + (j1 * width)] = (int32_t)*mu; + jpeg2000_modify_state(j1, j2, width, *sigma, block_states); + sigma += 1; + mu += 1; + + x1 = y != quad_height - 1 || is_border_y == 0; + sample_buf[j2 + ((j1 + 1) * width)] = ((int32_t)*mu) * x1; + jpeg2000_modify_state(j1 + 1, j2, width, (*sigma) * x1, block_states); + sigma += 1; + mu += 1; + + x2 = x != quad_width - 1 || is_border_x == 0; + sample_buf[(j2 + 1) + (j1 * width)] = ((int32_t)*mu) * x2; + jpeg2000_modify_state(j1, j2 + 1, width, (*sigma) * x2, block_states); + sigma += 1; + mu += 1; + + x3 = x1 | x2; + sample_buf[(j2 + 1) + (j1 + 1) * width] = ((int32_t)*mu) * x3; + jpeg2000_modify_state(j1 + 1, j2 + 1, width, (*sigma) * x3, block_states); + sigma += 1; + mu += 1; + } + } + ret = 1; +free: + av_freep(&sigma_n); + av_freep(&E); + av_freep(&mu_n); + return ret; +} + +static void jpeg2000_calc_mbr(uint8_t *mbr, const uint16_t i, const uint16_t j, + const uint32_t mbr_info, uint8_t causal_cond, + uint8_t *block_states, int width) +{ + int local_mbr = 0; + + local_mbr |= jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SIGMA, block_states); + local_mbr |= jpeg2000_get_state(i - 1, j + 0, width, HT_SHIFT_SIGMA, block_states); + local_mbr |= jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_SIGMA, block_states); + + local_mbr |= jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_SIGMA, block_states); + local_mbr |= jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_SIGMA, block_states); + + local_mbr |= jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_SIGMA, block_states) * causal_cond; + local_mbr |= jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_SIGMA, block_states) * causal_cond; + local_mbr |= jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_SIGMA, block_states) * causal_cond; + + local_mbr |= jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SCAN, block_states); + local_mbr |= jpeg2000_get_state(i - 1, j + 0, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SCAN, block_states); + local_mbr |= jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_SCAN, block_states); + + local_mbr |= jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_SCAN, block_states); + local_mbr |= jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_SCAN, block_states); + + local_mbr |= jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_SCAN, block_states) * causal_cond; + local_mbr |= jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_SCAN, block_states) * causal_cond; + local_mbr |= jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_SCAN, block_states) * causal_cond; + + *mbr |= local_mbr; +} + +static void jpeg2000_process_stripes_block(StateVars *sig_prop, int i_s, int j_s, + int width, int height, int stride, int pLSB, + int32_t *sample_buf, uint8_t *block_states, + uint8_t *magref_segment, uint32_t magref_length) +{ + for (int j = j_s; j < j_s + width; j++) { + uint32_t mbr_info = 0; + for (int i = i_s; i < i_s + height; i++) { + int modify_state, cond; + uint8_t bit; + uint8_t causal_cond = i != (i_s + height - 1); + int32_t *sp = &sample_buf[j + (i * (stride - 2))]; + uint8_t mbr = 0; + + if (jpeg2000_get_state(i, j, stride - 2, HT_SHIFT_SIGMA, block_states) == 0) + jpeg2000_calc_mbr(&mbr, i, j, mbr_info & 0x1EF, causal_cond, block_states, stride - 2); + mbr_info >>= 3; + cond = mbr != 0; + bit = jpeg2000_peek_bit(sig_prop, magref_segment, magref_length); + *sp |= (bit * cond) << pLSB; + sig_prop->bits -= cond; + modify_state = (((1 << HT_SHIFT_REF_IND) | (1 << HT_SHIFT_REF)) * cond) | 1 << HT_SHIFT_SCAN; + jpeg2000_modify_state(i, j, stride - 2, modify_state, block_states); + } + } +} + +/** + * See procedure decodeSigPropMag at Rec. ITU-T T.814, 7.4. +*/ +av_noinline +static void jpeg2000_decode_sigprop_segment(Jpeg2000Cblk *cblk, uint16_t width, + uint16_t height, uint8_t *magref_segment, + uint32_t magref_length, uint8_t pLSB, + int32_t *sample_buf, uint8_t *block_states) +{ + StateVars sp_dec; + + const uint16_t num_v_stripe = height / 4; + const uint16_t num_h_stripe = width / 4; + int b_width = 4; + int b_height = 4; + int stride = width + 2; + + int last_width; + uint16_t i = 0, j = 0; + + jpeg2000_init_zero(&sp_dec); + + for (int n1 = 0; n1 < num_v_stripe; n1++) { + j = 0; + for (int n2 = 0; n2 < num_h_stripe; n2++) { + jpeg2000_process_stripes_block(&sp_dec, i, j, b_width, b_height, stride, + pLSB, sample_buf, block_states, magref_segment, + magref_length); + j += 4; + } + last_width = width % 4; + if (last_width) + jpeg2000_process_stripes_block(&sp_dec, i, j, last_width, b_height, stride, + pLSB, sample_buf, block_states, magref_segment, + magref_length); + i += 4; + } + + /* Decode remaining height stripes */ + b_height = height % 4; + j = 0; + for (int n2 = 0; n2 < num_h_stripe; n2++) { + jpeg2000_process_stripes_block(&sp_dec, i, j, b_width, b_height, stride, + pLSB, sample_buf, block_states, magref_segment, + magref_length); + j += 4; + } + last_width = width % 4; + if (last_width) + jpeg2000_process_stripes_block(&sp_dec, i, j, last_width, b_height, stride, + pLSB, sample_buf, block_states, magref_segment, + magref_length); +} + +/** + * See procedure decodeSigPropMag at Rec. ITU-T T.814, 7.5. +*/ +static int +jpeg2000_decode_magref_segment(Jpeg2000Cblk *cblk, uint16_t width, uint16_t block_height, uint8_t *magref_segment, + uint32_t magref_length, uint8_t pLSB, int32_t *sample_buf, uint8_t *block_states) +{ + + StateVars mag_ref = { 0 }; + const uint16_t num_v_stripe = block_height / 4; + uint16_t height = 4; + uint16_t i_start = 0; + int32_t *sp; + + jpeg2000_init_mag_ref(&mag_ref, magref_length); + + for (int n1 = 0; n1 < num_v_stripe; n1++) { + for (int j = 0; j < width; j++) { + for (int i = i_start; i < i_start + height; i++) { + /** + * We move column wise, going from one quad to another. See + * Rec. ITU-T T.814, Figure 7. + */ + sp = &sample_buf[j + i * width]; + if (jpeg2000_get_state(i, j, width, HT_SHIFT_SIGMA, block_states) != 0) { + jpeg2000_modify_state(i, j, width, 1 << HT_SHIFT_REF_IND, block_states); + *sp |= jpeg2000_import_magref_bit(&mag_ref, magref_segment, magref_length) << pLSB; + } + } + } + i_start += 4; + } + height = block_height % 4; + for (int j = 0; j < width; j++) { + for (int i = i_start; i < i_start + height; i++) { + sp = &sample_buf[j + i * width]; + if (jpeg2000_get_state(i, j, width, HT_SHIFT_SIGMA, block_states) != 0) { + jpeg2000_modify_state(i, j, width, 1 << HT_SHIFT_REF_IND, block_states); + *sp |= jpeg2000_import_magref_bit(&mag_ref, magref_segment, magref_length) << pLSB; + } + } + } + return 1; +} + + +int +ff_jpeg2000_decode_htj2k(const Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, + int width, int height, int magp, uint8_t roi_shift) +{ + uint8_t p0 = 0; // Number of placeholder passes + uint32_t Lcup; // Length of HT cleanup segment + uint32_t Lref; // Length of Refinement segment + uint32_t Scup; // HT cleanup segment suffix length + uint32_t Pcup; // HT cleanup segment prefix length + + uint8_t S_blk; // Number of skipped magnitude bitplanes + uint8_t pLSB; + + uint8_t *Dcup; // Byte of an HT cleanup segment + uint8_t *Dref; // Byte of an HT refinement segment + + int z_blk; // Number of ht coding pass + + uint8_t empty_passes; + + StateVars mag_sgn; // Magnitude and Sign + StateVars mel; // Adaptive run-length coding + StateVars vlc; // Variable Length coding + StateVars sig_prop; // Significance propagation + + MelDecoderState mel_state; + + int ret; + + /* Temporary buffers */ + int32_t *sample_buf; + uint8_t *block_states; + + int32_t n, val; // Post-processing + + int32_t M_b = magp; + + /* codeblock size as constrained by Rec. ITU-T T.800, Table A.18 */ + av_assert0(width <= 1024U && height <= 1024U); + av_assert0(width * height <= 4096); + av_assert0(width * height > 0); + + memset(t1->data, 0, t1->stride * height * sizeof(*t1->data)); + memset(t1->flags, 0, t1->stride * (height + 2) * sizeof(*t1->flags)); + + if (cblk->npasses == 0) + return 0; + + if (cblk->npasses > 3) + p0 = 0; + else if (cblk->length == 0) + p0 = 1; + + empty_passes = p0 * 3; + z_blk = cblk->npasses - empty_passes; + + if (z_blk <= 0) + return 0; // No passes within this set, continue + + Lcup = cblk->pass_lengths[0]; + Lref = cblk->pass_lengths[1]; + + if (Lcup < 2) { + av_log(s->avctx, AV_LOG_ERROR, + "Cleanup pass length must be at least 2 bytes in length\n"); + return AVERROR_INVALIDDATA; + } + Dcup = cblk->data; + Dref = cblk->data + Lcup; // Dref comes after the refinement segment + S_blk = p0 + cblk->zbp; + pLSB = 30 - S_blk; + + Scup = (Dcup[Lcup - 1] << 4) + (Dcup[Lcup - 2] & 0x0F); + + if (Scup < 2 || Scup > Lcup || Scup > 4079) { + av_log(s->avctx, AV_LOG_ERROR, "Cleanup pass suffix length is invalid %d\n", + Scup); + ret = AVERROR_INVALIDDATA; + goto free; + } + Pcup = Lcup - Scup; + + /* modDcup shall be done before the creation of vlc instance. */ + Dcup[Lcup - 1] = 0xFF; + Dcup[Lcup - 2] |= 0x0F; + + /* Magnitude and refinement */ + jpeg2000_init_zero(&mag_sgn); + jpeg2000_bitbuf_refill_forward(&mag_sgn, Dcup, Pcup); + + /* Significance propagation */ + jpeg2000_init_zero(&sig_prop); + + /* Adaptive run length */ + jpeg2000_init_mel(&mel, Pcup); + + /* Variable Length coding */ + jpeg2000_init_vlc(&vlc, Lcup, Pcup, Dcup); + + jpeg2000_init_mel_decoder(&mel_state); + + sample_buf = av_calloc((width + 4) * (height + 4), sizeof(int32_t)); + block_states = av_calloc((width + 4) * (height + 4), sizeof(uint8_t)); + + if (!sample_buf || !block_states) { + ret = AVERROR(ENOMEM); + goto free; + } + if ((ret = jpeg2000_decode_ht_cleanup_segment(s, cblk, t1, &mel_state, &mel, &vlc, + &mag_sgn, Dcup, Lcup, Pcup, pLSB, width, + height, sample_buf, block_states)) < 0) + goto free; + + if (cblk->npasses > 1) + jpeg2000_decode_sigprop_segment(cblk, width, height, Dref, Lref, + pLSB - 1, sample_buf, block_states); + + if (cblk->npasses > 2) + if ((ret = jpeg2000_decode_magref_segment(cblk, width, height, Dref, Lref, + pLSB - 1, sample_buf, block_states)) < 0) + goto free; + + pLSB = 31 - M_b; + + /* Reconstruct the sample values */ + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + n = x + (y * t1->stride); + val = sample_buf[x + (y * width)]; + /* Convert sign-magnitude to two's complement. */ + val = val >> 31 ? 0x80000000 - val : val; + val >>= (pLSB - 1); + t1->data[n] = val; + } + } +free: + av_freep(&sample_buf); + av_freep(&block_states); + return ret; +} + +/** + * CtxVLC tables (see Rec. ITU-T T.800, Annex C) as found at + * https://github.com/osamu620/OpenHTJ2K (author: Osamu Watanabe) + */ +static const uint16_t dec_cxt_vlc_table1[1024] = { + 0x0016, 0x006A, 0x0046, 0x00DD, 0x0086, 0x888B, 0x0026, 0x444D, 0x0016, 0x00AA, 0x0046, 0x88AD, 0x0086, + 0x003A, 0x0026, 0x00DE, 0x0016, 0x00CA, 0x0046, 0x009D, 0x0086, 0x005A, 0x0026, 0x222D, 0x0016, 0x009A, + 0x0046, 0x007D, 0x0086, 0x01FD, 0x0026, 0x007E, 0x0016, 0x006A, 0x0046, 0x88CD, 0x0086, 0x888B, 0x0026, + 0x111D, 0x0016, 0x00AA, 0x0046, 0x005D, 0x0086, 0x003A, 0x0026, 0x00EE, 0x0016, 0x00CA, 0x0046, 0x00BD, + 0x0086, 0x005A, 0x0026, 0x11FF, 0x0016, 0x009A, 0x0046, 0x003D, 0x0086, 0x04ED, 0x0026, 0x2AAF, 0x0016, + 0x006A, 0x0046, 0x00DD, 0x0086, 0x888B, 0x0026, 0x444D, 0x0016, 0x00AA, 0x0046, 0x88AD, 0x0086, 0x003A, + 0x0026, 0x44EF, 0x0016, 0x00CA, 0x0046, 0x009D, 0x0086, 0x005A, 0x0026, 0x222D, 0x0016, 0x009A, 0x0046, + 0x007D, 0x0086, 0x01FD, 0x0026, 0x00BE, 0x0016, 0x006A, 0x0046, 0x88CD, 0x0086, 0x888B, 0x0026, 0x111D, + 0x0016, 0x00AA, 0x0046, 0x005D, 0x0086, 0x003A, 0x0026, 0x4CCF, 0x0016, 0x00CA, 0x0046, 0x00BD, 0x0086, + 0x005A, 0x0026, 0x00FE, 0x0016, 0x009A, 0x0046, 0x003D, 0x0086, 0x04ED, 0x0026, 0x006F, 0x0002, 0x0088, + 0x0002, 0x005C, 0x0002, 0x0018, 0x0002, 0x00DE, 0x0002, 0x0028, 0x0002, 0x009C, 0x0002, 0x004A, 0x0002, + 0x007E, 0x0002, 0x0088, 0x0002, 0x00CC, 0x0002, 0x0018, 0x0002, 0x888F, 0x0002, 0x0028, 0x0002, 0x00FE, + 0x0002, 0x003A, 0x0002, 0x222F, 0x0002, 0x0088, 0x0002, 0x04FD, 0x0002, 0x0018, 0x0002, 0x00BE, 0x0002, + 0x0028, 0x0002, 0x00BF, 0x0002, 0x004A, 0x0002, 0x006E, 0x0002, 0x0088, 0x0002, 0x00AC, 0x0002, 0x0018, + 0x0002, 0x444F, 0x0002, 0x0028, 0x0002, 0x00EE, 0x0002, 0x003A, 0x0002, 0x113F, 0x0002, 0x0088, 0x0002, + 0x005C, 0x0002, 0x0018, 0x0002, 0x00CF, 0x0002, 0x0028, 0x0002, 0x009C, 0x0002, 0x004A, 0x0002, 0x006F, + 0x0002, 0x0088, 0x0002, 0x00CC, 0x0002, 0x0018, 0x0002, 0x009F, 0x0002, 0x0028, 0x0002, 0x00EF, 0x0002, + 0x003A, 0x0002, 0x233F, 0x0002, 0x0088, 0x0002, 0x04FD, 0x0002, 0x0018, 0x0002, 0x00AF, 0x0002, 0x0028, + 0x0002, 0x44FF, 0x0002, 0x004A, 0x0002, 0x005F, 0x0002, 0x0088, 0x0002, 0x00AC, 0x0002, 0x0018, 0x0002, + 0x007F, 0x0002, 0x0028, 0x0002, 0x00DF, 0x0002, 0x003A, 0x0002, 0x111F, 0x0002, 0x0028, 0x0002, 0x005C, + 0x0002, 0x008A, 0x0002, 0x00BF, 0x0002, 0x0018, 0x0002, 0x00FE, 0x0002, 0x00CC, 0x0002, 0x007E, 0x0002, + 0x0028, 0x0002, 0x8FFF, 0x0002, 0x004A, 0x0002, 0x007F, 0x0002, 0x0018, 0x0002, 0x00DF, 0x0002, 0x00AC, + 0x0002, 0x133F, 0x0002, 0x0028, 0x0002, 0x222D, 0x0002, 0x008A, 0x0002, 0x00BE, 0x0002, 0x0018, 0x0002, + 0x44EF, 0x0002, 0x2AAD, 0x0002, 0x006E, 0x0002, 0x0028, 0x0002, 0x15FF, 0x0002, 0x004A, 0x0002, 0x009E, + 0x0002, 0x0018, 0x0002, 0x00CF, 0x0002, 0x003C, 0x0002, 0x223F, 0x0002, 0x0028, 0x0002, 0x005C, 0x0002, + 0x008A, 0x0002, 0x2BBF, 0x0002, 0x0018, 0x0002, 0x04EF, 0x0002, 0x00CC, 0x0002, 0x006F, 0x0002, 0x0028, + 0x0002, 0x27FF, 0x0002, 0x004A, 0x0002, 0x009F, 0x0002, 0x0018, 0x0002, 0x00DE, 0x0002, 0x00AC, 0x0002, + 0x444F, 0x0002, 0x0028, 0x0002, 0x222D, 0x0002, 0x008A, 0x0002, 0x8AAF, 0x0002, 0x0018, 0x0002, 0x00EE, + 0x0002, 0x2AAD, 0x0002, 0x005F, 0x0002, 0x0028, 0x0002, 0x44FF, 0x0002, 0x004A, 0x0002, 0x888F, 0x0002, + 0x0018, 0x0002, 0xAAAF, 0x0002, 0x003C, 0x0002, 0x111F, 0x0004, 0x8FFD, 0x0028, 0x005C, 0x0004, 0x00BC, + 0x008A, 0x66FF, 0x0004, 0x00CD, 0x0018, 0x111D, 0x0004, 0x009C, 0x003A, 0x8AAF, 0x0004, 0x00FC, 0x0028, + 0x133D, 0x0004, 0x00AC, 0x004A, 0x3BBF, 0x0004, 0x2BBD, 0x0018, 0x5FFF, 0x0004, 0x006C, 0x157D, 0x455F, + 0x0004, 0x2FFD, 0x0028, 0x222D, 0x0004, 0x22AD, 0x008A, 0x44EF, 0x0004, 0x00CC, 0x0018, 0x4FFF, 0x0004, + 0x007C, 0x003A, 0x447F, 0x0004, 0x04DD, 0x0028, 0x233D, 0x0004, 0x009D, 0x004A, 0x00DE, 0x0004, 0x88BD, + 0x0018, 0xAFFF, 0x0004, 0x115D, 0x1FFD, 0x444F, 0x0004, 0x8FFD, 0x0028, 0x005C, 0x0004, 0x00BC, 0x008A, + 0x8CEF, 0x0004, 0x00CD, 0x0018, 0x111D, 0x0004, 0x009C, 0x003A, 0x888F, 0x0004, 0x00FC, 0x0028, 0x133D, + 0x0004, 0x00AC, 0x004A, 0x44DF, 0x0004, 0x2BBD, 0x0018, 0x8AFF, 0x0004, 0x006C, 0x157D, 0x006F, 0x0004, + 0x2FFD, 0x0028, 0x222D, 0x0004, 0x22AD, 0x008A, 0x00EE, 0x0004, 0x00CC, 0x0018, 0x2EEF, 0x0004, 0x007C, + 0x003A, 0x277F, 0x0004, 0x04DD, 0x0028, 0x233D, 0x0004, 0x009D, 0x004A, 0x1BBF, 0x0004, 0x88BD, 0x0018, + 0x37FF, 0x0004, 0x115D, 0x1FFD, 0x333F, 0x0002, 0x0088, 0x0002, 0x02ED, 0x0002, 0x00CA, 0x0002, 0x4CCF, + 0x0002, 0x0048, 0x0002, 0x23FF, 0x0002, 0x001A, 0x0002, 0x888F, 0x0002, 0x0088, 0x0002, 0x006C, 0x0002, + 0x002A, 0x0002, 0x00AF, 0x0002, 0x0048, 0x0002, 0x22EF, 0x0002, 0x00AC, 0x0002, 0x005F, 0x0002, 0x0088, + 0x0002, 0x444D, 0x0002, 0x00CA, 0x0002, 0xCCCF, 0x0002, 0x0048, 0x0002, 0x00FE, 0x0002, 0x001A, 0x0002, + 0x006F, 0x0002, 0x0088, 0x0002, 0x005C, 0x0002, 0x002A, 0x0002, 0x009F, 0x0002, 0x0048, 0x0002, 0x00DF, + 0x0002, 0x03FD, 0x0002, 0x222F, 0x0002, 0x0088, 0x0002, 0x02ED, 0x0002, 0x00CA, 0x0002, 0x8CCF, 0x0002, + 0x0048, 0x0002, 0x11FF, 0x0002, 0x001A, 0x0002, 0x007E, 0x0002, 0x0088, 0x0002, 0x006C, 0x0002, 0x002A, + 0x0002, 0x007F, 0x0002, 0x0048, 0x0002, 0x00EE, 0x0002, 0x00AC, 0x0002, 0x003E, 0x0002, 0x0088, 0x0002, + 0x444D, 0x0002, 0x00CA, 0x0002, 0x00BE, 0x0002, 0x0048, 0x0002, 0x00BF, 0x0002, 0x001A, 0x0002, 0x003F, + 0x0002, 0x0088, 0x0002, 0x005C, 0x0002, 0x002A, 0x0002, 0x009E, 0x0002, 0x0048, 0x0002, 0x00DE, 0x0002, + 0x03FD, 0x0002, 0x111F, 0x0004, 0x8AED, 0x0048, 0x888D, 0x0004, 0x00DC, 0x00CA, 0x3FFF, 0x0004, 0xCFFD, + 0x002A, 0x003D, 0x0004, 0x00BC, 0x005A, 0x8DDF, 0x0004, 0x8FFD, 0x0048, 0x006C, 0x0004, 0x027D, 0x008A, + 0x99FF, 0x0004, 0x00EC, 0x00FA, 0x003C, 0x0004, 0x00AC, 0x001A, 0x009F, 0x0004, 0x2FFD, 0x0048, 0x007C, + 0x0004, 0x44CD, 0x00CA, 0x67FF, 0x0004, 0x1FFD, 0x002A, 0x444D, 0x0004, 0x00AD, 0x005A, 0x8CCF, 0x0004, + 0x4FFD, 0x0048, 0x445D, 0x0004, 0x01BD, 0x008A, 0x4EEF, 0x0004, 0x45DD, 0x00FA, 0x111D, 0x0004, 0x009C, + 0x001A, 0x222F, 0x0004, 0x8AED, 0x0048, 0x888D, 0x0004, 0x00DC, 0x00CA, 0xAFFF, 0x0004, 0xCFFD, 0x002A, + 0x003D, 0x0004, 0x00BC, 0x005A, 0x11BF, 0x0004, 0x8FFD, 0x0048, 0x006C, 0x0004, 0x027D, 0x008A, 0x22EF, + 0x0004, 0x00EC, 0x00FA, 0x003C, 0x0004, 0x00AC, 0x001A, 0x227F, 0x0004, 0x2FFD, 0x0048, 0x007C, 0x0004, + 0x44CD, 0x00CA, 0x5DFF, 0x0004, 0x1FFD, 0x002A, 0x444D, 0x0004, 0x00AD, 0x005A, 0x006F, 0x0004, 0x4FFD, + 0x0048, 0x445D, 0x0004, 0x01BD, 0x008A, 0x11DF, 0x0004, 0x45DD, 0x00FA, 0x111D, 0x0004, 0x009C, 0x001A, + 0x155F, 0x0006, 0x00FC, 0x0018, 0x111D, 0x0048, 0x888D, 0x00AA, 0x4DDF, 0x0006, 0x2AAD, 0x005A, 0x67FF, + 0x0028, 0x223D, 0x00BC, 0xAAAF, 0x0006, 0x00EC, 0x0018, 0x5FFF, 0x0048, 0x006C, 0x008A, 0xCCCF, 0x0006, + 0x009D, 0x00CA, 0x44EF, 0x0028, 0x003C, 0x8FFD, 0x137F, 0x0006, 0x8EED, 0x0018, 0x1FFF, 0x0048, 0x007C, + 0x00AA, 0x4CCF, 0x0006, 0x227D, 0x005A, 0x1DDF, 0x0028, 0x444D, 0x4FFD, 0x155F, 0x0006, 0x00DC, 0x0018, + 0x2EEF, 0x0048, 0x445D, 0x008A, 0x22BF, 0x0006, 0x009C, 0x00CA, 0x8CDF, 0x0028, 0x222D, 0x2FFD, 0x226F, + 0x0006, 0x00FC, 0x0018, 0x111D, 0x0048, 0x888D, 0x00AA, 0x1BBF, 0x0006, 0x2AAD, 0x005A, 0x33FF, 0x0028, + 0x223D, 0x00BC, 0x8AAF, 0x0006, 0x00EC, 0x0018, 0x9BFF, 0x0048, 0x006C, 0x008A, 0x8ABF, 0x0006, 0x009D, + 0x00CA, 0x4EEF, 0x0028, 0x003C, 0x8FFD, 0x466F, 0x0006, 0x8EED, 0x0018, 0xCFFF, 0x0048, 0x007C, 0x00AA, + 0x8CCF, 0x0006, 0x227D, 0x005A, 0xAEEF, 0x0028, 0x444D, 0x4FFD, 0x477F, 0x0006, 0x00DC, 0x0018, 0xAFFF, + 0x0048, 0x445D, 0x008A, 0x2BBF, 0x0006, 0x009C, 0x00CA, 0x44DF, 0x0028, 0x222D, 0x2FFD, 0x133F, 0x00F6, + 0xAFFD, 0x1FFB, 0x003C, 0x0008, 0x23BD, 0x007A, 0x11DF, 0x00F6, 0x45DD, 0x2FFB, 0x4EEF, 0x00DA, 0x177D, + 0xCFFD, 0x377F, 0x00F6, 0x3FFD, 0x8FFB, 0x111D, 0x0008, 0x009C, 0x005A, 0x1BBF, 0x00F6, 0x00CD, 0x00BA, + 0x8DDF, 0x4FFB, 0x006C, 0x9BFD, 0x455F, 0x00F6, 0x67FD, 0x1FFB, 0x002C, 0x0008, 0x00AC, 0x007A, 0x009F, + 0x00F6, 0x00AD, 0x2FFB, 0x7FFF, 0x00DA, 0x004C, 0x5FFD, 0x477F, 0x00F6, 0x00EC, 0x8FFB, 0x001C, 0x0008, + 0x008C, 0x005A, 0x888F, 0x00F6, 0x00CC, 0x00BA, 0x2EEF, 0x4FFB, 0x115D, 0x8AED, 0x113F, 0x00F6, 0xAFFD, + 0x1FFB, 0x003C, 0x0008, 0x23BD, 0x007A, 0x1DDF, 0x00F6, 0x45DD, 0x2FFB, 0xBFFF, 0x00DA, 0x177D, 0xCFFD, + 0x447F, 0x00F6, 0x3FFD, 0x8FFB, 0x111D, 0x0008, 0x009C, 0x005A, 0x277F, 0x00F6, 0x00CD, 0x00BA, 0x22EF, + 0x4FFB, 0x006C, 0x9BFD, 0x444F, 0x00F6, 0x67FD, 0x1FFB, 0x002C, 0x0008, 0x00AC, 0x007A, 0x11BF, 0x00F6, + 0x00AD, 0x2FFB, 0xFFFF, 0x00DA, 0x004C, 0x5FFD, 0x233F, 0x00F6, 0x00EC, 0x8FFB, 0x001C, 0x0008, 0x008C, + 0x005A, 0x006F, 0x00F6, 0x00CC, 0x00BA, 0x8BBF, 0x4FFB, 0x115D, 0x8AED, 0x222F}; + +static const uint16_t dec_cxt_vlc_table0[1024] = { + 0x0026, 0x00AA, 0x0046, 0x006C, 0x0086, 0x8AED, 0x0018, 0x8DDF, 0x0026, 0x01BD, 0x0046, 0x5FFF, 0x0086, + 0x027D, 0x005A, 0x155F, 0x0026, 0x003A, 0x0046, 0x444D, 0x0086, 0x4CCD, 0x0018, 0xCCCF, 0x0026, 0x2EFD, + 0x0046, 0x99FF, 0x0086, 0x009C, 0x00CA, 0x133F, 0x0026, 0x00AA, 0x0046, 0x445D, 0x0086, 0x8CCD, 0x0018, + 0x11DF, 0x0026, 0x4FFD, 0x0046, 0xCFFF, 0x0086, 0x009D, 0x005A, 0x007E, 0x0026, 0x003A, 0x0046, 0x1FFF, + 0x0086, 0x88AD, 0x0018, 0x00BE, 0x0026, 0x8FFD, 0x0046, 0x4EEF, 0x0086, 0x888D, 0x00CA, 0x111F, 0x0026, + 0x00AA, 0x0046, 0x006C, 0x0086, 0x8AED, 0x0018, 0x45DF, 0x0026, 0x01BD, 0x0046, 0x22EF, 0x0086, 0x027D, + 0x005A, 0x227F, 0x0026, 0x003A, 0x0046, 0x444D, 0x0086, 0x4CCD, 0x0018, 0x11BF, 0x0026, 0x2EFD, 0x0046, + 0x00FE, 0x0086, 0x009C, 0x00CA, 0x223F, 0x0026, 0x00AA, 0x0046, 0x445D, 0x0086, 0x8CCD, 0x0018, 0x00DE, + 0x0026, 0x4FFD, 0x0046, 0xABFF, 0x0086, 0x009D, 0x005A, 0x006F, 0x0026, 0x003A, 0x0046, 0x6EFF, 0x0086, + 0x88AD, 0x0018, 0x2AAF, 0x0026, 0x8FFD, 0x0046, 0x00EE, 0x0086, 0x888D, 0x00CA, 0x222F, 0x0004, 0x00CA, + 0x0088, 0x027D, 0x0004, 0x4CCD, 0x0028, 0x00FE, 0x0004, 0x2AFD, 0x0048, 0x005C, 0x0004, 0x009D, 0x0018, + 0x00DE, 0x0004, 0x01BD, 0x0088, 0x006C, 0x0004, 0x88AD, 0x0028, 0x11DF, 0x0004, 0x8AED, 0x0048, 0x003C, + 0x0004, 0x888D, 0x0018, 0x111F, 0x0004, 0x00CA, 0x0088, 0x006D, 0x0004, 0x88CD, 0x0028, 0x88FF, 0x0004, + 0x8BFD, 0x0048, 0x444D, 0x0004, 0x009C, 0x0018, 0x00BE, 0x0004, 0x4EFD, 0x0088, 0x445D, 0x0004, 0x00AC, + 0x0028, 0x00EE, 0x0004, 0x45DD, 0x0048, 0x222D, 0x0004, 0x003D, 0x0018, 0x007E, 0x0004, 0x00CA, 0x0088, + 0x027D, 0x0004, 0x4CCD, 0x0028, 0x1FFF, 0x0004, 0x2AFD, 0x0048, 0x005C, 0x0004, 0x009D, 0x0018, 0x11BF, + 0x0004, 0x01BD, 0x0088, 0x006C, 0x0004, 0x88AD, 0x0028, 0x22EF, 0x0004, 0x8AED, 0x0048, 0x003C, 0x0004, + 0x888D, 0x0018, 0x227F, 0x0004, 0x00CA, 0x0088, 0x006D, 0x0004, 0x88CD, 0x0028, 0x4EEF, 0x0004, 0x8BFD, + 0x0048, 0x444D, 0x0004, 0x009C, 0x0018, 0x2AAF, 0x0004, 0x4EFD, 0x0088, 0x445D, 0x0004, 0x00AC, 0x0028, + 0x8DDF, 0x0004, 0x45DD, 0x0048, 0x222D, 0x0004, 0x003D, 0x0018, 0x155F, 0x0004, 0x005A, 0x0088, 0x006C, + 0x0004, 0x88DD, 0x0028, 0x23FF, 0x0004, 0x11FD, 0x0048, 0x444D, 0x0004, 0x00AD, 0x0018, 0x00BE, 0x0004, + 0x137D, 0x0088, 0x155D, 0x0004, 0x00CC, 0x0028, 0x00DE, 0x0004, 0x02ED, 0x0048, 0x111D, 0x0004, 0x009D, + 0x0018, 0x007E, 0x0004, 0x005A, 0x0088, 0x455D, 0x0004, 0x44CD, 0x0028, 0x00EE, 0x0004, 0x1FFD, 0x0048, + 0x003C, 0x0004, 0x00AC, 0x0018, 0x555F, 0x0004, 0x47FD, 0x0088, 0x113D, 0x0004, 0x02BD, 0x0028, 0x477F, + 0x0004, 0x4CDD, 0x0048, 0x8FFF, 0x0004, 0x009C, 0x0018, 0x222F, 0x0004, 0x005A, 0x0088, 0x006C, 0x0004, + 0x88DD, 0x0028, 0x00FE, 0x0004, 0x11FD, 0x0048, 0x444D, 0x0004, 0x00AD, 0x0018, 0x888F, 0x0004, 0x137D, + 0x0088, 0x155D, 0x0004, 0x00CC, 0x0028, 0x8CCF, 0x0004, 0x02ED, 0x0048, 0x111D, 0x0004, 0x009D, 0x0018, + 0x006F, 0x0004, 0x005A, 0x0088, 0x455D, 0x0004, 0x44CD, 0x0028, 0x1DDF, 0x0004, 0x1FFD, 0x0048, 0x003C, + 0x0004, 0x00AC, 0x0018, 0x227F, 0x0004, 0x47FD, 0x0088, 0x113D, 0x0004, 0x02BD, 0x0028, 0x22BF, 0x0004, + 0x4CDD, 0x0048, 0x22EF, 0x0004, 0x009C, 0x0018, 0x233F, 0x0006, 0x4DDD, 0x4FFB, 0xCFFF, 0x0018, 0x113D, + 0x005A, 0x888F, 0x0006, 0x23BD, 0x008A, 0x00EE, 0x002A, 0x155D, 0xAAFD, 0x277F, 0x0006, 0x44CD, 0x8FFB, + 0x44EF, 0x0018, 0x467D, 0x004A, 0x2AAF, 0x0006, 0x00AC, 0x555B, 0x99DF, 0x1FFB, 0x003C, 0x5FFD, 0x266F, + 0x0006, 0x1DDD, 0x4FFB, 0x6EFF, 0x0018, 0x177D, 0x005A, 0x1BBF, 0x0006, 0x88AD, 0x008A, 0x5DDF, 0x002A, + 0x444D, 0x2FFD, 0x667F, 0x0006, 0x00CC, 0x8FFB, 0x2EEF, 0x0018, 0x455D, 0x004A, 0x119F, 0x0006, 0x009C, + 0x555B, 0x8CCF, 0x1FFB, 0x111D, 0x8CED, 0x006E, 0x0006, 0x4DDD, 0x4FFB, 0x3FFF, 0x0018, 0x113D, 0x005A, + 0x11BF, 0x0006, 0x23BD, 0x008A, 0x8DDF, 0x002A, 0x155D, 0xAAFD, 0x222F, 0x0006, 0x44CD, 0x8FFB, 0x00FE, + 0x0018, 0x467D, 0x004A, 0x899F, 0x0006, 0x00AC, 0x555B, 0x00DE, 0x1FFB, 0x003C, 0x5FFD, 0x446F, 0x0006, + 0x1DDD, 0x4FFB, 0x9BFF, 0x0018, 0x177D, 0x005A, 0x00BE, 0x0006, 0x88AD, 0x008A, 0xCDDF, 0x002A, 0x444D, + 0x2FFD, 0x007E, 0x0006, 0x00CC, 0x8FFB, 0x4EEF, 0x0018, 0x455D, 0x004A, 0x377F, 0x0006, 0x009C, 0x555B, + 0x8BBF, 0x1FFB, 0x111D, 0x8CED, 0x233F, 0x0004, 0x00AA, 0x0088, 0x047D, 0x0004, 0x01DD, 0x0028, 0x11DF, + 0x0004, 0x27FD, 0x0048, 0x005C, 0x0004, 0x8AAD, 0x0018, 0x2BBF, 0x0004, 0x009C, 0x0088, 0x006C, 0x0004, + 0x00CC, 0x0028, 0x00EE, 0x0004, 0x8CED, 0x0048, 0x222D, 0x0004, 0x888D, 0x0018, 0x007E, 0x0004, 0x00AA, + 0x0088, 0x006D, 0x0004, 0x88CD, 0x0028, 0x00FE, 0x0004, 0x19FD, 0x0048, 0x003C, 0x0004, 0x2AAD, 0x0018, + 0xAAAF, 0x0004, 0x8BFD, 0x0088, 0x005D, 0x0004, 0x00BD, 0x0028, 0x4CCF, 0x0004, 0x44ED, 0x0048, 0x4FFF, + 0x0004, 0x223D, 0x0018, 0x111F, 0x0004, 0x00AA, 0x0088, 0x047D, 0x0004, 0x01DD, 0x0028, 0x99FF, 0x0004, + 0x27FD, 0x0048, 0x005C, 0x0004, 0x8AAD, 0x0018, 0x00BE, 0x0004, 0x009C, 0x0088, 0x006C, 0x0004, 0x00CC, + 0x0028, 0x00DE, 0x0004, 0x8CED, 0x0048, 0x222D, 0x0004, 0x888D, 0x0018, 0x444F, 0x0004, 0x00AA, 0x0088, + 0x006D, 0x0004, 0x88CD, 0x0028, 0x2EEF, 0x0004, 0x19FD, 0x0048, 0x003C, 0x0004, 0x2AAD, 0x0018, 0x447F, + 0x0004, 0x8BFD, 0x0088, 0x005D, 0x0004, 0x00BD, 0x0028, 0x009F, 0x0004, 0x44ED, 0x0048, 0x67FF, 0x0004, + 0x223D, 0x0018, 0x133F, 0x0006, 0x00CC, 0x008A, 0x9DFF, 0x2FFB, 0x467D, 0x1FFD, 0x99BF, 0x0006, 0x2AAD, + 0x002A, 0x66EF, 0x4FFB, 0x005C, 0x2EED, 0x377F, 0x0006, 0x89BD, 0x004A, 0x00FE, 0x8FFB, 0x006C, 0x67FD, + 0x889F, 0x0006, 0x888D, 0x001A, 0x5DDF, 0x00AA, 0x222D, 0x89DD, 0x444F, 0x0006, 0x2BBD, 0x008A, 0xCFFF, + 0x2FFB, 0x226D, 0x009C, 0x00BE, 0x0006, 0xAAAD, 0x002A, 0x1DDF, 0x4FFB, 0x003C, 0x4DDD, 0x466F, 0x0006, + 0x8AAD, 0x004A, 0xAEEF, 0x8FFB, 0x445D, 0x8EED, 0x177F, 0x0006, 0x233D, 0x001A, 0x4CCF, 0x00AA, 0xAFFF, + 0x88CD, 0x133F, 0x0006, 0x00CC, 0x008A, 0x77FF, 0x2FFB, 0x467D, 0x1FFD, 0x3BBF, 0x0006, 0x2AAD, 0x002A, + 0x00EE, 0x4FFB, 0x005C, 0x2EED, 0x007E, 0x0006, 0x89BD, 0x004A, 0x4EEF, 0x8FFB, 0x006C, 0x67FD, 0x667F, + 0x0006, 0x888D, 0x001A, 0x00DE, 0x00AA, 0x222D, 0x89DD, 0x333F, 0x0006, 0x2BBD, 0x008A, 0x57FF, 0x2FFB, + 0x226D, 0x009C, 0x199F, 0x0006, 0xAAAD, 0x002A, 0x99DF, 0x4FFB, 0x003C, 0x4DDD, 0x155F, 0x0006, 0x8AAD, + 0x004A, 0xCEEF, 0x8FFB, 0x445D, 0x8EED, 0x277F, 0x0006, 0x233D, 0x001A, 0x1BBF, 0x00AA, 0x3FFF, 0x88CD, + 0x111F, 0x0006, 0x45DD, 0x2FFB, 0x111D, 0x0018, 0x467D, 0x8FFD, 0xCCCF, 0x0006, 0x19BD, 0x004A, 0x22EF, + 0x002A, 0x222D, 0x3FFD, 0x888F, 0x0006, 0x00CC, 0x008A, 0x00FE, 0x0018, 0x115D, 0xCFFD, 0x8AAF, 0x0006, + 0x00AC, 0x003A, 0x8CDF, 0x1FFB, 0x133D, 0x66FD, 0x466F, 0x0006, 0x8CCD, 0x2FFB, 0x5FFF, 0x0018, 0x006C, + 0x4FFD, 0xABBF, 0x0006, 0x22AD, 0x004A, 0x00EE, 0x002A, 0x233D, 0xAEFD, 0x377F, 0x0006, 0x2BBD, 0x008A, + 0x55DF, 0x0018, 0x005C, 0x177D, 0x119F, 0x0006, 0x009C, 0x003A, 0x4CCF, 0x1FFB, 0x333D, 0x8EED, 0x444F, + 0x0006, 0x45DD, 0x2FFB, 0x111D, 0x0018, 0x467D, 0x8FFD, 0x99BF, 0x0006, 0x19BD, 0x004A, 0x2EEF, 0x002A, + 0x222D, 0x3FFD, 0x667F, 0x0006, 0x00CC, 0x008A, 0x4EEF, 0x0018, 0x115D, 0xCFFD, 0x899F, 0x0006, 0x00AC, + 0x003A, 0x00DE, 0x1FFB, 0x133D, 0x66FD, 0x226F, 0x0006, 0x8CCD, 0x2FFB, 0x9BFF, 0x0018, 0x006C, 0x4FFD, + 0x00BE, 0x0006, 0x22AD, 0x004A, 0x1DDF, 0x002A, 0x233D, 0xAEFD, 0x007E, 0x0006, 0x2BBD, 0x008A, 0xCEEF, + 0x0018, 0x005C, 0x177D, 0x277F, 0x0006, 0x009C, 0x003A, 0x8BBF, 0x1FFB, 0x333D, 0x8EED, 0x455F, 0x1FF9, + 0x1DDD, 0xAFFB, 0x00DE, 0x8FF9, 0x001C, 0xFFFB, 0x477F, 0x4FF9, 0x177D, 0x3FFB, 0x3BBF, 0x2FF9, 0xAEEF, + 0x8EED, 0x444F, 0x1FF9, 0x22AD, 0x000A, 0x8BBF, 0x8FF9, 0x00FE, 0xCFFD, 0x007E, 0x4FF9, 0x115D, 0x5FFB, + 0x577F, 0x2FF9, 0x8DDF, 0x2EED, 0x333F, 0x1FF9, 0x2BBD, 0xAFFB, 0x88CF, 0x8FF9, 0xBFFF, 0xFFFB, 0x377F, + 0x4FF9, 0x006D, 0x3FFB, 0x00BE, 0x2FF9, 0x66EF, 0x9FFD, 0x133F, 0x1FF9, 0x009D, 0x000A, 0xABBF, 0x8FF9, + 0xDFFF, 0x6FFD, 0x006E, 0x4FF9, 0x002C, 0x5FFB, 0x888F, 0x2FF9, 0xCDDF, 0x4DDD, 0x222F, 0x1FF9, 0x1DDD, + 0xAFFB, 0x4CCF, 0x8FF9, 0x001C, 0xFFFB, 0x277F, 0x4FF9, 0x177D, 0x3FFB, 0x99BF, 0x2FF9, 0xCEEF, 0x8EED, + 0x004E, 0x1FF9, 0x22AD, 0x000A, 0x00AE, 0x8FF9, 0x7FFF, 0xCFFD, 0x005E, 0x4FF9, 0x115D, 0x5FFB, 0x009E, + 0x2FF9, 0x5DDF, 0x2EED, 0x003E, 0x1FF9, 0x2BBD, 0xAFFB, 0x00CE, 0x8FF9, 0xEFFF, 0xFFFB, 0x667F, 0x4FF9, + 0x006D, 0x3FFB, 0x8AAF, 0x2FF9, 0x00EE, 0x9FFD, 0x233F, 0x1FF9, 0x009D, 0x000A, 0x1BBF, 0x8FF9, 0x4EEF, + 0x6FFD, 0x455F, 0x4FF9, 0x002C, 0x5FFB, 0x008E, 0x2FF9, 0x99DF, 0x4DDD, 0x111F}; diff --git a/libavcodec/jpeg2000htdec.h b/libavcodec/jpeg2000htdec.h new file mode 100644 index 0000000000..572d095c92 --- /dev/null +++ b/libavcodec/jpeg2000htdec.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 Caleb Etemesi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_JPEG2000HTDEC_H +#define AVCODEC_JPEG2000HTDEC_H + +#include "jpeg2000dec.h" + +/** + * HT Block decoder as specified in Rec. ITU-T T.814 | ISO/IEC 15444-15 + */ + +int ff_jpeg2000_decode_htj2k(const Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, + Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, int width, + int height, int magp, uint8_t roi_shift); + +#endif /* AVCODEC_JPEG2000HTDEC_H */ From patchwork Tue Apr 11 18:28:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre-Anthony Lemieux X-Patchwork-Id: 41086 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4645:b0:e3:3194:9d20 with SMTP id eb5csp3094723pzb; Tue, 11 Apr 2023 11:29:01 -0700 (PDT) X-Google-Smtp-Source: AKy350ZlGNApxU4YmQkfCEKrxQYDtKJHJamORoNWiFyXZNOLK2pMHnOfbtr+qT5f1u0MW7PRX+4V X-Received: by 2002:a05:6402:384:b0:504:8b96:4ece with SMTP id o4-20020a056402038400b005048b964ecemr3079663edv.9.1681237741324; Tue, 11 Apr 2023 11:29:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681237741; cv=none; d=google.com; s=arc-20160816; b=PJnk+mWr7Kbx4K3w2+vVm2i6haySHVa7mTDUqgB/qlPLTu5ItZfxcZ4iak7W89WBgt 3/nyk1+MTNZie9B0rpbovYKJadRmmCM9CzG0vJIwQIGh813XnfOBbfI+ACfxvgkUXjD0 KZENDoXnLUhxIwQNr38bLSbJTTAZD598vYDk/VvaLW8xDS5PG+yTdj5+Mx2D4cnVPcel XDqXteMz0jH7TwWTt9cJschjGEJlo34NCmuar2/cdDhu2YfsHf83If6NVw2tI3jMmv6j 7ZoEclKytMbpV1ywfkiVZ9fxZKzviH1FdZYXhUYP+qyi9zpwhj42EJQZGkNQDaziarfb e5aA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=M+b3XKhb/fDm0STCVR3E0YKv6eIeMc0tZ5n1dkjt15M=; b=QK7MQdh0RZJOWy49iBDW2kyBkU/gLFOkDpQwBsWAg/dbbd01a2ngnpxns7tMcRCIwP /PpSuD/L9p94U8fSiQe35lOBFmLUq/2iBgeSras6unkwiGNVrajsr+qJZHFBBPgQZmu1 liZhBd6bioFDrR5Xob2L12lW6w+/TFxs0rPTnjil6KBE4ZLLy8/4vcPEN/14dtpULe/3 d6RkztuO3nYfAyMKTIlf+n3NzFmbXTw7WihKwd4Wicr8m0vuO1yk7q2hSZvhRLdph8zQ h450+VUeY02km2dEJnGKGkmMPVw0LmDIhzvyPrbFCM0eDCNCNERJbsArJDisl2Jn0vjQ uyRQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id c25-20020aa7d619000000b00504b2a6ace0si3509489edr.335.2023.04.11.11.28.59; Tue, 11 Apr 2023 11:29:01 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7D41D68ADF2; Tue, 11 Apr 2023 21:28:43 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pl1-f173.google.com (mail-pl1-f173.google.com [209.85.214.173]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 42F5668ABCF for ; Tue, 11 Apr 2023 21:28:37 +0300 (EEST) Received: by mail-pl1-f173.google.com with SMTP id ke16so8645965plb.6 for ; Tue, 11 Apr 2023 11:28:37 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681237715; x=1683829715; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8czkE28+Kzdg3Sla40vE8yFGU7IDXTkw+KIMLsehw/M=; b=Cs3EHNoaJ2n0KNIgJpEH6pHSUdwzeTRTrhGcKfTDIlzDCIwV003qGcsMJENgC/hAdX B08Ictq1b+nZThlYQVUcj3JlPi5XXxjlFhcJPATVOU5upIIu66a3FqEK0ufllgJtVsw2 /eEH0ZeXMsTnGbnaVHd6gZfwmE1QoQ9T8uMAA+B/HcIGZ2IHnf+r0GOhNymNn4n0PGyH c3eDbhQ9BQ7yGzeDf7WR7RnSDhJxDCBVfBter+awU8NRhUWUgfgg3/V9IWFhPf3myiff suUuOyQ2vGubp0/lPnFLs8eb0epekRDbbOEQld0ndTflLvD0nZAHFOm6ctnOEslbZF+O CEZg== X-Gm-Message-State: AAQBX9f5vxp8thzBb+hU2gb3z2UuOeVFEx674Wyjt0hrT+PoRg1sIaWq 163gJW+uunAj6ypR3WjUms1yk7i+AjU= X-Received: by 2002:a17:903:42cd:b0:1a5:898:37aa with SMTP id jy13-20020a17090342cd00b001a5089837aamr13741929plb.15.1681237714659; Tue, 11 Apr 2023 11:28:34 -0700 (PDT) Received: from localhost (76-14-89-2.sf-cable.astound.net. [76.14.89.2]) by smtp.gmail.com with ESMTPSA id jc22-20020a17090325d600b0019aa6bf4450sm53613plb.188.2023.04.11.11.28.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Apr 2023 11:28:34 -0700 (PDT) Received: by localhost (sSMTP sendmail emulation); Tue, 11 Apr 2023 11:28:30 -0700 From: pal@sandflow.com To: ffmpeg-devel@ffmpeg.org Date: Tue, 11 Apr 2023 11:28:22 -0700 Message-Id: <20230411182822.28859-3-pal@sandflow.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230411182822.28859-1-pal@sandflow.com> References: <20230411182822.28859-1-pal@sandflow.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 3/3] fate/jpeg2000: add JPEG 2000 tests using ITU/ISO conformance materials X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Pierre-Anthony Lemieux Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: OqMWu3FUaV2i From: Pierre-Anthony Lemieux Adds JPEG 2000 decoder tests using materials from the conformance suite specified in Rec. ITU-T T.803 | ISO/IEC 15444-4. The test materials are available at https://gitlab.com/wg1/htj2k-codestreams --- tests/Makefile | 1 + tests/fate/jpeg2000.mak | 64 ++++++++++++++++++++++++ tests/ref/fate/jpeg2000dec-ds0_ht_01_b11 | 6 +++ tests/ref/fate/jpeg2000dec-p0_01 | 6 +++ tests/ref/fate/jpeg2000dec-p0_02 | 6 +++ tests/ref/fate/jpeg2000dec-p0_03 | 6 +++ tests/ref/fate/jpeg2000dec-p0_04 | 6 +++ tests/ref/fate/jpeg2000dec-p0_05 | 6 +++ tests/ref/fate/jpeg2000dec-p0_07 | 6 +++ tests/ref/fate/jpeg2000dec-p0_08 | 6 +++ tests/ref/fate/jpeg2000dec-p0_09 | 6 +++ tests/ref/fate/jpeg2000dec-p0_11 | 6 +++ tests/ref/fate/jpeg2000dec-p0_12 | 6 +++ tests/ref/fate/jpeg2000dec-p0_14 | 6 +++ tests/ref/fate/jpeg2000dec-p0_15 | 6 +++ tests/ref/fate/jpeg2000dec-p0_16 | 6 +++ 16 files changed, 149 insertions(+) create mode 100644 tests/fate/jpeg2000.mak create mode 100644 tests/ref/fate/jpeg2000dec-ds0_ht_01_b11 create mode 100644 tests/ref/fate/jpeg2000dec-p0_01 create mode 100644 tests/ref/fate/jpeg2000dec-p0_02 create mode 100644 tests/ref/fate/jpeg2000dec-p0_03 create mode 100644 tests/ref/fate/jpeg2000dec-p0_04 create mode 100644 tests/ref/fate/jpeg2000dec-p0_05 create mode 100644 tests/ref/fate/jpeg2000dec-p0_07 create mode 100644 tests/ref/fate/jpeg2000dec-p0_08 create mode 100644 tests/ref/fate/jpeg2000dec-p0_09 create mode 100644 tests/ref/fate/jpeg2000dec-p0_11 create mode 100644 tests/ref/fate/jpeg2000dec-p0_12 create mode 100644 tests/ref/fate/jpeg2000dec-p0_14 create mode 100644 tests/ref/fate/jpeg2000dec-p0_15 create mode 100644 tests/ref/fate/jpeg2000dec-p0_16 diff --git a/tests/Makefile b/tests/Makefile index 1d50e1d175..d80065a9bf 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -200,6 +200,7 @@ include $(SRC_PATH)/tests/fate/id3v2.mak include $(SRC_PATH)/tests/fate/image.mak include $(SRC_PATH)/tests/fate/imf.mak include $(SRC_PATH)/tests/fate/indeo.mak +include $(SRC_PATH)/tests/fate/jpeg2000.mak include $(SRC_PATH)/tests/fate/libavcodec.mak include $(SRC_PATH)/tests/fate/libavdevice.mak include $(SRC_PATH)/tests/fate/libavformat.mak diff --git a/tests/fate/jpeg2000.mak b/tests/fate/jpeg2000.mak new file mode 100644 index 0000000000..b72908f710 --- /dev/null +++ b/tests/fate/jpeg2000.mak @@ -0,0 +1,64 @@ +# The following tests are based on the conformance suite specified in +# Rec. ITU-T T.803 | ISO/IEC 15444-4 available at the following URLs: +# * https://gitlab.com/wg1/htj2k-codestreams +# * https://www.itu.int/rec/T-REC-T.803/en +# * https://www.iso.org/standard/81574.html +# +# Notes: +# * p0_06.j2k is not included because it uses a pixel format that is not +# supported (4:2:2:1) +# * p0_10.j2k is not included because errors are emitted during decoding and +# there are significant deviations from the reference image in the bottom-left +# quadrant +# * p0_13.j2k is not included because it uses a pixel format that is not +# supported (257 color channels) +# * p0_04.j2k and p0_05.j2k exceed the error thresholds specified in the +# conformance suite +# * p0_09.j2k matches the reference image exactly when bitexact is not used, but +# exceed the error thresholds specified in the conformance suite when bitexact +# is used + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_01 +fate-jpeg2000dec-p0_01: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_01.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_02 +fate-jpeg2000dec-p0_02: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_02.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_03 +fate-jpeg2000dec-p0_03: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_03.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_04 +fate-jpeg2000dec-p0_04: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_04.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_05 +fate-jpeg2000dec-p0_05: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_05.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_07 +fate-jpeg2000dec-p0_07: CMD = framecrc -flags +bitexact -auto_conversion_filters -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_07.j2k -pix_fmt rgb48le + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_08 +fate-jpeg2000dec-p0_08: CMD = framecrc -flags +bitexact -auto_conversion_filters -lowres 1 -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_08.j2k -pix_fmt rgb48le + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_09 +fate-jpeg2000dec-p0_09: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_09.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_11 +fate-jpeg2000dec-p0_11: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_11.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_12 +fate-jpeg2000dec-p0_12: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_12.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_14 +fate-jpeg2000dec-p0_14: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_14.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_15 +fate-jpeg2000dec-p0_15: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_15.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_16 +fate-jpeg2000dec-p0_16: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_16.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-ds0_ht_01_b11 +fate-jpeg2000dec-ds0_ht_01_b11: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/htj2k_bsets_profile0/ds0_ht_01_b11.j2k + +FATE_SAMPLES_FFMPEG += $(FATE_JPEG2000DEC) +fate-jpeg2000dec: $(FATE_JPEG2000DEC) diff --git a/tests/ref/fate/jpeg2000dec-ds0_ht_01_b11 b/tests/ref/fate/jpeg2000dec-ds0_ht_01_b11 new file mode 100644 index 0000000000..af3eaa086d --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-ds0_ht_01_b11 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x128 +#sar 0: 0/1 +0, 0, 0, 1, 16384, 0x44426324 diff --git a/tests/ref/fate/jpeg2000dec-p0_01 b/tests/ref/fate/jpeg2000dec-p0_01 new file mode 100644 index 0000000000..d923cc2109 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_01 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x128 +#sar 0: 0/1 +0, 0, 0, 1, 16384, 0x04a3647e diff --git a/tests/ref/fate/jpeg2000dec-p0_02 b/tests/ref/fate/jpeg2000dec-p0_02 new file mode 100644 index 0000000000..f96d24c121 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_02 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x126 +#sar 0: 0/1 +0, 0, 0, 1, 8064, 0xd634c70c diff --git a/tests/ref/fate/jpeg2000dec-p0_03 b/tests/ref/fate/jpeg2000dec-p0_03 new file mode 100644 index 0000000000..e508fb61e0 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_03 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 256x256 +#sar 0: 0/1 +0, 0, 0, 1, 65536, 0x252408c0 diff --git a/tests/ref/fate/jpeg2000dec-p0_04 b/tests/ref/fate/jpeg2000dec-p0_04 new file mode 100644 index 0000000000..5de7880c44 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_04 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 640x480 +#sar 0: 0/1 +0, 0, 0, 1, 921600, 0x097d9665 diff --git a/tests/ref/fate/jpeg2000dec-p0_05 b/tests/ref/fate/jpeg2000dec-p0_05 new file mode 100644 index 0000000000..bb215043a1 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_05 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 1024x1024 +#sar 0: 0/1 +0, 0, 0, 1, 2621440, 0x081f5048 diff --git a/tests/ref/fate/jpeg2000dec-p0_07 b/tests/ref/fate/jpeg2000dec-p0_07 new file mode 100644 index 0000000000..e561a1b780 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_07 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 2048x2048 +#sar 0: 0/1 +0, 0, 0, 1, 25165824, 0x9685aad6 diff --git a/tests/ref/fate/jpeg2000dec-p0_08 b/tests/ref/fate/jpeg2000dec-p0_08 new file mode 100644 index 0000000000..5e202b741b --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_08 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 257x1536 +#sar 0: 0/1 +0, 0, 0, 1, 2368512, 0xece49ff9 diff --git a/tests/ref/fate/jpeg2000dec-p0_09 b/tests/ref/fate/jpeg2000dec-p0_09 new file mode 100644 index 0000000000..1755e7cc7d --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_09 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 17x37 +#sar 0: 0/1 +0, 0, 0, 1, 629, 0x5c9c389d diff --git a/tests/ref/fate/jpeg2000dec-p0_11 b/tests/ref/fate/jpeg2000dec-p0_11 new file mode 100644 index 0000000000..9b15604361 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_11 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x1 +#sar 0: 0/1 +0, 0, 0, 1, 128, 0xae9630db diff --git a/tests/ref/fate/jpeg2000dec-p0_12 b/tests/ref/fate/jpeg2000dec-p0_12 new file mode 100644 index 0000000000..435c124c99 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_12 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 3x5 +#sar 0: 0/1 +0, 0, 0, 1, 15, 0x2a170596 diff --git a/tests/ref/fate/jpeg2000dec-p0_14 b/tests/ref/fate/jpeg2000dec-p0_14 new file mode 100644 index 0000000000..5d28e611a0 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_14 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 49x49 +#sar 0: 0/1 +0, 0, 0, 1, 7203, 0x61d40b41 diff --git a/tests/ref/fate/jpeg2000dec-p0_15 b/tests/ref/fate/jpeg2000dec-p0_15 new file mode 100644 index 0000000000..e508fb61e0 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_15 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 256x256 +#sar 0: 0/1 +0, 0, 0, 1, 65536, 0x252408c0 diff --git a/tests/ref/fate/jpeg2000dec-p0_16 b/tests/ref/fate/jpeg2000dec-p0_16 new file mode 100644 index 0000000000..d923cc2109 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_16 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x128 +#sar 0: 0/1 +0, 0, 0, 1, 16384, 0x04a3647e