123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768 |
- ///////////////////////////////////////////////////////////////////////////
- //
- // Copyright (c) 2009-2014 DreamWorks Animation LLC.
- //
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * 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.
- // * Neither the name of DreamWorks Animation nor the names of
- // its contributors may be used to endorse or promote products derived
- // from this software without specific prior written permission.
- //
- // 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 "ImfFastHuf.h"
- #include <Iex.h>
- #include <string.h>
- #include <assert.h>
- #include <math.h>
- #include <vector>
- OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
- //
- // Adapted from hufUnpackEncTable -
- // We don't need to reconstruct the code book, just the encoded
- // lengths for each symbol. From the lengths, we can build the
- // base + offset tables. This should be a bit more efficient
- // for sparse code books.
- //
- // table - ptr to the start of the code length data. Will be
- // updated as we decode data
- //
- // numBytes - size of the encoded table (I think)?
- //
- // minSymbol - smallest symbol in the code book
- //
- // maxSymbol - largest symbol in the code book.
- //
- // rleSymbol - the symbol to trigger RLE in the encoded bitstream
- //
- FastHufDecoder::FastHufDecoder
- (const char *&table,
- int numBytes,
- int minSymbol,
- int maxSymbol,
- int rleSymbol)
- :
- _rleSymbol (rleSymbol),
- _numSymbols (0),
- _minCodeLength (255),
- _maxCodeLength (0),
- _idToSymbol (0)
- {
- //
- // List of symbols that we find with non-zero code lengths
- // (listed in the order we find them). Store these in the
- // same format as the code book stores codes + lengths -
- // low 6 bits are the length, everything above that is
- // the symbol.
- //
- std::vector<Int64> symbols;
- //
- // The 'base' table is the minimum code at each code length. base[i]
- // is the smallest code (numerically) of length i.
- //
- Int64 base[MAX_CODE_LEN + 1];
- //
- // The 'offset' table is the position (in sorted order) of the first id
- // of a given code lenght. Array is indexed by code length, like base.
- //
- Int64 offset[MAX_CODE_LEN + 1];
- //
- // Count of how many codes at each length there are. Array is
- // indexed by code length, like base and offset.
- //
- size_t codeCount[MAX_CODE_LEN + 1];
- for (int i = 0; i <= MAX_CODE_LEN; ++i)
- {
- codeCount[i] = 0;
- base[i] = 0xffffffffffffffffULL;
- offset[i] = 0;
- }
- //
- // Count the number of codes, the min/max code lengths, the number of
- // codes with each length, and record symbols with non-zero code
- // length as we find them.
- //
- const char *currByte = table;
- Int64 currBits = 0;
- int currBitCount = 0;
- const int SHORT_ZEROCODE_RUN = 59;
- const int LONG_ZEROCODE_RUN = 63;
- const int SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
- for (Int64 symbol = minSymbol; symbol <= maxSymbol; symbol++)
- {
- if (currByte - table > numBytes)
- {
- throw IEX_NAMESPACE::InputExc ("Error decoding Huffman table "
- "(Truncated table data).");
- }
- //
- // Next code length - either:
- // 0-58 (literal code length)
- // 59-62 (various lengths runs of 0)
- // 63 (run of n 0's, with n is the next 8 bits)
- //
- Int64 codeLen = readBits (6, currBits, currBitCount, currByte);
- if (codeLen == (Int64) LONG_ZEROCODE_RUN)
- {
- if (currByte - table > numBytes)
- {
- throw IEX_NAMESPACE::InputExc ("Error decoding Huffman table "
- "(Truncated table data).");
- }
- int runLen = readBits (8, currBits, currBitCount, currByte) +
- SHORTEST_LONG_RUN;
- if (symbol + runLen > maxSymbol + 1)
- {
- throw IEX_NAMESPACE::InputExc ("Error decoding Huffman table "
- "(Run beyond end of table).");
- }
-
- symbol += runLen - 1;
- }
- else if (codeLen >= (Int64) SHORT_ZEROCODE_RUN)
- {
- int runLen = codeLen - SHORT_ZEROCODE_RUN + 2;
- if (symbol + runLen > maxSymbol + 1)
- {
- throw IEX_NAMESPACE::InputExc ("Error decoding Huffman table "
- "(Run beyond end of table).");
- }
- symbol += runLen - 1;
- }
- else if (codeLen != 0)
- {
- symbols.push_back ((symbol << 6) | (codeLen & 63));
- if (codeLen < _minCodeLength)
- _minCodeLength = codeLen;
- if (codeLen > _maxCodeLength)
- _maxCodeLength = codeLen;
- codeCount[codeLen]++;
- }
- }
- for (int i = 0; i < MAX_CODE_LEN; ++i)
- _numSymbols += codeCount[i];
- table = currByte;
- //
- // Compute base - once we have the code length counts, there
- // is a closed form solution for this
- //
- {
- double* countTmp = new double[_maxCodeLength+1];
- for (int l = _minCodeLength; l <= _maxCodeLength; ++l)
- {
- countTmp[l] = (double)codeCount[l] *
- (double)(2 << (_maxCodeLength-l));
- }
-
- for (int l = _minCodeLength; l <= _maxCodeLength; ++l)
- {
- double tmp = 0;
- for (int k =l + 1; k <= _maxCodeLength; ++k)
- tmp += countTmp[k];
-
- tmp /= (double)(2 << (_maxCodeLength - l));
- base[l] = (Int64)ceil (tmp);
- }
- delete [] countTmp;
- }
-
- //
- // Compute offset - these are the positions of the first
- // id (not symbol) that has length [i]
- //
- offset[_maxCodeLength] = 0;
- for (int i= _maxCodeLength - 1; i >= _minCodeLength; i--)
- offset[i] = offset[i + 1] + codeCount[i + 1];
- //
- // Allocate and fill the symbol-to-id mapping. Smaller Ids should be
- // mapped to less-frequent symbols (which have longer codes). Use
- // the offset table to tell us where the id's for a given code
- // length start off.
- //
- _idToSymbol = new int[_numSymbols];
- Int64 mapping[MAX_CODE_LEN + 1];
- for (int i = 0; i < MAX_CODE_LEN + 1; ++i)
- mapping[i] = -1;
- for (int i = _minCodeLength; i <= _maxCodeLength; ++i)
- mapping[i] = offset[i];
- for (std::vector<Int64>::const_iterator i = symbols.begin();
- i != symbols.end();
- ++i)
- {
- int codeLen = *i & 63;
- int symbol = *i >> 6;
- if (mapping[codeLen] >= _numSymbols)
- throw IEX_NAMESPACE::InputExc ("Huffman decode error "
- "(Invalid symbol in header).");
-
- _idToSymbol[mapping[codeLen]] = symbol;
- mapping[codeLen]++;
- }
- buildTables(base, offset);
- }
- FastHufDecoder::~FastHufDecoder()
- {
- delete[] _idToSymbol;
- }
- //
- // Static check if the decoder is enabled.
- //
- // ATM, I only have access to little endian hardware for testing,
- // so I'm not entirely sure that we are reading fom the bit stream
- // properly on BE.
- //
- // If you happen to have more obscure hardware, check that the
- // byte swapping in refill() is happening sensable, add an endian
- // check if needed, and fix the preprocessor magic here.
- //
- #define READ64(c) \
- ((Int64)(c)[0] << 56) | ((Int64)(c)[1] << 48) | ((Int64)(c)[2] << 40) | \
- ((Int64)(c)[3] << 32) | ((Int64)(c)[4] << 24) | ((Int64)(c)[5] << 16) | \
- ((Int64)(c)[6] << 8) | ((Int64)(c)[7] )
- #ifdef __INTEL_COMPILER // ICC built-in swap for LE hosts
- #if defined (__i386__) || defined(__x86_64__)
- #undef READ64
- #define READ64(c) _bswap64 (*(const Int64*)(c))
- #endif
- #endif
- bool
- FastHufDecoder::enabled()
- {
- #if defined(__INTEL_COMPILER) || defined(__GNUC__)
- //
- // Enabled for ICC, GCC:
- // __i386__ -> x86
- // __x86_64__ -> 64-bit x86
- //
- #if defined (__i386__) || defined(__x86_64__)
- return true;
- #else
- return false;
- #endif
- #elif defined (_MSC_VER)
- //
- // Enabled for Visual Studio:
- // _M_IX86 -> x86
- // _M_X64 -> 64bit x86
- #if defined (_M_IX86) || defined(_M_X64)
- return true;
- #else
- return false;
- #endif
- #else
- //
- // Unknown compiler - Be safe and disable.
- //
- return false;
- #endif
- }
- //
- //
- // Built the acceleration tables for lookups on the upper bits
- // as well as the 'LJ' tables.
- //
- void
- FastHufDecoder::buildTables (Int64 *base, Int64 *offset)
- {
- //
- // Build the 'left justified' base table, by shifting base left..
- //
- for (int i = 0; i <= MAX_CODE_LEN; ++i)
- {
- if (base[i] != 0xffffffffffffffffULL)
- {
- _ljBase[i] = base[i] << (64 - i);
- }
- else
- {
- //
- // Unused code length - insert dummy values
- //
- _ljBase[i] = 0xffffffffffffffffULL;
- }
- }
- //
- // Combine some terms into a big fat constant, which for
- // lack of a better term we'll call the 'left justified'
- // offset table (because it serves the same function
- // as 'offset', when using the left justified base table.
- //
- for (int i = 0; i <= MAX_CODE_LEN; ++i)
- _ljOffset[i] = offset[i] - (_ljBase[i] >> (64 - i));
- //
- // Build the acceleration tables for the lookups of
- // short codes ( <= TABLE_LOOKUP_BITS long)
- //
- for (Int64 i = 0; i < 1 << TABLE_LOOKUP_BITS; ++i)
- {
- Int64 value = i << (64 - TABLE_LOOKUP_BITS);
- _tableSymbol[i] = 0xffff;
- _tableCodeLen[i] = 0;
- for (int codeLen = _minCodeLength; codeLen <= _maxCodeLength; ++codeLen)
- {
- if (_ljBase[codeLen] <= value)
- {
- _tableCodeLen[i] = codeLen;
- Int64 id = _ljOffset[codeLen] + (value >> (64 - codeLen));
- if (id < _numSymbols)
- {
- _tableSymbol[i] = _idToSymbol[id];
- }
- else
- {
- throw IEX_NAMESPACE::InputExc ("Huffman decode error "
- "(Overrun).");
- }
- break;
- }
- }
- }
- //
- // Store the smallest value in the table that points to real data.
- // This should be the entry for the largest length that has
- // valid data (in our case, non-dummy _ljBase)
- //
- int minIdx = TABLE_LOOKUP_BITS;
- while (minIdx > 0 && _ljBase[minIdx] == 0xffffffffffffffffULL)
- minIdx--;
- if (minIdx < 0)
- {
- //
- // Error, no codes with lengths 0-TABLE_LOOKUP_BITS used.
- // Set the min value such that the table is never tested.
- //
- _tableMin = 0xffffffffffffffffULL;
- }
- else
- {
- _tableMin = _ljBase[minIdx];
- }
- }
- //
- // For decoding, we're holding onto 2 Int64's.
- //
- // The first (buffer), holds the next bits from the bitstream to be
- // decoded. For certain paths in the decoder, we only need TABLE_LOOKUP_BITS
- // valid bits to decode the next symbol. For other paths, we need a full
- // 64-bits to decode a symbol.
- //
- // When we need to refill 'buffer', we could pull bits straight from
- // the bitstream. But this is very slow and requires lots of book keeping
- // (what's the next bit in the next byte?). Instead, we keep another Int64
- // around that we use to refill from. While this doesn't cut down on the
- // book keeping (still need to know how many valid bits), it does cut
- // down on some of the bit shifting crazy and byte access.
- //
- // The refill Int64 (bufferBack) gets left-shifted after we've pulled
- // off bits. If we run out of bits in the input bit stream, we just
- // shift in 0's to bufferBack.
- //
- // The refill act takes numBits from the top of bufferBack and sticks
- // them in the bottom of buffer. If there arn't enough bits in bufferBack,
- // it gets refilled (to 64-bits) from the input bitstream.
- //
- inline void
- FastHufDecoder::refill
- (Int64 &buffer,
- int numBits, // number of bits to refill
- Int64 &bufferBack, // the next 64-bits, to refill from
- int &bufferBackNumBits, // number of bits left in bufferBack
- const unsigned char *&currByte, // current byte in the bitstream
- int &currBitsLeft) // number of bits left in the bitsream
- {
- //
- // Refill bits into the bottom of buffer, from the top of bufferBack.
- // Always top up buffer to be completely full.
- //
- buffer |= bufferBack >> (64 - numBits);
- if (bufferBackNumBits < numBits)
- {
- numBits -= bufferBackNumBits;
- //
- // Refill all of bufferBack from the bitstream. Either grab
- // a full 64-bit chunk, or whatever bytes are left. If we
- // don't have 64-bits left, pad with 0's.
- //
- if (currBitsLeft >= 64)
- {
- bufferBack = READ64 (currByte);
- bufferBackNumBits = 64;
- currByte += sizeof (Int64);
- currBitsLeft -= 8 * sizeof (Int64);
- }
- else
- {
- bufferBack = 0;
- bufferBackNumBits = 64;
- Int64 shift = 56;
-
- while (currBitsLeft > 0)
- {
- bufferBack |= ((Int64)(*currByte)) << shift;
- currByte++;
- shift -= 8;
- currBitsLeft -= 8;
- }
- //
- // At this point, currBitsLeft might be negative, just because
- // we're subtracting whole bytes. To keep anyone from freaking
- // out, zero the counter.
- //
- if (currBitsLeft < 0)
- currBitsLeft = 0;
- }
- buffer |= bufferBack >> (64 - numBits);
- }
-
- bufferBack = bufferBack << numBits;
- bufferBackNumBits -= numBits;
- //
- // We can have cases where the previous shift of bufferBack is << 64 -
- // in which case no shift occurs. The bit count math still works though,
- // so if we don't have any bits left, zero out bufferBack.
- //
- if (bufferBackNumBits == 0)
- bufferBack = 0;
- }
- //
- // Read the next few bits out of a bitstream. Will be given a backing buffer
- // (buffer) that may still have data left over from previous reads
- // (bufferNumBits). Bitstream pointer (currByte) will be advanced when needed.
- //
- inline Int64
- FastHufDecoder::readBits
- (int numBits,
- Int64 &buffer, // c
- int &bufferNumBits, // lc
- const char *&currByte) // in
- {
- while (bufferNumBits < numBits)
- {
- buffer = (buffer << 8) | *(unsigned char*)(currByte++);
- bufferNumBits += 8;
- }
- bufferNumBits -= numBits;
- return (buffer >> bufferNumBits) & ((1 << numBits) - 1);
- }
- //
- // Decode using a the 'One-Shift' strategy for decoding, with a
- // small-ish table to accelerate decoding of short codes.
- //
- // If possible, try looking up codes into the acceleration table.
- // This has a few benifits - there's no search involved; We don't
- // need an additional lookup to map id to symbol; we don't need
- // a full 64-bits (so less refilling).
- //
- void
- FastHufDecoder::decode
- (const unsigned char *src,
- int numSrcBits,
- unsigned short *dst,
- int numDstElems)
- {
- if (numSrcBits < 128)
- throw IEX_NAMESPACE::InputExc ("Error choosing Huffman decoder implementation "
- "(insufficient number of bits).");
- //
- // Current position (byte/bit) in the src data stream
- // (after the first buffer fill)
- //
- const unsigned char *currByte = src + 2 * sizeof (Int64);
- numSrcBits -= 8 * 2 * sizeof (Int64);
- //
- // 64-bit buffer holding the current bits in the stream
- //
- Int64 buffer = READ64 (src);
- int bufferNumBits = 64;
- //
- // 64-bit buffer holding the next bits in the stream
- //
- Int64 bufferBack = READ64 ((src + sizeof (Int64)));
- int bufferBackNumBits = 64;
- int dstIdx = 0;
- while (dstIdx < numDstElems)
- {
- int codeLen;
- int symbol;
- //
- // Test if we can be table accelerated. If so, directly
- // lookup the output symbol. Otherwise, we need to fall
- // back to searching for the code.
- //
- // If we're doing table lookups, we don't really need
- // a re-filled buffer, so long as we have TABLE_LOOKUP_BITS
- // left. But for a search, we do need a refilled table.
- //
- if (_tableMin <= buffer)
- {
- int tableIdx = buffer >> (64 - TABLE_LOOKUP_BITS);
- //
- // For invalid codes, _tableCodeLen[] should return 0. This
- // will cause the decoder to get stuck in the current spot
- // until we run out of elements, then barf that the codestream
- // is bad. So we don't need to stick a condition like
- // if (codeLen > _maxCodeLength) in this inner.
- //
- codeLen = _tableCodeLen[tableIdx];
- symbol = _tableSymbol[tableIdx];
- }
- else
- {
- if (bufferNumBits < 64)
- {
- refill (buffer,
- 64 - bufferNumBits,
- bufferBack,
- bufferBackNumBits,
- currByte,
- numSrcBits);
- bufferNumBits = 64;
- }
- //
- // Brute force search:
- // Find the smallest length where _ljBase[length] <= buffer
- //
- codeLen = TABLE_LOOKUP_BITS + 1;
- while (_ljBase[codeLen] > buffer && codeLen <= _maxCodeLength)
- codeLen++;
- if (codeLen > _maxCodeLength)
- {
- throw IEX_NAMESPACE::InputExc ("Huffman decode error "
- "(Decoded an invalid symbol).");
- }
- Int64 id = _ljOffset[codeLen] + (buffer >> (64 - codeLen));
- if (id < _numSymbols)
- {
- symbol = _idToSymbol[id];
- }
- else
- {
- throw IEX_NAMESPACE::InputExc ("Huffman decode error "
- "(Decoded an invalid symbol).");
- }
- }
- //
- // Shift over bit stream, and update the bit count in the buffer
- //
- buffer = buffer << codeLen;
- bufferNumBits -= codeLen;
- //
- // If we recieved a RLE symbol (_rleSymbol), then we need
- // to read ahead 8 bits to know how many times to repeat
- // the previous symbol. Need to ensure we at least have
- // 8 bits of data in the buffer
- //
- if (symbol == _rleSymbol)
- {
- if (bufferNumBits < 8)
- {
- refill (buffer,
- 64 - bufferNumBits,
- bufferBack,
- bufferBackNumBits,
- currByte,
- numSrcBits);
- bufferNumBits = 64;
- }
- int rleCount = buffer >> 56;
- if (dstIdx < 1)
- {
- throw IEX_NAMESPACE::InputExc ("Huffman decode error (RLE code "
- "with no previous symbol).");
- }
- if (dstIdx + rleCount > numDstElems)
- {
- throw IEX_NAMESPACE::InputExc ("Huffman decode error (Symbol run "
- "beyond expected output buffer length).");
- }
- if (rleCount <= 0)
- {
- throw IEX_NAMESPACE::InputExc("Huffman decode error"
- " (Invalid RLE length)");
- }
- for (int i = 0; i < rleCount; ++i)
- dst[dstIdx + i] = dst[dstIdx - 1];
- dstIdx += rleCount;
- buffer = buffer << 8;
- bufferNumBits -= 8;
- }
- else
- {
- dst[dstIdx] = symbol;
- dstIdx++;
- }
- //
- // refill bit stream buffer if we're below the number of
- // bits needed for a table lookup
- //
- if (bufferNumBits < TABLE_LOOKUP_BITS)
- {
- refill (buffer,
- 64 - bufferNumBits,
- bufferBack,
- bufferBackNumBits,
- currByte,
- numSrcBits);
- bufferNumBits = 64;
- }
- }
- if (numSrcBits != 0)
- {
- throw IEX_NAMESPACE::InputExc ("Huffman decode error (Compressed data remains "
- "after filling expected output buffer).");
- }
- }
- OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
|