6 #include "7zSpecStream.h"
8 #include "../../IPassword.h"
9 #include "../../Common/ProgressUtils.h"
10 #include "../../Common/LimitedStreams.h"
11 #include "../../Common/InOutTempBuffer.h"
12 #include "../../Common/StreamObjects.h"
13 #include "../../Common/CreateCoder.h"
14 #include "../../Common/FilterCoder.h"
16 static const UInt64 k_AES = 0x06F10701;
17 static const UInt64 k_BCJ = 0x03030103;
18 static const UInt64 k_BCJ2 = 0x0303011B;
23 static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,
24 const CRecordVector<CMethodId> decompressionMethods,
27 folder.Coders.Clear();
28 // bindInfo.CoderMethodIDs.Clear();
29 // folder.OutStreams.Clear();
30 folder.PackStreams.Clear();
31 folder.BindPairs.Clear();
33 for (i = 0; i < bindInfo.BindPairs.Size(); i++)
36 bindPair.InIndex = bindInfo.BindPairs[i].InIndex;
37 bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;
38 folder.BindPairs.Add(bindPair);
40 for (i = 0; i < bindInfo.Coders.Size(); i++)
43 const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
44 coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
45 coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
46 coderInfo.MethodID = decompressionMethods[i];
47 folder.Coders.Add(coderInfo);
49 for (i = 0; i < bindInfo.InStreams.Size(); i++)
50 folder.PackStreams.Add(bindInfo.InStreams[i]);
53 HRESULT CEncoder::CreateMixerCoder(
54 DECL_EXTERNAL_CODECS_LOC_VARS
55 const UInt64 *inSizeForReduce)
57 _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;
58 _mixerCoder = _mixerCoderSpec;
59 RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));
60 for (int i = 0; i < _options.Methods.Size(); i++)
62 const CMethodFull &methodFull = _options.Methods[i];
63 _codersInfo.Add(CCoderInfo());
64 CCoderInfo &encodingInfo = _codersInfo.Back();
65 encodingInfo.MethodID = methodFull.Id;
66 CMyComPtr<ICompressCoder> encoder;
67 CMyComPtr<ICompressCoder2> encoder2;
71 EXTERNAL_CODECS_LOC_VARS
72 methodFull.Id, encoder, encoder2, true));
74 if (!encoder && !encoder2)
77 CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;
81 CMyComPtr<ICompressSetCoderMt> setCoderMt;
82 encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
85 RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));
91 RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon));
94 CMyComPtr<ICryptoResetSalt> resetSalt;
95 encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
96 if (resetSalt != NULL)
98 resetSalt->ResetSalt();
102 #ifdef EXTERNAL_CODECS
103 CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
104 encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
105 if (setCompressCodecsInfo)
107 RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
111 CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
112 encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
114 if (cryptoSetPassword)
117 const UInt32 sizeInBytes = _options.Password.Length() * 2;
118 buffer.SetCapacity(sizeInBytes);
119 for (int i = 0; i < _options.Password.Length(); i++)
121 wchar_t c = _options.Password[i];
122 ((Byte *)buffer)[i * 2] = (Byte)c;
123 ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
125 RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
129 _mixerCoderSpec->AddCoder(encoder);
131 _mixerCoderSpec->AddCoder2(encoder2);
136 HRESULT CEncoder::Encode(
137 DECL_EXTERNAL_CODECS_LOC_VARS
138 ISequentialInStream *inStream,
139 const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
141 ISequentialOutStream *outStream,
142 CRecordVector<UInt64> &packSizes,
143 ICompressProgressInfo *compressProgress)
145 RINOK(EncoderConstr());
147 if (_mixerCoderSpec == NULL)
149 RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
151 _mixerCoderSpec->ReInit();
152 // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
154 CObjectVector<CInOutTempBuffer> inOutTempBuffers;
155 CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
156 CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
157 int numMethods = _bindInfo.Coders.Size();
159 for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
161 inOutTempBuffers.Add(CInOutTempBuffer());
162 inOutTempBuffers.Back().Create();
163 inOutTempBuffers.Back().InitWriting();
165 for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
167 CSequentialOutTempBufferImp *tempBufferSpec =
168 new CSequentialOutTempBufferImp;
169 CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
170 tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
171 tempBuffers.Add(tempBuffer);
172 tempBufferSpecs.Add(tempBufferSpec);
175 for (i = 0; i < numMethods; i++)
176 _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
178 if (_bindInfo.InStreams.IsEmpty())
180 UInt32 mainCoderIndex, mainStreamIndex;
181 _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
183 if (inStreamSize != NULL)
185 CRecordVector<const UInt64 *> sizePointers;
186 for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
187 if (i == mainStreamIndex)
188 sizePointers.Add(inStreamSize);
190 sizePointers.Add(NULL);
191 _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
195 // UInt64 outStreamStartPos;
196 // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
198 CSequentialInStreamSizeCount2 *inStreamSizeCountSpec =
199 new CSequentialInStreamSizeCount2;
200 CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
201 CSequentialOutStreamSizeCount *outStreamSizeCountSpec =
202 new CSequentialOutStreamSizeCount;
203 CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
205 inStreamSizeCountSpec->Init(inStream);
206 outStreamSizeCountSpec->SetStream(outStream);
207 outStreamSizeCountSpec->Init();
209 CRecordVector<ISequentialInStream *> inStreamPointers;
210 CRecordVector<ISequentialOutStream *> outStreamPointers;
211 inStreamPointers.Add(inStreamSizeCount);
212 outStreamPointers.Add(outStreamSizeCount);
213 for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
214 outStreamPointers.Add(tempBuffers[i - 1]);
216 for (i = 0; i < _codersInfo.Size(); i++)
218 CCoderInfo &encodingInfo = _codersInfo[i];
220 CMyComPtr<ICryptoResetInitVector> resetInitVector;
221 _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
222 if (resetInitVector != NULL)
224 resetInitVector->ResetInitVector();
227 CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
228 _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
229 if (writeCoderProperties != NULL)
231 CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
232 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
233 outStreamSpec->Init();
234 writeCoderProperties->WriteCoderProperties(outStream);
235 size_t size = outStreamSpec->GetSize();
236 encodingInfo.Properties.SetCapacity(size);
237 memmove(encodingInfo.Properties, outStreamSpec->GetBuffer(), size);
241 UInt32 progressIndex = mainCoderIndex;
243 for (i = 0; i < _codersInfo.Size(); i++)
245 const CCoderInfo &e = _codersInfo[i];
246 if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size())
247 progressIndex = i + 1;
250 _mixerCoderSpec->SetProgressCoderIndex(progressIndex);
252 RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
253 &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
255 ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods,
258 packSizes.Add(outStreamSizeCountSpec->GetSize());
260 for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
262 CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
263 inOutTempBuffer.FlushWrite();
264 inOutTempBuffer.InitReading();
265 inOutTempBuffer.WriteToStream(outStream);
266 packSizes.Add(inOutTempBuffer.GetDataSize());
269 for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
271 int binder = _bindInfo.FindBinderForInStream(
272 _bindReverseConverter->DestOutToSrcInMap[i]);
275 streamSize = inStreamSizeCountSpec->GetSize();
277 streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
278 folderItem.UnPackSizes.Add(streamSize);
280 for (i = numMethods - 1; i >= 0; i--)
281 folderItem.Coders[numMethods - 1 - i].Properties = _codersInfo[i].Properties;
286 CEncoder::CEncoder(const CCompressionMethodMode &options):
287 _bindReverseConverter(0),
290 if (options.IsEmpty())
294 _mixerCoderSpec = NULL;
297 HRESULT CEncoder::EncoderConstr()
301 if (_options.Methods.IsEmpty())
303 // it has only password method;
304 if (!_options.PasswordIsDefined)
306 if (!_options.Binds.IsEmpty())
308 NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
311 method.NumInStreams = 1;
312 method.NumOutStreams = 1;
313 coderStreamsInfo.NumInStreams = 1;
314 coderStreamsInfo.NumOutStreams = 1;
317 _options.Methods.Add(method);
318 _bindInfo.Coders.Add(coderStreamsInfo);
320 _bindInfo.InStreams.Add(0);
321 _bindInfo.OutStreams.Add(0);
326 UInt32 numInStreams = 0, numOutStreams = 0;
328 for (i = 0; i < _options.Methods.Size(); i++)
330 const CMethodFull &methodFull = _options.Methods[i];
331 NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
332 coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
333 coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;
334 if (_options.Binds.IsEmpty())
336 if (i < _options.Methods.Size() - 1)
338 NCoderMixer::CBindPair bindPair;
339 bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
340 bindPair.OutIndex = numOutStreams;
341 _bindInfo.BindPairs.Add(bindPair);
344 _bindInfo.OutStreams.Insert(0, numOutStreams);
345 for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
346 _bindInfo.OutStreams.Add(numOutStreams + j);
349 numInStreams += coderStreamsInfo.NumInStreams;
350 numOutStreams += coderStreamsInfo.NumOutStreams;
352 _bindInfo.Coders.Add(coderStreamsInfo);
355 if (!_options.Binds.IsEmpty())
357 for (i = 0; i < _options.Binds.Size(); i++)
359 NCoderMixer::CBindPair bindPair;
360 const CBind &bind = _options.Binds[i];
361 bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;
362 bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;
363 _bindInfo.BindPairs.Add(bindPair);
365 for (i = 0; i < (int)numOutStreams; i++)
366 if (_bindInfo.FindBinderForOutStream(i) == -1)
367 _bindInfo.OutStreams.Add(i);
370 for (i = 0; i < (int)numInStreams; i++)
371 if (_bindInfo.FindBinderForInStream(i) == -1)
372 _bindInfo.InStreams.Add(i);
374 if (_bindInfo.InStreams.IsEmpty())
375 throw 1; // this is error
377 // Make main stream first in list
378 int inIndex = _bindInfo.InStreams[0];
381 UInt32 coderIndex, coderStreamIndex;
382 _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
383 UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
384 int binder = _bindInfo.FindBinderForOutStream(outIndex);
387 inIndex = _bindInfo.BindPairs[binder].InIndex;
390 for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
391 if (_bindInfo.OutStreams[i] == outIndex)
393 _bindInfo.OutStreams.Delete(i);
394 _bindInfo.OutStreams.Insert(0, outIndex);
400 if (_options.PasswordIsDefined)
402 int numCryptoStreams = _bindInfo.OutStreams.Size();
404 for (i = 0; i < numCryptoStreams; i++)
406 NCoderMixer::CBindPair bindPair;
407 bindPair.InIndex = numInStreams + i;
408 bindPair.OutIndex = _bindInfo.OutStreams[i];
409 _bindInfo.BindPairs.Add(bindPair);
411 _bindInfo.OutStreams.Clear();
414 if (numCryptoStreams == 0)
415 numCryptoStreams = 1;
418 for (i = 0; i < numCryptoStreams; i++)
420 NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
422 method.NumInStreams = 1;
423 method.NumOutStreams = 1;
424 coderStreamsInfo.NumInStreams = method.NumOutStreams;
425 coderStreamsInfo.NumOutStreams = method.NumInStreams;
428 _options.Methods.Add(method);
429 _bindInfo.Coders.Add(coderStreamsInfo);
430 _bindInfo.OutStreams.Add(numOutStreams + i);
436 for (int i = _options.Methods.Size() - 1; i >= 0; i--)
438 const CMethodFull &methodFull = _options.Methods[i];
439 _decompressionMethods.Add(methodFull.Id);
442 _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);
443 _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
448 CEncoder::~CEncoder()
450 delete _bindReverseConverter;