summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-10-09 13:25:27 +0200
committerGitHub <noreply@github.com>2020-10-09 13:25:27 +0200
commit491299eb073c80602ca8ee333303a31a581d3fa8 (patch)
treef464aca94231b459c62f774a6a956f3e73c2bbce /src
parent65c8f577d2f057e80040e98958eae80ca76c6b94 (diff)
parent1c5627ee7406f84cfb40809b7ac31c63342427df (diff)
Merge pull request #1253 from rouault/floating_point_irreversible_encoding
Single-threaded performance improvements in forward DWT for 5-3 and 9-7 (and other improvements)
Diffstat (limited to 'src')
-rw-r--r--src/bin/jp2/opj_compress.c35
-rw-r--r--src/lib/openjp2/CMakeLists.txt4
-rw-r--r--src/lib/openjp2/bench_dwt.c140
-rw-r--r--src/lib/openjp2/dwt.c1752
-rw-r--r--src/lib/openjp2/dwt.h20
-rw-r--r--src/lib/openjp2/j2k.c8
-rw-r--r--src/lib/openjp2/mct.c211
-rw-r--r--src/lib/openjp2/mct.h5
-rw-r--r--src/lib/openjp2/mqc.c176
-rw-r--r--src/lib/openjp2/mqc.h9
-rw-r--r--src/lib/openjp2/mqc_inl.h90
-rw-r--r--src/lib/openjp2/openjpeg.c6
-rw-r--r--src/lib/openjp2/openjpeg.h11
-rw-r--r--src/lib/openjp2/t1.c847
-rw-r--r--src/lib/openjp2/t1.h5
-rw-r--r--src/lib/openjp2/tcd.c69
16 files changed, 2209 insertions, 1179 deletions
diff --git a/src/bin/jp2/opj_compress.c b/src/bin/jp2/opj_compress.c
index cbc30fba..68274840 100644
--- a/src/bin/jp2/opj_compress.c
+++ b/src/bin/jp2/opj_compress.c
@@ -301,6 +301,10 @@ static void encode_help_display(void)
fprintf(stdout, " Currently supports only RPCL order.\n");
fprintf(stdout, "-C <comment>\n");
fprintf(stdout, " Add <comment> in the comment marker segment.\n");
+ if (opj_has_thread_support()) {
+ fprintf(stdout, " -threads <num_threads|ALL_CPUS>\n"
+ " Number of threads to use for encoding or ALL_CPUS for all available cores.\n");
+ }
/* UniPG>> */
#ifdef USE_JPWL
fprintf(stdout, "-W <params>\n");
@@ -579,7 +583,8 @@ static int parse_cmdline_encoder(int argc, char **argv,
img_fol_t *img_fol, raw_cparameters_t *raw_cp, char *indexfilename,
size_t indexfilename_size,
int* pOutFramerate,
- OPJ_BOOL* pOutPLT)
+ OPJ_BOOL* pOutPLT,
+ int* pOutNumThreads)
{
OPJ_UINT32 i, j;
int totlen, c;
@@ -596,7 +601,8 @@ static int parse_cmdline_encoder(int argc, char **argv,
{"jpip", NO_ARG, NULL, 'J'},
{"mct", REQ_ARG, NULL, 'Y'},
{"IMF", REQ_ARG, NULL, 'Z'},
- {"PLT", NO_ARG, NULL, 'A'}
+ {"PLT", NO_ARG, NULL, 'A'},
+ {"threads", REQ_ARG, NULL, 'B'}
};
/* parse the command line */
@@ -1679,6 +1685,19 @@ static int parse_cmdline_encoder(int argc, char **argv,
}
break;
+ /* ----------------------------------------------------- */
+ case 'B': { /* Number of threads */
+ if (strcmp(opj_optarg, "ALL_CPUS") == 0) {
+ *pOutNumThreads = opj_get_num_cpus();
+ if (*pOutNumThreads == 1) {
+ *pOutNumThreads = 0;
+ }
+ } else {
+ sscanf(opj_optarg, "%d", pOutNumThreads);
+ }
+ }
+ break;
+
/* ------------------------------------------------------ */
@@ -1860,6 +1879,7 @@ int main(int argc, char **argv)
OPJ_FLOAT64 t = opj_clock();
OPJ_BOOL PLT = OPJ_FALSE;
+ int num_threads = 0;
/* set encoding parameters to default values */
opj_set_default_encoder_parameters(&parameters);
@@ -1880,7 +1900,7 @@ int main(int argc, char **argv)
parameters.tcp_mct = (char)
255; /* This will be set later according to the input image or the provided option */
if (parse_cmdline_encoder(argc, argv, &parameters, &img_fol, &raw_cp,
- indexfilename, sizeof(indexfilename), &framerate, &PLT) == 1) {
+ indexfilename, sizeof(indexfilename), &framerate, &PLT, &num_threads) == 1) {
ret = 1;
goto fin;
}
@@ -2141,6 +2161,15 @@ int main(int argc, char **argv)
}
}
+ if (num_threads >= 1 &&
+ !opj_codec_set_threads(l_codec, num_threads)) {
+ fprintf(stderr, "failed to set number of threads\n");
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ ret = 1;
+ goto fin;
+ }
+
/* open a byte stream for writing and allocate memory for all tiles */
l_stream = opj_stream_create_default_file_stream(parameters.outfile, OPJ_FALSE);
if (! l_stream) {
diff --git a/src/lib/openjp2/CMakeLists.txt b/src/lib/openjp2/CMakeLists.txt
index b2714858..9f79b9c3 100644
--- a/src/lib/openjp2/CMakeLists.txt
+++ b/src/lib/openjp2/CMakeLists.txt
@@ -199,7 +199,7 @@ if(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
TARGET_LINK_LIBRARIES(${OPENJPEG_LIBRARY_NAME} ${CMAKE_THREAD_LIBS_INIT})
endif(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
-if(BUILD_UNIT_TESTS)
+if(BUILD_UNIT_TESTS AND UNIX)
add_executable(bench_dwt bench_dwt.c)
if(UNIX)
target_link_libraries(bench_dwt m ${OPENJPEG_LIBRARY_NAME})
@@ -215,4 +215,4 @@ if(BUILD_UNIT_TESTS)
if(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
target_link_libraries(test_sparse_array ${CMAKE_THREAD_LIBS_INIT})
endif(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
-endif(BUILD_UNIT_TESTS)
+endif(BUILD_UNIT_TESTS AND UNIX)
diff --git a/src/lib/openjp2/bench_dwt.c b/src/lib/openjp2/bench_dwt.c
index 8cb64d06..1124cd61 100644
--- a/src/lib/openjp2/bench_dwt.c
+++ b/src/lib/openjp2/bench_dwt.c
@@ -49,7 +49,8 @@ void init_tilec(opj_tcd_tilecomp_t * l_tilec,
OPJ_INT32 y0,
OPJ_INT32 x1,
OPJ_INT32 y1,
- OPJ_UINT32 numresolutions)
+ OPJ_UINT32 numresolutions,
+ OPJ_BOOL irreversible)
{
opj_tcd_resolution_t* l_res;
OPJ_UINT32 resno, l_level_no;
@@ -64,9 +65,16 @@ void init_tilec(opj_tcd_tilecomp_t * l_tilec,
(size_t)(l_tilec->y1 - l_tilec->y0);
l_tilec->data = (OPJ_INT32*) opj_malloc(sizeof(OPJ_INT32) * nValues);
for (i = 0; i < nValues; i++) {
- l_tilec->data[i] = getValue((OPJ_UINT32)i);
+ OPJ_INT32 val = getValue((OPJ_UINT32)i);
+ if (irreversible) {
+ OPJ_FLOAT32 fVal = (OPJ_FLOAT32)val;
+ memcpy(&l_tilec->data[i], &fVal, sizeof(OPJ_FLOAT32));
+ } else {
+ l_tilec->data[i] = val;
+ }
}
l_tilec->numresolutions = numresolutions;
+ l_tilec->minimum_num_resolutions = numresolutions;
l_tilec->resolutions = (opj_tcd_resolution_t*) opj_calloc(
l_tilec->numresolutions,
sizeof(opj_tcd_resolution_t));
@@ -98,9 +106,9 @@ void free_tilec(opj_tcd_tilecomp_t * l_tilec)
void usage(void)
{
printf(
- "bench_dwt [-size value] [-check] [-display] [-num_resolutions val]\n");
+ "bench_dwt [-decode|encode] [-I] [-size value] [-check] [-display]\n");
printf(
- " [-offset x y] [-num_threads val]\n");
+ " [-num_resolutions val] [-offset x y] [-num_threads val]\n");
exit(1);
}
@@ -131,6 +139,17 @@ OPJ_FLOAT64 opj_clock(void)
#endif
}
+static OPJ_FLOAT64 opj_wallclock(void)
+{
+#ifdef _WIN32
+ return opj_clock();
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (OPJ_FLOAT64)tv.tv_sec + 1e-6 * (OPJ_FLOAT64)tv.tv_usec;
+#endif
+}
+
int main(int argc, char** argv)
{
int num_threads = 0;
@@ -146,16 +165,24 @@ int main(int argc, char** argv)
OPJ_BOOL check = OPJ_FALSE;
OPJ_INT32 size = 16384 - 1;
OPJ_FLOAT64 start, stop;
+ OPJ_FLOAT64 start_wc, stop_wc;
OPJ_UINT32 offset_x = ((OPJ_UINT32)size + 1) / 2 - 1;
OPJ_UINT32 offset_y = ((OPJ_UINT32)size + 1) / 2 - 1;
OPJ_UINT32 num_resolutions = 6;
+ OPJ_BOOL bench_decode = OPJ_TRUE;
+ OPJ_BOOL irreversible = OPJ_FALSE;
for (i = 1; i < argc; i++) {
- if (strcmp(argv[i], "-display") == 0) {
+ if (strcmp(argv[i], "-encode") == 0) {
+ bench_decode = OPJ_FALSE;
+ } else if (strcmp(argv[i], "-decode") == 0) {
+ bench_decode = OPJ_TRUE;
+ } else if (strcmp(argv[i], "-display") == 0) {
display = OPJ_TRUE;
- check = OPJ_TRUE;
} else if (strcmp(argv[i], "-check") == 0) {
check = OPJ_TRUE;
+ } else if (strcmp(argv[i], "-I") == 0) {
+ irreversible = OPJ_TRUE;
} else if (strcmp(argv[i], "-size") == 0 && i + 1 < argc) {
size = atoi(argv[i + 1]);
i ++;
@@ -179,18 +206,29 @@ int main(int argc, char** argv)
}
}
+ if (irreversible && check) {
+ /* Due to irreversible inverse DWT not being symetric of forward */
+ /* See BUG_WEIRD_TWO_INVK in dwt.c */
+ printf("-I and -check aren't compatible\n");
+ exit(1);
+ }
+
tp = opj_thread_pool_create(num_threads);
init_tilec(&tilec, (OPJ_INT32)offset_x, (OPJ_INT32)offset_y,
(OPJ_INT32)offset_x + size, (OPJ_INT32)offset_y + size,
- num_resolutions);
+ num_resolutions, irreversible);
if (display) {
printf("Before\n");
k = 0;
for (j = 0; j < tilec.y1 - tilec.y0; j++) {
for (i = 0; i < tilec.x1 - tilec.x0; i++) {
- printf("%d ", tilec.data[k]);
+ if (irreversible) {
+ printf("%f ", ((OPJ_FLOAT32*)tilec.data)[k]);
+ } else {
+ printf("%d ", tilec.data[k]);
+ }
k ++;
}
printf("\n");
@@ -223,45 +261,87 @@ int main(int argc, char** argv)
image_comp.dy = 1;
start = opj_clock();
- opj_dwt_decode(&tcd, &tilec, tilec.numresolutions);
+ start_wc = opj_wallclock();
+ if (bench_decode) {
+ if (irreversible) {
+ opj_dwt_decode_real(&tcd, &tilec, tilec.numresolutions);
+ } else {
+ opj_dwt_decode(&tcd, &tilec, tilec.numresolutions);
+ }
+ } else {
+ if (irreversible) {
+ opj_dwt_encode_real(&tcd, &tilec);
+ } else {
+ opj_dwt_encode(&tcd, &tilec);
+ }
+ }
stop = opj_clock();
- printf("time for dwt_decode: %.03f s\n", stop - start);
+ stop_wc = opj_wallclock();
+ printf("time for %s: total = %.03f s, wallclock = %.03f s\n",
+ bench_decode ? "dwt_decode" : "dwt_encode",
+ stop - start,
+ stop_wc - start_wc);
- if (display || check) {
- if (display) {
+ if (display) {
+ if (bench_decode) {
printf("After IDWT\n");
- k = 0;
- for (j = 0; j < tilec.y1 - tilec.y0; j++) {
- for (i = 0; i < tilec.x1 - tilec.x0; i++) {
+ } else {
+ printf("After FDWT\n");
+ }
+ k = 0;
+ for (j = 0; j < tilec.y1 - tilec.y0; j++) {
+ for (i = 0; i < tilec.x1 - tilec.x0; i++) {
+ if (irreversible) {
+ printf("%f ", ((OPJ_FLOAT32*)tilec.data)[k]);
+ } else {
printf("%d ", tilec.data[k]);
- k ++;
}
- printf("\n");
+ k ++;
}
+ printf("\n");
}
+ }
- opj_dwt_encode(&tilec);
- if (display) {
- printf("After FDWT\n");
+ if ((display || check) && !irreversible) {
+
+ if (bench_decode) {
+ opj_dwt_encode(&tcd, &tilec);
+ } else {
+ opj_dwt_decode(&tcd, &tilec, tilec.numresolutions);
+ }
+
+
+ if (display && !irreversible) {
+ if (bench_decode) {
+ printf("After FDWT\n");
+ } else {
+ printf("After IDWT\n");
+ }
k = 0;
for (j = 0; j < tilec.y1 - tilec.y0; j++) {
for (i = 0; i < tilec.x1 - tilec.x0; i++) {
- printf("%d ", tilec.data[k]);
+ if (irreversible) {
+ printf("%f ", ((OPJ_FLOAT32*)tilec.data)[k]);
+ } else {
+ printf("%d ", tilec.data[k]);
+ }
k ++;
}
printf("\n");
}
}
- if (check) {
- size_t idx;
- size_t nValues = (size_t)(tilec.x1 - tilec.x0) *
- (size_t)(tilec.y1 - tilec.y0);
- for (idx = 0; idx < nValues; idx++) {
- if (tilec.data[idx] != getValue((OPJ_UINT32)idx)) {
- printf("Difference found at idx = %u\n", (OPJ_UINT32)idx);
- exit(1);
- }
+ }
+
+ if (check) {
+
+ size_t idx;
+ size_t nValues = (size_t)(tilec.x1 - tilec.x0) *
+ (size_t)(tilec.y1 - tilec.y0);
+ for (idx = 0; idx < nValues; idx++) {
+ if (tilec.data[idx] != getValue((OPJ_UINT32)idx)) {
+ printf("Difference found at idx = %u\n", (OPJ_UINT32)idx);
+ exit(1);
}
}
}
diff --git a/src/lib/openjp2/dwt.c b/src/lib/openjp2/dwt.c
index 5930d1c7..ee9eb5e6 100644
--- a/src/lib/openjp2/dwt.c
+++ b/src/lib/openjp2/dwt.c
@@ -87,12 +87,14 @@ typedef struct dwt_local {
OPJ_INT32 cas; /* 0 = start on even coord, 1 = start on odd coord */
} opj_dwt_t;
+#define NB_ELTS_V8 8
+
typedef union {
- OPJ_FLOAT32 f[4];
-} opj_v4_t;
+ OPJ_FLOAT32 f[NB_ELTS_V8];
+} opj_v8_t;
-typedef struct v4dwt_local {
- opj_v4_t* wavelet ;
+typedef struct v8dwt_local {
+ opj_v8_t* wavelet ;
OPJ_INT32 dn ; /* number of elements in high pass band */
OPJ_INT32 sn ; /* number of elements in low pass band */
OPJ_INT32 cas ; /* 0 = start on even coord, 1 = start on odd coord */
@@ -100,45 +102,34 @@ typedef struct v4dwt_local {
OPJ_UINT32 win_l_x1; /* end coord in low pass band */
OPJ_UINT32 win_h_x0; /* start coord in high pass band */
OPJ_UINT32 win_h_x1; /* end coord in high pass band */
-} opj_v4dwt_t ;
+} opj_v8dwt_t ;
-static const OPJ_FLOAT32 opj_dwt_alpha = 1.586134342f; /* 12994 */
-static const OPJ_FLOAT32 opj_dwt_beta = 0.052980118f; /* 434 */
-static const OPJ_FLOAT32 opj_dwt_gamma = -0.882911075f; /* -7233 */
-static const OPJ_FLOAT32 opj_dwt_delta = -0.443506852f; /* -3633 */
+/* From table F.4 from the standard */
+static const OPJ_FLOAT32 opj_dwt_alpha = -1.586134342f;
+static const OPJ_FLOAT32 opj_dwt_beta = -0.052980118f;
+static const OPJ_FLOAT32 opj_dwt_gamma = 0.882911075f;
+static const OPJ_FLOAT32 opj_dwt_delta = 0.443506852f;
-static const OPJ_FLOAT32 opj_K = 1.230174105f; /* 10078 */
-static const OPJ_FLOAT32 opj_c13318 = 1.625732422f;
+static const OPJ_FLOAT32 opj_K = 1.230174105f;
+static const OPJ_FLOAT32 opj_invK = (OPJ_FLOAT32)(1.0 / 1.230174105);
/*@}*/
-/**
-Virtual function type for wavelet transform in 1-D
-*/
-typedef void (*DWT1DFN)(const opj_dwt_t* v);
-
/** @name Local static functions */
/*@{*/
/**
Forward lazy transform (horizontal)
*/
-static void opj_dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn,
+static void opj_dwt_deinterleave_h(const OPJ_INT32 * OPJ_RESTRICT a,
+ OPJ_INT32 * OPJ_RESTRICT b,
+ OPJ_INT32 dn,
OPJ_INT32 sn, OPJ_INT32 cas);
-/**
-Forward lazy transform (vertical)
-*/
-static void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn,
- OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas);
-/**
-Forward 5-3 wavelet transform in 1-D
-*/
-static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn,
- OPJ_INT32 cas);
+
/**
Forward 9-7 wavelet transform in 1-D
*/
-static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn,
+static void opj_dwt_encode_1_real(void *a, OPJ_INT32 dn, OPJ_INT32 sn,
OPJ_INT32 cas);
/**
Explicit calculation of the Quantization Stepsizes
@@ -155,8 +146,29 @@ static OPJ_BOOL opj_dwt_decode_partial_tile(
opj_tcd_tilecomp_t* tilec,
OPJ_UINT32 numres);
-static OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
- void (*p_function)(OPJ_INT32 *, OPJ_INT32, OPJ_INT32, OPJ_INT32));
+/* Forward transform, for the vertical pass, processing cols columns */
+/* where cols <= NB_ELTS_V8 */
+/* Where void* is a OPJ_INT32* for 5x3 and OPJ_FLOAT32* for 9x7 */
+typedef void (*opj_encode_and_deinterleave_v_fnptr_type)(
+ void *array,
+ void *tmp,
+ OPJ_UINT32 height,
+ OPJ_BOOL even,
+ OPJ_UINT32 stride_width,
+ OPJ_UINT32 cols);
+
+/* Where void* is a OPJ_INT32* for 5x3 and OPJ_FLOAT32* for 9x7 */
+typedef void (*opj_encode_and_deinterleave_h_one_row_fnptr_type)(
+ void *row,
+ void *tmp,
+ OPJ_UINT32 width,
+ OPJ_BOOL even);
+
+static OPJ_BOOL opj_dwt_encode_procedure(opj_thread_pool_t* tp,
+ opj_tcd_tilecomp_t * tilec,
+ opj_encode_and_deinterleave_v_fnptr_type p_encode_and_deinterleave_v,
+ opj_encode_and_deinterleave_h_one_row_fnptr_type
+ p_encode_and_deinterleave_h_one_row);
static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r,
OPJ_UINT32 i);
@@ -164,42 +176,6 @@ static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r,
/* <summary> */
/* Inverse 9-7 wavelet transform in 1-D. */
/* </summary> */
-static void opj_v4dwt_decode(opj_v4dwt_t* OPJ_RESTRICT dwt);
-
-static void opj_v4dwt_interleave_h(opj_v4dwt_t* OPJ_RESTRICT dwt,
- OPJ_FLOAT32* OPJ_RESTRICT a,
- OPJ_UINT32 width,
- OPJ_UINT32 remaining_height);
-
-static void opj_v4dwt_interleave_v(opj_v4dwt_t* OPJ_RESTRICT dwt,
- OPJ_FLOAT32* OPJ_RESTRICT a,
- OPJ_UINT32 width,
- OPJ_UINT32 nb_elts_read);
-
-#ifdef __SSE__
-static void opj_v4dwt_decode_step1_sse(opj_v4_t* w,
- OPJ_UINT32 start,
- OPJ_UINT32 end,
- const __m128 c);
-
-static void opj_v4dwt_decode_step2_sse(opj_v4_t* l, opj_v4_t* w,
- OPJ_UINT32 start,
- OPJ_UINT32 end,
- OPJ_UINT32 m, __m128 c);
-
-#else
-static void opj_v4dwt_decode_step1(opj_v4_t* w,
- OPJ_UINT32 start,
- OPJ_UINT32 end,
- const OPJ_FLOAT32 c);
-
-static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w,
- OPJ_UINT32 start,
- OPJ_UINT32 end,
- OPJ_UINT32 m,
- OPJ_FLOAT32 c);
-
-#endif
/*@}*/
@@ -246,12 +222,14 @@ static const OPJ_FLOAT64 opj_dwt_norms_real[4][10] = {
/* <summary> */
/* Forward lazy transform (horizontal). */
/* </summary> */
-static void opj_dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn,
+static void opj_dwt_deinterleave_h(const OPJ_INT32 * OPJ_RESTRICT a,
+ OPJ_INT32 * OPJ_RESTRICT b,
+ OPJ_INT32 dn,
OPJ_INT32 sn, OPJ_INT32 cas)
{
OPJ_INT32 i;
- OPJ_INT32 * l_dest = b;
- OPJ_INT32 * l_src = a + cas;
+ OPJ_INT32 * OPJ_RESTRICT l_dest = b;
+ const OPJ_INT32 * OPJ_RESTRICT l_src = a + cas;
for (i = 0; i < sn; ++i) {
*l_dest++ = *l_src;
@@ -267,40 +245,13 @@ static void opj_dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn,
}
}
-/* <summary> */
-/* Forward lazy transform (vertical). */
-/* </summary> */
-static void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn,
- OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas)
-{
- OPJ_INT32 i = sn;
- OPJ_INT32 * l_dest = b;
- OPJ_INT32 * l_src = a + cas;
-
- while (i--) {
- *l_dest = *l_src;
- l_dest += x;
- l_src += 2;
- } /* b[i*x]=a[2*i+cas]; */
-
- l_dest = b + (OPJ_SIZE_T)sn * (OPJ_SIZE_T)x;
- l_src = a + 1 - cas;
-
- i = dn;
- while (i--) {
- *l_dest = *l_src;
- l_dest += x;
- l_src += 2;
- } /*b[(sn+i)*x]=a[(2*i+1-cas)];*/
-}
-
#ifdef STANDARD_SLOW_VERSION
/* <summary> */
/* Inverse lazy transform (horizontal). */
/* </summary> */
static void opj_dwt_interleave_h(const opj_dwt_t* h, OPJ_INT32 *a)
{
- OPJ_INT32 *ai = a;
+ const OPJ_INT32 *ai = a;
OPJ_INT32 *bi = h->mem + h->cas;
OPJ_INT32 i = h->sn;
while (i--) {
@@ -321,7 +272,7 @@ static void opj_dwt_interleave_h(const opj_dwt_t* h, OPJ_INT32 *a)
/* </summary> */
static void opj_dwt_interleave_v(const opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x)
{
- OPJ_INT32 *ai = a;
+ const OPJ_INT32 *ai = a;
OPJ_INT32 *bi = v->mem + v->cas;
OPJ_INT32 i = v->sn;
while (i--) {
@@ -341,37 +292,6 @@ static void opj_dwt_interleave_v(const opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x)
#endif /* STANDARD_SLOW_VERSION */
-/* <summary> */
-/* Forward 5-3 wavelet transform in 1-D. */
-/* </summary> */
-static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn,
- OPJ_INT32 cas)
-{
- OPJ_INT32 i;
-
- if (!cas) {
- if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */
- for (i = 0; i < dn; i++) {
- OPJ_D(i) -= (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1;
- }
- for (i = 0; i < sn; i++) {
- OPJ_S(i) += (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2;
- }
- }
- } else {
- if (!sn && dn == 1) { /* NEW : CASE ONE ELEMENT */
- OPJ_S(0) *= 2;
- } else {
- for (i = 0; i < dn; i++) {
- OPJ_S(i) -= (OPJ_DD_(i) + OPJ_DD_(i - 1)) >> 1;
- }
- for (i = 0; i < sn; i++) {
- OPJ_D(i) += (OPJ_SS_(i) + OPJ_SS_(i + 1) + 2) >> 2;
- }
- }
- }
-}
-
#ifdef STANDARD_SLOW_VERSION
/* <summary> */
/* Inverse 5-3 wavelet transform in 1-D. */
@@ -1033,110 +953,799 @@ static void opj_idwt53_v(const opj_dwt_t *dwt,
#endif
}
+#if 0
+static void opj_dwt_encode_step1(OPJ_FLOAT32* fw,
+ OPJ_UINT32 end,
+ const OPJ_FLOAT32 c)
+{
+ OPJ_UINT32 i = 0;
+ for (; i < end; ++i) {
+ fw[0] *= c;
+ fw += 2;
+ }
+}
+#else
+static void opj_dwt_encode_step1_combined(OPJ_FLOAT32* fw,
+ OPJ_UINT32 iters_c1,
+ OPJ_UINT32 iters_c2,
+ const OPJ_FLOAT32 c1,
+ const OPJ_FLOAT32 c2)
+{
+ OPJ_UINT32 i = 0;
+ const OPJ_UINT32 iters_common = opj_uint_min(iters_c1, iters_c2);
+ assert((((OPJ_SIZE_T)fw) & 0xf) == 0);
+ assert(opj_int_abs((OPJ_INT32)iters_c1 - (OPJ_INT32)iters_c2) <= 1);
+ for (; i + 3 < iters_common; i += 4) {
+#ifdef __SSE__
+ const __m128 vcst = _mm_set_ps(c2, c1, c2, c1);
+ *(__m128*)fw = _mm_mul_ps(*(__m128*)fw, vcst);
+ *(__m128*)(fw + 4) = _mm_mul_ps(*(__m128*)(fw + 4), vcst);
+#else
+ fw[0] *= c1;
+ fw[1] *= c2;
+ fw[2] *= c1;
+ fw[3] *= c2;
+ fw[4] *= c1;
+ fw[5] *= c2;
+ fw[6] *= c1;
+ fw[7] *= c2;
+#endif
+ fw += 8;
+ }
+ for (; i < iters_common; i++) {
+ fw[0] *= c1;
+ fw[1] *= c2;
+ fw += 2;
+ }
+ if (i < iters_c1) {
+ fw[0] *= c1;
+ } else if (i < iters_c2) {
+ fw[1] *= c2;
+ }
+}
-/* <summary> */
-/* Forward 9-7 wavelet transform in 1-D. */
-/* </summary> */
-static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn,
+#endif
+
+static void opj_dwt_encode_step2(OPJ_FLOAT32* fl, OPJ_FLOAT32* fw,
+ OPJ_UINT32 end,
+ OPJ_UINT32 m,
+ OPJ_FLOAT32 c)
+{
+ OPJ_UINT32 i;
+ OPJ_UINT32 imax = opj_uint_min(end, m);
+ if (imax > 0) {
+ fw[-1] += (fl[0] + fw[0]) * c;
+ fw += 2;
+ i = 1;
+ for (; i + 3 < imax; i += 4) {
+ fw[-1] += (fw[-2] + fw[0]) * c;
+ fw[1] += (fw[0] + fw[2]) * c;
+ fw[3] += (fw[2] + fw[4]) * c;
+ fw[5] += (fw[4] + fw[6]) * c;
+ fw += 8;
+ }
+ for (; i < imax; ++i) {
+ fw[-1] += (fw[-2] + fw[0]) * c;
+ fw += 2;
+ }
+ }
+ if (m < end) {
+ assert(m + 1 == end);
+ fw[-1] += (2 * fw[-2]) * c;
+ }
+}
+
+static void opj_dwt_encode_1_real(void *aIn, OPJ_INT32 dn, OPJ_INT32 sn,
OPJ_INT32 cas)
{
- OPJ_INT32 i;
- if (!cas) {
- if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */
- for (i = 0; i < dn; i++) {
- OPJ_D(i) -= opj_int_fix_mul(OPJ_S_(i) + OPJ_S_(i + 1), 12993);
+ OPJ_FLOAT32* w = (OPJ_FLOAT32*)aIn;
+ OPJ_INT32 a, b;
+ assert(dn + sn > 1);
+ if (cas == 0) {
+ a = 0;
+ b = 1;
+ } else {
+ a = 1;
+ b = 0;
+ }
+ opj_dwt_encode_step2(w + a, w + b + 1,
+ (OPJ_UINT32)dn,
+ (OPJ_UINT32)opj_int_min(dn, sn - b),
+ opj_dwt_alpha);
+ opj_dwt_encode_step2(w + b, w + a + 1,
+ (OPJ_UINT32)sn,
+ (OPJ_UINT32)opj_int_min(sn, dn - a),
+ opj_dwt_beta);
+ opj_dwt_encode_step2(w + a, w + b + 1,
+ (OPJ_UINT32)dn,
+ (OPJ_UINT32)opj_int_min(dn, sn - b),
+ opj_dwt_gamma);
+ opj_dwt_encode_step2(w + b, w + a + 1,
+ (OPJ_UINT32)sn,
+ (OPJ_UINT32)opj_int_min(sn, dn - a),
+ opj_dwt_delta);
+#if 0
+ opj_dwt_encode_step1(w + b, (OPJ_UINT32)dn,
+ opj_K);
+ opj_dwt_encode_step1(w + a, (OPJ_UINT32)sn,
+ opj_invK);
+#else
+ if (a == 0) {
+ opj_dwt_encode_step1_combined(w,
+ (OPJ_UINT32)sn,
+ (OPJ_UINT32)dn,
+ opj_invK,
+ opj_K);
+ } else {
+ opj_dwt_encode_step1_combined(w,
+ (OPJ_UINT32)dn,
+ (OPJ_UINT32)sn,
+ opj_K,
+ opj_invK);
+ }
+#endif
+}
+
+static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps,
+ opj_stepsize_t *bandno_stepsize)
+{
+ OPJ_INT32 p, n;
+ p = opj_int_floorlog2(stepsize) - 13;
+ n = 11 - opj_int_floorlog2(stepsize);
+ bandno_stepsize->mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff;
+ bandno_stepsize->expn = numbps - p;
+}
+
+/*
+==========================================================
+ DWT interface
+==========================================================
+*/
+
+/** Process one line for the horizontal pass of the 5x3 forward transform */
+static
+void opj_dwt_encode_and_deinterleave_h_one_row(void* rowIn,
+ void* tmpIn,
+ OPJ_UINT32 width,
+ OPJ_BOOL even)
+{
+ OPJ_INT32* OPJ_RESTRICT row = (OPJ_INT32*)rowIn;
+ OPJ_INT32* OPJ_RESTRICT tmp = (OPJ_INT32*)tmpIn;
+ const OPJ_INT32 sn = (OPJ_INT32)((width + (even ? 1 : 0)) >> 1);
+ const OPJ_INT32 dn = (OPJ_INT32)(width - (OPJ_UINT32)sn);
+
+ if (even) {
+ if (width > 1) {
+ OPJ_INT32 i;
+ for (i = 0; i < sn - 1; i++) {
+ tmp[sn + i] = row[2 * i + 1] - ((row[(i) * 2] + row[(i + 1) * 2]) >> 1);
}
- for (i = 0; i < sn; i++) {
- OPJ_S(i) -= opj_int_fix_mul(OPJ_D_(i - 1) + OPJ_D_(i), 434);
+ if ((width % 2) == 0) {
+ tmp[sn + i] = row[2 * i + 1] - row[(i) * 2];
}
- for (i = 0; i < dn; i++) {
- OPJ_D(i) += opj_int_fix_mul(OPJ_S_(i) + OPJ_S_(i + 1), 7233);
+ row[0] += (tmp[sn] + tmp[sn] + 2) >> 2;
+ for (i = 1; i < dn; i++) {
+ row[i] = row[2 * i] + ((tmp[sn + (i - 1)] + tmp[sn + i] + 2) >> 2);
}
- for (i = 0; i < sn; i++) {
- OPJ_S(i) += opj_int_fix_mul(OPJ_D_(i - 1) + OPJ_D_(i), 3633);
+ if ((width % 2) == 1) {
+ row[i] = row[2 * i] + ((tmp[sn + (i - 1)] + tmp[sn + (i - 1)] + 2) >> 2);
}
- for (i = 0; i < dn; i++) {
- OPJ_D(i) = opj_int_fix_mul(OPJ_D(i), 5038); /*5038 */
+ memcpy(row + sn, tmp + sn, (OPJ_SIZE_T)dn * sizeof(OPJ_INT32));
+ }
+ } else {
+ if (width == 1) {
+ row[0] *= 2;
+ } else {
+ OPJ_INT32 i;
+ tmp[sn + 0] = row[0] - row[1];
+ for (i = 1; i < sn; i++) {
+ tmp[sn + i] = row[2 * i] - ((row[2 * i + 1] + row[2 * (i - 1) + 1]) >> 1);
}
- for (i = 0; i < sn; i++) {
- OPJ_S(i) = opj_int_fix_mul(OPJ_S(i), 6659); /*6660 */
+ if ((width % 2) == 1) {
+ tmp[sn + i] = row[2 * i] - row[2 * (i - 1) + 1];
+ }
+
+ for (i = 0; i < dn - 1; i++) {
+ row[i] = row[2 * i + 1] + ((tmp[sn + i] + tmp[sn + i + 1] + 2) >> 2);
}
+ if ((width % 2) == 0) {
+ row[i] = row[2 * i + 1] + ((tmp[sn + i] + tmp[sn + i] + 2) >> 2);
+ }
+ memcpy(row + sn, tmp + sn, (OPJ_SIZE_T)dn * sizeof(OPJ_INT32));
+ }
+ }
+}
+
+/** Process one line for the horizontal pass of the 9x7 forward transform */
+static
+void opj_dwt_encode_and_deinterleave_h_one_row_real(void* rowIn,
+ void* tmpIn,
+ OPJ_UINT32 width,
+ OPJ_BOOL even)
+{
+ OPJ_FLOAT32* OPJ_RESTRICT row = (OPJ_FLOAT32*)rowIn;
+ OPJ_FLOAT32* OPJ_RESTRICT tmp = (OPJ_FLOAT32*)tmpIn;
+ const OPJ_INT32 sn = (OPJ_INT32)((width + (even ? 1 : 0)) >> 1);
+ const OPJ_INT32 dn = (OPJ_INT32)(width - (OPJ_UINT32)sn);
+ if (width == 1) {
+ return;
+ }
+ memcpy(tmp, row, width * sizeof(OPJ_FLOAT32));
+ opj_dwt_encode_1_real(tmp, dn, sn, even ? 0 : 1);
+ opj_dwt_deinterleave_h((OPJ_INT32 * OPJ_RESTRICT)tmp,
+ (OPJ_INT32 * OPJ_RESTRICT)row,
+ dn, sn, even ? 0 : 1);
+}
+
+typedef struct {
+ opj_dwt_t h;
+ OPJ_UINT32 rw; /* Width of the resolution to process */
+ OPJ_UINT32 w; /* Width of tiledp */
+ OPJ_INT32 * OPJ_RESTRICT tiledp;
+ OPJ_UINT32 min_j;
+ OPJ_UINT32 max_j;
+ opj_encode_and_deinterleave_h_one_row_fnptr_type p_function;
+} opj_dwt_encode_h_job_t;
+
+static void opj_dwt_encode_h_func(void* user_data, opj_tls_t* tls)
+{
+ OPJ_UINT32 j;
+ opj_dwt_encode_h_job_t* job;
+ (void)tls;
+
+ job = (opj_dwt_encode_h_job_t*)user_data;
+ for (j = job->min_j; j < job->max_j; j++) {
+ OPJ_INT32* OPJ_RESTRICT aj = job->tiledp + j * job->w;
+ (*job->p_function)(aj, job->h.mem, job->rw,
+ job->h.cas == 0 ? OPJ_TRUE : OPJ_FALSE);
+ }
+
+ opj_aligned_free(job->h.mem);
+ opj_free(job);
+}
+
+typedef struct {
+ opj_dwt_t v;
+ OPJ_UINT32 rh;
+ OPJ_UINT32 w;
+ OPJ_INT32 * OPJ_RESTRICT tiledp;
+ OPJ_UINT32 min_j;
+ OPJ_UINT32 max_j;
+ opj_encode_and_deinterleave_v_fnptr_type p_encode_and_deinterleave_v;
+} opj_dwt_encode_v_job_t;
+
+static void opj_dwt_encode_v_func(void* user_data, opj_tls_t* tls)
+{
+ OPJ_UINT32 j;
+ opj_dwt_encode_v_job_t* job;
+ (void)tls;
+
+ job = (opj_dwt_encode_v_job_t*)user_data;
+ for (j = job->min_j; j + NB_ELTS_V8 - 1 < job->max_j; j += NB_ELTS_V8) {
+ (*job->p_encode_and_deinterleave_v)(job->tiledp + j,
+ job->v.mem,
+ job->rh,
+ job->v.cas == 0,
+ job->w,
+ NB_ELTS_V8);
+ }
+ if (j < job->max_j) {
+ (*job->p_encode_and_deinterleave_v)(job->tiledp + j,
+ job->v.mem,
+ job->rh,
+ job->v.cas == 0,
+ job->w,
+ job->max_j - j);
+ }
+
+ opj_aligned_free(job->v.mem);
+ opj_free(job);
+}
+
+/** Fetch up to cols <= NB_ELTS_V8 for each line, and put them in tmpOut */
+/* that has a NB_ELTS_V8 interleave factor. */
+static void opj_dwt_fetch_cols_vertical_pass(const void *arrayIn,
+ void *tmpOut,
+ OPJ_UINT32 height,
+ OPJ_UINT32 stride_width,
+ OPJ_UINT32 cols)
+{
+ const OPJ_INT32* OPJ_RESTRICT array = (const OPJ_INT32 * OPJ_RESTRICT)arrayIn;
+ OPJ_INT32* OPJ_RESTRICT tmp = (OPJ_INT32 * OPJ_RESTRICT)tmpOut;
+ if (cols == NB_ELTS_V8) {
+ OPJ_UINT32 k;
+ for (k = 0; k < height; ++k) {
+ memcpy(tmp + NB_ELTS_V8 * k,
+ array + k * stride_width,
+ NB_ELTS_V8 * sizeof(OPJ_INT32));
}
} else {
- if ((sn > 0) || (dn > 1)) { /* NEW : CASE ONE ELEMENT */
- for (i = 0; i < dn; i++) {
- OPJ_S(i) -= opj_int_fix_mul(OPJ_DD_(i) + OPJ_DD_(i - 1), 12993);
+ OPJ_UINT32 k;
+ for (k = 0; k < height; ++k) {
+ OPJ_UINT32 c;
+ for (c = 0; c < cols; c++) {
+ tmp[NB_ELTS_V8 * k + c] = array[c + k * stride_width];
}
- for (i = 0; i < sn; i++) {
- OPJ_D(i) -= opj_int_fix_mul(OPJ_SS_(i) + OPJ_SS_(i + 1), 434);
+ for (; c < NB_ELTS_V8; c++) {
+ tmp[NB_ELTS_V8 * k + c] = 0;
}
- for (i = 0; i < dn; i++) {
- OPJ_S(i) += opj_int_fix_mul(OPJ_DD_(i) + OPJ_DD_(i - 1), 7233);
+ }
+ }
+}
+
+/* Deinterleave result of forward transform, where cols <= NB_ELTS_V8 */
+/* and src contains NB_ELTS_V8 consecutive values for up to NB_ELTS_V8 */
+/* columns. */
+static INLINE void opj_dwt_deinterleave_v_cols(
+ const OPJ_INT32 * OPJ_RESTRICT src,
+ OPJ_INT32 * OPJ_RESTRICT dst,
+ OPJ_INT32 dn,
+ OPJ_INT32 sn,
+ OPJ_UINT32 stride_width,
+ OPJ_INT32 cas,
+ OPJ_UINT32 cols)
+{
+ OPJ_INT32 k;
+ OPJ_INT32 i = sn;
+ OPJ_INT32 * OPJ_RESTRICT l_dest = dst;
+ const OPJ_INT32 * OPJ_RESTRICT l_src = src + cas * NB_ELTS_V8;
+ OPJ_UINT32 c;
+
+ for (k = 0; k < 2; k++) {
+ while (i--) {
+ if (cols == NB_ELTS_V8) {
+ memcpy(l_dest, l_src, NB_ELTS_V8 * sizeof(OPJ_INT32));
+ } else {
+ c = 0;
+ switch (cols) {
+ case 7:
+ l_dest[c] = l_src[c];
+ c++; /* fallthru */
+ case 6:
+ l_dest[c] = l_src[c];
+ c++; /* fallthru */
+ case 5:
+ l_dest[c] = l_src[c];
+ c++; /* fallthru */
+ case 4:
+ l_dest[c] = l_src[c];
+ c++; /* fallthru */
+ case 3:
+ l_dest[c] = l_src[c];
+ c++; /* fallthru */
+ case 2:
+ l_dest[c] = l_src[c];
+ c++; /* fallthru */
+ default:
+ l_dest[c] = l_src[c];
+ break;
+ }
}
- for (i = 0; i < sn; i++) {
- OPJ_D(i) += opj_int_fix_mul(OPJ_SS_(i) + OPJ_SS_(i + 1), 3633);
+ l_dest += stride_width;
+ l_src += 2 * NB_ELTS_V8;
+ }
+
+ l_dest = dst + (OPJ_SIZE_T)sn * (OPJ_SIZE_T)stride_width;
+ l_src = src + (1 - cas) * NB_ELTS_V8;
+ i = dn;
+ }
+}
+
+
+/* Forward 5-3 transform, for the vertical pass, processing cols columns */
+/* where cols <= NB_ELTS_V8 */
+static void opj_dwt_encode_and_deinterleave_v(
+ void *arrayIn,
+ void *tmpIn,
+ OPJ_UINT32 height,
+ OPJ_BOOL even,
+ OPJ_UINT32 stride_width,
+ OPJ_UINT32 cols)
+{
+ OPJ_INT32* OPJ_RESTRICT array = (OPJ_INT32 * OPJ_RESTRICT)arrayIn;
+ OPJ_INT32* OPJ_RESTRICT tmp = (OPJ_INT32 * OPJ_RESTRICT)tmpIn;
+ const OPJ_UINT32 sn = (height + (even ? 1 : 0)) >> 1;
+ const OPJ_UINT32 dn = height - sn;
+
+ opj_dwt_fetch_cols_vertical_pass(arrayIn, tmpIn, height, stride_width, cols);
+
+#define OPJ_Sc(i) tmp[(i)*2* NB_ELTS_V8 + c]
+#define OPJ_Dc(i) tmp[((1+(i)*2))* NB_ELTS_V8 + c]
+
+#ifdef __SSE2__
+ if (height == 1) {
+ if (!even) {
+ OPJ_UINT32 c;
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ tmp[c] *= 2;
}
- for (i = 0; i < dn; i++) {
- OPJ_S(i) = opj_int_fix_mul(OPJ_S(i), 5038); /*5038 */
+ }
+ } else if (even) {
+ OPJ_UINT32 c;
+ OPJ_UINT32 i;
+ i = 0;
+ if (i + 1 < sn) {
+ __m128i xmm_Si_0 = *(const __m128i*)(tmp + 4 * 0);
+ __m128i xmm_Si_1 = *(const __m128i*)(tmp + 4 * 1);
+ for (; i + 1 < sn; i++) {
+ __m128i xmm_Sip1_0 = *(const __m128i*)(tmp +
+ (i + 1) * 2 * NB_ELTS_V8 + 4 * 0);
+ __m128i xmm_Sip1_1 = *(const __m128i*)(tmp +
+ (i + 1) * 2 * NB_ELTS_V8 + 4 * 1);
+ __m128i xmm_Di_0 = *(const __m128i*)(tmp +
+ (1 + i * 2) * NB_ELTS_V8 + 4 * 0);
+ __m128i xmm_Di_1 = *(const __m128i*)(tmp +
+ (1 + i * 2) * NB_ELTS_V8 + 4 * 1);
+ xmm_Di_0 = _mm_sub_epi32(xmm_Di_0,
+ _mm_srai_epi32(_mm_add_epi32(xmm_Si_0, xmm_Sip1_0), 1));
+ xmm_Di_1 = _mm_sub_epi32(xmm_Di_1,
+ _mm_srai_epi32(_mm_add_epi32(xmm_Si_1, xmm_Sip1_1), 1));
+ *(__m128i*)(tmp + (1 + i * 2) * NB_ELTS_V8 + 4 * 0) = xmm_Di_0;
+ *(__m128i*)(tmp + (1 + i * 2) * NB_ELTS_V8 + 4 * 1) = xmm_Di_1;
+ xmm_Si_0 = xmm_Sip1_0;
+ xmm_Si_1 = xmm_Sip1_1;
}
- for (i = 0; i < sn; i++) {
- OPJ_D(i) = opj_int_fix_mul(OPJ_D(i), 6659); /*6660 */
+ }
+ if (((height) % 2) == 0) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Dc(i) -= OPJ_Sc(i);
+ }
+ }
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(0) += (OPJ_Dc(0) + OPJ_Dc(0) + 2) >> 2;
+ }
+ i = 1;
+ if (i < dn) {
+ __m128i xmm_Dim1_0 = *(const __m128i*)(tmp + (1 +
+ (i - 1) * 2) * NB_ELTS_V8 + 4 * 0);
+ __m128i xmm_Dim1_1 = *(const __m128i*)(tmp + (1 +
+ (i - 1) * 2) * NB_ELTS_V8 + 4 * 1);
+ const __m128i xmm_two = _mm_set1_epi32(2);
+ for (; i < dn; i++) {
+ __m128i xmm_Di_0 = *(const __m128i*)(tmp +
+ (1 + i * 2) * NB_ELTS_V8 + 4 * 0);
+ __m128i xmm_Di_1 = *(const __m128i*)(tmp +
+ (1 + i * 2) * NB_ELTS_V8 + 4 * 1);
+ __m128i xmm_Si_0 = *(const __m128i*)(tmp +
+ (i * 2) * NB_ELTS_V8 + 4 * 0);
+ __m128i xmm_Si_1 = *(const __m128i*)(tmp +
+ (i * 2) * NB_ELTS_V8 + 4 * 1);
+ xmm_Si_0 = _mm_add_epi32(xmm_Si_0,
+ _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(xmm_Dim1_0, xmm_Di_0), xmm_two), 2));
+ xmm_Si_1 = _mm_add_epi32(xmm_Si_1,
+ _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(xmm_Dim1_1, xmm_Di_1), xmm_two), 2));
+ *(__m128i*)(tmp + (i * 2) * NB_ELTS_V8 + 4 * 0) = xmm_Si_0;
+ *(__m128i*)(tmp + (i * 2) * NB_ELTS_V8 + 4 * 1) = xmm_Si_1;
+ xmm_Dim1_0 = xmm_Di_0;
+ xmm_Dim1_1 = xmm_Di_1;
+ }
+ }
+ if (((height) % 2) == 1) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(i) += (OPJ_Dc(i - 1) + OPJ_Dc(i - 1) + 2) >> 2;
+ }
+ }
+ } else {
+ OPJ_UINT32 c;
+ OPJ_UINT32 i;
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(0) -= OPJ_Dc(0);
+ }
+ i = 1;
+ if (i < sn) {
+ __m128i xmm_Dim1_0 = *(const __m128i*)(tmp + (1 +
+ (i - 1) * 2) * NB_ELTS_V8 + 4 * 0);
+ __m128i xmm_Dim1_1 = *(const __m128i*)(tmp + (1 +
+ (i - 1) * 2) * NB_ELTS_V8 + 4 * 1);
+ for (; i < sn; i++) {
+ __m128i xmm_Di_0 = *(const __m128i*)(tmp +
+ (1 + i * 2) * NB_ELTS_V8 + 4 * 0);
+ __m128i xmm_Di_1 = *(const __m128i*)(tmp +
+ (1 + i * 2) * NB_ELTS_V8 + 4 * 1);
+ __m128i xmm_Si_0 = *(const __m128i*)(tmp +
+ (i * 2) * NB_ELTS_V8 + 4 * 0);
+ __m128i xmm_Si_1 = *(const __m128i*)(tmp +
+ (i * 2) * NB_ELTS_V8 + 4 * 1);
+ xmm_Si_0 = _mm_sub_epi32(xmm_Si_0,
+ _mm_srai_epi32(_mm_add_epi32(xmm_Di_0, xmm_Dim1_0), 1));
+ xmm_Si_1 = _mm_sub_epi32(xmm_Si_1,
+ _mm_srai_epi32(_mm_add_epi32(xmm_Di_1, xmm_Dim1_1), 1));
+ *(__m128i*)(tmp + (i * 2) * NB_ELTS_V8 + 4 * 0) = xmm_Si_0;
+ *(__m128i*)(tmp + (i * 2) * NB_ELTS_V8 + 4 * 1) = xmm_Si_1;
+ xmm_Dim1_0 = xmm_Di_0;
+ xmm_Dim1_1 = xmm_Di_1;
+ }
+ }
+ if (((height) % 2) == 1) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(i) -= OPJ_Dc(i - 1);
+ }
+ }
+ i = 0;
+ if (i + 1 < dn) {
+ __m128i xmm_Si_0 = *((const __m128i*)(tmp + 4 * 0));
+ __m128i xmm_Si_1 = *((const __m128i*)(tmp + 4 * 1));
+ const __m128i xmm_two = _mm_set1_epi32(2);
+ for (; i + 1 < dn; i++) {
+ __m128i xmm_Sip1_0 = *(const __m128i*)(tmp +
+ (i + 1) * 2 * NB_ELTS_V8 + 4 * 0);
+ __m128i xmm_Sip1_1 = *(const __m128i*)(tmp +
+ (i + 1) * 2 * NB_ELTS_V8 + 4 * 1);
+ __m128i xmm_Di_0 = *(const __m128i*)(tmp +
+ (1 + i * 2) * NB_ELTS_V8 + 4 * 0);
+ __m128i xmm_Di_1 = *(const __m128i*)(tmp +
+ (1 + i * 2) * NB_ELTS_V8 + 4 * 1);
+ xmm_Di_0 = _mm_add_epi32(xmm_Di_0,
+ _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(xmm_Si_0, xmm_Sip1_0), xmm_two), 2));
+ xmm_Di_1 = _mm_add_epi32(xmm_Di_1,
+ _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(xmm_Si_1, xmm_Sip1_1), xmm_two), 2));
+ *(__m128i*)(tmp + (1 + i * 2) * NB_ELTS_V8 + 4 * 0) = xmm_Di_0;
+ *(__m128i*)(tmp + (1 + i * 2) * NB_ELTS_V8 + 4 * 1) = xmm_Di_1;
+ xmm_Si_0 = xmm_Sip1_0;
+ xmm_Si_1 = xmm_Sip1_1;
+ }
+ }
+ if (((height) % 2) == 0) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Dc(i) += (OPJ_Sc(i) + OPJ_Sc(i) + 2) >> 2;
+ }
+ }
+ }
+#else
+ if (even) {
+ OPJ_UINT32 c;
+ if (height > 1) {
+ OPJ_UINT32 i;
+ for (i = 0; i + 1 < sn; i++) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Dc(i) -= (OPJ_Sc(i) + OPJ_Sc(i + 1)) >> 1;
+ }
+ }
+ if (((height) % 2) == 0) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Dc(i) -= OPJ_Sc(i);
+ }
+ }
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(0) += (OPJ_Dc(0) + OPJ_Dc(0) + 2) >> 2;
+ }
+ for (i = 1; i < dn; i++) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(i) += (OPJ_Dc(i - 1) + OPJ_Dc(i) + 2) >> 2;
+ }
+ }
+ if (((height) % 2) == 1) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(i) += (OPJ_Dc(i - 1) + OPJ_Dc(i - 1) + 2) >> 2;
+ }
}
}
+ } else {
+ OPJ_UINT32 c;
+ if (height == 1) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(0) *= 2;
+ }
+ } else {
+ OPJ_UINT32 i;
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(0) -= OPJ_Dc(0);
+ }
+ for (i = 1; i < sn; i++) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(i) -= (OPJ_Dc(i) + OPJ_Dc(i - 1)) >> 1;
+ }
+ }
+ if (((height) % 2) == 1) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Sc(i) -= OPJ_Dc(i - 1);
+ }
+ }
+ for (i = 0; i + 1 < dn; i++) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Dc(i) += (OPJ_Sc(i) + OPJ_Sc(i + 1) + 2) >> 2;
+ }
+ }
+ if (((height) % 2) == 0) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ OPJ_Dc(i) += (OPJ_Sc(i) + OPJ_Sc(i) + 2) >> 2;
+ }
+ }
+ }
+ }
+#endif
+
+ if (cols == NB_ELTS_V8) {
+ opj_dwt_deinterleave_v_cols(tmp, array, (OPJ_INT32)dn, (OPJ_INT32)sn,
+ stride_width, even ? 0 : 1, NB_ELTS_V8);
+ } else {
+ opj_dwt_deinterleave_v_cols(tmp, array, (OPJ_INT32)dn, (OPJ_INT32)sn,
+ stride_width, even ? 0 : 1, cols);
}
}
-static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps,
- opj_stepsize_t *bandno_stepsize)
+static void opj_v8dwt_encode_step1(OPJ_FLOAT32* fw,
+ OPJ_UINT32 end,
+ const OPJ_FLOAT32 cst)
{
- OPJ_INT32 p, n;
- p = opj_int_floorlog2(stepsize) - 13;
- n = 11 - opj_int_floorlog2(stepsize);
- bandno_stepsize->mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff;
- bandno_stepsize->expn = numbps - p;
+ OPJ_UINT32 i;
+#ifdef __SSE__
+ __m128* vw = (__m128*) fw;
+ const __m128 vcst = _mm_set1_ps(cst);
+ for (i = 0; i < end; ++i) {
+ vw[0] = _mm_mul_ps(vw[0], vcst);
+ vw[1] = _mm_mul_ps(vw[1], vcst);
+ vw += 2 * (NB_ELTS_V8 * sizeof(OPJ_FLOAT32) / sizeof(__m128));
+ }
+#else
+ OPJ_UINT32 c;
+ for (i = 0; i < end; ++i) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ fw[i * 2 * NB_ELTS_V8 + c] *= cst;
+ }
+ }
+#endif
}
-/*
-==========================================================
- DWT interface
-==========================================================
-*/
+static void opj_v8dwt_encode_step2(OPJ_FLOAT32* fl, OPJ_FLOAT32* fw,
+ OPJ_UINT32 end,
+ OPJ_UINT32 m,
+ OPJ_FLOAT32 cst)
+{
+ OPJ_UINT32 i;
+ OPJ_UINT32 imax = opj_uint_min(end, m);
+#ifdef __SSE__
+ __m128* vw = (__m128*) fw;
+ __m128 vcst = _mm_set1_ps(cst);
+ if (imax > 0) {
+ __m128* vl = (__m128*) fl;
+ vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(_mm_add_ps(vl[0], vw[0]), vcst));
+ vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(_mm_add_ps(vl[1], vw[1]), vcst));
+ vw += 2 * (NB_ELTS_V8 * sizeof(OPJ_FLOAT32) / sizeof(__m128));
+ i = 1;
+
+ for (; i < imax; ++i) {
+ vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(_mm_add_ps(vw[-4], vw[0]), vcst));
+ vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(_mm_add_ps(vw[-3], vw[1]), vcst));
+ vw += 2 * (NB_ELTS_V8 * sizeof(OPJ_FLOAT32) / sizeof(__m128));
+ }
+ }
+ if (m < end) {
+ assert(m + 1 == end);
+ vcst = _mm_add_ps(vcst, vcst);
+ vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(vw[-4], vcst));
+ vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(vw[-3], vcst));
+ }
+#else
+ OPJ_INT32 c;
+ if (imax > 0) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ fw[-1 * NB_ELTS_V8 + c] += (fl[0 * NB_ELTS_V8 + c] + fw[0 * NB_ELTS_V8 + c]) *
+ cst;
+ }
+ fw += 2 * NB_ELTS_V8;
+ i = 1;
+ for (; i < imax; ++i) {
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ fw[-1 * NB_ELTS_V8 + c] += (fw[-2 * NB_ELTS_V8 + c] + fw[0 * NB_ELTS_V8 + c]) *
+ cst;
+ }
+ fw += 2 * NB_ELTS_V8;
+ }
+ }
+ if (m < end) {
+ assert(m + 1 == end);
+ for (c = 0; c < NB_ELTS_V8; c++) {
+ fw[-1 * NB_ELTS_V8 + c] += (2 * fw[-2 * NB_ELTS_V8 + c]) * cst;
+ }
+ }
+#endif
+}
+
+/* Forward 9-7 transform, for the vertical pass, processing cols columns */
+/* where cols <= NB_ELTS_V8 */
+static void opj_dwt_encode_and_deinterleave_v_real(
+ void *arrayIn,
+ void *tmpIn,
+ OPJ_UINT32 height,
+ OPJ_BOOL even,
+ OPJ_UINT32 stride_width,
+ OPJ_UINT32 cols)
+{
+ OPJ_FLOAT32* OPJ_RESTRICT array = (OPJ_FLOAT32 * OPJ_RESTRICT)arrayIn;
+ OPJ_FLOAT32* OPJ_RESTRICT tmp = (OPJ_FLOAT32 * OPJ_RESTRICT)tmpIn;
+ const OPJ_INT32 sn = (OPJ_INT32)((height + (even ? 1 : 0)) >> 1);
+ const OPJ_INT32 dn = (OPJ_INT32)(height - (OPJ_UINT32)sn);
+ OPJ_INT32 a, b;
+
+ if (height == 1) {
+ return;
+ }
+
+ opj_dwt_fetch_cols_vertical_pass(arrayIn, tmpIn, height, stride_width, cols);
+
+ if (even) {
+ a = 0;
+ b = 1;
+ } else {
+ a = 1;
+ b = 0;
+ }
+ opj_v8dwt_encode_step2(tmp + a * NB_ELTS_V8,
+ tmp + (b + 1) * NB_ELTS_V8,
+ (OPJ_UINT32)dn,
+ (OPJ_UINT32)opj_int_min(dn, sn - b),
+ opj_dwt_alpha);
+ opj_v8dwt_encode_step2(tmp + b * NB_ELTS_V8,
+ tmp + (a + 1) * NB_ELTS_V8,
+ (OPJ_UINT32)sn,
+ (OPJ_UINT32)opj_int_min(sn, dn - a),
+ opj_dwt_beta);
+ opj_v8dwt_encode_step2(tmp + a * NB_ELTS_V8,
+ tmp + (b + 1) * NB_ELTS_V8,
+ (OPJ_UINT32)dn,
+ (OPJ_UINT32)opj_int_min(dn, sn - b),
+ opj_dwt_gamma);
+ opj_v8dwt_encode_step2(tmp + b * NB_ELTS_V8,
+ tmp + (a + 1) * NB_ELTS_V8,
+ (OPJ_UINT32)sn,
+ (OPJ_UINT32)opj_int_min(sn, dn - a),
+ opj_dwt_delta);
+ opj_v8dwt_encode_step1(tmp + b * NB_ELTS_V8, (OPJ_UINT32)dn,
+ opj_K);
+ opj_v8dwt_encode_step1(tmp + a * NB_ELTS_V8, (OPJ_UINT32)sn,
+ opj_invK);
+
+
+ if (cols == NB_ELTS_V8) {
+ opj_dwt_deinterleave_v_cols((OPJ_INT32*)tmp,
+ (OPJ_INT32*)array,
+ (OPJ_INT32)dn, (OPJ_INT32)sn,
+ stride_width, even ? 0 : 1, NB_ELTS_V8);
+ } else {
+ opj_dwt_deinterleave_v_cols((OPJ_INT32*)tmp,
+ (OPJ_INT32*)array,
+ (OPJ_INT32)dn, (OPJ_INT32)sn,
+ stride_width, even ? 0 : 1, cols);
+ }
+}
/* <summary> */
/* Forward 5-3 wavelet transform in 2-D. */
/* </summary> */
-static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
- void (*p_function)(OPJ_INT32 *, OPJ_INT32, OPJ_INT32, OPJ_INT32))
+static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_thread_pool_t* tp,
+ opj_tcd_tilecomp_t * tilec,
+ opj_encode_and_deinterleave_v_fnptr_type p_encode_and_deinterleave_v,
+ opj_encode_and_deinterleave_h_one_row_fnptr_type
+ p_encode_and_deinterleave_h_one_row)
{
- OPJ_INT32 i, j, k;
- OPJ_INT32 *a = 00;
- OPJ_INT32 *aj = 00;
+ OPJ_INT32 i;
OPJ_INT32 *bj = 00;
- OPJ_INT32 w, l;
+ OPJ_UINT32 w;
+ OPJ_INT32 l;
- OPJ_INT32 rw; /* width of the resolution level computed */
- OPJ_INT32 rh; /* height of the resolution level computed */
OPJ_SIZE_T l_data_size;
opj_tcd_resolution_t * l_cur_res = 0;
opj_tcd_resolution_t * l_last_res = 0;
+ const int num_threads = opj_thread_pool_get_thread_count(tp);
+ OPJ_INT32 * OPJ_RESTRICT tiledp = tilec->data;
- w = tilec->x1 - tilec->x0;
+ w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
l = (OPJ_INT32)tilec->numresolutions - 1;
- a = tilec->data;
l_cur_res = tilec->resolutions + l;
l_last_res = l_cur_res - 1;
l_data_size = opj_dwt_max_resolution(tilec->resolutions, tilec->numresolutions);
/* overflow check */
- if (l_data_size > (SIZE_MAX / sizeof(OPJ_INT32))) {
+ if (l_data_size > (SIZE_MAX / (NB_ELTS_V8 * sizeof(OPJ_INT32)))) {
/* FIXME event manager error callback */
return OPJ_FALSE;
}
- l_data_size *= sizeof(OPJ_INT32);
- bj = (OPJ_INT32*)opj_malloc(l_data_size);
+ l_data_size *= NB_ELTS_V8 * sizeof(OPJ_INT32);
+ bj = (OPJ_INT32*)opj_aligned_32_malloc(l_data_size);
/* l_data_size is equal to 0 when numresolutions == 1 but bj is not used */
/* in that case, so do not error out */
if (l_data_size != 0 && ! bj) {
@@ -1145,43 +1754,135 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
i = l;
while (i--) {
- OPJ_INT32 rw1; /* width of the resolution level once lower than computed one */
- OPJ_INT32 rh1; /* height of the resolution level once lower than computed one */
+ OPJ_UINT32 j;
+ OPJ_UINT32 rw; /* width of the resolution level computed */
+ OPJ_UINT32 rh; /* height of the resolution level computed */
+ OPJ_UINT32
+ rw1; /* width of the resolution level once lower than computed one */
+ OPJ_UINT32
+ rh1; /* height of the resolution level once lower than computed one */
OPJ_INT32 cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */
OPJ_INT32 cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */
OPJ_INT32 dn, sn;
- rw = l_cur_res->x1 - l_cur_res->x0;
- rh = l_cur_res->y1 - l_cur_res->y0;
- rw1 = l_last_res->x1 - l_last_res->x0;
- rh1 = l_last_res->y1 - l_last_res->y0;
+ rw = (OPJ_UINT32)(l_cur_res->x1 - l_cur_res->x0);
+ rh = (OPJ_UINT32)(l_cur_res->y1 - l_cur_res->y0);
+ rw1 = (OPJ_UINT32)(l_last_res->x1 - l_last_res->x0);
+ rh1 = (OPJ_UINT32)(l_last_res->y1 - l_last_res->y0);
cas_row = l_cur_res->x0 & 1;
cas_col = l_cur_res->y0 & 1;
- sn = rh1;
- dn = rh - rh1;
- for (j = 0; j < rw; ++j) {
- aj = a + j;
- for (k = 0; k < rh; ++k) {
- bj[k] = aj[k * w];
+ sn = (OPJ_INT32)rh1;
+ dn = (OPJ_INT32)(rh - rh1);
+
+ /* Perform vertical pass */
+ if (num_threads <= 1 || rw < 2 * NB_ELTS_V8) {
+ for (j = 0; j + NB_ELTS_V8 - 1 < rw; j += NB_ELTS_V8) {
+ p_encode_and_deinterleave_v(tiledp + j,
+ bj,
+ rh,
+ cas_col == 0,
+ w,
+ NB_ELTS_V8);
+ }
+ if (j < rw) {
+ p_encode_and_deinterleave_v(tiledp + j,
+ bj,
+ rh,
+ cas_col == 0,
+ w,
+ rw - j);
}
+ } else {
+ OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads;
+ OPJ_UINT32 step_j;
- (*p_function)(bj, dn, sn, cas_col);
+ if (rw < num_jobs) {
+ num_jobs = rw;
+ }
+ step_j = ((rw / num_jobs) / NB_ELTS_V8) * NB_ELTS_V8;
- opj_dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col);
+ for (j = 0; j < num_jobs; j++) {
+ opj_dwt_encode_v_job_t* job;
+
+ job = (opj_dwt_encode_v_job_t*) opj_malloc(sizeof(opj_dwt_encode_v_job_t));
+ if (!job) {
+ opj_thread_pool_wait_completion(tp, 0);
+ opj_aligned_free(bj);
+ return OPJ_FALSE;
+ }
+ job->v.mem = (OPJ_INT32*)opj_aligned_32_malloc(l_data_size);
+ if (!job->v.mem) {
+ opj_thread_pool_wait_completion(tp, 0);
+ opj_free(job);
+ opj_aligned_free(bj);
+ return OPJ_FALSE;
+ }
+ job->v.dn = dn;
+ job->v.sn = sn;
+ job->v.cas = cas_col;
+ job->rh = rh;
+ job->w = w;
+ job->tiledp = tiledp;
+ job->min_j = j * step_j;
+ job->max_j = (j + 1 == num_jobs) ? rw : (j + 1) * step_j;
+ job->p_encode_and_deinterleave_v = p_encode_and_deinterleave_v;
+ opj_thread_pool_submit_job(tp, opj_dwt_encode_v_func, job);
+ }
+ opj_thread_pool_wait_completion(tp, 0);
}
- sn = rw1;
- dn = rw - rw1;
+ sn = (OPJ_INT32)rw1;
+ dn = (OPJ_INT32)(rw - rw1);
- for (j = 0; j < rh; j++) {
- aj = a + j * w;
- for (k = 0; k < rw; k++) {
- bj[k] = aj[k];
+ /* Perform horizontal pass */
+ if (num_threads <= 1 || rh <= 1) {
+ for (j = 0; j < rh; j++) {
+ OPJ_INT32* OPJ_RESTRICT aj = tiledp + j * w;
+ (*p_encode_and_deinterleave_h_one_row)(aj, bj, rw,
+ cas_row == 0 ? OPJ_TRUE : OPJ_FALSE);
+ }
+ } else {
+ OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads;
+ OPJ_UINT32 step_j;
+
+ if (rh < num_jobs) {
+ num_jobs = rh;
+ }
+ step_j = (rh / num_jobs);
+
+ for (j = 0; j < num_jobs; j++) {
+ opj_dwt_encode_h_job_t* job;
+
+ job = (opj_dwt_encode_h_job_t*) opj_malloc(sizeof(opj_dwt_encode_h_job_t));
+ if (!job) {
+ opj_thread_pool_wait_completion(tp, 0);
+ opj_aligned_free(bj);
+ return OPJ_FALSE;
+ }
+ job->h.mem = (OPJ_INT32*)opj_aligned_32_malloc(l_data_size);
+ if (!job->h.mem) {
+ opj_thread_pool_wait_completion(tp, 0);
+ opj_free(job);
+ opj_aligned_free(bj);
+ return OPJ_FALSE;
+ }
+ job->h.dn = dn;
+ job->h.sn = sn;
+ job->h.cas = cas_row;
+ job->rw = rw;
+ job->w = w;
+ job->tiledp = tiledp;
+ job->min_j = j * step_j;
+ job->max_j = (j + 1U) * step_j; /* this can overflow */
+ if (j == (num_jobs - 1U)) { /* this will take care of the overflow */
+ job->max_j = rh;
+ }
+ job->p_function = p_encode_and_deinterleave_h_one_row;
+ opj_thread_pool_submit_job(tp, opj_dwt_encode_h_func, job);
}
- (*p_function)(bj, dn, sn, cas_row);
- opj_dwt_deinterleave_h(bj, aj, dn, sn, cas_row);
+ opj_thread_pool_wait_completion(tp, 0);
}
l_cur_res = l_last_res;
@@ -1189,15 +1890,18 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
--l_last_res;
}
- opj_free(bj);
+ opj_aligned_free(bj);
return OPJ_TRUE;
}
/* Forward 5-3 wavelet transform in 2-D. */
/* </summary> */
-OPJ_BOOL opj_dwt_encode(opj_tcd_tilecomp_t * tilec)
+OPJ_BOOL opj_dwt_encode(opj_tcd_t *p_tcd,
+ opj_tcd_tilecomp_t * tilec)
{
- return opj_dwt_encode_procedure(tilec, opj_dwt_encode_1);
+ return opj_dwt_encode_procedure(p_tcd->thread_pool, tilec,
+ opj_dwt_encode_and_deinterleave_v,
+ opj_dwt_encode_and_deinterleave_h_one_row);
}
/* <summary> */
@@ -1213,21 +1917,6 @@ OPJ_BOOL opj_dwt_decode(opj_tcd_t *p_tcd, opj_tcd_tilecomp_t* tilec,
}
}
-
-/* <summary> */
-/* Get gain of 5-3 wavelet transform. */
-/* </summary> */
-OPJ_UINT32 opj_dwt_getgain(OPJ_UINT32 orient)
-{
- if (orient == 0) {
- return 0;
- }
- if (orient == 1 || orient == 2) {
- return 1;
- }
- return 2;
-}
-
/* <summary> */
/* Get norm of 5-3 wavelet. */
/* </summary> */
@@ -1247,18 +1936,12 @@ OPJ_FLOAT64 opj_dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient)
/* <summary> */
/* Forward 9-7 wavelet transform in 2-D. */
/* </summary> */
-OPJ_BOOL opj_dwt_encode_real(opj_tcd_tilecomp_t * tilec)
-{
- return opj_dwt_encode_procedure(tilec, opj_dwt_encode_1_real);
-}
-
-/* <summary> */
-/* Get gain of 9-7 wavelet transform. */
-/* </summary> */
-OPJ_UINT32 opj_dwt_getgain_real(OPJ_UINT32 orient)
+OPJ_BOOL opj_dwt_encode_real(opj_tcd_t *p_tcd,
+ opj_tcd_tilecomp_t * tilec)
{
- (void)orient;
- return 0;
+ return opj_dwt_encode_procedure(p_tcd->thread_pool, tilec,
+ opj_dwt_encode_and_deinterleave_v_real,
+ opj_dwt_encode_and_deinterleave_h_one_row_real);
}
/* <summary> */
@@ -1328,15 +2011,15 @@ typedef struct {
OPJ_INT32 * OPJ_RESTRICT tiledp;
OPJ_UINT32 min_j;
OPJ_UINT32 max_j;
-} opj_dwd_decode_h_job_t;
+} opj_dwt_decode_h_job_t;
static void opj_dwt_decode_h_func(void* user_data, opj_tls_t* tls)
{
OPJ_UINT32 j;
- opj_dwd_decode_h_job_t* job;
+ opj_dwt_decode_h_job_t* job;
(void)tls;
- job = (opj_dwd_decode_h_job_t*)user_data;
+ job = (opj_dwt_decode_h_job_t*)user_data;
for (j = job->min_j; j < job->max_j; j++) {
opj_idwt53_h(&job->h, &job->tiledp[j * job->w]);
}
@@ -1352,15 +2035,15 @@ typedef struct {
OPJ_INT32 * OPJ_RESTRICT tiledp;
OPJ_UINT32 min_j;
OPJ_UINT32 max_j;
-} opj_dwd_decode_v_job_t;
+} opj_dwt_decode_v_job_t;
static void opj_dwt_decode_v_func(void* user_data, opj_tls_t* tls)
{
OPJ_UINT32 j;
- opj_dwd_decode_v_job_t* job;
+ opj_dwt_decode_v_job_t* job;
(void)tls;
- job = (opj_dwd_decode_v_job_t*)user_data;
+ job = (opj_dwt_decode_v_job_t*)user_data;
for (j = job->min_j; j + PARALLEL_COLS_53 <= job->max_j;
j += PARALLEL_COLS_53) {
opj_idwt53_v(&job->v, &job->tiledp[j], (OPJ_SIZE_T)job->w,
@@ -1447,9 +2130,9 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp,
step_j = (rh / num_jobs);
for (j = 0; j < num_jobs; j++) {
- opj_dwd_decode_h_job_t* job;
+ opj_dwt_decode_h_job_t* job;
- job = (opj_dwd_decode_h_job_t*) opj_malloc(sizeof(opj_dwd_decode_h_job_t));
+ job = (opj_dwt_decode_h_job_t*) opj_malloc(sizeof(opj_dwt_decode_h_job_t));
if (!job) {
/* It would be nice to fallback to single thread case, but */
/* unfortunately some jobs may be launched and have modified */
@@ -1502,9 +2185,9 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp,
step_j = (rw / num_jobs);
for (j = 0; j < num_jobs; j++) {
- opj_dwd_decode_v_job_t* job;
+ opj_dwt_decode_v_job_t* job;
- job = (opj_dwd_decode_v_job_t*) opj_malloc(sizeof(opj_dwd_decode_v_job_t));
+ job = (opj_dwt_decode_v_job_t*) opj_malloc(sizeof(opj_dwt_decode_v_job_t));
if (!job) {
/* It would be nice to fallback to single thread case, but */
/* unfortunately some jobs may be launched and have modified */
@@ -2168,7 +2851,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile(
return OPJ_TRUE;
}
-static void opj_v4dwt_interleave_h(opj_v4dwt_t* OPJ_RESTRICT dwt,
+static void opj_v8dwt_interleave_h(opj_v8dwt_t* OPJ_RESTRICT dwt,
OPJ_FLOAT32* OPJ_RESTRICT a,
OPJ_UINT32 width,
OPJ_UINT32 remaining_height)
@@ -2179,39 +2862,69 @@ static void opj_v4dwt_interleave_h(opj_v4dwt_t* OPJ_RESTRICT dwt,
OPJ_UINT32 x1 = dwt->win_l_x1;
for (k = 0; k < 2; ++k) {
- if (remaining_height >= 4 && ((OPJ_SIZE_T) a & 0x0f) == 0 &&
- ((OPJ_SIZE_T) bi & 0x0f) == 0 && (width & 0x0f) == 0) {
+ if (remaining_height >= NB_ELTS_V8 && ((OPJ_SIZE_T) a & 0x0f) == 0 &&
+ ((OPJ_SIZE_T) bi & 0x0f) == 0) {
/* Fast code path */
for (i = x0; i < x1; ++i) {
OPJ_UINT32 j = i;
- bi[i * 8 ] = a[j];
+ OPJ_FLOAT32* OPJ_RESTRICT dst = bi + i * 2 * NB_ELTS_V8;
+ dst[0] = a[j];
+ j += width;
+ dst[1] = a[j];
+ j += width;
+ dst[2] = a[j];
+ j += width;
+ dst[3] = a[j];
+ j += width;
+ dst[4] = a[j];
j += width;
- bi[i * 8 + 1] = a[j];
+ dst[5] = a[j];
j += width;
- bi[i * 8 + 2] = a[j];
+ dst[6] = a[j];
j += width;
- bi[i * 8 + 3] = a[j];
+ dst[7] = a[j];
}
} else {
/* Slow code path */
for (i = x0; i < x1; ++i) {
OPJ_UINT32 j = i;
- bi[i * 8 ] = a[j];
+ OPJ_FLOAT32* OPJ_RESTRICT dst = bi + i * 2 * NB_ELTS_V8;
+ dst[0] = a[j];
j += width;
if (remaining_height == 1) {
continue;
}
- bi[i * 8 + 1] = a[j];
+ dst[1] = a[j];
j += width;
if (remaining_height == 2) {
continue;
}
- bi[i * 8 + 2] = a[j];
+ dst[2] = a[j];
j += width;
if (remaining_height == 3) {
continue;
}
- bi[i * 8 + 3] = a[j]; /* This one*/
+ dst[3] = a[j];
+ j += width;
+ if (remaining_height == 4) {
+ continue;
+ }
+ dst[4] = a[j];
+ j += width;
+ if (remaining_height == 5) {
+ continue;
+ }
+ dst[5] = a[j];
+ j += width;
+ if (remaining_height == 6) {
+ continue;
+ }
+ dst[6] = a[j];
+ j += width;
+ if (remaining_height == 7) {
+ continue;
+ }
+ dst[7] = a[j];
}
}
@@ -2222,7 +2935,7 @@ static void opj_v4dwt_interleave_h(opj_v4dwt_t* OPJ_RESTRICT dwt,
}
}
-static void opj_v4dwt_interleave_partial_h(opj_v4dwt_t* dwt,
+static void opj_v8dwt_interleave_partial_h(opj_v8dwt_t* dwt,
opj_sparse_array_int32_t* sa,
OPJ_UINT32 sa_line,
OPJ_UINT32 remaining_height)
@@ -2235,25 +2948,25 @@ static void opj_v4dwt_interleave_partial_h(opj_v4dwt_t* dwt,
dwt->win_l_x1, sa_line + i + 1,
/* Nasty cast from float* to int32* */
(OPJ_INT32*)(dwt->wavelet + dwt->cas + 2 * dwt->win_l_x0) + i,
- 8, 0, OPJ_TRUE);
+ 2 * NB_ELTS_V8, 0, OPJ_TRUE);
assert(ret);
ret = opj_sparse_array_int32_read(sa,
(OPJ_UINT32)dwt->sn + dwt->win_h_x0, sa_line + i,
(OPJ_UINT32)dwt->sn + dwt->win_h_x1, sa_line + i + 1,
/* Nasty cast from float* to int32* */
(OPJ_INT32*)(dwt->wavelet + 1 - dwt->cas + 2 * dwt->win_h_x0) + i,
- 8, 0, OPJ_TRUE);
+ 2 * NB_ELTS_V8, 0, OPJ_TRUE);
assert(ret);
OPJ_UNUSED(ret);
}
}
-static void opj_v4dwt_interleave_v(opj_v4dwt_t* OPJ_RESTRICT dwt,
- OPJ_FLOAT32* OPJ_RESTRICT a,
- OPJ_UINT32 width,
- OPJ_UINT32 nb_elts_read)
+static INLINE void opj_v8dwt_interleave_v(opj_v8dwt_t* OPJ_RESTRICT dwt,
+ OPJ_FLOAT32* OPJ_RESTRICT a,
+ OPJ_UINT32 width,
+ OPJ_UINT32 nb_elts_read)
{
- opj_v4_t* OPJ_RESTRICT bi = dwt->wavelet + dwt->cas;
+ opj_v8_t* OPJ_RESTRICT bi = dwt->wavelet + dwt->cas;
OPJ_UINT32 i;
for (i = dwt->win_l_x0; i < dwt->win_l_x1; ++i) {
@@ -2270,7 +2983,7 @@ static void opj_v4dwt_interleave_v(opj_v4dwt_t* OPJ_RESTRICT dwt,
}
}
-static void opj_v4dwt_interleave_partial_v(opj_v4dwt_t* OPJ_RESTRICT dwt,
+static void opj_v8dwt_interleave_partial_v(opj_v8dwt_t* OPJ_RESTRICT dwt,
opj_sparse_array_int32_t* sa,
OPJ_UINT32 sa_col,
OPJ_UINT32 nb_elts_read)
@@ -2280,44 +2993,36 @@ static void opj_v4dwt_interleave_partial_v(opj_v4dwt_t* OPJ_RESTRICT dwt,
sa_col, dwt->win_l_x0,
sa_col + nb_elts_read, dwt->win_l_x1,
(OPJ_INT32*)(dwt->wavelet + dwt->cas + 2 * dwt->win_l_x0),
- 1, 8, OPJ_TRUE);
+ 1, 2 * NB_ELTS_V8, OPJ_TRUE);
assert(ret);
ret = opj_sparse_array_int32_read(sa,
sa_col, (OPJ_UINT32)dwt->sn + dwt->win_h_x0,
sa_col + nb_elts_read, (OPJ_UINT32)dwt->sn + dwt->win_h_x1,
(OPJ_INT32*)(dwt->wavelet + 1 - dwt->cas + 2 * dwt->win_h_x0),
- 1, 8, OPJ_TRUE);
+ 1, 2 * NB_ELTS_V8, OPJ_TRUE);
assert(ret);
OPJ_UNUSED(ret);
}
#ifdef __SSE__
-static void opj_v4dwt_decode_step1_sse(opj_v4_t* w,
+static void opj_v8dwt_decode_step1_sse(opj_v8_t* w,
OPJ_UINT32 start,
OPJ_UINT32 end,
const __m128 c)
{
__m128* OPJ_RESTRICT vw = (__m128*) w;
- OPJ_UINT32 i;
- /* 4x unrolled loop */
- vw += 2 * start;
- for (i = start; i + 3 < end; i += 4, vw += 8) {
- __m128 xmm0 = _mm_mul_ps(vw[0], c);
- __m128 xmm2 = _mm_mul_ps(vw[2], c);
- __m128 xmm4 = _mm_mul_ps(vw[4], c);
- __m128 xmm6 = _mm_mul_ps(vw[6], c);
- vw[0] = xmm0;
- vw[2] = xmm2;
- vw[4] = xmm4;
- vw[6] = xmm6;
- }
- for (; i < end; ++i, vw += 2) {
+ OPJ_UINT32 i = start;
+ /* To be adapted if NB_ELTS_V8 changes */
+ vw += 4 * start;
+ /* Note: attempt at loop unrolling x2 doesn't help */
+ for (; i < end; ++i, vw += 4) {
vw[0] = _mm_mul_ps(vw[0], c);
+ vw[1] = _mm_mul_ps(vw[1], c);
}
}
-static void opj_v4dwt_decode_step2_sse(opj_v4_t* l, opj_v4_t* w,
+static void opj_v8dwt_decode_step2_sse(opj_v8_t* l, opj_v8_t* w,
OPJ_UINT32 start,
OPJ_UINT32 end,
OPJ_UINT32 m,
@@ -2325,74 +3030,58 @@ static void opj_v4dwt_decode_step2_sse(opj_v4_t* l, opj_v4_t* w,
{
__m128* OPJ_RESTRICT vl = (__m128*) l;
__m128* OPJ_RESTRICT vw = (__m128*) w;
+ /* To be adapted if NB_ELTS_V8 changes */
OPJ_UINT32 i;
OPJ_UINT32 imax = opj_uint_min(end, m);
- __m128 tmp1, tmp2, tmp3;
if (start == 0) {
- tmp1 = vl[0];
+ if (imax >= 1) {
+ vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(_mm_add_ps(vl[0], vw[0]), c));
+ vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(_mm_add_ps(vl[1], vw[1]), c));
+ vw += 4;
+ start = 1;
+ }
} else {
- vw += start * 2;
- tmp1 = vw[-3];
+ vw += start * 4;
}
i = start;
-
- /* 4x loop unrolling */
- for (; i + 3 < imax; i += 4) {
- __m128 tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
- tmp2 = vw[-1];
- tmp3 = vw[ 0];
- tmp4 = vw[ 1];
- tmp5 = vw[ 2];
- tmp6 = vw[ 3];
- tmp7 = vw[ 4];
- tmp8 = vw[ 5];
- tmp9 = vw[ 6];
- vw[-1] = _mm_add_ps(tmp2, _mm_mul_ps(_mm_add_ps(tmp1, tmp3), c));
- vw[ 1] = _mm_add_ps(tmp4, _mm_mul_ps(_mm_add_ps(tmp3, tmp5), c));
- vw[ 3] = _mm_add_ps(tmp6, _mm_mul_ps(_mm_add_ps(tmp5, tmp7), c));
- vw[ 5] = _mm_add_ps(tmp8, _mm_mul_ps(_mm_add_ps(tmp7, tmp9), c));
- tmp1 = tmp9;
- vw += 8;
- }
-
+ /* Note: attempt at loop unrolling x2 doesn't help */
for (; i < imax; ++i) {
- tmp2 = vw[-1];
- tmp3 = vw[ 0];
- vw[-1] = _mm_add_ps(tmp2, _mm_mul_ps(_mm_add_ps(tmp1, tmp3), c));
- tmp1 = tmp3;
- vw += 2;
+ vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(_mm_add_ps(vw[-4], vw[0]), c));
+ vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(_mm_add_ps(vw[-3], vw[1]), c));
+ vw += 4;
}
if (m < end) {
assert(m + 1 == end);
c = _mm_add_ps(c, c);
- c = _mm_mul_ps(c, vw[-2]);
- vw[-1] = _mm_add_ps(vw[-1], c);
+ vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(c, vw[-4]));
+ vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(c, vw[-3]));
}
}
#else
-static void opj_v4dwt_decode_step1(opj_v4_t* w,
+static void opj_v8dwt_decode_step1(opj_v8_t* w,
OPJ_UINT32 start,
OPJ_UINT32 end,
const OPJ_FLOAT32 c)
{
OPJ_FLOAT32* OPJ_RESTRICT fw = (OPJ_FLOAT32*) w;
OPJ_UINT32 i;
+ /* To be adapted if NB_ELTS_V8 changes */
for (i = start; i < end; ++i) {
- OPJ_FLOAT32 tmp1 = fw[i * 8 ];
- OPJ_FLOAT32 tmp2 = fw[i * 8 + 1];
- OPJ_FLOAT32 tmp3 = fw[i * 8 + 2];
- OPJ_FLOAT32 tmp4 = fw[i * 8 + 3];
- fw[i * 8 ] = tmp1 * c;
- fw[i * 8 + 1] = tmp2 * c;
- fw[i * 8 + 2] = tmp3 * c;
- fw[i * 8 + 3] = tmp4 * c;
+ fw[i * 2 * 8 ] = fw[i * 2 * 8 ] * c;
+ fw[i * 2 * 8 + 1] = fw[i * 2 * 8 + 1] * c;
+ fw[i * 2 * 8 + 2] = fw[i * 2 * 8 + 2] * c;
+ fw[i * 2 * 8 + 3] = fw[i * 2 * 8 + 3] * c;
+ fw[i * 2 * 8 + 4] = fw[i * 2 * 8 + 4] * c;
+ fw[i * 2 * 8 + 5] = fw[i * 2 * 8 + 5] * c;
+ fw[i * 2 * 8 + 6] = fw[i * 2 * 8 + 6] * c;
+ fw[i * 2 * 8 + 7] = fw[i * 2 * 8 + 7] * c;
}
}
-static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w,
+static void opj_v8dwt_decode_step2(opj_v8_t* l, opj_v8_t* w,
OPJ_UINT32 start,
OPJ_UINT32 end,
OPJ_UINT32 m,
@@ -2403,36 +3092,33 @@ static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w,
OPJ_UINT32 i;
OPJ_UINT32 imax = opj_uint_min(end, m);
if (start > 0) {
- fw += 8 * start;
- fl = fw - 8;
+ fw += 2 * NB_ELTS_V8 * start;
+ fl = fw - 2 * NB_ELTS_V8;
}
+ /* To be adapted if NB_ELTS_V8 changes */
for (i = start; i < imax; ++i) {
- OPJ_FLOAT32 tmp1_1 = fl[0];
- OPJ_FLOAT32 tmp1_2 = fl[1];
- OPJ_FLOAT32 tmp1_3 = fl[2];
- OPJ_FLOAT32 tmp1_4 = fl[3];
- OPJ_FLOAT32 tmp2_1 = fw[-4];
- OPJ_FLOAT32 tmp2_2 = fw[-3];
- OPJ_FLOAT32 tmp2_3 = fw[-2];
- OPJ_FLOAT32 tmp2_4 = fw[-1];
- OPJ_FLOAT32 tmp3_1 = fw[0];
- OPJ_FLOAT32 tmp3_2 = fw[1];
- OPJ_FLOAT32 tmp3_3 = fw[2];
- OPJ_FLOAT32 tmp3_4 = fw[3];
- fw[-4] = tmp2_1 + ((tmp1_1 + tmp3_1) * c);
- fw[-3] = tmp2_2 + ((tmp1_2 + tmp3_2) * c);
- fw[-2] = tmp2_3 + ((tmp1_3 + tmp3_3) * c);
- fw[-1] = tmp2_4 + ((tmp1_4 + tmp3_4) * c);
+ fw[-8] = fw[-8] + ((fl[0] + fw[0]) * c);
+ fw[-7] = fw[-7] + ((fl[1] + fw[1]) * c);
+ fw[-6] = fw[-6] + ((fl[2] + fw[2]) * c);
+ fw[-5] = fw[-5] + ((fl[3] + fw[3]) * c);
+ fw[-4] = fw[-4] + ((fl[4] + fw[4]) * c);
+ fw[-3] = fw[-3] + ((fl[5] + fw[5]) * c);
+ fw[-2] = fw[-2] + ((fl[6] + fw[6]) * c);
+ fw[-1] = fw[-1] + ((fl[7] + fw[7]) * c);
fl = fw;
- fw += 8;
+ fw += 2 * NB_ELTS_V8;
}
if (m < end) {
assert(m + 1 == end);
c += c;
- fw[-4] = fw[-4] + fl[0] * c;
- fw[-3] = fw[-3] + fl[1] * c;
- fw[-2] = fw[-2] + fl[2] * c;
- fw[-1] = fw[-1] + fl[3] * c;
+ fw[-8] = fw[-8] + fl[0] * c;
+ fw[-7] = fw[-7] + fl[1] * c;
+ fw[-6] = fw[-6] + fl[2] * c;
+ fw[-5] = fw[-5] + fl[3] * c;
+ fw[-4] = fw[-4] + fl[4] * c;
+ fw[-3] = fw[-3] + fl[5] * c;
+ fw[-2] = fw[-2] + fl[6] * c;
+ fw[-1] = fw[-1] + fl[7] * c;
}
}
@@ -2441,9 +3127,17 @@ static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w,
/* <summary> */
/* Inverse 9-7 wavelet transform in 1-D. */
/* </summary> */
-static void opj_v4dwt_decode(opj_v4dwt_t* OPJ_RESTRICT dwt)
+static void opj_v8dwt_decode(opj_v8dwt_t* OPJ_RESTRICT dwt)
{
OPJ_INT32 a, b;
+ /* BUG_WEIRD_TWO_INVK (look for this identifier in tcd.c) */
+ /* Historic value for 2 / opj_invK */
+ /* Normally, we should use invK, but if we do so, we have failures in the */
+ /* conformance test, due to MSE and peak errors significantly higher than */
+ /* accepted value */
+ /* Due to using two_invK instead of invK, we have to compensate in tcd.c */
+ /* the computation of the stepsize for the non LL subbands */
+ const float two_invK = 1.625732422f;
if (dwt->cas == 0) {
if (!((dwt->dn > 0) || (dwt->sn > 1))) {
return;
@@ -2458,60 +3152,147 @@ static void opj_v4dwt_decode(opj_v4dwt_t* OPJ_RESTRICT dwt)
b = 0;
}
#ifdef __SSE__
- opj_v4dwt_decode_step1_sse(dwt->wavelet + a, dwt->win_l_x0, dwt->win_l_x1,
+ opj_v8dwt_decode_step1_sse(dwt->wavelet + a, dwt->win_l_x0, dwt->win_l_x1,
_mm_set1_ps(opj_K));
- opj_v4dwt_decode_step1_sse(dwt->wavelet + b, dwt->win_h_x0, dwt->win_h_x1,
- _mm_set1_ps(opj_c13318));
- opj_v4dwt_decode_step2_sse(dwt->wavelet + b, dwt->wavelet + a + 1,
+ opj_v8dwt_decode_step1_sse(dwt->wavelet + b, dwt->win_h_x0, dwt->win_h_x1,
+ _mm_set1_ps(two_invK));
+ opj_v8dwt_decode_step2_sse(dwt->wavelet + b, dwt->wavelet + a + 1,
dwt->win_l_x0, dwt->win_l_x1,
(OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a),
- _mm_set1_ps(opj_dwt_delta));
- opj_v4dwt_decode_step2_sse(dwt->wavelet + a, dwt->wavelet + b + 1,
+ _mm_set1_ps(-opj_dwt_delta));
+ opj_v8dwt_decode_step2_sse(dwt->wavelet + a, dwt->wavelet + b + 1,
dwt->win_h_x0, dwt->win_h_x1,
(OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b),
- _mm_set1_ps(opj_dwt_gamma));
- opj_v4dwt_decode_step2_sse(dwt->wavelet + b, dwt->wavelet + a + 1,
+ _mm_set1_ps(-opj_dwt_gamma));
+ opj_v8dwt_decode_step2_sse(dwt->wavelet + b, dwt->wavelet + a + 1,
dwt->win_l_x0, dwt->win_l_x1,
(OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a),
- _mm_set1_ps(opj_dwt_beta));
- opj_v4dwt_decode_step2_sse(dwt->wavelet + a, dwt->wavelet + b + 1,
+ _mm_set1_ps(-opj_dwt_beta));
+ opj_v8dwt_decode_step2_sse(dwt->wavelet + a, dwt->wavelet + b + 1,
dwt->win_h_x0, dwt->win_h_x1,
(OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b),
- _mm_set1_ps(opj_dwt_alpha));
+ _mm_set1_ps(-opj_dwt_alpha));
#else
- opj_v4dwt_decode_step1(dwt->wavelet + a, dwt->win_l_x0, dwt->win_l_x1,
+ opj_v8dwt_decode_step1(dwt->wavelet + a, dwt->win_l_x0, dwt->win_l_x1,
opj_K);
- opj_v4dwt_decode_step1(dwt->wavelet + b, dwt->win_h_x0, dwt->win_h_x1,
- opj_c13318);
- opj_v4dwt_decode_step2(dwt->wavelet + b, dwt->wavelet + a + 1,
+ opj_v8dwt_decode_step1(dwt->wavelet + b, dwt->win_h_x0, dwt->win_h_x1,
+ two_invK);
+ opj_v8dwt_decode_step2(dwt->wavelet + b, dwt->wavelet + a + 1,
dwt->win_l_x0, dwt->win_l_x1,
(OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a),
- opj_dwt_delta);
- opj_v4dwt_decode_step2(dwt->wavelet + a, dwt->wavelet + b + 1,
+ -opj_dwt_delta);
+ opj_v8dwt_decode_step2(dwt->wavelet + a, dwt->wavelet + b + 1,
dwt->win_h_x0, dwt->win_h_x1,
(OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b),
- opj_dwt_gamma);
- opj_v4dwt_decode_step2(dwt->wavelet + b, dwt->wavelet + a + 1,
+ -opj_dwt_gamma);
+ opj_v8dwt_decode_step2(dwt->wavelet + b, dwt->wavelet + a + 1,
dwt->win_l_x0, dwt->win_l_x1,
(OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a),
- opj_dwt_beta);
- opj_v4dwt_decode_step2(dwt->wavelet + a, dwt->wavelet + b + 1,
+ -opj_dwt_beta);
+ opj_v8dwt_decode_step2(dwt->wavelet + a, dwt->wavelet + b + 1,
dwt->win_h_x0, dwt->win_h_x1,
(OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b),
- opj_dwt_alpha);
+ -opj_dwt_alpha);
#endif
}
+typedef struct {
+ opj_v8dwt_t h;
+ OPJ_UINT32 rw;
+ OPJ_UINT32 w;
+ OPJ_FLOAT32 * OPJ_RESTRICT aj;
+ OPJ_UINT32 nb_rows;
+} opj_dwt97_decode_h_job_t;
+
+static void opj_dwt97_decode_h_func(void* user_data, opj_tls_t* tls)
+{
+ OPJ_UINT32 j;
+ opj_dwt97_decode_h_job_t* job;
+ OPJ_FLOAT32 * OPJ_RESTRICT aj;
+ OPJ_UINT32 w;
+ (void)tls;
+
+ job = (opj_dwt97_decode_h_job_t*)user_data;
+ w = job->w;
+
+ assert((job->nb_rows % NB_ELTS_V8) == 0);
+
+ aj = job->aj;
+ for (j = 0; j + NB_ELTS_V8 <= job->nb_rows; j += NB_ELTS_V8) {
+ OPJ_UINT32 k;
+ opj_v8dwt_interleave_h(&job->h, aj, job->w, NB_ELTS_V8);
+ opj_v8dwt_decode(&job->h);
+
+ /* To be adapted if NB_ELTS_V8 changes */
+ for (k = 0; k < job->rw; k++) {
+ aj[k ] = job->h.wavelet[k].f[0];
+ aj[k + (OPJ_SIZE_T)w ] = job->h.wavelet[k].f[1];
+ aj[k + (OPJ_SIZE_T)w * 2] = job->h.wavelet[k].f[2];
+ aj[k + (OPJ_SIZE_T)w * 3] = job->h.wavelet[k].f[3];
+ }
+ for (k = 0; k < job->rw; k++) {
+ aj[k + (OPJ_SIZE_T)w * 4] = job->h.wavelet[k].f[4];
+ aj[k + (OPJ_SIZE_T)w * 5] = job->h.wavelet[k].f[5];
+ aj[k + (OPJ_SIZE_T)w * 6] = job->h.wavelet[k].f[6];
+ aj[k + (OPJ_SIZE_T)w * 7] = job->h.wavelet[k].f[7];
+ }
+
+ aj += w * NB_ELTS_V8;
+ }
+
+ opj_aligned_free(job->h.wavelet);
+ opj_free(job);
+}
+
+
+typedef struct {
+ opj_v8dwt_t v;
+ OPJ_UINT32 rh;
+ OPJ_UINT32 w;
+ OPJ_FLOAT32 * OPJ_RESTRICT aj;
+ OPJ_UINT32 nb_columns;
+} opj_dwt97_decode_v_job_t;
+
+static void opj_dwt97_decode_v_func(void* user_data, opj_tls_t* tls)
+{
+ OPJ_UINT32 j;
+ opj_dwt97_decode_v_job_t* job;
+ OPJ_FLOAT32 * OPJ_RESTRICT aj;
+ (void)tls;
+
+ job = (opj_dwt97_decode_v_job_t*)user_data;
+
+ assert((job->nb_columns % NB_ELTS_V8) == 0);
+
+ aj = job->aj;
+ for (j = 0; j + NB_ELTS_V8 <= job->nb_columns; j += NB_ELTS_V8) {
+ OPJ_UINT32 k;
+
+ opj_v8dwt_interleave_v(&job->v, aj, job->w, NB_ELTS_V8);
+ opj_v8dwt_decode(&job->v);
+
+ for (k = 0; k < job->rh; ++k) {
+ memcpy(&aj[k * (OPJ_SIZE_T)job->w], &job->v.wavelet[k],
+ NB_ELTS_V8 * sizeof(OPJ_FLOAT32));
+ }
+ aj += NB_ELTS_V8;
+ }
+
+ opj_aligned_free(job->v.wavelet);
+ opj_free(job);
+}
+
/* <summary> */
/* Inverse 9-7 wavelet transform in 2-D. */
/* </summary> */
static
-OPJ_BOOL opj_dwt_decode_tile_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
+OPJ_BOOL opj_dwt_decode_tile_97(opj_thread_pool_t* tp,
+ opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
OPJ_UINT32 numres)
{
- opj_v4dwt_t h;
- opj_v4dwt_t v;
+ opj_v8dwt_t h;
+ opj_v8dwt_t v;
opj_tcd_resolution_t* res = tilec->resolutions;
@@ -2525,20 +3306,19 @@ OPJ_BOOL opj_dwt_decode_tile_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
tilec->resolutions[tilec->minimum_num_resolutions - 1].x0);
OPJ_SIZE_T l_data_size;
+ const int num_threads = opj_thread_pool_get_thread_count(tp);
- l_data_size = opj_dwt_max_resolution(res, numres);
- /* overflow check */
- if (l_data_size > (SIZE_MAX - 5U)) {
- /* FIXME event manager error callback */
- return OPJ_FALSE;
+ if (numres == 1) {
+ return OPJ_TRUE;
}
- l_data_size += 5U;
+
+ l_data_size = opj_dwt_max_resolution(res, numres);
/* overflow check */
- if (l_data_size > (SIZE_MAX / sizeof(opj_v4_t))) {
+ if (l_data_size > (SIZE_MAX / sizeof(opj_v8_t))) {
/* FIXME event manager error callback */
return OPJ_FALSE;
}
- h.wavelet = (opj_v4_t*) opj_aligned_malloc(l_data_size * sizeof(opj_v4_t));
+ h.wavelet = (opj_v8_t*) opj_aligned_malloc(l_data_size * sizeof(opj_v8_t));
if (!h.wavelet) {
/* FIXME event manager error callback */
return OPJ_FALSE;
@@ -2566,35 +3346,80 @@ OPJ_BOOL opj_dwt_decode_tile_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
h.win_l_x1 = (OPJ_UINT32)h.sn;
h.win_h_x0 = 0;
h.win_h_x1 = (OPJ_UINT32)h.dn;
- for (j = 0; j + 3 < rh; j += 4) {
- OPJ_UINT32 k;
- opj_v4dwt_interleave_h(&h, aj, w, rh - j);
- opj_v4dwt_decode(&h);
- for (k = 0; k < rw; k++) {
- aj[k ] = h.wavelet[k].f[0];
- aj[k + (OPJ_SIZE_T)w ] = h.wavelet[k].f[1];
- aj[k + (OPJ_SIZE_T)w * 2] = h.wavelet[k].f[2];
- aj[k + (OPJ_SIZE_T)w * 3] = h.wavelet[k].f[3];
+ if (num_threads <= 1 || rh < 2 * NB_ELTS_V8) {
+ for (j = 0; j + (NB_ELTS_V8 - 1) < rh; j += NB_ELTS_V8) {
+ OPJ_UINT32 k;
+ opj_v8dwt_interleave_h(&h, aj, w, NB_ELTS_V8);
+ opj_v8dwt_decode(&h);
+
+ /* To be adapted if NB_ELTS_V8 changes */
+ for (k = 0; k < rw; k++) {
+ aj[k ] = h.wavelet[k].f[0];
+ aj[k + (OPJ_SIZE_T)w ] = h.wavelet[k].f[1];
+ aj[k + (OPJ_SIZE_T)w * 2] = h.wavelet[k].f[2];
+ aj[k + (OPJ_SIZE_T)w * 3] = h.wavelet[k].f[3];
+ }
+ for (k = 0; k < rw; k++) {
+ aj[k + (OPJ_SIZE_T)w * 4] = h.wavelet[k].f[4];
+ aj[k + (OPJ_SIZE_T)w * 5] = h.wavelet[k].f[5];
+ aj[k + (OPJ_SIZE_T)w * 6] = h.wavelet[k].f[6];
+ aj[k + (OPJ_SIZE_T)w * 7] = h.wavelet[k].f[7];
+ }
+
+ aj += w * NB_ELTS_V8;
}
+ } else {
+ OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads;
+ OPJ_UINT32 step_j;
- aj += w * 4;
+ if ((rh / NB_ELTS_V8) < num_jobs) {
+ num_jobs = rh / NB_ELTS_V8;
+ }
+ step_j = ((rh / num_jobs) / NB_ELTS_V8) * NB_ELTS_V8;
+ for (j = 0; j < num_jobs; j++) {
+ opj_dwt97_decode_h_job_t* job;
+
+ job = (opj_dwt97_decode_h_job_t*) opj_malloc(sizeof(opj_dwt97_decode_h_job_t));
+ if (!job) {
+ opj_thread_pool_wait_completion(tp, 0);
+ opj_aligned_free(h.wavelet);
+ return OPJ_FALSE;
+ }
+ job->h.wavelet = (opj_v8_t*)opj_aligned_malloc(l_data_size * sizeof(opj_v8_t));
+ if (!job->h.wavelet) {
+ opj_thread_pool_wait_completion(tp, 0);
+ opj_free(job);
+ opj_aligned_free(h.wavelet);
+ return OPJ_FALSE;
+ }
+ job->h.dn = h.dn;
+ job->h.sn = h.sn;
+ job->h.cas = h.cas;
+ job->h.win_l_x0 = h.win_l_x0;
+ job->h.win_l_x1 = h.win_l_x1;
+ job->h.win_h_x0 = h.win_h_x0;
+ job->h.win_h_x1 = h.win_h_x1;
+ job->rw = rw;
+ job->w = w;
+ job->aj = aj;
+ job->nb_rows = (j + 1 == num_jobs) ? (rh & (OPJ_UINT32)~
+ (NB_ELTS_V8 - 1)) - j * step_j : step_j;
+ aj += w * job->nb_rows;
+ opj_thread_pool_submit_job(tp, opj_dwt97_decode_h_func, job);
+ }
+ opj_thread_pool_wait_completion(tp, 0);
+ j = rh & (OPJ_UINT32)~(NB_ELTS_V8 - 1);
}
if (j < rh) {
OPJ_UINT32 k;
- opj_v4dwt_interleave_h(&h, aj, w, rh - j);
- opj_v4dwt_decode(&h);
+ opj_v8dwt_interleave_h(&h, aj, w, rh - j);
+ opj_v8dwt_decode(&h);
for (k = 0; k < rw; k++) {
- switch (rh - j) {
- case 3:
- aj[k + (OPJ_SIZE_T)w * 2] = h.wavelet[k].f[2];
- /* FALLTHRU */
- case 2:
- aj[k + (OPJ_SIZE_T)w ] = h.wavelet[k].f[1];
- /* FALLTHRU */
- case 1:
- aj[k] = h.wavelet[k].f[0];
+ OPJ_UINT32 l;
+ for (l = 0; l < rh - j; l++) {
+ aj[k + (OPJ_SIZE_T)w * l ] = h.wavelet[k].f[l];
}
}
}
@@ -2607,25 +3432,71 @@ OPJ_BOOL opj_dwt_decode_tile_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
v.win_h_x1 = (OPJ_UINT32)v.dn;
aj = (OPJ_FLOAT32*) tilec->data;
- for (j = rw; j > 3; j -= 4) {
- OPJ_UINT32 k;
+ if (num_threads <= 1 || rw < 2 * NB_ELTS_V8) {
+ for (j = rw; j > (NB_ELTS_V8 - 1); j -= NB_ELTS_V8) {
+ OPJ_UINT32 k;
- opj_v4dwt_interleave_v(&v, aj, w, 4);
- opj_v4dwt_decode(&v);
+ opj_v8dwt_interleave_v(&v, aj, w, NB_ELTS_V8);
+ opj_v8dwt_decode(&v);
- for (k = 0; k < rh; ++k) {
- memcpy(&aj[k * (OPJ_SIZE_T)w], &v.wavelet[k], 4 * sizeof(OPJ_FLOAT32));
+ for (k = 0; k < rh; ++k) {
+ memcpy(&aj[k * (OPJ_SIZE_T)w], &v.wavelet[k], NB_ELTS_V8 * sizeof(OPJ_FLOAT32));
+ }
+ aj += NB_ELTS_V8;
}
- aj += 4;
+ } else {
+ /* "bench_dwt -I" shows that scaling is poor, likely due to RAM
+ transfer being the limiting factor. So limit the number of
+ threads.
+ */
+ OPJ_UINT32 num_jobs = opj_uint_max((OPJ_UINT32)num_threads / 2, 2U);
+ OPJ_UINT32 step_j;
+
+ if ((rw / NB_ELTS_V8) < num_jobs) {
+ num_jobs = rw / NB_ELTS_V8;
+ }
+ step_j = ((rw / num_jobs) / NB_ELTS_V8) * NB_ELTS_V8;
+ for (j = 0; j < num_jobs; j++) {
+ opj_dwt97_decode_v_job_t* job;
+
+ job = (opj_dwt97_decode_v_job_t*) opj_malloc(sizeof(opj_dwt97_decode_v_job_t));
+ if (!job) {
+ opj_thread_pool_wait_completion(tp, 0);
+ opj_aligned_free(h.wavelet);
+ return OPJ_FALSE;
+ }
+ job->v.wavelet = (opj_v8_t*)opj_aligned_malloc(l_data_size * sizeof(opj_v8_t));
+ if (!job->v.wavelet) {
+ opj_thread_pool_wait_completion(tp, 0);
+ opj_free(job);
+ opj_aligned_free(h.wavelet);
+ return OPJ_FALSE;
+ }
+ job->v.dn = v.dn;
+ job->v.sn = v.sn;
+ job->v.cas = v.cas;
+ job->v.win_l_x0 = v.win_l_x0;
+ job->v.win_l_x1 = v.win_l_x1;
+ job->v.win_h_x0 = v.win_h_x0;
+ job->v.win_h_x1 = v.win_h_x1;
+ job->rh = rh;
+ job->w = w;
+ job->aj = aj;
+ job->nb_columns = (j + 1 == num_jobs) ? (rw & (OPJ_UINT32)~
+ (NB_ELTS_V8 - 1)) - j * step_j : step_j;
+ aj += job->nb_columns;
+ opj_thread_pool_submit_job(tp, opj_dwt97_decode_v_func, job);
+ }
+ opj_thread_pool_wait_completion(tp, 0);
}
- if (rw & 0x03) {
+ if (rw & (NB_ELTS_V8 - 1)) {
OPJ_UINT32 k;
- j = rw & 0x03;
+ j = rw & (NB_ELTS_V8 - 1);
- opj_v4dwt_interleave_v(&v, aj, w, j);
- opj_v4dwt_decode(&v);
+ opj_v8dwt_interleave_v(&v, aj, w, j);
+ opj_v8dwt_decode(&v);
for (k = 0; k < rh; ++k) {
memcpy(&aj[k * (OPJ_SIZE_T)w], &v.wavelet[k],
@@ -2643,8 +3514,8 @@ OPJ_BOOL opj_dwt_decode_partial_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
OPJ_UINT32 numres)
{
opj_sparse_array_int32_t* sa;
- opj_v4dwt_t h;
- opj_v4dwt_t v;
+ opj_v8dwt_t h;
+ opj_v8dwt_t v;
OPJ_UINT32 resno;
/* This value matches the maximum left/right extension given in tables */
/* F.2 and F.3 of the standard. Note: in opj_tcd_is_subband_area_of_interest() */
@@ -2694,19 +3565,12 @@ OPJ_BOOL opj_dwt_decode_partial_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
l_data_size = opj_dwt_max_resolution(tr, numres);
/* overflow check */
- if (l_data_size > (SIZE_MAX - 5U)) {
- /* FIXME event manager error callback */
- opj_sparse_array_int32_free(sa);
- return OPJ_FALSE;
- }
- l_data_size += 5U;
- /* overflow check */
- if (l_data_size > (SIZE_MAX / sizeof(opj_v4_t))) {
+ if (l_data_size > (SIZE_MAX / sizeof(opj_v8_t))) {
/* FIXME event manager error callback */
opj_sparse_array_int32_free(sa);
return OPJ_FALSE;
}
- h.wavelet = (opj_v4_t*) opj_aligned_malloc(l_data_size * sizeof(opj_v4_t));
+ h.wavelet = (opj_v8_t*) opj_aligned_malloc(l_data_size * sizeof(opj_v8_t));
if (!h.wavelet) {
/* FIXME event manager error callback */
opj_sparse_array_int32_free(sa);
@@ -2801,17 +3665,17 @@ OPJ_BOOL opj_dwt_decode_partial_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
h.win_l_x1 = win_ll_x1;
h.win_h_x0 = win_hl_x0;
h.win_h_x1 = win_hl_x1;
- for (j = 0; j + 3 < rh; j += 4) {
- if ((j + 3 >= win_ll_y0 && j < win_ll_y1) ||
- (j + 3 >= win_lh_y0 + (OPJ_UINT32)v.sn &&
+ for (j = 0; j + (NB_ELTS_V8 - 1) < rh; j += NB_ELTS_V8) {
+ if ((j + (NB_ELTS_V8 - 1) >= win_ll_y0 && j < win_ll_y1) ||
+ (j + (NB_ELTS_V8 - 1) >= win_lh_y0 + (OPJ_UINT32)v.sn &&
j < win_lh_y1 + (OPJ_UINT32)v.sn)) {
- opj_v4dwt_interleave_partial_h(&h, sa, j, opj_uint_min(4U, rh - j));
- opj_v4dwt_decode(&h);
+ opj_v8dwt_interleave_partial_h(&h, sa, j, opj_uint_min(NB_ELTS_V8, rh - j));
+ opj_v8dwt_decode(&h);
if (!opj_sparse_array_int32_write(sa,
win_tr_x0, j,
- win_tr_x1, j + 4,
+ win_tr_x1, j + NB_ELTS_V8,
(OPJ_INT32*)&h.wavelet[win_tr_x0].f[0],
- 4, 1, OPJ_TRUE)) {
+ NB_ELTS_V8, 1, OPJ_TRUE)) {
/* FIXME event manager error callback */
opj_sparse_array_int32_free(sa);
opj_aligned_free(h.wavelet);
@@ -2821,16 +3685,16 @@ OPJ_BOOL opj_dwt_decode_partial_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
}
if (j < rh &&
- ((j + 3 >= win_ll_y0 && j < win_ll_y1) ||
- (j + 3 >= win_lh_y0 + (OPJ_UINT32)v.sn &&
+ ((j + (NB_ELTS_V8 - 1) >= win_ll_y0 && j < win_ll_y1) ||
+ (j + (NB_ELTS_V8 - 1) >= win_lh_y0 + (OPJ_UINT32)v.sn &&
j < win_lh_y1 + (OPJ_UINT32)v.sn))) {
- opj_v4dwt_interleave_partial_h(&h, sa, j, rh - j);
- opj_v4dwt_decode(&h);
+ opj_v8dwt_interleave_partial_h(&h, sa, j, rh - j);
+ opj_v8dwt_decode(&h);
if (!opj_sparse_array_int32_write(sa,
win_tr_x0, j,
win_tr_x1, rh,
(OPJ_INT32*)&h.wavelet[win_tr_x0].f[0],
- 4, 1, OPJ_TRUE)) {
+ NB_ELTS_V8, 1, OPJ_TRUE)) {
/* FIXME event manager error callback */
opj_sparse_array_int32_free(sa);
opj_aligned_free(h.wavelet);
@@ -2842,17 +3706,17 @@ OPJ_BOOL opj_dwt_decode_partial_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
v.win_l_x1 = win_ll_y1;
v.win_h_x0 = win_lh_y0;
v.win_h_x1 = win_lh_y1;
- for (j = win_tr_x0; j < win_tr_x1; j += 4) {
- OPJ_UINT32 nb_elts = opj_uint_min(4U, win_tr_x1 - j);
+ for (j = win_tr_x0; j < win_tr_x1; j += NB_ELTS_V8) {
+ OPJ_UINT32 nb_elts = opj_uint_min(NB_ELTS_V8, win_tr_x1 - j);
- opj_v4dwt_interleave_partial_v(&v, sa, j, nb_elts);
- opj_v4dwt_decode(&v);
+ opj_v8dwt_interleave_partial_v(&v, sa, j, nb_elts);
+ opj_v8dwt_decode(&v);
if (!opj_sparse_array_int32_write(sa,
j, win_tr_y0,
j + nb_elts, win_tr_y1,
(OPJ_INT32*)&h.wavelet[win_tr_y0].f[0],
- 1, 4, OPJ_TRUE)) {
+ 1, NB_ELTS_V8, OPJ_TRUE)) {
/* FIXME event manager error callback */
opj_sparse_array_int32_free(sa);
opj_aligned_free(h.wavelet);
@@ -2885,7 +3749,7 @@ OPJ_BOOL opj_dwt_decode_real(opj_tcd_t *p_tcd,
OPJ_UINT32 numres)
{
if (p_tcd->whole_tile_decoding) {
- return opj_dwt_decode_tile_97(tilec, numres);
+ return opj_dwt_decode_tile_97(p_tcd->thread_pool, tilec, numres);
} else {
return opj_dwt_decode_partial_97(tilec, numres);
}
diff --git a/src/lib/openjp2/dwt.h b/src/lib/openjp2/dwt.h
index 4f63e524..215061e6 100644
--- a/src/lib/openjp2/dwt.h
+++ b/src/lib/openjp2/dwt.h
@@ -56,9 +56,11 @@ DWT.C are used by some function in TCD.C.
/**
Forward 5-3 wavelet transform in 2-D.
Apply a reversible DWT transform to a component of an image.
+@param p_tcd TCD handle
@param tilec Tile component information (current tile)
*/
-OPJ_BOOL opj_dwt_encode(opj_tcd_tilecomp_t * tilec);
+OPJ_BOOL opj_dwt_encode(opj_tcd_t *p_tcd,
+ opj_tcd_tilecomp_t * tilec);
/**
Inverse 5-3 wavelet transform in 2-D.
@@ -72,12 +74,6 @@ OPJ_BOOL opj_dwt_decode(opj_tcd_t *p_tcd,
OPJ_UINT32 numres);
/**
-Get the gain of a subband for the reversible 5-3 DWT.
-@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH)
-@return Returns 0 if orient = 0, returns 1 if orient = 1 or 2, returns 2 otherwise
-*/
-OPJ_UINT32 opj_dwt_getgain(OPJ_UINT32 orient) ;
-/**
Get the norm of a wavelet function of a subband at a specified level for the reversible 5-3 DWT.
@param level Level of the wavelet function
@param orient Band of the wavelet function
@@ -87,9 +83,11 @@ OPJ_FLOAT64 opj_dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient);
/**
Forward 9-7 wavelet transform in 2-D.
Apply an irreversible DWT transform to a component of an image.
+@param p_tcd TCD handle
@param tilec Tile component information (current tile)
*/
-OPJ_BOOL opj_dwt_encode_real(opj_tcd_tilecomp_t * tilec);
+OPJ_BOOL opj_dwt_encode_real(opj_tcd_t *p_tcd,
+ opj_tcd_tilecomp_t * tilec);
/**
Inverse 9-7 wavelet transform in 2-D.
Apply an irreversible inverse DWT transform to a component of an image.
@@ -102,12 +100,6 @@ OPJ_BOOL opj_dwt_decode_real(opj_tcd_t *p_tcd,
OPJ_UINT32 numres);
/**
-Get the gain of a subband for the irreversible 9-7 DWT.
-@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH)
-@return Returns the gain of the 9-7 wavelet transform
-*/
-OPJ_UINT32 opj_dwt_getgain_real(OPJ_UINT32 orient);
-/**
Get the norm of a wavelet function of a subband at a specified level for the irreversible 9-7 DWT
@param level Level of the wavelet function
@param orient Band of the wavelet function
diff --git a/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c
index c996cd88..08e79598 100644
--- a/src/lib/openjp2/j2k.c
+++ b/src/lib/openjp2/j2k.c
@@ -7822,6 +7822,14 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
*/
if (parameters->tile_size_on) {
+ if (cp->tdx == 0) {
+ opj_event_msg(p_manager, EVT_ERROR, "Invalid tile width\n");
+ return OPJ_FALSE;
+ }
+ if (cp->tdy == 0) {
+ opj_event_msg(p_manager, EVT_ERROR, "Invalid tile height\n");
+ return OPJ_FALSE;
+ }
cp->tw = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(image->x1 - cp->tx0),
(OPJ_INT32)cp->tdx);
cp->th = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(image->y1 - cp->ty0),
diff --git a/src/lib/openjp2/mct.c b/src/lib/openjp2/mct.c
index 08bc8115..88c8f409 100644
--- a/src/lib/openjp2/mct.c
+++ b/src/lib/openjp2/mct.c
@@ -209,175 +209,72 @@ OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno)
/* <summary> */
/* Forward irreversible MCT. */
/* </summary> */
-#ifdef __SSE4_1__
void opj_mct_encode_real(
- OPJ_INT32* OPJ_RESTRICT c0,
- OPJ_INT32* OPJ_RESTRICT c1,
- OPJ_INT32* OPJ_RESTRICT c2,
+ OPJ_FLOAT32* OPJ_RESTRICT c0,
+ OPJ_FLOAT32* OPJ_RESTRICT c1,
+ OPJ_FLOAT32* OPJ_RESTRICT c2,
OPJ_SIZE_T n)
{
OPJ_SIZE_T i;
- const OPJ_SIZE_T len = n;
-
- const __m128i ry = _mm_set1_epi32(2449);
- const __m128i gy = _mm_set1_epi32(4809);
- const __m128i by = _mm_set1_epi32(934);
- const __m128i ru = _mm_set1_epi32(1382);
- const __m128i gu = _mm_set1_epi32(2714);
- /* const __m128i bu = _mm_set1_epi32(4096); */
- /* const __m128i rv = _mm_set1_epi32(4096); */
- const __m128i gv = _mm_set1_epi32(3430);
- const __m128i bv = _mm_set1_epi32(666);
- const __m128i mulround = _mm_shuffle_epi32(_mm_cvtsi32_si128(4096),
- _MM_SHUFFLE(1, 0, 1, 0));
-
- for (i = 0; i < (len & ~3U); i += 4) {
- __m128i lo, hi;
- __m128i y, u, v;
- __m128i r = _mm_load_si128((const __m128i *) & (c0[i]));
- __m128i g = _mm_load_si128((const __m128i *) & (c1[i]));
- __m128i b = _mm_load_si128((const __m128i *) & (c2[i]));
-
- lo = r;
- hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1));
- lo = _mm_mul_epi32(lo, ry);
- hi = _mm_mul_epi32(hi, ry);
- lo = _mm_add_epi64(lo, mulround);
- hi = _mm_add_epi64(hi, mulround);
- lo = _mm_srli_epi64(lo, 13);
- hi = _mm_slli_epi64(hi, 32 - 13);
- y = _mm_blend_epi16(lo, hi, 0xCC);
-
- lo = g;
- hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1));
- lo = _mm_mul_epi32(lo, gy);
- hi = _mm_mul_epi32(hi, gy);
- lo = _mm_add_epi64(lo, mulround);
- hi = _mm_add_epi64(hi, mulround);
- lo = _mm_srli_epi64(lo, 13);
- hi = _mm_slli_epi64(hi, 32 - 13);
- y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC));
-
- lo = b;
- hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1));
- lo = _mm_mul_epi32(lo, by);
- hi = _mm_mul_epi32(hi, by);
- lo = _mm_add_epi64(lo, mulround);
- hi = _mm_add_epi64(hi, mulround);
- lo = _mm_srli_epi64(lo, 13);
- hi = _mm_slli_epi64(hi, 32 - 13);
- y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC));
- _mm_store_si128((__m128i *) & (c0[i]), y);
-
- /*lo = b;
- hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1));
- lo = _mm_mul_epi32(lo, mulround);
- hi = _mm_mul_epi32(hi, mulround);*/
- lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 2, 0)));
- hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 3, 1)));
- lo = _mm_slli_epi64(lo, 12);
- hi = _mm_slli_epi64(hi, 12);
- lo = _mm_add_epi64(lo, mulround);
- hi = _mm_add_epi64(hi, mulround);
- lo = _mm_srli_epi64(lo, 13);
- hi = _mm_slli_epi64(hi, 32 - 13);
- u = _mm_blend_epi16(lo, hi, 0xCC);
-
- lo = r;
- hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1));
- lo = _mm_mul_epi32(lo, ru);
- hi = _mm_mul_epi32(hi, ru);
- lo = _mm_add_epi64(lo, mulround);
- hi = _mm_add_epi64(hi, mulround);
- lo = _mm_srli_epi64(lo, 13);
- hi = _mm_slli_epi64(hi, 32 - 13);
- u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC));
-
- lo = g;
- hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1));
- lo = _mm_mul_epi32(lo, gu);
- hi = _mm_mul_epi32(hi, gu);
- lo = _mm_add_epi64(lo, mulround);
- hi = _mm_add_epi64(hi, mulround);
- lo = _mm_srli_epi64(lo, 13);
- hi = _mm_slli_epi64(hi, 32 - 13);
- u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC));
- _mm_store_si128((__m128i *) & (c1[i]), u);
+#ifdef __SSE__
+ const __m128 YR = _mm_set1_ps(0.299f);
+ const __m128 YG = _mm_set1_ps(0.587f);
+ const __m128 YB = _mm_set1_ps(0.114f);
+ const __m128 UR = _mm_set1_ps(-0.16875f);
+ const __m128 UG = _mm_set1_ps(-0.331260f);
+ const __m128 UB = _mm_set1_ps(0.5f);
+ const __m128 VR = _mm_set1_ps(0.5f);
+ const __m128 VG = _mm_set1_ps(-0.41869f);
+ const __m128 VB = _mm_set1_ps(-0.08131f);
+ for (i = 0; i < (n >> 3); i ++) {
+ __m128 r, g, b, y, u, v;
+
+ r = _mm_load_ps(c0);
+ g = _mm_load_ps(c1);
+ b = _mm_load_ps(c2);
+ y = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, YR), _mm_mul_ps(g, YG)),
+ _mm_mul_ps(b, YB));
+ u = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, UR), _mm_mul_ps(g, UG)),
+ _mm_mul_ps(b, UB));
+ v = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, VR), _mm_mul_ps(g, VG)),
+ _mm_mul_ps(b, VB));
+ _mm_store_ps(c0, y);
+ _mm_store_ps(c1, u);
+ _mm_store_ps(c2, v);
+ c0 += 4;
+ c1 += 4;
+ c2 += 4;
- /*lo = r;
- hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1));
- lo = _mm_mul_epi32(lo, mulround);
- hi = _mm_mul_epi32(hi, mulround);*/
- lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 2, 0)));
- hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 3, 1)));
- lo = _mm_slli_epi64(lo, 12);
- hi = _mm_slli_epi64(hi, 12);
- lo = _mm_add_epi64(lo, mulround);
- hi = _mm_add_epi64(hi, mulround);
- lo = _mm_srli_epi64(lo, 13);
- hi = _mm_slli_epi64(hi, 32 - 13);
- v = _mm_blend_epi16(lo, hi, 0xCC);
-
- lo = g;
- hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1));
- lo = _mm_mul_epi32(lo, gv);
- hi = _mm_mul_epi32(hi, gv);
- lo = _mm_add_epi64(lo, mulround);
- hi = _mm_add_epi64(hi, mulround);
- lo = _mm_srli_epi64(lo, 13);
- hi = _mm_slli_epi64(hi, 32 - 13);
- v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC));
-
- lo = b;
- hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1));
- lo = _mm_mul_epi32(lo, bv);
- hi = _mm_mul_epi32(hi, bv);
- lo = _mm_add_epi64(lo, mulround);
- hi = _mm_add_epi64(hi, mulround);
- lo = _mm_srli_epi64(lo, 13);
- hi = _mm_slli_epi64(hi, 32 - 13);
- v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC));
- _mm_store_si128((__m128i *) & (c2[i]), v);
- }
- for (; i < len; ++i) {
- OPJ_INT32 r = c0[i];
- OPJ_INT32 g = c1[i];
- OPJ_INT32 b = c2[i];
- OPJ_INT32 y = opj_int_fix_mul(r, 2449) + opj_int_fix_mul(g,
- 4809) + opj_int_fix_mul(b, 934);
- OPJ_INT32 u = -opj_int_fix_mul(r, 1382) - opj_int_fix_mul(g,
- 2714) + opj_int_fix_mul(b, 4096);
- OPJ_INT32 v = opj_int_fix_mul(r, 4096) - opj_int_fix_mul(g,
- 3430) - opj_int_fix_mul(b, 666);
- c0[i] = y;
- c1[i] = u;
- c2[i] = v;
+ r = _mm_load_ps(c0);
+ g = _mm_load_ps(c1);
+ b = _mm_load_ps(c2);
+ y = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, YR), _mm_mul_ps(g, YG)),
+ _mm_mul_ps(b, YB));
+ u = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, UR), _mm_mul_ps(g, UG)),
+ _mm_mul_ps(b, UB));
+ v = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, VR), _mm_mul_ps(g, VG)),
+ _mm_mul_ps(b, VB));
+ _mm_store_ps(c0, y);
+ _mm_store_ps(c1, u);
+ _mm_store_ps(c2, v);
+ c0 += 4;
+ c1 += 4;
+ c2 += 4;
}
-}
-#else
-void opj_mct_encode_real(
- OPJ_INT32* OPJ_RESTRICT c0,
- OPJ_INT32* OPJ_RESTRICT c1,
- OPJ_INT32* OPJ_RESTRICT c2,
- OPJ_SIZE_T n)
-{
- OPJ_SIZE_T i;
+ n &= 7;
+#endif
for (i = 0; i < n; ++i) {
- OPJ_INT32 r = c0[i];
- OPJ_INT32 g = c1[i];
- OPJ_INT32 b = c2[i];
- OPJ_INT32 y = opj_int_fix_mul(r, 2449) + opj_int_fix_mul(g,
- 4809) + opj_int_fix_mul(b, 934);
- OPJ_INT32 u = -opj_int_fix_mul(r, 1382) - opj_int_fix_mul(g,
- 2714) + opj_int_fix_mul(b, 4096);
- OPJ_INT32 v = opj_int_fix_mul(r, 4096) - opj_int_fix_mul(g,
- 3430) - opj_int_fix_mul(b, 666);
+ OPJ_FLOAT32 r = c0[i];
+ OPJ_FLOAT32 g = c1[i];
+ OPJ_FLOAT32 b = c2[i];
+ OPJ_FLOAT32 y = 0.299f * r + 0.587f * g + 0.114f * b;
+ OPJ_FLOAT32 u = -0.16875f * r - 0.331260f * g + 0.5f * b;
+ OPJ_FLOAT32 v = 0.5f * r - 0.41869f * g - 0.08131f * b;
c0[i] = y;
c1[i] = u;
c2[i] = v;
}
}
-#endif
/* <summary> */
/* Inverse irreversible MCT. */
diff --git a/src/lib/openjp2/mct.h b/src/lib/openjp2/mct.h
index 2e37ce73..3e1f5e49 100644
--- a/src/lib/openjp2/mct.h
+++ b/src/lib/openjp2/mct.h
@@ -85,8 +85,9 @@ Apply an irreversible multi-component transform to an image
@param c2 Samples blue component
@param n Number of samples for each component
*/
-void opj_mct_encode_real(OPJ_INT32* OPJ_RESTRICT c0, OPJ_INT32* OPJ_RESTRICT c1,
- OPJ_INT32* OPJ_RESTRICT c2, OPJ_SIZE_T n);
+void opj_mct_encode_real(OPJ_FLOAT32* OPJ_RESTRICT c0,
+ OPJ_FLOAT32* OPJ_RESTRICT c1,
+ OPJ_FLOAT32* OPJ_RESTRICT c2, OPJ_SIZE_T n);
/**
Apply an irreversible multi-component inverse transform to an image
@param c0 Samples for luminance component
diff --git a/src/lib/openjp2/mqc.c b/src/lib/openjp2/mqc.c
index 6299b171..4cbfabd0 100644
--- a/src/lib/openjp2/mqc.c
+++ b/src/lib/openjp2/mqc.c
@@ -47,27 +47,6 @@
/*@{*/
/**
-Output a byte, doing bit-stuffing if necessary.
-After a 0xff byte, the next byte must be smaller than 0x90.
-@param mqc MQC handle
-*/
-static void opj_mqc_byteout(opj_mqc_t *mqc);
-/**
-Renormalize mqc->a and mqc->c while encoding, so that mqc->a stays between 0x8000 and 0x10000
-@param mqc MQC handle
-*/
-static void opj_mqc_renorme(opj_mqc_t *mqc);
-/**
-Encode the most probable symbol
-@param mqc MQC handle
-*/
-static void opj_mqc_codemps(opj_mqc_t *mqc);
-/**
-Encode the most least symbol
-@param mqc MQC handle
-*/
-static void opj_mqc_codelps(opj_mqc_t *mqc);
-/**
Fill mqc->c with 1's for flushing
@param mqc MQC handle
*/
@@ -182,80 +161,6 @@ static const opj_mqc_state_t mqc_states[47 * 2] = {
==========================================================
*/
-static void opj_mqc_byteout(opj_mqc_t *mqc)
-{
- /* bp is initialized to start - 1 in opj_mqc_init_enc() */
- /* but this is safe, see opj_tcd_code_block_enc_allocate_data() */
- assert(mqc->bp >= mqc->start - 1);
- if (*mqc->bp == 0xff) {
- mqc->bp++;
- *mqc->bp = (OPJ_BYTE)(mqc->c >> 20);
- mqc->c &= 0xfffff;
- mqc->ct = 7;
- } else {
- if ((mqc->c & 0x8000000) == 0) {
- mqc->bp++;
- *mqc->bp = (OPJ_BYTE)(mqc->c >> 19);
- mqc->c &= 0x7ffff;
- mqc->ct = 8;
- } else {
- (*mqc->bp)++;
- if (*mqc->bp == 0xff) {
- mqc->c &= 0x7ffffff;
- mqc->bp++;
- *mqc->bp = (OPJ_BYTE)(mqc->c >> 20);
- mqc->c &= 0xfffff;
- mqc->ct = 7;
- } else {
- mqc->bp++;
- *mqc->bp = (OPJ_BYTE)(mqc->c >> 19);
- mqc->c &= 0x7ffff;
- mqc->ct = 8;
- }
- }
- }
-}
-
-static void opj_mqc_renorme(opj_mqc_t *mqc)
-{
- do {
- mqc->a <<= 1;
- mqc->c <<= 1;
- mqc->ct--;
- if (mqc->ct == 0) {
- opj_mqc_byteout(mqc);
- }
- } while ((mqc->a & 0x8000) == 0);
-}
-
-static void opj_mqc_codemps(opj_mqc_t *mqc)
-{
- mqc->a -= (*mqc->curctx)->qeval;
- if ((mqc->a & 0x8000) == 0) {
- if (mqc->a < (*mqc->curctx)->qeval) {
- mqc->a = (*mqc->curctx)->qeval;
- } else {
- mqc->c += (*mqc->curctx)->qeval;
- }
- *mqc->curctx = (*mqc->curctx)->nmps;
- opj_mqc_renorme(mqc);
- } else {
- mqc->c += (*mqc->curctx)->qeval;
- }
-}
-
-static void opj_mqc_codelps(opj_mqc_t *mqc)
-{
- mqc->a -= (*mqc->curctx)->qeval;
- if (mqc->a < (*mqc->curctx)->qeval) {
- mqc->c += (*mqc->curctx)->qeval;
- } else {
- mqc->a = (*mqc->curctx)->qeval;
- }
- *mqc->curctx = (*mqc->curctx)->nlps;
- opj_mqc_renorme(mqc);
-}
-
static void opj_mqc_setbits(opj_mqc_t *mqc)
{
OPJ_UINT32 tempc = mqc->c + mqc->a;
@@ -303,14 +208,6 @@ void opj_mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp)
mqc->end_of_byte_stream_counter = 0;
}
-void opj_mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d)
-{
- if ((*mqc->curctx)->mps == d) {
- opj_mqc_codemps(mqc);
- } else {
- opj_mqc_codelps(mqc);
- }
-}
void opj_mqc_flush(opj_mqc_t *mqc)
{
@@ -329,8 +226,6 @@ void opj_mqc_flush(opj_mqc_t *mqc)
}
}
-#define BYPASS_CT_INIT 0xDEADBEEF
-
void opj_mqc_bypass_init_enc(opj_mqc_t *mqc)
{
/* This function is normally called after at least one opj_mqc_flush() */
@@ -475,6 +370,43 @@ void opj_mqc_erterm_enc(opj_mqc_t *mqc)
}
}
+static INLINE void opj_mqc_renorme(opj_mqc_t *mqc)
+{
+ opj_mqc_renorme_macro(mqc, mqc->a, mqc->c, mqc->ct);
+}
+
+/**
+Encode the most probable symbol
+@param mqc MQC handle
+*/
+static INLINE void opj_mqc_codemps(opj_mqc_t *mqc)
+{
+ opj_mqc_codemps_macro(mqc, mqc->curctx, mqc->a, mqc->c, mqc->ct);
+}
+
+/**
+Encode the most least symbol
+@param mqc MQC handle
+*/
+static INLINE void opj_mqc_codelps(opj_mqc_t *mqc)
+{
+ opj_mqc_codelps_macro(mqc, mqc->curctx, mqc->a, mqc->c, mqc->ct);
+}
+
+/**
+Encode a symbol using the MQ-coder
+@param mqc MQC handle
+@param d The symbol to be encoded (0 or 1)
+*/
+static INLINE void opj_mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d)
+{
+ if ((*mqc->curctx)->mps == d) {
+ opj_mqc_codemps(mqc);
+ } else {
+ opj_mqc_codelps(mqc);
+ }
+}
+
void opj_mqc_segmark_enc(opj_mqc_t *mqc)
{
OPJ_UINT32 i;
@@ -557,4 +489,36 @@ void opj_mqc_setstate(opj_mqc_t *mqc, OPJ_UINT32 ctxno, OPJ_UINT32 msb,
mqc->ctxs[ctxno] = &mqc_states[msb + (OPJ_UINT32)(prob << 1)];
}
-
+void opj_mqc_byteout(opj_mqc_t *mqc)
+{
+ /* bp is initialized to start - 1 in opj_mqc_init_enc() */
+ /* but this is safe, see opj_tcd_code_block_enc_allocate_data() */
+ assert(mqc->bp >= mqc->start - 1);
+ if (*mqc->bp == 0xff) {
+ mqc->bp++;
+ *mqc->bp = (OPJ_BYTE)(mqc->c >> 20);
+ mqc->c &= 0xfffff;
+ mqc->ct = 7;
+ } else {
+ if ((mqc->c & 0x8000000) == 0) {
+ mqc->bp++;
+ *mqc->bp = (OPJ_BYTE)(mqc->c >> 19);
+ mqc->c &= 0x7ffff;
+ mqc->ct = 8;
+ } else {
+ (*mqc->bp)++;
+ if (*mqc->bp == 0xff) {
+ mqc->c &= 0x7ffffff;
+ mqc->bp++;
+ *mqc->bp = (OPJ_BYTE)(mqc->c >> 20);
+ mqc->c &= 0xfffff;
+ mqc->ct = 7;
+ } else {
+ mqc->bp++;
+ *mqc->bp = (OPJ_BYTE)(mqc->c >> 19);
+ mqc->c &= 0x7ffff;
+ mqc->ct = 8;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/lib/openjp2/mqc.h b/src/lib/openjp2/mqc.h
index 69a2a79d..9850fed0 100644
--- a/src/lib/openjp2/mqc.h
+++ b/src/lib/openjp2/mqc.h
@@ -96,6 +96,8 @@ typedef struct opj_mqc {
OPJ_BYTE backup[OPJ_COMMON_CBLK_DATA_EXTRA];
} opj_mqc_t;
+#define BYPASS_CT_INIT 0xDEADBEEF
+
#include "mqc_inl.h"
/** @name Exported functions */
@@ -135,12 +137,7 @@ Set the current context used for coding/decoding
@param ctxno Number that identifies the context
*/
#define opj_mqc_setcurctx(mqc, ctxno) (mqc)->curctx = &(mqc)->ctxs[(OPJ_UINT32)(ctxno)]
-/**
-Encode a symbol using the MQ-coder
-@param mqc MQC handle
-@param d The symbol to be encoded (0 or 1)
-*/
-void opj_mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d);
+
/**
Flush the encoder, so that all remaining data is written
@param mqc MQC handle
diff --git a/src/lib/openjp2/mqc_inl.h b/src/lib/openjp2/mqc_inl.h
index 310a3287..0031b94b 100644
--- a/src/lib/openjp2/mqc_inl.h
+++ b/src/lib/openjp2/mqc_inl.h
@@ -156,13 +156,13 @@ static INLINE OPJ_UINT32 opj_mqc_raw_decode(opj_mqc_t *mqc)
} \
}
-#define DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct) \
+#define DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct) \
register const opj_mqc_state_t **curctx = mqc->curctx; \
register OPJ_UINT32 c = mqc->c; \
register OPJ_UINT32 a = mqc->a; \
register OPJ_UINT32 ct = mqc->ct
-#define UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct) \
+#define UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct) \
mqc->curctx = curctx; \
mqc->c = c; \
mqc->a = a; \
@@ -193,4 +193,90 @@ Decode a symbol
#define opj_mqc_decode(d, mqc) \
opj_mqc_decode_macro(d, mqc, mqc->curctx, mqc->a, mqc->c, mqc->ct)
+/**
+Output a byte, doing bit-stuffing if necessary.
+After a 0xff byte, the next byte must be smaller than 0x90.
+@param mqc MQC handle
+*/
+void opj_mqc_byteout(opj_mqc_t *mqc);
+
+/**
+Renormalize mqc->a and mqc->c while encoding, so that mqc->a stays between 0x8000 and 0x10000
+@param mqc MQC handle
+@param a_ value of mqc->a
+@param c_ value of mqc->c_
+@param ct_ value of mqc->ct_
+*/
+#define opj_mqc_renorme_macro(mqc, a_, c_, ct_) \
+{ \
+ do { \
+ a_ <<= 1; \
+ c_ <<= 1; \
+ ct_--; \
+ if (ct_ == 0) { \
+ mqc->c = c_; \
+ opj_mqc_byteout(mqc); \
+ c_ = mqc->c; \
+ ct_ = mqc->ct; \
+ } \
+ } while( (a_ & 0x8000) == 0); \
+}
+
+#define opj_mqc_codemps_macro(mqc, curctx, a, c, ct) \
+{ \
+ a -= (*curctx)->qeval; \
+ if ((a & 0x8000) == 0) { \
+ if (a < (*curctx)->qeval) { \
+ a = (*curctx)->qeval; \
+ } else { \
+ c += (*curctx)->qeval; \
+ } \
+ *curctx = (*curctx)->nmps; \
+ opj_mqc_renorme_macro(mqc, a, c, ct); \
+ } else { \
+ c += (*curctx)->qeval; \
+ } \
+}
+
+#define opj_mqc_codelps_macro(mqc, curctx, a, c, ct) \
+{ \
+ a -= (*curctx)->qeval; \
+ if (a < (*curctx)->qeval) { \
+ c += (*curctx)->qeval; \
+ } else { \
+ a = (*curctx)->qeval; \
+ } \
+ *curctx = (*curctx)->nlps; \
+ opj_mqc_renorme_macro(mqc, a, c, ct); \
+}
+
+#define opj_mqc_encode_macro(mqc, curctx, a, c, ct, d) \
+{ \
+ if ((*curctx)->mps == (d)) { \
+ opj_mqc_codemps_macro(mqc, curctx, a, c, ct); \
+ } else { \
+ opj_mqc_codelps_macro(mqc, curctx, a, c, ct); \
+ } \
+}
+
+
+#define opj_mqc_bypass_enc_macro(mqc, c, ct, d) \
+{\
+ if (ct == BYPASS_CT_INIT) {\
+ ct = 8;\
+ }\
+ ct--;\
+ c = c + ((d) << ct);\
+ if (ct == 0) {\
+ *mqc->bp = (OPJ_BYTE)c;\
+ ct = 8;\
+ /* If the previous byte was 0xff, make sure that the next msb is 0 */ \
+ if (*mqc->bp == 0xff) {\
+ ct = 7;\
+ }\
+ mqc->bp++;\
+ c = 0;\
+ }\
+}
+
#endif /* OPJ_MQC_INL_H */
diff --git a/src/lib/openjp2/openjpeg.c b/src/lib/openjp2/openjpeg.c
index 1e2d60a6..9c9b6eb0 100644
--- a/src/lib/openjp2/openjpeg.c
+++ b/src/lib/openjp2/openjpeg.c
@@ -657,6 +657,9 @@ opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format)
const char* const*,
struct opj_event_mgr *)) opj_j2k_encoder_set_extra_options;
+ l_codec->opj_set_threads =
+ (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_j2k_set_threads;
+
l_codec->m_codec = opj_j2k_create_compress();
if (! l_codec->m_codec) {
opj_free(l_codec);
@@ -700,6 +703,9 @@ opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format)
const char* const*,
struct opj_event_mgr *)) opj_jp2_encoder_set_extra_options;
+ l_codec->opj_set_threads =
+ (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_jp2_set_threads;
+
l_codec->m_codec = opj_jp2_create(OPJ_FALSE);
if (! l_codec->m_codec) {
opj_free(l_codec);
diff --git a/src/lib/openjp2/openjpeg.h b/src/lib/openjp2/openjpeg.h
index da84f399..4bbd9a8b 100644
--- a/src/lib/openjp2/openjpeg.h
+++ b/src/lib/openjp2/openjpeg.h
@@ -1348,15 +1348,14 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec,
* number, or "ALL_CPUS". If OPJ_NUM_THREADS is set and this function is called,
* this function will override the behaviour of the environment variable.
*
- * Currently this function must be called after opj_setup_decoder() and
- * before opj_read_header().
+ * This function must be called after opj_setup_decoder() and
+ * before opj_read_header() for the decoding side, or after opj_setup_encoder()
+ * and before opj_start_compress() for the encoding side.
*
- * Note: currently only has effect on the decompressor.
- *
- * @param p_codec decompressor handler
+ * @param p_codec decompressor or compressor handler
* @param num_threads number of threads.
*
- * @return OPJ_TRUE if the decoder is correctly set
+ * @return OPJ_TRUE if the function is successful.
*/
OPJ_API OPJ_BOOL OPJ_CALLCONV opj_codec_set_threads(opj_codec_t *p_codec,
int num_threads);
diff --git a/src/lib/openjp2/t1.c b/src/lib/openjp2/t1.c
index b32daeae..a850f4ff 100644
--- a/src/lib/openjp2/t1.c
+++ b/src/lib/openjp2/t1.c
@@ -61,6 +61,13 @@
#define opj_t1_setcurctx(curctx, ctxno) curctx = &(mqc)->ctxs[(OPJ_UINT32)(ctxno)]
+/* Macros to deal with signed integer with just MSB bit set for
+ * negative values (smr = signed magnitude representation) */
+#define opj_smr_abs(x) (((OPJ_UINT32)(x)) & 0x7FFFFFFFU)
+#define opj_smr_sign(x) (((OPJ_UINT32)(x)) >> 31)
+#define opj_to_smr(x) ((x) >= 0 ? (OPJ_UINT32)(x) : ((OPJ_UINT32)(-x) | 0x80000000U))
+
+
/** @name Local static functions */
/*@{*/
@@ -177,18 +184,18 @@ static OPJ_FLOAT64 opj_t1_getwmsedec(
const OPJ_FLOAT64 * mct_norms,
OPJ_UINT32 mct_numcomps);
-static void opj_t1_encode_cblk(opj_t1_t *t1,
- opj_tcd_cblk_enc_t* cblk,
- OPJ_UINT32 orient,
- OPJ_UINT32 compno,
- OPJ_UINT32 level,
- OPJ_UINT32 qmfbid,
- OPJ_FLOAT64 stepsize,
- OPJ_UINT32 cblksty,
- OPJ_UINT32 numcomps,
- opj_tcd_tile_t * tile,
- const OPJ_FLOAT64 * mct_norms,
- OPJ_UINT32 mct_numcomps);
+/** Return "cumwmsedec" that should be used to increase tile->distotile */
+static double opj_t1_encode_cblk(opj_t1_t *t1,
+ opj_tcd_cblk_enc_t* cblk,
+ OPJ_UINT32 orient,
+ OPJ_UINT32 compno,
+ OPJ_UINT32 level,
+ OPJ_UINT32 qmfbid,
+ OPJ_FLOAT64 stepsize,
+ OPJ_UINT32 cblksty,
+ OPJ_UINT32 numcomps,
+ const OPJ_FLOAT64 * mct_norms,
+ OPJ_UINT32 mct_numcomps);
/**
Decode 1 code-block
@@ -329,61 +336,53 @@ static INLINE void opj_t1_update_flags(opj_flag_t *flagsp, OPJ_UINT32 ci,
/**
Encode significant pass
*/
-static INLINE void opj_t1_enc_sigpass_step(opj_t1_t *t1,
- opj_flag_t *flagsp,
- OPJ_INT32 *datap,
- OPJ_INT32 bpno,
- OPJ_INT32 one,
- OPJ_INT32 *nmsedec,
- OPJ_BYTE type,
- OPJ_UINT32 ci,
- OPJ_UINT32 vsc)
-{
- OPJ_UINT32 v;
-
- opj_mqc_t *mqc = &(t1->mqc); /* MQC component */
-
- OPJ_UINT32 const flags = *flagsp;
-
- if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U &&
- (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) {
- OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U));
- v = (opj_int_abs(*datap) & one) ? 1 : 0;
-#ifdef DEBUG_ENC_SIG
- fprintf(stderr, " ctxt1=%d\n", ctxt1);
-#endif
- opj_mqc_setcurctx(mqc, ctxt1);
- if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */
- opj_mqc_bypass_enc(mqc, v);
- } else {
- opj_mqc_encode(mqc, v);
- }
- if (v) {
- OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index(
- *flagsp,
- flagsp[-1], flagsp[1],
- ci);
- OPJ_UINT32 ctxt2 = opj_t1_getctxno_sc(lu);
- v = *datap < 0 ? 1U : 0U;
- *nmsedec += opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap),
- (OPJ_UINT32)bpno);
-#ifdef DEBUG_ENC_SIG
- fprintf(stderr, " ctxt2=%d\n", ctxt2);
-#endif
- opj_mqc_setcurctx(mqc, ctxt2);
- if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */
- opj_mqc_bypass_enc(mqc, v);
- } else {
- OPJ_UINT32 spb = opj_t1_getspb(lu);
-#ifdef DEBUG_ENC_SIG
- fprintf(stderr, " spb=%d\n", spb);
-#endif
- opj_mqc_encode(mqc, v ^ spb);
- }
- opj_t1_update_flags(flagsp, ci, v, t1->w + 2, vsc);
- }
- *flagsp |= T1_PI_THIS << (ci * 3U);
- }
+#define opj_t1_enc_sigpass_step_macro(mqc, curctx, a, c, ct, flagspIn, datapIn, bpno, one, nmsedec, type, ciIn, vscIn) \
+{ \
+ OPJ_UINT32 v; \
+ const OPJ_UINT32 ci = (ciIn); \
+ const OPJ_UINT32 vsc = (vscIn); \
+ const OPJ_INT32* l_datap = (datapIn); \
+ opj_flag_t* flagsp = (flagspIn); \
+ OPJ_UINT32 const flags = *flagsp; \
+ if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && \
+ (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { \
+ OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); \
+ v = (opj_smr_abs(*l_datap) & (OPJ_UINT32)one) ? 1 : 0; \
+/* #ifdef DEBUG_ENC_SIG */ \
+/* fprintf(stderr, " ctxt1=%d\n", ctxt1); */ \
+/* #endif */ \
+ opj_t1_setcurctx(curctx, ctxt1); \
+ if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ \
+ opj_mqc_bypass_enc_macro(mqc, c, ct, v); \
+ } else { \
+ opj_mqc_encode_macro(mqc, curctx, a, c, ct, v); \
+ } \
+ if (v) { \
+ OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( \
+ *flagsp, \
+ flagsp[-1], flagsp[1], \
+ ci); \
+ OPJ_UINT32 ctxt2 = opj_t1_getctxno_sc(lu); \
+ v = opj_smr_sign(*l_datap); \
+ *nmsedec += opj_t1_getnmsedec_sig(opj_smr_abs(*l_datap), \
+ (OPJ_UINT32)bpno); \
+/* #ifdef DEBUG_ENC_SIG */ \
+/* fprintf(stderr, " ctxt2=%d\n", ctxt2); */ \
+/* #endif */ \
+ opj_t1_setcurctx(curctx, ctxt2); \
+ if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ \
+ opj_mqc_bypass_enc_macro(mqc, c, ct, v); \
+ } else { \
+ OPJ_UINT32 spb = opj_t1_getspb(lu); \
+/* #ifdef DEBUG_ENC_SIG */ \
+/* fprintf(stderr, " spb=%d\n", spb); */ \
+/* #endif */ \
+ opj_mqc_encode_macro(mqc, curctx, a, c, ct, v ^ spb); \
+ } \
+ opj_t1_update_flags(flagsp, ci, v, t1->w + 2, vsc); \
+ } \
+ *flagsp |= T1_PI_THIS << (ci * 3U); \
+ } \
}
static INLINE void opj_t1_dec_sigpass_step_raw(
@@ -464,63 +463,64 @@ static void opj_t1_enc_sigpass(opj_t1_t *t1,
OPJ_INT32 const one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
opj_flag_t* f = &T1_FLAGS(0, 0);
OPJ_UINT32 const extra = 2;
+ opj_mqc_t* mqc = &(t1->mqc);
+ DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct);
+ const OPJ_INT32* datap = t1->data;
*nmsedec = 0;
#ifdef DEBUG_ENC_SIG
fprintf(stderr, "enc_sigpass: bpno=%d\n", bpno);
#endif
- for (k = 0; k < (t1->h & ~3U); k += 4) {
+ for (k = 0; k < (t1->h & ~3U); k += 4, f += extra) {
+ const OPJ_UINT32 w = t1->w;
#ifdef DEBUG_ENC_SIG
fprintf(stderr, " k=%d\n", k);
#endif
- for (i = 0; i < t1->w; ++i) {
+ for (i = 0; i < w; ++i, ++f, datap += 4) {
#ifdef DEBUG_ENC_SIG
fprintf(stderr, " i=%d\n", i);
#endif
if (*f == 0U) {
/* Nothing to do for any of the 4 data points */
- f++;
continue;
}
- opj_t1_enc_sigpass_step(
- t1,
+ opj_t1_enc_sigpass_step_macro(
+ mqc, curctx, a, c, ct,
f,
- &t1->data[((k + 0) * t1->data_stride) + i],
+ &datap[0],
bpno,
one,
nmsedec,
type,
0, cblksty & J2K_CCP_CBLKSTY_VSC);
- opj_t1_enc_sigpass_step(
- t1,
+ opj_t1_enc_sigpass_step_macro(
+ mqc, curctx, a, c, ct,
f,
- &t1->data[((k + 1) * t1->data_stride) + i],
+ &datap[1],
bpno,
one,
nmsedec,
type,
1, 0);
- opj_t1_enc_sigpass_step(
- t1,
+ opj_t1_enc_sigpass_step_macro(
+ mqc, curctx, a, c, ct,
f,
- &t1->data[((k + 2) * t1->data_stride) + i],
+ &datap[2],
bpno,
one,
nmsedec,
type,
2, 0);
- opj_t1_enc_sigpass_step(
- t1,
+ opj_t1_enc_sigpass_step_macro(
+ mqc, curctx, a, c, ct,
f,
- &t1->data[((k + 3) * t1->data_stride) + i],
+ &datap[3],
bpno,
one,
nmsedec,
type,
3, 0);
- ++f;
}
- f += extra;
}
if (k < t1->h) {
@@ -528,20 +528,20 @@ static void opj_t1_enc_sigpass(opj_t1_t *t1,
#ifdef DEBUG_ENC_SIG
fprintf(stderr, " k=%d\n", k);
#endif
- for (i = 0; i < t1->w; ++i) {
+ for (i = 0; i < t1->w; ++i, ++f) {
#ifdef DEBUG_ENC_SIG
fprintf(stderr, " i=%d\n", i);
#endif
if (*f == 0U) {
/* Nothing to do for any of the 4 data points */
- f++;
+ datap += (t1->h - k);
continue;
}
- for (j = k; j < t1->h; ++j) {
- opj_t1_enc_sigpass_step(
- t1,
+ for (j = k; j < t1->h; ++j, ++datap) {
+ opj_t1_enc_sigpass_step_macro(
+ mqc, curctx, a, c, ct,
f,
- &t1->data[(j * t1->data_stride) + i],
+ &datap[0],
bpno,
one,
nmsedec,
@@ -549,9 +549,10 @@ static void opj_t1_enc_sigpass(opj_t1_t *t1,
j - k,
(j == k && (cblksty & J2K_CCP_CBLKSTY_VSC) != 0));
}
- ++f;
}
}
+
+ UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct);
}
static void opj_t1_dec_sigpass_raw(
@@ -626,7 +627,7 @@ static void opj_t1_dec_sigpass_raw(
register opj_flag_t *flagsp = &t1->flags[(flags_stride) + 1]; \
const OPJ_UINT32 l_w = w; \
opj_mqc_t* mqc = &(t1->mqc); \
- DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \
+ DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \
register OPJ_UINT32 v; \
one = 1 << bpno; \
half = one >> 1; \
@@ -651,7 +652,7 @@ static void opj_t1_dec_sigpass_raw(
} \
} \
} \
- UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \
+ UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \
if( k < h ) { \
for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \
for (j = 0; j < h - k; ++j) { \
@@ -715,38 +716,27 @@ static void opj_t1_dec_sigpass_mqc(
/**
Encode refinement pass step
*/
-static INLINE void opj_t1_enc_refpass_step(opj_t1_t *t1,
- opj_flag_t *flagsp,
- OPJ_INT32 *datap,
- OPJ_INT32 bpno,
- OPJ_INT32 one,
- OPJ_INT32 *nmsedec,
- OPJ_BYTE type,
- OPJ_UINT32 ci)
-{
- OPJ_UINT32 v;
-
- opj_mqc_t *mqc = &(t1->mqc); /* MQC component */
-
- OPJ_UINT32 const shift_flags =
- (*flagsp >> (ci * 3U));
-
- if ((shift_flags & (T1_SIGMA_THIS | T1_PI_THIS)) == T1_SIGMA_THIS) {
- OPJ_UINT32 ctxt = opj_t1_getctxno_mag(shift_flags);
- *nmsedec += opj_t1_getnmsedec_ref((OPJ_UINT32)opj_int_abs(*datap),
- (OPJ_UINT32)bpno);
- v = (opj_int_abs(*datap) & one) ? 1 : 0;
-#ifdef DEBUG_ENC_REF
- fprintf(stderr, " ctxt=%d\n", ctxt);
-#endif
- opj_mqc_setcurctx(mqc, ctxt);
- if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */
- opj_mqc_bypass_enc(mqc, v);
- } else {
- opj_mqc_encode(mqc, v);
- }
- *flagsp |= T1_MU_THIS << (ci * 3U);
- }
+#define opj_t1_enc_refpass_step_macro(mqc, curctx, a, c, ct, flags, flagsUpdated, datap, bpno, one, nmsedec, type, ci) \
+{\
+ OPJ_UINT32 v; \
+ if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << ((ci) * 3U))) == (T1_SIGMA_THIS << ((ci) * 3U))) { \
+ const OPJ_UINT32 shift_flags = (flags >> ((ci) * 3U)); \
+ OPJ_UINT32 ctxt = opj_t1_getctxno_mag(shift_flags); \
+ OPJ_UINT32 abs_data = opj_smr_abs(*datap); \
+ *nmsedec += opj_t1_getnmsedec_ref(abs_data, \
+ (OPJ_UINT32)bpno); \
+ v = ((OPJ_INT32)abs_data & one) ? 1 : 0; \
+/* #ifdef DEBUG_ENC_REF */ \
+/* fprintf(stderr, " ctxt=%d\n", ctxt); */ \
+/* #endif */ \
+ opj_t1_setcurctx(curctx, ctxt); \
+ if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ \
+ opj_mqc_bypass_enc_macro(mqc, c, ct, v); \
+ } else { \
+ opj_mqc_encode_macro(mqc, curctx, a, c, ct, v); \
+ } \
+ flagsUpdated |= T1_MU_THIS << ((ci) * 3U); \
+ } \
}
@@ -807,100 +797,104 @@ static void opj_t1_enc_refpass(
const OPJ_INT32 one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
opj_flag_t* f = &T1_FLAGS(0, 0);
const OPJ_UINT32 extra = 2U;
+ opj_mqc_t* mqc = &(t1->mqc);
+ DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct);
+ const OPJ_INT32* datap = t1->data;
*nmsedec = 0;
#ifdef DEBUG_ENC_REF
fprintf(stderr, "enc_refpass: bpno=%d\n", bpno);
#endif
- for (k = 0; k < (t1->h & ~3U); k += 4) {
+ for (k = 0; k < (t1->h & ~3U); k += 4, f += extra) {
#ifdef DEBUG_ENC_REF
fprintf(stderr, " k=%d\n", k);
#endif
- for (i = 0; i < t1->w; ++i) {
+ for (i = 0; i < t1->w; ++i, f++, datap += 4) {
+ const OPJ_UINT32 flags = *f;
+ OPJ_UINT32 flagsUpdated = flags;
#ifdef DEBUG_ENC_REF
fprintf(stderr, " i=%d\n", i);
#endif
- if ((*f & (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13)) == 0) {
+ if ((flags & (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13)) == 0) {
/* none significant */
- f++;
continue;
}
- if ((*f & (T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3)) ==
+ if ((flags & (T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3)) ==
(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3)) {
/* all processed by sigpass */
- f++;
continue;
}
- opj_t1_enc_refpass_step(
- t1,
- f,
- &t1->data[((k + 0) * t1->data_stride) + i],
+ opj_t1_enc_refpass_step_macro(
+ mqc, curctx, a, c, ct,
+ flags, flagsUpdated,
+ &datap[0],
bpno,
one,
nmsedec,
type,
0);
- opj_t1_enc_refpass_step(
- t1,
- f,
- &t1->data[((k + 1) * t1->data_stride) + i],
+ opj_t1_enc_refpass_step_macro(
+ mqc, curctx, a, c, ct,
+ flags, flagsUpdated,
+ &datap[1],
bpno,
one,
nmsedec,
type,
1);
- opj_t1_enc_refpass_step(
- t1,
- f,
- &t1->data[((k + 2) * t1->data_stride) + i],
+ opj_t1_enc_refpass_step_macro(
+ mqc, curctx, a, c, ct,
+ flags, flagsUpdated,
+ &datap[2],
bpno,
one,
nmsedec,
type,
2);
- opj_t1_enc_refpass_step(
- t1,
- f,
- &t1->data[((k + 3) * t1->data_stride) + i],
+ opj_t1_enc_refpass_step_macro(
+ mqc, curctx, a, c, ct,
+ flags, flagsUpdated,
+ &datap[3],
bpno,
one,
nmsedec,
type,
3);
- ++f;
+ *f = flagsUpdated;
}
- f += extra;
}
if (k < t1->h) {
OPJ_UINT32 j;
+ const OPJ_UINT32 remaining_lines = t1->h - k;
#ifdef DEBUG_ENC_REF
fprintf(stderr, " k=%d\n", k);
#endif
- for (i = 0; i < t1->w; ++i) {
+ for (i = 0; i < t1->w; ++i, ++f) {
#ifdef DEBUG_ENC_REF
fprintf(stderr, " i=%d\n", i);
#endif
if ((*f & (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13)) == 0) {
/* none significant */
- f++;
+ datap += remaining_lines;
continue;
}
- for (j = k; j < t1->h; ++j) {
- opj_t1_enc_refpass_step(
- t1,
- f,
- &t1->data[(j * t1->data_stride) + i],
+ for (j = 0; j < remaining_lines; ++j, datap ++) {
+ opj_t1_enc_refpass_step_macro(
+ mqc, curctx, a, c, ct,
+ *f, *f,
+ &datap[0],
bpno,
one,
nmsedec,
type,
- j - k);
+ j);
}
- ++f;
}
}
+
+ UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct);
}
@@ -968,7 +962,7 @@ static void opj_t1_dec_refpass_raw(
register opj_flag_t *flagsp = &t1->flags[flags_stride + 1]; \
const OPJ_UINT32 l_w = w; \
opj_mqc_t* mqc = &(t1->mqc); \
- DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \
+ DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \
register OPJ_UINT32 v; \
one = 1 << bpno; \
poshalf = one >> 1; \
@@ -992,7 +986,7 @@ static void opj_t1_dec_refpass_raw(
} \
} \
} \
- UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \
+ UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \
if( k < h ) { \
for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \
for (j = 0; j < h - k; ++j) { \
@@ -1030,86 +1024,71 @@ static void opj_t1_dec_refpass_mqc(
/**
Encode clean-up pass step
*/
-static void opj_t1_enc_clnpass_step(
- opj_t1_t *t1,
- opj_flag_t *flagsp,
- OPJ_INT32 *datap,
- OPJ_INT32 bpno,
- OPJ_INT32 one,
- OPJ_INT32 *nmsedec,
- OPJ_UINT32 agg,
- OPJ_UINT32 runlen,
- OPJ_UINT32 lim,
- OPJ_UINT32 cblksty)
-{
- OPJ_UINT32 v;
- OPJ_UINT32 ci;
- opj_mqc_t *mqc = &(t1->mqc); /* MQC component */
-
- const OPJ_UINT32 check = (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13 |
- T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3);
-
- if ((*flagsp & check) == check) {
- if (runlen == 0) {
- *flagsp &= ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3);
- } else if (runlen == 1) {
- *flagsp &= ~(T1_PI_1 | T1_PI_2 | T1_PI_3);
- } else if (runlen == 2) {
- *flagsp &= ~(T1_PI_2 | T1_PI_3);
- } else if (runlen == 3) {
- *flagsp &= ~(T1_PI_3);
- }
- return;
- }
-
- for (ci = runlen; ci < lim; ++ci) {
- OPJ_UINT32 vsc;
- opj_flag_t flags;
- OPJ_UINT32 ctxt1;
-
- flags = *flagsp;
-
- if ((agg != 0) && (ci == runlen)) {
- goto LABEL_PARTIAL;
- }
-
- if (!(flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U)))) {
- ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U));
-#ifdef DEBUG_ENC_CLN
- printf(" ctxt1=%d\n", ctxt1);
-#endif
- opj_mqc_setcurctx(mqc, ctxt1);
- v = (opj_int_abs(*datap) & one) ? 1 : 0;
- opj_mqc_encode(mqc, v);
- if (v) {
- OPJ_UINT32 ctxt2, spb;
- OPJ_UINT32 lu;
-LABEL_PARTIAL:
- lu = opj_t1_getctxtno_sc_or_spb_index(
- *flagsp,
- flagsp[-1], flagsp[1],
- ci);
- *nmsedec += opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap),
- (OPJ_UINT32)bpno);
- ctxt2 = opj_t1_getctxno_sc(lu);
-#ifdef DEBUG_ENC_CLN
- printf(" ctxt2=%d\n", ctxt2);
-#endif
- opj_mqc_setcurctx(mqc, ctxt2);
-
- v = *datap < 0 ? 1U : 0U;
- spb = opj_t1_getspb(lu);
-#ifdef DEBUG_ENC_CLN
- printf(" spb=%d\n", spb);
-#endif
- opj_mqc_encode(mqc, v ^ spb);
- vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (ci == 0)) ? 1 : 0;
- opj_t1_update_flags(flagsp, ci, v, t1->w + 2U, vsc);
- }
- }
- *flagsp &= ~(T1_PI_THIS << (3U * ci));
- datap += t1->data_stride;
- }
+#define opj_t1_enc_clnpass_step_macro(mqc, curctx, a, c, ct, flagspIn, datapIn, bpno, one, nmsedec, agg, runlen, lim, cblksty) \
+{ \
+ OPJ_UINT32 v; \
+ OPJ_UINT32 ci; \
+ opj_flag_t* const flagsp = (flagspIn); \
+ const OPJ_INT32* l_datap = (datapIn); \
+ const OPJ_UINT32 check = (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13 | \
+ T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \
+ \
+ if ((*flagsp & check) == check) { \
+ if (runlen == 0) { \
+ *flagsp &= ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \
+ } else if (runlen == 1) { \
+ *flagsp &= ~(T1_PI_1 | T1_PI_2 | T1_PI_3); \
+ } else if (runlen == 2) { \
+ *flagsp &= ~(T1_PI_2 | T1_PI_3); \
+ } else if (runlen == 3) { \
+ *flagsp &= ~(T1_PI_3); \
+ } \
+ } \
+ else \
+ for (ci = runlen; ci < lim; ++ci) { \
+ OPJ_BOOL goto_PARTIAL = OPJ_FALSE; \
+ if ((agg != 0) && (ci == runlen)) { \
+ goto_PARTIAL = OPJ_TRUE; \
+ } \
+ else if (!(*flagsp & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U)))) { \
+ OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, *flagsp >> (ci * 3U)); \
+/* #ifdef DEBUG_ENC_CLN */ \
+/* printf(" ctxt1=%d\n", ctxt1); */ \
+/* #endif */ \
+ opj_t1_setcurctx(curctx, ctxt1); \
+ v = (opj_smr_abs(*l_datap) & (OPJ_UINT32)one) ? 1 : 0; \
+ opj_mqc_encode_macro(mqc, curctx, a, c, ct, v); \
+ if (v) { \
+ goto_PARTIAL = OPJ_TRUE; \
+ } \
+ } \
+ if( goto_PARTIAL ) { \
+ OPJ_UINT32 vsc; \
+ OPJ_UINT32 ctxt2, spb; \
+ OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( \
+ *flagsp, \
+ flagsp[-1], flagsp[1], \
+ ci); \
+ *nmsedec += opj_t1_getnmsedec_sig(opj_smr_abs(*l_datap), \
+ (OPJ_UINT32)bpno); \
+ ctxt2 = opj_t1_getctxno_sc(lu); \
+/* #ifdef DEBUG_ENC_CLN */ \
+/* printf(" ctxt2=%d\n", ctxt2); */ \
+/* #endif */ \
+ opj_t1_setcurctx(curctx, ctxt2); \
+ \
+ v = opj_smr_sign(*l_datap); \
+ spb = opj_t1_getspb(lu); \
+/* #ifdef DEBUG_ENC_CLN */ \
+/* printf(" spb=%d\n", spb); */\
+/* #endif */ \
+ opj_mqc_encode_macro(mqc, curctx, a, c, ct, v ^ spb); \
+ vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (ci == 0)) ? 1 : 0; \
+ opj_t1_update_flags(flagsp, ci, v, t1->w + 2U, vsc); \
+ } \
+ *flagsp &= ~(T1_PI_THIS << (3U * ci)); \
+ l_datap ++; \
+ } \
}
#define opj_t1_dec_clnpass_step_macro(check_flags, partial, \
@@ -1165,47 +1144,50 @@ static void opj_t1_enc_clnpass(
{
OPJ_UINT32 i, k;
const OPJ_INT32 one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
- OPJ_UINT32 agg, runlen;
-
- opj_mqc_t *mqc = &(t1->mqc); /* MQC component */
+ opj_mqc_t* mqc = &(t1->mqc);
+ DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct);
+ const OPJ_INT32* datap = t1->data;
+ opj_flag_t *f = &T1_FLAGS(0, 0);
+ const OPJ_UINT32 extra = 2U;
*nmsedec = 0;
#ifdef DEBUG_ENC_CLN
printf("enc_clnpass: bpno=%d\n", bpno);
#endif
- for (k = 0; k < (t1->h & ~3U); k += 4) {
+ for (k = 0; k < (t1->h & ~3U); k += 4, f += extra) {
#ifdef DEBUG_ENC_CLN
printf(" k=%d\n", k);
#endif
- for (i = 0; i < t1->w; ++i) {
+ for (i = 0; i < t1->w; ++i, f++) {
+ OPJ_UINT32 agg, runlen;
#ifdef DEBUG_ENC_CLN
printf(" i=%d\n", i);
#endif
- agg = !(T1_FLAGS(i, k));
+ agg = !*f;
#ifdef DEBUG_ENC_CLN
printf(" agg=%d\n", agg);
#endif
if (agg) {
- for (runlen = 0; runlen < 4; ++runlen) {
- if (opj_int_abs(t1->data[((k + runlen)*t1->data_stride) + i]) & one) {
+ for (runlen = 0; runlen < 4; ++runlen, ++datap) {
+ if (opj_smr_abs(*datap) & (OPJ_UINT32)one) {
break;
}
}
- opj_mqc_setcurctx(mqc, T1_CTXNO_AGG);
- opj_mqc_encode(mqc, runlen != 4);
+ opj_t1_setcurctx(curctx, T1_CTXNO_AGG);
+ opj_mqc_encode_macro(mqc, curctx, a, c, ct, runlen != 4);
if (runlen == 4) {
continue;
}
- opj_mqc_setcurctx(mqc, T1_CTXNO_UNI);
- opj_mqc_encode(mqc, runlen >> 1);
- opj_mqc_encode(mqc, runlen & 1);
+ opj_t1_setcurctx(curctx, T1_CTXNO_UNI);
+ opj_mqc_encode_macro(mqc, curctx, a, c, ct, runlen >> 1);
+ opj_mqc_encode_macro(mqc, curctx, a, c, ct, runlen & 1);
} else {
runlen = 0;
}
- opj_t1_enc_clnpass_step(
- t1,
- &T1_FLAGS(i, k),
- &t1->data[((k + runlen) * t1->data_stride) + i],
+ opj_t1_enc_clnpass_step_macro(
+ mqc, curctx, a, c, ct,
+ f,
+ datap,
bpno,
one,
nmsedec,
@@ -1213,23 +1195,24 @@ static void opj_t1_enc_clnpass(
runlen,
4U,
cblksty);
+ datap += 4 - runlen;
}
}
if (k < t1->h) {
- agg = 0;
- runlen = 0;
+ const OPJ_UINT32 agg = 0;
+ const OPJ_UINT32 runlen = 0;
#ifdef DEBUG_ENC_CLN
printf(" k=%d\n", k);
#endif
- for (i = 0; i < t1->w; ++i) {
+ for (i = 0; i < t1->w; ++i, f++) {
#ifdef DEBUG_ENC_CLN
printf(" i=%d\n", i);
printf(" agg=%d\n", agg);
#endif
- opj_t1_enc_clnpass_step(
- t1,
- &T1_FLAGS(i, k),
- &t1->data[((k + runlen) * t1->data_stride) + i],
+ opj_t1_enc_clnpass_step_macro(
+ mqc, curctx, a, c, ct,
+ f,
+ datap,
bpno,
one,
nmsedec,
@@ -1237,8 +1220,11 @@ static void opj_t1_enc_clnpass(
runlen,
t1->h - k,
cblksty);
+ datap += t1->h - k;
}
}
+
+ UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct);
}
#define opj_t1_dec_clnpass_internal(t1, bpno, vsc, w, h, flags_stride) \
@@ -1250,7 +1236,7 @@ static void opj_t1_enc_clnpass(
opj_mqc_t* mqc = &(t1->mqc); \
register OPJ_INT32 *data = t1->data; \
register opj_flag_t *flagsp = &t1->flags[flags_stride + 1]; \
- DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \
+ DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \
register OPJ_UINT32 v; \
one = 1 << bpno; \
half = one >> 1; \
@@ -1319,7 +1305,7 @@ static void opj_t1_enc_clnpass(
*flagsp = flags & ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \
} \
} \
- UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \
+ UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \
if( k < h ) { \
for (i = 0; i < l_w; ++i, ++flagsp, ++data) { \
for (j = 0; j < h - k; ++j) { \
@@ -1426,7 +1412,11 @@ static OPJ_FLOAT64 opj_t1_getwmsedec(
if (qmfbid == 1) {
w2 = opj_dwt_getnorm(level, orient);
} else { /* if (qmfbid == 0) */
+ const OPJ_INT32 log2_gain = (orient == 0) ? 0 :
+ (orient == 3) ? 2 : 1;
w2 = opj_dwt_getnorm_real(level, orient);
+ /* Not sure this is right. But preserves past behaviour */
+ stepsize /= (1 << log2_gain);
}
wmsedec = w1 * w2 * stepsize * (1 << bpno);
@@ -1450,7 +1440,7 @@ static OPJ_BOOL opj_t1_allocate_buffers(
assert(w * h <= 4096);
/* encoder uses tile buffer, so no need to allocate */
- if (!t1->encoder) {
+ {
OPJ_UINT32 datasize = w * h;
if (datasize > t1->datasize) {
@@ -1560,8 +1550,7 @@ void opj_t1_destroy(opj_t1_t *p_t1)
return;
}
- /* encoder uses tile buffer, so no need to free */
- if (!p_t1->encoder && p_t1->data) {
+ if (p_t1->data) {
opj_aligned_free(p_t1->data);
p_t1->data = 00;
}
@@ -1739,10 +1728,11 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls)
datap[i] /= 2;
}
} else { /* if (tccp->qmfbid == 0) */
+ const float stepsize = 0.5f * band->stepsize;
i = 0;
#ifdef __SSE2__
{
- const __m128 xmm_stepsize = _mm_set1_ps(band->stepsize);
+ const __m128 xmm_stepsize = _mm_set1_ps(stepsize);
for (; i < (cblk_size & ~15U); i += 16) {
__m128 xmm0_data = _mm_cvtepi32_ps(_mm_load_si128((__m128i * const)(
datap + 0)));
@@ -1761,7 +1751,7 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls)
}
#endif
for (; i < cblk_size; ++i) {
- OPJ_FLOAT32 tmp = ((OPJ_FLOAT32)(*datap)) * band->stepsize;
+ OPJ_FLOAT32 tmp = ((OPJ_FLOAT32)(*datap)) * stepsize;
memcpy(datap, &tmp, sizeof(tmp));
datap++;
}
@@ -1787,12 +1777,13 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls)
}
}
} else { /* if (tccp->qmfbid == 0) */
+ const float stepsize = 0.5f * band->stepsize;
OPJ_FLOAT32* OPJ_RESTRICT tiledp = (OPJ_FLOAT32*) &tilec->data[(OPJ_SIZE_T)y *
tile_w + (OPJ_SIZE_T)x];
for (j = 0; j < cblk_h; ++j) {
OPJ_FLOAT32* OPJ_RESTRICT tiledp2 = tiledp;
for (i = 0; i < cblk_w; ++i) {
- OPJ_FLOAT32 tmp = (OPJ_FLOAT32) * datap * band->stepsize;
+ OPJ_FLOAT32 tmp = (OPJ_FLOAT32) * datap * stepsize;
*tiledp2 = tmp;
datap++;
tiledp2++;
@@ -2114,124 +2105,232 @@ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1,
}
+typedef struct {
+ OPJ_UINT32 compno;
+ OPJ_UINT32 resno;
+ opj_tcd_cblk_enc_t* cblk;
+ opj_tcd_tile_t *tile;
+ opj_tcd_band_t* band;
+ opj_tcd_tilecomp_t* tilec;
+ opj_tccp_t* tccp;
+ const OPJ_FLOAT64 * mct_norms;
+ OPJ_UINT32 mct_numcomps;
+ volatile OPJ_BOOL* pret;
+ opj_mutex_t* mutex;
+} opj_t1_cblk_encode_processing_job_t;
+
+/** Procedure to deal with a asynchronous code-block encoding job.
+ *
+ * @param user_data Pointer to a opj_t1_cblk_encode_processing_job_t* structure
+ * @param tls TLS handle.
+ */
+static void opj_t1_clbl_encode_processor(void* user_data, opj_tls_t* tls)
+{
+ opj_t1_cblk_encode_processing_job_t* job =
+ (opj_t1_cblk_encode_processing_job_t*)user_data;
+ opj_tcd_cblk_enc_t* cblk = job->cblk;
+ const opj_tcd_band_t* band = job->band;
+ const opj_tcd_tilecomp_t* tilec = job->tilec;
+ const opj_tccp_t* tccp = job->tccp;
+ const OPJ_UINT32 resno = job->resno;
+ opj_t1_t* t1;
+ const OPJ_UINT32 tile_w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
+
+ OPJ_INT32* OPJ_RESTRICT tiledp;
+ OPJ_UINT32 cblk_w;
+ OPJ_UINT32 cblk_h;
+ OPJ_UINT32 i, j;
+
+ OPJ_INT32 x = cblk->x0 - band->x0;
+ OPJ_INT32 y = cblk->y0 - band->y0;
+
+ if (!*(job->pret)) {
+ opj_free(job);
+ return;
+ }
+
+ t1 = (opj_t1_t*) opj_tls_get(tls, OPJ_TLS_KEY_T1);
+ if (t1 == NULL) {
+ t1 = opj_t1_create(OPJ_TRUE); /* OPJ_TRUE == T1 for encoding */
+ opj_tls_set(tls, OPJ_TLS_KEY_T1, t1, opj_t1_destroy_wrapper);
+ }
+
+ if (band->bandno & 1) {
+ opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
+ x += pres->x1 - pres->x0;
+ }
+ if (band->bandno & 2) {
+ opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
+ y += pres->y1 - pres->y0;
+ }
+
+ if (!opj_t1_allocate_buffers(
+ t1,
+ (OPJ_UINT32)(cblk->x1 - cblk->x0),
+ (OPJ_UINT32)(cblk->y1 - cblk->y0))) {
+ *(job->pret) = OPJ_FALSE;
+ opj_free(job);
+ return;
+ }
+
+ cblk_w = t1->w;
+ cblk_h = t1->h;
+
+ tiledp = &tilec->data[(OPJ_SIZE_T)y * tile_w + (OPJ_SIZE_T)x];
+
+ if (tccp->qmfbid == 1) {
+ /* Do multiplication on unsigned type, even if the
+ * underlying type is signed, to avoid potential
+ * int overflow on large value (the output will be
+ * incorrect in such situation, but whatever...)
+ * This assumes complement-to-2 signed integer
+ * representation
+ * Fixes https://github.com/uclouvain/openjpeg/issues/1053
+ */
+ OPJ_UINT32* OPJ_RESTRICT tiledp_u = (OPJ_UINT32*) tiledp;
+ OPJ_UINT32* OPJ_RESTRICT t1data = (OPJ_UINT32*) t1->data;
+ /* Change from "natural" order to "zigzag" order of T1 passes */
+ for (j = 0; j < (cblk_h & ~3U); j += 4) {
+ for (i = 0; i < cblk_w; ++i) {
+ t1data[0] = tiledp_u[(j + 0) * tile_w + i] << T1_NMSEDEC_FRACBITS;
+ t1data[1] = tiledp_u[(j + 1) * tile_w + i] << T1_NMSEDEC_FRACBITS;
+ t1data[2] = tiledp_u[(j + 2) * tile_w + i] << T1_NMSEDEC_FRACBITS;
+ t1data[3] = tiledp_u[(j + 3) * tile_w + i] << T1_NMSEDEC_FRACBITS;
+ t1data += 4;
+ }
+ }
+ if (j < cblk_h) {
+ for (i = 0; i < cblk_w; ++i) {
+ OPJ_UINT32 k;
+ for (k = j; k < cblk_h; k++) {
+ t1data[0] = tiledp_u[k * tile_w + i] << T1_NMSEDEC_FRACBITS;
+ t1data ++;
+ }
+ }
+ }
+ } else { /* if (tccp->qmfbid == 0) */
+ OPJ_FLOAT32* OPJ_RESTRICT tiledp_f = (OPJ_FLOAT32*) tiledp;
+ OPJ_INT32* OPJ_RESTRICT t1data = t1->data;
+ /* Change from "natural" order to "zigzag" order of T1 passes */
+ for (j = 0; j < (cblk_h & ~3U); j += 4) {
+ for (i = 0; i < cblk_w; ++i) {
+ t1data[0] = (OPJ_INT32)opj_lrintf((tiledp_f[(j + 0) * tile_w + i] /
+ band->stepsize) * (1 << T1_NMSEDEC_FRACBITS));
+ t1data[1] = (OPJ_INT32)opj_lrintf((tiledp_f[(j + 1) * tile_w + i] /
+ band->stepsize) * (1 << T1_NMSEDEC_FRACBITS));
+ t1data[2] = (OPJ_INT32)opj_lrintf((tiledp_f[(j + 2) * tile_w + i] /
+ band->stepsize) * (1 << T1_NMSEDEC_FRACBITS));
+ t1data[3] = (OPJ_INT32)opj_lrintf((tiledp_f[(j + 3) * tile_w + i] /
+ band->stepsize) * (1 << T1_NMSEDEC_FRACBITS));
+ t1data += 4;
+ }
+ }
+ if (j < cblk_h) {
+ for (i = 0; i < cblk_w; ++i) {
+ OPJ_UINT32 k;
+ for (k = j; k < cblk_h; k++) {
+ t1data[0] = (OPJ_INT32)opj_lrintf((tiledp_f[k * tile_w + i] / band->stepsize)
+ * (1 << T1_NMSEDEC_FRACBITS));
+ t1data ++;
+ }
+ }
+ }
+ }
+ {
+ OPJ_FLOAT64 cumwmsedec =
+ opj_t1_encode_cblk(
+ t1,
+ cblk,
+ band->bandno,
+ job->compno,
+ tilec->numresolutions - 1 - resno,
+ tccp->qmfbid,
+ band->stepsize,
+ tccp->cblksty,
+ job->tile->numcomps,
+ job->mct_norms,
+ job->mct_numcomps);
+ if (job->mutex) {
+ opj_mutex_lock(job->mutex);
+ }
+ job->tile->distotile += cumwmsedec;
+ if (job->mutex) {
+ opj_mutex_unlock(job->mutex);
+ }
+ }
-OPJ_BOOL opj_t1_encode_cblks(opj_t1_t *t1,
+ opj_free(job);
+}
+
+
+OPJ_BOOL opj_t1_encode_cblks(opj_tcd_t* tcd,
opj_tcd_tile_t *tile,
opj_tcp_t *tcp,
const OPJ_FLOAT64 * mct_norms,
OPJ_UINT32 mct_numcomps
)
{
+ volatile OPJ_BOOL ret = OPJ_TRUE;
+ opj_thread_pool_t* tp = tcd->thread_pool;
OPJ_UINT32 compno, resno, bandno, precno, cblkno;
+ opj_mutex_t* mutex = opj_mutex_create();
tile->distotile = 0; /* fixed_quality */
for (compno = 0; compno < tile->numcomps; ++compno) {
opj_tcd_tilecomp_t* tilec = &tile->comps[compno];
opj_tccp_t* tccp = &tcp->tccps[compno];
- OPJ_UINT32 tile_w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
for (resno = 0; resno < tilec->numresolutions; ++resno) {
opj_tcd_resolution_t *res = &tilec->resolutions[resno];
for (bandno = 0; bandno < res->numbands; ++bandno) {
opj_tcd_band_t* OPJ_RESTRICT band = &res->bands[bandno];
- OPJ_INT32 bandconst;
/* Skip empty bands */
if (opj_tcd_is_band_empty(band)) {
continue;
}
-
- bandconst = 8192 * 8192 / ((OPJ_INT32) floor(band->stepsize * 8192));
for (precno = 0; precno < res->pw * res->ph; ++precno) {
opj_tcd_precinct_t *prc = &band->precincts[precno];
for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) {
opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno];
- OPJ_INT32* OPJ_RESTRICT tiledp;
- OPJ_UINT32 cblk_w;
- OPJ_UINT32 cblk_h;
- OPJ_UINT32 i, j, tileLineAdvance;
- OPJ_SIZE_T tileIndex = 0;
-
- OPJ_INT32 x = cblk->x0 - band->x0;
- OPJ_INT32 y = cblk->y0 - band->y0;
- if (band->bandno & 1) {
- opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
- x += pres->x1 - pres->x0;
- }
- if (band->bandno & 2) {
- opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
- y += pres->y1 - pres->y0;
- }
-
- if (!opj_t1_allocate_buffers(
- t1,
- (OPJ_UINT32)(cblk->x1 - cblk->x0),
- (OPJ_UINT32)(cblk->y1 - cblk->y0))) {
- return OPJ_FALSE;
- }
- cblk_w = t1->w;
- cblk_h = t1->h;
- tileLineAdvance = tile_w - cblk_w;
-
- tiledp = &tilec->data[(OPJ_SIZE_T)y * tile_w + (OPJ_SIZE_T)x];
- t1->data = tiledp;
- t1->data_stride = tile_w;
- if (tccp->qmfbid == 1) {
- /* Do multiplication on unsigned type, even if the
- * underlying type is signed, to avoid potential
- * int overflow on large value (the output will be
- * incorrect in such situation, but whatever...)
- * This assumes complement-to-2 signed integer
- * representation
- * Fixes https://github.com/uclouvain/openjpeg/issues/1053
- */
- OPJ_UINT32* OPJ_RESTRICT tiledp_u = (OPJ_UINT32*) tiledp;
- for (j = 0; j < cblk_h; ++j) {
- for (i = 0; i < cblk_w; ++i) {
- tiledp_u[tileIndex] <<= T1_NMSEDEC_FRACBITS;
- tileIndex++;
- }
- tileIndex += tileLineAdvance;
- }
- } else { /* if (tccp->qmfbid == 0) */
- for (j = 0; j < cblk_h; ++j) {
- for (i = 0; i < cblk_w; ++i) {
- OPJ_INT32 tmp = tiledp[tileIndex];
- tiledp[tileIndex] =
- opj_int_fix_mul_t1(
- tmp,
- bandconst);
- tileIndex++;
- }
- tileIndex += tileLineAdvance;
- }
+ opj_t1_cblk_encode_processing_job_t* job =
+ (opj_t1_cblk_encode_processing_job_t*) opj_calloc(1,
+ sizeof(opj_t1_cblk_encode_processing_job_t));
+ if (!job) {
+ ret = OPJ_FALSE;
+ goto end;
}
-
- opj_t1_encode_cblk(
- t1,
- cblk,
- band->bandno,
- compno,
- tilec->numresolutions - 1 - resno,
- tccp->qmfbid,
- band->stepsize,
- tccp->cblksty,
- tile->numcomps,
- tile,
- mct_norms,
- mct_numcomps);
+ job->compno = compno;
+ job->tile = tile;
+ job->resno = resno;
+ job->cblk = cblk;
+ job->band = band;
+ job->tilec = tilec;
+ job->tccp = tccp;
+ job->mct_norms = mct_norms;
+ job->mct_numcomps = mct_numcomps;
+ job->pret = &ret;
+ job->mutex = mutex;
+ opj_thread_pool_submit_job(tp, opj_t1_clbl_encode_processor, job);
} /* cblkno */
} /* precno */
} /* bandno */
} /* resno */
} /* compno */
- return OPJ_TRUE;
+
+end:
+ opj_thread_pool_wait_completion(tcd->thread_pool, 0);
+ if (mutex) {
+ opj_mutex_destroy(mutex);
+ }
+
+ return ret;
}
/* Returns whether the pass (bpno, passtype) is terminated */
@@ -2266,18 +2365,17 @@ static int opj_t1_enc_is_term_pass(opj_tcd_cblk_enc_t* cblk,
/** mod fixed_quality */
-static void opj_t1_encode_cblk(opj_t1_t *t1,
- opj_tcd_cblk_enc_t* cblk,
- OPJ_UINT32 orient,
- OPJ_UINT32 compno,
- OPJ_UINT32 level,
- OPJ_UINT32 qmfbid,
- OPJ_FLOAT64 stepsize,
- OPJ_UINT32 cblksty,
- OPJ_UINT32 numcomps,
- opj_tcd_tile_t * tile,
- const OPJ_FLOAT64 * mct_norms,
- OPJ_UINT32 mct_numcomps)
+static OPJ_FLOAT64 opj_t1_encode_cblk(opj_t1_t *t1,
+ opj_tcd_cblk_enc_t* cblk,
+ OPJ_UINT32 orient,
+ OPJ_UINT32 compno,
+ OPJ_UINT32 level,
+ OPJ_UINT32 qmfbid,
+ OPJ_FLOAT64 stepsize,
+ OPJ_UINT32 cblksty,
+ OPJ_UINT32 numcomps,
+ const OPJ_FLOAT64 * mct_norms,
+ OPJ_UINT32 mct_numcomps)
{
OPJ_FLOAT64 cumwmsedec = 0.0;
@@ -2291,6 +2389,7 @@ static void opj_t1_encode_cblk(opj_t1_t *t1,
OPJ_UINT32 i, j;
OPJ_BYTE type = T1_TYPE_MQ;
OPJ_FLOAT64 tempwmsedec;
+ OPJ_INT32* datap;
#ifdef EXTRA_DEBUG
printf("encode_cblk(x=%d,y=%d,x1=%d,y1=%d,orient=%d,compno=%d,level=%d\n",
@@ -2300,10 +2399,19 @@ static void opj_t1_encode_cblk(opj_t1_t *t1,
mqc->lut_ctxno_zc_orient = lut_ctxno_zc + (orient << 9);
max = 0;
- for (i = 0; i < t1->w; ++i) {
- for (j = 0; j < t1->h; ++j) {
- OPJ_INT32 tmp = abs(t1->data[i + j * t1->data_stride]);
- max = opj_int_max(max, tmp);
+ datap = t1->data;
+ for (j = 0; j < t1->h; ++j) {
+ const OPJ_UINT32 w = t1->w;
+ for (i = 0; i < w; ++i, ++datap) {
+ OPJ_INT32 tmp = *datap;
+ if (tmp < 0) {
+ OPJ_UINT32 tmp_unsigned;
+ max = opj_int_max(max, -tmp);
+ tmp_unsigned = opj_to_smr(tmp);
+ memcpy(datap, &tmp_unsigned, sizeof(OPJ_INT32));
+ } else {
+ max = opj_int_max(max, tmp);
+ }
}
}
@@ -2311,7 +2419,7 @@ static void opj_t1_encode_cblk(opj_t1_t *t1,
T1_NMSEDEC_FRACBITS) : 0;
if (cblk->numbps == 0) {
cblk->totalpasses = 0;
- return;
+ return cumwmsedec;
}
bpno = (OPJ_INT32)(cblk->numbps - 1);
@@ -2357,7 +2465,6 @@ static void opj_t1_encode_cblk(opj_t1_t *t1,
tempwmsedec = opj_t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid,
stepsize, numcomps, mct_norms, mct_numcomps) ;
cumwmsedec += tempwmsedec;
- tile->distotile += tempwmsedec;
pass->distortiondec = cumwmsedec;
if (opj_t1_enc_is_term_pass(cblk, cblksty, bpno, passtype)) {
@@ -2439,4 +2546,6 @@ static void opj_t1_encode_cblk(opj_t1_t *t1,
}
}
#endif
+
+ return cumwmsedec;
}
diff --git a/src/lib/openjp2/t1.h b/src/lib/openjp2/t1.h
index 171dfb0a..81ad0d00 100644
--- a/src/lib/openjp2/t1.h
+++ b/src/lib/openjp2/t1.h
@@ -198,7 +198,6 @@ typedef struct opj_t1 {
OPJ_UINT32 h;
OPJ_UINT32 datasize;
OPJ_UINT32 flagssize;
- OPJ_UINT32 data_stride;
OPJ_BOOL encoder;
/* Thre 3 variables below are only used by the decoder */
@@ -216,13 +215,13 @@ typedef struct opj_t1 {
/**
Encode the code-blocks of a tile
-@param t1 T1 handle
+@param tcd TCD handle
@param tile The tile to encode
@param tcp Tile coding parameters
@param mct_norms FIXME DOC
@param mct_numcomps Number of components used for MCT
*/
-OPJ_BOOL opj_t1_encode_cblks(opj_t1_t *t1,
+OPJ_BOOL opj_t1_encode_cblks(opj_tcd_t* tcd,
opj_tcd_tile_t *tile,
opj_tcp_t *tcp,
const OPJ_FLOAT64 * mct_norms,
diff --git a/src/lib/openjp2/tcd.c b/src/lib/openjp2/tcd.c
index 3a1c3026..810f83ec 100644
--- a/src/lib/openjp2/tcd.c
+++ b/src/lib/openjp2/tcd.c
@@ -112,7 +112,7 @@ void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img)
* Initializes tile coding/decoding
*/
static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
- OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block,
+ OPJ_BOOL isEncoder, OPJ_SIZE_T sizeof_block,
opj_event_mgr_t* manager);
/**
@@ -721,10 +721,9 @@ OPJ_BOOL opj_alloc_tile_component_data(opj_tcd_tilecomp_t *l_tilec)
/* ----------------------------------------------------------------------- */
static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
- OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block,
+ OPJ_BOOL isEncoder, OPJ_SIZE_T sizeof_block,
opj_event_mgr_t* manager)
{
- OPJ_UINT32(*l_gain_ptr)(OPJ_UINT32) = 00;
OPJ_UINT32 compno, resno, bandno, precno, cblkno;
opj_tcp_t * l_tcp = 00;
opj_cp_t * l_cp = 00;
@@ -740,7 +739,6 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
OPJ_UINT32 p, q;
OPJ_UINT32 l_level_no;
OPJ_UINT32 l_pdx, l_pdy;
- OPJ_UINT32 l_gain;
OPJ_INT32 l_x0b, l_y0b;
OPJ_UINT32 l_tx0, l_ty0;
/* extent of precincts , top left, bottom right**/
@@ -879,11 +877,6 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
l_level_no = l_tilec->numresolutions;
l_res = l_tilec->resolutions;
l_step_size = l_tccp->stepsizes;
- if (l_tccp->qmfbid == 0) {
- l_gain_ptr = &opj_dwt_getgain_real;
- } else {
- l_gain_ptr = &opj_dwt_getgain;
- }
/*fprintf(stderr, "\tlevel_no=%d\n",l_level_no);*/
for (resno = 0; resno < l_tilec->numresolutions; ++resno) {
@@ -970,7 +963,6 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
l_band = l_res->bands;
for (bandno = 0; bandno < l_res->numbands; ++bandno, ++l_band, ++l_step_size) {
- OPJ_INT32 numbps;
/*fprintf(stderr, "\t\t\tband_no=%d/%d\n", bandno, l_res->numbands );*/
if (resno == 0) {
@@ -1006,11 +998,24 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
}
}
- /** avoid an if with storing function pointer */
- l_gain = (*l_gain_ptr)(l_band->bandno);
- numbps = (OPJ_INT32)(l_image_comp->prec + l_gain);
- l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0,
- (OPJ_INT32)(numbps - l_step_size->expn)))) * fraction;
+ {
+ /* Table E-1 - Sub-band gains */
+ /* BUG_WEIRD_TWO_INVK (look for this identifier in dwt.c): */
+ /* the test (!isEncoder && l_tccp->qmfbid == 0) is strongly */
+ /* linked to the use of two_invK instead of invK */
+ const OPJ_INT32 log2_gain = (!isEncoder &&
+ l_tccp->qmfbid == 0) ? 0 : (l_band->bandno == 0) ? 0 :
+ (l_band->bandno == 3) ? 2 : 1;
+
+ /* Nominal dynamic range. Equation E-4 */
+ const OPJ_INT32 Rb = (OPJ_INT32)l_image_comp->prec + log2_gain;
+
+ /* Delta_b value of Equation E-3 in "E.1 Inverse quantization
+ * procedure" of the standard */
+ l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0,
+ (OPJ_INT32)(Rb - l_step_size->expn))));
+ }
+
/* Mb value of Equation E-2 in "E.1 Inverse quantization
* procedure" of the standard */
l_band->numbps = l_step_size->expn + (OPJ_INT32)l_tccp->numgbits -
@@ -1193,14 +1198,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
OPJ_BOOL opj_tcd_init_encode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
opj_event_mgr_t* p_manager)
{
- return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_TRUE, 1.0F,
+ return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_TRUE,
sizeof(opj_tcd_cblk_enc_t), p_manager);
}
OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
opj_event_mgr_t* p_manager)
{
- return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_FALSE, 0.5F,
+ return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_FALSE,
sizeof(opj_tcd_cblk_dec_t), p_manager);
}
@@ -2411,7 +2416,8 @@ static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd)
}
} else {
for (i = 0; i < l_nb_elem; ++i) {
- *l_current_ptr = (*l_current_ptr - l_tccp->m_dc_level_shift) * (1 << 11);
+ *((OPJ_FLOAT32 *) l_current_ptr) = (OPJ_FLOAT32)(*l_current_ptr -
+ l_tccp->m_dc_level_shift);
++l_current_ptr;
}
}
@@ -2469,8 +2475,11 @@ static OPJ_BOOL opj_tcd_mct_encode(opj_tcd_t *p_tcd)
opj_free(l_data);
} else if (l_tcp->tccps->qmfbid == 0) {
- opj_mct_encode_real(l_tile->comps[0].data, l_tile->comps[1].data,
- l_tile->comps[2].data, samples);
+ opj_mct_encode_real(
+ (OPJ_FLOAT32*)l_tile->comps[0].data,
+ (OPJ_FLOAT32*)l_tile->comps[1].data,
+ (OPJ_FLOAT32*)l_tile->comps[2].data,
+ samples);
} else {
opj_mct_encode(l_tile->comps[0].data, l_tile->comps[1].data,
l_tile->comps[2].data, samples);
@@ -2488,11 +2497,11 @@ static OPJ_BOOL opj_tcd_dwt_encode(opj_tcd_t *p_tcd)
for (compno = 0; compno < l_tile->numcomps; ++compno) {
if (l_tccp->qmfbid == 1) {
- if (! opj_dwt_encode(l_tile_comp)) {
+ if (! opj_dwt_encode(p_tcd, l_tile_comp)) {
return OPJ_FALSE;
}
} else if (l_tccp->qmfbid == 0) {
- if (! opj_dwt_encode_real(l_tile_comp)) {
+ if (! opj_dwt_encode_real(p_tcd, l_tile_comp)) {
return OPJ_FALSE;
}
}
@@ -2506,16 +2515,10 @@ static OPJ_BOOL opj_tcd_dwt_encode(opj_tcd_t *p_tcd)
static OPJ_BOOL opj_tcd_t1_encode(opj_tcd_t *p_tcd)
{
- opj_t1_t * l_t1;
const OPJ_FLOAT64 * l_mct_norms;
OPJ_UINT32 l_mct_numcomps = 0U;
opj_tcp_t * l_tcp = p_tcd->tcp;
- l_t1 = opj_t1_create(OPJ_TRUE);
- if (l_t1 == 00) {
- return OPJ_FALSE;
- }
-
if (l_tcp->mct == 1) {
l_mct_numcomps = 3U;
/* irreversible encoding */
@@ -2529,13 +2532,9 @@ static OPJ_BOOL opj_tcd_t1_encode(opj_tcd_t *p_tcd)
l_mct_norms = (const OPJ_FLOAT64 *)(l_tcp->mct_norms);
}
- if (! opj_t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles, l_tcp, l_mct_norms,
- l_mct_numcomps)) {
- opj_t1_destroy(l_t1);
- return OPJ_FALSE;
- }
-
- opj_t1_destroy(l_t1);
+ return opj_t1_encode_cblks(p_tcd,
+ p_tcd->tcd_image->tiles, l_tcp, l_mct_norms,
+ l_mct_numcomps);
return OPJ_TRUE;
}