diff --git a/include/utils-xz/utils-xz.h b/include/utils-xz/utils-xz.h index ca1f1657d..f8a6f65af 100644 --- a/include/utils-xz/utils-xz.h +++ b/include/utils-xz/utils-xz.h @@ -4,4 +4,7 @@ #define _XZ_SHARED_API #endif +#include + _XZ_SHARED_API const char* DecompressXZ(size_t downloadedDataSize, const uint8_t* downloadedData, const char* fileName); +_XZ_SHARED_API const char* DecompressXZ(size_t downloadedDataSize, const uint8_t* downloadedData, uint8_t* dest, int destSeek, int destSize); diff --git a/include/utils/LutLoader.h b/include/utils/LutLoader.h index c79f254bc..93bd91dc3 100644 --- a/include/utils/LutLoader.h +++ b/include/utils/LutLoader.h @@ -3,6 +3,7 @@ #ifndef PCH_ENABLED #include #include + #include #endif #include @@ -17,4 +18,7 @@ class LutLoader { MemoryBuffer _lut; void loadLutFile(Logger* _log, PixelFormat color, const QList& files); + private: + bool decompressLut(Logger* _log, QFile& file, int index); + void hasher(int index, Logger* _log); }; diff --git a/sources/utils-xz/utils-xz.cpp b/sources/utils-xz/utils-xz.cpp index bd43dd48f..508bfca02 100644 --- a/sources/utils-xz/utils-xz.cpp +++ b/sources/utils-xz/utils-xz.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include _XZ_SHARED_API const char* DecompressXZ(size_t downloadedDataSize, const uint8_t* downloadedData, const char* fileName) @@ -83,3 +84,99 @@ _XZ_SHARED_API const char* DecompressXZ(size_t downloadedDataSize, const uint8_t return error; } + +_XZ_SHARED_API const char* DecompressXZ(size_t downloadedDataSize, const uint8_t* downloadedData, uint8_t* dest, int destSeek, int destSize) +{ + size_t outSize = 16842808/2; + std::vector outBuffer; + const char* error = nullptr; + int currentPos = 0; + int writePos = 0; + + try + { + outBuffer.resize(outSize); + } + catch (...) + { + error = "Could not allocate buffer"; + } + + if (error == nullptr) + { + const uint32_t flags = LZMA_TELL_UNSUPPORTED_CHECK | LZMA_CONCATENATED; + lzma_stream strm = LZMA_STREAM_INIT; + strm.next_in = downloadedData; + strm.avail_in = downloadedDataSize; + lzma_ret lzmaRet = lzma_stream_decoder(&strm, outSize, flags); + if (lzmaRet == LZMA_OK) + { + do { + strm.next_out = outBuffer.data(); + strm.avail_out = outSize; + lzmaRet = lzma_code(&strm, LZMA_FINISH); + if (lzmaRet == LZMA_MEMLIMIT_ERROR) + { + outSize = lzma_memusage(&strm); + try + { + outBuffer.resize(outSize); + } + catch (...) + { + error = "Could not increase buffer size"; + break; + } + lzma_memlimit_set(&strm, outSize); + strm.avail_out = 0; + } + else if (lzmaRet != LZMA_OK && lzmaRet != LZMA_STREAM_END) + { + error = "LZMA decoder returned error"; + break; + } + else + { + int toWrite = outSize - strm.avail_out; + int endPos = currentPos + toWrite; + int chunkSize = -1, chunkPos = 0; + + if (currentPos <= destSeek && destSeek + destSize >= endPos) + { + chunkPos = destSeek - currentPos; + chunkSize = toWrite - chunkPos; + } + else if (currentPos <= destSeek + destSize && destSeek + destSize < endPos) + { + chunkSize = (destSeek + destSize) - currentPos; + } + else if (currentPos >= destSeek && destSeek + destSize >= endPos) + { + chunkSize = toWrite; + } + + if (chunkSize > 0) + { + memcpy(dest + writePos, outBuffer.data() + chunkPos, chunkSize); + writePos += chunkSize; + } + + currentPos = endPos; + } + } while (strm.avail_out == 0 && lzmaRet != LZMA_STREAM_END && (writePos < destSize)); + } + else + { + error = "Could not initialize LZMA decoder"; + } + + lzma_end(&strm); + } + + if (writePos != destSize) + { + error = "Incorrect final LUT size"; + } + + return error; +} diff --git a/sources/utils/LutLoader.cpp b/sources/utils/LutLoader.cpp index 53018a8a9..356cac7c1 100644 --- a/sources/utils/LutLoader.cpp +++ b/sources/utils/LutLoader.cpp @@ -24,12 +24,18 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - +#include #include #include #include +#include #include +#ifdef ENABLE_XZ + #include +#endif + + namespace { const int LUT_FILE_SIZE = 256 * 256 * 256 *3; const int LUT_MEMORY_ALIGN = 64; @@ -52,17 +58,26 @@ void LutLoader::loadLutFile(Logger* _log, PixelFormat color, const QList(compressedFile.data()), _lut.data(), index, LUT_FILE_SIZE); + #endif + + if (retVal != nullptr && _log) + { + Error(_log, "Error while decompressing LUT: %s", retVal); + } + + if (_log) Info(_log, "Decompression took %f seconds", (InternalClock::nowPrecise() - now) / 1000.0); + + return retVal == nullptr; +} + +void LutLoader::hasher(int index, Logger* _log) +{ + if (_log) + { + auto start = _lut.data(); + auto end = start + _lut.size(); + uint8_t position = 0; + uint16_t fletcher1 = 0; + uint16_t fletcher2 = 0; + uint16_t fletcherExt = 0; + while (start < end) + { + fletcher1 = (fletcher1 + (uint16_t)(*(start))) % 255; + fletcher2 = (fletcher2 + fletcher1) % 255; + fletcherExt = (fletcherExt + (*(start++) ^ (position++))) % 255; + } + Info(_log, "CRC for %i segment: 0x%.2X 0x%.2X 0x%.2X", index, fletcher1, fletcher2, fletcherExt); + } +}