1370b324cSopenharmony_ci// 7zEncode.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../../Common/ComTry.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "../../Common/CreateCoder.h"
8370b324cSopenharmony_ci#include "../../Common/FilterCoder.h"
9370b324cSopenharmony_ci#include "../../Common/LimitedStreams.h"
10370b324cSopenharmony_ci#include "../../Common/InOutTempBuffer.h"
11370b324cSopenharmony_ci#include "../../Common/ProgressUtils.h"
12370b324cSopenharmony_ci#include "../../Common/StreamObjects.h"
13370b324cSopenharmony_ci
14370b324cSopenharmony_ci#include "7zEncode.h"
15370b324cSopenharmony_ci#include "7zSpecStream.h"
16370b324cSopenharmony_ci
17370b324cSopenharmony_cinamespace NArchive {
18370b324cSopenharmony_cinamespace N7z {
19370b324cSopenharmony_ci
20370b324cSopenharmony_civoid CEncoder::InitBindConv()
21370b324cSopenharmony_ci{
22370b324cSopenharmony_ci  unsigned numIn = _bindInfo.Coders.Size();
23370b324cSopenharmony_ci
24370b324cSopenharmony_ci  SrcIn_to_DestOut.ClearAndSetSize(numIn);
25370b324cSopenharmony_ci  DestOut_to_SrcIn.ClearAndSetSize(numIn);
26370b324cSopenharmony_ci
27370b324cSopenharmony_ci  unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();
28370b324cSopenharmony_ci  SrcOut_to_DestIn.ClearAndSetSize(numOut);
29370b324cSopenharmony_ci  // _DestIn_to_SrcOut.ClearAndSetSize(numOut);
30370b324cSopenharmony_ci
31370b324cSopenharmony_ci  UInt32 destIn = 0;
32370b324cSopenharmony_ci  UInt32 destOut = 0;
33370b324cSopenharmony_ci
34370b324cSopenharmony_ci  for (unsigned i = _bindInfo.Coders.Size(); i != 0;)
35370b324cSopenharmony_ci  {
36370b324cSopenharmony_ci    i--;
37370b324cSopenharmony_ci
38370b324cSopenharmony_ci    const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];
39370b324cSopenharmony_ci
40370b324cSopenharmony_ci    numIn--;
41370b324cSopenharmony_ci    numOut -= coder.NumStreams;
42370b324cSopenharmony_ci
43370b324cSopenharmony_ci    SrcIn_to_DestOut[numIn] = destOut;
44370b324cSopenharmony_ci    DestOut_to_SrcIn[destOut] = numIn;
45370b324cSopenharmony_ci
46370b324cSopenharmony_ci    destOut++;
47370b324cSopenharmony_ci
48370b324cSopenharmony_ci    for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)
49370b324cSopenharmony_ci    {
50370b324cSopenharmony_ci      UInt32 index = numOut + j;
51370b324cSopenharmony_ci      SrcOut_to_DestIn[index] = destIn;
52370b324cSopenharmony_ci      // _DestIn_to_SrcOut[destIn] = index;
53370b324cSopenharmony_ci    }
54370b324cSopenharmony_ci  }
55370b324cSopenharmony_ci}
56370b324cSopenharmony_ci
57370b324cSopenharmony_civoid CEncoder::SetFolder(CFolder &folder)
58370b324cSopenharmony_ci{
59370b324cSopenharmony_ci  folder.Bonds.SetSize(_bindInfo.Bonds.Size());
60370b324cSopenharmony_ci
61370b324cSopenharmony_ci  unsigned i;
62370b324cSopenharmony_ci
63370b324cSopenharmony_ci  for (i = 0; i < _bindInfo.Bonds.Size(); i++)
64370b324cSopenharmony_ci  {
65370b324cSopenharmony_ci    CBond &fb = folder.Bonds[i];
66370b324cSopenharmony_ci    const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];
67370b324cSopenharmony_ci    fb.PackIndex = SrcOut_to_DestIn[mixerBond.PackIndex];
68370b324cSopenharmony_ci    fb.UnpackIndex = SrcIn_to_DestOut[mixerBond.UnpackIndex];
69370b324cSopenharmony_ci  }
70370b324cSopenharmony_ci
71370b324cSopenharmony_ci  folder.Coders.SetSize(_bindInfo.Coders.Size());
72370b324cSopenharmony_ci
73370b324cSopenharmony_ci  for (i = 0; i < _bindInfo.Coders.Size(); i++)
74370b324cSopenharmony_ci  {
75370b324cSopenharmony_ci    CCoderInfo &coderInfo = folder.Coders[i];
76370b324cSopenharmony_ci    const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];
77370b324cSopenharmony_ci
78370b324cSopenharmony_ci    coderInfo.NumStreams = coderStreamsInfo.NumStreams;
79370b324cSopenharmony_ci    coderInfo.MethodID = _decompressionMethods[i];
80370b324cSopenharmony_ci    // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.
81370b324cSopenharmony_ci  }
82370b324cSopenharmony_ci
83370b324cSopenharmony_ci  folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());
84370b324cSopenharmony_ci
85370b324cSopenharmony_ci  for (i = 0; i < _bindInfo.PackStreams.Size(); i++)
86370b324cSopenharmony_ci    folder.PackStreams[i] = SrcOut_to_DestIn[_bindInfo.PackStreams[i]];
87370b324cSopenharmony_ci}
88370b324cSopenharmony_ci
89370b324cSopenharmony_ci
90370b324cSopenharmony_ci
91370b324cSopenharmony_cistatic HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
92370b324cSopenharmony_ci{
93370b324cSopenharmony_ci  Z7_DECL_CMyComPtr_QI_FROM(
94370b324cSopenharmony_ci      ICompressSetCoderProperties,
95370b324cSopenharmony_ci      setCoderProperties, coder)
96370b324cSopenharmony_ci  if (setCoderProperties)
97370b324cSopenharmony_ci    return props.SetCoderProps(setCoderProperties, dataSizeReduce);
98370b324cSopenharmony_ci  return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
99370b324cSopenharmony_ci}
100370b324cSopenharmony_ci
101370b324cSopenharmony_ci
102370b324cSopenharmony_ci
103370b324cSopenharmony_civoid CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
104370b324cSopenharmony_ci{
105370b324cSopenharmony_ci  _progress = progress;
106370b324cSopenharmony_ci  OutSize = 0;
107370b324cSopenharmony_ci}
108370b324cSopenharmony_ci
109370b324cSopenharmony_ciZ7_COM7F_IMF(CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))
110370b324cSopenharmony_ci{
111370b324cSopenharmony_ci  UInt64 outSize2;
112370b324cSopenharmony_ci  {
113370b324cSopenharmony_ci    #ifndef Z7_ST
114370b324cSopenharmony_ci    NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
115370b324cSopenharmony_ci    #endif
116370b324cSopenharmony_ci    outSize2 = OutSize;
117370b324cSopenharmony_ci  }
118370b324cSopenharmony_ci
119370b324cSopenharmony_ci  if (_progress)
120370b324cSopenharmony_ci    return _progress->SetRatioInfo(inSize, &outSize2);
121370b324cSopenharmony_ci
122370b324cSopenharmony_ci  return S_OK;
123370b324cSopenharmony_ci}
124370b324cSopenharmony_ci
125370b324cSopenharmony_ci
126370b324cSopenharmony_ci
127370b324cSopenharmony_ciHRESULT CEncoder::CreateMixerCoder(
128370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
129370b324cSopenharmony_ci    const UInt64 *inSizeForReduce)
130370b324cSopenharmony_ci{
131370b324cSopenharmony_ci  #ifdef USE_MIXER_MT
132370b324cSopenharmony_ci  #ifdef USE_MIXER_ST
133370b324cSopenharmony_ci  if (_options.MultiThreadMixer)
134370b324cSopenharmony_ci  #endif
135370b324cSopenharmony_ci  {
136370b324cSopenharmony_ci    _mixerMT = new NCoderMixer2::CMixerMT(true);
137370b324cSopenharmony_ci    _mixerRef = _mixerMT;
138370b324cSopenharmony_ci    _mixer = _mixerMT;
139370b324cSopenharmony_ci  }
140370b324cSopenharmony_ci  #ifdef USE_MIXER_ST
141370b324cSopenharmony_ci  else
142370b324cSopenharmony_ci  #endif
143370b324cSopenharmony_ci  #endif
144370b324cSopenharmony_ci  {
145370b324cSopenharmony_ci    #ifdef USE_MIXER_ST
146370b324cSopenharmony_ci    _mixerST = new NCoderMixer2::CMixerST(true);
147370b324cSopenharmony_ci    _mixerRef = _mixerST;
148370b324cSopenharmony_ci    _mixer = _mixerST;
149370b324cSopenharmony_ci    #endif
150370b324cSopenharmony_ci  }
151370b324cSopenharmony_ci
152370b324cSopenharmony_ci  RINOK(_mixer->SetBindInfo(_bindInfo))
153370b324cSopenharmony_ci
154370b324cSopenharmony_ci  FOR_VECTOR (m, _options.Methods)
155370b324cSopenharmony_ci  {
156370b324cSopenharmony_ci    const CMethodFull &methodFull = _options.Methods[m];
157370b324cSopenharmony_ci
158370b324cSopenharmony_ci    CCreatedCoder cod;
159370b324cSopenharmony_ci
160370b324cSopenharmony_ci    if (methodFull.CodecIndex >= 0)
161370b324cSopenharmony_ci    {
162370b324cSopenharmony_ci      RINOK(CreateCoder_Index(
163370b324cSopenharmony_ci        EXTERNAL_CODECS_LOC_VARS
164370b324cSopenharmony_ci        (unsigned)methodFull.CodecIndex, true, cod))
165370b324cSopenharmony_ci    }
166370b324cSopenharmony_ci    else
167370b324cSopenharmony_ci    {
168370b324cSopenharmony_ci      RINOK(CreateCoder_Id(
169370b324cSopenharmony_ci        EXTERNAL_CODECS_LOC_VARS
170370b324cSopenharmony_ci        methodFull.Id, true, cod))
171370b324cSopenharmony_ci    }
172370b324cSopenharmony_ci
173370b324cSopenharmony_ci    if (!cod.Coder && !cod.Coder2)
174370b324cSopenharmony_ci    {
175370b324cSopenharmony_ci      return E_NOTIMPL; // unsupported method, if encoder
176370b324cSopenharmony_ci      // return E_FAIL;
177370b324cSopenharmony_ci    }
178370b324cSopenharmony_ci
179370b324cSopenharmony_ci    if (cod.NumStreams != methodFull.NumStreams)
180370b324cSopenharmony_ci      return E_FAIL;
181370b324cSopenharmony_ci
182370b324cSopenharmony_ci    CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
183370b324cSopenharmony_ci
184370b324cSopenharmony_ci    #ifndef Z7_ST
185370b324cSopenharmony_ci    if (methodFull.Set_NumThreads)
186370b324cSopenharmony_ci    {
187370b324cSopenharmony_ci      CMyComPtr<ICompressSetCoderMt> setCoderMt;
188370b324cSopenharmony_ci      encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
189370b324cSopenharmony_ci      if (setCoderMt)
190370b324cSopenharmony_ci      {
191370b324cSopenharmony_ci        RINOK(setCoderMt->SetNumberOfThreads(
192370b324cSopenharmony_ci            /* _options.NumThreads */
193370b324cSopenharmony_ci            methodFull.NumThreads
194370b324cSopenharmony_ci            ))
195370b324cSopenharmony_ci      }
196370b324cSopenharmony_ci    }
197370b324cSopenharmony_ci    #endif
198370b324cSopenharmony_ci
199370b324cSopenharmony_ci    RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon))
200370b324cSopenharmony_ci
201370b324cSopenharmony_ci    /*
202370b324cSopenharmony_ci    CMyComPtr<ICryptoResetSalt> resetSalt;
203370b324cSopenharmony_ci    encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
204370b324cSopenharmony_ci    if (resetSalt)
205370b324cSopenharmony_ci    {
206370b324cSopenharmony_ci      resetSalt->ResetSalt();
207370b324cSopenharmony_ci    }
208370b324cSopenharmony_ci    */
209370b324cSopenharmony_ci
210370b324cSopenharmony_ci    // now there is no codec that uses another external codec
211370b324cSopenharmony_ci    /*
212370b324cSopenharmony_ci    #ifdef Z7_EXTERNAL_CODECS
213370b324cSopenharmony_ci    CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
214370b324cSopenharmony_ci    encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
215370b324cSopenharmony_ci    if (setCompressCodecsInfo)
216370b324cSopenharmony_ci    {
217370b324cSopenharmony_ci      // we must use g_ExternalCodecs also
218370b324cSopenharmony_ci      RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs));
219370b324cSopenharmony_ci    }
220370b324cSopenharmony_ci    #endif
221370b324cSopenharmony_ci    */
222370b324cSopenharmony_ci
223370b324cSopenharmony_ci    CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
224370b324cSopenharmony_ci    encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
225370b324cSopenharmony_ci
226370b324cSopenharmony_ci    if (cryptoSetPassword)
227370b324cSopenharmony_ci    {
228370b324cSopenharmony_ci      const unsigned sizeInBytes = _options.Password.Len() * 2;
229370b324cSopenharmony_ci      CByteBuffer_Wipe buffer(sizeInBytes);
230370b324cSopenharmony_ci      for (unsigned i = 0; i < _options.Password.Len(); i++)
231370b324cSopenharmony_ci      {
232370b324cSopenharmony_ci        wchar_t c = _options.Password[i];
233370b324cSopenharmony_ci        ((Byte *)buffer)[i * 2] = (Byte)c;
234370b324cSopenharmony_ci        ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
235370b324cSopenharmony_ci      }
236370b324cSopenharmony_ci      RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes))
237370b324cSopenharmony_ci    }
238370b324cSopenharmony_ci
239370b324cSopenharmony_ci    _mixer->AddCoder(cod);
240370b324cSopenharmony_ci  }
241370b324cSopenharmony_ci  return S_OK;
242370b324cSopenharmony_ci}
243370b324cSopenharmony_ci
244370b324cSopenharmony_ci
245370b324cSopenharmony_ci
246370b324cSopenharmony_ciZ7_CLASS_IMP_COM_1(
247370b324cSopenharmony_ci  CSequentialOutTempBufferImp2
248370b324cSopenharmony_ci  , ISequentialOutStream
249370b324cSopenharmony_ci)
250370b324cSopenharmony_cipublic:
251370b324cSopenharmony_ci  CInOutTempBuffer TempBuffer;
252370b324cSopenharmony_ci  CMtEncMultiProgress *_mtProgressSpec;
253370b324cSopenharmony_ci
254370b324cSopenharmony_ci  CSequentialOutTempBufferImp2(): _mtProgressSpec(NULL) {}
255370b324cSopenharmony_ci};
256370b324cSopenharmony_ci
257370b324cSopenharmony_ciZ7_COM7F_IMF(CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed))
258370b324cSopenharmony_ci{
259370b324cSopenharmony_ci  COM_TRY_BEGIN
260370b324cSopenharmony_ci  if (processed)
261370b324cSopenharmony_ci    *processed = 0;
262370b324cSopenharmony_ci  RINOK(TempBuffer.Write_HRESULT(data, size))
263370b324cSopenharmony_ci  if (processed)
264370b324cSopenharmony_ci    *processed = size;
265370b324cSopenharmony_ci  if (_mtProgressSpec)
266370b324cSopenharmony_ci    _mtProgressSpec->AddOutSize(size);
267370b324cSopenharmony_ci  return S_OK;
268370b324cSopenharmony_ci  COM_TRY_END
269370b324cSopenharmony_ci}
270370b324cSopenharmony_ci
271370b324cSopenharmony_ci
272370b324cSopenharmony_ciZ7_CLASS_IMP_COM_1(
273370b324cSopenharmony_ci  CSequentialOutMtNotify
274370b324cSopenharmony_ci  , ISequentialOutStream
275370b324cSopenharmony_ci)
276370b324cSopenharmony_cipublic:
277370b324cSopenharmony_ci  CMyComPtr<ISequentialOutStream> _stream;
278370b324cSopenharmony_ci  CMtEncMultiProgress *_mtProgressSpec;
279370b324cSopenharmony_ci
280370b324cSopenharmony_ci  CSequentialOutMtNotify(): _mtProgressSpec(NULL) {}
281370b324cSopenharmony_ci};
282370b324cSopenharmony_ci
283370b324cSopenharmony_ciZ7_COM7F_IMF(CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed))
284370b324cSopenharmony_ci{
285370b324cSopenharmony_ci  UInt32 realProcessed = 0;
286370b324cSopenharmony_ci  HRESULT res = _stream->Write(data, size, &realProcessed);
287370b324cSopenharmony_ci  if (processed)
288370b324cSopenharmony_ci    *processed = realProcessed;
289370b324cSopenharmony_ci  if (_mtProgressSpec)
290370b324cSopenharmony_ci    _mtProgressSpec->AddOutSize(size);
291370b324cSopenharmony_ci  return res;
292370b324cSopenharmony_ci}
293370b324cSopenharmony_ci
294370b324cSopenharmony_ci
295370b324cSopenharmony_cistatic HRESULT FillProps_from_Coder(IUnknown *coder, CByteBuffer &props)
296370b324cSopenharmony_ci{
297370b324cSopenharmony_ci  Z7_DECL_CMyComPtr_QI_FROM(
298370b324cSopenharmony_ci      ICompressWriteCoderProperties,
299370b324cSopenharmony_ci      writeCoderProperties, coder)
300370b324cSopenharmony_ci  if (writeCoderProperties)
301370b324cSopenharmony_ci  {
302370b324cSopenharmony_ci    CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
303370b324cSopenharmony_ci    CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
304370b324cSopenharmony_ci    outStreamSpec->Init();
305370b324cSopenharmony_ci    RINOK(writeCoderProperties->WriteCoderProperties(dynOutStream))
306370b324cSopenharmony_ci    outStreamSpec->CopyToBuffer(props);
307370b324cSopenharmony_ci  }
308370b324cSopenharmony_ci  else
309370b324cSopenharmony_ci    props.Free();
310370b324cSopenharmony_ci  return S_OK;
311370b324cSopenharmony_ci}
312370b324cSopenharmony_ci
313370b324cSopenharmony_ciHRESULT CEncoder::Encode1(
314370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
315370b324cSopenharmony_ci    ISequentialInStream *inStream,
316370b324cSopenharmony_ci    // const UInt64 *inStreamSize,
317370b324cSopenharmony_ci    const UInt64 *inSizeForReduce,
318370b324cSopenharmony_ci    UInt64 expectedDataSize,
319370b324cSopenharmony_ci    CFolder &folderItem,
320370b324cSopenharmony_ci    // CRecordVector<UInt64> &coderUnpackSizes,
321370b324cSopenharmony_ci    // UInt64 &unpackSize,
322370b324cSopenharmony_ci    ISequentialOutStream *outStream,
323370b324cSopenharmony_ci    CRecordVector<UInt64> &packSizes,
324370b324cSopenharmony_ci    ICompressProgressInfo *compressProgress)
325370b324cSopenharmony_ci{
326370b324cSopenharmony_ci  RINOK(EncoderConstr())
327370b324cSopenharmony_ci
328370b324cSopenharmony_ci  if (!_mixerRef)
329370b324cSopenharmony_ci  {
330370b324cSopenharmony_ci    RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce))
331370b324cSopenharmony_ci  }
332370b324cSopenharmony_ci
333370b324cSopenharmony_ci  RINOK(_mixer->ReInit2())
334370b324cSopenharmony_ci
335370b324cSopenharmony_ci  CMtEncMultiProgress *mtProgressSpec = NULL;
336370b324cSopenharmony_ci  CMyComPtr<ICompressProgressInfo> mtProgress;
337370b324cSopenharmony_ci
338370b324cSopenharmony_ci  CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
339370b324cSopenharmony_ci  CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
340370b324cSopenharmony_ci
341370b324cSopenharmony_ci  CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
342370b324cSopenharmony_ci  CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
343370b324cSopenharmony_ci
344370b324cSopenharmony_ci  unsigned i;
345370b324cSopenharmony_ci
346370b324cSopenharmony_ci  for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
347370b324cSopenharmony_ci  {
348370b324cSopenharmony_ci    CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2();
349370b324cSopenharmony_ci    CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
350370b324cSopenharmony_ci    tempBufferSpecs.Add(tempBufferSpec);
351370b324cSopenharmony_ci    tempBuffers.Add(tempBuffer);
352370b324cSopenharmony_ci  }
353370b324cSopenharmony_ci
354370b324cSopenharmony_ci  const unsigned numMethods = _bindInfo.Coders.Size();
355370b324cSopenharmony_ci
356370b324cSopenharmony_ci  for (i = 0; i < numMethods; i++)
357370b324cSopenharmony_ci    _mixer->SetCoderInfo(i, NULL, NULL, false);
358370b324cSopenharmony_ci
359370b324cSopenharmony_ci
360370b324cSopenharmony_ci  /* inStreamSize can be used by BCJ2 to set optimal range of conversion.
361370b324cSopenharmony_ci     But current BCJ2 encoder uses also another way to check exact size of current file.
362370b324cSopenharmony_ci     So inStreamSize is not required. */
363370b324cSopenharmony_ci
364370b324cSopenharmony_ci  /*
365370b324cSopenharmony_ci  if (inStreamSize)
366370b324cSopenharmony_ci    _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
367370b324cSopenharmony_ci  */
368370b324cSopenharmony_ci
369370b324cSopenharmony_ci
370370b324cSopenharmony_ci  /*
371370b324cSopenharmony_ci  CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
372370b324cSopenharmony_ci  CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
373370b324cSopenharmony_ci  */
374370b324cSopenharmony_ci
375370b324cSopenharmony_ci  CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
376370b324cSopenharmony_ci  CMyComPtr<ISequentialOutStream> outStreamSizeCount;
377370b324cSopenharmony_ci
378370b324cSopenharmony_ci  // inStreamSizeCountSpec->Init(inStream);
379370b324cSopenharmony_ci
380370b324cSopenharmony_ci  // ISequentialInStream *inStreamPointer = inStreamSizeCount;
381370b324cSopenharmony_ci  ISequentialInStream *inStreamPointer = inStream;
382370b324cSopenharmony_ci
383370b324cSopenharmony_ci  CRecordVector<ISequentialOutStream *> outStreamPointers;
384370b324cSopenharmony_ci
385370b324cSopenharmony_ci  SetFolder(folderItem);
386370b324cSopenharmony_ci
387370b324cSopenharmony_ci  for (i = 0; i < numMethods; i++)
388370b324cSopenharmony_ci  {
389370b324cSopenharmony_ci    IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
390370b324cSopenharmony_ci    /*
391370b324cSopenharmony_ci    {
392370b324cSopenharmony_ci      CEncoder *sfEncoder = NULL;
393370b324cSopenharmony_ci      Z7_DECL_CMyComPtr_QI_FROM(
394370b324cSopenharmony_ci          IGetSfEncoderInternal,
395370b324cSopenharmony_ci          sf, coder)
396370b324cSopenharmony_ci      if (sf)
397370b324cSopenharmony_ci      {
398370b324cSopenharmony_ci        RINOK(sf->GetSfEncoder(&sfEncoder));
399370b324cSopenharmony_ci        if (!sfEncoder)
400370b324cSopenharmony_ci          return E_FAIL;
401370b324cSopenharmony_ci
402370b324cSopenharmony_ci      }
403370b324cSopenharmony_ci    }
404370b324cSopenharmony_ci    */
405370b324cSopenharmony_ci    /*
406370b324cSopenharmony_ci    #ifdef Z7_EXTERNAL_CODECS
407370b324cSopenharmony_ci    {
408370b324cSopenharmony_ci      Z7_DECL_CMyComPtr_QI_FROM(
409370b324cSopenharmony_ci          ISetCompressCodecsInfo,
410370b324cSopenharmony_ci          setCompressCodecsInfo, coder)
411370b324cSopenharmony_ci      if (setCompressCodecsInfo)
412370b324cSopenharmony_ci      {
413370b324cSopenharmony_ci        // we must use g_ExternalCodecs also
414370b324cSopenharmony_ci        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs))
415370b324cSopenharmony_ci      }
416370b324cSopenharmony_ci    }
417370b324cSopenharmony_ci    #endif
418370b324cSopenharmony_ci    */
419370b324cSopenharmony_ci    {
420370b324cSopenharmony_ci      Z7_DECL_CMyComPtr_QI_FROM(
421370b324cSopenharmony_ci          ICryptoResetInitVector,
422370b324cSopenharmony_ci          resetInitVector, coder)
423370b324cSopenharmony_ci      if (resetInitVector)
424370b324cSopenharmony_ci      {
425370b324cSopenharmony_ci        RINOK(resetInitVector->ResetInitVector())
426370b324cSopenharmony_ci      }
427370b324cSopenharmony_ci    }
428370b324cSopenharmony_ci    {
429370b324cSopenharmony_ci      Z7_DECL_CMyComPtr_QI_FROM(
430370b324cSopenharmony_ci          ICompressSetCoderPropertiesOpt,
431370b324cSopenharmony_ci          optProps, coder)
432370b324cSopenharmony_ci      if (optProps)
433370b324cSopenharmony_ci      {
434370b324cSopenharmony_ci        const PROPID propID = NCoderPropID::kExpectedDataSize;
435370b324cSopenharmony_ci        NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;
436370b324cSopenharmony_ci        RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1))
437370b324cSopenharmony_ci      }
438370b324cSopenharmony_ci    }
439370b324cSopenharmony_ci    // we must write properties from coder after ResetInitVector()
440370b324cSopenharmony_ci    RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))
441370b324cSopenharmony_ci  }
442370b324cSopenharmony_ci
443370b324cSopenharmony_ci  _mixer->SelectMainCoder(false);
444370b324cSopenharmony_ci  const UInt32 mainCoder = _mixer->MainCoderIndex;
445370b324cSopenharmony_ci
446370b324cSopenharmony_ci  bool useMtProgress = false;
447370b324cSopenharmony_ci  if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
448370b324cSopenharmony_ci  {
449370b324cSopenharmony_ci    #ifdef Z7_ST
450370b324cSopenharmony_ci    if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
451370b324cSopenharmony_ci    #endif
452370b324cSopenharmony_ci      useMtProgress = true;
453370b324cSopenharmony_ci  }
454370b324cSopenharmony_ci
455370b324cSopenharmony_ci  if (useMtProgress)
456370b324cSopenharmony_ci  {
457370b324cSopenharmony_ci    mtProgressSpec = new CMtEncMultiProgress;
458370b324cSopenharmony_ci    mtProgress = mtProgressSpec;
459370b324cSopenharmony_ci    mtProgressSpec->Init(compressProgress);
460370b324cSopenharmony_ci
461370b324cSopenharmony_ci    mtOutStreamNotifySpec = new CSequentialOutMtNotify;
462370b324cSopenharmony_ci    mtOutStreamNotify = mtOutStreamNotifySpec;
463370b324cSopenharmony_ci    mtOutStreamNotifySpec->_stream = outStream;
464370b324cSopenharmony_ci    mtOutStreamNotifySpec->_mtProgressSpec = mtProgressSpec;
465370b324cSopenharmony_ci
466370b324cSopenharmony_ci    FOR_VECTOR (t, tempBufferSpecs)
467370b324cSopenharmony_ci    {
468370b324cSopenharmony_ci      tempBufferSpecs[t]->_mtProgressSpec = mtProgressSpec;
469370b324cSopenharmony_ci    }
470370b324cSopenharmony_ci  }
471370b324cSopenharmony_ci
472370b324cSopenharmony_ci
473370b324cSopenharmony_ci  if (_bindInfo.PackStreams.Size() != 0)
474370b324cSopenharmony_ci  {
475370b324cSopenharmony_ci    outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
476370b324cSopenharmony_ci    outStreamSizeCount = outStreamSizeCountSpec;
477370b324cSopenharmony_ci    outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream);
478370b324cSopenharmony_ci    outStreamSizeCountSpec->Init();
479370b324cSopenharmony_ci    outStreamPointers.Add(outStreamSizeCount);
480370b324cSopenharmony_ci  }
481370b324cSopenharmony_ci
482370b324cSopenharmony_ci  for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
483370b324cSopenharmony_ci    outStreamPointers.Add(tempBuffers[i - 1]);
484370b324cSopenharmony_ci
485370b324cSopenharmony_ci  bool dataAfterEnd_Error;
486370b324cSopenharmony_ci
487370b324cSopenharmony_ci  RINOK(_mixer->Code(
488370b324cSopenharmony_ci      &inStreamPointer,
489370b324cSopenharmony_ci      &outStreamPointers.Front(),
490370b324cSopenharmony_ci      mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error))
491370b324cSopenharmony_ci
492370b324cSopenharmony_ci  if (_bindInfo.PackStreams.Size() != 0)
493370b324cSopenharmony_ci    packSizes.Add(outStreamSizeCountSpec->GetSize());
494370b324cSopenharmony_ci
495370b324cSopenharmony_ci  for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
496370b324cSopenharmony_ci  {
497370b324cSopenharmony_ci    CInOutTempBuffer &iotb = tempBufferSpecs[i - 1]->TempBuffer;
498370b324cSopenharmony_ci    RINOK(iotb.WriteToStream(outStream))
499370b324cSopenharmony_ci    packSizes.Add(iotb.GetDataSize());
500370b324cSopenharmony_ci  }
501370b324cSopenharmony_ci
502370b324cSopenharmony_ci  /* Code() in some future codec can change properties.
503370b324cSopenharmony_ci     v23: so we fill properties again after Code() */
504370b324cSopenharmony_ci  for (i = 0; i < numMethods; i++)
505370b324cSopenharmony_ci  {
506370b324cSopenharmony_ci    IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
507370b324cSopenharmony_ci    RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))
508370b324cSopenharmony_ci  }
509370b324cSopenharmony_ci
510370b324cSopenharmony_ci  return S_OK;
511370b324cSopenharmony_ci}
512370b324cSopenharmony_ci
513370b324cSopenharmony_ci
514370b324cSopenharmony_civoid CEncoder::Encode_Post(
515370b324cSopenharmony_ci      UInt64 unpackSize,
516370b324cSopenharmony_ci      CRecordVector<UInt64> &coderUnpackSizes)
517370b324cSopenharmony_ci{
518370b324cSopenharmony_ci  // unpackSize = 0;
519370b324cSopenharmony_ci  for (unsigned i = 0; i < _bindInfo.Coders.Size(); i++)
520370b324cSopenharmony_ci  {
521370b324cSopenharmony_ci    const int bond = _bindInfo.FindBond_for_UnpackStream(DestOut_to_SrcIn[i]);
522370b324cSopenharmony_ci    UInt64 streamSize;
523370b324cSopenharmony_ci    if (bond < 0)
524370b324cSopenharmony_ci    {
525370b324cSopenharmony_ci      // streamSize = inStreamSizeCountSpec->GetSize();
526370b324cSopenharmony_ci      // unpackSize = streamSize;
527370b324cSopenharmony_ci      streamSize = unpackSize;
528370b324cSopenharmony_ci    }
529370b324cSopenharmony_ci    else
530370b324cSopenharmony_ci      streamSize = _mixer->GetBondStreamSize((unsigned)bond);
531370b324cSopenharmony_ci    coderUnpackSizes.Add(streamSize);
532370b324cSopenharmony_ci  }
533370b324cSopenharmony_ci}
534370b324cSopenharmony_ci
535370b324cSopenharmony_ci
536370b324cSopenharmony_ciCEncoder::CEncoder(const CCompressionMethodMode &options):
537370b324cSopenharmony_ci    _constructed(false)
538370b324cSopenharmony_ci{
539370b324cSopenharmony_ci  if (options.IsEmpty())
540370b324cSopenharmony_ci    throw 1;
541370b324cSopenharmony_ci
542370b324cSopenharmony_ci  _options = options;
543370b324cSopenharmony_ci
544370b324cSopenharmony_ci  #ifdef USE_MIXER_ST
545370b324cSopenharmony_ci    _mixerST = NULL;
546370b324cSopenharmony_ci  #endif
547370b324cSopenharmony_ci
548370b324cSopenharmony_ci  #ifdef USE_MIXER_MT
549370b324cSopenharmony_ci    _mixerMT = NULL;
550370b324cSopenharmony_ci  #endif
551370b324cSopenharmony_ci
552370b324cSopenharmony_ci  _mixer = NULL;
553370b324cSopenharmony_ci}
554370b324cSopenharmony_ci
555370b324cSopenharmony_ci
556370b324cSopenharmony_ciHRESULT CEncoder::EncoderConstr()
557370b324cSopenharmony_ci{
558370b324cSopenharmony_ci  if (_constructed)
559370b324cSopenharmony_ci    return S_OK;
560370b324cSopenharmony_ci  if (_options.Methods.IsEmpty())
561370b324cSopenharmony_ci  {
562370b324cSopenharmony_ci    // it has only password method;
563370b324cSopenharmony_ci    if (!_options.PasswordIsDefined)
564370b324cSopenharmony_ci      throw 1;
565370b324cSopenharmony_ci    if (!_options.Bonds.IsEmpty())
566370b324cSopenharmony_ci      throw 1;
567370b324cSopenharmony_ci
568370b324cSopenharmony_ci    CMethodFull method;
569370b324cSopenharmony_ci    method.Id = k_AES;
570370b324cSopenharmony_ci    method.NumStreams = 1;
571370b324cSopenharmony_ci    _options.Methods.Add(method);
572370b324cSopenharmony_ci
573370b324cSopenharmony_ci    NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
574370b324cSopenharmony_ci    coderStreamsInfo.NumStreams = 1;
575370b324cSopenharmony_ci    _bindInfo.Coders.Add(coderStreamsInfo);
576370b324cSopenharmony_ci
577370b324cSopenharmony_ci    _bindInfo.PackStreams.Add(0);
578370b324cSopenharmony_ci    _bindInfo.UnpackCoder = 0;
579370b324cSopenharmony_ci  }
580370b324cSopenharmony_ci  else
581370b324cSopenharmony_ci  {
582370b324cSopenharmony_ci
583370b324cSopenharmony_ci  UInt32 numOutStreams = 0;
584370b324cSopenharmony_ci  unsigned i;
585370b324cSopenharmony_ci
586370b324cSopenharmony_ci  for (i = 0; i < _options.Methods.Size(); i++)
587370b324cSopenharmony_ci  {
588370b324cSopenharmony_ci    const CMethodFull &methodFull = _options.Methods[i];
589370b324cSopenharmony_ci    NCoderMixer2::CCoderStreamsInfo cod;
590370b324cSopenharmony_ci
591370b324cSopenharmony_ci    cod.NumStreams = methodFull.NumStreams;
592370b324cSopenharmony_ci
593370b324cSopenharmony_ci    if (_options.Bonds.IsEmpty())
594370b324cSopenharmony_ci    {
595370b324cSopenharmony_ci      // if there are no bonds in options, we create bonds via first streams of coders
596370b324cSopenharmony_ci      if (i != _options.Methods.Size() - 1)
597370b324cSopenharmony_ci      {
598370b324cSopenharmony_ci        NCoderMixer2::CBond bond;
599370b324cSopenharmony_ci        bond.PackIndex = numOutStreams;
600370b324cSopenharmony_ci        bond.UnpackIndex = i + 1; // it's next coder
601370b324cSopenharmony_ci        _bindInfo.Bonds.Add(bond);
602370b324cSopenharmony_ci      }
603370b324cSopenharmony_ci      else if (cod.NumStreams != 0)
604370b324cSopenharmony_ci        _bindInfo.PackStreams.Insert(0, numOutStreams);
605370b324cSopenharmony_ci
606370b324cSopenharmony_ci      for (UInt32 j = 1; j < cod.NumStreams; j++)
607370b324cSopenharmony_ci        _bindInfo.PackStreams.Add(numOutStreams + j);
608370b324cSopenharmony_ci    }
609370b324cSopenharmony_ci
610370b324cSopenharmony_ci    numOutStreams += cod.NumStreams;
611370b324cSopenharmony_ci
612370b324cSopenharmony_ci    _bindInfo.Coders.Add(cod);
613370b324cSopenharmony_ci  }
614370b324cSopenharmony_ci
615370b324cSopenharmony_ci  if (!_options.Bonds.IsEmpty())
616370b324cSopenharmony_ci  {
617370b324cSopenharmony_ci    for (i = 0; i < _options.Bonds.Size(); i++)
618370b324cSopenharmony_ci    {
619370b324cSopenharmony_ci      NCoderMixer2::CBond mixerBond;
620370b324cSopenharmony_ci      const CBond2 &bond = _options.Bonds[i];
621370b324cSopenharmony_ci      if (bond.InCoder >= _bindInfo.Coders.Size()
622370b324cSopenharmony_ci          || bond.OutCoder >= _bindInfo.Coders.Size()
623370b324cSopenharmony_ci          || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)
624370b324cSopenharmony_ci        return E_INVALIDARG;
625370b324cSopenharmony_ci      mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;
626370b324cSopenharmony_ci      mixerBond.UnpackIndex = bond.InCoder;
627370b324cSopenharmony_ci      _bindInfo.Bonds.Add(mixerBond);
628370b324cSopenharmony_ci    }
629370b324cSopenharmony_ci
630370b324cSopenharmony_ci    for (i = 0; i < numOutStreams; i++)
631370b324cSopenharmony_ci      if (_bindInfo.FindBond_for_PackStream(i) == -1)
632370b324cSopenharmony_ci        _bindInfo.PackStreams.Add(i);
633370b324cSopenharmony_ci  }
634370b324cSopenharmony_ci
635370b324cSopenharmony_ci  if (!_bindInfo.SetUnpackCoder())
636370b324cSopenharmony_ci    return E_INVALIDARG;
637370b324cSopenharmony_ci
638370b324cSopenharmony_ci  if (!_bindInfo.CalcMapsAndCheck())
639370b324cSopenharmony_ci    return E_INVALIDARG;
640370b324cSopenharmony_ci
641370b324cSopenharmony_ci  if (_bindInfo.PackStreams.Size() != 1)
642370b324cSopenharmony_ci  {
643370b324cSopenharmony_ci    /* main_PackStream is pack stream of main path of coders tree.
644370b324cSopenharmony_ci       We find main_PackStream, and place to start of list of out streams.
645370b324cSopenharmony_ci       It allows to use more optimal memory usage for temp buffers,
646370b324cSopenharmony_ci       if main_PackStream is largest stream. */
647370b324cSopenharmony_ci
648370b324cSopenharmony_ci    UInt32 ci = _bindInfo.UnpackCoder;
649370b324cSopenharmony_ci
650370b324cSopenharmony_ci    for (;;)
651370b324cSopenharmony_ci    {
652370b324cSopenharmony_ci      if (_bindInfo.Coders[ci].NumStreams == 0)
653370b324cSopenharmony_ci        break;
654370b324cSopenharmony_ci
655370b324cSopenharmony_ci      const UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
656370b324cSopenharmony_ci      const int bond = _bindInfo.FindBond_for_PackStream(outIndex);
657370b324cSopenharmony_ci      if (bond >= 0)
658370b324cSopenharmony_ci      {
659370b324cSopenharmony_ci        ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex;
660370b324cSopenharmony_ci        continue;
661370b324cSopenharmony_ci      }
662370b324cSopenharmony_ci
663370b324cSopenharmony_ci      const int si = _bindInfo.FindStream_in_PackStreams(outIndex);
664370b324cSopenharmony_ci      if (si >= 0)
665370b324cSopenharmony_ci        _bindInfo.PackStreams.MoveToFront((unsigned)si);
666370b324cSopenharmony_ci      break;
667370b324cSopenharmony_ci    }
668370b324cSopenharmony_ci  }
669370b324cSopenharmony_ci
670370b324cSopenharmony_ci  if (_options.PasswordIsDefined)
671370b324cSopenharmony_ci  {
672370b324cSopenharmony_ci    unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
673370b324cSopenharmony_ci
674370b324cSopenharmony_ci    unsigned numInStreams = _bindInfo.Coders.Size();
675370b324cSopenharmony_ci
676370b324cSopenharmony_ci    for (i = 0; i < numCryptoStreams; i++)
677370b324cSopenharmony_ci    {
678370b324cSopenharmony_ci      NCoderMixer2::CBond bond;
679370b324cSopenharmony_ci      bond.UnpackIndex = numInStreams + i;
680370b324cSopenharmony_ci      bond.PackIndex = _bindInfo.PackStreams[i];
681370b324cSopenharmony_ci      _bindInfo.Bonds.Add(bond);
682370b324cSopenharmony_ci    }
683370b324cSopenharmony_ci    _bindInfo.PackStreams.Clear();
684370b324cSopenharmony_ci
685370b324cSopenharmony_ci    /*
686370b324cSopenharmony_ci    if (numCryptoStreams == 0)
687370b324cSopenharmony_ci      numCryptoStreams = 1;
688370b324cSopenharmony_ci    */
689370b324cSopenharmony_ci
690370b324cSopenharmony_ci    for (i = 0; i < numCryptoStreams; i++)
691370b324cSopenharmony_ci    {
692370b324cSopenharmony_ci      CMethodFull method;
693370b324cSopenharmony_ci      method.NumStreams = 1;
694370b324cSopenharmony_ci      method.Id = k_AES;
695370b324cSopenharmony_ci      _options.Methods.Add(method);
696370b324cSopenharmony_ci
697370b324cSopenharmony_ci      NCoderMixer2::CCoderStreamsInfo cod;
698370b324cSopenharmony_ci      cod.NumStreams = 1;
699370b324cSopenharmony_ci      _bindInfo.Coders.Add(cod);
700370b324cSopenharmony_ci
701370b324cSopenharmony_ci      _bindInfo.PackStreams.Add(numOutStreams++);
702370b324cSopenharmony_ci    }
703370b324cSopenharmony_ci  }
704370b324cSopenharmony_ci
705370b324cSopenharmony_ci  }
706370b324cSopenharmony_ci
707370b324cSopenharmony_ci  for (unsigned i = _options.Methods.Size(); i != 0;)
708370b324cSopenharmony_ci    _decompressionMethods.Add(_options.Methods[--i].Id);
709370b324cSopenharmony_ci
710370b324cSopenharmony_ci  if (_bindInfo.Coders.Size() > 16)
711370b324cSopenharmony_ci    return E_INVALIDARG;
712370b324cSopenharmony_ci  if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)
713370b324cSopenharmony_ci    return E_INVALIDARG;
714370b324cSopenharmony_ci
715370b324cSopenharmony_ci  if (!_bindInfo.CalcMapsAndCheck())
716370b324cSopenharmony_ci    return E_INVALIDARG;
717370b324cSopenharmony_ci
718370b324cSopenharmony_ci  InitBindConv();
719370b324cSopenharmony_ci  _constructed = true;
720370b324cSopenharmony_ci  return S_OK;
721370b324cSopenharmony_ci}
722370b324cSopenharmony_ci
723370b324cSopenharmony_ciCEncoder::~CEncoder() {}
724370b324cSopenharmony_ci
725370b324cSopenharmony_ci}}
726