//***************************************************************************/ // This software is released under the 2-Clause BSD license, included // below. // // Copyright (c) 2021, Aous Naman // Copyright (c) 2021, Kakadu Software Pty Ltd, Australia // Copyright (c) 2021, The University of New South Wales, Australia // // 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 // HOLDER 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. //***************************************************************************/ // This file is part of the OpenJpeg software implementation. // File: ht_dec.c // Author: Aous Naman // Date: 01 September 2021 //***************************************************************************/ //***************************************************************************/ /** @file ht_dec.c * @brief implements HTJ2K block decoder */ #include <assert.h> #include <string.h> #include "opj_includes.h" #include "t1_ht_luts.h" ///////////////////////////////////////////////////////////////////////////// // compiler detection ///////////////////////////////////////////////////////////////////////////// #ifdef _MSC_VER #define OPJ_COMPILER_MSVC #elif (defined __GNUC__) #define OPJ_COMPILER_GNUC #endif #if defined(OPJ_COMPILER_MSVC) && defined(_M_ARM64) \ && !defined(_M_ARM64EC) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \ && !defined(__INTEL_COMPILER) && !defined(__clang__) #define MSVC_NEON_INTRINSICS #endif #ifdef MSVC_NEON_INTRINSICS #include <arm64_neon.h> #endif //************************************************************************/ /** @brief Displays the error message for disabling the decoding of SPP and * MRP passes */ static OPJ_BOOL only_cleanup_pass_is_decoded = …; //************************************************************************/ /** @brief Generates population count (i.e., the number of set bits) * * @param [in] val is the value for which population count is sought */ static INLINE OPJ_UINT32 population_count(OPJ_UINT32 val) { … } //************************************************************************/ /** @brief Counts the number of leading zeros * * @param [in] val is the value for which leading zero count is sought */ #ifdef OPJ_COMPILER_MSVC #pragma intrinsic(_BitScanReverse) #endif static INLINE OPJ_UINT32 count_leading_zeros(OPJ_UINT32 val) { … } //************************************************************************/ /** @brief Read a little-endian serialized UINT32. * * @param [in] dataIn pointer to byte stream to read from */ static INLINE OPJ_UINT32 read_le_uint32(const void* dataIn) { … } //************************************************************************/ /** @brief MEL state structure for reading and decoding the MEL bitstream * * A number of events is decoded from the MEL bitstream ahead of time * and stored in run/num_runs. * Each run represents the number of zero events before a one event. */ dec_mel_t; //************************************************************************/ /** @brief Reads and unstuffs the MEL bitstream * * This design needs more bytes in the codeblock buffer than the length * of the cleanup pass by up to 2 bytes. * * Unstuffing removes the MSB of the byte following a byte whose * value is 0xFF; this prevents sequences larger than 0xFF7F in value * from appearing the bitstream. * * @param [in] melp is a pointer to dec_mel_t structure */ static INLINE void mel_read(dec_mel_t *melp) { … } //************************************************************************/ /** @brief Decodes unstuffed MEL segment bits stored in tmp to runs * * Runs are stored in "runs" and the number of runs in "num_runs". * Each run represents a number of zero events that may or may not * terminate in a 1 event. * Each run is stored in 7 bits. The LSB is 1 if the run terminates in * a 1 event, 0 otherwise. The next 6 bits, for the case terminating * with 1, contain the number of consecutive 0 zero events * 2; for the * case terminating with 0, they store (number of consecutive 0 zero * events - 1) * 2. * A total of 6 bits (made up of 1 + 5) should have been enough. * * @param [in] melp is a pointer to dec_mel_t structure */ static INLINE void mel_decode(dec_mel_t *melp) { … } //************************************************************************/ /** @brief Initiates a dec_mel_t structure for MEL decoding and reads * some bytes in order to get the read address to a multiple * of 4 * * @param [in] melp is a pointer to dec_mel_t structure * @param [in] bbuf is a pointer to byte buffer * @param [in] lcup is the length of MagSgn+MEL+VLC segments * @param [in] scup is the length of MEL+VLC segments */ static INLINE OPJ_BOOL mel_init(dec_mel_t *melp, OPJ_UINT8* bbuf, int lcup, int scup) { … } //************************************************************************/ /** @brief Retrieves one run from dec_mel_t; if there are no runs stored * MEL segment is decoded * * @param [in] melp is a pointer to dec_mel_t structure */ static INLINE int mel_get_run(dec_mel_t *melp) { … } //************************************************************************/ /** @brief A structure for reading and unstuffing a segment that grows * backward, such as VLC and MRP */ rev_struct_t; //************************************************************************/ /** @brief Read and unstuff data from a backwardly-growing segment * * This reader can read up to 8 bytes from before the VLC segment. * Care must be taken not read from unreadable memory, causing a * segmentation fault. * * Note that there is another subroutine rev_read_mrp that is slightly * different. The other one fills zeros when the buffer is exhausted. * This one basically does not care if the bytes are consumed, because * any extra data should not be used in the actual decoding. * * Unstuffing is needed to prevent sequences more than 0xFF8F from * appearing in the bits stream; since we are reading backward, we keep * watch when a value larger than 0x8F appears in the bitstream. * If the byte following this is 0x7F, we unstuff this byte (ignore the * MSB of that byte, which should be 0). * * @param [in] vlcp is a pointer to rev_struct_t structure */ static INLINE void rev_read(rev_struct_t *vlcp) { … } //************************************************************************/ /** @brief Initiates the rev_struct_t structure and reads a few bytes to * move the read address to multiple of 4 * * There is another similar rev_init_mrp subroutine. The difference is * that this one, rev_init, discards the first 12 bits (they have the * sum of the lengths of VLC and MEL segments), and first unstuff depends * on first 4 bits. * * @param [in] vlcp is a pointer to rev_struct_t structure * @param [in] data is a pointer to byte at the start of the cleanup pass * @param [in] lcup is the length of MagSgn+MEL+VLC segments * @param [in] scup is the length of MEL+VLC segments */ static INLINE void rev_init(rev_struct_t *vlcp, OPJ_UINT8* data, int lcup, int scup) { … } //************************************************************************/ /** @brief Retrieves 32 bits from the head of a rev_struct structure * * By the end of this call, vlcp->tmp must have no less than 33 bits * * @param [in] vlcp is a pointer to rev_struct structure */ static INLINE OPJ_UINT32 rev_fetch(rev_struct_t *vlcp) { … } //************************************************************************/ /** @brief Consumes num_bits from a rev_struct structure * * @param [in] vlcp is a pointer to rev_struct structure * @param [in] num_bits is the number of bits to be removed */ static INLINE OPJ_UINT32 rev_advance(rev_struct_t *vlcp, OPJ_UINT32 num_bits) { … } //************************************************************************/ /** @brief Reads and unstuffs from rev_struct * * This is different than rev_read in that this fills in zeros when the * the available data is consumed. The other does not care about the * values when all data is consumed. * * See rev_read for more information about unstuffing * * @param [in] mrp is a pointer to rev_struct structure */ static INLINE void rev_read_mrp(rev_struct_t *mrp) { … } //************************************************************************/ /** @brief Initialized rev_struct structure for MRP segment, and reads * a number of bytes such that the next 32 bits read are from * an address that is a multiple of 4. Note this is designed for * an architecture that read size must be compatible with the * alignment of the read address * * There is another similar subroutine rev_init. This subroutine does * NOT skip the first 12 bits, and starts with unstuff set to true. * * @param [in] mrp is a pointer to rev_struct structure * @param [in] data is a pointer to byte at the start of the cleanup pass * @param [in] lcup is the length of MagSgn+MEL+VLC segments * @param [in] len2 is the length of SPP+MRP segments */ static INLINE void rev_init_mrp(rev_struct_t *mrp, OPJ_UINT8* data, int lcup, int len2) { … } //************************************************************************/ /** @brief Retrieves 32 bits from the head of a rev_struct structure * * By the end of this call, mrp->tmp must have no less than 33 bits * * @param [in] mrp is a pointer to rev_struct structure */ static INLINE OPJ_UINT32 rev_fetch_mrp(rev_struct_t *mrp) { … } //************************************************************************/ /** @brief Consumes num_bits from a rev_struct structure * * @param [in] mrp is a pointer to rev_struct structure * @param [in] num_bits is the number of bits to be removed */ static INLINE OPJ_UINT32 rev_advance_mrp(rev_struct_t *mrp, OPJ_UINT32 num_bits) { … } //************************************************************************/ /** @brief Decode initial UVLC to get the u value (or u_q) * * @param [in] vlc is the head of the VLC bitstream * @param [in] mode is 0, 1, 2, 3, or 4. Values in 0 to 3 are composed of * u_off of 1st quad and 2nd quad of a quad pair. The value * 4 occurs when both bits are 1, and the event decoded * from MEL bitstream is also 1. * @param [out] u is the u value (or u_q) + 1. Note: we produce u + 1; * this value is a partial calculation of u + kappa. */ static INLINE OPJ_UINT32 decode_init_uvlc(OPJ_UINT32 vlc, OPJ_UINT32 mode, OPJ_UINT32 *u) { … } //************************************************************************/ /** @brief Decode non-initial UVLC to get the u value (or u_q) * * @param [in] vlc is the head of the VLC bitstream * @param [in] mode is 0, 1, 2, or 3. The 1st bit is u_off of 1st quad * and 2nd for 2nd quad of a quad pair * @param [out] u is the u value (or u_q) + 1. Note: we produce u + 1; * this value is a partial calculation of u + kappa. */ static INLINE OPJ_UINT32 decode_noninit_uvlc(OPJ_UINT32 vlc, OPJ_UINT32 mode, OPJ_UINT32 *u) { … } //************************************************************************/ /** @brief State structure for reading and unstuffing of forward-growing * bitstreams; these are: MagSgn and SPP bitstreams */ frwd_struct_t; //************************************************************************/ /** @brief Read and unstuffs 32 bits from forward-growing bitstream * * A subroutine to read from both the MagSgn or SPP bitstreams; * in particular, when MagSgn bitstream is consumed, 0xFF's are fed, * while when SPP is exhausted 0's are fed in. * X controls this value. * * Unstuffing prevent sequences that are more than 0xFF7F from appearing * in the conpressed sequence. So whenever a value of 0xFF is coded, the * MSB of the next byte is set 0 and must be ignored during decoding. * * Reading can go beyond the end of buffer by up to 3 bytes. * * @param [in] msp is a pointer to frwd_struct_t structure * */ static INLINE void frwd_read(frwd_struct_t *msp) { … } //************************************************************************/ /** @brief Initialize frwd_struct_t struct and reads some bytes * * @param [in] msp is a pointer to frwd_struct_t * @param [in] data is a pointer to the start of data * @param [in] size is the number of byte in the bitstream * @param [in] X is the value fed in when the bitstream is exhausted. * See frwd_read. */ static INLINE void frwd_init(frwd_struct_t *msp, const OPJ_UINT8* data, int size, OPJ_UINT32 X) { … } //************************************************************************/ /** @brief Consume num_bits bits from the bitstream of frwd_struct_t * * @param [in] msp is a pointer to frwd_struct_t * @param [in] num_bits is the number of bit to consume */ static INLINE void frwd_advance(frwd_struct_t *msp, OPJ_UINT32 num_bits) { … } //************************************************************************/ /** @brief Fetches 32 bits from the frwd_struct_t bitstream * * @param [in] msp is a pointer to frwd_struct_t */ static INLINE OPJ_UINT32 frwd_fetch(frwd_struct_t *msp) { … } //************************************************************************/ /** @brief Allocates T1 buffers * * @param [in, out] t1 is codeblock cofficients storage * @param [in] w is codeblock width * @param [in] h is codeblock height */ static OPJ_BOOL opj_t1_allocate_buffers( opj_t1_t *t1, OPJ_UINT32 w, OPJ_UINT32 h) { … } /** Decode 1 HT code-block @param t1 T1 handle @param cblk Code-block coding parameters @param orient @param roishift Region of interest shifting value @param cblksty Code-block style @param p_manager the event manager @param p_manager_mutex mutex for the event manager @param check_pterm whether PTERM correct termination should be checked */ OPJ_BOOL opj_t1_ht_decode_cblk(opj_t1_t *t1, opj_tcd_cblk_dec_t* cblk, OPJ_UINT32 orient, OPJ_UINT32 roishift, OPJ_UINT32 cblksty, opj_event_mgr_t *p_manager, opj_mutex_t* p_manager_mutex, OPJ_BOOL check_pterm); //************************************************************************/ /** @brief Decodes one codeblock, processing the cleanup, siginificance * propagation, and magnitude refinement pass * * @param [in, out] t1 is codeblock cofficients storage * @param [in] cblk is codeblock properties * @param [in] orient is the subband to which the codeblock belongs (not needed) * @param [in] roishift is region of interest shift * @param [in] cblksty is codeblock style * @param [in] p_manager is events print manager * @param [in] p_manager_mutex a mutex to control access to p_manager * @param [in] check_pterm: check termination (not used) */ OPJ_BOOL opj_t1_ht_decode_cblk(opj_t1_t *t1, opj_tcd_cblk_dec_t* cblk, OPJ_UINT32 orient, OPJ_UINT32 roishift, OPJ_UINT32 cblksty, opj_event_mgr_t *p_manager, opj_mutex_t* p_manager_mutex, OPJ_BOOL check_pterm) { … }