diff options
author | Rider Linden <rider@lindenlab.com> | 2016-09-14 09:55:18 -0700 |
---|---|---|
committer | Rider Linden <rider@lindenlab.com> | 2016-09-14 09:55:18 -0700 |
commit | 51236b7c9c2e74639be6360b42154f21fecc9df8 (patch) | |
tree | b720cf9f432e3bf6c2b100d25a0fce48e4be4219 /indra/llkdu/llimagej2ckdu.cpp | |
parent | 694fe9cfc5a63f825bf77f4630c2da57c16171bf (diff) | |
parent | 4fb100ac7a33174883184f1320d0beac08ead3a7 (diff) |
Merge
Diffstat (limited to 'indra/llkdu/llimagej2ckdu.cpp')
-rw-r--r-- | indra/llkdu/llimagej2ckdu.cpp | 280 |
1 files changed, 132 insertions, 148 deletions
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index fa58931407..2847f347c2 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -82,37 +82,15 @@ private: // void set_default_colour_weights(kdu_params *siz); -const char* engineInfoLLImageJ2CKDU() -{ - static std::string version = llformat("KDU %s", KDU_CORE_VERSION); - return version.c_str(); -} - -LLImageJ2CKDU* createLLImageJ2CKDU() -{ - return new LLImageJ2CKDU(); -} - -void destroyLLImageJ2CKDU(LLImageJ2CKDU* kdu) -{ - delete kdu; - kdu = NULL; -} - +// Factory function: see declaration in llimagej2c.cpp LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl() { return new LLImageJ2CKDU(); } -void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl) +std::string LLImageJ2CKDU::getEngineInfo() const { - delete impl; - impl = NULL; -} - -const char* fallbackEngineInfoLLImageJ2CImpl() -{ - return engineInfoLLImageJ2CKDU(); + return llformat("KDU %s", KDU_CORE_VERSION); } class LLKDUDecodeState @@ -120,11 +98,11 @@ class LLKDUDecodeState public: LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap); ~LLKDUDecodeState(); - BOOL processTileDecode(F32 decode_time, BOOL limit_time = TRUE); + bool processTileDecode(F32 decode_time, bool limit_time = true); private: S32 mNumComponents; - BOOL mUseYCC; + bool mUseYCC; kdu_dims mDims; kdu_sample_allocator mAllocator; kdu_tile_comp mComps[4]; @@ -139,66 +117,84 @@ private: }; // Stuff for new kdu error handling -class LLKDUMessageWarning : public kdu_message +class LLKDUMessage: public kdu_message { public: - /*virtual*/ void put_text(const char *s); - /*virtual*/ void put_text(const kdu_uint16 *s); - - static LLKDUMessageWarning sDefaultMessage; -}; + LLKDUMessage(const std::string& type): + mType(type) + {} -class LLKDUMessageError : public kdu_message -{ -public: - /*virtual*/ void put_text(const char *s); - /*virtual*/ void put_text(const kdu_uint16 *s); - /*virtual*/ void flush(bool end_of_message = false); - static LLKDUMessageError sDefaultMessage; -}; + virtual void put_text(const char *s) + { + LL_INFOS() << "KDU " << mType << ": " << s << LL_ENDL; + } -void LLKDUMessageWarning::put_text(const char *s) -{ - LL_INFOS() << "KDU Warning: " << s << LL_ENDL; -} + virtual void put_text(const kdu_uint16 *s) + { + // The previous implementation simply streamed 's' to the log. So + // either this put_text() override was never called -- or it produced + // some baffling log messages -- because I assert that streaming a + // const kdu_uint16* to a std::ostream will display only the hex value + // of the pointer. + LL_INFOS() << "KDU " << mType << ": " + << utf16str_to_utf8str(llutf16string(s)) << LL_ENDL; + } -void LLKDUMessageWarning::put_text(const kdu_uint16 *s) -{ - LL_INFOS() << "KDU Warning: " << s << LL_ENDL; -} +private: + std::string mType; +}; -void LLKDUMessageError::put_text(const char *s) +struct LLKDUMessageWarning : public LLKDUMessage { - LL_INFOS() << "KDU Error: " << s << LL_ENDL; -} + LLKDUMessageWarning(): + LLKDUMessage("Warning") + { + kdu_customize_warnings(this); + } +}; +// Instantiating LLKDUMessageWarning calls kdu_customize_warnings() with the +// new instance. Make it static so this only happens once. +static LLKDUMessageWarning sWarningHandler; -void LLKDUMessageError::put_text(const kdu_uint16 *s) +struct LLKDUMessageError : public LLKDUMessage { - LL_INFOS() << "KDU Error: " << s << LL_ENDL; -} + LLKDUMessageError(): + LLKDUMessage("Error") + { + kdu_customize_errors(this); + } -void LLKDUMessageError::flush(bool end_of_message) -{ - if (end_of_message) + virtual void flush(bool end_of_message = false) { + // According to the documentation nat found: + // http://pirlwww.lpl.arizona.edu/resources/guide/software/Kakadu/html_pages/globals__kdu$mize_errors.html + // "If a kdu_error object is destroyed, handler→flush will be called with + // an end_of_message argument equal to true and the process will + // subsequently be terminated through exit. The termination may be + // avoided, however, by throwing an exception from within the message + // terminating handler→flush call." + // So throwing an exception here isn't arbitrary: we MUST throw an + // exception if we want to recover from a KDU error. + if (end_of_message) + { BOOST_THROW_EXCEPTION(KDUError("LLKDUMessageError::flush()")); + } } -} - -LLKDUMessageWarning LLKDUMessageWarning::sDefaultMessage; -LLKDUMessageError LLKDUMessageError::sDefaultMessage; -static bool kdu_message_initialized = false; +}; +// Instantiating LLKDUMessageError calls kdu_customize_errors() with the new +// instance. Make it static so this only happens once. +static LLKDUMessageError sErrorHandler; LLImageJ2CKDU::LLImageJ2CKDU() : LLImageJ2CImpl(), -mInputp(NULL), -mCodeStreamp(NULL), -mTPosp(NULL), -mTileIndicesp(NULL), -mRawImagep(NULL), -mDecodeState(NULL), -mBlocksSize(-1), -mPrecinctsSize(-1), -mLevels(0) + mInputp(), + mCodeStreamp(), + mTPosp(), + mTileIndicesp(), + mRawImagep(NULL), + mDecodeState(), + mBlocksSize(-1), + mPrecinctsSize(-1), + mLevels(0) { } @@ -210,7 +206,7 @@ LLImageJ2CKDU::~LLImageJ2CKDU() // Stuff for new simple decode void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision); -void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode) +void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECodeStreamMode mode) { S32 data_size = base.getDataSize(); S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size); @@ -218,38 +214,27 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod // // Initialization // - if (!kdu_message_initialized) - { - kdu_message_initialized = true; - kdu_customize_errors(&LLKDUMessageError::sDefaultMessage); - kdu_customize_warnings(&LLKDUMessageWarning::sDefaultMessage); - } - - if (mCodeStreamp) - { - mCodeStreamp->destroy(); - delete mCodeStreamp; - mCodeStreamp = NULL; - } + mCodeStreamp.reset(); if (!mInputp && base.getData()) { // The compressed data has been loaded // Setup the source for the codestream - mInputp = new LLKDUMemSource(base.getData(), data_size); + mInputp.reset(new LLKDUMemSource(base.getData(), data_size)); } if (mInputp) { + // This is LLKDUMemSource::reset(), not boost::scoped_ptr::reset(). mInputp->reset(); } - mCodeStreamp = new kdu_codestream; - mCodeStreamp->create(mInputp); + mCodeStreamp->create(mInputp.get()); // Set the maximum number of bytes to use from the codestream - // *TODO: This seems to be wrong. The base class should have no idea of how j2c compression works so no - // good way of computing what's the byte range to be used. + // *TODO: This seems to be wrong. The base class should have no idea of + // how j2c compression works so no good way of computing what's the byte + // range to be used. mCodeStreamp->set_max_bytes(max_bytes,true); // If you want to flip or rotate the image for some reason, change @@ -306,42 +291,26 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod if (!keep_codestream) { - mCodeStreamp->destroy(); - delete mCodeStreamp; - mCodeStreamp = NULL; - delete mInputp; - mInputp = NULL; + mCodeStreamp.reset(); + mInputp.reset(); } } void LLImageJ2CKDU::cleanupCodeStream() { - delete mInputp; - mInputp = NULL; - - delete mDecodeState; - mDecodeState = NULL; - - if (mCodeStreamp) - { - mCodeStreamp->destroy(); - delete mCodeStreamp; - mCodeStreamp = NULL; - } - - delete mTPosp; - mTPosp = NULL; - - delete mTileIndicesp; - mTileIndicesp = NULL; + mInputp.reset(); + mDecodeState.reset(); + mCodeStreamp.reset(); + mTPosp.reset(); + mTileIndicesp.reset(); } -BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region) +bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region) { return initDecode(base,raw_image,0.0f,MODE_FAST,0,4,discard_level,region); } -BOOL LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels) +bool LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels) { mPrecinctsSize = precincts_size; if (mPrecinctsSize != -1) @@ -365,10 +334,10 @@ BOOL LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc mLevels = llclamp(mLevels,MIN_DECOMPOSITION_LEVELS,MAX_DECOMPOSITION_LEVELS); base.setLevels(mLevels); } - return TRUE; + return true; } -BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region) +bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region) { base.resetLastError(); @@ -380,7 +349,7 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco //findDiscardLevelsBoundaries(base); base.updateRawDiscardLevel(); - setupCodeStream(base, TRUE, mode); + setupCodeStream(base, true, mode); mRawImagep = &raw_image; mCodeStreamp->change_appearance(false, true, false); @@ -415,12 +384,12 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco if (!mTileIndicesp) { - mTileIndicesp = new kdu_dims; + mTileIndicesp.reset(new kdu_dims); } mCodeStreamp->get_valid_tiles(*mTileIndicesp); if (!mTPosp) { - mTPosp = new kdu_coords; + mTPosp.reset(new kdu_coords); mTPosp->y = 0; mTPosp->x = 0; } @@ -428,32 +397,32 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco catch (const KDUError& msg) { base.setLastError(msg.what()); - return FALSE; + return false; } catch (...) { base.setLastError("Unknown J2C error"); - return FALSE; + return false; } - return TRUE; + return true; } -// Returns TRUE to mean done, whether successful or not. -BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) +// Returns true to mean done, whether successful or not. +bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) { ECodeStreamMode mode = MODE_FAST; LLTimer decode_timer; - if (!mCodeStreamp) + if (!mCodeStreamp->exists()) { if (!initDecode(base, raw_image, decode_time, mode, first_channel, max_channel_count)) { // Initializing the J2C decode failed, bail out. cleanupCodeStream(); - return TRUE; // done + return true; // done } } @@ -463,6 +432,13 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco // Now we are ready to walk through the tiles processing them one-by-one. kdu_byte *buffer = raw_image.getData(); + if (!buffer) + { + base.setLastError("Memory error"); + base.decodeFailed(); + cleanupCodeStream(); + return true; // done + } while (mTPosp->y < mTileIndicesp->size.y) { @@ -498,21 +474,20 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco kdu_coords offset = tile_dims.pos - dims.pos; int row_gap = channels*dims.size.x; // inter-row separation kdu_byte *buf = buffer + offset.y*row_gap + offset.x*channels; - mDecodeState = new LLKDUDecodeState(tile, buf, row_gap); + mDecodeState.reset(new LLKDUDecodeState(tile, buf, row_gap)); } // Do the actual processing F32 remaining_time = decode_time - decode_timer.getElapsedTimeF32(); // This is where we do the actual decode. If we run out of time, return false. if (mDecodeState->processTileDecode(remaining_time, (decode_time > 0.0f))) { - delete mDecodeState; - mDecodeState = NULL; + mDecodeState.reset(); } else { // Not finished decoding yet. // setLastError("Ran out of time while decoding"); - return FALSE; + return false; } } catch (const KDUError& msg) @@ -520,14 +495,14 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco base.setLastError(msg.what()); base.decodeFailed(); cleanupCodeStream(); - return TRUE; // done + return true; // done } catch (...) { base.setLastError( "Unknown J2C error" ); base.decodeFailed(); cleanupCodeStream(); - return TRUE; // done + return true; // done } @@ -539,11 +514,11 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco cleanupCodeStream(); - return TRUE; + return true; } -BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible) +bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible) { // Declare and set simple arguments bool transpose = false; @@ -711,36 +686,36 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co catch(const KDUError& msg) { base.setLastError(msg.what()); - return FALSE; + return false; } catch( ... ) { base.setLastError( "Unknown J2C error" ); - return FALSE; + return false; } - return TRUE; + return true; } -BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base) +bool LLImageJ2CKDU::getMetadata(LLImageJ2C &base) { // *FIX: kdu calls our callback function if there's an error, and // then bombs. To regain control, we throw an exception, and // catch it here. try { - setupCodeStream(base, FALSE, MODE_FAST); - return TRUE; + setupCodeStream(base, false, MODE_FAST); + return true; } catch (const KDUError& msg) { base.setLastError(msg.what()); - return FALSE; + return false; } catch (...) { base.setLastError( "Unknown J2C error" ); - return FALSE; + return false; } } @@ -748,6 +723,8 @@ BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base) /* STATIC copy_block */ /*****************************************************************************/ +/*==========================================================================*| +// Only called by copy_tile(), which is itself commented out static void copy_block(kdu_block *in, kdu_block *out) { if (in->K_max_prime != out->K_max_prime) @@ -776,11 +753,14 @@ static void copy_block(kdu_block *in, kdu_block *out) out->set_max_bytes(num_bytes,false); memcpy(out->byte_buffer,in->byte_buffer,(size_t) num_bytes); } +|*==========================================================================*/ /*****************************************************************************/ /* STATIC copy_tile */ /*****************************************************************************/ +/*==========================================================================*| +// Only called by findDiscardLevelsBoundaries(), which is itself commented out static void copy_tile(kdu_tile tile_in, kdu_tile tile_out, int tnum_in, int tnum_out, kdu_params *siz_in, kdu_params *siz_out, int skip_components, @@ -837,10 +817,13 @@ copy_tile(kdu_tile tile_in, kdu_tile tile_out, int tnum_in, int tnum_out, } } } +|*==========================================================================*/ // Find the block boundary for each discard level in the input image. // We parse the input blocks and copy them in a temporary output stream. // For the moment, we do nothing more that parsing the raw list of blocks and outputing result. +/*==========================================================================*| +// See comments in header file for why this is commented out. void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base) { // We need the number of levels in that image before starting. @@ -850,7 +833,7 @@ void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base) { //std::cout << "Parsing discard level = " << discard_level << std::endl; // Create the input codestream object. - setupCodeStream(base, TRUE, MODE_FAST); + setupCodeStream(base, true, MODE_FAST); mCodeStreamp->apply_input_restrictions(0, 4, discard_level, 0, NULL); mCodeStreamp->set_max_bytes(KDU_LONG_MAX,true); siz_params *siz_in = mCodeStreamp->access_siz(); @@ -944,6 +927,7 @@ void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base) } return; } +|*==========================================================================*/ void set_default_colour_weights(kdu_params *siz) { @@ -1209,7 +1193,7 @@ LLKDUDecodeState::~LLKDUDecodeState() mTile.close(); } -BOOL LLKDUDecodeState::processTileDecode(F32 decode_time, BOOL limit_time) +bool LLKDUDecodeState::processTileDecode(F32 decode_time, bool limit_time) /* Decompresses a tile, writing the data into the supplied byte buffer. The buffer contains interleaved image components, if there are any. Although you may think of the buffer as belonging entirely to this tile, @@ -1241,11 +1225,11 @@ separation between consecutive rows in the real buffer. */ { if (limit_time && decode_timer.getElapsedTimeF32() > decode_time) { - return FALSE; + return false; } } } - return TRUE; + return true; } // kdc_flow_control |