1*f6dc9357SAndroid Build Coastguard Worker // Lzma2Decoder.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Alloc.h"
8*f6dc9357SAndroid Build Coastguard Worker // #include "../../../C/CpuTicks.h"
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "Lzma2Decoder.h"
13*f6dc9357SAndroid Build Coastguard Worker
14*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
15*f6dc9357SAndroid Build Coastguard Worker namespace NLzma2 {
16*f6dc9357SAndroid Build Coastguard Worker
CDecoder()17*f6dc9357SAndroid Build Coastguard Worker CDecoder::CDecoder():
18*f6dc9357SAndroid Build Coastguard Worker _dec(NULL)
19*f6dc9357SAndroid Build Coastguard Worker , _inProcessed(0)
20*f6dc9357SAndroid Build Coastguard Worker , _prop(0xFF)
21*f6dc9357SAndroid Build Coastguard Worker , _finishMode(false)
22*f6dc9357SAndroid Build Coastguard Worker , _inBufSize(1 << 20)
23*f6dc9357SAndroid Build Coastguard Worker , _outStep(1 << 20)
24*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
25*f6dc9357SAndroid Build Coastguard Worker , _tryMt(1)
26*f6dc9357SAndroid Build Coastguard Worker , _numThreads(1)
27*f6dc9357SAndroid Build Coastguard Worker , _memUsage((UInt64)(sizeof(size_t)) << 28)
28*f6dc9357SAndroid Build Coastguard Worker #endif
29*f6dc9357SAndroid Build Coastguard Worker {}
30*f6dc9357SAndroid Build Coastguard Worker
~CDecoder()31*f6dc9357SAndroid Build Coastguard Worker CDecoder::~CDecoder()
32*f6dc9357SAndroid Build Coastguard Worker {
33*f6dc9357SAndroid Build Coastguard Worker if (_dec)
34*f6dc9357SAndroid Build Coastguard Worker Lzma2DecMt_Destroy(_dec);
35*f6dc9357SAndroid Build Coastguard Worker }
36*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetInBufSize (UInt32,UInt32 size))37*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 , UInt32 size)) { _inBufSize = size; return S_OK; }
Z7_COM7F_IMF(CDecoder::SetOutBufSize (UInt32,UInt32 size))38*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32 , UInt32 size)) { _outStep = size; return S_OK; }
39*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetDecoderProperties2 (const Byte * prop,UInt32 size))40*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size))
41*f6dc9357SAndroid Build Coastguard Worker {
42*f6dc9357SAndroid Build Coastguard Worker if (size != 1)
43*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
44*f6dc9357SAndroid Build Coastguard Worker if (prop[0] > 40)
45*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
46*f6dc9357SAndroid Build Coastguard Worker _prop = prop[0];
47*f6dc9357SAndroid Build Coastguard Worker return S_OK;
48*f6dc9357SAndroid Build Coastguard Worker }
49*f6dc9357SAndroid Build Coastguard Worker
50*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetFinishMode (UInt32 finishMode))51*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))
52*f6dc9357SAndroid Build Coastguard Worker {
53*f6dc9357SAndroid Build Coastguard Worker _finishMode = (finishMode != 0);
54*f6dc9357SAndroid Build Coastguard Worker return S_OK;
55*f6dc9357SAndroid Build Coastguard Worker }
56*f6dc9357SAndroid Build Coastguard Worker
57*f6dc9357SAndroid Build Coastguard Worker
58*f6dc9357SAndroid Build Coastguard Worker
59*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
60*f6dc9357SAndroid Build Coastguard Worker
Get_ExpectedBlockSize_From_Dict(UInt32 dictSize)61*f6dc9357SAndroid Build Coastguard Worker static UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize)
62*f6dc9357SAndroid Build Coastguard Worker {
63*f6dc9357SAndroid Build Coastguard Worker const UInt32 kMinSize = (UInt32)1 << 20;
64*f6dc9357SAndroid Build Coastguard Worker const UInt32 kMaxSize = (UInt32)1 << 28;
65*f6dc9357SAndroid Build Coastguard Worker UInt64 blockSize = (UInt64)dictSize << 2;
66*f6dc9357SAndroid Build Coastguard Worker if (blockSize < kMinSize) blockSize = kMinSize;
67*f6dc9357SAndroid Build Coastguard Worker if (blockSize > kMaxSize) blockSize = kMaxSize;
68*f6dc9357SAndroid Build Coastguard Worker if (blockSize < dictSize) blockSize = dictSize;
69*f6dc9357SAndroid Build Coastguard Worker blockSize += (kMinSize - 1);
70*f6dc9357SAndroid Build Coastguard Worker blockSize &= ~(UInt64)(kMinSize - 1);
71*f6dc9357SAndroid Build Coastguard Worker return blockSize;
72*f6dc9357SAndroid Build Coastguard Worker }
73*f6dc9357SAndroid Build Coastguard Worker
74*f6dc9357SAndroid Build Coastguard Worker #define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)))
75*f6dc9357SAndroid Build Coastguard Worker
76*f6dc9357SAndroid Build Coastguard Worker #endif
77*f6dc9357SAndroid Build Coastguard Worker
78*f6dc9357SAndroid Build Coastguard Worker #define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \
79*f6dc9357SAndroid Build Coastguard Worker if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;
80*f6dc9357SAndroid Build Coastguard Worker
81*f6dc9357SAndroid Build Coastguard Worker #define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
82*f6dc9357SAndroid Build Coastguard Worker if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
83*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))84*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
85*f6dc9357SAndroid Build Coastguard Worker const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
86*f6dc9357SAndroid Build Coastguard Worker {
87*f6dc9357SAndroid Build Coastguard Worker _inProcessed = 0;
88*f6dc9357SAndroid Build Coastguard Worker
89*f6dc9357SAndroid Build Coastguard Worker if (!_dec)
90*f6dc9357SAndroid Build Coastguard Worker {
91*f6dc9357SAndroid Build Coastguard Worker _dec = Lzma2DecMt_Create(
92*f6dc9357SAndroid Build Coastguard Worker // &g_AlignedAlloc,
93*f6dc9357SAndroid Build Coastguard Worker &g_Alloc,
94*f6dc9357SAndroid Build Coastguard Worker &g_MidAlloc);
95*f6dc9357SAndroid Build Coastguard Worker if (!_dec)
96*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
97*f6dc9357SAndroid Build Coastguard Worker }
98*f6dc9357SAndroid Build Coastguard Worker
99*f6dc9357SAndroid Build Coastguard Worker CLzma2DecMtProps props;
100*f6dc9357SAndroid Build Coastguard Worker Lzma2DecMtProps_Init(&props);
101*f6dc9357SAndroid Build Coastguard Worker
102*f6dc9357SAndroid Build Coastguard Worker props.inBufSize_ST = _inBufSize;
103*f6dc9357SAndroid Build Coastguard Worker props.outStep_ST = _outStep;
104*f6dc9357SAndroid Build Coastguard Worker
105*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
106*f6dc9357SAndroid Build Coastguard Worker {
107*f6dc9357SAndroid Build Coastguard Worker props.numThreads = 1;
108*f6dc9357SAndroid Build Coastguard Worker UInt32 numThreads = _numThreads;
109*f6dc9357SAndroid Build Coastguard Worker
110*f6dc9357SAndroid Build Coastguard Worker if (_tryMt && numThreads >= 1)
111*f6dc9357SAndroid Build Coastguard Worker {
112*f6dc9357SAndroid Build Coastguard Worker const UInt64 useLimit = _memUsage;
113*f6dc9357SAndroid Build Coastguard Worker const UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop);
114*f6dc9357SAndroid Build Coastguard Worker const UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize);
115*f6dc9357SAndroid Build Coastguard Worker const size_t expectedBlockSize = (size_t)expectedBlockSize64;
116*f6dc9357SAndroid Build Coastguard Worker const size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16;
117*f6dc9357SAndroid Build Coastguard Worker if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize)
118*f6dc9357SAndroid Build Coastguard Worker {
119*f6dc9357SAndroid Build Coastguard Worker props.outBlockMax = expectedBlockSize;
120*f6dc9357SAndroid Build Coastguard Worker props.inBlockMax = inBlockMax;
121*f6dc9357SAndroid Build Coastguard Worker const size_t kOverheadSize = props.inBufSize_MT + (1 << 16);
122*f6dc9357SAndroid Build Coastguard Worker const UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize);
123*f6dc9357SAndroid Build Coastguard Worker if (numThreads > okThreads)
124*f6dc9357SAndroid Build Coastguard Worker numThreads = (UInt32)okThreads;
125*f6dc9357SAndroid Build Coastguard Worker if (numThreads == 0)
126*f6dc9357SAndroid Build Coastguard Worker numThreads = 1;
127*f6dc9357SAndroid Build Coastguard Worker props.numThreads = numThreads;
128*f6dc9357SAndroid Build Coastguard Worker }
129*f6dc9357SAndroid Build Coastguard Worker }
130*f6dc9357SAndroid Build Coastguard Worker }
131*f6dc9357SAndroid Build Coastguard Worker #endif
132*f6dc9357SAndroid Build Coastguard Worker
133*f6dc9357SAndroid Build Coastguard Worker CSeqInStreamWrap inWrap;
134*f6dc9357SAndroid Build Coastguard Worker CSeqOutStreamWrap outWrap;
135*f6dc9357SAndroid Build Coastguard Worker CCompressProgressWrap progressWrap;
136*f6dc9357SAndroid Build Coastguard Worker
137*f6dc9357SAndroid Build Coastguard Worker inWrap.Init(inStream);
138*f6dc9357SAndroid Build Coastguard Worker outWrap.Init(outStream);
139*f6dc9357SAndroid Build Coastguard Worker progressWrap.Init(progress);
140*f6dc9357SAndroid Build Coastguard Worker
141*f6dc9357SAndroid Build Coastguard Worker SRes res;
142*f6dc9357SAndroid Build Coastguard Worker
143*f6dc9357SAndroid Build Coastguard Worker UInt64 inProcessed = 0;
144*f6dc9357SAndroid Build Coastguard Worker int isMT = False;
145*f6dc9357SAndroid Build Coastguard Worker
146*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
147*f6dc9357SAndroid Build Coastguard Worker isMT = _tryMt;
148*f6dc9357SAndroid Build Coastguard Worker #endif
149*f6dc9357SAndroid Build Coastguard Worker
150*f6dc9357SAndroid Build Coastguard Worker // UInt64 cpuTicks = GetCpuTicks();
151*f6dc9357SAndroid Build Coastguard Worker
152*f6dc9357SAndroid Build Coastguard Worker res = Lzma2DecMt_Decode(_dec, _prop, &props,
153*f6dc9357SAndroid Build Coastguard Worker &outWrap.vt, outSize, _finishMode,
154*f6dc9357SAndroid Build Coastguard Worker &inWrap.vt,
155*f6dc9357SAndroid Build Coastguard Worker &inProcessed,
156*f6dc9357SAndroid Build Coastguard Worker &isMT,
157*f6dc9357SAndroid Build Coastguard Worker progress ? &progressWrap.vt : NULL);
158*f6dc9357SAndroid Build Coastguard Worker
159*f6dc9357SAndroid Build Coastguard Worker /*
160*f6dc9357SAndroid Build Coastguard Worker cpuTicks = GetCpuTicks() - cpuTicks;
161*f6dc9357SAndroid Build Coastguard Worker printf("\n ticks = %10I64u\n", cpuTicks / 1000000);
162*f6dc9357SAndroid Build Coastguard Worker */
163*f6dc9357SAndroid Build Coastguard Worker
164*f6dc9357SAndroid Build Coastguard Worker
165*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
166*f6dc9357SAndroid Build Coastguard Worker /* we reset _tryMt, only if p->props.numThreads was changed */
167*f6dc9357SAndroid Build Coastguard Worker if (props.numThreads > 1)
168*f6dc9357SAndroid Build Coastguard Worker _tryMt = isMT;
169*f6dc9357SAndroid Build Coastguard Worker #endif
170*f6dc9357SAndroid Build Coastguard Worker
171*f6dc9357SAndroid Build Coastguard Worker _inProcessed = inProcessed;
172*f6dc9357SAndroid Build Coastguard Worker
173*f6dc9357SAndroid Build Coastguard Worker RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
174*f6dc9357SAndroid Build Coastguard Worker RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
175*f6dc9357SAndroid Build Coastguard Worker RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)
176*f6dc9357SAndroid Build Coastguard Worker
177*f6dc9357SAndroid Build Coastguard Worker if (res == SZ_OK && _finishMode)
178*f6dc9357SAndroid Build Coastguard Worker {
179*f6dc9357SAndroid Build Coastguard Worker if (inSize && *inSize != inProcessed)
180*f6dc9357SAndroid Build Coastguard Worker res = SZ_ERROR_DATA;
181*f6dc9357SAndroid Build Coastguard Worker if (outSize && *outSize != outWrap.Processed)
182*f6dc9357SAndroid Build Coastguard Worker res = SZ_ERROR_DATA;
183*f6dc9357SAndroid Build Coastguard Worker }
184*f6dc9357SAndroid Build Coastguard Worker
185*f6dc9357SAndroid Build Coastguard Worker return SResToHRESULT(res);
186*f6dc9357SAndroid Build Coastguard Worker }
187*f6dc9357SAndroid Build Coastguard Worker
188*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize (UInt64 * value))189*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))
190*f6dc9357SAndroid Build Coastguard Worker {
191*f6dc9357SAndroid Build Coastguard Worker *value = _inProcessed;
192*f6dc9357SAndroid Build Coastguard Worker return S_OK;
193*f6dc9357SAndroid Build Coastguard Worker }
194*f6dc9357SAndroid Build Coastguard Worker
195*f6dc9357SAndroid Build Coastguard Worker
196*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
197*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetNumberOfThreads (UInt32 numThreads))198*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 numThreads))
199*f6dc9357SAndroid Build Coastguard Worker {
200*f6dc9357SAndroid Build Coastguard Worker _numThreads = numThreads;
201*f6dc9357SAndroid Build Coastguard Worker return S_OK;
202*f6dc9357SAndroid Build Coastguard Worker }
203*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetMemLimit (UInt64 memUsage))204*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetMemLimit(UInt64 memUsage))
205*f6dc9357SAndroid Build Coastguard Worker {
206*f6dc9357SAndroid Build Coastguard Worker _memUsage = memUsage;
207*f6dc9357SAndroid Build Coastguard Worker return S_OK;
208*f6dc9357SAndroid Build Coastguard Worker }
209*f6dc9357SAndroid Build Coastguard Worker
210*f6dc9357SAndroid Build Coastguard Worker #endif
211*f6dc9357SAndroid Build Coastguard Worker
212*f6dc9357SAndroid Build Coastguard Worker
213*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_NO_READ_FROM_CODER
214*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetOutStreamSize (const UInt64 * outSize))215*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))
216*f6dc9357SAndroid Build Coastguard Worker {
217*f6dc9357SAndroid Build Coastguard Worker CLzma2DecMtProps props;
218*f6dc9357SAndroid Build Coastguard Worker Lzma2DecMtProps_Init(&props);
219*f6dc9357SAndroid Build Coastguard Worker props.inBufSize_ST = _inBufSize;
220*f6dc9357SAndroid Build Coastguard Worker props.outStep_ST = _outStep;
221*f6dc9357SAndroid Build Coastguard Worker
222*f6dc9357SAndroid Build Coastguard Worker _inProcessed = 0;
223*f6dc9357SAndroid Build Coastguard Worker
224*f6dc9357SAndroid Build Coastguard Worker if (!_dec)
225*f6dc9357SAndroid Build Coastguard Worker {
226*f6dc9357SAndroid Build Coastguard Worker _dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc);
227*f6dc9357SAndroid Build Coastguard Worker if (!_dec)
228*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
229*f6dc9357SAndroid Build Coastguard Worker }
230*f6dc9357SAndroid Build Coastguard Worker
231*f6dc9357SAndroid Build Coastguard Worker _inWrap.Init(_inStream);
232*f6dc9357SAndroid Build Coastguard Worker
233*f6dc9357SAndroid Build Coastguard Worker const SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt);
234*f6dc9357SAndroid Build Coastguard Worker
235*f6dc9357SAndroid Build Coastguard Worker if (res != SZ_OK)
236*f6dc9357SAndroid Build Coastguard Worker return SResToHRESULT(res);
237*f6dc9357SAndroid Build Coastguard Worker return S_OK;
238*f6dc9357SAndroid Build Coastguard Worker }
239*f6dc9357SAndroid Build Coastguard Worker
240*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetInStream (ISequentialInStream * inStream))241*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream))
242*f6dc9357SAndroid Build Coastguard Worker { _inStream = inStream; return S_OK; }
Z7_COM7F_IMF(CDecoder::ReleaseInStream ())243*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::ReleaseInStream())
244*f6dc9357SAndroid Build Coastguard Worker { _inStream.Release(); return S_OK; }
245*f6dc9357SAndroid Build Coastguard Worker
246*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::Read (void * data,UInt32 size,UInt32 * processedSize))247*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))
248*f6dc9357SAndroid Build Coastguard Worker {
249*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
250*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0;
251*f6dc9357SAndroid Build Coastguard Worker
252*f6dc9357SAndroid Build Coastguard Worker size_t size2 = size;
253*f6dc9357SAndroid Build Coastguard Worker UInt64 inProcessed = 0;
254*f6dc9357SAndroid Build Coastguard Worker
255*f6dc9357SAndroid Build Coastguard Worker const SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed);
256*f6dc9357SAndroid Build Coastguard Worker
257*f6dc9357SAndroid Build Coastguard Worker _inProcessed += inProcessed;
258*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
259*f6dc9357SAndroid Build Coastguard Worker *processedSize = (UInt32)size2;
260*f6dc9357SAndroid Build Coastguard Worker if (res != SZ_OK)
261*f6dc9357SAndroid Build Coastguard Worker return SResToHRESULT(res);
262*f6dc9357SAndroid Build Coastguard Worker return S_OK;
263*f6dc9357SAndroid Build Coastguard Worker }
264*f6dc9357SAndroid Build Coastguard Worker
265*f6dc9357SAndroid Build Coastguard Worker #endif
266*f6dc9357SAndroid Build Coastguard Worker
267*f6dc9357SAndroid Build Coastguard Worker }}
268