7 #include "../../IPassword.h"
8 #include "../../Common/LockedStream.h"
9 #include "../../Common/StreamObjects.h"
10 #include "../../Common/ProgressUtils.h"
11 #include "../../Common/LimitedStreams.h"
12 #include "../../Common/CreateCoder.h"
13 #include "../../Common/FilterCoder.h"
18 static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
19 CBindInfoEx &bindInfo)
23 for (i = 0; i < folder.BindPairs.Size(); i++)
25 NCoderMixer::CBindPair bindPair;
26 bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
27 bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
28 bindInfo.BindPairs.Add(bindPair);
30 UInt32 outStreamIndex = 0;
31 for (i = 0; i < folder.Coders.Size(); i++)
33 NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
34 const CCoderInfo &coderInfo = folder.Coders[i];
35 coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
36 coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
37 bindInfo.Coders.Add(coderStreamsInfo);
38 bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);
39 for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
40 if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
41 bindInfo.OutStreams.Add(outStreamIndex);
43 for (i = 0; i < folder.PackStreams.Size(); i++)
44 bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
47 static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
48 const NCoderMixer::CCoderStreamsInfo &a2)
50 return (a1.NumInStreams == a2.NumInStreams) &&
51 (a1.NumOutStreams == a2.NumOutStreams);
54 static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
56 return (a1.InIndex == a2.InIndex) &&
57 (a1.OutIndex == a2.OutIndex);
60 static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
62 if (a1.Coders.Size() != a2.Coders.Size())
65 for (i = 0; i < a1.Coders.Size(); i++)
66 if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
68 if (a1.BindPairs.Size() != a2.BindPairs.Size())
70 for (i = 0; i < a1.BindPairs.Size(); i++)
71 if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
73 for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
74 if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
76 if (a1.InStreams.Size() != a2.InStreams.Size())
78 if (a1.OutStreams.Size() != a2.OutStreams.Size())
83 CDecoder::CDecoder(bool multiThread)
88 _multiThread = multiThread;
89 _bindInfoExPrevIsDefined = false;
92 HRESULT CDecoder::Decode(
93 DECL_EXTERNAL_CODECS_LOC_VARS
96 const UInt64 *packSizes,
97 const CFolder &folderInfo,
98 ISequentialOutStream *outStream,
99 ICompressProgressInfo *compressProgress
101 , ICryptoGetTextPassword *getTextPassword
104 , bool mtMode, UInt32 numThreads
108 CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
110 CLockedInStream lockedInStream;
111 lockedInStream.Init(inStream);
113 for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
115 CLockedSequentialInStreamImp *lockedStreamImpSpec = new
116 CLockedSequentialInStreamImp;
117 CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
118 lockedStreamImpSpec->Init(&lockedInStream, startPos);
119 startPos += packSizes[j];
121 CLimitedSequentialInStream *streamSpec = new
122 CLimitedSequentialInStream;
123 CMyComPtr<ISequentialInStream> inStream = streamSpec;
124 streamSpec->SetStream(lockedStreamImp);
125 streamSpec->Init(packSizes[j]);
126 inStreams.Add(inStream);
129 int numCoders = folderInfo.Coders.Size();
131 CBindInfoEx bindInfo;
132 ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
133 bool createNewCoders;
134 if (!_bindInfoExPrevIsDefined)
135 createNewCoders = true;
137 createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
142 // _decoders2.Clear();
144 _mixerCoder.Release();
148 _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
149 _mixerCoder = _mixerCoderMTSpec;
150 _mixerCoderCommon = _mixerCoderMTSpec;
155 _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
156 _mixerCoder = _mixerCoderSTSpec;
157 _mixerCoderCommon = _mixerCoderSTSpec;
160 RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
162 for (i = 0; i < numCoders; i++)
164 const CCoderInfo &coderInfo = folderInfo.Coders[i];
167 CMyComPtr<ICompressCoder> decoder;
168 CMyComPtr<ICompressCoder2> decoder2;
170 EXTERNAL_CODECS_LOC_VARS
171 coderInfo.MethodID, decoder, decoder2, false));
172 CMyComPtr<IUnknown> decoderUnknown;
173 if (coderInfo.IsSimpleCoder())
178 decoderUnknown = (IUnknown *)decoder;
181 _mixerCoderMTSpec->AddCoder(decoder);
184 _mixerCoderSTSpec->AddCoder(decoder, false);
191 decoderUnknown = (IUnknown *)decoder2;
193 _mixerCoderMTSpec->AddCoder2(decoder2);
196 _mixerCoderSTSpec->AddCoder2(decoder2, false);
199 _decoders.Add(decoderUnknown);
200 #ifdef EXTERNAL_CODECS
201 CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
202 decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
203 if (setCompressCodecsInfo)
205 RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
209 _bindInfoExPrev = bindInfo;
210 _bindInfoExPrevIsDefined = true;
213 _mixerCoderCommon->ReInit();
215 UInt32 packStreamIndex = 0, unPackStreamIndex = 0;
216 UInt32 coderIndex = 0;
217 // UInt32 coder2Index = 0;
219 for (i = 0; i < numCoders; i++)
221 const CCoderInfo &coderInfo = folderInfo.Coders[i];
222 CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
225 CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
226 decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
227 if (setDecoderProperties)
229 const CByteBuffer &properties = coderInfo.Properties;
230 size_t size = properties.GetCapacity();
231 if (size > 0xFFFFFFFF)
235 RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size));
243 CMyComPtr<ICompressSetCoderMt> setCoderMt;
244 decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
247 RINOK(setCoderMt->SetNumberOfThreads(numThreads));
254 CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
255 decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
256 if (cryptoSetPassword)
258 if (getTextPassword == 0)
261 RINOK(getTextPassword->CryptoGetTextPassword(&password));
263 UString unicodePassword(password);
264 const UInt32 sizeInBytes = unicodePassword.Length() * 2;
265 buffer.SetCapacity(sizeInBytes);
266 for (int i = 0; i < unicodePassword.Length(); i++)
268 wchar_t c = unicodePassword[i];
269 ((Byte *)buffer)[i * 2] = (Byte)c;
270 ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
272 RINOK(cryptoSetPassword->CryptoSetPassword(
273 (const Byte *)buffer, sizeInBytes));
280 UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
281 UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
282 CRecordVector<const UInt64 *> packSizesPointers;
283 CRecordVector<const UInt64 *> unPackSizesPointers;
284 packSizesPointers.Reserve(numInStreams);
285 unPackSizesPointers.Reserve(numOutStreams);
287 for (j = 0; j < numOutStreams; j++, unPackStreamIndex++)
288 unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]);
290 for (j = 0; j < numInStreams; j++, packStreamIndex++)
292 int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
293 if (bindPairIndex >= 0)
294 packSizesPointers.Add(
295 &folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
298 int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
301 packSizesPointers.Add(&packSizes[index]);
305 _mixerCoderCommon->SetCoderInfo(i,
306 &packSizesPointers.Front(),
307 &unPackSizesPointers.Front());
309 UInt32 mainCoder, temp;
310 bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
313 _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
316 _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
321 CRecordVector<ISequentialInStream *> inStreamPointers;
322 inStreamPointers.Reserve(inStreams.Size());
323 for (i = 0; i < inStreams.Size(); i++)
324 inStreamPointers.Add(inStreams[i]);
325 ISequentialOutStream *outStreamPointer = outStream;
326 return _mixerCoder->Code(&inStreamPointers.Front(), NULL,
327 inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);