[FFmpeg-devel] [PATCH v2 1/2] avcodec/jpeg2000dec: Fix FF_DWT97_INT to pass the conformance testing defined in ISO/IEC 15444-4.
Osamu Watanabe
owatanab at es.takushoku-u.ac.jp
Fri Aug 30 05:07:40 EEST 2024
From: OSAMU WATANABE <owatanab at es.takushoku-u.ac.jp>
This commit fixes the problem described below on the integer version of the inverse DWT processing (FF_DWT97_INT, https://trac.ffmpeg.org/ticket/10123), which is activated with `-flags +bitexact`.
- Problem
- The tests for the following codestreams were filed with `-flags +bitexact`.
- p0_04.j2k, p0_05.j2k, p0_09.j2k, p1_02.j2k, p1_03.j2k, p1_06.j2k.
- ds0_ht_04_b11.j2k, ds0_ht_04_b12.j2k, ds0_ht_05_b11.j2k, ds0_ht_05_b12.j2k, ds0_ht_09_b11.j2k, ds1_ht_02_b11.j2k, ds1_ht_02_b12.j2k, ds1_ht_03_b11.j2k, ds1_ht_03_b12.j2k, ds1_ht_06_b11.j2k.
Co-authored-by: Pierre-Anthony Lemieux <pal at palemieux.com>
Signed-off-by: Osamu Watanabe <owatanab at es.takushoku-u.ac.jp>
---
libavcodec/jpeg2000.c | 7 +++----
libavcodec/jpeg2000dec.c | 4 +++-
libavcodec/jpeg2000dwt.c | 22 ++++++++++++++--------
3 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index d6ffb02319..2d093e4705 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -260,9 +260,8 @@ static void init_band_stepsize(AVCodecContext *avctx,
band->f_stepsize *= F_LFTG_X * F_LFTG_X * 4;
break;
}
- if (codsty->transform == FF_DWT97) {
- band->f_stepsize *= pow(F_LFTG_K, 2*(codsty->nreslevels2decode - reslevelno) + lband - 2);
- }
+ // scaling
+ band->f_stepsize *= pow(F_LFTG_K, 2*(codsty->nreslevels2decode - reslevelno) + lband - 2);
}
if (band->f_stepsize > (INT_MAX >> 15)) {
@@ -270,7 +269,7 @@ static void init_band_stepsize(AVCodecContext *avctx,
av_log(avctx, AV_LOG_ERROR, "stepsize out of range\n");
}
- band->i_stepsize = band->f_stepsize * (1 << 15);
+ band->i_stepsize = lrint(band->f_stepsize * (1 << 15) + 0.5f);
/* FIXME: In OpenJPEG code stepsize = stepsize * 0.5. Why?
* If not set output of entropic decoder is not correct. */
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 2e09b279dc..6af8c764d0 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -2136,7 +2136,9 @@ static void dequantization_int_97(int x, int y, Jpeg2000Cblk *cblk,
int32_t *datap = &comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * (y + j) + x];
int *src = t1->data + j*t1->stride;
for (i = 0; i < w; ++i)
- datap[i] = (src[i] * (int64_t)band->i_stepsize + (1<<15)) >> 16;
+ // Shifting down to 1 bit above from the binary point.
+ // This is mandatory for FF_DWT97_INT to pass the conformance testing.
+ datap[i] = (int32_t)(src[i] * (int64_t)band->i_stepsize + (1 << 14)) >> 15;
}
}
diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c
index 34e33553f7..256de264f3 100644
--- a/libavcodec/jpeg2000dwt.c
+++ b/libavcodec/jpeg2000dwt.c
@@ -39,7 +39,7 @@
/* Lifting parameters in integer format.
* Computed as param = (float param) * (1 << 16) */
-#define I_LFTG_ALPHA 103949ll
+#define I_LFTG_ALPHA 38413ll // = 103949 - 65536, (= 1.586 - 1.0)
#define I_LFTG_BETA 3472ll
#define I_LFTG_GAMMA 57862ll
#define I_LFTG_DELTA 29066ll
@@ -471,8 +471,11 @@ static void sr_1d97_int(int32_t *p, int i0, int i1)
for (i = (i0 >> 1); i < (i1 >> 1) + 1; i++)
p[2 * i] += (I_LFTG_BETA * (p[2 * i - 1] + (int64_t)p[2 * i + 1]) + (1 << 15)) >> 16;
/* step 6 */
- for (i = (i0 >> 1); i < (i1 >> 1); i++)
- p[2 * i + 1] += (I_LFTG_ALPHA * (p[2 * i] + (int64_t)p[2 * i + 2]) + (1 << 15)) >> 16;
+ for (i = (i0 >> 1); i < (i1 >> 1); i++) {
+ int64_t sum = p[2 * i] + (int64_t) p[2 * i + 2];
+ p[2 * i + 1] += sum;
+ p[2 * i + 1] += (I_LFTG_ALPHA * sum + (1 << 15)) >> 16;
+ }
}
static void dwt_decode97_int(DWTContext *s, int32_t *t)
@@ -500,9 +503,9 @@ static void dwt_decode97_int(DWTContext *s, int32_t *t)
l = line + mh;
for (lp = 0; lp < lv; lp++) {
int i, j = 0;
- // rescale with interleaving
+ // interleaving
for (i = mh; i < lh; i += 2, j++)
- l[i] = ((data[w * lp + j] * I_LFTG_K) + (1 << 15)) >> 16;
+ l[i] = data[w * lp + j];
for (i = 1 - mh; i < lh; i += 2, j++)
l[i] = data[w * lp + j];
@@ -516,9 +519,9 @@ static void dwt_decode97_int(DWTContext *s, int32_t *t)
l = line + mv;
for (lp = 0; lp < lh; lp++) {
int i, j = 0;
- // rescale with interleaving
+ // interleaving
for (i = mv; i < lv; i += 2, j++)
- l[i] = ((data[w * j + lp] * I_LFTG_K) + (1 << 15)) >> 16;
+ l[i] = data[w * j + lp];
for (i = 1 - mv; i < lv; i += 2, j++)
l[i] = data[w * j + lp];
@@ -530,7 +533,10 @@ static void dwt_decode97_int(DWTContext *s, int32_t *t)
}
for (i = 0; i < w * h; i++)
- data[i] = (data[i] + ((1LL<<I_PRESHIFT)>>1)) >> I_PRESHIFT;
+ // Shifting down to the binary point.
+ // In FF_DWT97_INT, the binary point of the input coefficients is 1 bit above from the LSB.
+ // So, we need `>> (I_PRESHIFT + 1)` here.
+ data[i] = (int32_t)(data[i] + ((1LL<<(I_PRESHIFT + 1))>>1)) >> (I_PRESHIFT + 1);
}
int ff_jpeg2000_dwt_init(DWTContext *s, int border[2][2],
--
2.34.1
More information about the ffmpeg-devel
mailing list