avcodec/jpeg2000dec: add support for HTJ2K block decoding

Signed-off-by: Pierre-Anthony Lemieux <pal@palemieux.com>
This commit is contained in:
caleb 2023-04-14 12:14:42 -07:00 committed by Pierre-Anthony Lemieux
parent 4a466aab30
commit b9c42cdf8d
No known key found for this signature in database
GPG Key ID: 698FA1F0F8D4EED4
5 changed files with 1539 additions and 19 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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
@ -440,13 +441,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");
} 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");
}
}
c->transform = bytestream2_get_byteu(&s->g); // DWT transformation type
/* set integer 9/7 DWT in case of BITEXACT flag */
if ((s->avctx->flags & AV_CODEC_FLAG_BITEXACT) && (c->transform == FF_DWT97))
@ -1070,13 +1071,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)
@ -1117,8 +1120,23 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
}
}
if (newpasses > 1 && (codsty->cblk_style & JPEG2000_CTSY_HTJ2K_F)) {
// 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);
@ -1869,7 +1887,10 @@ static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile
for (compno = 0; compno < s->ncomponents; 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<<codsty->log2_cblk_width) + 2;
@ -1877,7 +1898,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;
@ -1897,12 +1918,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,
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

1451
libavcodec/jpeg2000htdec.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2022 Caleb Etemesi <etemesicaleb@gmail.com>
*
* 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 */