1370b324cSopenharmony_ci// Lzma2Decoder.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci// #include <stdio.h> 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#include "../../../C/Alloc.h" 8370b324cSopenharmony_ci// #include "../../../C/CpuTicks.h" 9370b324cSopenharmony_ci 10370b324cSopenharmony_ci#include "../Common/StreamUtils.h" 11370b324cSopenharmony_ci 12370b324cSopenharmony_ci#include "Lzma2Decoder.h" 13370b324cSopenharmony_ci 14370b324cSopenharmony_cinamespace NCompress { 15370b324cSopenharmony_cinamespace NLzma2 { 16370b324cSopenharmony_ci 17370b324cSopenharmony_ciCDecoder::CDecoder(): 18370b324cSopenharmony_ci _dec(NULL) 19370b324cSopenharmony_ci , _inProcessed(0) 20370b324cSopenharmony_ci , _prop(0xFF) 21370b324cSopenharmony_ci , _finishMode(false) 22370b324cSopenharmony_ci , _inBufSize(1 << 20) 23370b324cSopenharmony_ci , _outStep(1 << 20) 24370b324cSopenharmony_ci #ifndef Z7_ST 25370b324cSopenharmony_ci , _tryMt(1) 26370b324cSopenharmony_ci , _numThreads(1) 27370b324cSopenharmony_ci , _memUsage((UInt64)(sizeof(size_t)) << 28) 28370b324cSopenharmony_ci #endif 29370b324cSopenharmony_ci{} 30370b324cSopenharmony_ci 31370b324cSopenharmony_ciCDecoder::~CDecoder() 32370b324cSopenharmony_ci{ 33370b324cSopenharmony_ci if (_dec) 34370b324cSopenharmony_ci Lzma2DecMt_Destroy(_dec); 35370b324cSopenharmony_ci} 36370b324cSopenharmony_ci 37370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 , UInt32 size)) { _inBufSize = size; return S_OK; } 38370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32 , UInt32 size)) { _outStep = size; return S_OK; } 39370b324cSopenharmony_ci 40370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)) 41370b324cSopenharmony_ci{ 42370b324cSopenharmony_ci if (size != 1) 43370b324cSopenharmony_ci return E_NOTIMPL; 44370b324cSopenharmony_ci if (prop[0] > 40) 45370b324cSopenharmony_ci return E_NOTIMPL; 46370b324cSopenharmony_ci _prop = prop[0]; 47370b324cSopenharmony_ci return S_OK; 48370b324cSopenharmony_ci} 49370b324cSopenharmony_ci 50370b324cSopenharmony_ci 51370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode)) 52370b324cSopenharmony_ci{ 53370b324cSopenharmony_ci _finishMode = (finishMode != 0); 54370b324cSopenharmony_ci return S_OK; 55370b324cSopenharmony_ci} 56370b324cSopenharmony_ci 57370b324cSopenharmony_ci 58370b324cSopenharmony_ci 59370b324cSopenharmony_ci#ifndef Z7_ST 60370b324cSopenharmony_ci 61370b324cSopenharmony_cistatic UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize) 62370b324cSopenharmony_ci{ 63370b324cSopenharmony_ci const UInt32 kMinSize = (UInt32)1 << 20; 64370b324cSopenharmony_ci const UInt32 kMaxSize = (UInt32)1 << 28; 65370b324cSopenharmony_ci UInt64 blockSize = (UInt64)dictSize << 2; 66370b324cSopenharmony_ci if (blockSize < kMinSize) blockSize = kMinSize; 67370b324cSopenharmony_ci if (blockSize > kMaxSize) blockSize = kMaxSize; 68370b324cSopenharmony_ci if (blockSize < dictSize) blockSize = dictSize; 69370b324cSopenharmony_ci blockSize += (kMinSize - 1); 70370b324cSopenharmony_ci blockSize &= ~(UInt64)(kMinSize - 1); 71370b324cSopenharmony_ci return blockSize; 72370b324cSopenharmony_ci} 73370b324cSopenharmony_ci 74370b324cSopenharmony_ci#define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))) 75370b324cSopenharmony_ci 76370b324cSopenharmony_ci#endif 77370b324cSopenharmony_ci 78370b324cSopenharmony_ci#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \ 79370b324cSopenharmony_ci if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes; 80370b324cSopenharmony_ci 81370b324cSopenharmony_ci#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ 82370b324cSopenharmony_ci if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; 83370b324cSopenharmony_ci 84370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 85370b324cSopenharmony_ci const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)) 86370b324cSopenharmony_ci{ 87370b324cSopenharmony_ci _inProcessed = 0; 88370b324cSopenharmony_ci 89370b324cSopenharmony_ci if (!_dec) 90370b324cSopenharmony_ci { 91370b324cSopenharmony_ci _dec = Lzma2DecMt_Create( 92370b324cSopenharmony_ci // &g_AlignedAlloc, 93370b324cSopenharmony_ci &g_Alloc, 94370b324cSopenharmony_ci &g_MidAlloc); 95370b324cSopenharmony_ci if (!_dec) 96370b324cSopenharmony_ci return E_OUTOFMEMORY; 97370b324cSopenharmony_ci } 98370b324cSopenharmony_ci 99370b324cSopenharmony_ci CLzma2DecMtProps props; 100370b324cSopenharmony_ci Lzma2DecMtProps_Init(&props); 101370b324cSopenharmony_ci 102370b324cSopenharmony_ci props.inBufSize_ST = _inBufSize; 103370b324cSopenharmony_ci props.outStep_ST = _outStep; 104370b324cSopenharmony_ci 105370b324cSopenharmony_ci #ifndef Z7_ST 106370b324cSopenharmony_ci { 107370b324cSopenharmony_ci props.numThreads = 1; 108370b324cSopenharmony_ci UInt32 numThreads = _numThreads; 109370b324cSopenharmony_ci 110370b324cSopenharmony_ci if (_tryMt && numThreads >= 1) 111370b324cSopenharmony_ci { 112370b324cSopenharmony_ci const UInt64 useLimit = _memUsage; 113370b324cSopenharmony_ci const UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop); 114370b324cSopenharmony_ci const UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize); 115370b324cSopenharmony_ci const size_t expectedBlockSize = (size_t)expectedBlockSize64; 116370b324cSopenharmony_ci const size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16; 117370b324cSopenharmony_ci if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize) 118370b324cSopenharmony_ci { 119370b324cSopenharmony_ci props.outBlockMax = expectedBlockSize; 120370b324cSopenharmony_ci props.inBlockMax = inBlockMax; 121370b324cSopenharmony_ci const size_t kOverheadSize = props.inBufSize_MT + (1 << 16); 122370b324cSopenharmony_ci const UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize); 123370b324cSopenharmony_ci if (numThreads > okThreads) 124370b324cSopenharmony_ci numThreads = (UInt32)okThreads; 125370b324cSopenharmony_ci if (numThreads == 0) 126370b324cSopenharmony_ci numThreads = 1; 127370b324cSopenharmony_ci props.numThreads = numThreads; 128370b324cSopenharmony_ci } 129370b324cSopenharmony_ci } 130370b324cSopenharmony_ci } 131370b324cSopenharmony_ci #endif 132370b324cSopenharmony_ci 133370b324cSopenharmony_ci CSeqInStreamWrap inWrap; 134370b324cSopenharmony_ci CSeqOutStreamWrap outWrap; 135370b324cSopenharmony_ci CCompressProgressWrap progressWrap; 136370b324cSopenharmony_ci 137370b324cSopenharmony_ci inWrap.Init(inStream); 138370b324cSopenharmony_ci outWrap.Init(outStream); 139370b324cSopenharmony_ci progressWrap.Init(progress); 140370b324cSopenharmony_ci 141370b324cSopenharmony_ci SRes res; 142370b324cSopenharmony_ci 143370b324cSopenharmony_ci UInt64 inProcessed = 0; 144370b324cSopenharmony_ci int isMT = False; 145370b324cSopenharmony_ci 146370b324cSopenharmony_ci #ifndef Z7_ST 147370b324cSopenharmony_ci isMT = _tryMt; 148370b324cSopenharmony_ci #endif 149370b324cSopenharmony_ci 150370b324cSopenharmony_ci // UInt64 cpuTicks = GetCpuTicks(); 151370b324cSopenharmony_ci 152370b324cSopenharmony_ci res = Lzma2DecMt_Decode(_dec, _prop, &props, 153370b324cSopenharmony_ci &outWrap.vt, outSize, _finishMode, 154370b324cSopenharmony_ci &inWrap.vt, 155370b324cSopenharmony_ci &inProcessed, 156370b324cSopenharmony_ci &isMT, 157370b324cSopenharmony_ci progress ? &progressWrap.vt : NULL); 158370b324cSopenharmony_ci 159370b324cSopenharmony_ci /* 160370b324cSopenharmony_ci cpuTicks = GetCpuTicks() - cpuTicks; 161370b324cSopenharmony_ci printf("\n ticks = %10I64u\n", cpuTicks / 1000000); 162370b324cSopenharmony_ci */ 163370b324cSopenharmony_ci 164370b324cSopenharmony_ci 165370b324cSopenharmony_ci #ifndef Z7_ST 166370b324cSopenharmony_ci /* we reset _tryMt, only if p->props.numThreads was changed */ 167370b324cSopenharmony_ci if (props.numThreads > 1) 168370b324cSopenharmony_ci _tryMt = isMT; 169370b324cSopenharmony_ci #endif 170370b324cSopenharmony_ci 171370b324cSopenharmony_ci _inProcessed = inProcessed; 172370b324cSopenharmony_ci 173370b324cSopenharmony_ci RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) 174370b324cSopenharmony_ci RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) 175370b324cSopenharmony_ci RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ) 176370b324cSopenharmony_ci 177370b324cSopenharmony_ci if (res == SZ_OK && _finishMode) 178370b324cSopenharmony_ci { 179370b324cSopenharmony_ci if (inSize && *inSize != inProcessed) 180370b324cSopenharmony_ci res = SZ_ERROR_DATA; 181370b324cSopenharmony_ci if (outSize && *outSize != outWrap.Processed) 182370b324cSopenharmony_ci res = SZ_ERROR_DATA; 183370b324cSopenharmony_ci } 184370b324cSopenharmony_ci 185370b324cSopenharmony_ci return SResToHRESULT(res); 186370b324cSopenharmony_ci} 187370b324cSopenharmony_ci 188370b324cSopenharmony_ci 189370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value)) 190370b324cSopenharmony_ci{ 191370b324cSopenharmony_ci *value = _inProcessed; 192370b324cSopenharmony_ci return S_OK; 193370b324cSopenharmony_ci} 194370b324cSopenharmony_ci 195370b324cSopenharmony_ci 196370b324cSopenharmony_ci#ifndef Z7_ST 197370b324cSopenharmony_ci 198370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 numThreads)) 199370b324cSopenharmony_ci{ 200370b324cSopenharmony_ci _numThreads = numThreads; 201370b324cSopenharmony_ci return S_OK; 202370b324cSopenharmony_ci} 203370b324cSopenharmony_ci 204370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetMemLimit(UInt64 memUsage)) 205370b324cSopenharmony_ci{ 206370b324cSopenharmony_ci _memUsage = memUsage; 207370b324cSopenharmony_ci return S_OK; 208370b324cSopenharmony_ci} 209370b324cSopenharmony_ci 210370b324cSopenharmony_ci#endif 211370b324cSopenharmony_ci 212370b324cSopenharmony_ci 213370b324cSopenharmony_ci#ifndef Z7_NO_READ_FROM_CODER 214370b324cSopenharmony_ci 215370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize)) 216370b324cSopenharmony_ci{ 217370b324cSopenharmony_ci CLzma2DecMtProps props; 218370b324cSopenharmony_ci Lzma2DecMtProps_Init(&props); 219370b324cSopenharmony_ci props.inBufSize_ST = _inBufSize; 220370b324cSopenharmony_ci props.outStep_ST = _outStep; 221370b324cSopenharmony_ci 222370b324cSopenharmony_ci _inProcessed = 0; 223370b324cSopenharmony_ci 224370b324cSopenharmony_ci if (!_dec) 225370b324cSopenharmony_ci { 226370b324cSopenharmony_ci _dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc); 227370b324cSopenharmony_ci if (!_dec) 228370b324cSopenharmony_ci return E_OUTOFMEMORY; 229370b324cSopenharmony_ci } 230370b324cSopenharmony_ci 231370b324cSopenharmony_ci _inWrap.Init(_inStream); 232370b324cSopenharmony_ci 233370b324cSopenharmony_ci const SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt); 234370b324cSopenharmony_ci 235370b324cSopenharmony_ci if (res != SZ_OK) 236370b324cSopenharmony_ci return SResToHRESULT(res); 237370b324cSopenharmony_ci return S_OK; 238370b324cSopenharmony_ci} 239370b324cSopenharmony_ci 240370b324cSopenharmony_ci 241370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream)) 242370b324cSopenharmony_ci { _inStream = inStream; return S_OK; } 243370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::ReleaseInStream()) 244370b324cSopenharmony_ci { _inStream.Release(); return S_OK; } 245370b324cSopenharmony_ci 246370b324cSopenharmony_ci 247370b324cSopenharmony_ciZ7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)) 248370b324cSopenharmony_ci{ 249370b324cSopenharmony_ci if (processedSize) 250370b324cSopenharmony_ci *processedSize = 0; 251370b324cSopenharmony_ci 252370b324cSopenharmony_ci size_t size2 = size; 253370b324cSopenharmony_ci UInt64 inProcessed = 0; 254370b324cSopenharmony_ci 255370b324cSopenharmony_ci const SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed); 256370b324cSopenharmony_ci 257370b324cSopenharmony_ci _inProcessed += inProcessed; 258370b324cSopenharmony_ci if (processedSize) 259370b324cSopenharmony_ci *processedSize = (UInt32)size2; 260370b324cSopenharmony_ci if (res != SZ_OK) 261370b324cSopenharmony_ci return SResToHRESULT(res); 262370b324cSopenharmony_ci return S_OK; 263370b324cSopenharmony_ci} 264370b324cSopenharmony_ci 265370b324cSopenharmony_ci#endif 266370b324cSopenharmony_ci 267370b324cSopenharmony_ci}} 268