Discussion:
[libav-devel] [PATCH 00/79] Collection of jpeg2000 corrections and impovemnts fromm ffmpeg
Nicolas Bertrand
2013-06-21 13:26:40 UTC
Permalink
"Some" enhancements and bug correction for jpeg2000 decoder
As not tested, I deactivated the jpeg2000 encoder

The fate-jpeg2000-dcinema test remains path ( ouf!)

Michael Niedermayer (76):
jpeg2000dec: Check ncomponents and tile dimensions
avcodec/jpeg2000dec: get_qcx, fix stack and heap overwrites
avcodec/jpeg2000dec: merge bytestream2 reading from j2kdec
vcodec/jpeg2000dec: fix av_log() type
jpeg2000dec & j2kdec: Fix return type of get_sot()
jpeg2000dec: read and check curtileno
jpeg2000dec: check TPsot
avcodec/jpeg2000dec: Port tile size check from j2kdec
j2k & jpeg2000dec: reset numX/Ytiles if tiles failed allocation
j2kdec & jpeg2000dec: check lengthinc against array size
jpeg2000/j2k: merge getsigctxno()
j2k/jpeg2000: merge cosmetics and whitespace
j2k: cosmetics from jpeg2000
j2k/jpeg2000: check cblk size
j2k/jpeg2000: log2_prec size cleanup
j2k/jpeg2000 headers: Cblk/Prec cleanup & merge
j2k/jpeg2000: restructure cblk coord
j2k/jpeg2000: drop xi/yi0/1 from Jpeg2000Prec
j2k/jpeg2000: merge a few whitespaces
j2k/jpeg2000: Partially merge quantization code
j2k/jpeg2000: merge j2k & jpeg2000 dwts, drop j2k dwt
jpeg2000: merge mant type from j2k
j2k/jpeg2000: merge lowres code
jpeg2000dwt: remove floats from mixed float/int 9/7 dwt
jpeg2000dwt: add float based 9/7 dwt
j2kdec/jpeg2000dec: partially merge quantization code
j2k/jpeg2000: fix typo in lut_gain index
jpeg2000dec: remove unneeded returns
j2k/jpeg2000: split stepsize in float & int variables
jpeg2000dec: mct_decode: remove unused return
j2k/jpeg2000: merge float DWT and related code
j2k/jpeg2000: split data pointer in int & float.
jpeg2000: tag_tree_size: replace check by assert
jpeg2000: remove unneeded variable initialization
jpeg2000: merges quantization fixes from j2k
jpeg2000: remove unneeded casts
jpeg2000/j2k: merge j2k/jpeg2000.c/h
j2k/jpeg2000: merge pix_fmt setting code
jpeg2000: drop red-blue swap
jpeg2000/j2k: merge non functional changes
jpeg2000dec: simplify init_tile() / merge from j2k
jpeg2000dec: fix ff_mqc_initdec() and data setup order
jpeg2000deci/j2kdec: fix sizeof types
j2k/jpeg2000: merge some of the tilepart related code
jpeg2000dec: merge struct field types from j2k
jpeg2000dec: merge sgnd fix from j2k
jpeg2000dec: merge simplification of jpeg2000_decode_packets() from
j2k
j2k/jpeg2000dec: merge
jpeg2000dec: print more detailed cdx/y debug info
jpeg2000dec: fix indention
jpeg2000dec: optimize dequantization_float()
jpeg2000dec: optimize dequantization_int()
jpeg2000: make sure s->numXtiles / s->numYtiles are reset when tile
is deallocated
jpeg2000dec; optimize output sample convert a bit
avcodec/jpeg2000dwt: merge rescaling with interleave in 9/7 float
IDWT
avcodec/jpeg2000dwt: merge rescaling with interleave in 9/7 int IDWT
jpeg2000: Fix Unintended sign extension in malloc arguments of cblk.
jpeg2000: Fix unintended sign extension in malloc arguments of prec
jpeg2000dec: assert that curtileno is valid when used
jpeg2000: check that nreslevels2decode has been initialized before
use
jpeg2000dec: Propagate error code from get_cox() correctly
jpeg2000: Make nreslevel fields int
jpeg2000dec: return error for invalid cdxy values
get_qcc: Check compno
jpeg2000dec: Support 4 tile parts
jpeg2000dec: Check that theres a SOT before SOD
jpeg2000dec: Use the matching coding style struct for transform
selection
jpeg2000dec: check that we have enough components for MCT
jpeg2000dec: fix av_log()
jpeg2000: Zero prec->cblk
jpeg2000dec: Check bpno in decode_cblk()
jpeg2000dec: dont set ncomponents to an invalid value
jpeg2000dec: Check compno in get_coc()
avcodec/jpeg2000dec: Check Psot
avcodec/jpeg2000dec: check len before parsing header
avcodec/jpeg2000dec: move bpno check to a earlier place

Nicolas Bertrand (2):
jpeg2000: Desactivation of encoder.
jpeg2000: set valid return value in jpeg2000_decode_frame

Paul B Mahol (1):
jpeg2000dec: remove redundant error log message

libavcodec/allcodecs.c | 2 +-
libavcodec/jpeg2000.c | 161 +++++---
libavcodec/jpeg2000.h | 23 +-
libavcodec/jpeg2000dec.c | 697 +++++++++++++++++++---------------
libavcodec/jpeg2000dwt.c | 257 +++++++++++--
libavcodec/jpeg2000dwt.h | 1 +
tests/ref/vsynth/vsynth1-jpeg2000 | 4 +
tests/ref/vsynth/vsynth1-jpeg2000-97 | 4 +
tests/ref/vsynth/vsynth2-jpeg2000 | 4 +
tests/ref/vsynth/vsynth2-jpeg2000-97 | 4 +
10 files changed, 762 insertions(+), 395 deletions(-)
create mode 100644 tests/ref/vsynth/vsynth1-jpeg2000
create mode 100644 tests/ref/vsynth/vsynth1-jpeg2000-97
create mode 100644 tests/ref/vsynth/vsynth2-jpeg2000
create mode 100644 tests/ref/vsynth/vsynth2-jpeg2000-97
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:26:41 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes various problems

Code ported from j2kdec

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 8c49ea9..72b84e7 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -176,6 +176,13 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->tile_offset_y = bytestream_get_be32(&s->buf); // YT0Siz
s->ncomponents = bytestream_get_be16(&s->buf); // CSiz

+ if(s->ncomponents <= 0 || s->ncomponents > 4) {
+ av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", s->ncomponents);
+ return AVERROR(EINVAL);
+ }
+ if(s->tile_width<=0 || s->tile_height<=0)
+ return AVERROR(EINVAL);
+
if (s->buf_end - s->buf < 2 * s->ncomponents)
return AVERROR(EINVAL);
--
1.7.9.5
Luca Barbato
2013-06-21 14:01:26 UTC
Permalink
Avoid multiple buffer overflow, maybe ?
Post by Nicolas Bertrand
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
---
libavcodec/jpeg2000dec.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 8c49ea9..72b84e7 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -176,6 +176,13 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->tile_offset_y = bytestream_get_be32(&s->buf); // YT0Siz
s->ncomponents = bytestream_get_be16(&s->buf); // CSiz
+ if(s->ncomponents <= 0 || s->ncomponents > 4) {
+ av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", s->ncomponents);
+ return AVERROR(EINVAL);
+ }
+ if(s->tile_width<=0 || s->tile_height<=0)
+ return AVERROR(EINVAL);
format it properly with spaces between operators.

lu
Nicolas BERTRAND
2013-06-24 10:18:15 UTC
Permalink
Post by Luca Barbato
Avoid multiple buffer overflow, maybe ?
For the title of the commit I guess?
I propose: jpeg2000: Check number of image components and tile dimensions
Nicolas Bertrand
2013-06-21 13:26:42 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This is likely remotely exploitable
Fix ported from j2kdec
No uptodate FFmpeg release should be affected by this

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 72b84e7..66d1aec 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -353,7 +353,7 @@ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q)

if (q->quantsty == JPEG2000_QSTY_NONE) {
n -= 3;
- if (s->buf_end - s->buf < n)
+ if (s->buf_end - s->buf < n || 32*3 < n)
return AVERROR(EINVAL);
for (i = 0; i < n; i++)
q->expn[i] = bytestream_get_byte(&s->buf) >> 3;
@@ -370,7 +370,7 @@ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q)
}
} else {
n = (n - 3) >> 1;
- if (s->buf_end - s->buf < n)
+ if (s->buf_end - s->buf < 2 * n || 32*3 < n)
return AVERROR(EINVAL);
for (i = 0; i < n; i++) {
x = bytestream_get_be16(&s->buf);
--
1.7.9.5
Luca Barbato
2013-06-21 14:05:15 UTC
Permalink
Post by Nicolas Bertrand
This is likely remotely exploitable
Fix ported from j2kdec
No uptodate FFmpeg release should be affected by this
Questions: What is 32*3 ? Make a define that is at least a bit explanatory.


jpeg2000dec: make sure ${whatever n is} is within bounds

Prevent buffer overwrites.
Post by Nicolas Bertrand
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Incidentally, what about using a more compact name for jpeg2000 such as
jpeg2k ?
Post by Nicolas Bertrand
---
libavcodec/jpeg2000dec.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 72b84e7..66d1aec 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -353,7 +353,7 @@ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q)
if (q->quantsty == JPEG2000_QSTY_NONE) {
n -= 3;
- if (s->buf_end - s->buf < n)
+ if (s->buf_end - s->buf < n || 32*3 < n)
return AVERROR(EINVAL);
for (i = 0; i < n; i++)
q->expn[i] = bytestream_get_byte(&s->buf) >> 3;
@@ -370,7 +370,7 @@ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q)
}
} else {
n = (n - 3) >> 1;
- if (s->buf_end - s->buf < n)
+ if (s->buf_end - s->buf < 2 * n || 32*3 < n)
return AVERROR(EINVAL);
for (i = 0; i < n; i++) {
x = bytestream_get_be16(&s->buf);
Same cleanup as the previous needed.

lu
Diego Biurrun
2013-06-21 14:12:41 UTC
Permalink
Post by Luca Barbato
Post by Nicolas Bertrand
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Incidentally, what about using a more compact name for jpeg2000 such as
jpeg2k ?
jpeg2000 is fine, let's not fuss about two characters.

Diego
Nicolas Bertrand
2013-06-21 13:26:43 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This fixes at least one out of array access

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/jpeg2000dec.c
---
libavcodec/jpeg2000dec.c | 203 ++++++++++++++++++++++------------------------
1 file changed, 99 insertions(+), 104 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 66d1aec..dbc49fb 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -44,8 +44,7 @@ typedef struct Jpeg2000TilePart {
uint16_t tp_idx; // Tile-part index
uint8_t tile_index; // Tile index who refers the tile-part
uint32_t tp_len; // Length of tile-part
- const uint8_t *tp_start_bstrm; // Start address bit stream in tile-part
- const uint8_t *tp_end_bstrm; // End address of the bit stream tile part
+ GetByteContext tpg; // bit stream in tile-part
} Jpeg2000TilePart;

/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile
@@ -61,6 +60,7 @@ typedef struct Jpeg2000Tile {
typedef struct Jpeg2000DecoderContext {
AVClass *class;
AVCodecContext *avctx;
+ GetByteContext g;

int width, height;
int image_offset_x, image_offset_y;
@@ -78,9 +78,6 @@ typedef struct Jpeg2000DecoderContext {
Jpeg2000CodingStyle codsty[4];
Jpeg2000QuantStyle qntsty[4];

- const uint8_t *buf_start;
- const uint8_t *buf;
- const uint8_t *buf_end;
int bit_index;

int16_t curtileno;
@@ -98,26 +95,23 @@ typedef struct Jpeg2000DecoderContext {
static int get_bits(Jpeg2000DecoderContext *s, int n)
{
int res = 0;
- if (s->buf_end - s->buf < ((n - s->bit_index) >> 8))
- return AVERROR(EINVAL);
+
while (--n >= 0) {
res <<= 1;
if (s->bit_index == 0) {
- s->bit_index = 7 + (*s->buf != 0xff);
- s->buf++;
+ s->bit_index = 7 + (bytestream2_get_byte(&s->g) != 0xFFu);
}
s->bit_index--;
- res |= (*s->buf >> s->bit_index) & 1;
+ res |= (bytestream2_peek_byte(&s->g) >> s->bit_index) & 1;
}
return res;
}

static void jpeg2000_flush(Jpeg2000DecoderContext *s)
{
- if (*s->buf == 0xff)
- s->buf++;
+ if (bytestream2_get_byte(&s->g) == 0xff)
+ bytestream2_skip(&s->g, 1);
s->bit_index = 8;
- s->buf++;
}

/* decode the value stored in node */
@@ -162,19 +156,19 @@ static int get_siz(Jpeg2000DecoderContext *s)
{
int i;

- if (s->buf_end - s->buf < 36)
+ if (bytestream2_get_bytes_left(&s->g) < 36)
return AVERROR(EINVAL);

- s->avctx->profile = bytestream_get_be16(&s->buf); // Rsiz
- s->width = bytestream_get_be32(&s->buf); // Width
- s->height = bytestream_get_be32(&s->buf); // Height
- s->image_offset_x = bytestream_get_be32(&s->buf); // X0Siz
- s->image_offset_y = bytestream_get_be32(&s->buf); // Y0Siz
- s->tile_width = bytestream_get_be32(&s->buf); // XTSiz
- s->tile_height = bytestream_get_be32(&s->buf); // YTSiz
- s->tile_offset_x = bytestream_get_be32(&s->buf); // XT0Siz
- s->tile_offset_y = bytestream_get_be32(&s->buf); // YT0Siz
- s->ncomponents = bytestream_get_be16(&s->buf); // CSiz
+ s->avctx->profile = bytestream2_get_be16u(&s->g); // Rsiz
+ s->width = bytestream2_get_be32u(&s->g); // Width
+ s->height = bytestream2_get_be32u(&s->g); // Height
+ s->image_offset_x = bytestream2_get_be32u(&s->g); // X0Siz
+ s->image_offset_y = bytestream2_get_be32u(&s->g); // Y0Siz
+ s->tile_width = bytestream2_get_be32u(&s->g); // XTSiz
+ s->tile_height = bytestream2_get_be32u(&s->g); // YTSiz
+ s->tile_offset_x = bytestream2_get_be32u(&s->g); // XT0Siz
+ s->tile_offset_y = bytestream2_get_be32u(&s->g); // YT0Siz
+ s->ncomponents = bytestream2_get_be16u(&s->g); // CSiz

if(s->ncomponents <= 0 || s->ncomponents > 4) {
av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", s->ncomponents);
@@ -183,16 +177,16 @@ static int get_siz(Jpeg2000DecoderContext *s)
if(s->tile_width<=0 || s->tile_height<=0)
return AVERROR(EINVAL);

- if (s->buf_end - s->buf < 2 * s->ncomponents)
+ if (bytestream2_get_bytes_left(&s->g) < 3 * s->ncomponents)
return AVERROR(EINVAL);

for (i = 0; i < s->ncomponents; i++) { // Ssiz_i XRsiz_i, YRsiz_i
- uint8_t x = bytestream_get_byte(&s->buf);
+ uint8_t x = bytestream2_get_byteu(&s->g);
s->cbps[i] = (x & 0x7f) + 1;
s->precision = FFMAX(s->cbps[i], s->precision);
s->sgnd[i] = (x & 0x80) == 1;
- s->cdx[i] = bytestream_get_byte(&s->buf);
- s->cdy[i] = bytestream_get_byte(&s->buf);
+ s->cdx[i] = bytestream2_get_byteu(&s->g);
+ s->cdy[i] = bytestream2_get_byteu(&s->g);
}

s->numXtiles = ff_jpeg2000_ceildiv(s->width - s->tile_offset_x, s->tile_width);
@@ -256,9 +250,9 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
{
uint8_t byte;

- if (s->buf_end - s->buf < 5)
+ if (bytestream2_get_bytes_left(&s->g) < 5)
return AVERROR(EINVAL);
- c->nreslevels = bytestream_get_byte(&s->buf) + 1; // num of resolution levels - 1
+ c->nreslevels = bytestream2_get_byteu(&s->g) + 1; // num of resolution levels - 1

/* compute number of resolution levels to decode */
if (c->nreslevels < s->reduction_factor)
@@ -266,15 +260,15 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
else
c->nreslevels2decode = c->nreslevels - s->reduction_factor;

- c->log2_cblk_width = bytestream_get_byte(&s->buf) + 2; // cblk width
- c->log2_cblk_height = bytestream_get_byte(&s->buf) + 2; // cblk height
+ c->log2_cblk_width = bytestream2_get_byteu(&s->g) + 2; // cblk width
+ c->log2_cblk_height = bytestream2_get_byteu(&s->g) + 2; // cblk height

- c->cblk_style = bytestream_get_byte(&s->buf);
+ c->cblk_style = bytestream2_get_byteu(&s->g);
if (c->cblk_style != 0) { // cblk style
av_log(s->avctx, AV_LOG_ERROR, "no extra cblk styles supported\n");
return -1;
}
- c->transform = bytestream_get_byte(&s->buf); // DWT transformation type
+ c->transform = bytestream2_get_byteu(&s->g); // DWT transformation type
/* set integer 9/7 DWT in case of BITEXACT flag */
if ((s->avctx->flags & CODEC_FLAG_BITEXACT) && (c->transform == FF_DWT97))
c->transform = FF_DWT97_INT;
@@ -282,7 +276,7 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
if (c->csty & JPEG2000_CSTY_PREC) {
int i;
for (i = 0; i < c->nreslevels; i++) {
- byte = bytestream_get_byte(&s->buf);
+ byte = bytestream2_get_byte(&s->g);
c->log2_prec_widths[i] = byte & 0x0F; // precinct PPx
c->log2_prec_heights[i] = (byte >> 4) & 0x0F; // precinct PPy
}
@@ -297,19 +291,19 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
Jpeg2000CodingStyle tmp;
int compno;

- if (s->buf_end - s->buf < 5)
+ if (bytestream2_get_bytes_left(&s->g) < 5)
return AVERROR(EINVAL);

tmp.log2_prec_width =
tmp.log2_prec_height = 15;

- tmp.csty = bytestream_get_byte(&s->buf);
+ tmp.csty = bytestream2_get_byteu(&s->g);

// get progression order
- tmp.prog_order = bytestream_get_byte(&s->buf);
+ tmp.prog_order = bytestream2_get_byteu(&s->g);

- tmp.nlayers = bytestream_get_be16(&s->buf);
- tmp.mct = bytestream_get_byte(&s->buf); // multiple component transformation
+ tmp.nlayers = bytestream2_get_be16u(&s->g);
+ tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation

get_cox(s, &tmp);
for (compno = 0; compno < s->ncomponents; compno++)
@@ -325,13 +319,13 @@ static int get_coc(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
{
int compno;

- if (s->buf_end - s->buf < 2)
+ if (bytestream2_get_bytes_left(&s->g) < 2)
return AVERROR(EINVAL);

- compno = bytestream_get_byte(&s->buf);
+ compno = bytestream2_get_byteu(&s->g);

c += compno;
- c->csty = bytestream_get_byte(&s->buf);
+ c->csty = bytestream2_get_byteu(&s->g);
get_cox(s, c);

properties[compno] |= HAD_COC;
@@ -343,24 +337,24 @@ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q)
{
int i, x;

- if (s->buf_end - s->buf < 1)
+ if (bytestream2_get_bytes_left(&s->g) < 1)
return AVERROR(EINVAL);

- x = bytestream_get_byte(&s->buf); // Sqcd
+ x = bytestream2_get_byteu(&s->g); // Sqcd

q->nguardbits = x >> 5;
q->quantsty = x & 0x1f;

if (q->quantsty == JPEG2000_QSTY_NONE) {
n -= 3;
- if (s->buf_end - s->buf < n || 32*3 < n)
+ if (bytestream2_get_bytes_left(&s->g) < n || 32*3 < n)
return AVERROR(EINVAL);
for (i = 0; i < n; i++)
- q->expn[i] = bytestream_get_byte(&s->buf) >> 3;
+ q->expn[i] = bytestream2_get_byteu(&s->g) >> 3;
} else if (q->quantsty == JPEG2000_QSTY_SI) {
- if (s->buf_end - s->buf < 2)
+ if (bytestream2_get_bytes_left(&s->g) < 2)
return AVERROR(EINVAL);
- x = bytestream_get_be16(&s->buf);
+ x = bytestream2_get_be16u(&s->g);
q->expn[0] = x >> 11;
q->mant[0] = x & 0x7ff;
for (i = 1; i < 32 * 3; i++) {
@@ -370,10 +364,10 @@ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q)
}
} else {
n = (n - 3) >> 1;
- if (s->buf_end - s->buf < 2 * n || 32*3 < n)
+ if (bytestream2_get_bytes_left(&s->g) < 2 * n || 32*3 < n)
return AVERROR(EINVAL);
for (i = 0; i < n; i++) {
- x = bytestream_get_be16(&s->buf);
+ x = bytestream2_get_be16u(&s->g);
q->expn[i] = x >> 11;
q->mant[i] = x & 0x7ff;
}
@@ -403,10 +397,10 @@ static int get_qcc(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q,
{
int compno;

- if (s->buf_end - s->buf < 1)
+ if (bytestream2_get_bytes_left(&s->g) < 1)
return AVERROR(EINVAL);

- compno = bytestream_get_byte(&s->buf);
+ compno = bytestream2_get_byteu(&s->g);
properties[compno] |= HAD_QCC;
return get_qcx(s, n - 1, q + compno);
}
@@ -419,20 +413,20 @@ static uint8_t get_sot(Jpeg2000DecoderContext *s, int n)
uint32_t Psot;
uint8_t TPsot;

- if (s->buf_end - s->buf < 4)
+ if (bytestream2_get_bytes_left(&s->g) < 8)
return AVERROR(EINVAL);

- Isot = bytestream_get_be16(&s->buf); // Isot
+ Isot = bytestream2_get_be16u(&s->g); // Isot
if (Isot) {
av_log(s->avctx, AV_LOG_ERROR,
"Not a DCINEMA JP2K file: more than one tile\n");
return -1;
}
- Psot = bytestream_get_be32(&s->buf); // Psot
- TPsot = bytestream_get_byte(&s->buf); // TPsot
+ Psot = bytestream2_get_be32u(&s->g); // Psot
+ TPsot = bytestream2_get_byteu(&s->g); // TPsot

/* Read TNSot but not used */
- bytestream_get_byte(&s->buf); // TNsot
+ bytestream2_get_byteu(&s->g); // TNsot

tp = s->tile[s->curtileno].tile_part + TPsot;
tp->tile_index = Isot;
@@ -441,9 +435,10 @@ static uint8_t get_sot(Jpeg2000DecoderContext *s, int n)

/* Start of bit stream. Pointer to SOD marker
* Check SOD marker is present. */
- if (JPEG2000_SOD == bytestream_get_be16(&s->buf))
- tp->tp_start_bstrm = s->buf;
- else {
+ if (JPEG2000_SOD == bytestream2_get_be16(&s->g)) {
+ bytestream2_init(&tp->tpg, s->g.buffer, tp->tp_len - n - 4);
+ bytestream2_skip(&s->g, tp->tp_len - n - 4);
+ } else {
av_log(s->avctx, AV_LOG_ERROR, "SOD marker not found \n");
return -1;
}
@@ -451,10 +446,6 @@ static uint8_t get_sot(Jpeg2000DecoderContext *s, int n)
/* End address of bit stream =
* start address + (Psot - size of SOT HEADER(n)
* - size of SOT MARKER(2) - size of SOD marker(2) */
- tp->tp_end_bstrm = s->buf + (tp->tp_len - n - 4);
-
- // set buffer pointer to end of tile part header
- s->buf = tp->tp_end_bstrm;

return 0;
}
@@ -470,8 +461,8 @@ static uint8_t get_sot(Jpeg2000DecoderContext *s, int n)
static uint8_t get_tlm(Jpeg2000DecoderContext *s, int n)
{
uint8_t Stlm, ST, SP, tile_tlm, i;
- bytestream_get_byte(&s->buf); /* Ztlm: skipped */
- Stlm = bytestream_get_byte(&s->buf);
+ bytestream2_get_byte(&s->g); /* Ztlm: skipped */
+ Stlm = bytestream2_get_byte(&s->g);

// too complex ? ST = ((Stlm >> 4) & 0x01) + ((Stlm >> 4) & 0x02);
ST = (Stlm >> 4) & 0x03;
@@ -483,19 +474,19 @@ static uint8_t get_tlm(Jpeg2000DecoderContext *s, int n)
case 0:
break;
case 1:
- bytestream_get_byte(&s->buf);
+ bytestream2_get_byte(&s->g);
break;
case 2:
- bytestream_get_be16(&s->buf);
+ bytestream2_get_be16(&s->g);
break;
case 3:
- bytestream_get_be32(&s->buf);
+ bytestream2_get_be32(&s->g);
break;
}
if (SP == 0) {
- bytestream_get_be16(&s->buf);
+ bytestream2_get_be16(&s->g);
} else {
- bytestream_get_be32(&s->buf);
+ bytestream2_get_be32(&s->g);
}
}
return 0;
@@ -627,8 +618,8 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
jpeg2000_flush(s);

if (codsty->csty & JPEG2000_CSTY_EPH) {
- if (AV_RB16(s->buf) == JPEG2000_EPH)
- s->buf += 2;
+ if (bytestream2_peek_be16(&s->g) == JPEG2000_EPH)
+ bytestream2_skip(&s->g, 2);
else
av_log(s->avctx, AV_LOG_ERROR, "EPH marker not found.\n");
}
@@ -640,12 +631,12 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width;
for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {
Jpeg2000Cblk *cblk = prec->cblk + cblkno;
- if (s->buf_end - s->buf < cblk->lengthinc)
+ if (bytestream2_get_bytes_left(&s->g) < cblk->lengthinc)
return AVERROR(EINVAL);
/* Code-block data can be empty. In that case initialize data
* with 0xFFFF. */
if (cblk->lengthinc > 0) {
- bytestream_get_buffer(&s->buf, cblk->data, cblk->lengthinc);
+ bytestream2_get_bufferu(&s->g, cblk->data, cblk->lengthinc);
} else {
cblk->data[0] = 0xFF;
cblk->data[1] = 0xFF;
@@ -699,7 +690,7 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
/* Set bit stream buffer address according to tile-part.
* For DCinema one tile-part per component, so can be
* indexed by component. */
- s->buf = tile->tile_part[compno].tp_start_bstrm;
+ s->g = tile->tile_part[compno].tpg;

/* Position loop (y axis)
* TODO: Automate computing of step 256.
@@ -744,7 +735,7 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
}

/* EOC marker reached */
- s->buf += 2;
+ bytestream2_skip(&s->g, 2);

return 0;
}
@@ -1158,22 +1149,22 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
for (;;) {
int len, ret = 0;
uint16_t marker;
- const uint8_t *oldbuf;
+ int oldpos;

- if (s->buf_end - s->buf < 2) {
+ if (bytestream2_get_bytes_left(&s->g) < 2) {
av_log(s->avctx, AV_LOG_ERROR, "Missing EOC\n");
break;
}

- marker = bytestream_get_be16(&s->buf);
- oldbuf = s->buf;
+ marker = bytestream2_get_be16u(&s->g);
+ oldpos = bytestream2_tell(&s->g);

if (marker == JPEG2000_EOC)
break;

- if (s->buf_end - s->buf < 2)
+ if (bytestream2_get_bytes_left(&s->g) < 2)
return AVERROR(EINVAL);
- len = bytestream_get_be16(&s->buf);
+ len = bytestream2_get_be16u(&s->g);
switch (marker) {
case JPEG2000_SIZ:
ret = get_siz(s);
@@ -1195,7 +1186,7 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
break;
case JPEG2000_COM:
// the comment is ignored
- s->buf += len - 2;
+ bytestream2_skip(&s->g, len - 2);
break;
case JPEG2000_TLM:
// Tile-part lengths
@@ -1204,11 +1195,11 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
default:
av_log(s->avctx, AV_LOG_ERROR,
"unsupported marker 0x%.4X at pos 0x%tX\n",
- marker, s->buf - s->buf_start - 4);
- s->buf += len - 2;
+ marker, bytestream2_tell(&s->g) - 4);
+ bytestream2_skip(&s->g, len - 2);
break;
}
- if (((s->buf - oldbuf != len) && (marker != JPEG2000_SOT)) || ret) {
+ if (((bytestream2_tell(&s->g) - oldpos != len) && (marker != JPEG2000_SOT)) || ret) {
av_log(s->avctx, AV_LOG_ERROR,
"error during processing marker segment %.4x\n", marker);
return ret ? ret : -1;
@@ -1233,19 +1224,18 @@ static int jpeg2000_read_bitstream_packets(Jpeg2000DecoderContext *s)

static int jp2_find_codestream(Jpeg2000DecoderContext *s)
{
- int32_t atom_size;
+ uint32_t atom_size, atom;
int found_codestream = 0, search_range = 10;

- // Skip JPEG 2000 signature atom.
- s->buf += 12;
-
- while (!found_codestream && search_range) {
- atom_size = AV_RB32(s->buf);
- if (AV_RB32(s->buf + 4) == JP2_CODESTREAM) {
+ while(!found_codestream && search_range && bytestream2_get_bytes_left(&s->g) >= 8) {
+ atom_size = bytestream2_get_be32u(&s->g);
+ atom = bytestream2_get_be32u(&s->g);
+ if (atom == JP2_CODESTREAM) {
found_codestream = 1;
- s->buf += 8;
} else {
- s->buf += atom_size;
+ if (bytestream2_get_bytes_left(&s->g) < atom_size - 8)
+ return 0;
+ bytestream2_skipu(&s->g, atom_size - 8);
search_range--;
}
}
@@ -1264,28 +1254,32 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
int tileno, ret;

s->avctx = avctx;
- s->buf = s->buf_start = avpkt->data;
- s->buf_end = s->buf_start + avpkt->size;
+ bytestream2_init(&s->g, avpkt->data, avpkt->size);
s->curtileno = 0; // TODO: only one tile in DCI JP2K. to implement for more tiles

// reduction factor, i.e number of resolution levels to skip
s->reduction_factor = s->lowres;

- if (s->buf_end - s->buf < 2)
+ if (bytestream2_get_bytes_left(&s->g) < 2)
return AVERROR(EINVAL);

// check if the image is in jp2 format
- if ((AV_RB32(s->buf) == 12) &&
- (AV_RB32(s->buf + 4) == JP2_SIG_TYPE) &&
- (AV_RB32(s->buf + 8) == JP2_SIG_VALUE)) {
+ if (bytestream2_get_bytes_left(&s->g) >= 12 &&
+ (bytestream2_get_be32u(&s->g) == 12) &&
+ (bytestream2_get_be32u(&s->g) == JP2_SIG_TYPE) &&
+ (bytestream2_get_be32u(&s->g) == JP2_SIG_VALUE)) {
if (!jp2_find_codestream(s)) {
av_log(avctx, AV_LOG_ERROR,
"couldn't find jpeg2k codestream atom\n");
return -1;
}
+ } else {
+ bytestream2_seek(&s->g, 0, SEEK_SET);
+ if (bytestream2_peek_be16(&s->g) != JPEG2000_SOC /*&& AV_RB32(s->buf + 4) == JP2_CODESTREAM*/)
+ bytestream2_skip(&s->g, 8);
}

- if (bytestream_get_be16(&s->buf) != JPEG2000_SOC) {
+ if (bytestream2_get_be16u(&s->g) != JPEG2000_SOC) {
av_log(avctx, AV_LOG_ERROR, "SOC marker not present\n");
return -1;
}
@@ -1308,6 +1302,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,

*got_frame = 1;

+ return bytestream2_tell(&s->g);
end:
jpeg2000_dec_cleanup(s);
return ret ? ret : s->buf - s->buf_start;
--
1.7.9.5
Luca Barbato
2013-06-21 14:07:07 UTC
Permalink
Post by Nicolas Bertrand
This fixes at least one out of array access
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
The commit message should be

jpeg2000dec: use bytestream2

Prevent some overreads.

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind

lu
Nicolas Bertrand
2013-06-21 13:26:44 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index dbc49fb..8e5a5ce 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1194,7 +1194,7 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
break;
default:
av_log(s->avctx, AV_LOG_ERROR,
- "unsupported marker 0x%.4X at pos 0x%tX\n",
+ "unsupported marker 0x%.4X at pos 0x%X\n",
marker, bytestream2_tell(&s->g) - 4);
bytestream2_skip(&s->g, len - 2);
break;
--
1.7.9.5
Luca Barbato
2013-06-21 14:07:37 UTC
Permalink
Fold in the previous.
Nicolas Bertrand
2013-06-21 13:26:45 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2kdec.c
---
libavcodec/jpeg2000dec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 8e5a5ce..b1633e3 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -406,7 +406,7 @@ static int get_qcc(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q,
}

/* Get start of tile segment. */
-static uint8_t get_sot(Jpeg2000DecoderContext *s, int n)
+static int get_sot(Jpeg2000DecoderContext *s, int n)
{
Jpeg2000TilePart *tp;
uint16_t Isot;
--
1.7.9.5
Luca Barbato
2013-06-21 14:08:19 UTC
Permalink
the commit message needs the same rework.

lu
Nicolas Bertrand
2013-06-21 13:26:46 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array accesses
Code ported from j2kdec

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index b1633e3..038ab4f 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -416,7 +416,11 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
if (bytestream2_get_bytes_left(&s->g) < 8)
return AVERROR(EINVAL);

- Isot = bytestream2_get_be16u(&s->g); // Isot
+ s->curtileno = Isot = bytestream2_get_be16u(&s->g); // Isot
+ if((unsigned)s->curtileno >= s->numXtiles * s->numYtiles){
+ s->curtileno=0;
+ return AVERROR(EINVAL);
+ }
if (Isot) {
av_log(s->avctx, AV_LOG_ERROR,
"Not a DCINEMA JP2K file: more than one tile\n");
--
1.7.9.5
Luca Barbato
2013-06-21 14:11:50 UTC
Permalink
jpeg2000dec: validate the current tile number
Post by Nicolas Bertrand
Fixes out of array accesses
Code ported from j2kdec
j2kdec doesn't exist here.
Post by Nicolas Bertrand
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
---
libavcodec/jpeg2000dec.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index b1633e3..038ab4f 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -416,7 +416,11 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
if (bytestream2_get_bytes_left(&s->g) < 8)
return AVERROR(EINVAL);
- Isot = bytestream2_get_be16u(&s->g); // Isot
+ s->curtileno = Isot = bytestream2_get_be16u(&s->g); // Isot
+ if((unsigned)s->curtileno >= s->numXtiles * s->numYtiles){
why curtileno is signed? A negative value has any mean?
Post by Nicolas Bertrand
+ s->curtileno=0;
+ return AVERROR(EINVAL);
INVALIDDATA
Post by Nicolas Bertrand
+ }
if (Isot) {
av_log(s->avctx, AV_LOG_ERROR,
"Not a DCINEMA JP2K file: more than one tile\n");
Do we error out in that case?

lu
Nicolas Bertrand
2013-06-21 13:26:47 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array accesses

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 038ab4f..45396d0 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -432,6 +432,11 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
/* Read TNSot but not used */
bytestream2_get_byteu(&s->g); // TNsot

+ if (TPsot >= FF_ARRAY_ELEMS(s->tile[s->curtileno].tile_part)) {
+ av_log(s->avctx, AV_LOG_ERROR, "TPsot %d too big\n", TPsot);
+ return AVERROR_PATCHWELCOME;
+ }
+
tp = s->tile[s->curtileno].tile_part + TPsot;
tp->tile_index = Isot;
tp->tp_len = Psot;
--
1.7.9.5
Luca Barbato
2013-06-21 14:12:45 UTC
Permalink
Post by Nicolas Bertrand
Fixes out of array accesses
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
---
libavcodec/jpeg2000dec.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 038ab4f..45396d0 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -432,6 +432,11 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
/* Read TNSot but not used */
bytestream2_get_byteu(&s->g); // TNsot
+ if (TPsot >= FF_ARRAY_ELEMS(s->tile[s->curtileno].tile_part)) {
+ av_log(s->avctx, AV_LOG_ERROR, "TPsot %d too big\n", TPsot);
+ return AVERROR_PATCHWELCOME;
+ }
Why patch is welcome? Is it a missing feature? Do we need/have samples?

lu
Nicolas Bertrand
2013-06-21 13:26:48 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes potential integer overflow

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 45396d0..a8dae3e 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -192,6 +192,9 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->numXtiles = ff_jpeg2000_ceildiv(s->width - s->tile_offset_x, s->tile_width);
s->numYtiles = ff_jpeg2000_ceildiv(s->height - s->tile_offset_y, s->tile_height);

+ if(s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(Jpeg2000Tile))
+ return AVERROR(EINVAL);
+
s->tile = av_mallocz(s->numXtiles * s->numYtiles * sizeof(*s->tile));
if (!s->tile)
return AVERROR(ENOMEM);
--
1.7.9.5
Luca Barbato
2013-06-21 14:14:06 UTC
Permalink
Post by Nicolas Bertrand
Fixes potential integer overflow
---
libavcodec/jpeg2000dec.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 45396d0..a8dae3e 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -192,6 +192,9 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->numXtiles = ff_jpeg2000_ceildiv(s->width - s->tile_offset_x, s->tile_width);
s->numYtiles = ff_jpeg2000_ceildiv(s->height - s->tile_offset_y, s->tile_height);
+ if(s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(Jpeg2000Tile))
+ return AVERROR(EINVAL);
+
s->tile = av_mallocz(s->numXtiles * s->numYtiles * sizeof(*s->tile));
That should use av_mallocz_array instead.
Post by Nicolas Bertrand
if (!s->tile)
return AVERROR(ENOMEM);
Nicolas Bertrand
2013-06-21 13:26:49 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes null pointer dereference

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2kdec.c
---
libavcodec/jpeg2000dec.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index a8dae3e..4ef0e8b 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1180,6 +1180,8 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
switch (marker) {
case JPEG2000_SIZ:
ret = get_siz(s);
+ if (!s->tile)
+ s->numXtiles = s->numYtiles = 0;
break;
case JPEG2000_COC:
ret = get_coc(s, codsty, properties);
--
1.7.9.5
Luca Barbato
2013-06-21 14:14:56 UTC
Permalink
Post by Nicolas Bertrand
Fixes null pointer dereference
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
libavcodec/j2kdec.c
---
libavcodec/jpeg2000dec.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index a8dae3e..4ef0e8b 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1180,6 +1180,8 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
switch (marker) {
ret = get_siz(s);
+ if (!s->tile)
+ s->numXtiles = s->numYtiles = 0;
Looks fishy, what is get_siz is supposed to do?

lu
Nicolas Bertrand
2013-06-21 13:26:50 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array reads

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2kdec.c
---
libavcodec/jpeg2000dec.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 4ef0e8b..5620b5b 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -643,7 +643,9 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width;
for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {
Jpeg2000Cblk *cblk = prec->cblk + cblkno;
- if (bytestream2_get_bytes_left(&s->g) < cblk->lengthinc)
+ if ( bytestream2_get_bytes_left(&s->g) < cblk->lengthinc
+ || sizeof(cblk->data) < cblk->lengthinc
+ )
return AVERROR(EINVAL);
/* Code-block data can be empty. In that case initialize data
* with 0xFFFF. */
--
1.7.9.5
Luca Barbato
2013-06-21 14:16:01 UTC
Permalink
Post by Nicolas Bertrand
Fixes out of array reads
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
libavcodec/j2kdec.c
---
libavcodec/jpeg2000dec.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 4ef0e8b..5620b5b 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -643,7 +643,9 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width;
for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {
Jpeg2000Cblk *cblk = prec->cblk + cblkno;
- if (bytestream2_get_bytes_left(&s->g) < cblk->lengthinc)
+ if ( bytestream2_get_bytes_left(&s->g) < cblk->lengthinc
+ || sizeof(cblk->data) < cblk->lengthinc
+ )
return AVERROR(EINVAL);
Please doublecheck it while you fix the formatting.

lu
Nicolas Bertrand
2013-06-21 13:26:51 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
---
libavcodec/jpeg2000.c | 52 ++++++++++++++++++-------------------------------
1 file changed, 19 insertions(+), 33 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 705399a..f9e8235 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -95,47 +95,33 @@ static int getsigctxno(int flag, int bandno)
((flag & JPEG2000_T1_SIG_NW) ? 1 : 0) +
((flag & JPEG2000_T1_SIG_SE) ? 1 : 0) +
((flag & JPEG2000_T1_SIG_SW) ? 1 : 0);
- if (bandno < 3) {
+
+ if (bandno < 3){
if (bandno == 1)
FFSWAP(int, h, v);
- if (h == 2)
- return 8;
- if (h == 1) {
- if (v >= 1)
- return 7;
- if (d >= 1)
- return 6;
+ if (h == 2) return 8;
+ if (h == 1){
+ if (v >= 1) return 7;
+ if (d >= 1) return 6;
return 5;
}
- if (v == 2)
- return 4;
- if (v == 1)
- return 3;
- if (d >= 2)
- return 2;
- if (d == 1)
- return 1;
- return 0;
- } else {
- if (d >= 3)
- return 8;
- if (d == 2) {
- if (h + v >= 1)
- return 7;
+ if (v == 2) return 4;
+ if (v == 1) return 3;
+ if (d >= 2) return 2;
+ if (d == 1) return 1;
+ } else{
+ if (d >= 3) return 8;
+ if (d == 2){
+ if (h+v >= 1) return 7;
return 6;
}
- if (d == 1) {
- if (h + v >= 2)
- return 5;
- if (h + v == 1)
- return 4;
+ if (d == 1){
+ if (h+v >= 2) return 5;
+ if (h+v == 1) return 4;
return 3;
}
- if (h + v >= 2)
- return 2;
- if (h + v == 1)
- return 1;
- return 0;
+ if (h+v >= 2) return 2;
+ if (h+v == 1) return 1;
}
return 0;
}
--
1.7.9.5
Luca Barbato
2013-06-21 14:16:43 UTC
Permalink
Fix the formatting please.

lu
Nicolas Bertrand
2013-06-21 13:26:52 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2kdec.c
---
libavcodec/jpeg2000dec.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 5620b5b..38f0512 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -60,7 +60,7 @@ typedef struct Jpeg2000Tile {
typedef struct Jpeg2000DecoderContext {
AVClass *class;
AVCodecContext *avctx;
- GetByteContext g;
+ GetByteContext g;

int width, height;
int image_offset_x, image_offset_y;
@@ -170,11 +170,11 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->tile_offset_y = bytestream2_get_be32u(&s->g); // YT0Siz
s->ncomponents = bytestream2_get_be16u(&s->g); // CSiz

- if(s->ncomponents <= 0 || s->ncomponents > 4) {
+ if (s->ncomponents <= 0 || s->ncomponents > 4) {
av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", s->ncomponents);
return AVERROR(EINVAL);
}
- if(s->tile_width<=0 || s->tile_height<=0)
+ if (s->tile_width<=0 || s->tile_height<=0)
return AVERROR(EINVAL);

if (bytestream2_get_bytes_left(&s->g) < 3 * s->ncomponents)
@@ -192,7 +192,7 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->numXtiles = ff_jpeg2000_ceildiv(s->width - s->tile_offset_x, s->tile_width);
s->numYtiles = ff_jpeg2000_ceildiv(s->height - s->tile_offset_y, s->tile_height);

- if(s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(Jpeg2000Tile))
+ if (s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(Jpeg2000Tile))
return AVERROR(EINVAL);

s->tile = av_mallocz(s->numXtiles * s->numYtiles * sizeof(*s->tile));
@@ -420,7 +420,7 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
return AVERROR(EINVAL);

s->curtileno = Isot = bytestream2_get_be16u(&s->g); // Isot
- if((unsigned)s->curtileno >= s->numXtiles * s->numYtiles){
+ if ((unsigned)s->curtileno >= s->numXtiles * s->numYtiles) {
s->curtileno=0;
return AVERROR(EINVAL);
}
@@ -1243,7 +1243,7 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s)
uint32_t atom_size, atom;
int found_codestream = 0, search_range = 10;

- while(!found_codestream && search_range && bytestream2_get_bytes_left(&s->g) >= 8) {
+ while (!found_codestream && search_range && bytestream2_get_bytes_left(&s->g) >= 8) {
atom_size = bytestream2_get_be32u(&s->g);
atom = bytestream2_get_be32u(&s->g);
if (atom == JP2_CODESTREAM) {
--
1.7.9.5
Luca Barbato
2013-06-21 14:17:17 UTC
Permalink
No, fold it with the patches above.
Nicolas Bertrand
2013-06-21 13:26:53 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
---
libavcodec/jpeg2000.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index f9e8235..90efca9 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -96,11 +96,11 @@ static int getsigctxno(int flag, int bandno)
((flag & JPEG2000_T1_SIG_SE) ? 1 : 0) +
((flag & JPEG2000_T1_SIG_SW) ? 1 : 0);

- if (bandno < 3){
+ if (bandno < 3) {
if (bandno == 1)
FFSWAP(int, h, v);
if (h == 2) return 8;
- if (h == 1){
+ if (h == 1) {
if (v >= 1) return 7;
if (d >= 1) return 6;
return 5;
@@ -111,11 +111,11 @@ static int getsigctxno(int flag, int bandno)
if (d == 1) return 1;
} else{
if (d >= 3) return 8;
- if (d == 2){
+ if (d == 2) {
if (h+v >= 1) return 7;
return 6;
}
- if (d == 1){
+ if (d == 1) {
if (h+v >= 2) return 5;
if (h+v == 1) return 4;
return 3;
--
1.7.9.5
Luca Barbato
2013-06-21 14:17:39 UTC
Permalink
No.
Nicolas Bertrand
2013-06-21 13:26:54 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This is based on j2k FCD which is ambigous thus the limit
might be tighter.

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2kdec.c
---
libavcodec/jpeg2000dec.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 38f0512..5546fa4 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -263,8 +263,14 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
else
c->nreslevels2decode = c->nreslevels - s->reduction_factor;

- c->log2_cblk_width = bytestream2_get_byteu(&s->g) + 2; // cblk width
- c->log2_cblk_height = bytestream2_get_byteu(&s->g) + 2; // cblk height
+ c->log2_cblk_width = (bytestream2_get_byteu(&s->g) & 15) + 2; // cblk width
+ c->log2_cblk_height = (bytestream2_get_byteu(&s->g) & 15) + 2; // cblk height
+
+ if (c->log2_cblk_width > 10 || c->log2_cblk_height > 10 ||
+ c->log2_cblk_width + c->log2_cblk_height > 14) {
+ av_log(s->avctx, AV_LOG_ERROR, "cblk size invalid\n");
+ return AVERROR_INVALIDDATA;
+ }

c->cblk_style = bytestream2_get_byteu(&s->g);
if (c->cblk_style != 0) { // cblk style
--
1.7.9.5
Luca Barbato
2013-06-21 14:18:13 UTC
Permalink
Post by Nicolas Bertrand
This is based on j2k FCD which is ambigous thus the limit
might be tighter.
Rework the commit message.
Nicolas Bertrand
2013-06-21 13:26:55 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This also changes the cblk size storage method to what jpeg2000 uses

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
libavcodec/j2k.h
libavcodec/j2kdec.c
libavcodec/j2kenc.c
---
libavcodec/jpeg2000.h | 2 --
libavcodec/jpeg2000dec.c | 10 +++++++---
2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index 1e46f07..946f908 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -134,8 +134,6 @@ typedef struct Jpeg2000CodingStyle {
log2_cblk_height; // exponent of codeblock size
uint8_t transform; // DWT type
uint8_t csty; // coding style
- uint8_t log2_prec_width,
- log2_prec_height; // precinct size
uint8_t nlayers; // number of layers
uint8_t mct; // multiple component transformation
uint8_t cblk_style; // codeblock coding style
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 5546fa4..e1be5a0 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -256,6 +256,10 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
if (bytestream2_get_bytes_left(&s->g) < 5)
return AVERROR(EINVAL);
c->nreslevels = bytestream2_get_byteu(&s->g) + 1; // num of resolution levels - 1
+ if (c->nreslevels >= JPEG2000_MAX_RESLEVELS) {
+ av_log(s->avctx, AV_LOG_ERROR, "nreslevels %d is invalid\n", c->nreslevels);
+ return AVERROR_INVALIDDATA;
+ }

/* compute number of resolution levels to decode */
if (c->nreslevels < s->reduction_factor)
@@ -289,6 +293,9 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
c->log2_prec_widths[i] = byte & 0x0F; // precinct PPx
c->log2_prec_heights[i] = (byte >> 4) & 0x0F; // precinct PPy
}
+ } else {
+ memset(c->log2_prec_widths , 15, sizeof(c->log2_prec_widths ));
+ memset(c->log2_prec_heights, 15, sizeof(c->log2_prec_heights));
}
return 0;
}
@@ -303,9 +310,6 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
if (bytestream2_get_bytes_left(&s->g) < 5)
return AVERROR(EINVAL);

- tmp.log2_prec_width =
- tmp.log2_prec_height = 15;
-
tmp.csty = bytestream2_get_byteu(&s->g);

// get progression order
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:26:56 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.h
---
libavcodec/jpeg2000.h | 1 -
1 file changed, 1 deletion(-)

diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index 946f908..c1f88f4 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -182,7 +182,6 @@ typedef struct Jpeg2000Prec {
typedef struct Jpeg2000Band {
uint16_t coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
uint16_t log2_cblk_width, log2_cblk_height;
- uint16_t cblknx, cblkny;
float stepsize; // quantization stepsize
Jpeg2000Prec *prec;
} Jpeg2000Band; // subband
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:26:57 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
---
libavcodec/jpeg2000.c | 10 ++++++++++
libavcodec/jpeg2000dec.c | 8 --------
2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 90efca9..230a836 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -426,6 +426,16 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
/* Compute Cy1 */
cblk->coord[1][1] = FFMIN(Cy0 + (1 << band->log2_cblk_height),
prec->coord[1][1]);
+
+ if((bandno + !!reslevelno) & 1) {
+ cblk->coord[0][0] += comp->reslevel[reslevelno-1].coord[0][1] - comp->reslevel[reslevelno-1].coord[0][0];
+ cblk->coord[0][1] += comp->reslevel[reslevelno-1].coord[0][1] - comp->reslevel[reslevelno-1].coord[0][0];
+ }
+ if((bandno + !!reslevelno) & 2) {
+ cblk->coord[1][0] += comp->reslevel[reslevelno-1].coord[1][1] - comp->reslevel[reslevelno-1].coord[1][0];
+ cblk->coord[1][1] += comp->reslevel[reslevelno-1].coord[1][1] - comp->reslevel[reslevelno-1].coord[1][0];
+ }
+
cblk->zero = 0;
cblk->lblock = 3;
cblk->length = 0;
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index e1be5a0..84a0711 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1062,14 +1062,6 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
/* Manage band offsets */
x = cblk->coord[0][0];
y = cblk->coord[1][0];
- if ((reslevelno > 0) && ((bandno + 1) & 1)) {
- Jpeg2000ResLevel *pres = comp->reslevel + (reslevelno - 1);
- x += pres->coord[0][1] - pres->coord[0][0];
- }
- if ((reslevelno > 0) && ((bandno + 1) & 2)) {
- Jpeg2000ResLevel *pres = comp->reslevel + (reslevelno - 1);
- y += pres->coord[1][1] - pres->coord[1][0];
- }

if (s->avctx->flags & CODEC_FLAG_BITEXACT)
dequantization_int(x, y, cblk, comp, &t1, band);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:26:58 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
libavcodec/j2k.h
libavcodec/j2kenc.c
---
libavcodec/jpeg2000.h | 1 -
libavcodec/jpeg2000dec.c | 2 --
2 files changed, 3 deletions(-)

diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index c1f88f4..78a6e17 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -168,7 +168,6 @@ typedef struct Jpeg2000Cblk {
} Jpeg2000Cblk; // code block

typedef struct Jpeg2000Prec {
- uint16_t xi0, yi0; // codeblock indexes ([xi0, xi1))
uint16_t nb_codeblocks_width;
uint16_t nb_codeblocks_height;
Jpeg2000TgtNode *zerobits;
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 84a0711..9e21186 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -605,8 +605,6 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
if (band->coord[0][0] == band->coord[0][1] ||
band->coord[1][0] == band->coord[1][1])
continue;
- prec->yi0 = 0;
- prec->xi0 = 0;
nb_code_blocks = prec->nb_codeblocks_height *
prec->nb_codeblocks_width;
for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:26:59 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
---
libavcodec/jpeg2000.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 230a836..1d8726a 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -109,7 +109,7 @@ static int getsigctxno(int flag, int bandno)
if (v == 1) return 3;
if (d >= 2) return 2;
if (d == 1) return 1;
- } else{
+ } else {
if (d >= 3) return 8;
if (d == 2) {
if (h+v >= 1) return 7;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:00 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
libavcodec/j2k.h
libavcodec/j2kdec.c
libavcodec/j2kenc.c
---
libavcodec/jpeg2000.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 1d8726a..cbbd805 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -267,15 +267,15 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
int numbps;
case JPEG2000_QSTY_NONE:
/* TODO: to verify. No quantization in this case */
+ band->stepsize = (float) (1 << 13);
+ break;
+ case JPEG2000_QSTY_SI:
+ /*TODO: Compute formula to implement. */
numbps = cbps +
lut_gain[codsty->transform][bandno + reslevelno > 0];
band->stepsize = (float)SHL(2048 + qntsty->mant[gbandno],
2 + numbps - qntsty->expn[gbandno]);
break;
- case JPEG2000_QSTY_SI:
- /*TODO: Compute formula to implement. */
- band->stepsize = (float) (1 << 13);
- break;
case JPEG2000_QSTY_SE:
/* Exponent quantization step.
* Formula:
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:01 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/Makefile
libavcodec/j2k.c
libavcodec/j2k.h
libavcodec/j2kdec.c
libavcodec/j2kenc.c
tests/ref/vsynth/vsynth1-j2k-97
tests/ref/vsynth/vsynth2-j2k-97
---
libavcodec/jpeg2000dwt.c | 151 +++++++++++++++++++++++++++++++++++++++++++++-
libavcodec/jpeg2000dwt.h | 1 +
2 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c
index 0601e5a..2e8fedd 100644
--- a/libavcodec/jpeg2000dwt.c
+++ b/libavcodec/jpeg2000dwt.c
@@ -51,7 +51,6 @@
#define I_LFTG_K 80621
#define I_LFTG_X 106544

-
static inline void extend53(int *p, int i0, int i1)
{
p[i0 - 1] = p[i0 + 1];
@@ -80,6 +79,143 @@ static inline void extend97_int(int32_t *p, int i0, int i1)
}
}

+static void sd_1d53(int *p, int i0, int i1)
+{
+ int i;
+
+ if (i1 == i0 + 1)
+ return;
+
+ extend53(p, i0, i1);
+
+ for (i = (i0+1)/2 - 1; i < (i1+1)/2; i++)
+ p[2*i+1] -= (p[2*i] + p[2*i+2]) >> 1;
+ for (i = (i0+1)/2; i < (i1+1)/2; i++)
+ p[2*i] += (p[2*i-1] + p[2*i+1] + 2) >> 2;
+}
+
+static void dwt_encode53(DWTContext *s, int *t)
+{
+ int lev,
+ w = s->linelen[s->ndeclevels-1][0];
+ int *line = s->i_linebuf;
+ line += 3;
+
+ for (lev = s->ndeclevels-1; lev >= 0; lev--){
+ int lh = s->linelen[lev][0],
+ lv = s->linelen[lev][1],
+ mh = s->mod[lev][0],
+ mv = s->mod[lev][1],
+ lp;
+ int *l;
+
+ // HOR_SD
+ l = line + mh;
+ for (lp = 0; lp < lv; lp++){
+ int i, j = 0;
+
+ for (i = 0; i < lh; i++)
+ l[i] = t[w*lp + i];
+
+ sd_1d53(line, mh, mh + lh);
+
+ // copy back and deinterleave
+ for (i = mh; i < lh; i+=2, j++)
+ t[w*lp + j] = l[i];
+ for (i = 1-mh; i < lh; i+=2, j++)
+ t[w*lp + j] = l[i];
+ }
+
+ // VER_SD
+ l = line + mv;
+ for (lp = 0; lp < lh; lp++) {
+ int i, j = 0;
+
+ for (i = 0; i < lv; i++)
+ l[i] = t[w*i + lp];
+
+ sd_1d53(line, mv, mv + lv);
+
+ // copy back and deinterleave
+ for (i = mv; i < lv; i+=2, j++)
+ t[w*j + lp] = l[i];
+ for (i = 1-mv; i < lv; i+=2, j++)
+ t[w*j + lp] = l[i];
+ }
+ }
+}
+
+static void sd_1d97(float *p, int i0, int i1)
+{
+ int i;
+
+ if (i1 == i0 + 1)
+ return;
+
+ extend97_float(p, i0, i1);
+ i0++; i1++;
+
+ for (i = i0/2 - 2; i < i1/2 + 1; i++)
+ p[2*i+1] -= 1.586134 * (p[2*i] + p[2*i+2]);
+ for (i = i0/2 - 1; i < i1/2 + 1; i++)
+ p[2*i] -= 0.052980 * (p[2*i-1] + p[2*i+1]);
+ for (i = i0/2 - 1; i < i1/2; i++)
+ p[2*i+1] += 0.882911 * (p[2*i] + p[2*i+2]);
+ for (i = i0/2; i < i1/2; i++)
+ p[2*i] += 0.443506 * (p[2*i-1] + p[2*i+1]);
+}
+
+static void dwt_encode97_int(DWTContext *s, int *t)
+{
+ int lev,
+ w = s->linelen[s->ndeclevels-1][0];
+ float *line = s->i_linebuf;
+ line += 5;
+
+ for (lev = s->ndeclevels-1; lev >= 0; lev--){
+ int lh = s->linelen[lev][0],
+ lv = s->linelen[lev][1],
+ mh = s->mod[lev][0],
+ mv = s->mod[lev][1],
+ lp;
+ float *l;
+
+ // HOR_SD
+ l = line + mh;
+ for (lp = 0; lp < lv; lp++){
+ int i, j = 0;
+
+ for (i = 0; i < lh; i++)
+ l[i] = t[w*lp + i];
+
+ sd_1d97(line, mh, mh + lh);
+
+ // copy back and deinterleave
+ for (i = mh; i < lh; i+=2, j++)
+ t[w*lp + j] = F_LFTG_X * l[i] / 2;
+ for (i = 1-mh; i < lh; i+=2, j++)
+ t[w*lp + j] = F_LFTG_K * l[i] / 2;
+ }
+
+ // VER_SD
+ l = line + mv;
+ for (lp = 0; lp < lh; lp++) {
+ int i, j = 0;
+
+ for (i = 0; i < lv; i++)
+ l[i] = t[w*i + lp];
+
+ sd_1d97(line, mv, mv + lv);
+
+ // copy back and deinterleave
+ for (i = mv; i < lv; i+=2, j++)
+ t[w*j + lp] = F_LFTG_X * l[i] / 2;
+ for (i = 1-mv; i < lv; i+=2, j++)
+ t[w*j + lp] = F_LFTG_K * l[i] / 2;
+ }
+ }
+}
+
static void sr_1d53(int *p, int i0, int i1)
{
int i;
@@ -346,6 +482,19 @@ int ff_jpeg2000_dwt_init(DWTContext *s, uint16_t border[2][2],
return 0;
}

+int ff_dwt_encode(DWTContext *s, int *t)
+{
+ switch(s->type){
+ case FF_DWT97_INT:
+ dwt_encode97_int(s, t); break;
+ case FF_DWT53:
+ dwt_encode53(s, t); break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
int ff_dwt_decode(DWTContext *s, void *t)
{
switch (s->type) {
diff --git a/libavcodec/jpeg2000dwt.h b/libavcodec/jpeg2000dwt.h
index 9aaa18b..9e889f1 100644
--- a/libavcodec/jpeg2000dwt.h
+++ b/libavcodec/jpeg2000dwt.h
@@ -57,6 +57,7 @@ typedef struct DWTContext {
int ff_jpeg2000_dwt_init(DWTContext *s, uint16_t border[2][2],
int decomp_levels, int type);

+int ff_dwt_encode(DWTContext *s, int *t);
int ff_dwt_decode(DWTContext *s, void *t);

void ff_dwt_destroy(DWTContext *s);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:03 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This also fixes lowres use with ffplay

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
libavcodec/j2k.h
libavcodec/j2kdec.c
libavcodec/j2kenc.c
---
libavcodec/jpeg2000dec.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 9e21186..3e377bf 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -543,12 +543,10 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno)
comp->coord_o[1][0] = FFMAX(tiley * s->tile_height + s->tile_offset_y, s->image_offset_y);
comp->coord_o[1][1] = FFMIN((tiley + 1) * s->tile_height + s->tile_offset_y, s->height);

- // FIXME: add a dcinema profile check ?
- // value is guaranteed by profile (orig=0, 1 tile)
- comp->coord[0][0] = 0;
- comp->coord[0][1] = s->avctx->width;
- comp->coord[1][0] = 0;
- comp->coord[1][1] = s->avctx->height;
+ comp->coord[0][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], s->reduction_factor);
+ comp->coord[0][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[0][1], s->reduction_factor);
+ comp->coord[1][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], s->reduction_factor);
+ comp->coord[1][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][1], s->reduction_factor);

if (ret = ff_jpeg2000_init_component(comp, codsty, qntsty,
s->cbps[compno], s->cdx[compno],
@@ -1367,5 +1365,6 @@ AVCodec ff_jpeg2000_decoder = {
.pix_fmts = (enum AVPixelFormat[]) { AV_PIX_FMT_XYZ12,
AV_PIX_FMT_GRAY8,
-1 },
+ .max_lowres = 5,
.profiles = NULL_IF_CONFIG_SMALL(profiles)
};
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:04 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This should fix some fate failures

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

tests/ref/vsynth/vsynth1-j2k-97
tests/ref/vsynth/vsynth2-j2k-97
---
libavcodec/jpeg2000dwt.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c
index 2e8fedd..e4125e3 100644
--- a/libavcodec/jpeg2000dwt.c
+++ b/libavcodec/jpeg2000dwt.c
@@ -145,31 +145,31 @@ static void dwt_encode53(DWTContext *s, int *t)
}
}

-static void sd_1d97(float *p, int i0, int i1)
+static void sd_1d97_int(int *p, int i0, int i1)
{
int i;

if (i1 == i0 + 1)
return;

- extend97_float(p, i0, i1);
+ extend97_int(p, i0, i1);
i0++; i1++;

for (i = i0/2 - 2; i < i1/2 + 1; i++)
- p[2*i+1] -= 1.586134 * (p[2*i] + p[2*i+2]);
+ p[2 * i + 1] -= (I_LFTG_ALPHA * (p[2 * i] + p[2 * i + 2]) + (1 << 15)) >> 16;
for (i = i0/2 - 1; i < i1/2 + 1; i++)
- p[2*i] -= 0.052980 * (p[2*i-1] + p[2*i+1]);
+ p[2 * i] -= (I_LFTG_BETA * (p[2 * i - 1] + p[2 * i + 1]) + (1 << 15)) >> 16;
for (i = i0/2 - 1; i < i1/2; i++)
- p[2*i+1] += 0.882911 * (p[2*i] + p[2*i+2]);
+ p[2 * i + 1] += (I_LFTG_GAMMA * (p[2 * i] + p[2 * i + 2]) + (1 << 15)) >> 16;
for (i = i0/2; i < i1/2; i++)
- p[2*i] += 0.443506 * (p[2*i-1] + p[2*i+1]);
+ p[2 * i] += (I_LFTG_DELTA * (p[2 * i - 1] + p[2 * i + 1]) + (1 << 15)) >> 16;
}

static void dwt_encode97_int(DWTContext *s, int *t)
{
int lev,
w = s->linelen[s->ndeclevels-1][0];
- float *line = s->i_linebuf;
+ int *line = s->i_linebuf;
line += 5;

for (lev = s->ndeclevels-1; lev >= 0; lev--){
@@ -178,7 +178,7 @@ static void dwt_encode97_int(DWTContext *s, int *t)
mh = s->mod[lev][0],
mv = s->mod[lev][1],
lp;
- float *l;
+ int *l;

// HOR_SD
l = line + mh;
@@ -188,13 +188,13 @@ static void dwt_encode97_int(DWTContext *s, int *t)
for (i = 0; i < lh; i++)
l[i] = t[w*lp + i];

- sd_1d97(line, mh, mh + lh);
+ sd_1d97_int(line, mh, mh + lh);

// copy back and deinterleave
for (i = mh; i < lh; i+=2, j++)
- t[w*lp + j] = F_LFTG_X * l[i] / 2;
+ t[w*lp + j] = ((l[i] * I_LFTG_X) + (1 << 16)) >> 17;
for (i = 1-mh; i < lh; i+=2, j++)
- t[w*lp + j] = F_LFTG_K * l[i] / 2;
+ t[w*lp + j] = ((l[i] * I_LFTG_K) + (1 << 16)) >> 17;
}

// VER_SD
@@ -205,13 +205,13 @@ static void dwt_encode97_int(DWTContext *s, int *t)
for (i = 0; i < lv; i++)
l[i] = t[w*i + lp];

- sd_1d97(line, mv, mv + lv);
+ sd_1d97_int(line, mv, mv + lv);

// copy back and deinterleave
for (i = mv; i < lv; i+=2, j++)
- t[w*j + lp] = F_LFTG_X * l[i] / 2;
+ t[w*j + lp] = ((l[i] * I_LFTG_X) + (1 << 16)) >> 17;
for (i = 1-mv; i < lv; i+=2, j++)
- t[w*j + lp] = F_LFTG_K * l[i] / 2;
+ t[w*j + lp] = ((l[i] * I_LFTG_K) + (1 << 16)) >> 17;
}
}
}
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:02 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

mant fits in 16bit

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index 78a6e17..5f15db1 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -144,7 +144,7 @@ typedef struct Jpeg2000CodingStyle {

typedef struct Jpeg2000QuantStyle {
uint8_t expn[32 * 3]; // quantization exponent
- uint32_t mant[32 * 3]; // quantization mantissa
+ uint16_t mant[32 * 3]; // quantization mantissa
uint8_t quantsty; // quantization style
uint8_t nguardbits; // number of guard bits
} Jpeg2000QuantStyle;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:05 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Untested as theres no code yet using it in the encoder.
Code based on mixed float/int dwt

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dwt.c | 74 +++++++++++++++++++++++++++++++++++++++++++++-
libavcodec/jpeg2000dwt.h | 2 +-
2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c
index e4125e3..d5bcf9d 100644
--- a/libavcodec/jpeg2000dwt.c
+++ b/libavcodec/jpeg2000dwt.c
@@ -144,6 +144,76 @@ static void dwt_encode53(DWTContext *s, int *t)
}
}
}
+static void sd_1d97_float(float *p, int i0, int i1)
+{
+ int i;
+
+ if (i1 == i0 + 1)
+ return;
+
+ extend97_float(p, i0, i1);
+ i0++; i1++;
+
+ for (i = i0/2 - 2; i < i1/2 + 1; i++)
+ p[2*i+1] -= 1.586134 * (p[2*i] + p[2*i+2]);
+ for (i = i0/2 - 1; i < i1/2 + 1; i++)
+ p[2*i] -= 0.052980 * (p[2*i-1] + p[2*i+1]);
+ for (i = i0/2 - 1; i < i1/2; i++)
+ p[2*i+1] += 0.882911 * (p[2*i] + p[2*i+2]);
+ for (i = i0/2; i < i1/2; i++)
+ p[2*i] += 0.443506 * (p[2*i-1] + p[2*i+1]);
+}
+
+static void dwt_encode97_float(DWTContext *s, float *t)
+{
+ int lev,
+ w = s->linelen[s->ndeclevels-1][0];
+ float *line = s->f_linebuf;
+ line += 5;
+
+ for (lev = s->ndeclevels-1; lev >= 0; lev--){
+ int lh = s->linelen[lev][0],
+ lv = s->linelen[lev][1],
+ mh = s->mod[lev][0],
+ mv = s->mod[lev][1],
+ lp;
+ float *l;
+
+ // HOR_SD
+ l = line + mh;
+ for (lp = 0; lp < lv; lp++){
+ int i, j = 0;
+
+ for (i = 0; i < lh; i++)
+ l[i] = t[w*lp + i];
+
+ sd_1d97_float(line, mh, mh + lh);
+
+ // copy back and deinterleave
+ for (i = mh; i < lh; i+=2, j++)
+ t[w*lp + j] = F_LFTG_X * l[i] / 2;
+ for (i = 1-mh; i < lh; i+=2, j++)
+ t[w*lp + j] = F_LFTG_K * l[i] / 2;
+ }
+
+ // VER_SD
+ l = line + mv;
+ for (lp = 0; lp < lh; lp++) {
+ int i, j = 0;
+
+ for (i = 0; i < lv; i++)
+ l[i] = t[w*i + lp];
+
+ sd_1d97_float(line, mv, mv + lv);
+
+ // copy back and deinterleave
+ for (i = mv; i < lv; i+=2, j++)
+ t[w*j + lp] = F_LFTG_X * l[i] / 2;
+ for (i = 1-mv; i < lv; i+=2, j++)
+ t[w*j + lp] = F_LFTG_K * l[i] / 2;
+ }
+ }
+}

static void sd_1d97_int(int *p, int i0, int i1)
{
@@ -482,9 +552,11 @@ int ff_jpeg2000_dwt_init(DWTContext *s, uint16_t border[2][2],
return 0;
}

-int ff_dwt_encode(DWTContext *s, int *t)
+int ff_dwt_encode(DWTContext *s, void *t)
{
switch(s->type){
+ case FF_DWT97:
+ dwt_encode97_float(s, t); break;
case FF_DWT97_INT:
dwt_encode97_int(s, t); break;
case FF_DWT53:
diff --git a/libavcodec/jpeg2000dwt.h b/libavcodec/jpeg2000dwt.h
index 9e889f1..8976db0 100644
--- a/libavcodec/jpeg2000dwt.h
+++ b/libavcodec/jpeg2000dwt.h
@@ -57,7 +57,7 @@ typedef struct DWTContext {
int ff_jpeg2000_dwt_init(DWTContext *s, uint16_t border[2][2],
int decomp_levels, int type);

-int ff_dwt_encode(DWTContext *s, int *t);
+int ff_dwt_encode(DWTContext *s, void *t);
int ff_dwt_decode(DWTContext *s, void *t);

void ff_dwt_destroy(DWTContext *s);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:06 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

The quantization code needs more work, not so much work
merging but more work investigating what is correct.

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
libavcodec/j2kdec.c
tests/ref/vsynth/vsynth1-j2k
tests/ref/vsynth/vsynth1-j2k-97
tests/ref/vsynth/vsynth2-j2k
tests/ref/vsynth/vsynth2-j2k-97
---
libavcodec/jpeg2000.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index cbbd805..f098554 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -288,15 +288,15 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
gain = cbps;
band->stepsize = pow(2.0, gain - qntsty->expn[gbandno]);
band->stepsize *= (float)qntsty->mant[gbandno] / 2048.0 + 1.0;
- /* FIXME: In openjepg code stespize = stepsize * 0.5. Why?
- * If not set output of entropic decoder is not correct. */
- band->stepsize *= 0.5;
break;
default:
band->stepsize = 0;
av_log(avctx, AV_LOG_ERROR, "Unknown quantization format\n");
break;
}
+ /* FIXME: In openjepg code stespize = stepsize * 0.5. Why?
+ * If not set output of entropic decoder is not correct. */
+ band->stepsize *= 0.5;
/* BITEXACT computing case --> convert to int */
if (avctx->flags & CODEC_FLAG_BITEXACT)
band->stepsize = (int32_t)(band->stepsize * (1 << 16));
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:07 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

no testcase

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
---
libavcodec/jpeg2000.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index f098554..ec372c5 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -272,7 +272,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
case JPEG2000_QSTY_SI:
/*TODO: Compute formula to implement. */
numbps = cbps +
- lut_gain[codsty->transform][bandno + reslevelno > 0];
+ lut_gain[codsty->transform][bandno + (reslevelno > 0)];
band->stepsize = (float)SHL(2048 + qntsty->mant[gbandno],
2 + numbps - qntsty->expn[gbandno]);
break;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:08 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 3e377bf..b9583f8 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -931,7 +931,6 @@ static void dequantization_float(int x, int y, Jpeg2000Cblk *cblk,
idx = (comp->coord[0][1] - comp->coord[0][0]) * j + i;
datap[idx] = (float)(t1->data[j][i]) * ((float)band->stepsize);
}
- return;
}

/* Integer dequantization of a codeblock.*/
@@ -948,7 +947,6 @@ static void dequantization_int(int x, int y, Jpeg2000Cblk *cblk,
datap[idx] =
((int32_t)(t1->data[j][i]) * ((int32_t)band->stepsize) + (1 << 15)) >> 16;
}
- return;
}

/* Inverse ICT parameters in float and integer.
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:09 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This is more clear and less prone to mistakes.

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
libavcodec/j2k.h
libavcodec/j2kdec.c
libavcodec/j2kenc.c
---
libavcodec/jpeg2000.c | 18 +++++++++---------
libavcodec/jpeg2000.h | 5 ++---
libavcodec/jpeg2000dec.c | 4 ++--
3 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index ec372c5..57242d8 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -267,13 +267,13 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
int numbps;
case JPEG2000_QSTY_NONE:
/* TODO: to verify. No quantization in this case */
- band->stepsize = (float) (1 << 13);
+ band->f_stepsize = (float) (1 << 13);
break;
case JPEG2000_QSTY_SI:
/*TODO: Compute formula to implement. */
numbps = cbps +
lut_gain[codsty->transform][bandno + (reslevelno > 0)];
- band->stepsize = (float)SHL(2048 + qntsty->mant[gbandno],
+ band->f_stepsize = (float)SHL(2048 + qntsty->mant[gbandno],
2 + numbps - qntsty->expn[gbandno]);
break;
case JPEG2000_QSTY_SE:
@@ -286,20 +286,20 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
* but it works (compared to OpenJPEG). Why?
* Further investigation needed. */
gain = cbps;
- band->stepsize = pow(2.0, gain - qntsty->expn[gbandno]);
- band->stepsize *= (float)qntsty->mant[gbandno] / 2048.0 + 1.0;
+ band->f_stepsize = pow(2.0, gain - qntsty->expn[gbandno]);
+ band->f_stepsize *= (float)qntsty->mant[gbandno] / 2048.0 + 1.0;
break;
default:
- band->stepsize = 0;
+ band->f_stepsize = 0;
av_log(avctx, AV_LOG_ERROR, "Unknown quantization format\n");
break;
}
/* FIXME: In openjepg code stespize = stepsize * 0.5. Why?
* If not set output of entropic decoder is not correct. */
- band->stepsize *= 0.5;
- /* BITEXACT computing case --> convert to int */
- if (avctx->flags & CODEC_FLAG_BITEXACT)
- band->stepsize = (int32_t)(band->stepsize * (1 << 16));
+ if (!av_codec_is_encoder(avctx->codec))
+ band->f_stepsize *= 0.5;
+
+ band->i_stepsize = (int32_t)(band->f_stepsize * (1 << 16));

/* computation of tbx_0, tbx_1, tby_0, tby_1
* see ISO/IEC 15444-1:2002 B.5 eq. B-15 and tbl B.1
diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index 5f15db1..d78ed56 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -176,12 +176,11 @@ typedef struct Jpeg2000Prec {
uint16_t coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
} Jpeg2000Prec; // precinct

-/* TODO: stepsize can be float or integer depending on
- * reversible or irreversible transformation. */
typedef struct Jpeg2000Band {
uint16_t coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
uint16_t log2_cblk_width, log2_cblk_height;
- float stepsize; // quantization stepsize
+ int i_stepsize; // quantization stepsize
+ float f_stepsize; // quantization stepsize
Jpeg2000Prec *prec;
} Jpeg2000Band; // subband

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index b9583f8..37266cf 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -929,7 +929,7 @@ static void dequantization_float(int x, int y, Jpeg2000Cblk *cblk,
for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j)
for (i = 0; i < (cblk->coord[0][1] - cblk->coord[0][0]); ++i) {
idx = (comp->coord[0][1] - comp->coord[0][0]) * j + i;
- datap[idx] = (float)(t1->data[j][i]) * ((float)band->stepsize);
+ datap[idx] = (float)(t1->data[j][i]) * band->f_stepsize;
}
}

@@ -945,7 +945,7 @@ static void dequantization_int(int x, int y, Jpeg2000Cblk *cblk,
for (i = 0; i < (cblk->coord[0][1] - cblk->coord[0][0]); ++i) {
idx = (comp->coord[0][1] - comp->coord[0][0]) * j + i;
datap[idx] =
- ((int32_t)(t1->data[j][i]) * ((int32_t)band->stepsize) + (1 << 15)) >> 16;
+ ((int32_t)(t1->data[j][i]) * band->i_stepsize + (1 << 15)) >> 16;
}
}
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:10 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 37266cf..6440f45 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -964,10 +964,9 @@ static const int i_ict_params[4] = {
116130
};

-static int mct_decode(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
+static void mct_decode(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
{
int i, csize = 1;
- int ret = 0;
int32_t *src[3], i0, i1, i2;
float *srcf[3], i0f, i1f, i2f;

@@ -1013,7 +1012,6 @@ static int mct_decode(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
}
break;
}
- return ret;
}

static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:11 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

the float conditions are largely changed to check the DWT
instead of the bitexact flag, which previously was wrong
(DWT53 is always int)

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
libavcodec/j2kdec.c
libavcodec/j2kenc.c
---
libavcodec/jpeg2000dec.c | 35 ++++++++++++++++++++---------------
1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 6440f45..9d40a4e 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1055,10 +1055,10 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
x = cblk->coord[0][0];
y = cblk->coord[1][0];

- if (s->avctx->flags & CODEC_FLAG_BITEXACT)
- dequantization_int(x, y, cblk, comp, &t1, band);
- else
+ if (codsty->transform == FF_DWT97)
dequantization_float(x, y, cblk, comp, &t1, band);
+ else
+ dequantization_int(x, y, cblk, comp, &t1, band);
} /* end cblk */
} /*end prec */
} /* end band */
@@ -1078,7 +1078,8 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
if (s->precision <= 8) {
for (compno = 0; compno < s->ncomponents; compno++) {
Jpeg2000Component *comp = tile->comp + compno;
- int32_t *datap = (int32_t *)comp->data;
+ float *datap = comp->data;
+ int32_t *i_datap = (int32_t *) comp->data;
y = tile->comp[compno].coord[1][0] - s->image_offset_y;
line = picture->data[0] + y * picture->linesize[0];
for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]) {
@@ -1088,12 +1089,16 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
dst = line + x * s->ncomponents + compno;

for (; x < tile->comp[compno].coord[0][1] - s->image_offset_x; x += s->cdx[compno]) {
- *datap += 1 << (s->cbps[compno] - 1);
- if (*datap < 0)
- *datap = 0;
- else if (*datap >= (1 << s->cbps[compno]))
- *datap = (1 << s->cbps[compno]) - 1;
- *dst = *datap++;
+ int val;
+ /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
+ if (tile->codsty->transform == FF_DWT97)
+ val = lrintf(*datap) + (1 << (s->cbps[compno] - 1));
+ else
+ val = *i_datap + (1 << (s->cbps[compno] - 1));
+ val = av_clip(val, 0, (1 << s->cbps[compno]) - 1);
+ *dst = val << (8 - s->cbps[compno]);
+ datap++;
+ i_datap++;
dst += s->ncomponents;
}
line += picture->linesize[0];
@@ -1113,15 +1118,15 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
x = tile->comp[compno].coord[0][0] - s->image_offset_x;
dst = linel + (x * s->ncomponents + compno);
for (; x < s->avctx->width; x += s->cdx[compno]) {
- int16_t val;
+ int val;
/* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
- if (s->avctx->flags & CODEC_FLAG_BITEXACT)
- val = *i_datap + (1 << (s->cbps[compno] - 1));
- else
+ if (tile->codsty->transform == FF_DWT97)
val = lrintf(*datap) + (1 << (s->cbps[compno] - 1));
+ else
+ val = *i_datap + (1 << (s->cbps[compno] - 1));
val = av_clip(val, 0, (1 << s->cbps[compno]) - 1);
/* align 12 bit values in little-endian mode */
- *dst = val << 4;
+ *dst = val << (16 - s->cbps[compno]);
datap++;
i_datap++;
dst += s->ncomponents;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:12 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This fixes a TODO item and unifies both decoders structures
It also fixes undefined behavior due to aliasing violations

I choose 2 fields instead of a union because mistakely using the
wrong type with a union will lead to hard to debug "wrong output"
while with 2 fields mistakely using the wrong type will crash
with a null pointer derefernce which is much easier to debug

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2k.c
libavcodec/j2k.h
libavcodec/j2kdec.c
libavcodec/j2kenc.c
---
libavcodec/jpeg2000.c | 17 +++++++++++++----
libavcodec/jpeg2000.h | 6 ++----
libavcodec/jpeg2000dec.c | 25 +++++++++++++------------
3 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 57242d8..12acfe3 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -200,9 +200,17 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
csize = (comp->coord[0][1] - comp->coord[0][0]) *
(comp->coord[1][1] - comp->coord[1][0]);

- comp->data = av_malloc_array(csize, sizeof(*comp->data));
- if (!comp->data)
- return AVERROR(ENOMEM);
+ if (codsty->transform == FF_DWT97) {
+ comp->i_data = NULL;
+ comp->f_data = av_malloc_array(csize, sizeof(*comp->f_data));
+ if (!comp->f_data)
+ return AVERROR(ENOMEM);
+ } else {
+ comp->f_data = NULL;
+ comp->i_data = av_malloc_array(csize, sizeof(*comp->i_data));
+ if (!comp->i_data)
+ return AVERROR(ENOMEM);
+ }
comp->reslevel = av_malloc_array(codsty->nreslevels, sizeof(*comp->reslevel));
if (!comp->reslevel)
return AVERROR(ENOMEM);
@@ -470,5 +478,6 @@ void ff_jpeg2000_cleanup(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty)

ff_dwt_destroy(&comp->dwt);
av_freep(&comp->reslevel);
- av_freep(&comp->data);
+ av_freep(&comp->i_data);
+ av_freep(&comp->f_data);
}
diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index d78ed56..bf0a824 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -192,13 +192,11 @@ typedef struct Jpeg2000ResLevel {
Jpeg2000Band *band;
} Jpeg2000ResLevel; // resolution level

-/* TODO: data can be float of integer depending of reversible/irreversible
- * transformation.
- */
typedef struct Jpeg2000Component {
Jpeg2000ResLevel *reslevel;
DWTContext dwt;
- float *data;
+ float *f_data;
+ int *i_data;
uint16_t coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} -- can be reduced with lowres option
uint16_t coord_o[2][2]; // border coordinates {{x0, x1}, {y0, y1}} -- original values from jpeg2000 headers
} Jpeg2000Component;
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 9d40a4e..3e32b02 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -925,7 +925,7 @@ static void dequantization_float(int x, int y, Jpeg2000Cblk *cblk,
Jpeg2000T1Context *t1, Jpeg2000Band *band)
{
int i, j, idx;
- float *datap = &comp->data[(comp->coord[0][1] - comp->coord[0][0]) * y + x];
+ float *datap = &comp->f_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x];
for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j)
for (i = 0; i < (cblk->coord[0][1] - cblk->coord[0][0]); ++i) {
idx = (comp->coord[0][1] - comp->coord[0][0]) * j + i;
@@ -939,8 +939,7 @@ static void dequantization_int(int x, int y, Jpeg2000Cblk *cblk,
Jpeg2000T1Context *t1, Jpeg2000Band *band)
{
int i, j, idx;
- int32_t *datap =
- (int32_t *) &comp->data[(comp->coord[0][1] - comp->coord[0][0]) * y + x];
+ int32_t *datap = &comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x];
for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j)
for (i = 0; i < (cblk->coord[0][1] - cblk->coord[0][0]); ++i) {
idx = (comp->coord[0][1] - comp->coord[0][0]) * j + i;
@@ -972,9 +971,9 @@ static void mct_decode(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)

for (i = 0; i < 3; i++)
if (tile->codsty[0].transform == FF_DWT97)
- srcf[i] = tile->comp[i].data;
+ srcf[i] = tile->comp[i].f_data;
else
- src[i] = (int32_t *)tile->comp[i].data;
+ src [i] = tile->comp[i].i_data;

for (i = 0; i < 2; i++)
csize *= tile->comp[0].coord[i][1] - tile->comp[0].coord[i][0];
@@ -1065,21 +1064,23 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
} /* end reslevel */

/* inverse DWT */
- ff_dwt_decode(&comp->dwt, comp->data);
+ ff_dwt_decode(&comp->dwt, codsty->transform == FF_DWT97 ? (void*)comp->f_data : (void*)comp->i_data);
} /*end comp */

/* inverse MCT transformation */
if (tile->codsty[0].mct)
mct_decode(s, tile);

- if (s->avctx->pix_fmt == AV_PIX_FMT_BGRA) // RGBA -> BGRA
- FFSWAP(float *, tile->comp[0].data, tile->comp[2].data);
+ if (s->avctx->pix_fmt == AV_PIX_FMT_BGRA) { // RGBA -> BGRA
+ FFSWAP(float *, tile->comp[0].f_data, tile->comp[2].f_data);
+ FFSWAP(int *, tile->comp[0].i_data, tile->comp[2].i_data);
+ }

if (s->precision <= 8) {
for (compno = 0; compno < s->ncomponents; compno++) {
Jpeg2000Component *comp = tile->comp + compno;
- float *datap = comp->data;
- int32_t *i_datap = (int32_t *) comp->data;
+ float *datap = comp->f_data;
+ int32_t *i_datap = comp->i_data;
y = tile->comp[compno].coord[1][0] - s->image_offset_y;
line = picture->data[0] + y * picture->linesize[0];
for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]) {
@@ -1107,8 +1108,8 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
} else {
for (compno = 0; compno < s->ncomponents; compno++) {
Jpeg2000Component *comp = tile->comp + compno;
- float *datap = comp->data;
- int32_t *i_datap = (int32_t *) comp->data;
+ float *datap = comp->f_data;
+ int32_t *i_datap = comp->i_data;
uint16_t *linel;

y = tile->comp[compno].coord[1][0] - s->image_offset_y;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:13 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This function is never called with values large enough for the
error condition to occur

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 12acfe3..73e4189 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -25,6 +25,7 @@
* JPEG 2000 image encoder and decoder common functions
*/

+#include "libavutil/avassert.h"
#include "libavutil/common.h"
#include "libavutil/mem.h"
#include "avcodec.h"
@@ -40,8 +41,7 @@ static int32_t tag_tree_size(uint16_t w, uint16_t h)
uint32_t res = 0;
while (w > 1 || h > 1) {
res += w * h;
- if (res + 1 >= INT32_MAX)
- return -1;
+ av_assert0(res + 1 < INT32_MAX);
w = (w + 1) >> 1;
h = (h + 1) >> 1;
}
@@ -55,8 +55,6 @@ static Jpeg2000TgtNode *ff_jpeg2000_tag_tree_init(int w, int h)
int32_t tt_size;

tt_size = tag_tree_size(w, h);
- if (tt_size == -1)
- return NULL;

t = res = av_mallocz_array(tt_size, sizeof(*t));
if (!res)
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:14 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 73e4189..37bcc04 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -188,7 +188,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
{
uint8_t log2_band_prec_width, log2_band_prec_height;
int reslevelno, bandno, gbandno = 0, ret, i, j;
- uint32_t csize = 1;
+ uint32_t csize;

if (ret = ff_jpeg2000_dwt_init(&comp->dwt, comp->coord,
codsty->nreslevels2decode - 1,
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:15 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 37bcc04..3a97fa9 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -273,12 +273,12 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
int numbps;
case JPEG2000_QSTY_NONE:
/* TODO: to verify. No quantization in this case */
- band->f_stepsize = (float) (1 << 13);
+ band->f_stepsize = 1;
break;
case JPEG2000_QSTY_SI:
/*TODO: Compute formula to implement. */
numbps = cbps +
- lut_gain[codsty->transform][bandno + (reslevelno > 0)];
+ lut_gain[codsty->transform == FF_DWT53][bandno + (reslevelno > 0)];
band->f_stepsize = (float)SHL(2048 + qntsty->mant[gbandno],
2 + numbps - qntsty->expn[gbandno]);
break;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:16 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 3a97fa9..75dccfc 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -279,7 +279,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
/*TODO: Compute formula to implement. */
numbps = cbps +
lut_gain[codsty->transform == FF_DWT53][bandno + (reslevelno > 0)];
- band->f_stepsize = (float)SHL(2048 + qntsty->mant[gbandno],
+ band->f_stepsize = SHL(2048 + qntsty->mant[gbandno],
2 + numbps - qntsty->expn[gbandno]);
break;
case JPEG2000_QSTY_SE:
@@ -293,7 +293,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
* Further investigation needed. */
gain = cbps;
band->f_stepsize = pow(2.0, gain - qntsty->expn[gbandno]);
- band->f_stepsize *= (float)qntsty->mant[gbandno] / 2048.0 + 1.0;
+ band->f_stepsize *= qntsty->mant[gbandno] / 2048.0 + 1.0;
break;
default:
band->f_stepsize = 0;
@@ -305,7 +305,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
if (!av_codec_is_encoder(avctx->codec))
band->f_stepsize *= 0.5;

- band->i_stepsize = (int32_t)(band->f_stepsize * (1 << 16));
+ band->i_stepsize = band->f_stepsize * (1 << 16);

/* computation of tbx_0, tbx_1, tby_0, tby_1
* see ISO/IEC 15444-1:2002 B.5 eq. B-15 and tbl B.1
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:17 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Now only j2kdec / jpeg2000dec.c remain

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/Makefile
libavcodec/j2kdec.c
libavcodec/j2kenc.c
---
libavcodec/jpeg2000.c | 41 ++++++++++++++++++++++++++++++++++++++---
libavcodec/jpeg2000.h | 2 ++
2 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 75dccfc..6a3e9f6 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -79,6 +79,16 @@ static Jpeg2000TgtNode *ff_jpeg2000_tag_tree_init(int w, int h)
return res;
}

+static void tag_tree_zero(Jpeg2000TgtNode *t, int w, int h)
+{
+ int i, siz = tag_tree_size(w, h);
+
+ for (i = 0; i < siz; i++) {
+ t[i].val = 0;
+ t[i].vis = 0;
+ }
+}
+
uint8_t ff_jpeg2000_sigctxno_lut[256][4];

static int getsigctxno(int flag, int bandno)
@@ -316,9 +326,8 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
band->coord[i][j] =
- ff_jpeg2000_ceildivpow2(comp->coord_o[i][j],
+ ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - comp->coord_o[i][0],
declvl - 1);
-
log2_band_prec_width = reslevel->log2_prec_width;
log2_band_prec_height = reslevel->log2_prec_height;
/* see ISO/IEC 15444-1:2002 eq. B-17 and eq. B-15 */
@@ -333,7 +342,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
for (j = 0; j < 2; j++)
/* Formula example for tbx_0 = ceildiv((tcx_0 - 2 ^ (declvl - 1) * x0_b) / declvl) */
band->coord[i][j] =
- ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] -
+ ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - comp->coord_o[i][0] -
(((bandno + 1 >> i) & 1) << declvl - 1),
declvl);
/* TODO: Manage case of 3 band offsets here or
@@ -349,6 +358,11 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
log2_band_prec_height = reslevel->log2_prec_height - 1;
}

+ for (j = 0; j < 2; j++)
+ band->coord[0][j] = ff_jpeg2000_ceildiv(band->coord[0][j], dx);
+ for (j = 0; j < 2; j++)
+ band->coord[1][j] = ff_jpeg2000_ceildiv(band->coord[1][j], dy);
+
band->prec = av_malloc_array(reslevel->num_precincts_x *
reslevel->num_precincts_y,
sizeof(*band->prec));
@@ -454,6 +468,27 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
return 0;
}

+void ff_jpeg2000_reinit(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty)
+{
+ int reslevelno, bandno, cblkno, precno;
+ for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) {
+ Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
+ for (bandno = 0; bandno < rlevel->nbands; bandno++) {
+ Jpeg2000Band *band = rlevel->band + bandno;
+ for(precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++) {
+ Jpeg2000Prec *prec = band->prec + precno;
+ tag_tree_zero(prec->zerobits, prec->nb_codeblocks_width, prec->nb_codeblocks_height);
+ tag_tree_zero(prec->cblkincl, prec->nb_codeblocks_width, prec->nb_codeblocks_height);
+ for (cblkno = 0; cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height; cblkno++) {
+ Jpeg2000Cblk *cblk = prec->cblk + cblkno;
+ cblk->length = 0;
+ cblk->lblock = 3;
+ }
+ }
+ }
+ }
+}
+
void ff_jpeg2000_cleanup(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty)
{
int reslevelno, bandno, precno;
diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index bf0a824..ea68d41 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -256,6 +256,8 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
int cbps, int dx, int dy,
AVCodecContext *ctx);

+void ff_jpeg2000_reinit(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty);
+
void ff_jpeg2000_cleanup(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty);

#endif /* AVCODEC_JPEG2000_H */
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:18 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2kdec.c
---
libavcodec/jpeg2000dec.c | 42 ++++++++++++++++++++----------------------
1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 3e32b02..52e95a6 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -213,37 +213,35 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->avctx->height = ff_jpeg2000_ceildivpow2(s->height - s->image_offset_y,
s->reduction_factor);

- switch (s->avctx->profile) {
- case FF_PROFILE_JPEG2000_DCINEMA_2K:
- case FF_PROFILE_JPEG2000_DCINEMA_4K:
- /* XYZ color-space for digital cinema profiles */
- s->avctx->pix_fmt = AV_PIX_FMT_XYZ12;
+ switch(s->ncomponents) {
+ case 1:
+ if (s->precision > 8)
+ s->avctx->pix_fmt = AV_PIX_FMT_GRAY16;
+ else
+ s->avctx->pix_fmt = AV_PIX_FMT_GRAY8;
break;
- default:
- /* For other profiles selects color-space according number of
- * components and bit depth precision. */
- switch (s->ncomponents) {
- case 1:
- if (s->precision > 8)
- s->avctx->pix_fmt = AV_PIX_FMT_GRAY16;
- else
- s->avctx->pix_fmt = AV_PIX_FMT_GRAY8;
+ case 3:
+ switch (s->avctx->profile) {
+ case FF_PROFILE_JPEG2000_DCINEMA_2K:
+ case FF_PROFILE_JPEG2000_DCINEMA_4K:
+ /* XYZ color-space for digital cinema profiles */
+ s->avctx->pix_fmt = AV_PIX_FMT_XYZ12;
break;
- case 3:
+ default:
if (s->precision > 8)
s->avctx->pix_fmt = AV_PIX_FMT_RGB48;
else
s->avctx->pix_fmt = AV_PIX_FMT_RGB24;
break;
- case 4:
- s->avctx->pix_fmt = AV_PIX_FMT_BGRA;
- break;
- default:
- /* pixel format can not be identified */
- s->avctx->pix_fmt = AV_PIX_FMT_NONE;
- break;
}
break;
+ case 4:
+ s->avctx->pix_fmt = AV_PIX_FMT_RGBA;
+ break;
+ default:
+ /* pixel format can not be identified */
+ s->avctx->pix_fmt = AV_PIX_FMT_NONE;
+ break;
}
return 0;
}
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:19 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This should no longer be needed as the pix fmt was updated

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 5 -----
1 file changed, 5 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 52e95a6..1c78f9b 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1069,11 +1069,6 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
if (tile->codsty[0].mct)
mct_decode(s, tile);

- if (s->avctx->pix_fmt == AV_PIX_FMT_BGRA) { // RGBA -> BGRA
- FFSWAP(float *, tile->comp[0].f_data, tile->comp[2].f_data);
- FFSWAP(int *, tile->comp[0].i_data, tile->comp[2].i_data);
- }
-
if (s->precision <= 8) {
for (compno = 0; compno < s->ncomponents; compno++) {
Jpeg2000Component *comp = tile->comp + compno;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:20 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2kdec.c
---
libavcodec/jpeg2000dec.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 1c78f9b..65b63e1 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -601,6 +601,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
if (band->coord[0][0] == band->coord[0][1] ||
band->coord[1][0] == band->coord[1][1])
continue;
+
nb_code_blocks = prec->nb_codeblocks_height *
prec->nb_codeblocks_width;
for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {
@@ -1019,8 +1020,8 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,

uint8_t *line;
Jpeg2000T1Context t1;
- /* Loop on tile components */

+ /* Loop on tile components */
for (compno = 0; compno < s->ncomponents; compno++) {
Jpeg2000Component *comp = tile->comp + compno;
Jpeg2000CodingStyle *codsty = tile->codsty + compno;
@@ -1074,6 +1075,7 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
Jpeg2000Component *comp = tile->comp + compno;
float *datap = comp->f_data;
int32_t *i_datap = comp->i_data;
+
y = tile->comp[compno].coord[1][0] - s->image_offset_y;
line = picture->data[0] + y * picture->linesize[0];
for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]) {
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:21 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 65b63e1..3d78016 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -518,8 +518,6 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno)
int tilex = tileno % s->numXtiles;
int tiley = tileno / s->numXtiles;
Jpeg2000Tile *tile = s->tile + tileno;
- Jpeg2000CodingStyle *codsty;
- Jpeg2000QuantStyle *qntsty;

if (!tile->comp)
return AVERROR(ENOMEM);
@@ -527,14 +525,14 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno)
/* copy codsty, qnsty to tile. TODO: Is it the best way?
* codsty, qnsty is an array of 4 structs Jpeg2000CodingStyle
* and Jpeg2000QuantStyle */
- memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(*codsty));
- memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(*qntsty));
+ memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(*tile->codsty));
+ memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(*tile->qntsty));

for (compno = 0; compno < s->ncomponents; compno++) {
Jpeg2000Component *comp = tile->comp + compno;
+ Jpeg2000CodingStyle *codsty = tile->codsty + compno;
+ Jpeg2000QuantStyle *qntsty = tile->qntsty + compno;
int ret; // global bandno
- codsty = tile->codsty + compno;
- qntsty = tile->qntsty + compno;

comp->coord_o[0][0] = FFMAX(tilex * s->tile_width + s->tile_offset_x, s->image_offset_x);
comp->coord_o[0][1] = FFMIN((tilex + 1) * s->tile_width + s->tile_offset_x, s->width);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:22 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 3d78016..899a34f 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -883,9 +883,9 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty,
for (y = 0; y < height + 2; y++)
memset(t1->flags[y], 0, (width + 2) * sizeof(width));

- ff_mqc_initdec(&t1->mqc, cblk->data);
cblk->data[cblk->length] = 0xff;
cblk->data[cblk->length + 1] = 0xff;
+ ff_mqc_initdec(&t1->mqc, cblk->data);

while (passno--) {
switch (pass_t) {
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:23 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2kdec.c
libavcodec/jpeg2000dec.c
---
libavcodec/jpeg2000dec.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 899a34f..2ba1fb3 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -876,12 +876,13 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty,
int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1, y;

for (y = 0; y < height; y++)
- memset(t1->data[y], 0, width * sizeof(width));
+ memset(t1->data[y], 0, width * sizeof(**t1->data));
+
/* If code-block contains no compressed data: nothing to do. */
if (!cblk->length)
return 0;
for (y = 0; y < height + 2; y++)
- memset(t1->flags[y], 0, (width + 2) * sizeof(width));
+ memset(t1->flags[y], 0, (width + 2) * sizeof(**t1->flags));

cblk->data[cblk->length] = 0xff;
cblk->data[cblk->length + 1] = 0xff;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:24 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/j2kdec.c
---
libavcodec/jpeg2000dec.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 2ba1fb3..38a2d30 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -975,6 +975,7 @@ static void mct_decode(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)

for (i = 0; i < 2; i++)
csize *= tile->comp[0].coord[i][1] - tile->comp[0].coord[i][0];
+
switch (tile->codsty[0].transform) {
case FF_DWT97:
for (i = 0; i < csize; i++) {
@@ -1024,12 +1025,13 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
for (compno = 0; compno < s->ncomponents; compno++) {
Jpeg2000Component *comp = tile->comp + compno;
Jpeg2000CodingStyle *codsty = tile->codsty + compno;
+
/* Loop on resolution levels */
for (reslevelno = 0; reslevelno < codsty->nreslevels2decode; reslevelno++) {
Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
/* Loop on bands */
for (bandno = 0; bandno < rlevel->nbands; bandno++) {
- uint16_t nb_precincts, precno;
+ int nb_precincts, precno;
Jpeg2000Band *band = rlevel->band + bandno;
int cblkno = 0, bandpos;
bandpos = bandno + (reslevelno > 0);
@@ -1110,6 +1112,7 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
linel = (uint16_t *)picture->data[0] + y * (picture->linesize[0] >> 1);
for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]) {
uint16_t *dst;
+
x = tile->comp[compno].coord[0][0] - s->image_offset_x;
dst = linel + (x * s->ncomponents + compno);
for (; x < s->avctx->width; x += s->cdx[compno]) {
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:25 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes AVOption type mismatch

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 38a2d30..4f7ffd7 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -80,12 +80,13 @@ typedef struct Jpeg2000DecoderContext {

int bit_index;

- int16_t curtileno;
+ int curtileno;
+
Jpeg2000Tile *tile;

/*options parameters*/
- int16_t lowres;
- int16_t reduction_factor;
+ int lowres;
+ int reduction_factor;
} Jpeg2000DecoderContext;

/* get_bits functions for JPEG2000 packet bitstream
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:26 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 4f7ffd7..623cb11 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -185,7 +185,7 @@ static int get_siz(Jpeg2000DecoderContext *s)
uint8_t x = bytestream2_get_byteu(&s->g);
s->cbps[i] = (x & 0x7f) + 1;
s->precision = FFMAX(s->cbps[i], s->precision);
- s->sgnd[i] = (x & 0x80) == 1;
+ s->sgnd[i] = !!(x & 0x80);
s->cdx[i] = bytestream2_get_byteu(&s->g);
s->cdy[i] = bytestream2_get_byteu(&s->g);
}
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:27 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 623cb11..f3ca020 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -669,12 +669,10 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
{
int layno, reslevelno, compno, precno, ok_reslevel;
- uint8_t prog_order = tile->codsty[0].prog_order;
- uint16_t x;
- uint16_t y;
+ int x, y;

s->bit_index = 8;
- switch (prog_order) {
+ switch (tile->codsty[0].prog_order) {
case JPEG2000_PGOD_LRCP:
for (layno = 0; layno < tile->codsty[0].nlayers; layno++) {
ok_reslevel = 1;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:28 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>

Conflicts:

libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/j2kenc.c
libavcodec/jpeg2000dec.c
tests/fate/vcodec.mak
---
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 2 +-
libavcodec/j2kenc.c | 1056 ++++++++++++++++++++++++++++++++++
libavcodec/jpeg2000.c | 2 +-
libavcodec/jpeg2000dec.c | 189 +++---
tests/fate/vcodec.mak | 6 +
tests/ref/vsynth/vsynth1-jpeg2000 | 4 +
tests/ref/vsynth/vsynth1-jpeg2000-97 | 4 +
tests/ref/vsynth/vsynth2-jpeg2000 | 4 +
tests/ref/vsynth/vsynth2-jpeg2000-97 | 4 +
10 files changed, 1189 insertions(+), 83 deletions(-)
create mode 100644 libavcodec/j2kenc.c
create mode 100644 tests/ref/vsynth/vsynth1-jpeg2000
create mode 100644 tests/ref/vsynth/vsynth1-jpeg2000-97
create mode 100644 tests/ref/vsynth/vsynth2-jpeg2000
create mode 100644 tests/ref/vsynth/vsynth2-jpeg2000-97

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index d9c6e33..e9af72d 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -208,6 +208,7 @@ OBJS-$(CONFIG_INDEO4_DECODER) += indeo4.o ivi_common.o ivi_dsp.o
OBJS-$(CONFIG_INDEO5_DECODER) += indeo5.o ivi_common.o ivi_dsp.o
OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER) += dpcm.o
OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o
+OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o jpeg2000.o
OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o \
jpeg2000dwt.o mqcdec.o mqc.o
OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o \
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 6bfc042..650bd9d 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -163,7 +163,7 @@ void avcodec_register_all(void)
REGISTER_DECODER(INDEO4, indeo4);
REGISTER_DECODER(INDEO5, indeo5);
REGISTER_DECODER(INTERPLAY_VIDEO, interplay_video);
- REGISTER_DECODER(JPEG2000, jpeg2000);
+ REGISTER_ENCDEC (JPEG2000, jpeg2000);
REGISTER_ENCDEC (JPEGLS, jpegls);
REGISTER_DECODER(JV, jv);
REGISTER_DECODER(KGV1, kgv1);
diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
new file mode 100644
index 0000000..e4c84ef
--- /dev/null
+++ b/libavcodec/j2kenc.c
@@ -0,0 +1,1056 @@
+/*
+ * JPEG2000 image encoder
+ * Copyright (c) 2007 Kamil Nowosad
+ *
+ * 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
+ */
+
+/**
+ * JPEG2000 image encoder
+ * @file
+ * @author Kamil Nowosad
+ */
+
+#include <float.h>
+#include "avcodec.h"
+#include "internal.h"
+#include "bytestream.h"
+#include "jpeg2000.h"
+#include "libavutil/common.h"
+
+#define NMSEDEC_BITS 7
+#define NMSEDEC_FRACBITS (NMSEDEC_BITS-1)
+#define WMSEDEC_SHIFT 13 ///< must be >= 13
+#define LAMBDA_SCALE (100000000LL << (WMSEDEC_SHIFT - 13))
+
+static int lut_nmsedec_ref [1<<NMSEDEC_BITS],
+ lut_nmsedec_ref0[1<<NMSEDEC_BITS],
+ lut_nmsedec_sig [1<<NMSEDEC_BITS],
+ lut_nmsedec_sig0[1<<NMSEDEC_BITS];
+
+static const int dwt_norms[2][4][10] = { // [dwt_type][band][rlevel] (multiplied by 10000)
+ {{10000, 19650, 41770, 84030, 169000, 338400, 676900, 1353000, 2706000, 5409000},
+ {20220, 39890, 83550, 170400, 342700, 686300, 1373000, 2746000, 5490000},
+ {20220, 39890, 83550, 170400, 342700, 686300, 1373000, 2746000, 5490000},
+ {20800, 38650, 83070, 171800, 347100, 695900, 1393000, 2786000, 5572000}},
+
+ {{10000, 15000, 27500, 53750, 106800, 213400, 426700, 853300, 1707000, 3413000},
+ {10380, 15920, 29190, 57030, 113300, 226400, 452500, 904800, 1809000},
+ {10380, 15920, 29190, 57030, 113300, 226400, 452500, 904800, 1809000},
+ { 7186, 9218, 15860, 30430, 60190, 120100, 240000, 479700, 959300}}
+};
+
+typedef struct {
+ Jpeg2000Component *comp;
+} Jpeg2000Tile;
+
+typedef struct {
+ AVCodecContext *avctx;
+ AVFrame picture;
+
+ int width, height; ///< image width and height
+ uint8_t cbps[4]; ///< bits per sample in particular components
+ int chroma_shift[2];
+ uint8_t planar;
+ int ncomponents;
+ int tile_width, tile_height; ///< tile size
+ int numXtiles, numYtiles;
+
+ uint8_t *buf_start;
+ uint8_t *buf;
+ uint8_t *buf_end;
+ int bit_index;
+
+ int64_t lambda;
+
+ Jpeg2000CodingStyle codsty;
+ Jpeg2000QuantStyle qntsty;
+
+ Jpeg2000Tile *tile;
+} Jpeg2000EncoderContext;
+
+
+/* debug */
+#if 0
+#undef ifprintf
+#undef printf
+
+static void nspaces(FILE *fd, int n)
+{
+ while(n--) putc(' ', fd);
+}
+
+static void printcomp(Jpeg2000Component *comp)
+{
+ int i;
+ for (i = 0; i < comp->y1 - comp->y0; i++)
+ ff_jpeg2000_printv(comp->i_data + i * (comp->x1 - comp->x0), comp->x1 - comp->x0);
+}
+
+static void dump(Jpeg2000EncoderContext *s, FILE *fd)
+{
+ int tileno, compno, reslevelno, bandno, precno;
+ fprintf(fd, "XSiz = %d, YSiz = %d, tile_width = %d, tile_height = %d\n"
+ "numXtiles = %d, numYtiles = %d, ncomponents = %d\n"
+ "tiles:\n",
+ s->width, s->height, s->tile_width, s->tile_height,
+ s->numXtiles, s->numYtiles, s->ncomponents);
+ for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
+ Jpeg2000Tile *tile = s->tile + tileno;
+ nspaces(fd, 2);
+ fprintf(fd, "tile %d:\n", tileno);
+ for(compno = 0; compno < s->ncomponents; compno++){
+ Jpeg2000Component *comp = tile->comp + compno;
+ nspaces(fd, 4);
+ fprintf(fd, "component %d:\n", compno);
+ nspaces(fd, 4);
+ fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d\n",
+ comp->x0, comp->x1, comp->y0, comp->y1);
+ for(reslevelno = 0; reslevelno < s->nreslevels; reslevelno++){
+ Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
+ nspaces(fd, 6);
+ fprintf(fd, "reslevel %d:\n", reslevelno);
+ nspaces(fd, 6);
+ fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d, nbands = %d\n",
+ reslevel->x0, reslevel->x1, reslevel->y0,
+ reslevel->y1, reslevel->nbands);
+ for(bandno = 0; bandno < reslevel->nbands; bandno++){
+ Jpeg2000Band *band = reslevel->band + bandno;
+ nspaces(fd, 8);
+ fprintf(fd, "band %d:\n", bandno);
+ nspaces(fd, 8);
+ fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d,"
+ "codeblock_width = %d, codeblock_height = %d cblknx = %d cblkny = %d\n",
+ band->x0, band->x1,
+ band->y0, band->y1,
+ band->codeblock_width, band->codeblock_height,
+ band->cblknx, band->cblkny);
+ for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){
+ Jpeg2000Prec *prec = band->prec + precno;
+ nspaces(fd, 10);
+ fprintf(fd, "prec %d:\n", precno);
+ nspaces(fd, 10);
+ fprintf(fd, "xi0 = %d, xi1 = %d, yi0 = %d, yi1 = %d\n",
+ prec->xi0, prec->xi1, prec->yi0, prec->yi1);
+ }
+ }
+ }
+ }
+ }
+}
+#endif
+
+/* bitstream routines */
+
+/** put n times val bit */
+static void put_bits(Jpeg2000EncoderContext *s, int val, int n) // TODO: optimize
+{
+ while (n-- > 0){
+ if (s->bit_index == 8)
+ {
+ s->bit_index = *s->buf == 0xff;
+ *(++s->buf) = 0;
+ }
+ *s->buf |= val << (7 - s->bit_index++);
+ }
+}
+
+/** put n least significant bits of a number num */
+static void put_num(Jpeg2000EncoderContext *s, int num, int n)
+{
+ while(--n >= 0)
+ put_bits(s, (num >> n) & 1, 1);
+}
+
+/** flush the bitstream */
+static void j2k_flush(Jpeg2000EncoderContext *s)
+{
+ if (s->bit_index){
+ s->bit_index = 0;
+ s->buf++;
+ }
+}
+
+/* tag tree routines */
+
+/** code the value stored in node */
+static void tag_tree_code(Jpeg2000EncoderContext *s, Jpeg2000TgtNode *node, int threshold)
+{
+ Jpeg2000TgtNode *stack[30];
+ int sp = 1, curval = 0;
+ stack[0] = node;
+
+ node = node->parent;
+ while(node){
+ if (node->vis){
+ curval = node->val;
+ break;
+ }
+ node->vis++;
+ stack[sp++] = node;
+ node = node->parent;
+ }
+ while(--sp >= 0){
+ if (stack[sp]->val >= threshold){
+ put_bits(s, 0, threshold - curval);
+ break;
+ }
+ put_bits(s, 0, stack[sp]->val - curval);
+ put_bits(s, 1, 1);
+ curval = stack[sp]->val;
+ }
+}
+
+/** update the value in node */
+static void tag_tree_update(Jpeg2000TgtNode *node)
+{
+ int lev = 0;
+ while (node->parent){
+ if (node->parent->val <= node->val)
+ break;
+ node->parent->val = node->val;
+ node = node->parent;
+ lev++;
+ }
+}
+
+static int put_siz(Jpeg2000EncoderContext *s)
+{
+ int i;
+
+ if (s->buf_end - s->buf < 40 + 3 * s->ncomponents)
+ return -1;
+
+ bytestream_put_be16(&s->buf, JPEG2000_SIZ);
+ bytestream_put_be16(&s->buf, 38 + 3 * s->ncomponents); // Lsiz
+ bytestream_put_be16(&s->buf, 0); // Rsiz
+ bytestream_put_be32(&s->buf, s->width); // width
+ bytestream_put_be32(&s->buf, s->height); // height
+ bytestream_put_be32(&s->buf, 0); // X0Siz
+ bytestream_put_be32(&s->buf, 0); // Y0Siz
+
+ bytestream_put_be32(&s->buf, s->tile_width); // XTSiz
+ bytestream_put_be32(&s->buf, s->tile_height); // YTSiz
+ bytestream_put_be32(&s->buf, 0); // XT0Siz
+ bytestream_put_be32(&s->buf, 0); // YT0Siz
+ bytestream_put_be16(&s->buf, s->ncomponents); // CSiz
+
+ for (i = 0; i < s->ncomponents; i++){ // Ssiz_i XRsiz_i, YRsiz_i
+ bytestream_put_byte(&s->buf, 7);
+ bytestream_put_byte(&s->buf, i?1<<s->chroma_shift[0]:1);
+ bytestream_put_byte(&s->buf, i?1<<s->chroma_shift[1]:1);
+ }
+ return 0;
+}
+
+static int put_cod(Jpeg2000EncoderContext *s)
+{
+ Jpeg2000CodingStyle *codsty = &s->codsty;
+
+ if (s->buf_end - s->buf < 14)
+ return -1;
+
+ bytestream_put_be16(&s->buf, JPEG2000_COD);
+ bytestream_put_be16(&s->buf, 12); // Lcod
+ bytestream_put_byte(&s->buf, 0); // Scod
+ // SGcod
+ bytestream_put_byte(&s->buf, 0); // progression level
+ bytestream_put_be16(&s->buf, 1); // num of layers
+ if(s->avctx->pix_fmt == AV_PIX_FMT_YUV444P){
+ bytestream_put_byte(&s->buf, 2); // ICT
+ }else{
+ bytestream_put_byte(&s->buf, 0); // unspecified
+ }
+ // SPcod
+ bytestream_put_byte(&s->buf, codsty->nreslevels - 1); // num of decomp. levels
+ bytestream_put_byte(&s->buf, codsty->log2_cblk_width-2); // cblk width
+ bytestream_put_byte(&s->buf, codsty->log2_cblk_height-2); // cblk height
+ bytestream_put_byte(&s->buf, 0); // cblk style
+ bytestream_put_byte(&s->buf, codsty->transform == FF_DWT53); // transformation
+ return 0;
+}
+
+static int put_qcd(Jpeg2000EncoderContext *s, int compno)
+{
+ int i, size;
+ Jpeg2000CodingStyle *codsty = &s->codsty;
+ Jpeg2000QuantStyle *qntsty = &s->qntsty;
+
+ if (qntsty->quantsty == JPEG2000_QSTY_NONE)
+ size = 4 + 3 * (codsty->nreslevels-1);
+ else // QSTY_SE
+ size = 5 + 6 * (codsty->nreslevels-1);
+
+ if (s->buf_end - s->buf < size + 2)
+ return -1;
+
+ bytestream_put_be16(&s->buf, JPEG2000_QCD);
+ bytestream_put_be16(&s->buf, size); // LQcd
+ bytestream_put_byte(&s->buf, (qntsty->nguardbits << 5) | qntsty->quantsty); // Sqcd
+ if (qntsty->quantsty == JPEG2000_QSTY_NONE)
+ for (i = 0; i < codsty->nreslevels * 3 - 2; i++)
+ bytestream_put_byte(&s->buf, qntsty->expn[i] << 3);
+ else // QSTY_SE
+ for (i = 0; i < codsty->nreslevels * 3 - 2; i++)
+ bytestream_put_be16(&s->buf, (qntsty->expn[i] << 11) | qntsty->mant[i]);
+ return 0;
+}
+
+static uint8_t *put_sot(Jpeg2000EncoderContext *s, int tileno)
+{
+ uint8_t *psotptr;
+
+ if (s->buf_end - s->buf < 12)
+ return NULL;
+
+ bytestream_put_be16(&s->buf, JPEG2000_SOT);
+ bytestream_put_be16(&s->buf, 10); // Lsot
+ bytestream_put_be16(&s->buf, tileno); // Isot
+
+ psotptr = s->buf;
+ bytestream_put_be32(&s->buf, 0); // Psot (filled in later)
+
+ bytestream_put_byte(&s->buf, 0); // TPsot
+ bytestream_put_byte(&s->buf, 1); // TNsot
+ return psotptr;
+}
+
+/**
+ * compute the sizes of tiles, resolution levels, bands, etc.
+ * allocate memory for them
+ * divide the input image into tile-components
+ */
+static int init_tiles(Jpeg2000EncoderContext *s)
+{
+ int tileno, tilex, tiley, compno;
+ Jpeg2000CodingStyle *codsty = &s->codsty;
+ Jpeg2000QuantStyle *qntsty = &s->qntsty;
+
+ s->numXtiles = ff_jpeg2000_ceildiv(s->width, s->tile_width);
+ s->numYtiles = ff_jpeg2000_ceildiv(s->height, s->tile_height);
+
+ s->tile = av_malloc(s->numXtiles * s->numYtiles * sizeof(Jpeg2000Tile));
+ if (!s->tile)
+ return AVERROR(ENOMEM);
+ for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++)
+ for (tilex = 0; tilex < s->numXtiles; tilex++, tileno++){
+ Jpeg2000Tile *tile = s->tile + tileno;
+
+ tile->comp = av_mallocz(s->ncomponents * sizeof(Jpeg2000Component));
+ if (!tile->comp)
+ return AVERROR(ENOMEM);
+ for (compno = 0; compno < s->ncomponents; compno++){
+ Jpeg2000Component *comp = tile->comp + compno;
+ int ret, i, j;
+
+ comp->coord[0][0] = comp->coord_o[0][0] = tilex * s->tile_width;
+ comp->coord[0][1] = comp->coord_o[0][1] = FFMIN((tilex+1)*s->tile_width, s->width);
+ comp->coord[1][0] = comp->coord_o[1][0] = tiley * s->tile_height;
+ comp->coord[1][1] = comp->coord_o[1][1] = FFMIN((tiley+1)*s->tile_height, s->height);
+ if (compno > 0)
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 2; j++)
+ comp->coord[i][j] = comp->coord_o[i][j] = ff_jpeg2000_ceildivpow2(comp->coord[i][j], s->chroma_shift[i]);
+
+ if (ret = ff_jpeg2000_init_component(comp,
+ codsty,
+ qntsty,
+ s->cbps[compno],
+ compno?1<<s->chroma_shift[0]:1,
+ compno?1<<s->chroma_shift[1]:1,
+ s->avctx
+ ))
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static void copy_frame(Jpeg2000EncoderContext *s)
+{
+ int tileno, compno, i, y, x;
+ uint8_t *line;
+ for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
+ Jpeg2000Tile *tile = s->tile + tileno;
+ if (s->planar){
+ for (compno = 0; compno < s->ncomponents; compno++){
+ Jpeg2000Component *comp = tile->comp + compno;
+ int *dst = comp->i_data;
+ line = s->picture.data[compno]
+ + comp->coord[1][0] * s->picture.linesize[compno]
+ + comp->coord[0][0];
+ for (y = comp->coord[1][0]; y < comp->coord[1][1]; y++){
+ uint8_t *ptr = line;
+ for (x = comp->coord[0][0]; x < comp->coord[0][1]; x++)
+ *dst++ = *ptr++ - (1 << 7);
+ line += s->picture.linesize[compno];
+ }
+ }
+ } else{
+ line = s->picture.data[0] + tile->comp[0].coord[1][0] * s->picture.linesize[0]
+ + tile->comp[0].coord[0][0] * s->ncomponents;
+
+ i = 0;
+ for (y = tile->comp[0].coord[1][0]; y < tile->comp[0].coord[1][1]; y++){
+ uint8_t *ptr = line;
+ for (x = tile->comp[0].coord[0][0]; x < tile->comp[0].coord[0][1]; x++, i++){
+ for (compno = 0; compno < s->ncomponents; compno++){
+ tile->comp[compno].i_data[i] = *ptr++ - (1 << 7);
+ }
+ }
+ line += s->picture.linesize[0];
+ }
+ }
+ }
+}
+
+static void init_quantization(Jpeg2000EncoderContext *s)
+{
+ int compno, reslevelno, bandno;
+ Jpeg2000QuantStyle *qntsty = &s->qntsty;
+ Jpeg2000CodingStyle *codsty = &s->codsty;
+
+ for (compno = 0; compno < s->ncomponents; compno++){
+ int gbandno = 0;
+ for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){
+ int nbands, lev = codsty->nreslevels - reslevelno - 1;
+ nbands = reslevelno ? 3 : 1;
+ for (bandno = 0; bandno < nbands; bandno++, gbandno++){
+ int expn, mant;
+
+ if (codsty->transform == FF_DWT97_INT){
+ int bandpos = bandno + (reslevelno>0),
+ ss = 81920000 / dwt_norms[0][bandpos][lev],
+ log = av_log2(ss);
+ mant = (11 - log < 0 ? ss >> log - 11 : ss << 11 - log) & 0x7ff;
+ expn = s->cbps[compno] - log + 13;
+ } else
+ expn = ((bandno&2)>>1) + (reslevelno>0) + s->cbps[compno];
+
+ qntsty->expn[gbandno] = expn;
+ qntsty->mant[gbandno] = mant;
+ }
+ }
+ }
+}
+
+static void init_luts(void)
+{
+ int i, a,
+ mask = ~((1<<NMSEDEC_FRACBITS)-1);
+
+ for (i = 0; i < (1 << NMSEDEC_BITS); i++){
+ lut_nmsedec_sig[i] = FFMAX(6*i - (9<<NMSEDEC_FRACBITS-1) << 12-NMSEDEC_FRACBITS, 0);
+ lut_nmsedec_sig0[i] = FFMAX((i*i + (1<<NMSEDEC_FRACBITS-1) & mask) << 1, 0);
+
+ a = (i >> (NMSEDEC_BITS-2)&2) + 1;
+ lut_nmsedec_ref[i] = FFMAX((-2*i + (1<<NMSEDEC_FRACBITS) + a*i - (a*a<<NMSEDEC_FRACBITS-2))
+ << 13-NMSEDEC_FRACBITS, 0);
+ lut_nmsedec_ref0[i] = FFMAX(((i*i + (1-4*i << NMSEDEC_FRACBITS-1) + (1<<2*NMSEDEC_FRACBITS)) & mask)
+ << 1, 0);
+ }
+}
+
+/* tier-1 routines */
+static int getnmsedec_sig(int x, int bpno)
+{
+ if (bpno > NMSEDEC_FRACBITS)
+ return lut_nmsedec_sig[(x >> (bpno - NMSEDEC_FRACBITS)) & ((1 << NMSEDEC_BITS) - 1)];
+ return lut_nmsedec_sig0[x & ((1 << NMSEDEC_BITS) - 1)];
+}
+
+static int getnmsedec_ref(int x, int bpno)
+{
+ if (bpno > NMSEDEC_FRACBITS)
+ return lut_nmsedec_ref[(x >> (bpno - NMSEDEC_FRACBITS)) & ((1 << NMSEDEC_BITS) - 1)];
+ return lut_nmsedec_ref0[x & ((1 << NMSEDEC_BITS) - 1)];
+}
+
+static void encode_sigpass(Jpeg2000T1Context *t1, int width, int height, int bandno, int *nmsedec, int bpno)
+{
+ int y0, x, y, mask = 1 << (bpno + NMSEDEC_FRACBITS);
+ for (y0 = 0; y0 < height; y0 += 4)
+ for (x = 0; x < width; x++)
+ for (y = y0; y < height && y < y0+4; y++){
+ if (!(t1->flags[y+1][x+1] & JPEG2000_T1_SIG) && (t1->flags[y+1][x+1] & JPEG2000_T1_SIG_NB)){
+ int ctxno = ff_jpeg2000_getsigctxno(t1->flags[y+1][x+1], bandno),
+ bit = t1->data[y][x] & mask ? 1 : 0;
+ ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, bit);
+ if (bit){
+ int xorbit;
+ int ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y+1][x+1], &xorbit);
+ ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, (t1->flags[y+1][x+1] >> 15) ^ xorbit);
+ *nmsedec += getnmsedec_sig(t1->data[y][x], bpno + NMSEDEC_FRACBITS);
+ ff_jpeg2000_set_significance(t1, x, y, t1->flags[y+1][x+1] >> 15);
+ }
+ t1->flags[y+1][x+1] |= JPEG2000_T1_VIS;
+ }
+ }
+}
+
+static void encode_refpass(Jpeg2000T1Context *t1, int width, int height, int *nmsedec, int bpno)
+{
+ int y0, x, y, mask = 1 << (bpno + NMSEDEC_FRACBITS);
+ for (y0 = 0; y0 < height; y0 += 4)
+ for (x = 0; x < width; x++)
+ for (y = y0; y < height && y < y0+4; y++)
+ if ((t1->flags[y+1][x+1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS)) == JPEG2000_T1_SIG){
+ int ctxno = ff_jpeg2000_getrefctxno(t1->flags[y+1][x+1]);
+ *nmsedec += getnmsedec_ref(t1->data[y][x], bpno + NMSEDEC_FRACBITS);
+ ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, t1->data[y][x] & mask ? 1:0);
+ t1->flags[y+1][x+1] |= JPEG2000_T1_REF;
+ }
+}
+
+static void encode_clnpass(Jpeg2000T1Context *t1, int width, int height, int bandno, int *nmsedec, int bpno)
+{
+ int y0, x, y, mask = 1 << (bpno + NMSEDEC_FRACBITS);
+ for (y0 = 0; y0 < height; y0 += 4)
+ for (x = 0; x < width; x++){
+ if (y0 + 3 < height && !(
+ (t1->flags[y0+1][x+1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) ||
+ (t1->flags[y0+2][x+1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) ||
+ (t1->flags[y0+3][x+1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) ||
+ (t1->flags[y0+4][x+1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG))))
+ {
+ // aggregation mode
+ int rlen;
+ for (rlen = 0; rlen < 4; rlen++)
+ if (t1->data[y0+rlen][x] & mask)
+ break;
+ ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + MQC_CX_RL, rlen != 4);
+ if (rlen == 4)
+ continue;
+ ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI, rlen >> 1);
+ ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI, rlen & 1);
+ for (y = y0 + rlen; y < y0 + 4; y++){
+ if (!(t1->flags[y+1][x+1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))){
+ int ctxno = ff_jpeg2000_getsigctxno(t1->flags[y+1][x+1], bandno);
+ if (y > y0 + rlen)
+ ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, t1->data[y][x] & mask ? 1:0);
+ if (t1->data[y][x] & mask){ // newly significant
+ int xorbit;
+ int ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y+1][x+1], &xorbit);
+ *nmsedec += getnmsedec_sig(t1->data[y][x], bpno + NMSEDEC_FRACBITS);
+ ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, (t1->flags[y+1][x+1] >> 15) ^ xorbit);
+ ff_jpeg2000_set_significance(t1, x, y, t1->flags[y+1][x+1] >> 15);
+ }
+ }
+ t1->flags[y+1][x+1] &= ~JPEG2000_T1_VIS;
+ }
+ } else{
+ for (y = y0; y < y0 + 4 && y < height; y++){
+ if (!(t1->flags[y+1][x+1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))){
+ int ctxno = ff_jpeg2000_getsigctxno(t1->flags[y+1][x+1], bandno);
+ ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, t1->data[y][x] & mask ? 1:0);
+ if (t1->data[y][x] & mask){ // newly significant
+ int xorbit;
+ int ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y+1][x+1], &xorbit);
+ *nmsedec += getnmsedec_sig(t1->data[y][x], bpno + NMSEDEC_FRACBITS);
+ ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, (t1->flags[y+1][x+1] >> 15) ^ xorbit);
+ ff_jpeg2000_set_significance(t1, x, y, t1->flags[y+1][x+1] >> 15);
+ }
+ }
+ t1->flags[y+1][x+1] &= ~JPEG2000_T1_VIS;
+ }
+ }
+ }
+}
+
+static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, Jpeg2000Tile *tile,
+ int width, int height, int bandpos, int lev)
+{
+ int pass_t = 2, passno, x, y, max=0, nmsedec, bpno;
+ int64_t wmsedec = 0;
+
+ for (y = 0; y < height+2; y++)
+ memset(t1->flags[y], 0, (width+2)*sizeof(int));
+
+ for (y = 0; y < height; y++){
+ for (x = 0; x < width; x++){
+ if (t1->data[y][x] < 0){
+ t1->flags[y+1][x+1] |= JPEG2000_T1_SGN;
+ t1->data[y][x] = -t1->data[y][x];
+ }
+ max = FFMAX(max, t1->data[y][x]);
+ }
+ }
+
+ if (max == 0){
+ cblk->nonzerobits = 0;
+ bpno = 0;
+ } else{
+ cblk->nonzerobits = av_log2(max) + 1 - NMSEDEC_FRACBITS;
+ bpno = cblk->nonzerobits - 1;
+ }
+
+ ff_mqc_initenc(&t1->mqc, cblk->data);
+
+ for (passno = 0; bpno >= 0; passno++){
+ nmsedec=0;
+
+ switch(pass_t){
+ case 0: encode_sigpass(t1, width, height, bandpos, &nmsedec, bpno);
+ break;
+ case 1: encode_refpass(t1, width, height, &nmsedec, bpno);
+ break;
+ case 2: encode_clnpass(t1, width, height, bandpos, &nmsedec, bpno);
+ break;
+ }
+
+ cblk->passes[passno].rate = 3 + ff_mqc_length(&t1->mqc);
+ wmsedec += (int64_t)nmsedec << (2*bpno);
+ cblk->passes[passno].disto = wmsedec;
+
+ if (++pass_t == 3){
+ pass_t = 0;
+ bpno--;
+ }
+ }
+ cblk->npasses = passno;
+ cblk->ninclpasses = passno;
+
+ // TODO: optional flush on each pass
+ cblk->passes[passno-1].rate = ff_mqc_flush(&t1->mqc);
+}
+
+/* tier-2 routines: */
+
+static void putnumpasses(Jpeg2000EncoderContext *s, int n)
+{
+ if (n == 1)
+ put_num(s, 0, 1);
+ else if (n == 2)
+ put_num(s, 2, 2);
+ else if (n <= 5)
+ put_num(s, 0xc | (n-3), 4);
+ else if (n <= 36)
+ put_num(s, 0x1e0 | (n-6), 9);
+ else
+ put_num(s, 0xff80 | (n-37), 16);
+}
+
+
+static int encode_packet(Jpeg2000EncoderContext *s, Jpeg2000ResLevel *rlevel, int precno,
+ uint8_t *expn, int numgbits)
+{
+ int bandno, empty = 1;
+
+ // init bitstream
+ *s->buf = 0;
+ s->bit_index = 0;
+
+ // header
+
+ // is the packet empty?
+ for (bandno = 0; bandno < rlevel->nbands; bandno++){
+ if (rlevel->band[bandno].coord[0][0] < rlevel->band[bandno].coord[0][1]
+ && rlevel->band[bandno].coord[1][0] < rlevel->band[bandno].coord[1][1]){
+ empty = 0;
+ break;
+ }
+ }
+
+ put_bits(s, !empty, 1);
+ if (empty){
+ j2k_flush(s);
+ return 0;
+ }
+
+ for (bandno = 0; bandno < rlevel->nbands; bandno++){
+ Jpeg2000Band *band = rlevel->band + bandno;
+ Jpeg2000Prec *prec = band->prec + precno;
+ int yi, xi, pos;
+ int cblknw = prec->nb_codeblocks_width;
+
+ if (band->coord[0][0] == band->coord[0][1]
+ || band->coord[1][0] == band->coord[1][1])
+ continue;
+
+ for (pos=0, yi = 0; yi < prec->nb_codeblocks_height; yi++){
+ for (xi = 0; xi < cblknw; xi++, pos++){
+ prec->cblkincl[pos].val = prec->cblk[yi * cblknw + xi].ninclpasses == 0;
+ tag_tree_update(prec->cblkincl + pos);
+ prec->zerobits[pos].val = expn[bandno] + numgbits - 1 - prec->cblk[yi * cblknw + xi].nonzerobits;
+ tag_tree_update(prec->zerobits + pos);
+ }
+ }
+
+ for (pos=0, yi = 0; yi < prec->nb_codeblocks_height; yi++){
+ for (xi = 0; xi < cblknw; xi++, pos++){
+ int pad = 0, llen, length;
+ Jpeg2000Cblk *cblk = prec->cblk + yi * cblknw + xi;
+
+ if (s->buf_end - s->buf < 20) // approximately
+ return -1;
+
+ // inclusion information
+ tag_tree_code(s, prec->cblkincl + pos, 1);
+ if (!cblk->ninclpasses)
+ continue;
+ // zerobits information
+ tag_tree_code(s, prec->zerobits + pos, 100);
+ // number of passes
+ putnumpasses(s, cblk->ninclpasses);
+
+ length = cblk->passes[cblk->ninclpasses-1].rate;
+ llen = av_log2(length) - av_log2(cblk->ninclpasses) - 2;
+ if (llen < 0){
+ pad = -llen;
+ llen = 0;
+ }
+ // length of code block
+ put_bits(s, 1, llen);
+ put_bits(s, 0, 1);
+ put_num(s, length, av_log2(length)+1+pad);
+ }
+ }
+ }
+ j2k_flush(s);
+ for (bandno = 0; bandno < rlevel->nbands; bandno++){
+ Jpeg2000Band *band = rlevel->band + bandno;
+ Jpeg2000Prec *prec = band->prec + precno;
+ int yi, cblknw = prec->nb_codeblocks_width;
+ for (yi =0; yi < prec->nb_codeblocks_height; yi++){
+ int xi;
+ for (xi = 0; xi < cblknw; xi++){
+ Jpeg2000Cblk *cblk = prec->cblk + yi * cblknw + xi;
+ if (cblk->ninclpasses){
+ if (s->buf_end - s->buf < cblk->passes[cblk->ninclpasses-1].rate)
+ return -1;
+ bytestream_put_buffer(&s->buf, cblk->data, cblk->passes[cblk->ninclpasses-1].rate);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno)
+{
+ int compno, reslevelno, ret;
+ Jpeg2000CodingStyle *codsty = &s->codsty;
+ Jpeg2000QuantStyle *qntsty = &s->qntsty;
+
+ av_log(s->avctx, AV_LOG_DEBUG, "tier2\n");
+ // lay-rlevel-comp-pos progression
+ for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){
+ for (compno = 0; compno < s->ncomponents; compno++){
+ int precno;
+ Jpeg2000ResLevel *reslevel = s->tile[tileno].comp[compno].reslevel + reslevelno;
+ for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){
+ if (ret = encode_packet(s, reslevel, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0),
+ qntsty->nguardbits))
+ return ret;
+ }
+ }
+ }
+ av_log(s->avctx, AV_LOG_DEBUG, "after tier2\n");
+ return 0;
+}
+
+static int getcut(Jpeg2000Cblk *cblk, int64_t lambda, int dwt_norm)
+{
+ int passno, res = 0;
+ for (passno = 0; passno < cblk->npasses; passno++){
+ int dr;
+ int64_t dd;
+
+ dr = cblk->passes[passno].rate
+ - (res ? cblk->passes[res-1].rate:0);
+ dd = cblk->passes[passno].disto
+ - (res ? cblk->passes[res-1].disto:0);
+
+ if (((dd * dwt_norm) >> WMSEDEC_SHIFT) * dwt_norm >= dr * lambda)
+ res = passno+1;
+ }
+ return res;
+}
+
+static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
+{
+ int precno, compno, reslevelno, bandno, cblkno, lev;
+ Jpeg2000CodingStyle *codsty = &s->codsty;
+
+ for (compno = 0; compno < s->ncomponents; compno++){
+ Jpeg2000Component *comp = tile->comp + compno;
+
+ for (reslevelno = 0, lev = codsty->nreslevels-1; reslevelno < codsty->nreslevels; reslevelno++, lev--){
+ Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
+
+ for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){
+ for (bandno = 0; bandno < reslevel->nbands ; bandno++){
+ int bandpos = bandno + (reslevelno > 0);
+ Jpeg2000Band *band = reslevel->band + bandno;
+ Jpeg2000Prec *prec = band->prec + precno;
+
+ for (cblkno = 0; cblkno < prec->nb_codeblocks_height * prec->nb_codeblocks_width; cblkno++){
+ Jpeg2000Cblk *cblk = prec->cblk + cblkno;
+
+ cblk->ninclpasses = getcut(cblk, s->lambda,
+ (int64_t)dwt_norms[codsty->transform == FF_DWT53][bandpos][lev] * (int64_t)band->i_stepsize >> 16);
+ }
+ }
+ }
+ }
+ }
+}
+
+static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno)
+{
+ int compno, reslevelno, bandno, ret;
+ Jpeg2000T1Context t1;
+ Jpeg2000CodingStyle *codsty = &s->codsty;
+ for (compno = 0; compno < s->ncomponents; compno++){
+ Jpeg2000Component *comp = s->tile[tileno].comp + compno;
+
+ av_log(s->avctx, AV_LOG_DEBUG,"dwt\n");
+ if (ret = ff_dwt_encode(&comp->dwt, comp->i_data))
+ return ret;
+ av_log(s->avctx, AV_LOG_DEBUG,"after dwt -> tier1\n");
+
+ for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){
+ Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
+
+ for (bandno = 0; bandno < reslevel->nbands ; bandno++){
+ Jpeg2000Band *band = reslevel->band + bandno;
+ Jpeg2000Prec *prec = band->prec; // we support only 1 precinct per band ATM in the encoder
+ int cblkx, cblky, cblkno=0, xx0, x0, xx1, y0, yy0, yy1, bandpos;
+ yy0 = bandno == 0 ? 0 : comp->reslevel[reslevelno-1].coord[1][1] - comp->reslevel[reslevelno-1].coord[1][0];
+ y0 = yy0;
+ yy1 = FFMIN(ff_jpeg2000_ceildivpow2(band->coord[1][0] + 1, band->log2_cblk_height) << band->log2_cblk_height,
+ band->coord[1][1]) - band->coord[1][0] + yy0;
+
+ if (band->coord[0][0] == band->coord[0][1] || band->coord[1][0] == band->coord[1][1])
+ continue;
+
+ bandpos = bandno + (reslevelno > 0);
+
+ for (cblky = 0; cblky < prec->nb_codeblocks_height; cblky++){
+ if (reslevelno == 0 || bandno == 1)
+ xx0 = 0;
+ else
+ xx0 = comp->reslevel[reslevelno-1].coord[0][1] - comp->reslevel[reslevelno-1].coord[0][0];
+ x0 = xx0;
+ xx1 = FFMIN(ff_jpeg2000_ceildivpow2(band->coord[0][0] + 1, band->log2_cblk_width) << band->log2_cblk_width,
+ band->coord[0][1]) - band->coord[0][0] + xx0;
+
+ for (cblkx = 0; cblkx < prec->nb_codeblocks_width; cblkx++, cblkno++){
+ int y, x;
+ if (codsty->transform == FF_DWT53){
+ for (y = yy0; y < yy1; y++){
+ int *ptr = t1.data[y-yy0];
+ for (x = xx0; x < xx1; x++){
+ *ptr++ = comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x] << NMSEDEC_FRACBITS;
+ }
+ }
+ } else{
+ for (y = yy0; y < yy1; y++){
+ int *ptr = t1.data[y-yy0];
+ for (x = xx0; x < xx1; x++){
+ *ptr = (comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x]);
+ *ptr = (int64_t)*ptr * (int64_t)(16384 * 65536 / band->i_stepsize) >> 14 - NMSEDEC_FRACBITS;
+ ptr++;
+ }
+ }
+ }
+ encode_cblk(s, &t1, prec->cblk + cblkno, tile, xx1 - xx0, yy1 - yy0,
+ bandpos, codsty->nreslevels - reslevelno - 1);
+ xx0 = xx1;
+ xx1 = FFMIN(xx1 + (1 << band->log2_cblk_width), band->coord[0][1] - band->coord[0][0] + x0);
+ }
+ yy0 = yy1;
+ yy1 = FFMIN(yy1 + (1 << band->log2_cblk_height), band->coord[1][1] - band->coord[1][0] + y0);
+ }
+ }
+ }
+ av_log(s->avctx, AV_LOG_DEBUG, "after tier1\n");
+ }
+
+ av_log(s->avctx, AV_LOG_DEBUG, "rate control\n");
+ truncpasses(s, tile);
+ if (ret = encode_packets(s, tile, tileno))
+ return ret;
+ av_log(s->avctx, AV_LOG_DEBUG, "after rate control\n");
+ return 0;
+}
+
+static void cleanup(Jpeg2000EncoderContext *s)
+{
+ int tileno, compno;
+ Jpeg2000CodingStyle *codsty = &s->codsty;
+
+ for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
+ for (compno = 0; compno < s->ncomponents; compno++){
+ Jpeg2000Component *comp = s->tile[tileno].comp + compno;
+ ff_jpeg2000_cleanup(comp, codsty);
+ }
+ av_freep(&s->tile[tileno].comp);
+ }
+ av_freep(&s->tile);
+}
+
+static void reinit(Jpeg2000EncoderContext *s)
+{
+ int tileno, compno;
+ for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
+ Jpeg2000Tile *tile = s->tile + tileno;
+ for (compno = 0; compno < s->ncomponents; compno++)
+ ff_jpeg2000_reinit(tile->comp + compno, &s->codsty);
+ }
+}
+
+static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+ const AVFrame *pict, int *got_packet)
+{
+ int tileno, ret;
+ Jpeg2000EncoderContext *s = avctx->priv_data;
+
+ if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*9 + FF_MIN_BUFFER_SIZE)) < 0)
+ return ret;
+
+ // init:
+ s->buf = s->buf_start = pkt->data;
+ s->buf_end = pkt->data + pkt->size;
+
+ s->picture = *pict;
+ avctx->coded_frame= &s->picture;
+
+ s->lambda = s->picture.quality * LAMBDA_SCALE;
+
+ copy_frame(s);
+ reinit(s);
+
+ if (s->buf_end - s->buf < 2)
+ return -1;
+ bytestream_put_be16(&s->buf, JPEG2000_SOC);
+ if (ret = put_siz(s))
+ return ret;
+ if (ret = put_cod(s))
+ return ret;
+ if (ret = put_qcd(s, 0))
+ return ret;
+
+ for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
+ uint8_t *psotptr;
+ if (!(psotptr = put_sot(s, tileno)))
+ return -1;
+ if (s->buf_end - s->buf < 2)
+ return -1;
+ bytestream_put_be16(&s->buf, JPEG2000_SOD);
+ if (ret = encode_tile(s, s->tile + tileno, tileno))
+ return ret;
+ bytestream_put_be32(&psotptr, s->buf - psotptr + 6);
+ }
+ if (s->buf_end - s->buf < 2)
+ return -1;
+ bytestream_put_be16(&s->buf, JPEG2000_EOC);
+
+ av_log(s->avctx, AV_LOG_DEBUG, "end\n");
+ pkt->size = s->buf - s->buf_start;
+ pkt->flags |= AV_PKT_FLAG_KEY;
+ *got_packet = 1;
+
+ return 0;
+}
+
+static av_cold int j2kenc_init(AVCodecContext *avctx)
+{
+ int i, ret;
+ Jpeg2000EncoderContext *s = avctx->priv_data;
+ Jpeg2000CodingStyle *codsty = &s->codsty;
+ Jpeg2000QuantStyle *qntsty = &s->qntsty;
+
+ s->avctx = avctx;
+ av_log(s->avctx, AV_LOG_DEBUG, "init\n");
+
+ // defaults:
+ // TODO: implement setting non-standard precinct size
+ memset(codsty->log2_prec_widths , 15, sizeof(codsty->log2_prec_widths ));
+ memset(codsty->log2_prec_heights, 15, sizeof(codsty->log2_prec_heights));
+ codsty->nreslevels2decode=
+ codsty->nreslevels = 7;
+ codsty->log2_cblk_width = 4;
+ codsty->log2_cblk_height = 4;
+ codsty->transform = avctx->prediction_method ? FF_DWT53 : FF_DWT97_INT;
+
+ qntsty->nguardbits = 1;
+
+ s->tile_width = 256;
+ s->tile_height = 256;
+
+ if (codsty->transform == FF_DWT53)
+ qntsty->quantsty = JPEG2000_QSTY_NONE;
+ else
+ qntsty->quantsty = JPEG2000_QSTY_SE;
+
+ s->width = avctx->width;
+ s->height = avctx->height;
+
+ for (i = 0; i < 3; i++)
+ s->cbps[i] = 8;
+
+ if (avctx->pix_fmt == AV_PIX_FMT_RGB24){
+ s->ncomponents = 3;
+ } else if (avctx->pix_fmt == AV_PIX_FMT_GRAY8){
+ s->ncomponents = 1;
+ } else{ // planar YUV
+ s->planar = 1;
+ s->ncomponents = 3;
+ avcodec_get_chroma_sub_sample(avctx->pix_fmt,
+ s->chroma_shift, s->chroma_shift + 1);
+ }
+
+ ff_jpeg2000_init_tier1_luts();
+
+ init_luts();
+
+ init_quantization(s);
+ if (ret=init_tiles(s))
+ return ret;
+
+ av_log(s->avctx, AV_LOG_DEBUG, "after init\n");
+
+ return 0;
+}
+
+static int j2kenc_destroy(AVCodecContext *avctx)
+{
+ Jpeg2000EncoderContext *s = avctx->priv_data;
+
+ cleanup(s);
+ return 0;
+}
+
+AVCodec ff_jpeg2000_encoder = {
+ .name = "jpeg2000",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_JPEG2000,
+ .priv_data_size = sizeof(Jpeg2000EncoderContext),
+ .init = j2kenc_init,
+ .encode2 = encode_frame,
+ .close = j2kenc_destroy,
+ .capabilities = CODEC_CAP_EXPERIMENTAL,
+ .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"),
+ .pix_fmts = (const enum AVPixelFormat[]) {
+ AV_PIX_FMT_RGB24, AV_PIX_FMT_YUV444P, AV_PIX_FMT_GRAY8,
+/* AV_PIX_FMT_YUV420P,
+ AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P,
+ AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P,*/
+ AV_PIX_FMT_NONE
+ }
+};
diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 6a3e9f6..0fb7013 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -492,7 +492,7 @@ void ff_jpeg2000_reinit(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty)
void ff_jpeg2000_cleanup(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty)
{
int reslevelno, bandno, precno;
- for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) {
+ for (reslevelno = 0; comp->reslevel && reslevelno < codsty->nreslevels; reslevelno++) {
Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;

for (bandno = 0; bandno < reslevel->nbands; bandno++) {
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index f3ca020..14e11c2 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -41,9 +41,8 @@
#define HAD_QCC 0x02

typedef struct Jpeg2000TilePart {
- uint16_t tp_idx; // Tile-part index
uint8_t tile_index; // Tile index who refers the tile-part
- uint32_t tp_len; // Length of tile-part
+ const uint8_t *tp_end;
GetByteContext tpg; // bit stream in tile-part
} Jpeg2000TilePart;

@@ -55,6 +54,7 @@ typedef struct Jpeg2000Tile {
Jpeg2000CodingStyle codsty[4];
Jpeg2000QuantStyle qntsty[4];
Jpeg2000TilePart tile_part[3];
+ uint16_t tp_idx; // Tile-part index
} Jpeg2000Tile;

typedef struct Jpeg2000DecoderContext {
@@ -122,6 +122,9 @@ static int tag_tree_decode(Jpeg2000DecoderContext *s, Jpeg2000TgtNode *node,
Jpeg2000TgtNode *stack[30];
int sp = -1, curval = 0;

+ if (!node)
+ return AVERROR(EINVAL);
+
while (node && !node->vis) {
stack[++sp] = node;
node = node->parent;
@@ -185,9 +188,12 @@ static int get_siz(Jpeg2000DecoderContext *s)
uint8_t x = bytestream2_get_byteu(&s->g);
s->cbps[i] = (x & 0x7f) + 1;
s->precision = FFMAX(s->cbps[i], s->precision);
- s->sgnd[i] = !!(x & 0x80);
+ s->sgnd[i] = !!(x & 0x80);
s->cdx[i] = bytestream2_get_byteu(&s->g);
s->cdy[i] = bytestream2_get_byteu(&s->g);
+ if (s->cdx[i] != 1 || s->cdy[i] != 1) {
+ av_log(s->avctx, AV_LOG_ERROR, "unsupported/ CDxy values\n");
+ }
}

s->numXtiles = ff_jpeg2000_ceildiv(s->width - s->tile_offset_x, s->tile_width);
@@ -277,8 +283,7 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)

c->cblk_style = bytestream2_get_byteu(&s->g);
if (c->cblk_style != 0) { // cblk style
- av_log(s->avctx, AV_LOG_ERROR, "no extra cblk styles supported\n");
- return -1;
+ av_log(s->avctx, AV_LOG_WARNING, "extra cblk styles %X\n", c->cblk_style);
}
c->transform = bytestream2_get_byteu(&s->g); // DWT transformation type
/* set integer 9/7 DWT in case of BITEXACT flag */
@@ -433,11 +438,6 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
s->curtileno=0;
return AVERROR(EINVAL);
}
- if (Isot) {
- av_log(s->avctx, AV_LOG_ERROR,
- "Not a DCINEMA JP2K file: more than one tile\n");
- return -1;
- }
Psot = bytestream2_get_be32u(&s->g); // Psot
TPsot = bytestream2_get_byteu(&s->g); // TPsot

@@ -449,24 +449,18 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
return AVERROR_PATCHWELCOME;
}

+ s->tile[s->curtileno].tp_idx = TPsot;
tp = s->tile[s->curtileno].tile_part + TPsot;
tp->tile_index = Isot;
- tp->tp_len = Psot;
- tp->tp_idx = TPsot;
-
- /* Start of bit stream. Pointer to SOD marker
- * Check SOD marker is present. */
- if (JPEG2000_SOD == bytestream2_get_be16(&s->g)) {
- bytestream2_init(&tp->tpg, s->g.buffer, tp->tp_len - n - 4);
- bytestream2_skip(&s->g, tp->tp_len - n - 4);
- } else {
- av_log(s->avctx, AV_LOG_ERROR, "SOD marker not found \n");
- return -1;
- }
+ tp->tp_end = s->g.buffer + Psot - n - 2;
+
+ if (!TPsot) {
+ Jpeg2000Tile *tile = s->tile + s->curtileno;

- /* End address of bit stream =
- * start address + (Psot - size of SOT HEADER(n)
- * - size of SOT MARKER(2) - size of SOD marker(2) */
+ /* copy defaults */
+ memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(Jpeg2000CodingStyle));
+ memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(Jpeg2000QuantStyle));
+ }

return 0;
}
@@ -523,12 +517,6 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno)
if (!tile->comp)
return AVERROR(ENOMEM);

- /* copy codsty, qnsty to tile. TODO: Is it the best way?
- * codsty, qnsty is an array of 4 structs Jpeg2000CodingStyle
- * and Jpeg2000QuantStyle */
- memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(*tile->codsty));
- memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(*tile->qntsty));
-
for (compno = 0; compno < s->ncomponents; compno++) {
Jpeg2000Component *comp = tile->comp + compno;
Jpeg2000CodingStyle *codsty = tile->codsty + compno;
@@ -674,6 +662,7 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
s->bit_index = 8;
switch (tile->codsty[0].prog_order) {
case JPEG2000_PGOD_LRCP:
+ case JPEG2000_PGOD_RLCP:
for (layno = 0; layno < tile->codsty[0].nlayers; layno++) {
ok_reslevel = 1;
for (reslevelno = 0; ok_reslevel; reslevelno++) {
@@ -683,7 +672,7 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
Jpeg2000QuantStyle *qntsty = tile->qntsty + compno;
if (reslevelno < codsty->nreslevels) {
Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel +
- reslevelno;
+ reslevelno;
ok_reslevel = 1;
for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++)
if (jpeg2000_decode_packet(s,
@@ -758,32 +747,33 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile

/* TIER-1 routines */
static void decode_sigpass(Jpeg2000T1Context *t1, int width, int height,
- int bpno, int bandno)
+ int bpno, int bandno, int bpass_csty_symbol,
+ int vert_causal_ctx_csty_symbol)
{
int mask = 3 << (bpno - 1), y0, x, y;

for (y0 = 0; y0 < height; y0 += 4)
for (x = 0; x < width; x++)
- for (y = y0; y < height && y < y0 + 4; y++)
- if ((t1->flags[y + 1][x + 1] & JPEG2000_T1_SIG_NB)
- && !(t1->flags[y + 1][x + 1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))) {
- if (ff_mqc_decode(&t1->mqc,
- t1->mqc.cx_states +
- ff_jpeg2000_getsigctxno(t1->flags[y + 1][x + 1],
- bandno))) {
- int xorbit, ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y + 1][x + 1],
- &xorbit);
-
- t1->data[y][x] =
- (ff_mqc_decode(&t1->mqc,
- t1->mqc.cx_states + ctxno) ^ xorbit)
- ? -mask : mask;
+ for (y = y0; y < height && y < y0 + 4; y++) {
+ if ((t1->flags[y+1][x+1] & JPEG2000_T1_SIG_NB)
+ && !(t1->flags[y+1][x+1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))) {
+ int flags_mask = -1;
+ if (vert_causal_ctx_csty_symbol && y == y0 + 3)
+ flags_mask &= ~(JPEG2000_T1_SIG_S | JPEG2000_T1_SIG_SW | JPEG2000_T1_SIG_SE);
+ if (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ff_jpeg2000_getsigctxno(t1->flags[y+1][x+1] & flags_mask, bandno))) {
+ int xorbit, ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y+1][x+1], &xorbit);
+ if (bpass_csty_symbol)
+ t1->data[y][x] = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? -mask : mask;
+ else
+ t1->data[y][x] = (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ^ xorbit) ?
+ -mask : mask;

ff_jpeg2000_set_significance(t1, x, y,
t1->data[y][x] < 0);
}
t1->flags[y + 1][x + 1] |= JPEG2000_T1_VIS;
}
+ }
}

static void decode_refpass(Jpeg2000T1Context *t1, int width, int height,
@@ -810,11 +800,11 @@ static void decode_refpass(Jpeg2000T1Context *t1, int width, int height,

static void decode_clnpass(Jpeg2000DecoderContext *s, Jpeg2000T1Context *t1,
int width, int height, int bpno, int bandno,
- int seg_symbols)
+ int seg_symbols, int vert_causal_ctx_csty_symbol)
{
int mask = 3 << (bpno - 1), y0, x, y, runlen, dec;

- for (y0 = 0; y0 < height; y0 += 4)
+ for (y0 = 0; y0 < height; y0 += 4) {
for (x = 0; x < width; x++) {
if (y0 + 3 < height &&
!((t1->flags[y0 + 1][x + 1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) ||
@@ -836,11 +826,13 @@ static void decode_clnpass(Jpeg2000DecoderContext *s, Jpeg2000T1Context *t1,

for (y = y0 + runlen; y < y0 + 4 && y < height; y++) {
if (!dec) {
- if (!(t1->flags[y + 1][x + 1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS)))
- dec = ff_mqc_decode(&t1->mqc,
- t1->mqc.cx_states +
- ff_jpeg2000_getsigctxno(t1->flags[y + 1][x + 1],
- bandno));
+ if (!(t1->flags[y+1][x+1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))) {
+ int flags_mask = -1;
+ if (vert_causal_ctx_csty_symbol && y == y0 + 3)
+ flags_mask &= ~(JPEG2000_T1_SIG_S | JPEG2000_T1_SIG_SW | JPEG2000_T1_SIG_SE);
+ dec = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ff_jpeg2000_getsigctxno(t1->flags[y+1][x+1] & flags_mask,
+ bandno));
+ }
}
if (dec) {
int xorbit;
@@ -856,6 +848,7 @@ static void decode_clnpass(Jpeg2000DecoderContext *s, Jpeg2000T1Context *t1,
t1->flags[y + 1][x + 1] &= ~JPEG2000_T1_VIS;
}
}
+ }
if (seg_symbols) {
int val;
val = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI);
@@ -872,7 +865,9 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty,
Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk,
int width, int height, int bandpos)
{
- int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1, y;
+ int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1, y, clnpass_cnt = 0;
+ int bpass_csty_symbol = JPEG2000_CBLK_BYPASS & codsty->cblk_style;
+ int vert_causal_ctx_csty_symbol = JPEG2000_CBLK_VSC & codsty->cblk_style;

for (y = 0; y < height; y++)
memset(t1->data[y], 0, width * sizeof(**t1->data));
@@ -880,24 +875,31 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty,
/* If code-block contains no compressed data: nothing to do. */
if (!cblk->length)
return 0;
- for (y = 0; y < height + 2; y++)
- memset(t1->flags[y], 0, (width + 2) * sizeof(**t1->flags));

- cblk->data[cblk->length] = 0xff;
- cblk->data[cblk->length + 1] = 0xff;
+ for (y = 0; y < height+2; y++)
+ memset(t1->flags[y], 0, (width + 2)*sizeof(**t1->flags));
+
+ cblk->data[cblk->length] = 0xff;
+ cblk->data[cblk->length+1] = 0xff;
ff_mqc_initdec(&t1->mqc, cblk->data);

while (passno--) {
- switch (pass_t) {
+ switch(pass_t) {
case 0:
- decode_sigpass(t1, width, height, bpno + 1, bandpos);
+ decode_sigpass(t1, width, height, bpno + 1, bandpos,
+ bpass_csty_symbol && (clnpass_cnt >= 4), vert_causal_ctx_csty_symbol);
break;
case 1:
decode_refpass(t1, width, height, bpno + 1);
+ if (bpass_csty_symbol && clnpass_cnt >= 4)
+ ff_mqc_initdec(&t1->mqc, cblk->data);
break;
case 2:
decode_clnpass(s, t1, width, height, bpno + 1, bandpos,
- codsty->cblk_style & JPEG2000_CBLK_SEGSYM);
+ codsty->cblk_style & JPEG2000_CBLK_SEGSYM, vert_causal_ctx_csty_symbol);
+ clnpass_cnt = clnpass_cnt + 1;
+ if (bpass_csty_symbol && clnpass_cnt >= 4)
+ ff_mqc_initdec(&t1->mqc, cblk->data);
break;
}

@@ -1033,8 +1035,12 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
int nb_precincts, precno;
Jpeg2000Band *band = rlevel->band + bandno;
int cblkno = 0, bandpos;
+
bandpos = bandno + (reslevelno > 0);

+ if (band->coord[0][0] == band->coord[0][1] || band->coord[1][0] == band->coord[1][1])
+ continue;
+
nb_precincts = rlevel->num_precincts_x * rlevel->num_precincts_y;
/* Loop on precincts */
for (precno = 0; precno < nb_precincts; precno++) {
@@ -1114,8 +1120,8 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,

x = tile->comp[compno].coord[0][0] - s->image_offset_x;
dst = linel + (x * s->ncomponents + compno);
- for (; x < s->avctx->width; x += s->cdx[compno]) {
- int val;
+ for (; x < tile->comp[compno].coord[0][1] - s->image_offset_x; x += s-> cdx[compno]) {
+ int val;
/* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
if (tile->codsty->transform == FF_DWT97)
val = lrintf(*datap) + (1 << (s->cbps[compno] - 1));
@@ -1169,6 +1175,15 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
marker = bytestream2_get_be16u(&s->g);
oldpos = bytestream2_tell(&s->g);

+ if (marker == JPEG2000_SOD) {
+ Jpeg2000Tile *tile = s->tile + s->curtileno;
+ Jpeg2000TilePart *tp = tile->tile_part + tile->tp_idx;
+
+ bytestream2_init(&tp->tpg, s->g.buffer, tp->tp_end - s->g.buffer);
+ bytestream2_skip(&s->g, tp->tp_end - s->g.buffer);
+
+ continue;
+ }
if (marker == JPEG2000_EOC)
break;

@@ -1194,7 +1209,11 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
ret = get_qcd(s, len, qntsty, properties);
break;
case JPEG2000_SOT:
- ret = get_sot(s, len);
+ if (!(ret = get_sot(s, len))) {
+ codsty = s->tile[s->curtileno].codsty;
+ qntsty = s->tile[s->curtileno].qntsty;
+ properties = s->tile[s->curtileno].properties;
+ }
break;
case JPEG2000_COM:
// the comment is ignored
@@ -1211,7 +1230,7 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
bytestream2_skip(&s->g, len - 2);
break;
}
- if (((bytestream2_tell(&s->g) - oldpos != len) && (marker != JPEG2000_SOT)) || ret) {
+ if (bytestream2_tell(&s->g) - oldpos != len || ret) {
av_log(s->avctx, AV_LOG_ERROR,
"error during processing marker segment %.4x\n", marker);
return ret ? ret : -1;
@@ -1224,12 +1243,18 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
static int jpeg2000_read_bitstream_packets(Jpeg2000DecoderContext *s)
{
int ret = 0;
- Jpeg2000Tile *tile = s->tile + s->curtileno;
+ int tileno;

- if (ret = init_tile(s, s->curtileno))
- return ret;
- if (ret = jpeg2000_decode_packets(s, tile))
- return ret;
+ for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++) {
+ Jpeg2000Tile *tile = s->tile + tileno;
+
+ if (ret = init_tile(s, tileno))
+ return ret;
+
+ s->g = tile->tile_part[0].tpg;
+ if (ret = jpeg2000_decode_packets(s, tile))
+ return ret;
+ }

return 0;
}
@@ -1267,13 +1292,15 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,

s->avctx = avctx;
bytestream2_init(&s->g, avpkt->data, avpkt->size);
- s->curtileno = 0; // TODO: only one tile in DCI JP2K. to implement for more tiles
+ s->curtileno = -1;

// reduction factor, i.e number of resolution levels to skip
s->reduction_factor = s->lowres;

- if (bytestream2_get_bytes_left(&s->g) < 2)
- return AVERROR(EINVAL);
+ if (bytestream2_get_bytes_left(&s->g) < 2) {
+ ret = AVERROR(EINVAL);
+ goto end;
+ }

// check if the image is in jp2 format
if (bytestream2_get_bytes_left(&s->g) >= 12 &&
@@ -1283,17 +1310,17 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
if (!jp2_find_codestream(s)) {
av_log(avctx, AV_LOG_ERROR,
"couldn't find jpeg2k codestream atom\n");
- return -1;
+ ret = -1;
+ goto end;
}
} else {
bytestream2_seek(&s->g, 0, SEEK_SET);
- if (bytestream2_peek_be16(&s->g) != JPEG2000_SOC /*&& AV_RB32(s->buf + 4) == JP2_CODESTREAM*/)
- bytestream2_skip(&s->g, 8);
}

if (bytestream2_get_be16u(&s->g) != JPEG2000_SOC) {
av_log(avctx, AV_LOG_ERROR, "SOC marker not present\n");
- return -1;
+ ret = -1;
+ goto end;
}
if (ret = jpeg2000_read_main_headers(s))
goto end;
@@ -1308,10 +1335,13 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,

if (ret = jpeg2000_read_bitstream_packets(s))
goto end;
+
for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++)
if (ret = jpeg2000_decode_tile(s, s->tile + tileno, picture))
goto end;

+ jpeg2000_dec_cleanup(s);
+
*got_frame = 1;

return bytestream2_tell(&s->g);
@@ -1360,9 +1390,6 @@ AVCodec ff_jpeg2000_decoder = {
.init_static_data = jpeg2000_init_static_data,
.decode = jpeg2000_decode_frame,
.priv_class = &class,
- .pix_fmts = (enum AVPixelFormat[]) { AV_PIX_FMT_XYZ12,
- AV_PIX_FMT_GRAY8,
- -1 },
.max_lowres = 5,
.profiles = NULL_IF_CONFIG_SMALL(profiles)
};
diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak
index ed9fa2e..ebbbe16 100644
--- a/tests/fate/vcodec.mak
+++ b/tests/fate/vcodec.mak
@@ -82,6 +82,12 @@ FATE_VCODEC-$(call ENCDEC, JPEGLS, AVI) += jpegls
fate-vsynth%-jpegls: ENCOPTS = -sws_flags neighbor+full_chroma_int
fate-vsynth%-jpegls: DECOPTS = -sws_flags area

+FATE_VCODEC-$(call ENCDEC, JPEG2000, AVI) += jpeg2000 jpeg2000-97
+fate-vsynth%-jpeg2000: ENCOPTS = -qscale 7 -strict experimental -pred 1 -pix_fmt rgb24
+fate-vsynth%-jpeg2000: DECINOPTS = -vcodec jpeg2000
+fate-vsynth%-jpeg2000-97: ENCOPTS = -qscale 7 -strict experimental -pix_fmt rgb24
+fate-vsynth%-jpeg2000-97: DECINOPTS = -vcodec jpeg2000
+
FATE_VCODEC-$(call ENCDEC, LJPEG MJPEG, AVI) += ljpeg
fate-vsynth%-ljpeg: ENCOPTS = -strict -1

diff --git a/tests/ref/vsynth/vsynth1-jpeg2000 b/tests/ref/vsynth/vsynth1-jpeg2000
new file mode 100644
index 0000000..cf53feb
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-jpeg2000
@@ -0,0 +1,4 @@
+e6e3d338eeb394d6fadc7bbb55fa9e6e *tests/data/fate/vsynth1-jpeg2000.avi
+2306902 tests/data/fate/vsynth1-jpeg2000.avi
+1774b621bd92a53a24712cb77e9f0b28 *tests/data/fate/vsynth1-jpeg2000.out.rawvideo
+stddev: 5.37 PSNR: 33.52 MAXDIFF: 63 bytes: 7603200/ 7603200
diff --git a/tests/ref/vsynth/vsynth1-jpeg2000-97 b/tests/ref/vsynth/vsynth1-jpeg2000-97
new file mode 100644
index 0000000..f219406
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-jpeg2000-97
@@ -0,0 +1,4 @@
+c135eb14e9f219242180270c2a242634 *tests/data/fate/vsynth1-jpeg2000-97.avi
+2243132 tests/data/fate/vsynth1-jpeg2000-97.avi
+30a9c13e18fe4acaf28062b5003bb671 *tests/data/fate/vsynth1-jpeg2000-97.out.rawvideo
+stddev: 6.41 PSNR: 31.99 MAXDIFF: 75 bytes: 7603200/ 7603200
diff --git a/tests/ref/vsynth/vsynth2-jpeg2000 b/tests/ref/vsynth/vsynth2-jpeg2000
new file mode 100644
index 0000000..cacd467
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-jpeg2000
@@ -0,0 +1,4 @@
+fc49816ba28731689872f5c87ca91c10 *tests/data/fate/vsynth2-jpeg2000.avi
+1151144 tests/data/fate/vsynth2-jpeg2000.avi
+e7d79c9e11d0fe97f03e38be66c34e4f *tests/data/fate/vsynth2-jpeg2000.out.rawvideo
+stddev: 4.41 PSNR: 35.23 MAXDIFF: 63 bytes: 7603200/ 7603200
diff --git a/tests/ref/vsynth/vsynth2-jpeg2000-97 b/tests/ref/vsynth/vsynth2-jpeg2000-97
new file mode 100644
index 0000000..001e840
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-jpeg2000-97
@@ -0,0 +1,4 @@
+3ac3e49a89136bddde9e44bac3e5b4ed *tests/data/fate/vsynth2-jpeg2000-97.avi
+1118952 tests/data/fate/vsynth2-jpeg2000-97.avi
+9d69ac6d46152ed2d6dd6a90d5793c80 *tests/data/fate/vsynth2-jpeg2000-97.out.rawvideo
+stddev: 5.32 PSNR: 33.61 MAXDIFF: 60 bytes: 7603200/ 7603200
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:29 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 14e11c2..67f5a5c 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -192,7 +192,7 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->cdx[i] = bytestream2_get_byteu(&s->g);
s->cdy[i] = bytestream2_get_byteu(&s->g);
if (s->cdx[i] != 1 || s->cdy[i] != 1) {
- av_log(s->avctx, AV_LOG_ERROR, "unsupported/ CDxy values\n");
+ av_log(s->avctx, AV_LOG_ERROR, "unsupported/ CDxy values %d %d for component %d\n", s->cdx[i], s->cdy[i], i);
}
}
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:30 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 67f5a5c..eb2af68 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1091,7 +1091,7 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
dst = line + x * s->ncomponents + compno;

for (; x < tile->comp[compno].coord[0][1] - s->image_offset_x; x += s->cdx[compno]) {
- int val;
+ int val;
/* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
if (tile->codsty->transform == FF_DWT97)
val = lrintf(*datap) + (1 << (s->cbps[compno] - 1));
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:32 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

4400->2800 cycles

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index bd26ace..9cc627a 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -938,14 +938,14 @@ static void dequantization_int(int x, int y, Jpeg2000Cblk *cblk,
Jpeg2000Component *comp,
Jpeg2000T1Context *t1, Jpeg2000Band *band)
{
- int i, j, idx;
- int32_t *datap = &comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x];
- for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j)
- for (i = 0; i < (cblk->coord[0][1] - cblk->coord[0][0]); ++i) {
- idx = (comp->coord[0][1] - comp->coord[0][0]) * j + i;
- datap[idx] =
- ((int32_t)(t1->data[j][i]) * band->i_stepsize + (1 << 15)) >> 16;
- }
+ int i, j;
+ int w = cblk->coord[0][1] - cblk->coord[0][0];
+ for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j) {
+ int32_t *datap = &comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * (y + j) + x];
+ int *src = t1->data[j];
+ for (i = 0; i < w; ++i)
+ datap[i] = (src[i] * band->i_stepsize + (1 << 15)) >> 16;
+ }
}

/* Inverse ICT parameters in float and integer.
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:31 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

4700 -> 2700 cycles (sandybridge i7)

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index eb2af68..bd26ace 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -923,13 +923,14 @@ static void dequantization_float(int x, int y, Jpeg2000Cblk *cblk,
Jpeg2000Component *comp,
Jpeg2000T1Context *t1, Jpeg2000Band *band)
{
- int i, j, idx;
- float *datap = &comp->f_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x];
- for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j)
- for (i = 0; i < (cblk->coord[0][1] - cblk->coord[0][0]); ++i) {
- idx = (comp->coord[0][1] - comp->coord[0][0]) * j + i;
- datap[idx] = (float)(t1->data[j][i]) * band->f_stepsize;
- }
+ int i, j;
+ int w = cblk->coord[0][1] - cblk->coord[0][0];
+ for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j) {
+ float *datap = &comp->f_data[(comp->coord[0][1] - comp->coord[0][0]) * (y + j) + x];
+ int *src = t1->data[j];
+ for (i = 0; i < w; ++i)
+ datap[i] = src[i] * band->f_stepsize;
+ }
}

/* Integer dequantization of a codeblock.*/
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:33 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This keeps the structure fields more consistent after cleanup

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 9cc627a..4806d3c 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1155,6 +1155,7 @@ static void jpeg2000_dec_cleanup(Jpeg2000DecoderContext *s)
av_freep(&s->tile[tileno].comp);
}
av_freep(&s->tile);
+ s->numXtiles = s->numYtiles = 0;
}

static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:34 UTC
Permalink
From: Paul B Mahol <***@gmail.com>

Signed-off-by: Paul B Mahol <***@gmail.com>
---
libavcodec/jpeg2000dec.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 4806d3c..eeb66d9 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1328,10 +1328,8 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
goto end;

/* get picture buffer */
- if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
- av_log(avctx, AV_LOG_ERROR, "ff_thread_get_buffer() failed.\n");
+ if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
goto end;
- }
picture->pict_type = AV_PICTURE_TYPE_I;
picture->key_frame = 1;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:35 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

67935 -> 29984 kcycles

Reviewed-by: Nicolas BERTRAND <***@gmail.com>
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 68 +++++++++++++++++++++++++++++-----------------
1 file changed, 43 insertions(+), 25 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index eeb66d9..b53a8b6 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1082,6 +1082,8 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
Jpeg2000Component *comp = tile->comp + compno;
float *datap = comp->f_data;
int32_t *i_datap = comp->i_data;
+ int cbps = s->cbps[compno];
+ int w = tile->comp[compno].coord[0][1] - s->image_offset_x;

y = tile->comp[compno].coord[1][0] - s->image_offset_y;
line = picture->data[0] + y * picture->linesize[0];
@@ -1091,18 +1093,24 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
x = tile->comp[compno].coord[0][0] - s->image_offset_x;
dst = line + x * s->ncomponents + compno;

- for (; x < tile->comp[compno].coord[0][1] - s->image_offset_x; x += s->cdx[compno]) {
- int val;
- /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
- if (tile->codsty->transform == FF_DWT97)
- val = lrintf(*datap) + (1 << (s->cbps[compno] - 1));
- else
- val = *i_datap + (1 << (s->cbps[compno] - 1));
- val = av_clip(val, 0, (1 << s->cbps[compno]) - 1);
- *dst = val << (8 - s->cbps[compno]);
- datap++;
- i_datap++;
- dst += s->ncomponents;
+ if (tile->codsty->transform == FF_DWT97) {
+ for (; x < w; x += s->cdx[compno]) {
+ int val = lrintf(*datap) + (1 << (cbps - 1));
+ /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
+ val = av_clip(val, 0, (1 << cbps) - 1);
+ *dst = val << (8 - cbps);
+ datap++;
+ dst += s->ncomponents;
+ }
+ } else {
+ for (; x < w; x += s->cdx[compno]) {
+ int val = *i_datap + (1 << (cbps - 1));
+ /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
+ val = av_clip(val, 0, (1 << cbps) - 1);
+ *dst = val << (8 - cbps);
+ i_datap++;
+ dst += s->ncomponents;
+ }
}
line += picture->linesize[0];
}
@@ -1113,6 +1121,8 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
float *datap = comp->f_data;
int32_t *i_datap = comp->i_data;
uint16_t *linel;
+ int cbps = s->cbps[compno];
+ int w = tile->comp[compno].coord[0][1] - s->image_offset_x;

y = tile->comp[compno].coord[1][0] - s->image_offset_y;
linel = (uint16_t *)picture->data[0] + y * (picture->linesize[0] >> 1);
@@ -1121,24 +1131,32 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,

x = tile->comp[compno].coord[0][0] - s->image_offset_x;
dst = linel + (x * s->ncomponents + compno);
- for (; x < tile->comp[compno].coord[0][1] - s->image_offset_x; x += s-> cdx[compno]) {
- int val;
- /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
- if (tile->codsty->transform == FF_DWT97)
- val = lrintf(*datap) + (1 << (s->cbps[compno] - 1));
- else
- val = *i_datap + (1 << (s->cbps[compno] - 1));
- val = av_clip(val, 0, (1 << s->cbps[compno]) - 1);
- /* align 12 bit values in little-endian mode */
- *dst = val << (16 - s->cbps[compno]);
- datap++;
- i_datap++;
- dst += s->ncomponents;
+ if (tile->codsty->transform == FF_DWT97) {
+ for (; x < w; x += s-> cdx[compno]) {
+ int val = lrintf(*datap) + (1 << (cbps - 1));
+ /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
+ val = av_clip(val, 0, (1 << cbps) - 1);
+ /* align 12 bit values in little-endian mode */
+ *dst = val << (16 - cbps);
+ datap++;
+ dst += s->ncomponents;
+ }
+ } else {
+ for (; x < w; x += s-> cdx[compno]) {
+ int val = *i_datap + (1 << (cbps - 1));
+ /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
+ val = av_clip(val, 0, (1 << cbps) - 1);
+ /* align 12 bit values in little-endian mode */
+ *dst = val << (16 - cbps);
+ i_datap++;
+ dst += s->ncomponents;
+ }
}
linel += picture->linesize[0] >> 1;
}
}
}
+
return 0;
}
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:36 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

10% faster

Reviewed-by: Nicolas BERTRAND <***@gmail.com>
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dwt.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c
index d5bcf9d..99467f6 100644
--- a/libavcodec/jpeg2000dwt.c
+++ b/libavcodec/jpeg2000dwt.c
@@ -359,13 +359,6 @@ static void sr_1d97_float(float *p, int i0, int i1)

extend97_float(p, i0, i1);

- /*step 1*/
- for (i = i0 / 2 - 1; i < i1 / 2 + 2; i++)
- p[2 * i] *= F_LFTG_K;
- /* step 2*/
- for (i = i0 / 2 - 2; i < i1 / 2 + 2; i++)
- p[2 * i + 1] *= F_LFTG_X;
- /* step 3*/
for (i = i0 / 2 - 1; i < i1 / 2 + 2; i++)
p[2 * i] -= F_LFTG_DELTA * (p[2 * i - 1] + p[2 * i + 1]);
/* step 4 */
@@ -401,9 +394,9 @@ static void dwt_decode97_float(DWTContext *s, float *t)
int i, j = 0;
// copy with interleaving
for (i = mh; i < lh; i += 2, j++)
- l[i] = data[w * lp + j];
+ l[i] = data[w * lp + j] * F_LFTG_K;
for (i = 1 - mh; i < lh; i += 2, j++)
- l[i] = data[w * lp + j];
+ l[i] = data[w * lp + j] * F_LFTG_X;

sr_1d97_float(line, mh, mh + lh);

@@ -417,9 +410,9 @@ static void dwt_decode97_float(DWTContext *s, float *t)
int i, j = 0;
// copy with interleaving
for (i = mv; i < lv; i += 2, j++)
- l[i] = data[w * j + lp];
+ l[i] = data[w * j + lp] * F_LFTG_K;
for (i = 1 - mv; i < lv; i += 2, j++)
- l[i] = data[w * j + lp];
+ l[i] = data[w * j + lp] * F_LFTG_X;

sr_1d97_float(line, mv, mv + lv);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:37 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Tha fate tests change because the edge mirroring was wrong before this commit

Reviewed-by: Nicolas BERTRAND <***@gmail.com>
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dwt.c | 19 ++++++-------------
tests/ref/vsynth/vsynth1-jpeg2000-97 | 4 ++--
tests/ref/vsynth/vsynth2-jpeg2000-97 | 4 ++--
3 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c
index 99467f6..5f97144 100644
--- a/libavcodec/jpeg2000dwt.c
+++ b/libavcodec/jpeg2000dwt.c
@@ -431,13 +431,6 @@ static void sr_1d97_int(int32_t *p, int i0, int i1)

extend97_int(p, i0, i1);

- /*step 1*/
- for (i = i0 / 2 - 1; i < i1 / 2 + 2; i++)
- p[2 * i] = ((p[2 * i] * I_LFTG_K) + (1 << 15)) >> 16;
- /* step 2*/
- for (i = i0 / 2 - 2; i < i1 / 2 + 2; i++)
- p[2 * i + 1] = ((p[2 * i + 1] * I_LFTG_X) + (1 << 15)) >> 16;
- /* step 3*/
for (i = i0 / 2 - 1; i < i1 / 2 + 2; i++)
p[2 * i] -= (I_LFTG_DELTA * (p[2 * i - 1] + p[2 * i + 1]) + (1 << 15)) >> 16;
/* step 4 */
@@ -471,11 +464,11 @@ static void dwt_decode97_int(DWTContext *s, int32_t *t)
l = line + mh;
for (lp = 0; lp < lv; lp++) {
int i, j = 0;
- // copy with interleaving
+ // rescale with interleaving
for (i = mh; i < lh; i += 2, j++)
- l[i] = data[w * lp + j];
+ l[i] = ((data[w * lp + j] * I_LFTG_K) + (1 << 15)) >> 16;
for (i = 1 - mh; i < lh; i += 2, j++)
- l[i] = data[w * lp + j];
+ l[i] = ((data[w * lp + j] * I_LFTG_X) + (1 << 15)) >> 16;

sr_1d97_int(line, mh, mh + lh);

@@ -487,11 +480,11 @@ static void dwt_decode97_int(DWTContext *s, int32_t *t)
l = line + mv;
for (lp = 0; lp < lh; lp++) {
int i, j = 0;
- // copy with interleaving
+ // rescale with interleaving
for (i = mv; i < lv; i += 2, j++)
- l[i] = data[w * j + lp];
+ l[i] = ((data[w * j + lp] * I_LFTG_K) + (1 << 15)) >> 16;
for (i = 1 - mv; i < lv; i += 2, j++)
- l[i] = data[w * j + lp];
+ l[i] = ((data[w * j + lp] * I_LFTG_X) + (1 << 15)) >> 16;

sr_1d97_int(line, mv, mv + lv);

diff --git a/tests/ref/vsynth/vsynth1-jpeg2000-97 b/tests/ref/vsynth/vsynth1-jpeg2000-97
index f219406..f8399f2 100644
--- a/tests/ref/vsynth/vsynth1-jpeg2000-97
+++ b/tests/ref/vsynth/vsynth1-jpeg2000-97
@@ -1,4 +1,4 @@
c135eb14e9f219242180270c2a242634 *tests/data/fate/vsynth1-jpeg2000-97.avi
2243132 tests/data/fate/vsynth1-jpeg2000-97.avi
-30a9c13e18fe4acaf28062b5003bb671 *tests/data/fate/vsynth1-jpeg2000-97.out.rawvideo
-stddev: 6.41 PSNR: 31.99 MAXDIFF: 75 bytes: 7603200/ 7603200
+e1a095b40d7f6440f6c46f2995c4759c *tests/data/fate/vsynth1-jpeg2000-97.out.rawvideo
+stddev: 6.23 PSNR: 32.23 MAXDIFF: 75 bytes: 7603200/ 7603200
diff --git a/tests/ref/vsynth/vsynth2-jpeg2000-97 b/tests/ref/vsynth/vsynth2-jpeg2000-97
index 001e840..e7fce13 100644
--- a/tests/ref/vsynth/vsynth2-jpeg2000-97
+++ b/tests/ref/vsynth/vsynth2-jpeg2000-97
@@ -1,4 +1,4 @@
3ac3e49a89136bddde9e44bac3e5b4ed *tests/data/fate/vsynth2-jpeg2000-97.avi
1118952 tests/data/fate/vsynth2-jpeg2000-97.avi
-9d69ac6d46152ed2d6dd6a90d5793c80 *tests/data/fate/vsynth2-jpeg2000-97.out.rawvideo
-stddev: 5.32 PSNR: 33.61 MAXDIFF: 60 bytes: 7603200/ 7603200
+8ac8b9ee81fa73c873668e9f6b78764d *tests/data/fate/vsynth2-jpeg2000-97.out.rawvideo
+stddev: 4.95 PSNR: 34.23 MAXDIFF: 60 bytes: 7603200/ 7603200
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:39 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes: CID1026772/3
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 319b94e..5a9b2e0 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -364,7 +364,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
band->coord[1][j] = ff_jpeg2000_ceildiv(band->coord[1][j], dy);

band->prec = av_malloc_array(reslevel->num_precincts_x *
- reslevel->num_precincts_y,
+ (uint64_t)reslevel->num_precincts_y,
sizeof(*band->prec));
if (!band->prec)
return AVERROR(ENOMEM);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:40 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes CID1026755
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index b53a8b6..fecd459 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -25,6 +25,7 @@
* JPEG 2000 image decoder
*/

+#include "libavutil/avassert.h"
#include "libavutil/common.h"
#include "libavutil/opt.h"
#include "avcodec.h"
@@ -1230,6 +1231,7 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
break;
case JPEG2000_SOT:
if (!(ret = get_sot(s, len))) {
+ av_assert1(s->curtileno >= 0);
codsty = s->tile[s->curtileno].codsty;
qntsty = s->tile[s->curtileno].qntsty;
properties = s->tile[s->curtileno].properties;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:38 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes CID1026770
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 0fb7013..319b94e 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -420,7 +420,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
return AVERROR(ENOMEM);

prec->cblk = av_malloc_array(prec->nb_codeblocks_width *
- prec->nb_codeblocks_height,
+ (uint64_t)prec->nb_codeblocks_height,
sizeof(*prec->cblk));
if (!prec->cblk)
return AVERROR(ENOMEM);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:41 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array accesses

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 5a9b2e0..ff717ea 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -200,6 +200,11 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
int reslevelno, bandno, gbandno = 0, ret, i, j;
uint32_t csize;

+ if (codsty->nreslevels2decode <= 0) {
+ av_log(avctx, AV_LOG_ERROR, "nreslevels2decode %d invalid or uninitialized\n", codsty->nreslevels2decode);
+ return AVERROR(EINVAL);
+ }
+
if (ret = ff_jpeg2000_dwt_init(&comp->dwt, comp->coord,
codsty->nreslevels2decode - 1,
codsty->transform))
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:42 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Without this the context state could become inconsistent

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index fecd459..64fa838 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -310,7 +310,7 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
uint8_t *properties)
{
Jpeg2000CodingStyle tmp;
- int compno;
+ int compno, ret;

if (bytestream2_get_bytes_left(&s->g) < 5)
return AVERROR(EINVAL);
@@ -323,7 +323,9 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
tmp.nlayers = bytestream2_get_be16u(&s->g);
tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation

- get_cox(s, &tmp);
+ if ((ret = get_cox(s, &tmp)) < 0)
+ return ret;
+
for (compno = 0; compno < s->ncomponents; compno++)
if (!(properties[compno] & HAD_COC))
memcpy(c + compno, &tmp, sizeof(tmp));
@@ -335,7 +337,7 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
static int get_coc(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
uint8_t *properties)
{
- int compno;
+ int compno, ret;

if (bytestream2_get_bytes_left(&s->g) < 2)
return AVERROR(EINVAL);
@@ -344,7 +346,9 @@ static int get_coc(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,

c += compno;
c->csty = bytestream2_get_byteu(&s->g);
- get_cox(s, c);
+
+ if ((ret = get_cox(s, c)) < 0)
+ return ret;

properties[compno] |= HAD_COC;
return 0;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:43 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This prevents potential integer overflows

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index ea68d41..a105306 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -128,8 +128,8 @@ typedef struct Jpeg2000TgtNode {
} Jpeg2000TgtNode;

typedef struct Jpeg2000CodingStyle {
- uint8_t nreslevels; // number of resolution levels
- uint8_t nreslevels2decode; // number of resolution levels to decode
+ int nreslevels; // number of resolution levels
+ int nreslevels2decode; // number of resolution levels to decode
uint8_t log2_cblk_width,
log2_cblk_height; // exponent of codeblock size
uint8_t transform; // DWT type
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:44 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes division by 0

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 64fa838..d7e8e70 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -194,6 +194,8 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->cdy[i] = bytestream2_get_byteu(&s->g);
if (s->cdx[i] != 1 || s->cdy[i] != 1) {
av_log(s->avctx, AV_LOG_ERROR, "unsupported/ CDxy values %d %d for component %d\n", s->cdx[i], s->cdy[i], i);
+ if (!s->cdx[i] || !s->cdy[i])
+ return AVERROR_INVALIDDATA;
}
}
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:45 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array accesses

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index d7e8e70..1db3269 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -425,6 +425,11 @@ static int get_qcc(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q,
return AVERROR(EINVAL);

compno = bytestream2_get_byteu(&s->g);
+ if (compno >= s->ncomponents) {
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid compno\n");
+ return AVERROR_INVALIDDATA;
+ }
+
properties[compno] |= HAD_QCC;
return get_qcx(s, n - 1, q + compno);
}
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:46 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array accesses

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 1db3269..6c1623a 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -54,7 +54,7 @@ typedef struct Jpeg2000Tile {
uint8_t properties[4];
Jpeg2000CodingStyle codsty[4];
Jpeg2000QuantStyle qntsty[4];
- Jpeg2000TilePart tile_part[3];
+ Jpeg2000TilePart tile_part[4];
uint16_t tp_idx; // Tile-part index
} Jpeg2000Tile;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:47 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array access

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 6c1623a..913b7e4 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1208,9 +1208,16 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
oldpos = bytestream2_tell(&s->g);

if (marker == JPEG2000_SOD) {
- Jpeg2000Tile *tile = s->tile + s->curtileno;
- Jpeg2000TilePart *tp = tile->tile_part + tile->tp_idx;
+ Jpeg2000Tile *tile;
+ Jpeg2000TilePart *tp;

+ if (s->curtileno < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "Missing SOT\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ tile = s->tile + s->curtileno;
+ tp = tile->tile_part + tile->tp_idx;
bytestream2_init(&tp->tpg, s->g.buffer, tp->tp_end - s->g.buffer);
bytestream2_skip(&s->g, tp->tp_end - s->g.buffer);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:48 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes a null pointer dereference

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 913b7e4..682f6be 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1092,6 +1092,7 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
if (s->precision <= 8) {
for (compno = 0; compno < s->ncomponents; compno++) {
Jpeg2000Component *comp = tile->comp + compno;
+ Jpeg2000CodingStyle *codsty = tile->codsty + compno;
float *datap = comp->f_data;
int32_t *i_datap = comp->i_data;
int cbps = s->cbps[compno];
@@ -1105,7 +1106,7 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
x = tile->comp[compno].coord[0][0] - s->image_offset_x;
dst = line + x * s->ncomponents + compno;

- if (tile->codsty->transform == FF_DWT97) {
+ if (codsty->transform == FF_DWT97) {
for (; x < w; x += s->cdx[compno]) {
int val = lrintf(*datap) + (1 << (cbps - 1));
/* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
@@ -1130,6 +1131,7 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
} else {
for (compno = 0; compno < s->ncomponents; compno++) {
Jpeg2000Component *comp = tile->comp + compno;
+ Jpeg2000CodingStyle *codsty = tile->codsty + compno;
float *datap = comp->f_data;
int32_t *i_datap = comp->i_data;
uint16_t *linel;
@@ -1143,7 +1145,7 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,

x = tile->comp[compno].coord[0][0] - s->image_offset_x;
dst = linel + (x * s->ncomponents + compno);
- if (tile->codsty->transform == FF_DWT97) {
+ if (codsty->transform == FF_DWT97) {
for (; x < w; x += s-> cdx[compno]) {
int val = lrintf(*datap) + (1 << (cbps - 1));
/* DC level shift and clip see ISO 15444-1:2002 G.1.2 */
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:49 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array accesses

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 682f6be..e9166b7 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -325,6 +325,11 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
tmp.nlayers = bytestream2_get_be16u(&s->g);
tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation

+ if (tmp.mct && s->ncomponents < 3) {
+ av_log(s->avctx, "MCT %d with too few components (%d)\n", tmp.mct, s->ncomponents);
+ return AVERROR_INVALIDDATA;
+ }
+
if ((ret = get_cox(s, &tmp)) < 0)
return ret;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:50 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Found-by: ubitux
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index e9166b7..72e44d5 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -326,7 +326,7 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation

if (tmp.mct && s->ncomponents < 3) {
- av_log(s->avctx, "MCT %d with too few components (%d)\n", tmp.mct, s->ncomponents);
+ av_log(s->avctx, AV_LOG_ERROR, "MCT %d with too few components (%d)\n", tmp.mct, s->ncomponents);
return AVERROR_INVALIDDATA;
}
--
1.7.9.5
Diego Biurrun
2013-06-21 14:21:26 UTC
Permalink
Post by Nicolas Bertrand
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -326,7 +326,7 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
if (tmp.mct && s->ncomponents < 3) {
- av_log(s->avctx, "MCT %d with too few components (%d)\n", tmp.mct, s->ncomponents);
+ av_log(s->avctx, AV_LOG_ERROR, "MCT %d with too few components (%d)\n", tmp.mct, s->ncomponents);
return AVERROR_INVALIDDATA;
Please fold all such "fixes of fixes" into the faulty commit. This
commit churn should be avoided.

Diego
Nicolas Bertrand
2013-06-21 13:27:51 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Prevent use of uninitialized memory / valgrind failure

Found-by: ubitux
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index ff717ea..7bde518 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -424,9 +424,9 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
if (!prec->zerobits)
return AVERROR(ENOMEM);

- prec->cblk = av_malloc_array(prec->nb_codeblocks_width *
- (uint64_t)prec->nb_codeblocks_height,
- sizeof(*prec->cblk));
+ prec->cblk = av_mallocz_array(prec->nb_codeblocks_width *
+ (uint64_t)prec->nb_codeblocks_height,
+ sizeof(*prec->cblk));
if (!prec->cblk)
return AVERROR(ENOMEM);
for (cblkno = 0; cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height; cblkno++) {
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:52 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes integer overflow in fate-redcode-demux

Reviewed-by: Nicolas BERTRAND <***@gmail.com>
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 72e44d5..069775c 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -901,6 +901,10 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty,
ff_mqc_initdec(&t1->mqc, cblk->data);

while (passno--) {
+ if (bpno < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "bpno invalid\n");
+ return AVERROR(EINVAL);
+ }
switch(pass_t) {
case 0:
decode_sigpass(t1, width, height, bpno + 1, bandpos,
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:53 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array accesses

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 069775c..adcce76 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -160,6 +160,7 @@ static int tag_tree_decode(Jpeg2000DecoderContext *s, Jpeg2000TgtNode *node,
static int get_siz(Jpeg2000DecoderContext *s)
{
int i;
+ int ncomponents;

if (bytestream2_get_bytes_left(&s->g) < 36)
return AVERROR(EINVAL);
@@ -173,12 +174,14 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->tile_height = bytestream2_get_be32u(&s->g); // YTSiz
s->tile_offset_x = bytestream2_get_be32u(&s->g); // XT0Siz
s->tile_offset_y = bytestream2_get_be32u(&s->g); // YT0Siz
- s->ncomponents = bytestream2_get_be16u(&s->g); // CSiz
+ ncomponents = bytestream2_get_be16u(&s->g); // CSiz

- if (s->ncomponents <= 0 || s->ncomponents > 4) {
- av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", s->ncomponents);
+ if (ncomponents <= 0 || ncomponents > 4) {
+ av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", ncomponents);
return AVERROR(EINVAL);
}
+ s->ncomponents = ncomponents;
+
if (s->tile_width<=0 || s->tile_height<=0)
return AVERROR(EINVAL);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:54 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array accesses

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index adcce76..648e6a4 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -354,6 +354,11 @@ static int get_coc(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,

compno = bytestream2_get_byteu(&s->g);

+ if (compno >= s->ncomponents) {
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid compno %d\n", compno);
+ return AVERROR_INVALIDDATA;
+ }
+
c += compno;
c->csty = bytestream2_get_byteu(&s->g);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:55 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array read

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 648e6a4..5807bdc 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -469,6 +469,10 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
/* Read TNSot but not used */
bytestream2_get_byteu(&s->g); // TNsot

+ if (Psot > bytestream2_get_bytes_left(&s->g) + n + 2) {
+ av_log(s->avctx, AV_LOG_ERROR, "Psot %d too big\n", Psot);
+ return AVERROR_INVALIDDATA;
+ }
if (TPsot >= FF_ARRAY_ELEMS(s->tile[s->curtileno].tile_part)) {
av_log(s->avctx, AV_LOG_ERROR, "TPsot %d too big\n", TPsot);
return AVERROR_PATCHWELCOME;
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:56 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

Fixes out of array read

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 5807bdc..177800c 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1249,9 +1249,9 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
if (marker == JPEG2000_EOC)
break;

- if (bytestream2_get_bytes_left(&s->g) < 2)
+ len = bytestream2_get_be16(&s->g);
+ if (len < 2 || bytestream2_get_bytes_left(&s->g) < len - 2)
return AVERROR(EINVAL);
- len = bytestream2_get_be16u(&s->g);
switch (marker) {
case JPEG2000_SIZ:
ret = get_siz(s);
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:57 UTC
Permalink
From: Michael Niedermayer <***@gmx.at>

This prevents additional integer overflows

Signed-off-by: Michael Niedermayer <***@gmx.at>
---
libavcodec/jpeg2000dec.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 177800c..6060679 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -633,10 +633,16 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
else if (incl < 0)
return incl;

- if (!cblk->npasses)
- cblk->nonzerobits = expn[bandno] + numgbits - 1 -
+ if (!cblk->npasses) {
+ int v = expn[bandno] + numgbits - 1 -
tag_tree_decode(s, prec->zerobits + cblkno,
100);
+ if (v < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "nonzerobits %d invalid\n", v);
+ return AVERROR_INVALIDDATA;
+ }
+ cblk->nonzerobits = v;
+ }
if ((newpasses = getnpasses(s)) < 0)
return newpasses;
if ((llen = getlblockinc(s)) < 0)
@@ -913,10 +919,6 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty,
ff_mqc_initdec(&t1->mqc, cblk->data);

while (passno--) {
- if (bpno < 0) {
- av_log(s->avctx, AV_LOG_ERROR, "bpno invalid\n");
- return AVERROR(EINVAL);
- }
switch(pass_t) {
case 0:
decode_sigpass(t1, width, height, bpno + 1, bandpos,
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:58 UTC
Permalink
---
libavcodec/Makefile | 1 -
libavcodec/allcodecs.c | 2 +-
libavcodec/j2kenc.c | 1056 ------------------------------------------------
tests/fate/vcodec.mak | 6 -
4 files changed, 1 insertion(+), 1064 deletions(-)
delete mode 100644 libavcodec/j2kenc.c

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index e9af72d..d9c6e33 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -208,7 +208,6 @@ OBJS-$(CONFIG_INDEO4_DECODER) += indeo4.o ivi_common.o ivi_dsp.o
OBJS-$(CONFIG_INDEO5_DECODER) += indeo5.o ivi_common.o ivi_dsp.o
OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER) += dpcm.o
OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o
-OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o jpeg2000.o
OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o \
jpeg2000dwt.o mqcdec.o mqc.o
OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o \
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 650bd9d..9e0d2f0 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -163,7 +163,7 @@ void avcodec_register_all(void)
REGISTER_DECODER(INDEO4, indeo4);
REGISTER_DECODER(INDEO5, indeo5);
REGISTER_DECODER(INTERPLAY_VIDEO, interplay_video);
- REGISTER_ENCDEC (JPEG2000, jpeg2000);
+ REGISTER_DECODER (JPEG2000, jpeg2000);
REGISTER_ENCDEC (JPEGLS, jpegls);
REGISTER_DECODER(JV, jv);
REGISTER_DECODER(KGV1, kgv1);
diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
deleted file mode 100644
index e4c84ef..0000000
--- a/libavcodec/j2kenc.c
+++ /dev/null
@@ -1,1056 +0,0 @@
-/*
- * JPEG2000 image encoder
- * Copyright (c) 2007 Kamil Nowosad
- *
- * 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
- */
-
-/**
- * JPEG2000 image encoder
- * @file
- * @author Kamil Nowosad
- */
-
-#include <float.h>
-#include "avcodec.h"
-#include "internal.h"
-#include "bytestream.h"
-#include "jpeg2000.h"
-#include "libavutil/common.h"
-
-#define NMSEDEC_BITS 7
-#define NMSEDEC_FRACBITS (NMSEDEC_BITS-1)
-#define WMSEDEC_SHIFT 13 ///< must be >= 13
-#define LAMBDA_SCALE (100000000LL << (WMSEDEC_SHIFT - 13))
-
-static int lut_nmsedec_ref [1<<NMSEDEC_BITS],
- lut_nmsedec_ref0[1<<NMSEDEC_BITS],
- lut_nmsedec_sig [1<<NMSEDEC_BITS],
- lut_nmsedec_sig0[1<<NMSEDEC_BITS];
-
-static const int dwt_norms[2][4][10] = { // [dwt_type][band][rlevel] (multiplied by 10000)
- {{10000, 19650, 41770, 84030, 169000, 338400, 676900, 1353000, 2706000, 5409000},
- {20220, 39890, 83550, 170400, 342700, 686300, 1373000, 2746000, 5490000},
- {20220, 39890, 83550, 170400, 342700, 686300, 1373000, 2746000, 5490000},
- {20800, 38650, 83070, 171800, 347100, 695900, 1393000, 2786000, 5572000}},
-
- {{10000, 15000, 27500, 53750, 106800, 213400, 426700, 853300, 1707000, 3413000},
- {10380, 15920, 29190, 57030, 113300, 226400, 452500, 904800, 1809000},
- {10380, 15920, 29190, 57030, 113300, 226400, 452500, 904800, 1809000},
- { 7186, 9218, 15860, 30430, 60190, 120100, 240000, 479700, 959300}}
-};
-
-typedef struct {
- Jpeg2000Component *comp;
-} Jpeg2000Tile;
-
-typedef struct {
- AVCodecContext *avctx;
- AVFrame picture;
-
- int width, height; ///< image width and height
- uint8_t cbps[4]; ///< bits per sample in particular components
- int chroma_shift[2];
- uint8_t planar;
- int ncomponents;
- int tile_width, tile_height; ///< tile size
- int numXtiles, numYtiles;
-
- uint8_t *buf_start;
- uint8_t *buf;
- uint8_t *buf_end;
- int bit_index;
-
- int64_t lambda;
-
- Jpeg2000CodingStyle codsty;
- Jpeg2000QuantStyle qntsty;
-
- Jpeg2000Tile *tile;
-} Jpeg2000EncoderContext;
-
-
-/* debug */
-#if 0
-#undef ifprintf
-#undef printf
-
-static void nspaces(FILE *fd, int n)
-{
- while(n--) putc(' ', fd);
-}
-
-static void printcomp(Jpeg2000Component *comp)
-{
- int i;
- for (i = 0; i < comp->y1 - comp->y0; i++)
- ff_jpeg2000_printv(comp->i_data + i * (comp->x1 - comp->x0), comp->x1 - comp->x0);
-}
-
-static void dump(Jpeg2000EncoderContext *s, FILE *fd)
-{
- int tileno, compno, reslevelno, bandno, precno;
- fprintf(fd, "XSiz = %d, YSiz = %d, tile_width = %d, tile_height = %d\n"
- "numXtiles = %d, numYtiles = %d, ncomponents = %d\n"
- "tiles:\n",
- s->width, s->height, s->tile_width, s->tile_height,
- s->numXtiles, s->numYtiles, s->ncomponents);
- for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
- Jpeg2000Tile *tile = s->tile + tileno;
- nspaces(fd, 2);
- fprintf(fd, "tile %d:\n", tileno);
- for(compno = 0; compno < s->ncomponents; compno++){
- Jpeg2000Component *comp = tile->comp + compno;
- nspaces(fd, 4);
- fprintf(fd, "component %d:\n", compno);
- nspaces(fd, 4);
- fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d\n",
- comp->x0, comp->x1, comp->y0, comp->y1);
- for(reslevelno = 0; reslevelno < s->nreslevels; reslevelno++){
- Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
- nspaces(fd, 6);
- fprintf(fd, "reslevel %d:\n", reslevelno);
- nspaces(fd, 6);
- fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d, nbands = %d\n",
- reslevel->x0, reslevel->x1, reslevel->y0,
- reslevel->y1, reslevel->nbands);
- for(bandno = 0; bandno < reslevel->nbands; bandno++){
- Jpeg2000Band *band = reslevel->band + bandno;
- nspaces(fd, 8);
- fprintf(fd, "band %d:\n", bandno);
- nspaces(fd, 8);
- fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d,"
- "codeblock_width = %d, codeblock_height = %d cblknx = %d cblkny = %d\n",
- band->x0, band->x1,
- band->y0, band->y1,
- band->codeblock_width, band->codeblock_height,
- band->cblknx, band->cblkny);
- for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){
- Jpeg2000Prec *prec = band->prec + precno;
- nspaces(fd, 10);
- fprintf(fd, "prec %d:\n", precno);
- nspaces(fd, 10);
- fprintf(fd, "xi0 = %d, xi1 = %d, yi0 = %d, yi1 = %d\n",
- prec->xi0, prec->xi1, prec->yi0, prec->yi1);
- }
- }
- }
- }
- }
-}
-#endif
-
-/* bitstream routines */
-
-/** put n times val bit */
-static void put_bits(Jpeg2000EncoderContext *s, int val, int n) // TODO: optimize
-{
- while (n-- > 0){
- if (s->bit_index == 8)
- {
- s->bit_index = *s->buf == 0xff;
- *(++s->buf) = 0;
- }
- *s->buf |= val << (7 - s->bit_index++);
- }
-}
-
-/** put n least significant bits of a number num */
-static void put_num(Jpeg2000EncoderContext *s, int num, int n)
-{
- while(--n >= 0)
- put_bits(s, (num >> n) & 1, 1);
-}
-
-/** flush the bitstream */
-static void j2k_flush(Jpeg2000EncoderContext *s)
-{
- if (s->bit_index){
- s->bit_index = 0;
- s->buf++;
- }
-}
-
-/* tag tree routines */
-
-/** code the value stored in node */
-static void tag_tree_code(Jpeg2000EncoderContext *s, Jpeg2000TgtNode *node, int threshold)
-{
- Jpeg2000TgtNode *stack[30];
- int sp = 1, curval = 0;
- stack[0] = node;
-
- node = node->parent;
- while(node){
- if (node->vis){
- curval = node->val;
- break;
- }
- node->vis++;
- stack[sp++] = node;
- node = node->parent;
- }
- while(--sp >= 0){
- if (stack[sp]->val >= threshold){
- put_bits(s, 0, threshold - curval);
- break;
- }
- put_bits(s, 0, stack[sp]->val - curval);
- put_bits(s, 1, 1);
- curval = stack[sp]->val;
- }
-}
-
-/** update the value in node */
-static void tag_tree_update(Jpeg2000TgtNode *node)
-{
- int lev = 0;
- while (node->parent){
- if (node->parent->val <= node->val)
- break;
- node->parent->val = node->val;
- node = node->parent;
- lev++;
- }
-}
-
-static int put_siz(Jpeg2000EncoderContext *s)
-{
- int i;
-
- if (s->buf_end - s->buf < 40 + 3 * s->ncomponents)
- return -1;
-
- bytestream_put_be16(&s->buf, JPEG2000_SIZ);
- bytestream_put_be16(&s->buf, 38 + 3 * s->ncomponents); // Lsiz
- bytestream_put_be16(&s->buf, 0); // Rsiz
- bytestream_put_be32(&s->buf, s->width); // width
- bytestream_put_be32(&s->buf, s->height); // height
- bytestream_put_be32(&s->buf, 0); // X0Siz
- bytestream_put_be32(&s->buf, 0); // Y0Siz
-
- bytestream_put_be32(&s->buf, s->tile_width); // XTSiz
- bytestream_put_be32(&s->buf, s->tile_height); // YTSiz
- bytestream_put_be32(&s->buf, 0); // XT0Siz
- bytestream_put_be32(&s->buf, 0); // YT0Siz
- bytestream_put_be16(&s->buf, s->ncomponents); // CSiz
-
- for (i = 0; i < s->ncomponents; i++){ // Ssiz_i XRsiz_i, YRsiz_i
- bytestream_put_byte(&s->buf, 7);
- bytestream_put_byte(&s->buf, i?1<<s->chroma_shift[0]:1);
- bytestream_put_byte(&s->buf, i?1<<s->chroma_shift[1]:1);
- }
- return 0;
-}
-
-static int put_cod(Jpeg2000EncoderContext *s)
-{
- Jpeg2000CodingStyle *codsty = &s->codsty;
-
- if (s->buf_end - s->buf < 14)
- return -1;
-
- bytestream_put_be16(&s->buf, JPEG2000_COD);
- bytestream_put_be16(&s->buf, 12); // Lcod
- bytestream_put_byte(&s->buf, 0); // Scod
- // SGcod
- bytestream_put_byte(&s->buf, 0); // progression level
- bytestream_put_be16(&s->buf, 1); // num of layers
- if(s->avctx->pix_fmt == AV_PIX_FMT_YUV444P){
- bytestream_put_byte(&s->buf, 2); // ICT
- }else{
- bytestream_put_byte(&s->buf, 0); // unspecified
- }
- // SPcod
- bytestream_put_byte(&s->buf, codsty->nreslevels - 1); // num of decomp. levels
- bytestream_put_byte(&s->buf, codsty->log2_cblk_width-2); // cblk width
- bytestream_put_byte(&s->buf, codsty->log2_cblk_height-2); // cblk height
- bytestream_put_byte(&s->buf, 0); // cblk style
- bytestream_put_byte(&s->buf, codsty->transform == FF_DWT53); // transformation
- return 0;
-}
-
-static int put_qcd(Jpeg2000EncoderContext *s, int compno)
-{
- int i, size;
- Jpeg2000CodingStyle *codsty = &s->codsty;
- Jpeg2000QuantStyle *qntsty = &s->qntsty;
-
- if (qntsty->quantsty == JPEG2000_QSTY_NONE)
- size = 4 + 3 * (codsty->nreslevels-1);
- else // QSTY_SE
- size = 5 + 6 * (codsty->nreslevels-1);
-
- if (s->buf_end - s->buf < size + 2)
- return -1;
-
- bytestream_put_be16(&s->buf, JPEG2000_QCD);
- bytestream_put_be16(&s->buf, size); // LQcd
- bytestream_put_byte(&s->buf, (qntsty->nguardbits << 5) | qntsty->quantsty); // Sqcd
- if (qntsty->quantsty == JPEG2000_QSTY_NONE)
- for (i = 0; i < codsty->nreslevels * 3 - 2; i++)
- bytestream_put_byte(&s->buf, qntsty->expn[i] << 3);
- else // QSTY_SE
- for (i = 0; i < codsty->nreslevels * 3 - 2; i++)
- bytestream_put_be16(&s->buf, (qntsty->expn[i] << 11) | qntsty->mant[i]);
- return 0;
-}
-
-static uint8_t *put_sot(Jpeg2000EncoderContext *s, int tileno)
-{
- uint8_t *psotptr;
-
- if (s->buf_end - s->buf < 12)
- return NULL;
-
- bytestream_put_be16(&s->buf, JPEG2000_SOT);
- bytestream_put_be16(&s->buf, 10); // Lsot
- bytestream_put_be16(&s->buf, tileno); // Isot
-
- psotptr = s->buf;
- bytestream_put_be32(&s->buf, 0); // Psot (filled in later)
-
- bytestream_put_byte(&s->buf, 0); // TPsot
- bytestream_put_byte(&s->buf, 1); // TNsot
- return psotptr;
-}
-
-/**
- * compute the sizes of tiles, resolution levels, bands, etc.
- * allocate memory for them
- * divide the input image into tile-components
- */
-static int init_tiles(Jpeg2000EncoderContext *s)
-{
- int tileno, tilex, tiley, compno;
- Jpeg2000CodingStyle *codsty = &s->codsty;
- Jpeg2000QuantStyle *qntsty = &s->qntsty;
-
- s->numXtiles = ff_jpeg2000_ceildiv(s->width, s->tile_width);
- s->numYtiles = ff_jpeg2000_ceildiv(s->height, s->tile_height);
-
- s->tile = av_malloc(s->numXtiles * s->numYtiles * sizeof(Jpeg2000Tile));
- if (!s->tile)
- return AVERROR(ENOMEM);
- for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++)
- for (tilex = 0; tilex < s->numXtiles; tilex++, tileno++){
- Jpeg2000Tile *tile = s->tile + tileno;
-
- tile->comp = av_mallocz(s->ncomponents * sizeof(Jpeg2000Component));
- if (!tile->comp)
- return AVERROR(ENOMEM);
- for (compno = 0; compno < s->ncomponents; compno++){
- Jpeg2000Component *comp = tile->comp + compno;
- int ret, i, j;
-
- comp->coord[0][0] = comp->coord_o[0][0] = tilex * s->tile_width;
- comp->coord[0][1] = comp->coord_o[0][1] = FFMIN((tilex+1)*s->tile_width, s->width);
- comp->coord[1][0] = comp->coord_o[1][0] = tiley * s->tile_height;
- comp->coord[1][1] = comp->coord_o[1][1] = FFMIN((tiley+1)*s->tile_height, s->height);
- if (compno > 0)
- for (i = 0; i < 2; i++)
- for (j = 0; j < 2; j++)
- comp->coord[i][j] = comp->coord_o[i][j] = ff_jpeg2000_ceildivpow2(comp->coord[i][j], s->chroma_shift[i]);
-
- if (ret = ff_jpeg2000_init_component(comp,
- codsty,
- qntsty,
- s->cbps[compno],
- compno?1<<s->chroma_shift[0]:1,
- compno?1<<s->chroma_shift[1]:1,
- s->avctx
- ))
- return ret;
- }
- }
- return 0;
-}
-
-static void copy_frame(Jpeg2000EncoderContext *s)
-{
- int tileno, compno, i, y, x;
- uint8_t *line;
- for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
- Jpeg2000Tile *tile = s->tile + tileno;
- if (s->planar){
- for (compno = 0; compno < s->ncomponents; compno++){
- Jpeg2000Component *comp = tile->comp + compno;
- int *dst = comp->i_data;
- line = s->picture.data[compno]
- + comp->coord[1][0] * s->picture.linesize[compno]
- + comp->coord[0][0];
- for (y = comp->coord[1][0]; y < comp->coord[1][1]; y++){
- uint8_t *ptr = line;
- for (x = comp->coord[0][0]; x < comp->coord[0][1]; x++)
- *dst++ = *ptr++ - (1 << 7);
- line += s->picture.linesize[compno];
- }
- }
- } else{
- line = s->picture.data[0] + tile->comp[0].coord[1][0] * s->picture.linesize[0]
- + tile->comp[0].coord[0][0] * s->ncomponents;
-
- i = 0;
- for (y = tile->comp[0].coord[1][0]; y < tile->comp[0].coord[1][1]; y++){
- uint8_t *ptr = line;
- for (x = tile->comp[0].coord[0][0]; x < tile->comp[0].coord[0][1]; x++, i++){
- for (compno = 0; compno < s->ncomponents; compno++){
- tile->comp[compno].i_data[i] = *ptr++ - (1 << 7);
- }
- }
- line += s->picture.linesize[0];
- }
- }
- }
-}
-
-static void init_quantization(Jpeg2000EncoderContext *s)
-{
- int compno, reslevelno, bandno;
- Jpeg2000QuantStyle *qntsty = &s->qntsty;
- Jpeg2000CodingStyle *codsty = &s->codsty;
-
- for (compno = 0; compno < s->ncomponents; compno++){
- int gbandno = 0;
- for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){
- int nbands, lev = codsty->nreslevels - reslevelno - 1;
- nbands = reslevelno ? 3 : 1;
- for (bandno = 0; bandno < nbands; bandno++, gbandno++){
- int expn, mant;
-
- if (codsty->transform == FF_DWT97_INT){
- int bandpos = bandno + (reslevelno>0),
- ss = 81920000 / dwt_norms[0][bandpos][lev],
- log = av_log2(ss);
- mant = (11 - log < 0 ? ss >> log - 11 : ss << 11 - log) & 0x7ff;
- expn = s->cbps[compno] - log + 13;
- } else
- expn = ((bandno&2)>>1) + (reslevelno>0) + s->cbps[compno];
-
- qntsty->expn[gbandno] = expn;
- qntsty->mant[gbandno] = mant;
- }
- }
- }
-}
-
-static void init_luts(void)
-{
- int i, a,
- mask = ~((1<<NMSEDEC_FRACBITS)-1);
-
- for (i = 0; i < (1 << NMSEDEC_BITS); i++){
- lut_nmsedec_sig[i] = FFMAX(6*i - (9<<NMSEDEC_FRACBITS-1) << 12-NMSEDEC_FRACBITS, 0);
- lut_nmsedec_sig0[i] = FFMAX((i*i + (1<<NMSEDEC_FRACBITS-1) & mask) << 1, 0);
-
- a = (i >> (NMSEDEC_BITS-2)&2) + 1;
- lut_nmsedec_ref[i] = FFMAX((-2*i + (1<<NMSEDEC_FRACBITS) + a*i - (a*a<<NMSEDEC_FRACBITS-2))
- << 13-NMSEDEC_FRACBITS, 0);
- lut_nmsedec_ref0[i] = FFMAX(((i*i + (1-4*i << NMSEDEC_FRACBITS-1) + (1<<2*NMSEDEC_FRACBITS)) & mask)
- << 1, 0);
- }
-}
-
-/* tier-1 routines */
-static int getnmsedec_sig(int x, int bpno)
-{
- if (bpno > NMSEDEC_FRACBITS)
- return lut_nmsedec_sig[(x >> (bpno - NMSEDEC_FRACBITS)) & ((1 << NMSEDEC_BITS) - 1)];
- return lut_nmsedec_sig0[x & ((1 << NMSEDEC_BITS) - 1)];
-}
-
-static int getnmsedec_ref(int x, int bpno)
-{
- if (bpno > NMSEDEC_FRACBITS)
- return lut_nmsedec_ref[(x >> (bpno - NMSEDEC_FRACBITS)) & ((1 << NMSEDEC_BITS) - 1)];
- return lut_nmsedec_ref0[x & ((1 << NMSEDEC_BITS) - 1)];
-}
-
-static void encode_sigpass(Jpeg2000T1Context *t1, int width, int height, int bandno, int *nmsedec, int bpno)
-{
- int y0, x, y, mask = 1 << (bpno + NMSEDEC_FRACBITS);
- for (y0 = 0; y0 < height; y0 += 4)
- for (x = 0; x < width; x++)
- for (y = y0; y < height && y < y0+4; y++){
- if (!(t1->flags[y+1][x+1] & JPEG2000_T1_SIG) && (t1->flags[y+1][x+1] & JPEG2000_T1_SIG_NB)){
- int ctxno = ff_jpeg2000_getsigctxno(t1->flags[y+1][x+1], bandno),
- bit = t1->data[y][x] & mask ? 1 : 0;
- ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, bit);
- if (bit){
- int xorbit;
- int ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y+1][x+1], &xorbit);
- ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, (t1->flags[y+1][x+1] >> 15) ^ xorbit);
- *nmsedec += getnmsedec_sig(t1->data[y][x], bpno + NMSEDEC_FRACBITS);
- ff_jpeg2000_set_significance(t1, x, y, t1->flags[y+1][x+1] >> 15);
- }
- t1->flags[y+1][x+1] |= JPEG2000_T1_VIS;
- }
- }
-}
-
-static void encode_refpass(Jpeg2000T1Context *t1, int width, int height, int *nmsedec, int bpno)
-{
- int y0, x, y, mask = 1 << (bpno + NMSEDEC_FRACBITS);
- for (y0 = 0; y0 < height; y0 += 4)
- for (x = 0; x < width; x++)
- for (y = y0; y < height && y < y0+4; y++)
- if ((t1->flags[y+1][x+1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS)) == JPEG2000_T1_SIG){
- int ctxno = ff_jpeg2000_getrefctxno(t1->flags[y+1][x+1]);
- *nmsedec += getnmsedec_ref(t1->data[y][x], bpno + NMSEDEC_FRACBITS);
- ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, t1->data[y][x] & mask ? 1:0);
- t1->flags[y+1][x+1] |= JPEG2000_T1_REF;
- }
-}
-
-static void encode_clnpass(Jpeg2000T1Context *t1, int width, int height, int bandno, int *nmsedec, int bpno)
-{
- int y0, x, y, mask = 1 << (bpno + NMSEDEC_FRACBITS);
- for (y0 = 0; y0 < height; y0 += 4)
- for (x = 0; x < width; x++){
- if (y0 + 3 < height && !(
- (t1->flags[y0+1][x+1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) ||
- (t1->flags[y0+2][x+1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) ||
- (t1->flags[y0+3][x+1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) ||
- (t1->flags[y0+4][x+1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG))))
- {
- // aggregation mode
- int rlen;
- for (rlen = 0; rlen < 4; rlen++)
- if (t1->data[y0+rlen][x] & mask)
- break;
- ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + MQC_CX_RL, rlen != 4);
- if (rlen == 4)
- continue;
- ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI, rlen >> 1);
- ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI, rlen & 1);
- for (y = y0 + rlen; y < y0 + 4; y++){
- if (!(t1->flags[y+1][x+1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))){
- int ctxno = ff_jpeg2000_getsigctxno(t1->flags[y+1][x+1], bandno);
- if (y > y0 + rlen)
- ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, t1->data[y][x] & mask ? 1:0);
- if (t1->data[y][x] & mask){ // newly significant
- int xorbit;
- int ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y+1][x+1], &xorbit);
- *nmsedec += getnmsedec_sig(t1->data[y][x], bpno + NMSEDEC_FRACBITS);
- ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, (t1->flags[y+1][x+1] >> 15) ^ xorbit);
- ff_jpeg2000_set_significance(t1, x, y, t1->flags[y+1][x+1] >> 15);
- }
- }
- t1->flags[y+1][x+1] &= ~JPEG2000_T1_VIS;
- }
- } else{
- for (y = y0; y < y0 + 4 && y < height; y++){
- if (!(t1->flags[y+1][x+1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))){
- int ctxno = ff_jpeg2000_getsigctxno(t1->flags[y+1][x+1], bandno);
- ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, t1->data[y][x] & mask ? 1:0);
- if (t1->data[y][x] & mask){ // newly significant
- int xorbit;
- int ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y+1][x+1], &xorbit);
- *nmsedec += getnmsedec_sig(t1->data[y][x], bpno + NMSEDEC_FRACBITS);
- ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, (t1->flags[y+1][x+1] >> 15) ^ xorbit);
- ff_jpeg2000_set_significance(t1, x, y, t1->flags[y+1][x+1] >> 15);
- }
- }
- t1->flags[y+1][x+1] &= ~JPEG2000_T1_VIS;
- }
- }
- }
-}
-
-static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, Jpeg2000Tile *tile,
- int width, int height, int bandpos, int lev)
-{
- int pass_t = 2, passno, x, y, max=0, nmsedec, bpno;
- int64_t wmsedec = 0;
-
- for (y = 0; y < height+2; y++)
- memset(t1->flags[y], 0, (width+2)*sizeof(int));
-
- for (y = 0; y < height; y++){
- for (x = 0; x < width; x++){
- if (t1->data[y][x] < 0){
- t1->flags[y+1][x+1] |= JPEG2000_T1_SGN;
- t1->data[y][x] = -t1->data[y][x];
- }
- max = FFMAX(max, t1->data[y][x]);
- }
- }
-
- if (max == 0){
- cblk->nonzerobits = 0;
- bpno = 0;
- } else{
- cblk->nonzerobits = av_log2(max) + 1 - NMSEDEC_FRACBITS;
- bpno = cblk->nonzerobits - 1;
- }
-
- ff_mqc_initenc(&t1->mqc, cblk->data);
-
- for (passno = 0; bpno >= 0; passno++){
- nmsedec=0;
-
- switch(pass_t){
- case 0: encode_sigpass(t1, width, height, bandpos, &nmsedec, bpno);
- break;
- case 1: encode_refpass(t1, width, height, &nmsedec, bpno);
- break;
- case 2: encode_clnpass(t1, width, height, bandpos, &nmsedec, bpno);
- break;
- }
-
- cblk->passes[passno].rate = 3 + ff_mqc_length(&t1->mqc);
- wmsedec += (int64_t)nmsedec << (2*bpno);
- cblk->passes[passno].disto = wmsedec;
-
- if (++pass_t == 3){
- pass_t = 0;
- bpno--;
- }
- }
- cblk->npasses = passno;
- cblk->ninclpasses = passno;
-
- // TODO: optional flush on each pass
- cblk->passes[passno-1].rate = ff_mqc_flush(&t1->mqc);
-}
-
-/* tier-2 routines: */
-
-static void putnumpasses(Jpeg2000EncoderContext *s, int n)
-{
- if (n == 1)
- put_num(s, 0, 1);
- else if (n == 2)
- put_num(s, 2, 2);
- else if (n <= 5)
- put_num(s, 0xc | (n-3), 4);
- else if (n <= 36)
- put_num(s, 0x1e0 | (n-6), 9);
- else
- put_num(s, 0xff80 | (n-37), 16);
-}
-
-
-static int encode_packet(Jpeg2000EncoderContext *s, Jpeg2000ResLevel *rlevel, int precno,
- uint8_t *expn, int numgbits)
-{
- int bandno, empty = 1;
-
- // init bitstream
- *s->buf = 0;
- s->bit_index = 0;
-
- // header
-
- // is the packet empty?
- for (bandno = 0; bandno < rlevel->nbands; bandno++){
- if (rlevel->band[bandno].coord[0][0] < rlevel->band[bandno].coord[0][1]
- && rlevel->band[bandno].coord[1][0] < rlevel->band[bandno].coord[1][1]){
- empty = 0;
- break;
- }
- }
-
- put_bits(s, !empty, 1);
- if (empty){
- j2k_flush(s);
- return 0;
- }
-
- for (bandno = 0; bandno < rlevel->nbands; bandno++){
- Jpeg2000Band *band = rlevel->band + bandno;
- Jpeg2000Prec *prec = band->prec + precno;
- int yi, xi, pos;
- int cblknw = prec->nb_codeblocks_width;
-
- if (band->coord[0][0] == band->coord[0][1]
- || band->coord[1][0] == band->coord[1][1])
- continue;
-
- for (pos=0, yi = 0; yi < prec->nb_codeblocks_height; yi++){
- for (xi = 0; xi < cblknw; xi++, pos++){
- prec->cblkincl[pos].val = prec->cblk[yi * cblknw + xi].ninclpasses == 0;
- tag_tree_update(prec->cblkincl + pos);
- prec->zerobits[pos].val = expn[bandno] + numgbits - 1 - prec->cblk[yi * cblknw + xi].nonzerobits;
- tag_tree_update(prec->zerobits + pos);
- }
- }
-
- for (pos=0, yi = 0; yi < prec->nb_codeblocks_height; yi++){
- for (xi = 0; xi < cblknw; xi++, pos++){
- int pad = 0, llen, length;
- Jpeg2000Cblk *cblk = prec->cblk + yi * cblknw + xi;
-
- if (s->buf_end - s->buf < 20) // approximately
- return -1;
-
- // inclusion information
- tag_tree_code(s, prec->cblkincl + pos, 1);
- if (!cblk->ninclpasses)
- continue;
- // zerobits information
- tag_tree_code(s, prec->zerobits + pos, 100);
- // number of passes
- putnumpasses(s, cblk->ninclpasses);
-
- length = cblk->passes[cblk->ninclpasses-1].rate;
- llen = av_log2(length) - av_log2(cblk->ninclpasses) - 2;
- if (llen < 0){
- pad = -llen;
- llen = 0;
- }
- // length of code block
- put_bits(s, 1, llen);
- put_bits(s, 0, 1);
- put_num(s, length, av_log2(length)+1+pad);
- }
- }
- }
- j2k_flush(s);
- for (bandno = 0; bandno < rlevel->nbands; bandno++){
- Jpeg2000Band *band = rlevel->band + bandno;
- Jpeg2000Prec *prec = band->prec + precno;
- int yi, cblknw = prec->nb_codeblocks_width;
- for (yi =0; yi < prec->nb_codeblocks_height; yi++){
- int xi;
- for (xi = 0; xi < cblknw; xi++){
- Jpeg2000Cblk *cblk = prec->cblk + yi * cblknw + xi;
- if (cblk->ninclpasses){
- if (s->buf_end - s->buf < cblk->passes[cblk->ninclpasses-1].rate)
- return -1;
- bytestream_put_buffer(&s->buf, cblk->data, cblk->passes[cblk->ninclpasses-1].rate);
- }
- }
- }
- }
- return 0;
-}
-
-static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno)
-{
- int compno, reslevelno, ret;
- Jpeg2000CodingStyle *codsty = &s->codsty;
- Jpeg2000QuantStyle *qntsty = &s->qntsty;
-
- av_log(s->avctx, AV_LOG_DEBUG, "tier2\n");
- // lay-rlevel-comp-pos progression
- for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){
- for (compno = 0; compno < s->ncomponents; compno++){
- int precno;
- Jpeg2000ResLevel *reslevel = s->tile[tileno].comp[compno].reslevel + reslevelno;
- for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){
- if (ret = encode_packet(s, reslevel, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0),
- qntsty->nguardbits))
- return ret;
- }
- }
- }
- av_log(s->avctx, AV_LOG_DEBUG, "after tier2\n");
- return 0;
-}
-
-static int getcut(Jpeg2000Cblk *cblk, int64_t lambda, int dwt_norm)
-{
- int passno, res = 0;
- for (passno = 0; passno < cblk->npasses; passno++){
- int dr;
- int64_t dd;
-
- dr = cblk->passes[passno].rate
- - (res ? cblk->passes[res-1].rate:0);
- dd = cblk->passes[passno].disto
- - (res ? cblk->passes[res-1].disto:0);
-
- if (((dd * dwt_norm) >> WMSEDEC_SHIFT) * dwt_norm >= dr * lambda)
- res = passno+1;
- }
- return res;
-}
-
-static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
-{
- int precno, compno, reslevelno, bandno, cblkno, lev;
- Jpeg2000CodingStyle *codsty = &s->codsty;
-
- for (compno = 0; compno < s->ncomponents; compno++){
- Jpeg2000Component *comp = tile->comp + compno;
-
- for (reslevelno = 0, lev = codsty->nreslevels-1; reslevelno < codsty->nreslevels; reslevelno++, lev--){
- Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
-
- for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){
- for (bandno = 0; bandno < reslevel->nbands ; bandno++){
- int bandpos = bandno + (reslevelno > 0);
- Jpeg2000Band *band = reslevel->band + bandno;
- Jpeg2000Prec *prec = band->prec + precno;
-
- for (cblkno = 0; cblkno < prec->nb_codeblocks_height * prec->nb_codeblocks_width; cblkno++){
- Jpeg2000Cblk *cblk = prec->cblk + cblkno;
-
- cblk->ninclpasses = getcut(cblk, s->lambda,
- (int64_t)dwt_norms[codsty->transform == FF_DWT53][bandpos][lev] * (int64_t)band->i_stepsize >> 16);
- }
- }
- }
- }
- }
-}
-
-static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno)
-{
- int compno, reslevelno, bandno, ret;
- Jpeg2000T1Context t1;
- Jpeg2000CodingStyle *codsty = &s->codsty;
- for (compno = 0; compno < s->ncomponents; compno++){
- Jpeg2000Component *comp = s->tile[tileno].comp + compno;
-
- av_log(s->avctx, AV_LOG_DEBUG,"dwt\n");
- if (ret = ff_dwt_encode(&comp->dwt, comp->i_data))
- return ret;
- av_log(s->avctx, AV_LOG_DEBUG,"after dwt -> tier1\n");
-
- for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){
- Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
-
- for (bandno = 0; bandno < reslevel->nbands ; bandno++){
- Jpeg2000Band *band = reslevel->band + bandno;
- Jpeg2000Prec *prec = band->prec; // we support only 1 precinct per band ATM in the encoder
- int cblkx, cblky, cblkno=0, xx0, x0, xx1, y0, yy0, yy1, bandpos;
- yy0 = bandno == 0 ? 0 : comp->reslevel[reslevelno-1].coord[1][1] - comp->reslevel[reslevelno-1].coord[1][0];
- y0 = yy0;
- yy1 = FFMIN(ff_jpeg2000_ceildivpow2(band->coord[1][0] + 1, band->log2_cblk_height) << band->log2_cblk_height,
- band->coord[1][1]) - band->coord[1][0] + yy0;
-
- if (band->coord[0][0] == band->coord[0][1] || band->coord[1][0] == band->coord[1][1])
- continue;
-
- bandpos = bandno + (reslevelno > 0);
-
- for (cblky = 0; cblky < prec->nb_codeblocks_height; cblky++){
- if (reslevelno == 0 || bandno == 1)
- xx0 = 0;
- else
- xx0 = comp->reslevel[reslevelno-1].coord[0][1] - comp->reslevel[reslevelno-1].coord[0][0];
- x0 = xx0;
- xx1 = FFMIN(ff_jpeg2000_ceildivpow2(band->coord[0][0] + 1, band->log2_cblk_width) << band->log2_cblk_width,
- band->coord[0][1]) - band->coord[0][0] + xx0;
-
- for (cblkx = 0; cblkx < prec->nb_codeblocks_width; cblkx++, cblkno++){
- int y, x;
- if (codsty->transform == FF_DWT53){
- for (y = yy0; y < yy1; y++){
- int *ptr = t1.data[y-yy0];
- for (x = xx0; x < xx1; x++){
- *ptr++ = comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x] << NMSEDEC_FRACBITS;
- }
- }
- } else{
- for (y = yy0; y < yy1; y++){
- int *ptr = t1.data[y-yy0];
- for (x = xx0; x < xx1; x++){
- *ptr = (comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x]);
- *ptr = (int64_t)*ptr * (int64_t)(16384 * 65536 / band->i_stepsize) >> 14 - NMSEDEC_FRACBITS;
- ptr++;
- }
- }
- }
- encode_cblk(s, &t1, prec->cblk + cblkno, tile, xx1 - xx0, yy1 - yy0,
- bandpos, codsty->nreslevels - reslevelno - 1);
- xx0 = xx1;
- xx1 = FFMIN(xx1 + (1 << band->log2_cblk_width), band->coord[0][1] - band->coord[0][0] + x0);
- }
- yy0 = yy1;
- yy1 = FFMIN(yy1 + (1 << band->log2_cblk_height), band->coord[1][1] - band->coord[1][0] + y0);
- }
- }
- }
- av_log(s->avctx, AV_LOG_DEBUG, "after tier1\n");
- }
-
- av_log(s->avctx, AV_LOG_DEBUG, "rate control\n");
- truncpasses(s, tile);
- if (ret = encode_packets(s, tile, tileno))
- return ret;
- av_log(s->avctx, AV_LOG_DEBUG, "after rate control\n");
- return 0;
-}
-
-static void cleanup(Jpeg2000EncoderContext *s)
-{
- int tileno, compno;
- Jpeg2000CodingStyle *codsty = &s->codsty;
-
- for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
- for (compno = 0; compno < s->ncomponents; compno++){
- Jpeg2000Component *comp = s->tile[tileno].comp + compno;
- ff_jpeg2000_cleanup(comp, codsty);
- }
- av_freep(&s->tile[tileno].comp);
- }
- av_freep(&s->tile);
-}
-
-static void reinit(Jpeg2000EncoderContext *s)
-{
- int tileno, compno;
- for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
- Jpeg2000Tile *tile = s->tile + tileno;
- for (compno = 0; compno < s->ncomponents; compno++)
- ff_jpeg2000_reinit(tile->comp + compno, &s->codsty);
- }
-}
-
-static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
- const AVFrame *pict, int *got_packet)
-{
- int tileno, ret;
- Jpeg2000EncoderContext *s = avctx->priv_data;
-
- if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*9 + FF_MIN_BUFFER_SIZE)) < 0)
- return ret;
-
- // init:
- s->buf = s->buf_start = pkt->data;
- s->buf_end = pkt->data + pkt->size;
-
- s->picture = *pict;
- avctx->coded_frame= &s->picture;
-
- s->lambda = s->picture.quality * LAMBDA_SCALE;
-
- copy_frame(s);
- reinit(s);
-
- if (s->buf_end - s->buf < 2)
- return -1;
- bytestream_put_be16(&s->buf, JPEG2000_SOC);
- if (ret = put_siz(s))
- return ret;
- if (ret = put_cod(s))
- return ret;
- if (ret = put_qcd(s, 0))
- return ret;
-
- for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
- uint8_t *psotptr;
- if (!(psotptr = put_sot(s, tileno)))
- return -1;
- if (s->buf_end - s->buf < 2)
- return -1;
- bytestream_put_be16(&s->buf, JPEG2000_SOD);
- if (ret = encode_tile(s, s->tile + tileno, tileno))
- return ret;
- bytestream_put_be32(&psotptr, s->buf - psotptr + 6);
- }
- if (s->buf_end - s->buf < 2)
- return -1;
- bytestream_put_be16(&s->buf, JPEG2000_EOC);
-
- av_log(s->avctx, AV_LOG_DEBUG, "end\n");
- pkt->size = s->buf - s->buf_start;
- pkt->flags |= AV_PKT_FLAG_KEY;
- *got_packet = 1;
-
- return 0;
-}
-
-static av_cold int j2kenc_init(AVCodecContext *avctx)
-{
- int i, ret;
- Jpeg2000EncoderContext *s = avctx->priv_data;
- Jpeg2000CodingStyle *codsty = &s->codsty;
- Jpeg2000QuantStyle *qntsty = &s->qntsty;
-
- s->avctx = avctx;
- av_log(s->avctx, AV_LOG_DEBUG, "init\n");
-
- // defaults:
- // TODO: implement setting non-standard precinct size
- memset(codsty->log2_prec_widths , 15, sizeof(codsty->log2_prec_widths ));
- memset(codsty->log2_prec_heights, 15, sizeof(codsty->log2_prec_heights));
- codsty->nreslevels2decode=
- codsty->nreslevels = 7;
- codsty->log2_cblk_width = 4;
- codsty->log2_cblk_height = 4;
- codsty->transform = avctx->prediction_method ? FF_DWT53 : FF_DWT97_INT;
-
- qntsty->nguardbits = 1;
-
- s->tile_width = 256;
- s->tile_height = 256;
-
- if (codsty->transform == FF_DWT53)
- qntsty->quantsty = JPEG2000_QSTY_NONE;
- else
- qntsty->quantsty = JPEG2000_QSTY_SE;
-
- s->width = avctx->width;
- s->height = avctx->height;
-
- for (i = 0; i < 3; i++)
- s->cbps[i] = 8;
-
- if (avctx->pix_fmt == AV_PIX_FMT_RGB24){
- s->ncomponents = 3;
- } else if (avctx->pix_fmt == AV_PIX_FMT_GRAY8){
- s->ncomponents = 1;
- } else{ // planar YUV
- s->planar = 1;
- s->ncomponents = 3;
- avcodec_get_chroma_sub_sample(avctx->pix_fmt,
- s->chroma_shift, s->chroma_shift + 1);
- }
-
- ff_jpeg2000_init_tier1_luts();
-
- init_luts();
-
- init_quantization(s);
- if (ret=init_tiles(s))
- return ret;
-
- av_log(s->avctx, AV_LOG_DEBUG, "after init\n");
-
- return 0;
-}
-
-static int j2kenc_destroy(AVCodecContext *avctx)
-{
- Jpeg2000EncoderContext *s = avctx->priv_data;
-
- cleanup(s);
- return 0;
-}
-
-AVCodec ff_jpeg2000_encoder = {
- .name = "jpeg2000",
- .type = AVMEDIA_TYPE_VIDEO,
- .id = AV_CODEC_ID_JPEG2000,
- .priv_data_size = sizeof(Jpeg2000EncoderContext),
- .init = j2kenc_init,
- .encode2 = encode_frame,
- .close = j2kenc_destroy,
- .capabilities = CODEC_CAP_EXPERIMENTAL,
- .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"),
- .pix_fmts = (const enum AVPixelFormat[]) {
- AV_PIX_FMT_RGB24, AV_PIX_FMT_YUV444P, AV_PIX_FMT_GRAY8,
-/* AV_PIX_FMT_YUV420P,
- AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P,
- AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P,*/
- AV_PIX_FMT_NONE
- }
-};
diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak
index ebbbe16..ed9fa2e 100644
--- a/tests/fate/vcodec.mak
+++ b/tests/fate/vcodec.mak
@@ -82,12 +82,6 @@ FATE_VCODEC-$(call ENCDEC, JPEGLS, AVI) += jpegls
fate-vsynth%-jpegls: ENCOPTS = -sws_flags neighbor+full_chroma_int
fate-vsynth%-jpegls: DECOPTS = -sws_flags area

-FATE_VCODEC-$(call ENCDEC, JPEG2000, AVI) += jpeg2000 jpeg2000-97
-fate-vsynth%-jpeg2000: ENCOPTS = -qscale 7 -strict experimental -pred 1 -pix_fmt rgb24
-fate-vsynth%-jpeg2000: DECINOPTS = -vcodec jpeg2000
-fate-vsynth%-jpeg2000-97: ENCOPTS = -qscale 7 -strict experimental -pix_fmt rgb24
-fate-vsynth%-jpeg2000-97: DECINOPTS = -vcodec jpeg2000
-
FATE_VCODEC-$(call ENCDEC, LJPEG MJPEG, AVI) += ljpeg
fate-vsynth%-ljpeg: ENCOPTS = -strict -1
--
1.7.9.5
Nicolas Bertrand
2013-06-21 13:27:59 UTC
Permalink
---
libavcodec/jpeg2000dec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 6060679..0d4bc06 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1410,7 +1410,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
return bytestream2_tell(&s->g);
end:
jpeg2000_dec_cleanup(s);
- return ret ? ret : s->buf - s->buf_start;
+ return ret;
}

static void jpeg2000_init_static_data(AVCodec *codec)
--
1.7.9.5
Diego Biurrun
2013-06-21 14:19:11 UTC
Permalink
Post by Nicolas Bertrand
"Some" enhancements and bug correction for jpeg2000 decoder
As not tested, I deactivated the jpeg2000 encoder
I'm curious to learn how you deactivated that which does not exist ..
Post by Nicolas Bertrand
The fate-jpeg2000-dcinema test remains path ( ouf!)
pass?

These patches need a lot of cleanup. Formatting is extremely sloppy as
usual, please fix to comply with K&R, I'd hate to see my cleanup on
jpeg2000 ruined. The log messages also need to be fixed, there are many
typos and references to stuff that does not exist in libav.

Thanks for taking on the port.

Diego
Nicolas BERTRAND
2013-06-21 22:32:40 UTC
Permalink
Post by Diego Biurrun
Post by Nicolas Bertrand
"Some" enhancements and bug correction for jpeg2000 decoder
As not tested, I deactivated the jpeg2000 encoder
I'm curious to learn how you deactivated that which does not exist ..
I just not imported libavcodec/j2kenc.c, see patch 78/79
Post by Diego Biurrun
Post by Nicolas Bertrand
The fate-jpeg2000-dcinema test remains path ( ouf!)
pass?
yes
Post by Diego Biurrun
These patches need a lot of cleanup. Formatting is extremely sloppy as
usual, please fix to comply with K&R, I'd hate to see my cleanup on
jpeg2000 ruined. The log messages also need to be fixed, there are many
typos and references to stuff that does not exist in libav.
Thanks for taking on the port.
Well, it will take time.
Post by Diego Biurrun
Diego
_______________________________________________
libav-devel mailing list
https://lists.libav.org/mailman/listinfo/libav-devel
Luca Barbato
2013-06-22 10:06:13 UTC
Permalink
Post by Nicolas BERTRAND
Well, it will take time.
I can help you with the set of patches but for some of them I'll need
you knowledge (as you saw by my questions).

lu
Loading...