Compare commits

..

55 Commits

Author SHA1 Message Date
Antonin Descampe
7113c4e3bb Update THANKS.md 2016-10-03 23:47:10 +02:00
Antonin Descampe
b8197de716 Update CHANGELOG.md 2016-10-03 23:45:44 +02:00
Antonin Descampe
b079198838 fix abi-check and limit upload to website for master 2016-09-29 22:06:23 +02:00
Antonin Descampe
110d31891b fix abi-check 2016-09-29 21:44:38 +02:00
Antonin Descampe
cc0c71c30b fix abi-check 2016-09-29 20:23:01 +02:00
Antonin Descampe
5695ac15ff Update abi-check scripts for v2.1.2 2016-09-28 20:59:10 +02:00
Antonin Descampe
df5e8628f2 Update NEWS.md for v2.1.2 2016-09-28 20:58:55 +02:00
Antonin Descampe
b0c0f0ff04 Update Changelog for v2.1.2 2016-09-28 20:58:34 +02:00
Antonin Descampe
9afc1699f0 Update version number for future release 2.2.0 2016-09-28 18:55:02 +02:00
Mathieu Malaterre
34dae137a9 OPENJPEG_NAMESPACE is configurable by user 2016-09-26 12:01:31 +02:00
Mathieu Malaterre
4d5c5e7c48 Remove typos from comments and man pages 2016-09-26 11:26:55 +02:00
Matthieu Darbois
fac916f72a Fix PNM file reading (#847)
Malformed PNM file could cause a crash in opj_compress.
Checks were added to prevent this.

Fixes #843
Updates #440
2016-09-22 00:30:34 +02:00
Stefan Weil
8715ce2749 Fix some issues reported by Coverity Scan (#846)
* test_tile_decoder: Fix potential buffer overflow (coverity)

CID 1190155 (#1 of 1): Unbounded source buffer (STRING_SIZE)

Using a pointer instead of buffer of fixed size avoids the limit
for the length of the input file name.

Signed-off-by: Stefan Weil <sw@weilnetz.de>

* test_tile_encoder: Fix potential buffer overflow (coverity)

CID 1190154 (#1 of 1): Unbounded source buffer (STRING_SIZE)

Using a pointer instead of buffer of fixed size avoids the limit
for the length of the output file name. This implies that the length
can exceed 255, so the data type for variable len had to be fixed, too.

Signed-off-by: Stefan Weil <sw@weilnetz.de>

* openjpip: Initialize data before returning it

This fixes an error reported by Coverity:

CID 1190143 (#1 of 1): Uninitialized scalar variable (UNINIT)

Signed-off-by: Stefan Weil <sw@weilnetz.de>
2016-09-21 21:15:25 +02:00
Stefan Weil
045aa4d9f2 Fix potential out-of-bounds read (coverity) (#844)
* query_parser: Fix potential out-of-bounds read (coverity)

CID 1190207 (#1 of 1): Out-of-bounds read (OVERRUN)

Variable i must be checked before testing query_param.box_type.

Signed-off-by: Stefan Weil <sw@weilnetz.de>

* jpip_parser: Fix potential out-of-bounds read (coverity)

CID 1190206 (#1 of 1): Out-of-bounds read (OVERRUN)

Variable i must be checked before testing query_param.box_type.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
2016-09-21 13:17:09 +02:00
Antonin Descampe
da94042481 Merge pull request #834 from trylab/issue833
Fix issue 833.
2016-09-20 18:59:30 +02:00
Antonin Descampe
31d44f0280 Disable automatic compilation of t1_generate_luts
Fix #831
2016-09-20 18:48:06 +02:00
Antonin Descampe
3aaeea7ce8 renamed USE_THREAD to OPJ_USE_THREAD
renaming to be consistent with previous OPJ CMake options
2016-09-16 17:54:12 +02:00
Matthieu Darbois
6e7616c83c Remove TODO for overflow check (#842)
The check was already done. It’s been simplified.
Reformat to get consistent style throughout the functions.
2016-09-15 23:51:34 +02:00
Matthieu Darbois
9a07ccb3d0 Add overflow checks for opj_aligned_malloc (#841)
See
https://pdfium.googlesource.com/pdfium/+/b20ab6c7acb3be1393461eb650ca8fa4660c937e/third_party/libopenjpeg20/0020-opj_aligned_malloc.patch
2016-09-15 01:57:53 +02:00
Matthieu Darbois
f88c9974e2 Flags in T1 shall be unsigned (#840)
This will remove some conversion warnings
2016-09-14 23:46:46 +02:00
Matthieu Darbois
0954bc11e3 Fix some warnings (#838)
Fix warnings introduced by uclouvain/openjpeg#786
2016-09-14 00:12:43 +02:00
Antonin Descampe
1e69940955 Merge branch 'smuehlst-bit-fields-type' 2016-09-13 21:21:56 +02:00
Antonin Descampe
f66e120452 Merge branch 'bit-fields-type' of https://github.com/smuehlst/openjpeg into smuehlst-bit-fields-type 2016-09-13 21:21:11 +02:00
Antonin Descampe
d6d0f070e1 Merge pull request #786 from rouault/tier1_optimizations_multithreading
T1 & DWT multithreading decoding optimizations
2016-09-13 16:39:26 +02:00
Antonin Descampe
f1f7c53308 remove ops 1.4 and 1.2 from abi-check to avoid symlinks in gh-pages 2016-09-13 16:21:38 +02:00
trylab
893143c8e1 Fix issue 833.
Add some overflow check operations.
2016-09-13 17:43:30 +08:00
Matthieu Darbois
805972f4c8 Add test for issue 820 (#829)
Update uclouvain/openjpeg#820
2016-09-11 19:47:32 +02:00
Matthieu Darbois
45ed017b1b Add test for issue 826 (#827)
Update uclouvain/openjpeg#826

Also correct names for data of issue uclouvain/openjpeg#823
2016-09-08 23:56:06 +02:00
Even Rouault
48c16b2c19 Merge branch 'master' of https://github.com/uclouvain/openjpeg into tier1_optimizations_multithreading_2
Conflicts:
	src/lib/openjp2/t1.c
2016-09-08 10:30:09 +02:00
Even Rouault
ab22c5bad5 opj_thread_pool: fix potential deadlock at thread pool destruction 2016-09-08 09:43:36 +02:00
Stephan Mühlstrasser
8750e183c6 Moved type OPJ_BITFIELD from openjpeg.h to opj_includes.h
OPJ_BITFIELD is used only in internal headers and must not
appear in the public openjpeg.h header.
2016-09-07 08:41:01 +02:00
Stephan Mühlstrasser
6c83f1468c Merge branch 'master' into bit-fields-type 2016-09-07 08:35:19 +02:00
Even Rouault
4f9abb9a45 [Win32] Use _beginthreadex instead of CreateThread() 2016-08-11 21:59:28 +02:00
Stephan Mühlstrasser
54874194a8 Unified bit-field declaration, removed tabs. 2016-07-27 10:09:54 +02:00
Stephan Mühlstrasser
d2d35bf6c2 Create separate type for bit-fields.
The definition of bit-fields with type OPJ_UINT32 caused complilation errors
on IBM iSeries, because OPJ_UINT32 is defined as uint32_t, and
uint32_t is defined as unsigned long in <stdint.h>. The definition of
bit-fields with an integer type of  a specific size doesn't make sense
anyway.
2016-07-25 20:46:11 +02:00
Even Rouault
7d3c7a345f Be robust to failed allocations of job structures 2016-05-26 23:51:32 +02:00
Even Rouault
69497d35c0 opj_decompress: use clock_gettime() instead of getrusage() so as to get the time spent, and not to the total CPU time 2016-05-25 21:59:43 +02:00
Even Rouault
d67cd2220a opj_decompress: add a -threads <num_threads> option 2016-05-25 21:02:07 +02:00
Even Rouault
e3eb0a206d .travis.yml: add a conf with OPJ_NUM_THREADS=2 2016-05-25 21:02:07 +02:00
Even Rouault
57b216bb58 Use thread pool for DWT decoding 2016-05-25 21:02:07 +02:00
Even Rouault
5fbb8b2645 Use thread-pool for T1 decoding 2016-05-25 21:02:07 +02:00
Even Rouault
d4b7f03cfa Add opj_codec_set_threads() in public API and propagate resulting thread pool to tcd level
By default, only the main thread is used. If opj_codec_set_threads() is not used,
but the OPJ_NUM_THREADS environment variable is set, its value will be
used to initialize the number of threads. The value can be either an integer
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.
2016-05-25 21:02:07 +02:00
Even Rouault
54179fe1d5 Add threading and thread pool API 2016-05-25 21:02:07 +02:00
Even Rouault
7092f7ea11 Fix MSVC210 build issue (use of C99 declaration after statement) introduced in ba1edf6cd41415594729bc90ad3b0008af48251e 2016-05-23 16:00:28 +02:00
Even Rouault
107eb31531 Improve perf of opj_t1_dec_sigpass_mqc_vsc() and opj_t1_dec_refpass_mqc_vsc() with loop unrolling 2016-05-23 13:45:15 +02:00
Even Rouault
8371491a99 Better inlining of opj_t1_updateflagscolflags() w.r.t. flags_stride 2016-05-23 11:53:54 +02:00
Even Rouault
956c31d5a6 opj_t1_dec_clnpass(): remove useless test in the runlen decoding path (of the non VSC case) 2016-05-23 11:53:54 +02:00
Even Rouault
93f7f90711 opj_t1_decode_cblks(): tiny perf increase when loop unrolling 2016-05-23 11:53:53 +02:00
Even Rouault
1da397e94a Tier 1 decoding: add a colflags array
Addition flag array such that colflags[1+0] is for state of col=0,row=0..3,
colflags[1+1] for col=1, row=0..3, colflags[1+flags_stride] for col=0,row=4..7, ...
This array avoids too much cache trashing when processing by 4 vertical samples
as done in the various decoding steps.
2016-05-23 11:53:53 +02:00
Even Rouault
31882ad7f4 Const'ify lut arrays so they are in the read-only data section 2016-05-22 00:54:06 +02:00
Even Rouault
ba1edf6cd4 Reduce number of occurrences of orient function argument
This is essentially used to shift inside the lut_ctxno_zc, which we
can precompute at the beginning of opj_t1_decode_cblk() /
opj_t1_encode_cblk()
2016-05-22 00:50:34 +02:00
Even Rouault
23a01dfdef Specialize decoding passes for 64x64 code blocks 2016-05-21 16:27:35 +02:00
Even Rouault
d8fef96f23 Improve code generation in opj_t1_dec_clnpass()
Add a opj_t1_dec_clnpass_step_only_if_flag_not_sig_visit() method that
does the job of opj_t1_dec_clnpass_step_only() assuming the conditions
are met. And use it in opj_t1_dec_clnpass(). The compiler generates
more efficient code.
2016-05-21 15:52:02 +02:00
Even Rouault
c539808d09 opj_t1_updateflags(): tiny optimization
We can avoid using a loop-up table with some shift arithmetics.
2016-05-21 15:46:56 +02:00
Kal Conley
426bf8d337 Move some MQC functions into a header for speed
Allow these hot functions to be inlined. This boosts decode performance by ~10%.
2016-05-21 15:18:07 +02:00
46 changed files with 3223 additions and 869 deletions

View File

@ -1,21 +1,93 @@
language: c
env:
global:
- secure: "Tx8C7AkTwGDiPEzEaS6t3emevQMYzlcDGilbGWXT7vnSKbftH6lr/9djoKhD2Y2xA62XEfHr9fho9FzUGYuuTADz05qYIdc5m1lILRWok8SFwDt27DS0CpaSpvDYzzCPe70zBdEq1VZ05U+kXA2a4bS+R0xDA8q8vRx4jOl9LjpHvt8R2K7qHkx9LH5YmBz42PjbXdmxJPdFTY8SgWUy7dOMsnPMq0UzTLS54DMlOxSRaCrVw6qv15uIBrgTQiy+XtNft2qe5J+61w6WEhaWhbofuaxuc86jiryA8XUv04WuafoYxaErgf5+nw2/CfMAP2k5TFsNDN/F07xlCj/0aL/kVJGmVsKHUlDBbzEDhkQjw8C6hANOfagBSfRgWvko0E5o0bo0sRrIsbg1feVby7zkfX2a73fTDNC30Z3SSkzTWz37VNJLUMF14LmRDaq4/0DtIAjJDy4qaUwh4RCLcCPlbAf9nmBZn8asIFswPLd4gnktk9n42AyPHNDLExKCwe3+LsVO8ruAlejlnZyEU91vpVMF14j6WeQm2mnYb9CBdOVsBmrskyuTZ4oENDAx14CoxgL6lvxhf+gnZMhvIft1ybM+wQTdfBIl6cqlOMmU9uC8IecQx1Rz/ek17cR3PQXOWQu/jNiU2nJt1WGpBfzYSBjg/e1cVzRvIi+eI5k="
addons:
coverity_scan:
project:
name: "uclouvain/openjpeg"
description: "Build submitted via Travis CI"
notification_email: info@openjpeg.org
build_command_prepend: "mkdir build && cd build && cmake -G 'Unix Makefiles' -DBUILD_CODEC=ON -DBUILD_THIRDPARTY=ON .."
build_command: "make -j 4"
branch_pattern: coverity_scan
matrix:
include:
- os: osx
compiler: clang
env: OPJ_CI_ARCH=x86_64 OPJ_CI_BUILD_CONFIGURATION=Release OPJ_CI_INCLUDE_IF_DEPLOY=1
- os: linux
compiler: gcc
env: OPJ_CI_ARCH=x86_64 OPJ_CI_BUILD_CONFIGURATION=Release OPJ_CI_INCLUDE_IF_DEPLOY=1
- os: linux
compiler: gcc
env: OPJ_CI_ARCH=x86_64 OPJ_CI_BUILD_CONFIGURATION=Release OPJ_NUM_THREADS=2
- os: linux
compiler: gcc
env: OPJ_CI_ARCH=i386 OPJ_CI_BUILD_CONFIGURATION=Release
addons:
apt:
packages:
- gcc-multilib
- os: linux
compiler: gcc
env: OPJ_CI_ARCH=x86_64 OPJ_CI_BUILD_CONFIGURATION=Debug
- os: linux
compiler: clang
env: OPJ_CI_ARCH=x86_64 OPJ_CI_BUILD_CONFIGURATION=Debug OPJ_CI_ASAN=1
- os: linux
compiler: clang-3.8
env: OPJ_CI_ARCH=x86_64 OPJ_CI_BUILD_CONFIGURATION=Release
addons:
apt:
sources:
- llvm-toolchain-precise-3.8
- ubuntu-toolchain-r-test
packages:
- clang-3.8
- os: linux
compiler: x86_64-w64-mingw32-gcc
env: OPJ_CI_ARCH=x86_64 OPJ_CI_BUILD_CONFIGURATION=Release
addons:
apt:
packages:
- gcc-mingw-w64-base
- binutils-mingw-w64-x86-64
- gcc-mingw-w64-x86-64
- gcc-mingw-w64
- os: linux
compiler: x86_64-w64-mingw32-gcc
env: OPJ_CI_ARCH=i386 OPJ_CI_BUILD_CONFIGURATION=Release
addons:
apt:
packages:
- gcc-mingw-w64-base
- binutils-mingw-w64-i686
- gcc-mingw-w64-i686
- gcc-mingw-w64
- os: linux
compiler: gcc-4.8
env: OPJ_CI_ABI_CHECK=1
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.8
- libelf-dev
- elfutils
- texinfo
- exuberant-ctags
install:
- echo "Coverity scan build"
- ./tools/travis-ci/install.sh
script:
- echo "Coverity scan build"
- ./tools/travis-ci/run.sh
- ./tools/travis-ci/abi-check.sh
before_deploy:
- export OPJ_RELEASE_PKG_FILE=$(ls build/openjpeg-${TRAVIS_TAG}*)
- echo "deploying $OPJ_RELEASE_PKG_FILE to GitHub releases"
deploy:
provider: releases
api_key:
secure: Npi13uOffALCVNwea4p4q8v85Lo/WsRqaeZQcWrAkt8MxRnfvWQtmnuwmHnVB6Cig+T1lVUHrklOaJIApIb6nkGq3CS/9bD8+SCS2NEdAAP/QYWnBi0ubWXVMRyDLypmwRpzLNSZ0xLYGFUl2PjieZYKRcz1dd/J7S+FnXhPtdjXweq0FS63zTcMe7ggjfmzSOWUCEFmMjZPaM0Be+3PweieCO1dxlHuy7ugCkx2S7d+5hNsicIhQmTADjqtJAkHoMhYqu6/yLFxhjO/+f938PATFULdODTvjCsUwdN/ySWi1Oj4uPAntfytZP7H6YrzLh8dS73QCsdkhhDJIgJskHIBSbRyyEVUnOvQgD9VaBVGHtc1KtZQTwc41OUO3BGPHl97s3oX6bqWqo/L53dB3TPHGx+1+2HL/F0zaDZuHhAKMkPwe8LFPMPB/ur65zXMHjnWb2ZTVVdoIvkbQ7nu8ApI60ejxocYBsEyAuC2CPXU2ki4jdEhm0E1hIziWNE9/LTuM17ziQuJ6WpXOSMrfP4o5aVDmLp5ZGBSocrspOksgyI9XogHaO/r+Y6N3exy+giObFfMHkZVUpsKrKmtOJ7TC1Vg5HsYGlWW8RN8dkJV47bUXm9K4sMos9eYMUt/czykPAs+132cogpII3QxXpFZQqZg6SEPVfOiyqQzTUI=
file_glob: true
file: "${OPJ_RELEASE_PKG_FILE}"
skip_cleanup: true
on:
repo: uclouvain/openjpeg
tags: true
condition: "$OPJ_CI_INCLUDE_IF_DEPLOY = 1"

View File

@ -1,5 +1,60 @@
# Changelog
## [v2.1.2](https://github.com/uclouvain/openjpeg/releases/v2.1.2) (2016-09-28)
[Full Changelog](https://github.com/uclouvain/openjpeg/compare/v2.1.1...v2.1.2)
**Closed issues:**
- null ptr dereference in convert.c:1331 [\#843](https://github.com/uclouvain/openjpeg/issues/843)
- Out-of-Bounds Read in function bmp24toimage of convertbmp.c [\#833](https://github.com/uclouvain/openjpeg/issues/833)
- Disable automatic compilation of t1\_generate\_luts in CMakeLists.txt [\#831](https://github.com/uclouvain/openjpeg/issues/831)
- CVE-2016-7163 Integer overflow in opj\_pi\_create\_decode [\#826](https://github.com/uclouvain/openjpeg/issues/826)
- Security Advisory for OpenJPEG [\#810](https://github.com/uclouvain/openjpeg/issues/810)
- Add dashboard with static lib [\#804](https://github.com/uclouvain/openjpeg/issues/804)
- hidden visibility for the static library / building with -DOPJ\_STATIC against shared lib [\#802](https://github.com/uclouvain/openjpeg/issues/802)
- Optimization when building library from source [\#799](https://github.com/uclouvain/openjpeg/issues/799)
- unsigned int16 on Solaris 11.2/sparc [\#796](https://github.com/uclouvain/openjpeg/issues/796)
- appveyor [\#793](https://github.com/uclouvain/openjpeg/issues/793)
- Please make a new release [\#782](https://github.com/uclouvain/openjpeg/issues/782)
- FFMpeg will not link to 2.1.1 release built as shared library [\#766](https://github.com/uclouvain/openjpeg/issues/766)
- API change since v2: opj\_event\_mgr\_t not available [\#754](https://github.com/uclouvain/openjpeg/issues/754)
- openjpeg.h needs dependencies [\#673](https://github.com/uclouvain/openjpeg/issues/673)
- "master" does not build on ubuntu [\#658](https://github.com/uclouvain/openjpeg/issues/658)
- Package 'openjp2', required by 'libopenjpip', not found [\#594](https://github.com/uclouvain/openjpeg/issues/594)
**Merged pull requests:**
- Fix PNM file reading [\#847](https://github.com/uclouvain/openjpeg/pull/847) ([mayeut](https://github.com/mayeut))
- Fix some issues reported by Coverity Scan [\#846](https://github.com/uclouvain/openjpeg/pull/846) ([stweil](https://github.com/stweil))
- Fix potential out-of-bounds read \(coverity\) [\#844](https://github.com/uclouvain/openjpeg/pull/844) ([stweil](https://github.com/stweil))
- Remove TODO for overflow check [\#842](https://github.com/uclouvain/openjpeg/pull/842) ([mayeut](https://github.com/mayeut))
- Add overflow checks for opj\_aligned\_malloc [\#841](https://github.com/uclouvain/openjpeg/pull/841) ([mayeut](https://github.com/mayeut))
- Flags in T1 shall be unsigned [\#840](https://github.com/uclouvain/openjpeg/pull/840) ([mayeut](https://github.com/mayeut))
- Fix some warnings [\#838](https://github.com/uclouvain/openjpeg/pull/838) ([mayeut](https://github.com/mayeut))
- Fix issue 833. [\#834](https://github.com/uclouvain/openjpeg/pull/834) ([trylab](https://github.com/trylab))
- Add overflow checks for opj\_aligned\_malloc [\#832](https://github.com/uclouvain/openjpeg/pull/832) ([mayeut](https://github.com/mayeut))
- Add test for issue 820 [\#829](https://github.com/uclouvain/openjpeg/pull/829) ([mayeut](https://github.com/mayeut))
- Add test for issue 826 [\#827](https://github.com/uclouvain/openjpeg/pull/827) ([mayeut](https://github.com/mayeut))
- Fix coverity 113065 \(CWE-484\) [\#824](https://github.com/uclouvain/openjpeg/pull/824) ([mayeut](https://github.com/mayeut))
- Add sanity check for tile coordinates [\#823](https://github.com/uclouvain/openjpeg/pull/823) ([mayeut](https://github.com/mayeut))
- Add test for PR 818 [\#822](https://github.com/uclouvain/openjpeg/pull/822) ([mayeut](https://github.com/mayeut))
- Update to libpng 1.6.25 [\#821](https://github.com/uclouvain/openjpeg/pull/821) ([mayeut](https://github.com/mayeut))
- CVE-2016-8332: fix incrementing of "l\_tcp-\>m\_nb\_mcc\_records" in opj\_j2k\_read\_mcc [\#820](https://github.com/uclouvain/openjpeg/pull/820) ([mayeut](https://github.com/mayeut))
- Add overflow check in opj\_tcd\_init\_tile [\#819](https://github.com/uclouvain/openjpeg/pull/819) ([mayeut](https://github.com/mayeut))
- Fix leak & invalid behavior of opj\_jp2\_read\_ihdr [\#818](https://github.com/uclouvain/openjpeg/pull/818) ([mayeut](https://github.com/mayeut))
- Add overflow check in opj\_j2k\_update\_image\_data [\#817](https://github.com/uclouvain/openjpeg/pull/817) ([mayeut](https://github.com/mayeut))
- Change 'restrict' define to 'OPJ\_RESTRICT' [\#816](https://github.com/uclouvain/openjpeg/pull/816) ([mayeut](https://github.com/mayeut))
- Switch to clang 3.8 [\#814](https://github.com/uclouvain/openjpeg/pull/814) ([mayeut](https://github.com/mayeut))
- Fix an integer overflow issue [\#809](https://github.com/uclouvain/openjpeg/pull/809) ([trylab](https://github.com/trylab))
- Update to lcms 2.8 [\#808](https://github.com/uclouvain/openjpeg/pull/808) ([mayeut](https://github.com/mayeut))
- Update to libpng 1.6.24 [\#807](https://github.com/uclouvain/openjpeg/pull/807) ([mayeut](https://github.com/mayeut))
- Reenable clang-3.9 build on travis [\#806](https://github.com/uclouvain/openjpeg/pull/806) ([mayeut](https://github.com/mayeut))
- Bit fields type [\#805](https://github.com/uclouvain/openjpeg/pull/805) ([smuehlst](https://github.com/smuehlst))
- Add compilation test for standalone inclusion of openjpeg.h [\#798](https://github.com/uclouvain/openjpeg/pull/798) ([mayeut](https://github.com/mayeut))
- jpwl: Remove non-portable data type u\_int16\_t \(fix issue \#796\) [\#797](https://github.com/uclouvain/openjpeg/pull/797) ([stweil](https://github.com/stweil))
- Fix dependency for pkg-config \(issue \#594\) [\#795](https://github.com/uclouvain/openjpeg/pull/795) ([stweil](https://github.com/stweil))
- Add .gitignore [\#787](https://github.com/uclouvain/openjpeg/pull/787) ([stweil](https://github.com/stweil))
## [v2.1.1](https://github.com/uclouvain/openjpeg/releases/tag/v2.1.1) (2016-07-05)
[Full Changelog](https://github.com/uclouvain/openjpeg/compare/version.2.1...v2.1.1)
@ -388,4 +443,4 @@ List of fixed issues and enhancements unavailable, see [NEWS](https://github.com
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*

View File

@ -32,8 +32,8 @@ include_regular_expression("^.*$")
#-----------------------------------------------------------------------------
# OPENJPEG version number, useful for packaging and doxygen doc:
set(OPENJPEG_VERSION_MAJOR 2)
set(OPENJPEG_VERSION_MINOR 1)
set(OPENJPEG_VERSION_BUILD 1)
set(OPENJPEG_VERSION_MINOR 2)
set(OPENJPEG_VERSION_BUILD 0)
set(OPENJPEG_VERSION
"${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}")
set(PACKAGE_VERSION
@ -53,6 +53,8 @@ set(PACKAGE_VERSION
# 2.0.1 | 6
# 2.1 | 7
# 2.1.1 | 7
# 2.1.2 | 7
# 2.2.0 | 8
# above is the recommendation by the OPJ team. If you really need to override this default,
# you can specify your own OPENJPEG_SOVERSION at cmake configuration time:
# cmake -DOPENJPEG_SOVERSION:STRING=42 /path/to/openjpeg
@ -67,7 +69,7 @@ set(OPENJPEG_LIBRARY_PROPERTIES
# --------------------------------------------------------------------------
# Path to additional CMake modules
set(CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake
${${OPENJPEG_NAMESPACE}_SOURCE_DIR}/cmake
${CMAKE_MODULE_PATH})
# --------------------------------------------------------------------------
@ -163,8 +165,8 @@ TEST_BIG_ENDIAN(OPJ_BIG_ENDIAN)
#-----------------------------------------------------------------------------
# Setup file for setting custom ctest vars
configure_file(
${CMAKE_SOURCE_DIR}/cmake/CTestCustom.cmake.in
${CMAKE_BINARY_DIR}/CTestCustom.cmake
${${OPENJPEG_NAMESPACE}_SOURCE_DIR}/cmake/CTestCustom.cmake.in
${${OPENJPEG_NAMESPACE}_BINARY_DIR}/CTestCustom.cmake
@ONLY
)
@ -226,7 +228,7 @@ CHECK_INCLUDE_FILE("unistd.h" HAVE_UNISTD_H)
include(TestLargeFiles)
OPJ_TEST_LARGE_FILES(OPJ_HAVE_LARGEFILES)
# Allocating Aligned Memory Blocks
# Allocating Aligned Memory Blocks
include(CheckIncludeFiles)
check_include_files(malloc.h OPJ_HAVE_MALLOC_H)
include(CheckSymbolExists)
@ -249,6 +251,7 @@ if(BUILD_JPIP_SERVER)
endif()
endif()
add_subdirectory(src/lib)
option(BUILD_LUTS_GENERATOR "Build utility to generate t1_luts.h" OFF)
#-----------------------------------------------------------------------------
# Build Applications
@ -322,8 +325,8 @@ endif()
#-----------------------------------------------------------------------------
# install all targets referenced as OPENJPEGTargets
install(EXPORT OpenJPEGTargets DESTINATION ${OPENJPEG_INSTALL_PACKAGE_DIR})
configure_file( ${OPENJPEG_SOURCE_DIR}/cmake/OpenJPEGConfig.cmake.in
${OPENJPEG_BINARY_DIR}/OpenJPEGConfig.cmake
configure_file( ${${OPENJPEG_NAMESPACE}_SOURCE_DIR}/cmake/OpenJPEGConfig.cmake.in
${${OPENJPEG_NAMESPACE}_BINARY_DIR}/OpenJPEGConfig.cmake
@ONLY
)
install( FILES ${OPENJPEG_BINARY_DIR}/OpenJPEGConfig.cmake

View File

@ -2,6 +2,11 @@
More details in the [Changelog](https://github.com/uclouvain/openjpeg/blob/master/CHANGELOG.md)
## OpenJPEG 2.1.2
* Bug fixes (including security fixes)
* No API/ABI break compared to v2.1.1
## OpenJPEG 2.1.1
* Huge amount of critical bugfixes

View File

@ -29,6 +29,7 @@ it complete and exempt of errors.
* Julien Malik
* Arnaud Maye
* Vincent Nicolas
* Aleksander Nikolic (Cisco Talos)
* Glenn Pearson
* Even Rouault
* Dzonatas Sol

View File

@ -32,7 +32,7 @@
.TH opj_compress 1 "Version 2.1.1" "opj_compress" "converts to jpeg2000 files"
.P
.SH NAME
opj_compress -
opj_compress \-
This program reads in an image of a certain type and converts it to a
jpeg2000 file. It is part of the OpenJPEG library.
.SP
@ -43,20 +43,20 @@ Valid output image extensions are
.B .j2k, .jp2
.SH SYNOPSIS
.P
.B opj_compress -i \fRinfile.bmp \fB-o \fRoutfile.j2k
.B opj_compress \-i \fRinfile.bmp \fB-o \fRoutfile.j2k
.P
.B opj_compress -ImgDir \fRdirectory_name \fB-OutFor \fRjp2
.B opj_compress \-ImgDir \fRdirectory_name \fB-OutFor \fRjp2
.P
.B opj_compress -h \fRPrint a help message and exit.
.B opj_compress \-h \fRPrint a help message and exit.
.P
.R See JPWL OPTIONS for special options
.SH OPTIONS
.TP
.B \-\^b " n,n"
(Size of code block (e.g. -b 32,32). Default: 64 x 64)
(Size of code block (e.g. \-b 32,32). Default: 64 x 64)
.TP
.B \-\^c " n"
(Size of precinct (e.g. -c 128,128). Default: 2^15 x 2^15)
(Size of precinct (e.g. \-c 128,128). Default: 2^15 x 2^15)
.TP
.B \-\^cinema2K " fps"
Digital Cinema 2K profile compliant codestream. Valid \fBfps\fR values are 24 or 48.
@ -65,7 +65,7 @@ Digital Cinema 2K profile compliant codestream. Valid \fBfps\fR values are 24 or
Digital Cinema 4K profile compliant codestream. Does not need an fps: default is 24 fps.
.TP
.B \-\^d " X,Y"
(Offset of image origin (e.g. -d 150,300))
(Offset of image origin (e.g. \-d 150,300))
.TP
.B \-\^h
Print a help message and exit.
@ -85,20 +85,20 @@ Progression order. \fBname\fR can be one out of:LRCP, RLCP, RPCL, PCRL, CPRL. De
.B \-\^q " n"
different psnr for successive layers
.br
.B Note: \fR(options -r and -q cannot be used together)
.B Note: \fR(options \-r and \-q cannot be used together)
.TP
.B \-\^r " n"
different compression ratio(s) for successive layers. The rate specified for each quality level is the desired compression factor.
.br
.B Note: \fR(options -r and -q cannot be used together)
.B Note: \fR(options \-r and \-q cannot be used together)
.TP
.B \-\^s " X,Y"
sub-sampling factor (e.g. -s 2,2). Default: No sub-sampling in x or y direction.
sub-sampling factor (e.g. \-s 2,2). Default: No sub-sampling in x or y direction.
.br
.B Remark: \fRsub-sampling bigger than 2 can produce errors.
.TP
.B \-\^t " W,H"
(Size of tile (e.g. -t 512,512) )
(Size of tile (e.g. \-t 512,512) )
.TP
.B \-\^x " name"
(Create index file and fill it. Default: no index file)
@ -132,7 +132,7 @@ ERTERM(16)
.br
SEGMARK(32)
.br
Values can be added: RESTART(4) + RESET(2) + SEGMARK(32) = -M 38
Values can be added: RESTART(4) + RESET(2) + SEGMARK(32) = \-M 38
.TP
.B \-\^OutFor "ext"
(extension for output files)
@ -149,7 +149,7 @@ e.g. \fB-ROI c=0,U=25\fR
(Write SOP marker before each packet. Default: No SOP marker in the codestream.)
.TP
.B \-\^T "X,Y"
(Offset of the origin of the tiles (e.g. -T 100,75) )
(Offset of the origin of the tiles (e.g. \-T 100,75) )
.TP
.B \-\^W
(see JPWL OPTIONS)
@ -157,7 +157,7 @@ e.g. \fB-ROI c=0,U=25\fR
.SH JPWL OPTIONS
Options usable only if the library has been compiled with \fB-DUSE_JPWL\fR
.P
.B -W h<tilepart><=type>, s<tilepart><=method>, a=<addr>, z=<size>, g=<range>, p<tilepart:pack><=type>
.B \-W h<tilepart><=type>, s<tilepart><=method>, a=<addr>, z=<size>, g=<range>, p<tilepart:pack><=type>
.P
.B h\fR selects the header error protection (EPB): \fBtype\fR can be
[0=none 1,absent=predefined 16=CRC-16 32=CRC-32 37-128=RS]
@ -176,7 +176,7 @@ Options usable only if the library has been compiled with \fB-DUSE_JPWL\fR
(max. 16 specs)
.P
.B s \fRenables sensitivity data insertion (ESD): \fBmethod\fR can be
[-1=NO ESD 0=RELATIVE ERROR 1=MSE 2=MSE REDUCTION 3=PSNR
[\-1=NO ESD 0=RELATIVE ERROR 1=MSE 2=MSE REDUCTION 3=PSNR
4=PSNR INCREMENT 5=MAXERR 6=TSE 7=RESERVED]
if \fBtilepart\fR is absent, it is for main header only
if \fBtilepart\fR is present, it applies from that tile
@ -194,13 +194,13 @@ Options usable only if the library has been compiled with \fB-DUSE_JPWL\fR
.P
.SH EXAMPLES
.P
.B opj_compress -i \fRfile.bmp \fB-o \fRfile.j2k \fB-r \fR20,10,1 (compress 20x, then 10x, then lossless).
.B opj_compress \-i \fRfile.bmp \fB-o \fRfile.j2k \fB-r \fR20,10,1 (compress 20x, then 10x, then lossless).
.P
.B opj_compress -i \fRfile.ppm \fB-o \fRfile.j2k \fB-q \fR30,40,50
.B opj_compress \-i \fRfile.ppm \fB-o \fRfile.j2k \fB-q \fR30,40,50
.P
.B opj_compress -i \fRfile.pgx \fB-o \fRfile.j2k \fB-POC \fRT1=0,0,1,5,3,CPRL
.B opj_compress \-i \fRfile.pgx \fB-o \fRfile.j2k \fB-POC \fRT1=0,0,1,5,3,CPRL
.P
.B opj_compress -i \fRlena.raw \fB-o \fRlena.j2k \fB-F \fR512,512,3,8,u
.B opj_compress \-i \fRlena.raw \fB-o \fRlena.j2k \fB-F \fR512,512,3,8,u
.P
.SH AUTHORS
Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium

View File

@ -32,7 +32,7 @@
.TH opj_decompress 1 "Version 2.1.1" "opj_decompress" "converts jpeg2000 files"
.P
.SH NAME
opj_decompress -
opj_decompress \-
This program reads in a jpeg2000 image and converts it to another
image type. It is part of the OpenJPEG library.
.SP
@ -43,11 +43,11 @@ Valid output image extensions are
.B .bmp, .pgm, .pgx, .png, .pnm, .ppm, .raw, .tga, .tif \fR. For PNG resp. TIF it needs libpng resp. libtiff .
.SH SYNOPSIS
.P
.B opj_decompress -i \fRinfile.j2k \fB-o \fRoutfile.png
.B opj_decompress \-i \fRinfile.j2k \fB-o \fRoutfile.png
.P
.B opj_decompress -ImgDir \fRimages/ \fB-OutFor \fRbmp
.B opj_decompress \-ImgDir \fRimages/ \fB-OutFor \fRbmp
.P
.B opj_decompress -h \fRPrint help message and exit
.B opj_decompress \-h \fRPrint help message and exit
.P
.R See JPWL OPTIONS for special options
.SH OPTIONS

View File

@ -32,7 +32,7 @@
.TH opj_dump 1 "Version 2.1.1" "opj_dump" "dumps jpeg2000 files"
.P
.SH NAME
opj_dump -
opj_dump \-
This program reads in a jpeg2000 image and dumps the contents to stdout. It is part of the OpenJPEG library.
.SP
Valid input image extensions are
@ -40,11 +40,11 @@ Valid input image extensions are
.SP
.SH SYNOPSIS
.P
.B opj_dump -i \fRinfile.j2k
.B opj_dump \-i \fRinfile.j2k
.P
.B opj_dump -ImgDir \fRimages/ \fRDump all files in images/
.B opj_dump \-ImgDir \fRimages/ \fRDump all files in images/
.P
.B opj_dump -h \fRPrint help message and exit
.B opj_dump \-h \fRPrint help message and exit
.P
.SH OPTIONS
.TP

View File

@ -57,6 +57,9 @@ foreach(exe opj_decompress opj_compress opj_dump)
# On unix you need to link to the math library:
if(UNIX)
target_link_libraries(${exe} m)
IF("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
target_link_libraries(${exe} rt)
endif()
endif()
# Install exe
install(TARGETS ${exe}

View File

@ -1328,11 +1328,14 @@ struct pnm_header
static char *skip_white(char *s)
{
while(*s)
if (s != NULL)
{
if(*s == '\n' || *s == '\r') return NULL;
if(isspace(*s)) { ++s; continue; }
return s;
while(*s)
{
if(*s == '\n' || *s == '\r') return NULL;
if(isspace(*s)) { ++s; continue; }
return s;
}
}
return NULL;
}
@ -1377,7 +1380,7 @@ static char *skip_idf(char *start, char out_idf[256])
static void read_pnm_header(FILE *reader, struct pnm_header *ph)
{
int format, have_wh, end, ttype;
int format, end, ttype;
char idf[256], type[256];
char line[256];
@ -1398,11 +1401,12 @@ static void read_pnm_header(FILE *reader, struct pnm_header *ph)
return;
}
ph->format = format;
ttype = end = have_wh = 0;
ttype = end = 0;
while(fgets(line, 250, reader))
{
char *s;
int allow_null = 0;
if(*line == '#') continue;
@ -1478,36 +1482,25 @@ static void read_pnm_header(FILE *reader, struct pnm_header *ph)
return;
} /* if(format == 7) */
if( !have_wh)
{
/* Here format is in range [1,6] */
if (ph->width == 0) {
s = skip_int(s, &ph->width);
if ((s == NULL) || (*s == 0) || (ph->width < 1)) return;
allow_null = 1;
}
if (ph->height == 0) {
s = skip_int(s, &ph->height);
have_wh = 1;
if(format == 1 || format == 4) break;
if(format == 2 || format == 3 || format == 5 || format == 6)
{
if (skip_int(s, &ph->maxval) != NULL) {
if(ph->maxval > 65535) {
return;
}
else {
break;
}
}
if ((s == NULL) && allow_null) continue;
if ((s == NULL) || (*s == 0) || (ph->height < 1)) return;
if(format == 1 || format == 4) {
break;
}
continue;
}
if(format == 2 || format == 3 || format == 5 || format == 6)
{
/* P2, P3, P5, P6: */
s = skip_int(s, &ph->maxval);
if(ph->maxval > 65535) return;
allow_null = 1;
}
/* here, format is in P2, P3, P5, P6 */
s = skip_int(s, &ph->maxval);
if ((s == NULL) && allow_null) continue;
if ((s == NULL) || (*s == 0)) return;
break;
}/* while(fgets( ) */
if(format == 2 || format == 3 || format > 4)
@ -1524,18 +1517,14 @@ static void read_pnm_header(FILE *reader, struct pnm_header *ph)
}
if(ph->depth < 1 || ph->depth > 4) return;
if(ph->width && ph->height && ph->depth && ph->maxval && ttype)
if (ttype)
ph->ok = 1;
}
else
{
if(format != 1 && format != 4)
ph->ok = 1;
if(format == 1 || format == 4)
{
if(ph->width && ph->height && ph->maxval) ph->ok = 1;
}
else
{
if(ph->width && ph->height) ph->ok = 1;
ph->maxval = 255;
}
}

View File

@ -675,10 +675,28 @@ opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters)
}
}
if (Info_h.biWidth == 0 || Info_h.biHeight == 0) {
fclose(IN);
return NULL;
}
if (Info_h.biBitCount > (((OPJ_UINT32)-1) - 31) / Info_h.biWidth) {
fclose(IN);
return NULL;
}
stride = ((Info_h.biWidth * Info_h.biBitCount + 31U) / 32U) * 4U; /* rows are aligned on 32bits */
if (Info_h.biBitCount == 4 && Info_h.biCompression == 2) { /* RLE 4 gets decoded as 8 bits data for now... */
if (8 > (((OPJ_UINT32)-1) - 31) / Info_h.biWidth) {
fclose(IN);
return NULL;
}
stride = ((Info_h.biWidth * 8U + 31U) / 32U) * 4U;
}
if (stride > ((OPJ_UINT32)-1) / sizeof(OPJ_UINT8) / Info_h.biHeight) {
fclose(IN);
return NULL;
}
pData = (OPJ_UINT8 *) calloc(1, stride * Info_h.biHeight * sizeof(OPJ_UINT8));
if (pData == NULL) {
fclose(IN);

View File

@ -236,7 +236,7 @@ static void encode_help_display(void) {
fprintf(stdout,"-I\n");
fprintf(stdout," Use the irreversible DWT 9-7.\n");
fprintf(stdout,"-mct <0|1|2>\n");
fprintf(stdout," Explicitely specifies if a Multiple Component Transform has to be used.\n");
fprintf(stdout," Explicitly specifies if a Multiple Component Transform has to be used.\n");
fprintf(stdout," 0: no MCT ; 1: RGB->YCC conversion ; 2: custom MCT.\n");
fprintf(stdout," If custom MCT, \"-m\" option has to be used (see hereunder).\n");
fprintf(stdout," By default, RGB->YCC conversion is used if there are 3 components or more,\n");
@ -1029,7 +1029,7 @@ static int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *param
return 1;
}
fprintf(stdout,"CINEMA 2K profile activated\n"
"Other options specified could be overriden\n");
"Other options specified could be overridden\n");
}
break;
@ -1040,7 +1040,7 @@ static int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *param
{
parameters->rsiz = OPJ_PROFILE_CINEMA_4K;
fprintf(stdout,"CINEMA 4K profile activated\n"
"Other options specified could be overriden\n");
"Other options specified could be overridden\n");
}
break;

View File

@ -43,6 +43,7 @@
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#ifdef _WIN32
#include "windirent.h"
@ -150,6 +151,8 @@ typedef struct opj_decompress_params
int upsample;
/* split output components to different files */
int split_pnm;
/** number of threads */
int num_threads;
}opj_decompress_parameters;
/* -------------------------------------------------------------------------- */
@ -224,8 +227,11 @@ static void decode_help_display(void) {
" -upsample\n"
" Downsampled components will be upsampled to image size\n"
" -split-pnm\n"
" Split output components to different files when writing to PNM\n"
"\n");
" Split output components to different files when writing to PNM\n");
if( opj_has_thread_support() ) {
fprintf(stdout," -threads <num_threads>\n"
" Number of threads to use for decoding.\n");
}
/* UniPG>> */
#ifdef USE_JPWL
fprintf(stdout," -W <options>\n"
@ -520,7 +526,8 @@ int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *para
{"OutFor", REQ_ARG, NULL,'O'},
{"force-rgb", NO_ARG, NULL, 1},
{"upsample", NO_ARG, NULL, 1},
{"split-pnm", NO_ARG, NULL, 1}
{"split-pnm", NO_ARG, NULL, 1},
{"threads", REQ_ARG, NULL, 'T'}
};
const char optlist[] = "i:o:r:l:x:d:t:p:"
@ -808,6 +815,22 @@ int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *para
break;
#endif /* USE_JPWL */
/* <<UniPG */
/* ----------------------------------------------------- */
case 'T': /* Number of threads */
{
if( strcmp(opj_optarg, "ALL_CPUS") == 0 )
{
parameters->num_threads = opj_get_num_cpus();
if( parameters->num_threads == 1 )
parameters->num_threads = 0;
}
else
{
sscanf(opj_optarg, "%d", &parameters->num_threads);
}
}
break;
/* ----------------------------------------------------- */
@ -885,17 +908,22 @@ OPJ_FLOAT64 opj_clock(void) {
/* t is the high resolution performance counter (see MSDN) */
QueryPerformanceCounter ( & t ) ;
return freq.QuadPart ? (t.QuadPart / (OPJ_FLOAT64)freq.QuadPart) : 0;
#elif defined(__linux)
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return( (OPJ_FLOAT64)ts.tv_sec + (OPJ_FLOAT64)ts.tv_nsec * 1e-9 );
#else
/* Unix or Linux: use resource usage */
struct rusage t;
OPJ_FLOAT64 procTime;
/* (1) Get the rusage data structure at this moment (man getrusage) */
getrusage(0,&t);
/* (2) What is the elapsed time ? - CPU time = User time + System time */
/* Unix : use resource usage */
/* FIXME: this counts the total CPU time, instead of the user perceived time */
struct rusage t;
OPJ_FLOAT64 procTime;
/* (1) Get the rusage data structure at this moment (man getrusage) */
getrusage(0,&t);
/* (2) What is the elapsed time ? - CPU time = User time + System time */
/* (2a) Get the seconds */
procTime = (OPJ_FLOAT64)(t.ru_utime.tv_sec + t.ru_stime.tv_sec);
/* (2b) More precisely! Get the microseconds part ! */
return ( procTime + (OPJ_FLOAT64)(t.ru_utime.tv_usec + t.ru_stime.tv_usec) * 1e-6 ) ;
procTime = (OPJ_FLOAT64)(t.ru_utime.tv_sec + t.ru_stime.tv_sec);
/* (2b) More precisely! Get the microseconds part ! */
return ( procTime + (OPJ_FLOAT64)(t.ru_utime.tv_usec + t.ru_stime.tv_usec) * 1e-6 ) ;
#endif
}
@ -1306,7 +1334,13 @@ int main(int argc, char **argv)
opj_destroy_codec(l_codec);
failed = 1; goto fin;
}
if( parameters.num_threads >= 1 && !opj_codec_set_threads(l_codec, parameters.num_threads) ) {
fprintf(stderr, "ERROR -> opj_decompress: failed to set number of threads\n");
opj_stream_destroy(l_stream);
opj_destroy_codec(l_codec);
failed = 1; goto fin;
}
/* Read the main header of the codestream and if necessary the JP2 boxes*/
if(! opj_read_header(l_stream, l_codec, &image)){

View File

@ -5,10 +5,12 @@ install( FILES ${CMAKE_CURRENT_BINARY_DIR}/opj_config.h
DESTINATION ${OPENJPEG_INSTALL_INCLUDE_DIR} COMPONENT Headers)
include_directories(
${OPENJPEG_BINARY_DIR}/src/lib/openjp2 # opj_config.h and opj_config_private.h
${${OPENJPEG_NAMESPACE}_BINARY_DIR}/src/lib/openjp2 # opj_config.h and opj_config_private.h
)
# Defines the source code for the library
set(OPENJPEG_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/thread.c
${CMAKE_CURRENT_SOURCE_DIR}/thread.h
${CMAKE_CURRENT_SOURCE_DIR}/bio.c
${CMAKE_CURRENT_SOURCE_DIR}/bio.h
${CMAKE_CURRENT_SOURCE_DIR}/cio.c
@ -29,6 +31,7 @@ set(OPENJPEG_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/mct.h
${CMAKE_CURRENT_SOURCE_DIR}/mqc.c
${CMAKE_CURRENT_SOURCE_DIR}/mqc.h
${CMAKE_CURRENT_SOURCE_DIR}/mqc_inl.h
${CMAKE_CURRENT_SOURCE_DIR}/openjpeg.c
${CMAKE_CURRENT_SOURCE_DIR}/openjpeg.h
${CMAKE_CURRENT_SOURCE_DIR}/opj_clock.c
@ -73,6 +76,11 @@ if(OPJ_DISABLE_TPSOT_FIX)
add_definitions(-DOPJ_DISABLE_TPSOT_FIX)
endif()
# Special case for old i586-mingw32msvc-gcc cross compiler
if(NOT WIN32 AND CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER MATCHES ".*mingw32msvc.*" )
set(WIN32 YES)
endif()
# Build the library
if(WIN32)
if(BUILD_SHARED_LIBS)
@ -110,16 +118,18 @@ install(
DESTINATION ${OPENJPEG_INSTALL_MAN_DIR}/man3)
endif()
# internal utilities to generate t1_luts.h (part of the jp2 lib)
if(BUILD_LUTS_GENERATOR)
# internal utility to generate t1_luts.h (part of the jp2 lib)
# no need to install:
add_executable(t1_generate_luts t1_generate_luts.c)
if(UNIX)
target_link_libraries(t1_generate_luts m)
add_executable(t1_generate_luts t1_generate_luts.c)
if(UNIX)
target_link_libraries(t1_generate_luts m)
endif()
endif()
# Experimental option; let's how cppcheck performs
# Implementation details:
# I could not figure out how to easily upload a file to CDash. Instead simply
# I could not figure out how to easily upload a file to CDash. Instead simply
# pretend cppcheck is part of the Build step. Technically cppcheck can even
# output gcc formatted error/warning report
# Another implementation detail: I could not redirect error to the error
@ -142,3 +152,36 @@ if(OPJ_USE_DSYMUTIL)
DEPENDS ${OPENJPEG_LIBRARY_NAME})
endif()
endif()
#################################################################################
# threading configuration
#################################################################################
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
option(OPJ_USE_THREAD "Build with thread/mutex support " ON)
if(NOT OPJ_USE_THREAD)
add_definitions( -DMUTEX_stub)
endif(NOT OPJ_USE_THREAD)
find_package(Threads QUIET)
if(OPJ_USE_THREAD AND WIN32 AND NOT Threads_FOUND )
add_definitions( -DMUTEX_win32)
set(Threads_FOUND YES)
endif()
if(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_WIN32_THREADS_INIT )
add_definitions( -DMUTEX_win32)
endif(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_WIN32_THREADS_INIT )
if(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT )
add_definitions( -DMUTEX_pthread)
endif(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT )
if(OPJ_USE_THREAD AND NOT Threads_FOUND)
message(FATAL_ERROR "No thread library found and thread/mutex support is required by OPJ_USE_THREAD option")
endif(OPJ_USE_THREAD AND NOT Threads_FOUND)
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)

View File

@ -124,7 +124,7 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_st
/**
Inverse wavelet transform in 2-D.
*/
static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn);
static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn);
static OPJ_BOOL opj_dwt_encode_procedure( opj_tcd_tilecomp_t * tilec,
void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) );
@ -395,7 +395,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void
OPJ_INT32 rw; /* width of the resolution level computed */
OPJ_INT32 rh; /* height of the resolution level computed */
OPJ_UINT32 l_data_size;
size_t l_data_size;
opj_tcd_resolution_t * l_cur_res = 0;
opj_tcd_resolution_t * l_last_res = 0;
@ -407,8 +407,14 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void
l_cur_res = tilec->resolutions + l;
l_last_res = l_cur_res - 1;
l_data_size = opj_dwt_max_resolution( tilec->resolutions,tilec->numresolutions) * (OPJ_UINT32)sizeof(OPJ_INT32);
bj = (OPJ_INT32*)opj_malloc((size_t)l_data_size);
l_data_size = opj_dwt_max_resolution( tilec->resolutions,tilec->numresolutions);
/* overflow check */
if (l_data_size > (SIZE_MAX / 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 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) {
@ -473,8 +479,8 @@ OPJ_BOOL opj_dwt_encode(opj_tcd_tilecomp_t * tilec)
/* <summary> */
/* Inverse 5-3 wavelet transform in 2-D. */
/* </summary> */
OPJ_BOOL opj_dwt_decode(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) {
return opj_dwt_decode_tile(tilec, numres, &opj_dwt_decode_1);
OPJ_BOOL opj_dwt_decode(opj_thread_pool_t* tp, opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) {
return opj_dwt_decode_tile(tp, tilec, numres, &opj_dwt_decode_1);
}
@ -556,10 +562,73 @@ static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r, O
return mr ;
}
typedef struct
{
opj_dwt_t h;
DWT1DFN dwt_1D;
OPJ_UINT32 rw;
OPJ_UINT32 w;
OPJ_INT32 * OPJ_RESTRICT tiledp;
OPJ_UINT32 min_j;
OPJ_UINT32 max_j;
} opj_dwd_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;
(void)tls;
job = (opj_dwd_decode_h_job_t*)user_data;
for( j = job->min_j; j < job->max_j; j++ )
{
opj_dwt_interleave_h(&job->h, &job->tiledp[j*job->w]);
(job->dwt_1D)(&job->h);
memcpy(&job->tiledp[j*job->w], job->h.mem, job->rw * sizeof(OPJ_INT32));
}
opj_aligned_free(job->h.mem);
opj_free(job);
}
typedef struct
{
opj_dwt_t v;
DWT1DFN dwt_1D;
OPJ_UINT32 rh;
OPJ_UINT32 w;
OPJ_INT32 * OPJ_RESTRICT tiledp;
OPJ_UINT32 min_j;
OPJ_UINT32 max_j;
} opj_dwd_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;
(void)tls;
job = (opj_dwd_decode_v_job_t*)user_data;
for( j = job->min_j; j < job->max_j; j++ )
{
OPJ_UINT32 k;
opj_dwt_interleave_v(&job->v, &job->tiledp[j], (OPJ_INT32)job->w);
(job->dwt_1D)(&job->v);
for(k = 0; k < job->rh; ++k) {
job->tiledp[k * job->w + j] = job->v.mem[k];
}
}
opj_aligned_free(job->v.mem);
opj_free(job);
}
/* <summary> */
/* Inverse wavelet transform in 2-D. */
/* Inverse wavelet transform in 2-D. */
/* </summary> */
static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) {
static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D)
{
opj_dwt_t h;
opj_dwt_t v;
@ -569,11 +638,21 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres
OPJ_UINT32 rh = (OPJ_UINT32)(tr->y1 - tr->y0); /* height of the resolution level computed */
OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
size_t h_mem_size;
int num_threads;
if (numres == 1U) {
return OPJ_TRUE;
}
h.mem = (OPJ_INT32*)opj_aligned_malloc(opj_dwt_max_resolution(tr, numres) * sizeof(OPJ_INT32));
num_threads = opj_thread_pool_get_thread_count(tp);
h_mem_size = opj_dwt_max_resolution(tr, numres);
/* overflow check */
if (h_mem_size > (SIZE_MAX / sizeof(OPJ_INT32))) {
/* FIXME event manager error callback */
return OPJ_FALSE;
}
h_mem_size *= sizeof(OPJ_INT32);
h.mem = (OPJ_INT32*)opj_aligned_malloc(h_mem_size);
if (! h.mem){
/* FIXME event manager error callback */
return OPJ_FALSE;
@ -595,29 +674,133 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres
h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn);
h.cas = tr->x0 % 2;
for(j = 0; j < rh; ++j) {
opj_dwt_interleave_h(&h, &tiledp[j*w]);
(dwt_1D)(&h);
memcpy(&tiledp[j*w], h.mem, rw * sizeof(OPJ_INT32));
if( num_threads <= 1 || rh <= 1 )
{
for(j = 0; j < rh; ++j) {
opj_dwt_interleave_h(&h, &tiledp[j*w]);
(dwt_1D)(&h);
memcpy(&tiledp[j*w], h.mem, rw * sizeof(OPJ_INT32));
}
}
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_dwd_decode_h_job_t* job;
job = (opj_dwd_decode_h_job_t*) opj_malloc(sizeof(opj_dwd_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 */
/* tiledp, so it is not practical to recover from that error */
/* FIXME event manager error callback */
opj_thread_pool_wait_completion(tp, 0);
opj_aligned_free(h.mem);
return OPJ_FALSE;
}
job->h = h;
job->dwt_1D = dwt_1D;
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->h.mem = (OPJ_INT32*)opj_aligned_malloc(h_mem_size);
if (!job->h.mem)
{
/* FIXME event manager error callback */
opj_thread_pool_wait_completion(tp, 0);
opj_free(job);
opj_aligned_free(h.mem);
return OPJ_FALSE;
}
opj_thread_pool_submit_job( tp, opj_dwt_decode_h_func, job );
}
opj_thread_pool_wait_completion(tp, 0);
}
v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn);
v.cas = tr->y0 % 2;
for(j = 0; j < rw; ++j){
OPJ_UINT32 k;
opj_dwt_interleave_v(&v, &tiledp[j], (OPJ_INT32)w);
(dwt_1D)(&v);
for(k = 0; k < rh; ++k) {
tiledp[k * w + j] = v.mem[k];
if( num_threads <= 1 || rw <= 1 )
{
for(j = 0; j < rw; ++j){
OPJ_UINT32 k;
opj_dwt_interleave_v(&v, &tiledp[j], (OPJ_INT32)w);
(dwt_1D)(&v);
for(k = 0; k < rh; ++k) {
tiledp[k * w + j] = v.mem[k];
}
}
}
else
{
OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads;
OPJ_UINT32 step_j;
if( rw < num_jobs ) {
num_jobs = rw;
}
step_j = (rw / num_jobs);
for( j = 0; j < num_jobs; j++ )
{
opj_dwd_decode_v_job_t* job;
job = (opj_dwd_decode_v_job_t*) opj_malloc(sizeof(opj_dwd_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 */
/* tiledp, so it is not practical to recover from that error */
/* FIXME event manager error callback */
opj_thread_pool_wait_completion(tp, 0);
opj_aligned_free(v.mem);
return OPJ_FALSE;
}
job->v = v;
job->dwt_1D = dwt_1D;
job->rh = rh;
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 = rw;
}
job->v.mem = (OPJ_INT32*)opj_aligned_malloc(h_mem_size);
if (!job->v.mem)
{
/* FIXME event manager error callback */
opj_thread_pool_wait_completion(tp, 0);
opj_free(job);
opj_aligned_free(v.mem);
return OPJ_FALSE;
}
opj_thread_pool_submit_job( tp, opj_dwt_decode_v_func, job );
}
opj_thread_pool_wait_completion(tp, 0);
}
}
opj_aligned_free(h.mem);
return OPJ_TRUE;
}
static void opj_v4dwt_interleave_h(opj_v4dwt_t* OPJ_RESTRICT w, OPJ_FLOAT32* OPJ_RESTRICT a, OPJ_INT32 x, OPJ_INT32 size){
static void opj_v4dwt_interleave_h(opj_v4dwt_t* OPJ_RESTRICT w, OPJ_FLOAT32* OPJ_RESTRICT a, OPJ_INT32 x, OPJ_INT32 size)
{
OPJ_FLOAT32* OPJ_RESTRICT bi = (OPJ_FLOAT32*) (w->wavelet + w->cas);
OPJ_INT32 count = w->sn;
OPJ_INT32 i, k;
@ -846,7 +1029,21 @@ OPJ_BOOL opj_dwt_decode_real(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec, OPJ_UINT32
OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
h.wavelet = (opj_v4_t*) opj_aligned_malloc((opj_dwt_max_resolution(res, numres)+5) * sizeof(opj_v4_t));
size_t l_data_size;
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;
}
l_data_size += 5U;
/* overflow check */
if (l_data_size > (SIZE_MAX / sizeof(opj_v4_t))) {
/* FIXME event manager error callback */
return OPJ_FALSE;
}
h.wavelet = (opj_v4_t*) opj_aligned_malloc(l_data_size * sizeof(opj_v4_t));
if (!h.wavelet) {
/* FIXME event manager error callback */
return OPJ_FALSE;

View File

@ -63,10 +63,11 @@ OPJ_BOOL opj_dwt_encode(opj_tcd_tilecomp_t * tilec);
/**
Inverse 5-3 wavelet transform in 2-D.
Apply a reversible inverse DWT transform to a component of an image.
@param tp Thread pool
@param tilec Tile component information (current tile)
@param numres Number of resolution levels to decode
*/
OPJ_BOOL opj_dwt_decode(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres);
OPJ_BOOL opj_dwt_decode(opj_thread_pool_t* tp, opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres);
/**
Get the gain of a subband for the reversible 5-3 DWT.

View File

@ -5948,6 +5948,35 @@ void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters)
}
}
OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads)
{
if( opj_has_thread_support() )
{
opj_thread_pool_destroy(j2k->m_tp);
j2k->m_tp = NULL;
if (num_threads <= (OPJ_UINT32)INT_MAX ) {
j2k->m_tp = opj_thread_pool_create((int)num_threads);
}
if( j2k->m_tp == NULL )
{
j2k->m_tp = opj_thread_pool_create(0);
return OPJ_FALSE;
}
return OPJ_TRUE;
}
return OPJ_FALSE;
}
static int opj_j2k_get_default_thread_count()
{
const char* num_threads = getenv("OPJ_NUM_THREADS");
if( num_threads == NULL || !opj_has_thread_support() )
return 0;
if( strcmp(num_threads, "ALL_CPUS") == 0 )
return opj_get_num_cpus();
return atoi(num_threads);
}
/* ----------------------------------------------------------------------- */
/* J2K encoder interface */
/* ----------------------------------------------------------------------- */
@ -5985,6 +6014,17 @@ opj_j2k_t* opj_j2k_create_compress(void)
return NULL;
}
l_j2k->m_tp = opj_thread_pool_create(opj_j2k_get_default_thread_count());
if( !l_j2k->m_tp )
{
l_j2k->m_tp = opj_thread_pool_create(0);
}
if( !l_j2k->m_tp )
{
opj_j2k_destroy(l_j2k);
return NULL;
}
return l_j2k;
}
@ -7490,7 +7530,7 @@ static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd ( opj_j2k_t * p_j2
return OPJ_FALSE;
}
if ( !opj_tcd_init(p_j2k->m_tcd, l_image, &(p_j2k->m_cp)) ) {
if ( !opj_tcd_init(p_j2k->m_tcd, l_image, &(p_j2k->m_cp), p_j2k->m_tp) ) {
opj_tcd_destroy(p_j2k->m_tcd);
p_j2k->m_tcd = 00;
opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n");
@ -7571,6 +7611,9 @@ void opj_j2k_destroy (opj_j2k_t *p_j2k)
opj_image_destroy(p_j2k->m_output_image);
p_j2k->m_output_image = NULL;
opj_thread_pool_destroy(p_j2k->m_tp);
p_j2k->m_tp = NULL;
opj_free(p_j2k);
}
@ -8668,6 +8711,17 @@ opj_j2k_t* opj_j2k_create_decompress(void)
return 00;
}
l_j2k->m_tp = opj_thread_pool_create(opj_j2k_get_default_thread_count());
if( !l_j2k->m_tp )
{
l_j2k->m_tp = opj_thread_pool_create(0);
}
if( !l_j2k->m_tp )
{
opj_j2k_destroy(l_j2k);
return NULL;
}
return l_j2k;
}
@ -10944,7 +10998,7 @@ static OPJ_BOOL opj_j2k_create_tcd( opj_j2k_t *p_j2k,
return OPJ_FALSE;
}
if (!opj_tcd_init(p_j2k->m_tcd,p_j2k->m_private_image,&p_j2k->m_cp)) {
if (!opj_tcd_init(p_j2k->m_tcd,p_j2k->m_private_image,&p_j2k->m_cp, p_j2k->m_tp)) {
opj_tcd_destroy(p_j2k->m_tcd);
p_j2k->m_tcd = 00;
return OPJ_FALSE;

View File

@ -228,7 +228,7 @@ typedef struct opj_simple_mcc_decorrelation_data
OPJ_UINT32 m_nb_comps;
opj_mct_data_t * m_decorrelation_array;
opj_mct_data_t * m_offset_array;
OPJ_UINT32 m_is_irreversible : 1;
OPJ_BITFIELD m_is_irreversible : 1;
}
opj_simple_mcc_decorrelation_data_t;
@ -306,11 +306,11 @@ typedef struct opj_tcp
/***** FLAGS *******/
/** If cod == 1 --> there was a COD marker for the present tile */
OPJ_UINT32 cod : 1;
OPJ_BITFIELD cod : 1;
/** If ppt == 1 --> there was a PPT marker for the present tile */
OPJ_UINT32 ppt : 1;
OPJ_BITFIELD ppt : 1;
/** indicates if a POC marker has been used O:NO, 1:YES */
OPJ_UINT32 POC : 1;
OPJ_BITFIELD POC : 1;
} opj_tcp_t;
@ -327,13 +327,13 @@ typedef struct opj_encoding_param
/** Flag determining tile part generation*/
OPJ_BYTE m_tp_flag;
/** allocation by rate/distortion */
OPJ_UINT32 m_disto_alloc : 1;
OPJ_BITFIELD m_disto_alloc : 1;
/** allocation by fixed layer */
OPJ_UINT32 m_fixed_alloc : 1;
OPJ_BITFIELD m_fixed_alloc : 1;
/** add fixed_quality */
OPJ_UINT32 m_fixed_quality : 1;
OPJ_BITFIELD m_fixed_quality : 1;
/** Enabling Tile part generation*/
OPJ_UINT32 m_tp_on : 1;
OPJ_BITFIELD m_tp_on : 1;
}
opj_encoding_param_t;
@ -453,9 +453,9 @@ typedef struct opj_cp
/******** FLAGS *********/
/** if ppm == 1 --> there was a PPM marker*/
OPJ_UINT32 ppm : 1;
OPJ_BITFIELD ppm : 1;
/** tells if the parameter is a coding or decoding one */
OPJ_UINT32 m_is_decoder : 1;
OPJ_BITFIELD m_is_decoder : 1;
/* <<UniPG */
} opj_cp_t;
@ -497,12 +497,12 @@ typedef struct opj_j2k_dec
*/
OPJ_BOOL m_last_tile_part;
/** to tell that a tile can be decoded. */
OPJ_UINT32 m_can_decode : 1;
OPJ_UINT32 m_discard_tiles : 1;
OPJ_UINT32 m_skip_data : 1;
OPJ_BITFIELD m_can_decode : 1;
OPJ_BITFIELD m_discard_tiles : 1;
OPJ_BITFIELD m_skip_data : 1;
/** TNsot correction : see issue 254 **/
OPJ_UINT32 m_nb_tile_parts_correction_checked : 1;
OPJ_UINT32 m_nb_tile_parts_correction : 1;
OPJ_BITFIELD m_nb_tile_parts_correction_checked : 1;
OPJ_BITFIELD m_nb_tile_parts_correction : 1;
} opj_j2k_dec_t;
@ -589,6 +589,12 @@ typedef struct opj_j2k
/** the current tile coder/decoder **/
struct opj_tcd * m_tcd;
/** Number of threads to use */
int m_num_threads;
/** Thread pool */
opj_thread_pool_t* m_tp;
}
opj_j2k_t;
@ -607,6 +613,8 @@ Decoding parameters are returned in j2k->cp.
*/
void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters);
OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads);
/**
* Creates a J2K compression structure
*

View File

@ -1777,6 +1777,11 @@ void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters)
jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
}
OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads)
{
return opj_j2k_set_threads(jp2->j2k, num_threads);
}
/* ----------------------------------------------------------------------- */
/* JP2 encoder interface */
/* ----------------------------------------------------------------------- */

View File

@ -243,6 +243,8 @@ Decoding parameters are returned in jp2->j2k->cp.
*/
void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters);
OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads);
/**
* Decode an image from a JPEG-2000 file stream
* @param jp2 JP2 decompressor handle

View File

@ -70,28 +70,6 @@ Fill mqc->c with 1's for flushing
@param mqc MQC handle
*/
static void opj_mqc_setbits(opj_mqc_t *mqc);
/**
FIXME DOC
@param mqc MQC handle
@return
*/
static INLINE OPJ_INT32 opj_mqc_mpsexchange(opj_mqc_t *const mqc);
/**
FIXME DOC
@param mqc MQC handle
@return
*/
static INLINE OPJ_INT32 opj_mqc_lpsexchange(opj_mqc_t *const mqc);
/**
Input a byte
@param mqc MQC handle
*/
static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc);
/**
Renormalize mqc->a and mqc->c while decoding
@param mqc MQC handle
*/
static INLINE void opj_mqc_renormd(opj_mqc_t *const mqc);
/*@}*/
/*@}*/
@ -284,82 +262,6 @@ static void opj_mqc_setbits(opj_mqc_t *mqc) {
}
}
static INLINE OPJ_INT32 opj_mqc_mpsexchange(opj_mqc_t *const mqc) {
OPJ_INT32 d;
if (mqc->a < (*mqc->curctx)->qeval) {
d = (OPJ_INT32)(1 - (*mqc->curctx)->mps);
*mqc->curctx = (*mqc->curctx)->nlps;
} else {
d = (OPJ_INT32)(*mqc->curctx)->mps;
*mqc->curctx = (*mqc->curctx)->nmps;
}
return d;
}
static INLINE OPJ_INT32 opj_mqc_lpsexchange(opj_mqc_t *const mqc) {
OPJ_INT32 d;
if (mqc->a < (*mqc->curctx)->qeval) {
mqc->a = (*mqc->curctx)->qeval;
d = (OPJ_INT32)(*mqc->curctx)->mps;
*mqc->curctx = (*mqc->curctx)->nmps;
} else {
mqc->a = (*mqc->curctx)->qeval;
d = (OPJ_INT32)(1 - (*mqc->curctx)->mps);
*mqc->curctx = (*mqc->curctx)->nlps;
}
return d;
}
#ifdef MQC_PERF_OPT
static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc) {
unsigned int i = *((unsigned int *) mqc->bp);
mqc->c += i & 0xffff00;
mqc->ct = i & 0x0f;
mqc->bp += (i >> 2) & 0x04;
}
#else
static void opj_mqc_bytein(opj_mqc_t *const mqc) {
if (mqc->bp != mqc->end) {
OPJ_UINT32 c;
if (mqc->bp + 1 != mqc->end) {
c = *(mqc->bp + 1);
} else {
c = 0xff;
}
if (*mqc->bp == 0xff) {
if (c > 0x8f) {
mqc->c += 0xff00;
mqc->ct = 8;
} else {
mqc->bp++;
mqc->c += c << 9;
mqc->ct = 7;
}
} else {
mqc->bp++;
mqc->c += c << 8;
mqc->ct = 8;
}
} else {
mqc->c += 0xff00;
mqc->ct = 8;
}
}
#endif
static INLINE void opj_mqc_renormd(opj_mqc_t *const mqc) {
do {
if (mqc->ct == 0) {
opj_mqc_bytein(mqc);
}
mqc->a <<= 1;
mqc->c <<= 1;
mqc->ct--;
} while (mqc->a < 0x8000);
}
/*
==========================================================
MQ-Coder interface
@ -585,25 +487,6 @@ OPJ_BOOL opj_mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len) {
return OPJ_TRUE;
}
OPJ_INT32 opj_mqc_decode(opj_mqc_t *const mqc) {
OPJ_INT32 d;
mqc->a -= (*mqc->curctx)->qeval;
if ((mqc->c >> 16) < (*mqc->curctx)->qeval) {
d = opj_mqc_lpsexchange(mqc);
opj_mqc_renormd(mqc);
} else {
mqc->c -= (*mqc->curctx)->qeval << 16;
if ((mqc->a & 0x8000) == 0) {
d = opj_mqc_mpsexchange(mqc);
opj_mqc_renormd(mqc);
} else {
d = (OPJ_INT32)(*mqc->curctx)->mps;
}
}
return d;
}
void opj_mqc_resetstates(opj_mqc_t *mqc) {
OPJ_UINT32 i;
for (i = 0; i < MQC_NUMCTXS; i++) {

View File

@ -77,11 +77,14 @@ typedef struct opj_mqc {
OPJ_BYTE *end;
opj_mqc_state_t *ctxs[MQC_NUMCTXS];
opj_mqc_state_t **curctx;
const OPJ_BYTE *lut_ctxno_zc_orient; /* lut_ctxno_zc shifted by 256 * bandno */
#ifdef MQC_PERF_OPT
unsigned char *buffer;
#endif
} opj_mqc_t;
#include "mqc_inl.h"
/** @name Exported functions */
/*@{*/
/* ----------------------------------------------------------------------- */
@ -198,7 +201,7 @@ Decode a symbol
@param mqc MQC handle
@return Returns the decoded symbol (0 or 1)
*/
OPJ_INT32 opj_mqc_decode(opj_mqc_t * const mqc);
static INLINE OPJ_INT32 opj_mqc_decode(opj_mqc_t * const mqc);
/* ----------------------------------------------------------------------- */
/*@}*/

159
src/lib/openjp2/mqc_inl.h Normal file
View File

@ -0,0 +1,159 @@
/*
* The copyright in this software is being made available under the 2-clauses
* BSD License, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such rights
* are granted under this license.
*
* Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2014, Professor Benoit Macq
* Copyright (c) 2001-2003, David Janssens
* Copyright (c) 2002-2003, Yannick Verschueren
* Copyright (c) 2003-2007, Francois-Olivier Devaux
* Copyright (c) 2003-2014, Antonin Descampe
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __MQC_INL_H
#define __MQC_INL_H
/**
FIXME DOC
@param mqc MQC handle
@return
*/
static INLINE OPJ_INT32 opj_mqc_mpsexchange(opj_mqc_t *const mqc) {
OPJ_INT32 d;
if (mqc->a < (*mqc->curctx)->qeval) {
d = (OPJ_INT32)(1 - (*mqc->curctx)->mps);
*mqc->curctx = (*mqc->curctx)->nlps;
} else {
d = (OPJ_INT32)(*mqc->curctx)->mps;
*mqc->curctx = (*mqc->curctx)->nmps;
}
return d;
}
/**
FIXME DOC
@param mqc MQC handle
@return
*/
static INLINE OPJ_INT32 opj_mqc_lpsexchange(opj_mqc_t *const mqc) {
OPJ_INT32 d;
if (mqc->a < (*mqc->curctx)->qeval) {
mqc->a = (*mqc->curctx)->qeval;
d = (OPJ_INT32)(*mqc->curctx)->mps;
*mqc->curctx = (*mqc->curctx)->nmps;
} else {
mqc->a = (*mqc->curctx)->qeval;
d = (OPJ_INT32)(1 - (*mqc->curctx)->mps);
*mqc->curctx = (*mqc->curctx)->nlps;
}
return d;
}
/**
Input a byte
@param mqc MQC handle
*/
#ifdef MQC_PERF_OPT
static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc) {
unsigned int i = *((unsigned int *) mqc->bp);
mqc->c += i & 0xffff00;
mqc->ct = i & 0x0f;
mqc->bp += (i >> 2) & 0x04;
}
#else
static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc) {
if (mqc->bp != mqc->end) {
OPJ_UINT32 c;
if (mqc->bp + 1 != mqc->end) {
c = *(mqc->bp + 1);
} else {
c = 0xff;
}
if (*mqc->bp == 0xff) {
if (c > 0x8f) {
mqc->c += 0xff00;
mqc->ct = 8;
} else {
mqc->bp++;
mqc->c += c << 9;
mqc->ct = 7;
}
} else {
mqc->bp++;
mqc->c += c << 8;
mqc->ct = 8;
}
} else {
mqc->c += 0xff00;
mqc->ct = 8;
}
}
#endif
/**
Renormalize mqc->a and mqc->c while decoding
@param mqc MQC handle
*/
static INLINE void opj_mqc_renormd(opj_mqc_t *const mqc) {
do {
if (mqc->ct == 0) {
opj_mqc_bytein(mqc);
}
mqc->a <<= 1;
mqc->c <<= 1;
mqc->ct--;
} while (mqc->a < 0x8000);
}
/**
Decode a symbol
@param mqc MQC handle
@return Returns the decoded symbol (0 or 1)
*/
static INLINE OPJ_INT32 opj_mqc_decode(opj_mqc_t *const mqc) {
OPJ_INT32 d;
mqc->a -= (*mqc->curctx)->qeval;
if ((mqc->c >> 16) < (*mqc->curctx)->qeval) {
d = opj_mqc_lpsexchange(mqc);
opj_mqc_renormd(mqc);
} else {
mqc->c -= (*mqc->curctx)->qeval << 16;
if ((mqc->a & 0x8000) == 0) {
d = opj_mqc_mpsexchange(mqc);
opj_mqc_renormd(mqc);
} else {
d = (OPJ_INT32)(*mqc->curctx)->mps;
}
}
return d;
}
#endif /* __MQC_INL_H */

View File

@ -239,6 +239,9 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format)
OPJ_UINT32 res_factor,
struct opj_event_mgr * p_manager)) opj_j2k_set_decoded_resolution_factor;
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_decompress();
if (! l_codec->m_codec) {
@ -315,6 +318,9 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format)
OPJ_UINT32 res_factor,
opj_event_mgr_t * p_manager)) opj_jp2_set_decoded_resolution_factor;
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_TRUE);
if (! l_codec->m_codec) {
@ -354,6 +360,18 @@ void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *paramete
}
}
OPJ_BOOL OPJ_CALLCONV opj_codec_set_threads(opj_codec_t *p_codec,
int num_threads)
{
if (p_codec && (num_threads >= 0)) {
opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
return l_codec->opj_set_threads(l_codec->m_codec, (OPJ_UINT32)num_threads);
}
return OPJ_FALSE;
}
OPJ_BOOL OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec,
opj_dparameters_t *parameters
)

View File

@ -1262,6 +1262,25 @@ OPJ_API void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *
OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec,
opj_dparameters_t *parameters );
/**
* Allocates worker threads for the compressor/decompressor.
*
* By default, only the main thread is used. If this function is not used,
* but the OPJ_NUM_THREADS environment variable is set, its value will be
* used to initialize the number of threads. The value can be either an integer
* 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.
*
* Note: currently only has effect on the decompressor.
*
* @param p_codec decompressor handler
* @param num_threads number of threads.
*
* @return OPJ_TRUE if the decoder is correctly set
*/
OPJ_API OPJ_BOOL OPJ_CALLCONV opj_codec_set_threads(opj_codec_t *p_codec,
int num_threads);
/**
* Decodes an image header.
*
@ -1554,6 +1573,19 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_MCT( opj_cparameters_t *parameters,
OPJ_INT32 * p_dc_shift,
OPJ_UINT32 pNbComp);
/*
==========================================================
Thread functions
==========================================================
*/
/** Returns if the library is built with thread support.
* OPJ_TRUE if mutex, condition, thread, thread pool are available.
*/
OPJ_API OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void);
/** Return the number of virtual CPUs */
OPJ_API int OPJ_CALLCONV opj_get_num_cpus(void);
#ifdef __cplusplus

View File

@ -113,6 +113,7 @@ typedef struct opj_codec_private
OPJ_BOOL (*opj_set_decoded_resolution_factor) ( void * p_codec,
OPJ_UINT32 res_factor,
opj_event_mgr_t * p_manager);
} m_decompression;
/**
@ -157,6 +158,9 @@ typedef struct opj_codec_private
void (*opj_dump_codec) (void * p_codec, OPJ_INT32 info_flag, FILE* output_stream);
opj_codestream_info_v2_t* (*opj_get_codec_info)(void* p_codec);
opj_codestream_index_t* (*opj_get_codec_index)(void* p_codec);
/** Set number of threads */
OPJ_BOOL (*opj_set_threads) ( void * p_codec, OPJ_UINT32 num_threads );
}
opj_codec_private_t;

View File

@ -54,6 +54,7 @@
#include <stdarg.h>
#include <ctype.h>
#include <assert.h>
#include <limits.h>
/*
Use fseeko() and ftello() if they are available since they use
@ -183,6 +184,9 @@ static INLINE long opj_lrintf(float f) {
# pragma intrinsic(__emul)
#endif
/* Type to use for bit-fields in internal headers */
typedef unsigned int OPJ_BITFIELD;
#include "opj_inttypes.h"
#include "opj_clock.h"
#include "opj_malloc.h"
@ -191,6 +195,9 @@ static INLINE long opj_lrintf(float f) {
#include "bio.h"
#include "cio.h"
#include "thread.h"
#include "tls_keys.h"
#include "image.h"
#include "invert.h"
#include "j2k.h"

View File

@ -1238,14 +1238,14 @@ opj_pi_iterator_t *opj_pi_create_decode(opj_image_t *p_image,
/* memory allocation for include */
/* prevent an integer overflow issue */
/* 0 < l_tcp->numlayers < 65536 c.f. opj_j2k_read_cod in j2k.c */
l_current_pi->include = 00;
if (l_step_l <= (SIZE_MAX / (l_tcp->numlayers + 1U)))
{
l_current_pi->include = (OPJ_INT16*) opj_calloc((size_t)(l_tcp->numlayers + 1U) * l_step_l, sizeof(OPJ_INT16));
}
if
(!l_current_pi->include)
if (!l_current_pi->include)
{
opj_free(l_tmp_data);
opj_free(l_tmp_ptr);

File diff suppressed because it is too large Load Diff

View File

@ -50,48 +50,74 @@ in T1.C are used by some function in TCD.C.
/* ----------------------------------------------------------------------- */
#define T1_NMSEDEC_BITS 7
#define T1_SIG_NE 0x0001 /**< Context orientation : North-East direction */
#define T1_SIG_SE 0x0002 /**< Context orientation : South-East direction */
#define T1_SIG_SW 0x0004 /**< Context orientation : South-West direction */
#define T1_SIG_NW 0x0008 /**< Context orientation : North-West direction */
#define T1_SIG_N 0x0010 /**< Context orientation : North direction */
#define T1_SIG_E 0x0020 /**< Context orientation : East direction */
#define T1_SIG_S 0x0040 /**< Context orientation : South direction */
#define T1_SIG_W 0x0080 /**< Context orientation : West direction */
/* CAUTION: the value of those constants must not be changed, otherwise the */
/* optimization of opj_t1_updateflags() will break! */
/* BEGINNING of flags that apply to opj_flag_t */
#define T1_SIG_NE 0x0001U /**< Context orientation : North-East direction */
#define T1_SIG_SE 0x0002U /**< Context orientation : South-East direction */
#define T1_SIG_SW 0x0004U /**< Context orientation : South-West direction */
#define T1_SIG_NW 0x0008U /**< Context orientation : North-West direction */
#define T1_SIG_N 0x0010U /**< Context orientation : North direction */
#define T1_SIG_E 0x0020U /**< Context orientation : East direction */
#define T1_SIG_S 0x0040U /**< Context orientation : South direction */
#define T1_SIG_W 0x0080U /**< Context orientation : West direction */
#define T1_SIG_OTH (T1_SIG_N|T1_SIG_NE|T1_SIG_E|T1_SIG_SE|T1_SIG_S|T1_SIG_SW|T1_SIG_W|T1_SIG_NW)
#define T1_SIG_PRIM (T1_SIG_N|T1_SIG_E|T1_SIG_S|T1_SIG_W)
#define T1_SGN_N 0x0100
#define T1_SGN_E 0x0200
#define T1_SGN_S 0x0400
#define T1_SGN_W 0x0800
#define T1_SGN_N 0x0100U
#define T1_SGN_E 0x0200U
#define T1_SGN_S 0x0400U
#define T1_SGN_W 0x0800U
#define T1_SGN (T1_SGN_N|T1_SGN_E|T1_SGN_S|T1_SGN_W)
#define T1_SIG 0x1000
#define T1_REFINE 0x2000
#define T1_VISIT 0x4000
#define T1_SIG 0x1000U /**< No longer used by decoder */
#define T1_REFINE 0x2000U /**< No longer used by decoder */
#define T1_VISIT 0x4000U /**< No longer used by decoder */
/* END of flags that apply to opj_flag_t */
#define T1_NUMCTXS_ZC 9
#define T1_NUMCTXS_SC 5
#define T1_NUMCTXS_ZC 9
#define T1_NUMCTXS_SC 5
#define T1_NUMCTXS_MAG 3
#define T1_NUMCTXS_AGG 1
#define T1_NUMCTXS_UNI 1
#define T1_CTXNO_ZC 0
#define T1_CTXNO_SC (T1_CTXNO_ZC+T1_NUMCTXS_ZC)
#define T1_CTXNO_ZC 0
#define T1_CTXNO_SC (T1_CTXNO_ZC+T1_NUMCTXS_ZC)
#define T1_CTXNO_MAG (T1_CTXNO_SC+T1_NUMCTXS_SC)
#define T1_CTXNO_AGG (T1_CTXNO_MAG+T1_NUMCTXS_MAG)
#define T1_CTXNO_UNI (T1_CTXNO_AGG+T1_NUMCTXS_AGG)
#define T1_NUMCTXS (T1_CTXNO_UNI+T1_NUMCTXS_UNI)
#define T1_NUMCTXS (T1_CTXNO_UNI+T1_NUMCTXS_UNI)
#define T1_NMSEDEC_FRACBITS (T1_NMSEDEC_BITS-1)
#define T1_TYPE_MQ 0 /**< Normal coding using entropy coder */
#define T1_TYPE_RAW 1 /**< No encoding the information is store under raw format in codestream (mode switch RAW)*/
/* Those flags are used by opj_colflag_t */
#define T1_COLFLAG_RBS 4U /* RBS = Row Bit Shift */
#define T1_COLFLAG_SIG_OTHER_ROW_0 (1U << 0U) /**< This sample has at least one significant neighbour */
#define T1_COLFLAG_SIG_ROW_0 (1U << 1U) /**< This sample is significant */
#define T1_COLFLAG_VISIT_ROW_0 (1U << 2U) /**< This sample has been visited */
#define T1_COLFLAG_REFINE_ROW_0 (1U << 3U) /**< This sample has been refined */
#define T1_COLFLAG_SIG_OTHER_ROW_1 (T1_COLFLAG_SIG_OTHER_ROW_0 << (1U * T1_COLFLAG_RBS))
#define T1_COLFLAG_SIG_ROW_1 (T1_COLFLAG_SIG_ROW_0 << (1U * T1_COLFLAG_RBS))
#define T1_COLFLAG_VISIT_ROW_1 (T1_COLFLAG_VISIT_ROW_0 << (1U * T1_COLFLAG_RBS))
#define T1_COLFLAG_REFINE_ROW_1 (T1_COLFLAG_REFINE_ROW_0 << (1U * T1_COLFLAG_RBS))
#define T1_COLFLAG_SIG_OTHER_ROW_2 (T1_COLFLAG_SIG_OTHER_ROW_0 << (2U * T1_COLFLAG_RBS))
#define T1_COLFLAG_SIG_ROW_2 (T1_COLFLAG_SIG_ROW_0 << (2U * T1_COLFLAG_RBS))
#define T1_COLFLAG_VISIT_ROW_2 (T1_COLFLAG_VISIT_ROW_0 << (2U * T1_COLFLAG_RBS))
#define T1_COLFLAG_REFINE_ROW_2 (T1_COLFLAG_REFINE_ROW_0 << (2U * T1_COLFLAG_RBS))
#define T1_COLFLAG_SIG_OTHER_ROW_3 (T1_COLFLAG_SIG_OTHER_ROW_0 << (3U * T1_COLFLAG_RBS))
#define T1_COLFLAG_SIG_ROW_3 (T1_COLFLAG_SIG_ROW_0 << (3U * T1_COLFLAG_RBS))
#define T1_COLFLAG_VISIT_ROW_3 (T1_COLFLAG_VISIT_ROW_0 << (3U * T1_COLFLAG_RBS))
#define T1_COLFLAG_REFINE_ROW_3 (T1_COLFLAG_REFINE_ROW_0 << (3U * T1_COLFLAG_RBS))
/* ----------------------------------------------------------------------- */
typedef OPJ_INT16 opj_flag_t;
typedef OPJ_UINT16 opj_flag_t;
/** Flags for 4 consecutive rows of a column */
typedef OPJ_UINT16 opj_colflag_t;
/**
Tier-1 coding (coding of code-block coefficients)
@ -105,11 +131,17 @@ typedef struct opj_t1 {
OPJ_INT32 *data;
opj_flag_t *flags;
/** Addition flag array such that colflags[1+0] is for state of col=0,row=0..3,
colflags[1+1] for col=1, row=0..3, colflags[1+flags_stride] for col=0,row=4..7, ...
This array avoids too much cache trashing when processing by 4 vertical samples
as done in the various decoding steps. */
opj_colflag_t* colflags;
OPJ_UINT32 w;
OPJ_UINT32 h;
OPJ_UINT32 datasize;
OPJ_UINT32 flagssize;
OPJ_UINT32 flags_stride;
OPJ_UINT32 colflags_size;
OPJ_UINT32 data_stride;
OPJ_BOOL encoder;
} opj_t1_t;
@ -140,7 +172,8 @@ Decode the code-blocks of a tile
@param tilec The tile to decode
@param tccp Tile coding parameters
*/
OPJ_BOOL opj_t1_decode_cblks( opj_t1_t* t1,
void opj_t1_decode_cblks( opj_thread_pool_t* tp,
volatile OPJ_BOOL* pret,
opj_tcd_tilecomp_t* tilec,
opj_tccp_t* tccp);

View File

@ -38,7 +38,7 @@
#include "opj_includes.h"
static int t1_init_ctxno_zc(int f, int orient) {
static int t1_init_ctxno_zc(unsigned int f, unsigned int orient) {
int h, v, d, n, t, hv;
h = ((f & T1_SIG_W) != 0) + ((f & T1_SIG_E) != 0);
v = ((f & T1_SIG_N) != 0) + ((f & T1_SIG_S) != 0);
@ -113,7 +113,7 @@ static int t1_init_ctxno_zc(int f, int orient) {
return (T1_CTXNO_ZC + n);
}
static int t1_init_ctxno_sc(int f) {
static int t1_init_ctxno_sc(unsigned int f) {
int hc, vc, n;
n = 0;
@ -154,7 +154,7 @@ static int t1_init_ctxno_sc(int f) {
return (T1_CTXNO_SC + n);
}
static int t1_init_spb(int f) {
static int t1_init_spb(unsigned int f) {
int hc, vc, n;
hc = opj_int_min(((f & (T1_SIG_E | T1_SGN_E)) ==
@ -192,7 +192,7 @@ static void dump_array16(int array[],int size){
int main(int argc, char **argv)
{
int i, j;
unsigned int i, j;
double u, v, t;
int lut_ctxno_zc[1024];
@ -205,47 +205,47 @@ int main(int argc, char **argv)
printf("/* This file was automatically generated by t1_generate_luts.c */\n\n");
/* lut_ctxno_zc */
for (j = 0; j < 4; ++j) {
for (i = 0; i < 256; ++i) {
int orient = j;
if (orient == 2) {
orient = 1;
} else if (orient == 1) {
orient = 2;
for (j = 0U; j < 4U; ++j) {
for (i = 0U; i < 256U; ++i) {
unsigned int orient = j;
if (orient == 2U) {
orient = 1U;
} else if (orient == 1U) {
orient = 2U;
}
lut_ctxno_zc[(orient << 8) | i] = t1_init_ctxno_zc(i, j);
}
}
printf("static OPJ_BYTE lut_ctxno_zc[1024] = {\n ");
for (i = 0; i < 1023; ++i) {
printf("static const OPJ_BYTE lut_ctxno_zc[1024] = {\n ");
for (i = 0U; i < 1023U; ++i) {
printf("%i, ", lut_ctxno_zc[i]);
if(!((i+1)&0x1f))
if(!((i+1U)&0x1fU))
printf("\n ");
}
printf("%i\n};\n\n", lut_ctxno_zc[1023]);
/* lut_ctxno_sc */
printf("static OPJ_BYTE lut_ctxno_sc[256] = {\n ");
for (i = 0; i < 255; ++i) {
printf("static const OPJ_BYTE lut_ctxno_sc[256] = {\n ");
for (i = 0U; i < 255U; ++i) {
printf("0x%x, ", t1_init_ctxno_sc(i << 4));
if(!((i+1)&0xf))
if(!((i+1U)&0xfU))
printf("\n ");
}
printf("0x%x\n};\n\n", t1_init_ctxno_sc(255 << 4));
printf("0x%x\n};\n\n", t1_init_ctxno_sc(255U << 4));
/* lut_spb */
printf("static OPJ_BYTE lut_spb[256] = {\n ");
for (i = 0; i < 255; ++i) {
printf("static const OPJ_BYTE lut_spb[256] = {\n ");
for (i = 0U; i < 255U; ++i) {
printf("%i, ", t1_init_spb(i << 4));
if(!((i+1)&0x1f))
if(!((i+1U)&0x1fU))
printf("\n ");
}
printf("%i\n};\n\n", t1_init_spb(255 << 4));
printf("%i\n};\n\n", t1_init_spb(255U << 4));
/* FIXME FIXME FIXME */
/* fprintf(stdout,"nmsedec luts:\n"); */
for (i = 0; i < (1 << T1_NMSEDEC_BITS); ++i) {
for (i = 0U; i < (1U << T1_NMSEDEC_BITS); ++i) {
t = i / pow(2, T1_NMSEDEC_FRACBITS);
u = t;
v = t - 1.5;
@ -269,17 +269,17 @@ int main(int argc, char **argv)
(int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0));
}
printf("static OPJ_INT16 lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = {\n ");
dump_array16(lut_nmsedec_sig, 1 << T1_NMSEDEC_BITS);
printf("static const OPJ_INT16 lut_nmsedec_sig[1U << T1_NMSEDEC_BITS] = {\n ");
dump_array16(lut_nmsedec_sig, 1U << T1_NMSEDEC_BITS);
printf("static OPJ_INT16 lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = {\n ");
dump_array16(lut_nmsedec_sig0, 1 << T1_NMSEDEC_BITS);
printf("static const OPJ_INT16 lut_nmsedec_sig0[1U << T1_NMSEDEC_BITS] = {\n ");
dump_array16(lut_nmsedec_sig0, 1U << T1_NMSEDEC_BITS);
printf("static OPJ_INT16 lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = {\n ");
dump_array16(lut_nmsedec_ref, 1 << T1_NMSEDEC_BITS);
printf("static const OPJ_INT16 lut_nmsedec_ref[1U << T1_NMSEDEC_BITS] = {\n ");
dump_array16(lut_nmsedec_ref, 1U << T1_NMSEDEC_BITS);
printf("static OPJ_INT16 lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = {\n ");
dump_array16(lut_nmsedec_ref0, 1 << T1_NMSEDEC_BITS);
printf("static const OPJ_INT16 lut_nmsedec_ref0[1U << T1_NMSEDEC_BITS] = {\n ");
dump_array16(lut_nmsedec_ref0, 1U << T1_NMSEDEC_BITS);
return 0;
}

View File

@ -1,6 +1,6 @@
/* This file was automatically generated by t1_generate_luts.c */
static OPJ_BYTE lut_ctxno_zc[1024] = {
static const OPJ_BYTE lut_ctxno_zc[1024] = {
0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
@ -35,7 +35,7 @@ static OPJ_BYTE lut_ctxno_zc[1024] = {
2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8
};
static OPJ_BYTE lut_ctxno_sc[256] = {
static const OPJ_BYTE lut_ctxno_sc[256] = {
0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd,
0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc,
0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa,
@ -54,7 +54,7 @@ static OPJ_BYTE lut_ctxno_sc[256] = {
0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd
};
static OPJ_BYTE lut_spb[256] = {
static const OPJ_BYTE lut_spb[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -65,7 +65,7 @@ static OPJ_BYTE lut_spb[256] = {
0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
static OPJ_INT16 lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = {
static const OPJ_INT16 lut_nmsedec_sig[1U << T1_NMSEDEC_BITS] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@ -84,7 +84,7 @@ static OPJ_INT16 lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = {
0x6c00, 0x6d80, 0x6f00, 0x7080, 0x7200, 0x7380, 0x7500, 0x7680
};
static OPJ_INT16 lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = {
static const OPJ_INT16 lut_nmsedec_sig0[1U << T1_NMSEDEC_BITS] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080,
0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200,
0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400,
@ -103,7 +103,7 @@ static OPJ_INT16 lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = {
0x7080, 0x7280, 0x7480, 0x7600, 0x7800, 0x7a00, 0x7c00, 0x7e00
};
static OPJ_INT16 lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = {
static const OPJ_INT16 lut_nmsedec_ref[1U << T1_NMSEDEC_BITS] = {
0x1800, 0x1780, 0x1700, 0x1680, 0x1600, 0x1580, 0x1500, 0x1480,
0x1400, 0x1380, 0x1300, 0x1280, 0x1200, 0x1180, 0x1100, 0x1080,
0x1000, 0x0f80, 0x0f00, 0x0e80, 0x0e00, 0x0d80, 0x0d00, 0x0c80,
@ -122,7 +122,7 @@ static OPJ_INT16 lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = {
0x1400, 0x1480, 0x1500, 0x1580, 0x1600, 0x1680, 0x1700, 0x1780
};
static OPJ_INT16 lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = {
static const OPJ_INT16 lut_nmsedec_ref0[1U << T1_NMSEDEC_BITS] = {
0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x1b00, 0x1a80, 0x1980,
0x1880, 0x1780, 0x1700, 0x1600, 0x1500, 0x1480, 0x1380, 0x1300,
0x1200, 0x1180, 0x1080, 0x1000, 0x0f00, 0x0e80, 0x0e00, 0x0d00,

View File

@ -580,7 +580,8 @@ OPJ_BOOL opj_tcd_rateallocate( opj_tcd_t *tcd,
OPJ_BOOL opj_tcd_init( opj_tcd_t *p_tcd,
opj_image_t * p_image,
opj_cp_t * p_cp )
opj_cp_t * p_cp,
opj_thread_pool_t* p_tp )
{
p_tcd->image = p_image;
p_tcd->cp = p_cp;
@ -597,6 +598,7 @@ OPJ_BOOL opj_tcd_init( opj_tcd_t *p_tcd,
p_tcd->tcd_image->tiles->numcomps = p_image->numcomps;
p_tcd->tp_pos = p_cp->m_specific_param.m_enc.m_tp_pos;
p_tcd->thread_pool = p_tp;
return OPJ_TRUE;
}
@ -1588,30 +1590,22 @@ static OPJ_BOOL opj_tcd_t2_decode (opj_tcd_t *p_tcd,
static OPJ_BOOL opj_tcd_t1_decode ( opj_tcd_t *p_tcd )
{
OPJ_UINT32 compno;
opj_t1_t * l_t1;
opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles;
opj_tcd_tilecomp_t* l_tile_comp = l_tile->comps;
opj_tccp_t * l_tccp = p_tcd->tcp->tccps;
l_t1 = opj_t1_create(OPJ_FALSE);
if (l_t1 == 00) {
return OPJ_FALSE;
}
volatile OPJ_BOOL ret = OPJ_TRUE;
for (compno = 0; compno < l_tile->numcomps; ++compno) {
/* The +3 is headroom required by the vectorized DWT */
if (OPJ_FALSE == opj_t1_decode_cblks(l_t1, l_tile_comp, l_tccp)) {
opj_t1_destroy(l_t1);
return OPJ_FALSE;
}
opj_t1_decode_cblks(p_tcd->thread_pool, &ret, l_tile_comp, l_tccp);
if( !ret )
break;
++l_tile_comp;
++l_tccp;
}
opj_t1_destroy(l_t1);
opj_thread_pool_wait_completion(p_tcd->thread_pool, 0);
return OPJ_TRUE;
return ret;
}
@ -1638,7 +1632,7 @@ static OPJ_BOOL opj_tcd_dwt_decode ( opj_tcd_t *p_tcd )
*/
if (l_tccp->qmfbid == 1) {
if (! opj_dwt_decode(l_tile_comp, l_img_comp->resno_decoded+1)) {
if (! opj_dwt_decode(p_tcd->thread_pool, l_tile_comp, l_img_comp->resno_decoded+1)) {
return OPJ_FALSE;
}
}

View File

@ -70,7 +70,7 @@ typedef struct opj_tcd_pass {
OPJ_UINT32 rate;
OPJ_FLOAT64 distortiondec;
OPJ_UINT32 len;
OPJ_UINT32 term : 1;
OPJ_BITFIELD term : 1;
} opj_tcd_pass_t;
/**
@ -219,7 +219,9 @@ typedef struct opj_tcd
/** current encoded/decoded tile */
OPJ_UINT32 tcd_tileno;
/** tell if the tcd is a decoder. */
OPJ_UINT32 m_is_decoder : 1;
OPJ_BITFIELD m_is_decoder : 1;
/** Thread pool */
opj_thread_pool_t* thread_pool;
} opj_tcd_t;
/** @name Exported functions */
@ -249,12 +251,14 @@ void opj_tcd_destroy(opj_tcd_t *tcd);
* @param p_tcd TCD handle.
* @param p_image raw image.
* @param p_cp coding parameters.
* @param p_tp thread pool
*
* @return true if the encoding values could be set (false otherwise).
*/
OPJ_BOOL opj_tcd_init( opj_tcd_t *p_tcd,
opj_image_t * p_image,
opj_cp_t * p_cp );
opj_cp_t * p_cp,
opj_thread_pool_t* p_tp);
/**
* Allocates memory for decoding a specific tile.

968
src/lib/openjp2/thread.c Normal file
View File

@ -0,0 +1,968 @@
/*
* The copyright in this software is being made available under the 2-clauses
* BSD License, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such rights
* are granted under this license.
*
* Copyright (c) 2016, Even Rouault
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "opj_includes.h"
#include "thread.h"
#include <assert.h>
#ifdef MUTEX_win32
/* Some versions of x86_64-w64-mingw32-gc -m32 resolve InterlockedCompareExchange() */
/* as __sync_val_compare_and_swap_4 but fails to link it. As this protects against */
/* a rather unlikely race, skip it */
#if !(defined(__MINGW32__) && defined(__i386__))
#define HAVE_INTERLOCKED_COMPARE_EXCHANGE 1
#endif
#include <windows.h>
#include <process.h>
OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void)
{
return OPJ_TRUE;
}
int OPJ_CALLCONV opj_get_num_cpus(void)
{
SYSTEM_INFO info;
DWORD dwNum;
GetSystemInfo(&info);
dwNum = info.dwNumberOfProcessors;
if( dwNum < 1 )
return 1;
return (int)dwNum;
}
struct opj_mutex_t
{
CRITICAL_SECTION cs;
};
opj_mutex_t* opj_mutex_create(void)
{
opj_mutex_t* mutex = (opj_mutex_t*) opj_malloc(sizeof(opj_mutex_t));
if( !mutex )
return NULL;
InitializeCriticalSectionAndSpinCount(&(mutex->cs), 4000);
return mutex;
}
void opj_mutex_lock(opj_mutex_t* mutex)
{
EnterCriticalSection( &(mutex->cs) );
}
void opj_mutex_unlock(opj_mutex_t* mutex)
{
LeaveCriticalSection( &(mutex->cs) );
}
void opj_mutex_destroy(opj_mutex_t* mutex)
{
if( !mutex ) return;
DeleteCriticalSection( &(mutex->cs) );
opj_free( mutex );
}
struct opj_cond_waiter_list_t
{
HANDLE hEvent;
struct opj_cond_waiter_list_t* next;
};
typedef struct opj_cond_waiter_list_t opj_cond_waiter_list_t;
struct opj_cond_t
{
opj_mutex_t *internal_mutex;
opj_cond_waiter_list_t *waiter_list;
};
static DWORD TLSKey = 0;
static volatile LONG inTLSLockedSection = 0;
static volatile int TLSKeyInit = OPJ_FALSE;
opj_cond_t* opj_cond_create(void)
{
opj_cond_t* cond = (opj_cond_t*) opj_malloc(sizeof(opj_cond_t));
if( !cond )
return NULL;
/* Make sure that the TLS key is allocated in a thread-safe way */
/* We cannot use a global mutex/critical section since its creation itself would not be */
/* thread-safe, so use InterlockedCompareExchange trick */
while( OPJ_TRUE )
{
#if HAVE_INTERLOCKED_COMPARE_EXCHANGE
if( InterlockedCompareExchange(&inTLSLockedSection, 1, 0) == 0 )
#endif
{
if( !TLSKeyInit )
{
TLSKey = TlsAlloc();
TLSKeyInit = OPJ_TRUE;
}
#if HAVE_INTERLOCKED_COMPARE_EXCHANGE
InterlockedCompareExchange(&inTLSLockedSection, 0, 1);
#endif
break;
}
}
if( TLSKey == TLS_OUT_OF_INDEXES )
{
opj_free(cond);
return NULL;
}
cond->internal_mutex = opj_mutex_create();
if (cond->internal_mutex == NULL)
{
opj_free(cond);
return NULL;
}
cond->waiter_list = NULL;
return cond;
}
void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex)
{
opj_cond_waiter_list_t* item;
HANDLE hEvent = (HANDLE) TlsGetValue( TLSKey );
if (hEvent == NULL)
{
hEvent = CreateEvent(NULL, /* security attributes */
0, /* manual reset = no */
0, /* initial state = unsignaled */
NULL /* no name */);
assert(hEvent);
TlsSetValue( TLSKey, hEvent );
}
/* Insert the waiter into the waiter list of the condition */
opj_mutex_lock(cond->internal_mutex);
item = (opj_cond_waiter_list_t*)opj_malloc(sizeof(opj_cond_waiter_list_t));
assert(item != NULL);
item->hEvent = hEvent;
item->next = cond->waiter_list;
cond->waiter_list = item;
opj_mutex_unlock(cond->internal_mutex);
/* Release the client mutex before waiting for the event being signaled */
opj_mutex_unlock(mutex);
/* Ideally we would check that we do not get WAIT_FAILED but it is hard */
/* to report a failure. */
WaitForSingleObject(hEvent, INFINITE);
/* Reacquire the client mutex */
opj_mutex_lock(mutex);
}
void opj_cond_signal(opj_cond_t* cond)
{
opj_cond_waiter_list_t* psIter;
/* Signal the first registered event, and remove it from the list */
opj_mutex_lock(cond->internal_mutex);
psIter = cond->waiter_list;
if (psIter != NULL)
{
SetEvent(psIter->hEvent);
cond->waiter_list = psIter->next;
opj_free(psIter);
}
opj_mutex_unlock(cond->internal_mutex);
}
void opj_cond_destroy(opj_cond_t* cond)
{
if( !cond ) return;
opj_mutex_destroy(cond->internal_mutex);
assert(cond->waiter_list == NULL);
opj_free(cond);
}
struct opj_thread_t
{
opj_thread_fn thread_fn;
void* user_data;
HANDLE hThread;
};
unsigned int __stdcall opj_thread_callback_adapter( void *info )
{
opj_thread_t* thread = (opj_thread_t*) info;
HANDLE hEvent = NULL;
thread->thread_fn( thread->user_data );
/* Free the handle possible allocated by a cond */
while( OPJ_TRUE )
{
/* Make sure TLSKey is not being created just at that moment... */
#if HAVE_INTERLOCKED_COMPARE_EXCHANGE
if( InterlockedCompareExchange(&inTLSLockedSection, 1, 0) == 0 )
#endif
{
if( TLSKeyInit )
{
hEvent = (HANDLE) TlsGetValue( TLSKey );
}
#if HAVE_INTERLOCKED_COMPARE_EXCHANGE
InterlockedCompareExchange(&inTLSLockedSection, 0, 1);
#endif
break;
}
}
if( hEvent )
CloseHandle(hEvent);
return 0;
}
opj_thread_t* opj_thread_create( opj_thread_fn thread_fn, void* user_data )
{
opj_thread_t* thread;
assert( thread_fn );
thread = (opj_thread_t*) opj_malloc( sizeof(opj_thread_t) );
if( !thread )
return NULL;
thread->thread_fn = thread_fn;
thread->user_data = user_data;
thread->hThread = (HANDLE)_beginthreadex(NULL, 0,
opj_thread_callback_adapter, thread, 0, NULL);
if( thread->hThread == NULL )
{
opj_free( thread );
return NULL;
}
return thread;
}
void opj_thread_join( opj_thread_t* thread )
{
WaitForSingleObject(thread->hThread, INFINITE);
CloseHandle( thread->hThread );
opj_free(thread);
}
#elif MUTEX_pthread
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void)
{
return OPJ_TRUE;
}
int OPJ_CALLCONV opj_get_num_cpus(void)
{
#ifdef _SC_NPROCESSORS_ONLN
return (int)sysconf(_SC_NPROCESSORS_ONLN);
#else
return 1;
#endif
}
struct opj_mutex_t
{
pthread_mutex_t mutex;
};
opj_mutex_t* opj_mutex_create(void)
{
opj_mutex_t* mutex = (opj_mutex_t*) opj_calloc(1U, sizeof(opj_mutex_t));
if( mutex != NULL ) {
if ( pthread_mutex_init(&mutex->mutex, NULL) != 0) {
opj_free(mutex);
mutex = NULL;
}
}
return mutex;
}
void opj_mutex_lock(opj_mutex_t* mutex)
{
pthread_mutex_lock(&(mutex->mutex));
}
void opj_mutex_unlock(opj_mutex_t* mutex)
{
pthread_mutex_unlock(&(mutex->mutex));
}
void opj_mutex_destroy(opj_mutex_t* mutex)
{
if( !mutex ) return;
pthread_mutex_destroy(&(mutex->mutex));
opj_free(mutex);
}
struct opj_cond_t
{
pthread_cond_t cond;
};
opj_cond_t* opj_cond_create(void)
{
opj_cond_t* cond = (opj_cond_t*) opj_malloc(sizeof(opj_cond_t));
if( !cond )
return NULL;
if( pthread_cond_init(&(cond->cond), NULL) != 0 )
{
opj_free(cond);
return NULL;
}
return cond;
}
void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex)
{
pthread_cond_wait(&(cond->cond), &(mutex->mutex));
}
void opj_cond_signal(opj_cond_t* cond)
{
int ret = pthread_cond_signal(&(cond->cond));
(void)ret;
assert(ret == 0);
}
void opj_cond_destroy(opj_cond_t* cond)
{
if( !cond ) return;
pthread_cond_destroy(&(cond->cond));
opj_free(cond);
}
struct opj_thread_t
{
opj_thread_fn thread_fn;
void* user_data;
pthread_t thread;
};
static void* opj_thread_callback_adapter( void* info )
{
opj_thread_t* thread = (opj_thread_t*) info;
thread->thread_fn( thread->user_data );
return NULL;
}
opj_thread_t* opj_thread_create( opj_thread_fn thread_fn, void* user_data )
{
pthread_attr_t attr;
opj_thread_t* thread;
assert( thread_fn );
thread = (opj_thread_t*) opj_malloc( sizeof(opj_thread_t) );
if( !thread )
return NULL;
thread->thread_fn = thread_fn;
thread->user_data = user_data;
pthread_attr_init( &attr );
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
if( pthread_create( &(thread->thread), &attr,
opj_thread_callback_adapter, (void *) thread ) != 0 )
{
opj_free( thread );
return NULL;
}
return thread;
}
void opj_thread_join( opj_thread_t* thread )
{
void* status;
pthread_join( thread->thread, &status);
opj_free(thread);
}
#else
/* Stub implementation */
OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void)
{
return OPJ_FALSE;
}
int OPJ_CALLCONV opj_get_num_cpus(void)
{
return 1;
}
opj_mutex_t* opj_mutex_create(void)
{
return NULL;
}
void opj_mutex_lock(opj_mutex_t* mutex)
{
(void) mutex;
}
void opj_mutex_unlock(opj_mutex_t* mutex)
{
(void) mutex;
}
void opj_mutex_destroy(opj_mutex_t* mutex)
{
(void) mutex;
}
opj_cond_t* opj_cond_create(void)
{
return NULL;
}
void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex)
{
(void) cond;
(void) mutex;
}
void opj_cond_signal(opj_cond_t* cond)
{
(void) cond;
}
void opj_cond_destroy(opj_cond_t* cond)
{
(void) cond;
}
opj_thread_t* opj_thread_create( opj_thread_fn thread_fn, void* user_data )
{
(void) thread_fn;
(void) user_data;
return NULL;
}
void opj_thread_join( opj_thread_t* thread )
{
(void) thread;
}
#endif
typedef struct
{
int key;
void* value;
opj_tls_free_func opj_free_func;
} opj_tls_key_val_t;
struct opj_tls_t
{
opj_tls_key_val_t* key_val;
int key_val_count;
};
static opj_tls_t* opj_tls_new(void)
{
return (opj_tls_t*) opj_calloc(1, sizeof(opj_tls_t));
}
static void opj_tls_destroy(opj_tls_t* tls)
{
int i;
if( !tls ) return;
for(i=0;i<tls->key_val_count;i++)
{
if( tls->key_val[i].opj_free_func )
tls->key_val[i].opj_free_func(tls->key_val[i].value);
}
opj_free(tls->key_val);
opj_free(tls);
}
void* opj_tls_get(opj_tls_t* tls, int key)
{
int i;
for(i=0;i<tls->key_val_count;i++)
{
if( tls->key_val[i].key == key )
return tls->key_val[i].value;
}
return NULL;
}
OPJ_BOOL opj_tls_set(opj_tls_t* tls, int key, void* value, opj_tls_free_func opj_free_func)
{
opj_tls_key_val_t* new_key_val;
int i;
if (tls->key_val_count == INT_MAX) {
return OPJ_FALSE;
}
for(i=0;i<tls->key_val_count;i++)
{
if( tls->key_val[i].key == key )
{
if( tls->key_val[i].opj_free_func ) {
tls->key_val[i].opj_free_func(tls->key_val[i].value);
}
tls->key_val[i].value = value;
tls->key_val[i].opj_free_func = opj_free_func;
return OPJ_TRUE;
}
}
new_key_val = (opj_tls_key_val_t*) opj_realloc( tls->key_val,
((size_t)tls->key_val_count + 1U) * sizeof(opj_tls_key_val_t) );
if( !new_key_val )
return OPJ_FALSE;
tls->key_val = new_key_val;
new_key_val[tls->key_val_count].key = key;
new_key_val[tls->key_val_count].value = value;
new_key_val[tls->key_val_count].opj_free_func = opj_free_func;
tls->key_val_count ++;
return OPJ_TRUE;
}
typedef struct
{
opj_job_fn job_fn;
void *user_data;
} opj_worker_thread_job_t;
typedef struct
{
opj_thread_pool_t *tp;
opj_thread_t *thread;
int marked_as_waiting;
opj_mutex_t *mutex;
opj_cond_t *cond;
} opj_worker_thread_t;
typedef enum
{
OPJWTS_OK,
OPJWTS_STOP,
OPJWTS_ERROR
} opj_worker_thread_state;
struct opj_job_list_t
{
opj_worker_thread_job_t* job;
struct opj_job_list_t* next;
};
typedef struct opj_job_list_t opj_job_list_t;
struct opj_worker_thread_list_t
{
opj_worker_thread_t* worker_thread;
struct opj_worker_thread_list_t* next;
};
typedef struct opj_worker_thread_list_t opj_worker_thread_list_t;
struct opj_thread_pool_t
{
opj_worker_thread_t* worker_threads;
int worker_threads_count;
opj_cond_t* cond;
opj_mutex_t* mutex;
volatile opj_worker_thread_state state;
opj_job_list_t* job_queue;
volatile int pending_jobs_count;
opj_worker_thread_list_t* waiting_worker_thread_list;
int waiting_worker_thread_count;
opj_tls_t* tls;
int signaling_threshold;
};
static OPJ_BOOL opj_thread_pool_setup(opj_thread_pool_t* tp, int num_threads);
static opj_worker_thread_job_t* opj_thread_pool_get_next_job(opj_thread_pool_t* tp,
opj_worker_thread_t* worker_thread,
OPJ_BOOL signal_job_finished);
opj_thread_pool_t* opj_thread_pool_create(int num_threads)
{
opj_thread_pool_t* tp;
tp = (opj_thread_pool_t*) opj_calloc(1, sizeof(opj_thread_pool_t));
if( !tp )
return NULL;
tp->state = OPJWTS_OK;
if( num_threads <= 0 )
{
tp->tls = opj_tls_new();
if( !tp->tls )
{
opj_free(tp);
tp = NULL;
}
return tp;
}
tp->mutex = opj_mutex_create();
if( !tp->mutex )
{
opj_free(tp);
return NULL;
}
if( !opj_thread_pool_setup(tp, num_threads) )
{
opj_thread_pool_destroy(tp);
return NULL;
}
return tp;
}
static void opj_worker_thread_function(void* user_data)
{
opj_worker_thread_t* worker_thread;
opj_thread_pool_t* tp;
opj_tls_t* tls;
OPJ_BOOL job_finished = OPJ_FALSE;
worker_thread = (opj_worker_thread_t* ) user_data;
tp = worker_thread->tp;
tls = opj_tls_new();
while( OPJ_TRUE )
{
opj_worker_thread_job_t* job = opj_thread_pool_get_next_job(tp, worker_thread, job_finished);
if( job == NULL )
break;
if( job->job_fn )
{
job->job_fn(job->user_data, tls);
}
opj_free(job);
job_finished = OPJ_TRUE;
}
opj_tls_destroy(tls);
}
static OPJ_BOOL opj_thread_pool_setup(opj_thread_pool_t* tp, int num_threads)
{
int i;
OPJ_BOOL bRet = OPJ_TRUE;
assert( num_threads > 0 );
tp->cond = opj_cond_create();
if( tp->cond == NULL )
return OPJ_FALSE;
tp->worker_threads = (opj_worker_thread_t*) opj_calloc( (size_t)num_threads,
sizeof(opj_worker_thread_t) );
if( tp->worker_threads == NULL )
return OPJ_FALSE;
tp->worker_threads_count = num_threads;
for(i=0;i<num_threads;i++)
{
tp->worker_threads[i].tp = tp;
tp->worker_threads[i].mutex = opj_mutex_create();
if( tp->worker_threads[i].mutex == NULL )
{
tp->worker_threads_count = i;
bRet = OPJ_FALSE;
break;
}
tp->worker_threads[i].cond = opj_cond_create();
if( tp->worker_threads[i].cond == NULL )
{
opj_mutex_destroy(tp->worker_threads[i].mutex);
tp->worker_threads_count = i;
bRet = OPJ_FALSE;
break;
}
tp->worker_threads[i].marked_as_waiting = OPJ_FALSE;
tp->worker_threads[i].thread = opj_thread_create(opj_worker_thread_function,
&(tp->worker_threads[i]));
if( tp->worker_threads[i].thread == NULL )
{
tp->worker_threads_count = i;
bRet = OPJ_FALSE;
break;
}
}
/* Wait all threads to be started */
/* printf("waiting for all threads to be started\n"); */
opj_mutex_lock(tp->mutex);
while( tp->waiting_worker_thread_count < num_threads )
{
opj_cond_wait(tp->cond, tp->mutex);
}
opj_mutex_unlock(tp->mutex);
/* printf("all threads started\n"); */
if( tp->state == OPJWTS_ERROR )
bRet = OPJ_FALSE;
return bRet;
}
/*
void opj_waiting()
{
printf("waiting!\n");
}
*/
static opj_worker_thread_job_t* opj_thread_pool_get_next_job(opj_thread_pool_t* tp,
opj_worker_thread_t* worker_thread,
OPJ_BOOL signal_job_finished)
{
while( OPJ_TRUE )
{
opj_job_list_t* top_job_iter;
opj_mutex_lock(tp->mutex);
if( signal_job_finished )
{
signal_job_finished = OPJ_FALSE;
tp->pending_jobs_count --;
/*printf("tp=%p, remaining jobs: %d\n", tp, tp->pending_jobs_count);*/
if( tp->pending_jobs_count <= tp->signaling_threshold )
opj_cond_signal(tp->cond);
}
if( tp->state == OPJWTS_STOP )
{
opj_mutex_unlock(tp->mutex);
return NULL;
}
top_job_iter = tp->job_queue;
if( top_job_iter )
{
opj_worker_thread_job_t* job;
tp->job_queue = top_job_iter->next;
job = top_job_iter->job;
opj_mutex_unlock(tp->mutex);
opj_free(top_job_iter);
return job;
}
/* opj_waiting(); */
if( !worker_thread->marked_as_waiting )
{
opj_worker_thread_list_t* item;
worker_thread->marked_as_waiting = OPJ_TRUE;
tp->waiting_worker_thread_count ++;
assert(tp->waiting_worker_thread_count <= tp->worker_threads_count);
item= (opj_worker_thread_list_t*) opj_malloc(sizeof(opj_worker_thread_list_t));
if( item == NULL )
{
tp->state = OPJWTS_ERROR;
opj_cond_signal(tp->cond);
opj_mutex_unlock(tp->mutex);
return NULL;
}
item->worker_thread = worker_thread;
item->next = tp->waiting_worker_thread_list;
tp->waiting_worker_thread_list = item;
}
/* printf("signaling that worker thread is ready\n"); */
opj_cond_signal(tp->cond);
opj_mutex_lock(worker_thread->mutex);
opj_mutex_unlock(tp->mutex);
/* printf("waiting for job\n"); */
opj_cond_wait( worker_thread->cond, worker_thread->mutex );
opj_mutex_unlock(worker_thread->mutex);
/* printf("got job\n"); */
}
}
OPJ_BOOL opj_thread_pool_submit_job(opj_thread_pool_t* tp,
opj_job_fn job_fn,
void* user_data)
{
opj_worker_thread_job_t* job;
opj_job_list_t* item;
if( tp->mutex == NULL )
{
job_fn( user_data, tp->tls );
return OPJ_TRUE;
}
job = (opj_worker_thread_job_t*)opj_malloc(sizeof(opj_worker_thread_job_t));
if( job == NULL )
return OPJ_FALSE;
job->job_fn = job_fn;
job->user_data = user_data;
item = (opj_job_list_t*) opj_malloc(sizeof(opj_job_list_t));
if( item == NULL )
{
opj_free(job);
return OPJ_FALSE;
}
item->job = job;
opj_mutex_lock(tp->mutex);
tp->signaling_threshold = 100 * tp->worker_threads_count;
while( tp->pending_jobs_count > tp->signaling_threshold )
{
/* printf("%d jobs enqueued. Waiting\n", tp->pending_jobs_count); */
opj_cond_wait(tp->cond, tp->mutex);
/* printf("...%d jobs enqueued.\n", tp->pending_jobs_count); */
}
item->next = tp->job_queue;
tp->job_queue = item;
tp->pending_jobs_count ++;
if( tp->waiting_worker_thread_list )
{
opj_worker_thread_t* worker_thread;
opj_worker_thread_list_t* next;
opj_worker_thread_list_t* to_opj_free;
worker_thread = tp->waiting_worker_thread_list->worker_thread;
assert( worker_thread->marked_as_waiting );
worker_thread->marked_as_waiting = OPJ_FALSE;
next = tp->waiting_worker_thread_list->next;
to_opj_free = tp->waiting_worker_thread_list;
tp->waiting_worker_thread_list = next;
tp->waiting_worker_thread_count --;
opj_mutex_lock(worker_thread->mutex);
opj_mutex_unlock(tp->mutex);
opj_cond_signal(worker_thread->cond);
opj_mutex_unlock(worker_thread->mutex);
opj_free(to_opj_free);
}
else
opj_mutex_unlock(tp->mutex);
return OPJ_TRUE;
}
void opj_thread_pool_wait_completion(opj_thread_pool_t* tp, int max_remaining_jobs)
{
if( tp->mutex == NULL )
{
return;
}
if( max_remaining_jobs < 0 )
max_remaining_jobs = 0;
opj_mutex_lock(tp->mutex);
tp->signaling_threshold = max_remaining_jobs;
while( tp->pending_jobs_count > max_remaining_jobs )
{
/*printf("tp=%p, jobs before wait = %d, max_remaining_jobs = %d\n", tp, tp->pending_jobs_count, max_remaining_jobs);*/
opj_cond_wait(tp->cond, tp->mutex);
/*printf("tp=%p, jobs after wait = %d\n", tp, tp->pending_jobs_count);*/
}
opj_mutex_unlock(tp->mutex);
}
int opj_thread_pool_get_thread_count(opj_thread_pool_t* tp)
{
return tp->worker_threads_count;
}
void opj_thread_pool_destroy(opj_thread_pool_t* tp)
{
if( !tp ) return;
if( tp->cond )
{
int i;
opj_thread_pool_wait_completion(tp, 0);
opj_mutex_lock(tp->mutex);
tp->state = OPJWTS_STOP;
opj_mutex_unlock(tp->mutex);
for(i=0;i<tp->worker_threads_count;i++)
{
opj_mutex_lock(tp->worker_threads[i].mutex);
opj_cond_signal(tp->worker_threads[i].cond);
opj_mutex_unlock(tp->worker_threads[i].mutex);
opj_thread_join(tp->worker_threads[i].thread);
opj_cond_destroy(tp->worker_threads[i].cond);
opj_mutex_destroy(tp->worker_threads[i].mutex);
}
opj_free(tp->worker_threads);
while( tp->waiting_worker_thread_list != NULL )
{
opj_worker_thread_list_t* next = tp->waiting_worker_thread_list->next;
opj_free( tp->waiting_worker_thread_list );
tp->waiting_worker_thread_list = next;
}
opj_cond_destroy(tp->cond);
}
opj_mutex_destroy(tp->mutex);
opj_tls_destroy(tp->tls);
opj_free(tp);
}

253
src/lib/openjp2/thread.h Normal file
View File

@ -0,0 +1,253 @@
/*
* The copyright in this software is being made available under the 2-clauses
* BSD License, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such rights
* are granted under this license.
*
* Copyright (c) 2016, Even Rouault
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef THREAD_H
#define THREAD_H
#include "openjpeg.h"
/**
@file thread.h
@brief Thread API
The functions in thread.c have for goal to manage mutex, conditions, thread
creation and thread pools that accept jobs.
*/
/** @defgroup THREAD THREAD - Mutex, conditions, threads and thread pools */
/*@{*/
/** @name Mutex */
/*@{*/
/** Opaque type for a mutex */
typedef struct opj_mutex_t opj_mutex_t;
/** Creates a mutex.
* @return the mutex or NULL in case of error (can for example happen if the library
* is built without thread support)
*/
opj_mutex_t* opj_mutex_create(void);
/** Lock/acquire the mutex.
* @param mutex the mutex to acquire.
*/
void opj_mutex_lock(opj_mutex_t* mutex);
/** Unlock/release the mutex.
* @param mutex the mutex to release.
*/
void opj_mutex_unlock(opj_mutex_t* mutex);
/** Destroy a mutex
* @param mutex the mutex to destroy.
*/
void opj_mutex_destroy(opj_mutex_t* mutex);
/*@}*/
/** @name Condition */
/*@{*/
/** Opaque type for a condition */
typedef struct opj_cond_t opj_cond_t;
/** Creates a condition.
* @return the condition or NULL in case of error (can for example happen if the library
* is built without thread support)
*/
opj_cond_t* opj_cond_create(void);
/** Wait for the condition to be signaled.
* The semantics is the same as the POSIX pthread_cond_wait.
* The provided mutex *must* be acquired before calling this function, and
* released afterwards.
* The mutex will be released by this function while it must wait for the condition
* and reacquired afterwards.
* In some particular situations, the function might return even if the condition is not signaled
* with opj_cond_signal(), hence the need to check with an application level
* mechanism.
*
* Waiting thread :
* \code
* opj_mutex_lock(mutex);
* while( !some_application_level_condition )
* {
* opj_cond_wait(cond, mutex);
* }
* opj_mutex_unlock(mutex);
* \endcode
*
* Signaling thread :
* \code
* opj_mutex_lock(mutex);
* some_application_level_condition = TRUE;
* opj_cond_signal(cond);
* opj_mutex_unlock(mutex);
* \endcode
*
* @param cond the condition to wait.
* @param mutex the mutex (in acquired state before calling this function)
*/
void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex);
/** Signal waiting threads on a condition.
* One of the thread waiting with opj_cond_wait() will be waken up.
* It is strongly advised that this call is done with the mutex that is used
* by opj_cond_wait(), in a acquired state.
* @param cond the condition to signal.
*/
void opj_cond_signal(opj_cond_t* cond);
/** Destroy a condition
* @param cond the condition to destroy.
*/
void opj_cond_destroy(opj_cond_t* cond);
/*@}*/
/** @name Thread */
/*@{*/
/** Opaque type for a thread handle */
typedef struct opj_thread_t opj_thread_t;
/** User function to execute in a thread
* @param user_data user data provided with opj_thread_create()
*/
typedef void (*opj_thread_fn)(void* user_data);
/** Creates a new thread.
* @param thread_fn Function to run in the new thread.
* @param user_data user data provided to the thread function. Might be NULL.
* @return a thread handle or NULL in case of failure (can for example happen if the library
* is built without thread support)
*/
opj_thread_t* opj_thread_create( opj_thread_fn thread_fn, void* user_data );
/** Wait for a thread to be finished and release associated resources to the
* thread handle.
* @param thread the thread to wait for being finished.
*/
void opj_thread_join( opj_thread_t* thread );
/*@}*/
/** @name Thread local storage */
/*@{*/
/** Opaque type for a thread local storage */
typedef struct opj_tls_t opj_tls_t;
/** Get a thread local value corresponding to the provided key.
* @param tls thread local storage handle
* @param key key whose value to retrieve.
* @return value associated with the key, or NULL is missing.
*/
void* opj_tls_get(opj_tls_t* tls, int key);
/** Type of the function used to free a TLS value */
typedef void (*opj_tls_free_func)(void* value);
/** Set a thread local value corresponding to the provided key.
* @param tls thread local storage handle
* @param key key whose value to set.
* @param value value to set (may be NULL).
* @param free_func function to call currently installed value.
* @return OPJ_TRUE if successful.
*/
OPJ_BOOL opj_tls_set(opj_tls_t* tls, int key, void* value, opj_tls_free_func free_func);
/*@}*/
/** @name Thread pool */
/*@{*/
/** Opaque type for a thread pool */
typedef struct opj_thread_pool_t opj_thread_pool_t;
/** Create a new thread pool.
* num_thread must nominally be >= 1 to create a real thread pool. If num_threads
* is negative or null, then a dummy thread pool will be created. All functions
* operating on the thread pool will work, but job submission will be run
* synchronously in the calling thread.
*
* @param num_threads the number of threads to allocate for this thread pool.
* @return a thread pool handle, or NULL in case of failure (can for example happen if the library
* is built without thread support)
*/
opj_thread_pool_t* opj_thread_pool_create(int num_threads);
/** User function to execute in a thread
* @param user_data user data provided with opj_thread_create()
* @param tls handle to thread local storage
*/
typedef void (*opj_job_fn)(void* user_data, opj_tls_t* tls);
/** Submit a new job to be run by one of the thread in the thread pool.
* The job ( thread_fn, user_data ) will be added in the queue of jobs managed
* by the thread pool, and run by the first thread that is no longer busy.
*
* @param tp the thread pool handle.
* @param job_fn Function to run. Must not be NULL.
* @param user_data User data provided to thread_fn.
* @return OPJ_TRUE if the job was successfully submitted.
*/
OPJ_BOOL opj_thread_pool_submit_job(opj_thread_pool_t* tp, opj_job_fn job_fn, void* user_data);
/** Wait that no more than max_remaining_jobs jobs are remaining in the queue of
* the thread pool. The aim of this function is to avoid submitting too many
* jobs while the thread pool cannot cope fast enough with them, which would
* result potentially in out-of-memory situations with too many job descriptions
* being queued.
*
* @param tp the thread pool handle
* @param max_remaining_jobs maximum number of jobs allowed to be queued without waiting.
*/
void opj_thread_pool_wait_completion(opj_thread_pool_t* tp, int max_remaining_jobs);
/** Return the number of threads associated with the thread pool.
*
* @param tp the thread pool handle.
* @return number of threads associated with the thread pool.
*/
int opj_thread_pool_get_thread_count(opj_thread_pool_t* tp);
/** Destroy a thread pool.
* @param tp the thread pool handle.
*/
void opj_thread_pool_destroy(opj_thread_pool_t* tp);
/*@}*/
/*@}*/
#endif /* THREAD_H */

View File

@ -0,0 +1,37 @@
/*
* The copyright in this software is being made available under the 2-clauses
* BSD License, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such rights
* are granted under this license.
*
* Copyright (c) 2016, Even Rouault
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TLS_KEYS_H
#define TLS_KEYS_H
#define OPJ_TLS_KEY_T1 0
#endif

View File

@ -117,6 +117,7 @@ CODmarker_param_t get_CODmkrdata_from_j2kstream( Byte_t *CODstream)
if( *CODstream++ != 0xff || *CODstream++ != 0x52){
fprintf( FCGI_stderr, "Error, COD marker not found in the reconstructed j2kstream\n");
memset(&COD, 0, sizeof(COD));
return COD;
}

View File

@ -438,7 +438,7 @@ void enqueue_allprecincts( int tile_id, int level, int lastcomp, OPJ_BOOL *comps
OPJ_BOOL enqueue_metabins( query_param_t query_param, metadatalist_param_t *metadatalist, msgqueue_param_t *msgqueue)
{
int i;
for( i=0; query_param.box_type[i][0]!=0 && i<MAX_NUMOFBOX; i++){
for( i=0; i<MAX_NUMOFBOX && query_param.box_type[i][0]!=0; i++){
if( query_param.box_type[i][0] == '*'){
fprintf( FCGI_stdout, "Status: 501\r\n");
fprintf( FCGI_stdout, "Reason: metareq with all box-property * not implemented\r\n");

View File

@ -264,7 +264,7 @@ void print_queryparam( query_param_t query_param)
}
fprintf( logstream, "\t req-box-prop\n");
for( i=0; query_param.box_type[i][0]!=0 && i<MAX_NUMOFBOX; i++){
for( i=0; i<MAX_NUMOFBOX && query_param.box_type[i][0]!=0; i++){
fprintf( logstream, "\t\t box_type: %.4s limit: %d w:%d s:%d g:%d a:%d priority:%d\n", query_param.box_type[i], query_param.limit[i], query_param.w[i], query_param.s[i], query_param.g[i], query_param.a[i], query_param.priority[i]);
}

View File

@ -51,6 +51,7 @@ set(BLACKLIST_JPEG2000_TMP
issue427-null-image-size.jp2
issue427-illegal-tile-offset.jp2
issue495.jp2
issue820.jp2
)
# Define a list of file which should be gracefully rejected:

View File

@ -146,6 +146,8 @@ opj_compress -i @INPUT_NR_PATH@/flower-minisblack-11.tif -o @TEMP_PATH@/flower-m
opj_compress -i @INPUT_NR_PATH@/flower-minisblack-13.tif -o @TEMP_PATH@/flower-minisblack-13.tif.jp2
opj_compress -i @INPUT_NR_PATH@/flower-minisblack-15.tif -o @TEMP_PATH@/flower-minisblack-15.tif.jp2
# issue 843 Crash with invalid ppm file
!opj_compress -i @INPUT_NR_PATH@/issue843.ppm -o @TEMP_PATH@/issue843.ppm.jp2
# DECODER TEST SUITE
opj_decompress -i @INPUT_NR_PATH@/Bretagne2.j2k -o @TEMP_PATH@/Bretagne2.j2k.pgx
@ -566,6 +568,9 @@ opj_decompress -i @INPUT_NR_PATH@/issue726.j2k -o @TEMP_PATH@/issue726.png
!opj_decompress -i @INPUT_NR_PATH@/issue775-2.j2k -o @TEMP_PATH@/issue775-2.png
# issue 818
opj_decompress -i @INPUT_NR_PATH@/issue818.jp2 -o @TEMP_PATH@/issue818.png
# issue 823 (yes, not a typo, test image is issue822)
!opj_decompress -i @INPUT_NR_PATH@/issue822.jp2 -o @TEMP_PATH@/issue822.png
# issue 823
!opj_decompress -i @INPUT_NR_PATH@/issue823.jp2 -o @TEMP_PATH@/issue823.png
# issue 826
!opj_decompress -i @INPUT_NR_PATH@/issue826.jp2 -o @TEMP_PATH@/issue826.png
# issue 820
!opj_decompress -i @INPUT_NR_PATH@/issue820.jp2 -o @TEMP_PATH@/issue820.png

View File

@ -178,7 +178,7 @@ int main (int argc, char *argv[])
int da_y0=0;
int da_x1=1000;
int da_y1=1000;
char input_file[64];
const char *input_file;
/* should be test_tile_decoder 0 0 1000 1000 tte1.j2k */
if( argc == 6 )
@ -187,7 +187,7 @@ int main (int argc, char *argv[])
da_y0=atoi(argv[2]);
da_x1=atoi(argv[3]);
da_y1=atoi(argv[4]);
strcpy(input_file,argv[5]);
input_file = argv[5];
}
else
@ -196,7 +196,7 @@ int main (int argc, char *argv[])
da_y0=0;
da_x1=1000;
da_y1=1000;
strcpy(input_file,"test.j2k");
input_file = "test.j2k";
}
if (! l_data) {

View File

@ -69,7 +69,7 @@ int main (int argc, char *argv[])
opj_stream_t * l_stream;
OPJ_UINT32 l_nb_tiles;
OPJ_UINT32 l_data_size;
unsigned char len;
size_t len;
#ifdef USING_MCT
const OPJ_FLOAT32 l_mct [] =
@ -96,7 +96,7 @@ int main (int argc, char *argv[])
int tile_height;
int comp_prec;
int irreversible;
char output_file[64];
const char *output_file;
/* should be test_tile_encoder 3 2000 2000 1000 1000 8 tte1.j2k */
if( argc == 9 )
@ -108,7 +108,7 @@ int main (int argc, char *argv[])
tile_height = atoi( argv[5] );
comp_prec = atoi( argv[6] );
irreversible = atoi( argv[7] );
strcpy(output_file, argv[8] );
output_file = argv[8];
}
else
{
@ -119,7 +119,7 @@ int main (int argc, char *argv[])
tile_height = 1000;
comp_prec = 8;
irreversible = 1;
strcpy(output_file, "test.j2k" );
output_file = "test.j2k";
}
if( num_comps > NUM_COMPS_MAX )
{
@ -228,7 +228,7 @@ int main (int argc, char *argv[])
}
/* should we do j2k or jp2 ?*/
len = (unsigned char)strlen( output_file );
len = strlen( output_file );
if( strcmp( output_file + len - 4, ".jp2" ) == 0 )
{
l_codec = opj_create_compress(OPJ_CODEC_JP2);

View File

@ -5,8 +5,8 @@
"Git": "https://github.com/uclouvain/openjpeg.git",
"Maintainer": "OpenJPEG team",
"MaintainerUrl": "http://www.openjpeg.org/",
"Package": "version.",
"Configure": "-DCMAKE_C_FLAGS='-fvisibility=hidden -g -Og -w -fpermissive'",
"Package": "version.",
"Versions": [
{
@ -21,10 +21,22 @@
"PublicSymbols": "public_symbols/openjpeg/current/list",
"PublicTypes": "public_types/openjpeg/current/list"
},
{
"Number": "2.1.2",
"Installed": "installed/openjpeg/2.1.2",
"Source": "src/openjpeg/2.1.2/version.-2.1.2.tar.gz",
"Changelog": "CHANGELOG.md",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off",
"PublicSymbols": "public_symbols/openjpeg/2.1.2/list",
"PublicTypes": "public_types/openjpeg/2.1.2/list"
},
{
"Number": "2.1.1",
"Installed": "installed/openjpeg/2.1.1",
"Source": "src/openjpeg/2.1.1/v2.1.1.tar.gz",
"Source": "src/openjpeg/2.1.1/version.-2.1.1.tar.gz",
"Changelog": "CHANGELOG.md",
"HeadersDiff": "On",
"PkgDiff": "Off",
@ -104,29 +116,5 @@
"ABIDiff": "Off",
"PublicSymbols": "public_symbols/openjpeg/1.5/list",
"PublicTypes": "public_types/openjpeg/1.5/list"
},
{
"Number": "1.4",
"Installed": "installed/openjpeg/1.4",
"Source": "src/openjpeg/1.4/version.1.4.tar.gz",
"Changelog": "CHANGES",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off",
"PublicSymbols": "public_symbols/openjpeg/1.4/list",
"PublicTypes": "public_types/openjpeg/1.4/list"
},
{
"Number": "1.2",
"Installed": "installed/openjpeg/1.2",
"Source": "src/openjpeg/1.2/version.1.2.tar.gz",
"Changelog": "ChangeLog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off",
"PublicSymbols": "public_symbols/openjpeg/1.2/list",
"PublicTypes": "public_types/openjpeg/1.2/list"
}]
}

View File

@ -14,8 +14,8 @@ if [ "${OPJ_CI_ABI_CHECK:-}" != "1" ]; then
fi
OPJ_UPLOAD_ABI_REPORT=0
#OPJ_PREVIOUS_VERSION="2.1"
OPJ_LATEST_VERSION="2.1.1"
#OPJ_PREVIOUS_VERSION="2.1.1"
OPJ_LATEST_VERSION="2.1.2"
if [ "${OPJ_PREVIOUS_VERSION:-}" != "" ]; then
OPJ_LIMIT_ABI_BUILDS="-limit 3"
else
@ -26,7 +26,7 @@ OPJ_SSH_REPO=${OPJ_REPO/https:\/\/github.com\//git@github.com:}
OPJ_UPLOAD_BRANCH="gh-pages"
OPJ_UPLOAD_DIR="abi-check"
if [ "${TRAVIS_REPO_SLUG:-}" != "" ]; then
if [ "$(echo "${TRAVIS_REPO_SLUG}" | sed 's/\(^.*\)\/.*/\1/')" == "uclouvain" ] && [ "${TRAVIS_PULL_REQUEST:-}" == "false" ]; then
if [ "$(echo "${TRAVIS_REPO_SLUG}" | sed 's/\(^.*\)\/.*/\1/')" == "uclouvain" ] && [ "${TRAVIS_PULL_REQUEST:-}" == "false" ] && [ "${TRAVIS_BRANCH:-}" == "master" ]; then
# Upload updated report to gh-pages
OPJ_UPLOAD_ABI_REPORT=1
# Build full report
@ -71,7 +71,7 @@ rm -rf installed/openjpeg/current/*
# Let's create all we need
grep -v Git ${OPJ_SOURCE_DIR}/tools/abi-tracker/openjpeg.json > ./openjpeg.json
#abi-monitor ${OPJ_LIMIT_ABI_BUILDS} -get openjpeg.json
abi-monitor ${OPJ_LIMIT_ABI_BUILDS} -get openjpeg.json
if [ "${OPJ_LIMIT_ABI_BUILDS}" != "" ]; then
cp -f ${OPJ_SOURCE_DIR}/tools/abi-tracker/openjpeg.json ./openjpeg.json
else
@ -79,7 +79,11 @@ else
grep -v Configure ${OPJ_SOURCE_DIR}/tools/abi-tracker/openjpeg.json > ./openjpeg.json
fi
cp -rf ${OPJ_SOURCE_DIR} src/openjpeg/current
abi-monitor ${OPJ_LIMIT_ABI_BUILDS} -rebuild openjpeg.json
abi-monitor -v current -build openjpeg.json
abi-monitor -v ${OPJ_LATEST_VERSION} -build openjpeg.json
if [ "${OPJ_PREVIOUS_VERSION:-}" != "" ]; then
abi-monitor -v ${OPJ_PREVIOUS_VERSION} -build openjpeg.json
fi
abi-tracker -build openjpeg.json
EXIT_CODE=0