xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/7z/7zDecode.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // 7zDecode.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 "../../Common/LimitedStreams.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ProgressUtils.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamObjects.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #include "7zDecode.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
13*f6dc9357SAndroid Build Coastguard Worker namespace N7z {
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1(
16*f6dc9357SAndroid Build Coastguard Worker   CDecProgress
17*f6dc9357SAndroid Build Coastguard Worker   , ICompressProgressInfo
18*f6dc9357SAndroid Build Coastguard Worker )
19*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ICompressProgressInfo> _progress;
20*f6dc9357SAndroid Build Coastguard Worker public:
21*f6dc9357SAndroid Build Coastguard Worker   CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
22*f6dc9357SAndroid Build Coastguard Worker };
23*f6dc9357SAndroid Build Coastguard Worker 
24*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize))
25*f6dc9357SAndroid Build Coastguard Worker {
26*f6dc9357SAndroid Build Coastguard Worker   return _progress->SetRatioInfo(NULL, outSize);
27*f6dc9357SAndroid Build Coastguard Worker }
28*f6dc9357SAndroid Build Coastguard Worker 
29*f6dc9357SAndroid Build Coastguard Worker static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)
30*f6dc9357SAndroid Build Coastguard Worker {
31*f6dc9357SAndroid Build Coastguard Worker   bi.Clear();
32*f6dc9357SAndroid Build Coastguard Worker 
33*f6dc9357SAndroid Build Coastguard Worker   bi.Bonds.ClearAndSetSize(folder.Bonds.Size());
34*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
35*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < folder.Bonds.Size(); i++)
36*f6dc9357SAndroid Build Coastguard Worker   {
37*f6dc9357SAndroid Build Coastguard Worker     NCoderMixer2::CBond &bond = bi.Bonds[i];
38*f6dc9357SAndroid Build Coastguard Worker     const N7z::CBond &folderBond = folder.Bonds[i];
39*f6dc9357SAndroid Build Coastguard Worker     bond.PackIndex = folderBond.PackIndex;
40*f6dc9357SAndroid Build Coastguard Worker     bond.UnpackIndex = folderBond.UnpackIndex;
41*f6dc9357SAndroid Build Coastguard Worker   }
42*f6dc9357SAndroid Build Coastguard Worker 
43*f6dc9357SAndroid Build Coastguard Worker   bi.Coders.ClearAndSetSize(folder.Coders.Size());
44*f6dc9357SAndroid Build Coastguard Worker   bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
45*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < folder.Coders.Size(); i++)
46*f6dc9357SAndroid Build Coastguard Worker   {
47*f6dc9357SAndroid Build Coastguard Worker     const CCoderInfo &coderInfo = folder.Coders[i];
48*f6dc9357SAndroid Build Coastguard Worker     bi.Coders[i].NumStreams = coderInfo.NumStreams;
49*f6dc9357SAndroid Build Coastguard Worker     bi.CoderMethodIDs[i] = coderInfo.MethodID;
50*f6dc9357SAndroid Build Coastguard Worker   }
51*f6dc9357SAndroid Build Coastguard Worker 
52*f6dc9357SAndroid Build Coastguard Worker   /*
53*f6dc9357SAndroid Build Coastguard Worker   if (!bi.SetUnpackCoder())
54*f6dc9357SAndroid Build Coastguard Worker     throw 1112;
55*f6dc9357SAndroid Build Coastguard Worker   */
56*f6dc9357SAndroid Build Coastguard Worker   bi.UnpackCoder = folder.UnpackCoder;
57*f6dc9357SAndroid Build Coastguard Worker   bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
58*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < folder.PackStreams.Size(); i++)
59*f6dc9357SAndroid Build Coastguard Worker     bi.PackStreams[i] = folder.PackStreams[i];
60*f6dc9357SAndroid Build Coastguard Worker }
61*f6dc9357SAndroid Build Coastguard Worker 
62*f6dc9357SAndroid Build Coastguard Worker static inline bool AreCodersEqual(
63*f6dc9357SAndroid Build Coastguard Worker     const NCoderMixer2::CCoderStreamsInfo &a1,
64*f6dc9357SAndroid Build Coastguard Worker     const NCoderMixer2::CCoderStreamsInfo &a2)
65*f6dc9357SAndroid Build Coastguard Worker {
66*f6dc9357SAndroid Build Coastguard Worker   return (a1.NumStreams == a2.NumStreams);
67*f6dc9357SAndroid Build Coastguard Worker }
68*f6dc9357SAndroid Build Coastguard Worker 
69*f6dc9357SAndroid Build Coastguard Worker static inline bool AreBondsEqual(
70*f6dc9357SAndroid Build Coastguard Worker     const NCoderMixer2::CBond &a1,
71*f6dc9357SAndroid Build Coastguard Worker     const NCoderMixer2::CBond &a2)
72*f6dc9357SAndroid Build Coastguard Worker {
73*f6dc9357SAndroid Build Coastguard Worker   return
74*f6dc9357SAndroid Build Coastguard Worker     (a1.PackIndex == a2.PackIndex) &&
75*f6dc9357SAndroid Build Coastguard Worker     (a1.UnpackIndex == a2.UnpackIndex);
76*f6dc9357SAndroid Build Coastguard Worker }
77*f6dc9357SAndroid Build Coastguard Worker 
78*f6dc9357SAndroid Build Coastguard Worker static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
79*f6dc9357SAndroid Build Coastguard Worker {
80*f6dc9357SAndroid Build Coastguard Worker   if (a1.Coders.Size() != a2.Coders.Size())
81*f6dc9357SAndroid Build Coastguard Worker     return false;
82*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
83*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < a1.Coders.Size(); i++)
84*f6dc9357SAndroid Build Coastguard Worker     if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
85*f6dc9357SAndroid Build Coastguard Worker       return false;
86*f6dc9357SAndroid Build Coastguard Worker 
87*f6dc9357SAndroid Build Coastguard Worker   if (a1.Bonds.Size() != a2.Bonds.Size())
88*f6dc9357SAndroid Build Coastguard Worker     return false;
89*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < a1.Bonds.Size(); i++)
90*f6dc9357SAndroid Build Coastguard Worker     if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))
91*f6dc9357SAndroid Build Coastguard Worker       return false;
92*f6dc9357SAndroid Build Coastguard Worker 
93*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
94*f6dc9357SAndroid Build Coastguard Worker     if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
95*f6dc9357SAndroid Build Coastguard Worker       return false;
96*f6dc9357SAndroid Build Coastguard Worker 
97*f6dc9357SAndroid Build Coastguard Worker   if (a1.PackStreams.Size() != a2.PackStreams.Size())
98*f6dc9357SAndroid Build Coastguard Worker     return false;
99*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < a1.PackStreams.Size(); i++)
100*f6dc9357SAndroid Build Coastguard Worker     if (a1.PackStreams[i] != a2.PackStreams[i])
101*f6dc9357SAndroid Build Coastguard Worker       return false;
102*f6dc9357SAndroid Build Coastguard Worker 
103*f6dc9357SAndroid Build Coastguard Worker   /*
104*f6dc9357SAndroid Build Coastguard Worker   if (a1.UnpackCoder != a2.UnpackCoder)
105*f6dc9357SAndroid Build Coastguard Worker     return false;
106*f6dc9357SAndroid Build Coastguard Worker   */
107*f6dc9357SAndroid Build Coastguard Worker   return true;
108*f6dc9357SAndroid Build Coastguard Worker }
109*f6dc9357SAndroid Build Coastguard Worker 
110*f6dc9357SAndroid Build Coastguard Worker CDecoder::CDecoder(bool useMixerMT):
111*f6dc9357SAndroid Build Coastguard Worker     _bindInfoPrev_Defined(false)
112*f6dc9357SAndroid Build Coastguard Worker {
113*f6dc9357SAndroid Build Coastguard Worker   #if defined(USE_MIXER_ST) && defined(USE_MIXER_MT)
114*f6dc9357SAndroid Build Coastguard Worker   _useMixerMT = useMixerMT;
115*f6dc9357SAndroid Build Coastguard Worker   #else
116*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(useMixerMT)
117*f6dc9357SAndroid Build Coastguard Worker   #endif
118*f6dc9357SAndroid Build Coastguard Worker }
119*f6dc9357SAndroid Build Coastguard Worker 
120*f6dc9357SAndroid Build Coastguard Worker 
121*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_0(
122*f6dc9357SAndroid Build Coastguard Worker   CLockedInStream
123*f6dc9357SAndroid Build Coastguard Worker )
124*f6dc9357SAndroid Build Coastguard Worker public:
125*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IInStream> Stream;
126*f6dc9357SAndroid Build Coastguard Worker   UInt64 Pos;
127*f6dc9357SAndroid Build Coastguard Worker 
128*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_MIXER_MT
129*f6dc9357SAndroid Build Coastguard Worker   NWindows::NSynchronization::CCriticalSection CriticalSection;
130*f6dc9357SAndroid Build Coastguard Worker   #endif
131*f6dc9357SAndroid Build Coastguard Worker };
132*f6dc9357SAndroid Build Coastguard Worker 
133*f6dc9357SAndroid Build Coastguard Worker 
134*f6dc9357SAndroid Build Coastguard Worker #ifdef USE_MIXER_MT
135*f6dc9357SAndroid Build Coastguard Worker 
136*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1(
137*f6dc9357SAndroid Build Coastguard Worker   CLockedSequentialInStreamMT
138*f6dc9357SAndroid Build Coastguard Worker   , ISequentialInStream
139*f6dc9357SAndroid Build Coastguard Worker )
140*f6dc9357SAndroid Build Coastguard Worker   CLockedInStream *_glob;
141*f6dc9357SAndroid Build Coastguard Worker   UInt64 _pos;
142*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IUnknown> _globRef;
143*f6dc9357SAndroid Build Coastguard Worker public:
144*f6dc9357SAndroid Build Coastguard Worker   void Init(CLockedInStream *lockedInStream, UInt64 startPos)
145*f6dc9357SAndroid Build Coastguard Worker   {
146*f6dc9357SAndroid Build Coastguard Worker     _globRef = lockedInStream;
147*f6dc9357SAndroid Build Coastguard Worker     _glob = lockedInStream;
148*f6dc9357SAndroid Build Coastguard Worker     _pos = startPos;
149*f6dc9357SAndroid Build Coastguard Worker   }
150*f6dc9357SAndroid Build Coastguard Worker };
151*f6dc9357SAndroid Build Coastguard Worker 
152*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize))
153*f6dc9357SAndroid Build Coastguard Worker {
154*f6dc9357SAndroid Build Coastguard Worker   NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
155*f6dc9357SAndroid Build Coastguard Worker 
156*f6dc9357SAndroid Build Coastguard Worker   if (_pos != _glob->Pos)
157*f6dc9357SAndroid Build Coastguard Worker   {
158*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekSet(_glob->Stream, _pos))
159*f6dc9357SAndroid Build Coastguard Worker     _glob->Pos = _pos;
160*f6dc9357SAndroid Build Coastguard Worker   }
161*f6dc9357SAndroid Build Coastguard Worker 
162*f6dc9357SAndroid Build Coastguard Worker   UInt32 realProcessedSize = 0;
163*f6dc9357SAndroid Build Coastguard Worker   const HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
164*f6dc9357SAndroid Build Coastguard Worker   _pos += realProcessedSize;
165*f6dc9357SAndroid Build Coastguard Worker   _glob->Pos = _pos;
166*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
167*f6dc9357SAndroid Build Coastguard Worker     *processedSize = realProcessedSize;
168*f6dc9357SAndroid Build Coastguard Worker   return res;
169*f6dc9357SAndroid Build Coastguard Worker }
170*f6dc9357SAndroid Build Coastguard Worker 
171*f6dc9357SAndroid Build Coastguard Worker #endif
172*f6dc9357SAndroid Build Coastguard Worker 
173*f6dc9357SAndroid Build Coastguard Worker 
174*f6dc9357SAndroid Build Coastguard Worker #ifdef USE_MIXER_ST
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1(
177*f6dc9357SAndroid Build Coastguard Worker   CLockedSequentialInStreamST
178*f6dc9357SAndroid Build Coastguard Worker   , ISequentialInStream
179*f6dc9357SAndroid Build Coastguard Worker )
180*f6dc9357SAndroid Build Coastguard Worker   CLockedInStream *_glob;
181*f6dc9357SAndroid Build Coastguard Worker   UInt64 _pos;
182*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IUnknown> _globRef;
183*f6dc9357SAndroid Build Coastguard Worker public:
184*f6dc9357SAndroid Build Coastguard Worker   void Init(CLockedInStream *lockedInStream, UInt64 startPos)
185*f6dc9357SAndroid Build Coastguard Worker   {
186*f6dc9357SAndroid Build Coastguard Worker     _globRef = lockedInStream;
187*f6dc9357SAndroid Build Coastguard Worker     _glob = lockedInStream;
188*f6dc9357SAndroid Build Coastguard Worker     _pos = startPos;
189*f6dc9357SAndroid Build Coastguard Worker   }
190*f6dc9357SAndroid Build Coastguard Worker };
191*f6dc9357SAndroid Build Coastguard Worker 
192*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize))
193*f6dc9357SAndroid Build Coastguard Worker {
194*f6dc9357SAndroid Build Coastguard Worker   if (_pos != _glob->Pos)
195*f6dc9357SAndroid Build Coastguard Worker   {
196*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekSet(_glob->Stream, _pos))
197*f6dc9357SAndroid Build Coastguard Worker     _glob->Pos = _pos;
198*f6dc9357SAndroid Build Coastguard Worker   }
199*f6dc9357SAndroid Build Coastguard Worker 
200*f6dc9357SAndroid Build Coastguard Worker   UInt32 realProcessedSize = 0;
201*f6dc9357SAndroid Build Coastguard Worker   const HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
202*f6dc9357SAndroid Build Coastguard Worker   _pos += realProcessedSize;
203*f6dc9357SAndroid Build Coastguard Worker   _glob->Pos = _pos;
204*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
205*f6dc9357SAndroid Build Coastguard Worker     *processedSize = realProcessedSize;
206*f6dc9357SAndroid Build Coastguard Worker   return res;
207*f6dc9357SAndroid Build Coastguard Worker }
208*f6dc9357SAndroid Build Coastguard Worker 
209*f6dc9357SAndroid Build Coastguard Worker #endif
210*f6dc9357SAndroid Build Coastguard Worker 
211*f6dc9357SAndroid Build Coastguard Worker 
212*f6dc9357SAndroid Build Coastguard Worker 
213*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::Decode(
214*f6dc9357SAndroid Build Coastguard Worker     DECL_EXTERNAL_CODECS_LOC_VARS
215*f6dc9357SAndroid Build Coastguard Worker     IInStream *inStream,
216*f6dc9357SAndroid Build Coastguard Worker     UInt64 startPos,
217*f6dc9357SAndroid Build Coastguard Worker     const CFolders &folders, unsigned folderIndex,
218*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *unpackSize
219*f6dc9357SAndroid Build Coastguard Worker 
220*f6dc9357SAndroid Build Coastguard Worker     , ISequentialOutStream *outStream
221*f6dc9357SAndroid Build Coastguard Worker     , ICompressProgressInfo *compressProgress
222*f6dc9357SAndroid Build Coastguard Worker 
223*f6dc9357SAndroid Build Coastguard Worker     , ISequentialInStream **
224*f6dc9357SAndroid Build Coastguard Worker         #ifdef USE_MIXER_ST
225*f6dc9357SAndroid Build Coastguard Worker         inStreamMainRes
226*f6dc9357SAndroid Build Coastguard Worker         #endif
227*f6dc9357SAndroid Build Coastguard Worker 
228*f6dc9357SAndroid Build Coastguard Worker     , bool &dataAfterEnd_Error
229*f6dc9357SAndroid Build Coastguard Worker 
230*f6dc9357SAndroid Build Coastguard Worker     Z7_7Z_DECODER_CRYPRO_VARS_DECL
231*f6dc9357SAndroid Build Coastguard Worker 
232*f6dc9357SAndroid Build Coastguard Worker     #if !defined(Z7_ST)
233*f6dc9357SAndroid Build Coastguard Worker     , bool mtMode, UInt32 numThreads, UInt64 memUsage
234*f6dc9357SAndroid Build Coastguard Worker     #endif
235*f6dc9357SAndroid Build Coastguard Worker     )
236*f6dc9357SAndroid Build Coastguard Worker {
237*f6dc9357SAndroid Build Coastguard Worker   dataAfterEnd_Error = false;
238*f6dc9357SAndroid Build Coastguard Worker 
239*f6dc9357SAndroid Build Coastguard Worker   const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
240*f6dc9357SAndroid Build Coastguard Worker   CFolderEx folderInfo;
241*f6dc9357SAndroid Build Coastguard Worker   folders.ParseFolderEx(folderIndex, folderInfo);
242*f6dc9357SAndroid Build Coastguard Worker 
243*f6dc9357SAndroid Build Coastguard Worker   if (!folderInfo.IsDecodingSupported())
244*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
245*f6dc9357SAndroid Build Coastguard Worker 
246*f6dc9357SAndroid Build Coastguard Worker   CBindInfoEx bindInfo;
247*f6dc9357SAndroid Build Coastguard Worker   Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);
248*f6dc9357SAndroid Build Coastguard Worker   if (!bindInfo.CalcMapsAndCheck())
249*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
250*f6dc9357SAndroid Build Coastguard Worker 
251*f6dc9357SAndroid Build Coastguard Worker   UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);
252*f6dc9357SAndroid Build Coastguard Worker   bool fullUnpack = true;
253*f6dc9357SAndroid Build Coastguard Worker   if (unpackSize)
254*f6dc9357SAndroid Build Coastguard Worker   {
255*f6dc9357SAndroid Build Coastguard Worker     if (*unpackSize > folderUnpackSize)
256*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
257*f6dc9357SAndroid Build Coastguard Worker     fullUnpack = (*unpackSize == folderUnpackSize);
258*f6dc9357SAndroid Build Coastguard Worker   }
259*f6dc9357SAndroid Build Coastguard Worker 
260*f6dc9357SAndroid Build Coastguard Worker   /*
261*f6dc9357SAndroid Build Coastguard Worker   We don't need to init isEncrypted and passwordIsDefined
262*f6dc9357SAndroid Build Coastguard Worker   We must upgrade them only
263*f6dc9357SAndroid Build Coastguard Worker 
264*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_NO_CRYPTO
265*f6dc9357SAndroid Build Coastguard Worker   isEncrypted = false;
266*f6dc9357SAndroid Build Coastguard Worker   passwordIsDefined = false;
267*f6dc9357SAndroid Build Coastguard Worker   #endif
268*f6dc9357SAndroid Build Coastguard Worker   */
269*f6dc9357SAndroid Build Coastguard Worker 
270*f6dc9357SAndroid Build Coastguard Worker   if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
271*f6dc9357SAndroid Build Coastguard Worker   {
272*f6dc9357SAndroid Build Coastguard Worker     _bindInfoPrev_Defined = false;
273*f6dc9357SAndroid Build Coastguard Worker     _mixerRef.Release();
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker     #ifdef USE_MIXER_MT
276*f6dc9357SAndroid Build Coastguard Worker     #ifdef USE_MIXER_ST
277*f6dc9357SAndroid Build Coastguard Worker     if (_useMixerMT)
278*f6dc9357SAndroid Build Coastguard Worker     #endif
279*f6dc9357SAndroid Build Coastguard Worker     {
280*f6dc9357SAndroid Build Coastguard Worker       _mixerMT = new NCoderMixer2::CMixerMT(false);
281*f6dc9357SAndroid Build Coastguard Worker       _mixerRef = _mixerMT;
282*f6dc9357SAndroid Build Coastguard Worker       _mixer = _mixerMT;
283*f6dc9357SAndroid Build Coastguard Worker     }
284*f6dc9357SAndroid Build Coastguard Worker     #ifdef USE_MIXER_ST
285*f6dc9357SAndroid Build Coastguard Worker     else
286*f6dc9357SAndroid Build Coastguard Worker     #endif
287*f6dc9357SAndroid Build Coastguard Worker     #endif
288*f6dc9357SAndroid Build Coastguard Worker     {
289*f6dc9357SAndroid Build Coastguard Worker       #ifdef USE_MIXER_ST
290*f6dc9357SAndroid Build Coastguard Worker       _mixerST = new NCoderMixer2::CMixerST(false);
291*f6dc9357SAndroid Build Coastguard Worker       _mixerRef = _mixerST;
292*f6dc9357SAndroid Build Coastguard Worker       _mixer = _mixerST;
293*f6dc9357SAndroid Build Coastguard Worker       #endif
294*f6dc9357SAndroid Build Coastguard Worker     }
295*f6dc9357SAndroid Build Coastguard Worker 
296*f6dc9357SAndroid Build Coastguard Worker     RINOK(_mixer->SetBindInfo(bindInfo))
297*f6dc9357SAndroid Build Coastguard Worker 
298*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR(i, folderInfo.Coders)
299*f6dc9357SAndroid Build Coastguard Worker     {
300*f6dc9357SAndroid Build Coastguard Worker       const CCoderInfo &coderInfo = folderInfo.Coders[i];
301*f6dc9357SAndroid Build Coastguard Worker 
302*f6dc9357SAndroid Build Coastguard Worker       #ifndef Z7_SFX
303*f6dc9357SAndroid Build Coastguard Worker       // we don't support RAR codecs here
304*f6dc9357SAndroid Build Coastguard Worker       if ((coderInfo.MethodID >> 8) == 0x403)
305*f6dc9357SAndroid Build Coastguard Worker         return E_NOTIMPL;
306*f6dc9357SAndroid Build Coastguard Worker       #endif
307*f6dc9357SAndroid Build Coastguard Worker 
308*f6dc9357SAndroid Build Coastguard Worker       CCreatedCoder cod;
309*f6dc9357SAndroid Build Coastguard Worker       RINOK(CreateCoder_Id(
310*f6dc9357SAndroid Build Coastguard Worker           EXTERNAL_CODECS_LOC_VARS
311*f6dc9357SAndroid Build Coastguard Worker           coderInfo.MethodID, false, cod))
312*f6dc9357SAndroid Build Coastguard Worker 
313*f6dc9357SAndroid Build Coastguard Worker       if (coderInfo.IsSimpleCoder())
314*f6dc9357SAndroid Build Coastguard Worker       {
315*f6dc9357SAndroid Build Coastguard Worker         if (!cod.Coder)
316*f6dc9357SAndroid Build Coastguard Worker           return E_NOTIMPL;
317*f6dc9357SAndroid Build Coastguard Worker         // CMethodId m = coderInfo.MethodID;
318*f6dc9357SAndroid Build Coastguard Worker         // isFilter = (IsFilterMethod(m) || m == k_AES);
319*f6dc9357SAndroid Build Coastguard Worker       }
320*f6dc9357SAndroid Build Coastguard Worker       else
321*f6dc9357SAndroid Build Coastguard Worker       {
322*f6dc9357SAndroid Build Coastguard Worker         if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
323*f6dc9357SAndroid Build Coastguard Worker           return E_NOTIMPL;
324*f6dc9357SAndroid Build Coastguard Worker       }
325*f6dc9357SAndroid Build Coastguard Worker       _mixer->AddCoder(cod);
326*f6dc9357SAndroid Build Coastguard Worker 
327*f6dc9357SAndroid Build Coastguard Worker       // now there is no codec that uses another external codec
328*f6dc9357SAndroid Build Coastguard Worker       /*
329*f6dc9357SAndroid Build Coastguard Worker       #ifdef Z7_EXTERNAL_CODECS
330*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
331*f6dc9357SAndroid Build Coastguard Worker       decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
332*f6dc9357SAndroid Build Coastguard Worker       if (setCompressCodecsInfo)
333*f6dc9357SAndroid Build Coastguard Worker       {
334*f6dc9357SAndroid Build Coastguard Worker         // we must use g_ExternalCodecs also
335*f6dc9357SAndroid Build Coastguard Worker         RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs));
336*f6dc9357SAndroid Build Coastguard Worker       }
337*f6dc9357SAndroid Build Coastguard Worker       #endif
338*f6dc9357SAndroid Build Coastguard Worker       */
339*f6dc9357SAndroid Build Coastguard Worker     }
340*f6dc9357SAndroid Build Coastguard Worker 
341*f6dc9357SAndroid Build Coastguard Worker     _bindInfoPrev = bindInfo;
342*f6dc9357SAndroid Build Coastguard Worker     _bindInfoPrev_Defined = true;
343*f6dc9357SAndroid Build Coastguard Worker   }
344*f6dc9357SAndroid Build Coastguard Worker 
345*f6dc9357SAndroid Build Coastguard Worker   RINOK(_mixer->ReInit2())
346*f6dc9357SAndroid Build Coastguard Worker 
347*f6dc9357SAndroid Build Coastguard Worker   UInt32 packStreamIndex = 0;
348*f6dc9357SAndroid Build Coastguard Worker   UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
349*f6dc9357SAndroid Build Coastguard Worker 
350*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
351*f6dc9357SAndroid Build Coastguard Worker 
352*f6dc9357SAndroid Build Coastguard Worker   #if !defined(Z7_ST)
353*f6dc9357SAndroid Build Coastguard Worker   bool mt_wasUsed = false;
354*f6dc9357SAndroid Build Coastguard Worker   #endif
355*f6dc9357SAndroid Build Coastguard Worker 
356*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < folderInfo.Coders.Size(); i++)
357*f6dc9357SAndroid Build Coastguard Worker   {
358*f6dc9357SAndroid Build Coastguard Worker     const CCoderInfo &coderInfo = folderInfo.Coders[i];
359*f6dc9357SAndroid Build Coastguard Worker     IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
360*f6dc9357SAndroid Build Coastguard Worker 
361*f6dc9357SAndroid Build Coastguard Worker     // now there is no codec that uses another external codec
362*f6dc9357SAndroid Build Coastguard Worker     /*
363*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_EXTERNAL_CODECS
364*f6dc9357SAndroid Build Coastguard Worker     {
365*f6dc9357SAndroid Build Coastguard Worker       Z7_DECL_CMyComPtr_QI_FROM(ISetCompressCodecsInfo,
366*f6dc9357SAndroid Build Coastguard Worker           setCompressCodecsInfo, decoder)
367*f6dc9357SAndroid Build Coastguard Worker       if (setCompressCodecsInfo)
368*f6dc9357SAndroid Build Coastguard Worker       {
369*f6dc9357SAndroid Build Coastguard Worker         // we must use g_ExternalCodecs also
370*f6dc9357SAndroid Build Coastguard Worker         RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs))
371*f6dc9357SAndroid Build Coastguard Worker       }
372*f6dc9357SAndroid Build Coastguard Worker     }
373*f6dc9357SAndroid Build Coastguard Worker     #endif
374*f6dc9357SAndroid Build Coastguard Worker     */
375*f6dc9357SAndroid Build Coastguard Worker 
376*f6dc9357SAndroid Build Coastguard Worker     #if !defined(Z7_ST)
377*f6dc9357SAndroid Build Coastguard Worker     if (!mt_wasUsed)
378*f6dc9357SAndroid Build Coastguard Worker     {
379*f6dc9357SAndroid Build Coastguard Worker       if (mtMode)
380*f6dc9357SAndroid Build Coastguard Worker       {
381*f6dc9357SAndroid Build Coastguard Worker         Z7_DECL_CMyComPtr_QI_FROM(ICompressSetCoderMt,
382*f6dc9357SAndroid Build Coastguard Worker             setCoderMt, decoder)
383*f6dc9357SAndroid Build Coastguard Worker         if (setCoderMt)
384*f6dc9357SAndroid Build Coastguard Worker         {
385*f6dc9357SAndroid Build Coastguard Worker           mt_wasUsed = true;
386*f6dc9357SAndroid Build Coastguard Worker           RINOK(setCoderMt->SetNumberOfThreads(numThreads))
387*f6dc9357SAndroid Build Coastguard Worker         }
388*f6dc9357SAndroid Build Coastguard Worker       }
389*f6dc9357SAndroid Build Coastguard Worker       // if (memUsage != 0)
390*f6dc9357SAndroid Build Coastguard Worker       {
391*f6dc9357SAndroid Build Coastguard Worker         Z7_DECL_CMyComPtr_QI_FROM(ICompressSetMemLimit,
392*f6dc9357SAndroid Build Coastguard Worker             setMemLimit, decoder)
393*f6dc9357SAndroid Build Coastguard Worker         if (setMemLimit)
394*f6dc9357SAndroid Build Coastguard Worker         {
395*f6dc9357SAndroid Build Coastguard Worker           mt_wasUsed = true;
396*f6dc9357SAndroid Build Coastguard Worker           RINOK(setMemLimit->SetMemLimit(memUsage))
397*f6dc9357SAndroid Build Coastguard Worker         }
398*f6dc9357SAndroid Build Coastguard Worker       }
399*f6dc9357SAndroid Build Coastguard Worker     }
400*f6dc9357SAndroid Build Coastguard Worker     #endif
401*f6dc9357SAndroid Build Coastguard Worker 
402*f6dc9357SAndroid Build Coastguard Worker     {
403*f6dc9357SAndroid Build Coastguard Worker       Z7_DECL_CMyComPtr_QI_FROM(
404*f6dc9357SAndroid Build Coastguard Worker           ICompressSetDecoderProperties2,
405*f6dc9357SAndroid Build Coastguard Worker           setDecoderProperties, decoder)
406*f6dc9357SAndroid Build Coastguard Worker       const CByteBuffer &props = coderInfo.Props;
407*f6dc9357SAndroid Build Coastguard Worker       const UInt32 size32 = (UInt32)props.Size();
408*f6dc9357SAndroid Build Coastguard Worker       if (props.Size() != size32)
409*f6dc9357SAndroid Build Coastguard Worker         return E_NOTIMPL;
410*f6dc9357SAndroid Build Coastguard Worker       if (setDecoderProperties)
411*f6dc9357SAndroid Build Coastguard Worker       {
412*f6dc9357SAndroid Build Coastguard Worker         HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, size32);
413*f6dc9357SAndroid Build Coastguard Worker         if (res == E_INVALIDARG)
414*f6dc9357SAndroid Build Coastguard Worker           res = E_NOTIMPL;
415*f6dc9357SAndroid Build Coastguard Worker         RINOK(res)
416*f6dc9357SAndroid Build Coastguard Worker       }
417*f6dc9357SAndroid Build Coastguard Worker       else if (size32 != 0)
418*f6dc9357SAndroid Build Coastguard Worker       {
419*f6dc9357SAndroid Build Coastguard Worker         // v23: we fail, if decoder doesn't support properties
420*f6dc9357SAndroid Build Coastguard Worker         return E_NOTIMPL;
421*f6dc9357SAndroid Build Coastguard Worker       }
422*f6dc9357SAndroid Build Coastguard Worker     }
423*f6dc9357SAndroid Build Coastguard Worker 
424*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_NO_CRYPTO
425*f6dc9357SAndroid Build Coastguard Worker     {
426*f6dc9357SAndroid Build Coastguard Worker       Z7_DECL_CMyComPtr_QI_FROM(
427*f6dc9357SAndroid Build Coastguard Worker           ICryptoSetPassword,
428*f6dc9357SAndroid Build Coastguard Worker           cryptoSetPassword, decoder)
429*f6dc9357SAndroid Build Coastguard Worker       if (cryptoSetPassword)
430*f6dc9357SAndroid Build Coastguard Worker       {
431*f6dc9357SAndroid Build Coastguard Worker         isEncrypted = true;
432*f6dc9357SAndroid Build Coastguard Worker         if (!getTextPassword)
433*f6dc9357SAndroid Build Coastguard Worker           return E_NOTIMPL;
434*f6dc9357SAndroid Build Coastguard Worker         CMyComBSTR_Wipe passwordBSTR;
435*f6dc9357SAndroid Build Coastguard Worker         RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR))
436*f6dc9357SAndroid Build Coastguard Worker         passwordIsDefined = true;
437*f6dc9357SAndroid Build Coastguard Worker         password.Wipe_and_Empty();
438*f6dc9357SAndroid Build Coastguard Worker         size_t len = 0;
439*f6dc9357SAndroid Build Coastguard Worker         if (passwordBSTR)
440*f6dc9357SAndroid Build Coastguard Worker         {
441*f6dc9357SAndroid Build Coastguard Worker           password = passwordBSTR;
442*f6dc9357SAndroid Build Coastguard Worker           len = password.Len();
443*f6dc9357SAndroid Build Coastguard Worker         }
444*f6dc9357SAndroid Build Coastguard Worker         CByteBuffer_Wipe buffer(len * 2);
445*f6dc9357SAndroid Build Coastguard Worker         const LPCOLESTR psw = passwordBSTR;
446*f6dc9357SAndroid Build Coastguard Worker         for (size_t k = 0; k < len; k++)
447*f6dc9357SAndroid Build Coastguard Worker         {
448*f6dc9357SAndroid Build Coastguard Worker           const wchar_t c = psw[k];
449*f6dc9357SAndroid Build Coastguard Worker           ((Byte *)buffer)[k * 2] = (Byte)c;
450*f6dc9357SAndroid Build Coastguard Worker           ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);
451*f6dc9357SAndroid Build Coastguard Worker         }
452*f6dc9357SAndroid Build Coastguard Worker         RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()))
453*f6dc9357SAndroid Build Coastguard Worker       }
454*f6dc9357SAndroid Build Coastguard Worker     }
455*f6dc9357SAndroid Build Coastguard Worker     #endif
456*f6dc9357SAndroid Build Coastguard Worker 
457*f6dc9357SAndroid Build Coastguard Worker     bool finishMode = false;
458*f6dc9357SAndroid Build Coastguard Worker     {
459*f6dc9357SAndroid Build Coastguard Worker       Z7_DECL_CMyComPtr_QI_FROM(
460*f6dc9357SAndroid Build Coastguard Worker           ICompressSetFinishMode,
461*f6dc9357SAndroid Build Coastguard Worker           setFinishMode, decoder)
462*f6dc9357SAndroid Build Coastguard Worker       if (setFinishMode)
463*f6dc9357SAndroid Build Coastguard Worker       {
464*f6dc9357SAndroid Build Coastguard Worker         finishMode = fullUnpack;
465*f6dc9357SAndroid Build Coastguard Worker         RINOK(setFinishMode->SetFinishMode(BoolToUInt(finishMode)))
466*f6dc9357SAndroid Build Coastguard Worker       }
467*f6dc9357SAndroid Build Coastguard Worker     }
468*f6dc9357SAndroid Build Coastguard Worker 
469*f6dc9357SAndroid Build Coastguard Worker     UInt32 numStreams = (UInt32)coderInfo.NumStreams;
470*f6dc9357SAndroid Build Coastguard Worker 
471*f6dc9357SAndroid Build Coastguard Worker     CObjArray<UInt64> packSizes(numStreams);
472*f6dc9357SAndroid Build Coastguard Worker     CObjArray<const UInt64 *> packSizesPointers(numStreams);
473*f6dc9357SAndroid Build Coastguard Worker 
474*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
475*f6dc9357SAndroid Build Coastguard Worker     {
476*f6dc9357SAndroid Build Coastguard Worker       int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
477*f6dc9357SAndroid Build Coastguard Worker 
478*f6dc9357SAndroid Build Coastguard Worker       if (bond >= 0)
479*f6dc9357SAndroid Build Coastguard Worker         packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
480*f6dc9357SAndroid Build Coastguard Worker       else
481*f6dc9357SAndroid Build Coastguard Worker       {
482*f6dc9357SAndroid Build Coastguard Worker         int index = folderInfo.Find_in_PackStreams(packStreamIndex);
483*f6dc9357SAndroid Build Coastguard Worker         if (index < 0)
484*f6dc9357SAndroid Build Coastguard Worker           return E_NOTIMPL;
485*f6dc9357SAndroid Build Coastguard Worker         packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];
486*f6dc9357SAndroid Build Coastguard Worker         packSizesPointers[j] = &packSizes[j];
487*f6dc9357SAndroid Build Coastguard Worker       }
488*f6dc9357SAndroid Build Coastguard Worker     }
489*f6dc9357SAndroid Build Coastguard Worker 
490*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *unpackSizesPointer =
491*f6dc9357SAndroid Build Coastguard Worker         (unpackSize && i == bindInfo.UnpackCoder) ?
492*f6dc9357SAndroid Build Coastguard Worker             unpackSize :
493*f6dc9357SAndroid Build Coastguard Worker             &folders.CoderUnpackSizes[unpackStreamIndexStart + i];
494*f6dc9357SAndroid Build Coastguard Worker 
495*f6dc9357SAndroid Build Coastguard Worker     _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers, finishMode);
496*f6dc9357SAndroid Build Coastguard Worker   }
497*f6dc9357SAndroid Build Coastguard Worker 
498*f6dc9357SAndroid Build Coastguard Worker   if (outStream)
499*f6dc9357SAndroid Build Coastguard Worker   {
500*f6dc9357SAndroid Build Coastguard Worker     _mixer->SelectMainCoder(!fullUnpack);
501*f6dc9357SAndroid Build Coastguard Worker   }
502*f6dc9357SAndroid Build Coastguard Worker 
503*f6dc9357SAndroid Build Coastguard Worker   CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
504*f6dc9357SAndroid Build Coastguard Worker 
505*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<IUnknown, CLockedInStream> lockedInStream;
506*f6dc9357SAndroid Build Coastguard Worker 
507*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_MIXER_MT
508*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_MIXER_ST
509*f6dc9357SAndroid Build Coastguard Worker   bool needMtLock = _useMixerMT;
510*f6dc9357SAndroid Build Coastguard Worker   #endif
511*f6dc9357SAndroid Build Coastguard Worker   #endif
512*f6dc9357SAndroid Build Coastguard Worker 
513*f6dc9357SAndroid Build Coastguard Worker   if (folderInfo.PackStreams.Size() > 1)
514*f6dc9357SAndroid Build Coastguard Worker   {
515*f6dc9357SAndroid Build Coastguard Worker     // lockedInStream.Pos = (UInt64)(Int64)-1;
516*f6dc9357SAndroid Build Coastguard Worker     // RINOK(InStream_GetPos(inStream, lockedInStream.Pos))
517*f6dc9357SAndroid Build Coastguard Worker     RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStream->Pos))
518*f6dc9357SAndroid Build Coastguard Worker     lockedInStream->Stream = inStream;
519*f6dc9357SAndroid Build Coastguard Worker 
520*f6dc9357SAndroid Build Coastguard Worker     #ifdef USE_MIXER_MT
521*f6dc9357SAndroid Build Coastguard Worker     #ifdef USE_MIXER_ST
522*f6dc9357SAndroid Build Coastguard Worker     /*
523*f6dc9357SAndroid Build Coastguard Worker       For ST-mixer mode:
524*f6dc9357SAndroid Build Coastguard Worker       If parallel input stream reading from pack streams is possible,
525*f6dc9357SAndroid Build Coastguard Worker       we must use MT-lock for packed streams.
526*f6dc9357SAndroid Build Coastguard Worker       Internal decoders in 7-Zip will not read pack streams in parallel in ST-mixer mode.
527*f6dc9357SAndroid Build Coastguard Worker       So we force to needMtLock mode only if there is unknown (external) decoder.
528*f6dc9357SAndroid Build Coastguard Worker     */
529*f6dc9357SAndroid Build Coastguard Worker     if (!needMtLock && _mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
530*f6dc9357SAndroid Build Coastguard Worker       needMtLock = true;
531*f6dc9357SAndroid Build Coastguard Worker     #endif
532*f6dc9357SAndroid Build Coastguard Worker     #endif
533*f6dc9357SAndroid Build Coastguard Worker   }
534*f6dc9357SAndroid Build Coastguard Worker 
535*f6dc9357SAndroid Build Coastguard Worker   for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
536*f6dc9357SAndroid Build Coastguard Worker   {
537*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ISequentialInStream> packStream;
538*f6dc9357SAndroid Build Coastguard Worker     const UInt64 packPos = startPos + packPositions[j];
539*f6dc9357SAndroid Build Coastguard Worker 
540*f6dc9357SAndroid Build Coastguard Worker     if (folderInfo.PackStreams.Size() == 1)
541*f6dc9357SAndroid Build Coastguard Worker     {
542*f6dc9357SAndroid Build Coastguard Worker       RINOK(InStream_SeekSet(inStream, packPos))
543*f6dc9357SAndroid Build Coastguard Worker       packStream = inStream;
544*f6dc9357SAndroid Build Coastguard Worker     }
545*f6dc9357SAndroid Build Coastguard Worker     else
546*f6dc9357SAndroid Build Coastguard Worker     {
547*f6dc9357SAndroid Build Coastguard Worker       #ifdef USE_MIXER_MT
548*f6dc9357SAndroid Build Coastguard Worker       #ifdef USE_MIXER_ST
549*f6dc9357SAndroid Build Coastguard Worker       if (needMtLock)
550*f6dc9357SAndroid Build Coastguard Worker       #endif
551*f6dc9357SAndroid Build Coastguard Worker       {
552*f6dc9357SAndroid Build Coastguard Worker         CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
553*f6dc9357SAndroid Build Coastguard Worker         packStream = lockedStreamImpSpec;
554*f6dc9357SAndroid Build Coastguard Worker         lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);
555*f6dc9357SAndroid Build Coastguard Worker       }
556*f6dc9357SAndroid Build Coastguard Worker       #ifdef USE_MIXER_ST
557*f6dc9357SAndroid Build Coastguard Worker       else
558*f6dc9357SAndroid Build Coastguard Worker       #endif
559*f6dc9357SAndroid Build Coastguard Worker       #endif
560*f6dc9357SAndroid Build Coastguard Worker       {
561*f6dc9357SAndroid Build Coastguard Worker         #ifdef USE_MIXER_ST
562*f6dc9357SAndroid Build Coastguard Worker         CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
563*f6dc9357SAndroid Build Coastguard Worker         packStream = lockedStreamImpSpec;
564*f6dc9357SAndroid Build Coastguard Worker         lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);
565*f6dc9357SAndroid Build Coastguard Worker         #endif
566*f6dc9357SAndroid Build Coastguard Worker       }
567*f6dc9357SAndroid Build Coastguard Worker     }
568*f6dc9357SAndroid Build Coastguard Worker 
569*f6dc9357SAndroid Build Coastguard Worker     CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
570*f6dc9357SAndroid Build Coastguard Worker     inStreams.AddNew() = streamSpec;
571*f6dc9357SAndroid Build Coastguard Worker     streamSpec->SetStream(packStream);
572*f6dc9357SAndroid Build Coastguard Worker     streamSpec->Init(packPositions[j + 1] - packPositions[j]);
573*f6dc9357SAndroid Build Coastguard Worker   }
574*f6dc9357SAndroid Build Coastguard Worker 
575*f6dc9357SAndroid Build Coastguard Worker   const unsigned num = inStreams.Size();
576*f6dc9357SAndroid Build Coastguard Worker   CObjArray<ISequentialInStream *> inStreamPointers(num);
577*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < num; i++)
578*f6dc9357SAndroid Build Coastguard Worker     inStreamPointers[i] = inStreams[i];
579*f6dc9357SAndroid Build Coastguard Worker 
580*f6dc9357SAndroid Build Coastguard Worker   if (outStream)
581*f6dc9357SAndroid Build Coastguard Worker   {
582*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ICompressProgressInfo> progress2;
583*f6dc9357SAndroid Build Coastguard Worker     if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))
584*f6dc9357SAndroid Build Coastguard Worker       progress2 = new CDecProgress(compressProgress);
585*f6dc9357SAndroid Build Coastguard Worker 
586*f6dc9357SAndroid Build Coastguard Worker     ISequentialOutStream *outStreamPointer = outStream;
587*f6dc9357SAndroid Build Coastguard Worker     return _mixer->Code(inStreamPointers, &outStreamPointer,
588*f6dc9357SAndroid Build Coastguard Worker         progress2 ? (ICompressProgressInfo *)progress2 : compressProgress,
589*f6dc9357SAndroid Build Coastguard Worker         dataAfterEnd_Error);
590*f6dc9357SAndroid Build Coastguard Worker   }
591*f6dc9357SAndroid Build Coastguard Worker 
592*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_MIXER_ST
593*f6dc9357SAndroid Build Coastguard Worker     return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
594*f6dc9357SAndroid Build Coastguard Worker   #else
595*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
596*f6dc9357SAndroid Build Coastguard Worker   #endif
597*f6dc9357SAndroid Build Coastguard Worker }
598*f6dc9357SAndroid Build Coastguard Worker 
599*f6dc9357SAndroid Build Coastguard Worker }}
600