xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/7z/7zEncode.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // 7zEncode.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/ComTry.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/CreateCoder.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/FilterCoder.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/LimitedStreams.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/InOutTempBuffer.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ProgressUtils.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamObjects.h"
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker #include "7zEncode.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "7zSpecStream.h"
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
18*f6dc9357SAndroid Build Coastguard Worker namespace N7z {
19*f6dc9357SAndroid Build Coastguard Worker 
InitBindConv()20*f6dc9357SAndroid Build Coastguard Worker void CEncoder::InitBindConv()
21*f6dc9357SAndroid Build Coastguard Worker {
22*f6dc9357SAndroid Build Coastguard Worker   unsigned numIn = _bindInfo.Coders.Size();
23*f6dc9357SAndroid Build Coastguard Worker 
24*f6dc9357SAndroid Build Coastguard Worker   SrcIn_to_DestOut.ClearAndSetSize(numIn);
25*f6dc9357SAndroid Build Coastguard Worker   DestOut_to_SrcIn.ClearAndSetSize(numIn);
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker   unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();
28*f6dc9357SAndroid Build Coastguard Worker   SrcOut_to_DestIn.ClearAndSetSize(numOut);
29*f6dc9357SAndroid Build Coastguard Worker   // _DestIn_to_SrcOut.ClearAndSetSize(numOut);
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker   UInt32 destIn = 0;
32*f6dc9357SAndroid Build Coastguard Worker   UInt32 destOut = 0;
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = _bindInfo.Coders.Size(); i != 0;)
35*f6dc9357SAndroid Build Coastguard Worker   {
36*f6dc9357SAndroid Build Coastguard Worker     i--;
37*f6dc9357SAndroid Build Coastguard Worker 
38*f6dc9357SAndroid Build Coastguard Worker     const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];
39*f6dc9357SAndroid Build Coastguard Worker 
40*f6dc9357SAndroid Build Coastguard Worker     numIn--;
41*f6dc9357SAndroid Build Coastguard Worker     numOut -= coder.NumStreams;
42*f6dc9357SAndroid Build Coastguard Worker 
43*f6dc9357SAndroid Build Coastguard Worker     SrcIn_to_DestOut[numIn] = destOut;
44*f6dc9357SAndroid Build Coastguard Worker     DestOut_to_SrcIn[destOut] = numIn;
45*f6dc9357SAndroid Build Coastguard Worker 
46*f6dc9357SAndroid Build Coastguard Worker     destOut++;
47*f6dc9357SAndroid Build Coastguard Worker 
48*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)
49*f6dc9357SAndroid Build Coastguard Worker     {
50*f6dc9357SAndroid Build Coastguard Worker       UInt32 index = numOut + j;
51*f6dc9357SAndroid Build Coastguard Worker       SrcOut_to_DestIn[index] = destIn;
52*f6dc9357SAndroid Build Coastguard Worker       // _DestIn_to_SrcOut[destIn] = index;
53*f6dc9357SAndroid Build Coastguard Worker     }
54*f6dc9357SAndroid Build Coastguard Worker   }
55*f6dc9357SAndroid Build Coastguard Worker }
56*f6dc9357SAndroid Build Coastguard Worker 
SetFolder(CFolder & folder)57*f6dc9357SAndroid Build Coastguard Worker void CEncoder::SetFolder(CFolder &folder)
58*f6dc9357SAndroid Build Coastguard Worker {
59*f6dc9357SAndroid Build Coastguard Worker   folder.Bonds.SetSize(_bindInfo.Bonds.Size());
60*f6dc9357SAndroid Build Coastguard Worker 
61*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
62*f6dc9357SAndroid Build Coastguard Worker 
63*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < _bindInfo.Bonds.Size(); i++)
64*f6dc9357SAndroid Build Coastguard Worker   {
65*f6dc9357SAndroid Build Coastguard Worker     CBond &fb = folder.Bonds[i];
66*f6dc9357SAndroid Build Coastguard Worker     const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];
67*f6dc9357SAndroid Build Coastguard Worker     fb.PackIndex = SrcOut_to_DestIn[mixerBond.PackIndex];
68*f6dc9357SAndroid Build Coastguard Worker     fb.UnpackIndex = SrcIn_to_DestOut[mixerBond.UnpackIndex];
69*f6dc9357SAndroid Build Coastguard Worker   }
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker   folder.Coders.SetSize(_bindInfo.Coders.Size());
72*f6dc9357SAndroid Build Coastguard Worker 
73*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < _bindInfo.Coders.Size(); i++)
74*f6dc9357SAndroid Build Coastguard Worker   {
75*f6dc9357SAndroid Build Coastguard Worker     CCoderInfo &coderInfo = folder.Coders[i];
76*f6dc9357SAndroid Build Coastguard Worker     const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];
77*f6dc9357SAndroid Build Coastguard Worker 
78*f6dc9357SAndroid Build Coastguard Worker     coderInfo.NumStreams = coderStreamsInfo.NumStreams;
79*f6dc9357SAndroid Build Coastguard Worker     coderInfo.MethodID = _decompressionMethods[i];
80*f6dc9357SAndroid Build Coastguard Worker     // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.
81*f6dc9357SAndroid Build Coastguard Worker   }
82*f6dc9357SAndroid Build Coastguard Worker 
83*f6dc9357SAndroid Build Coastguard Worker   folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());
84*f6dc9357SAndroid Build Coastguard Worker 
85*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < _bindInfo.PackStreams.Size(); i++)
86*f6dc9357SAndroid Build Coastguard Worker     folder.PackStreams[i] = SrcOut_to_DestIn[_bindInfo.PackStreams[i]];
87*f6dc9357SAndroid Build Coastguard Worker }
88*f6dc9357SAndroid Build Coastguard Worker 
89*f6dc9357SAndroid Build Coastguard Worker 
90*f6dc9357SAndroid Build Coastguard Worker 
SetCoderProps2(const CProps & props,const UInt64 * dataSizeReduce,IUnknown * coder)91*f6dc9357SAndroid Build Coastguard Worker static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
92*f6dc9357SAndroid Build Coastguard Worker {
93*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(
94*f6dc9357SAndroid Build Coastguard Worker       ICompressSetCoderProperties,
95*f6dc9357SAndroid Build Coastguard Worker       setCoderProperties, coder)
96*f6dc9357SAndroid Build Coastguard Worker   if (setCoderProperties)
97*f6dc9357SAndroid Build Coastguard Worker     return props.SetCoderProps(setCoderProperties, dataSizeReduce);
98*f6dc9357SAndroid Build Coastguard Worker   return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
99*f6dc9357SAndroid Build Coastguard Worker }
100*f6dc9357SAndroid Build Coastguard Worker 
101*f6dc9357SAndroid Build Coastguard Worker 
102*f6dc9357SAndroid Build Coastguard Worker 
Init(ICompressProgressInfo * progress)103*f6dc9357SAndroid Build Coastguard Worker void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
104*f6dc9357SAndroid Build Coastguard Worker {
105*f6dc9357SAndroid Build Coastguard Worker   _progress = progress;
106*f6dc9357SAndroid Build Coastguard Worker   OutSize = 0;
107*f6dc9357SAndroid Build Coastguard Worker }
108*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CMtEncMultiProgress::SetRatioInfo (const UInt64 * inSize,const UInt64 *))109*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))
110*f6dc9357SAndroid Build Coastguard Worker {
111*f6dc9357SAndroid Build Coastguard Worker   UInt64 outSize2;
112*f6dc9357SAndroid Build Coastguard Worker   {
113*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
114*f6dc9357SAndroid Build Coastguard Worker     NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
115*f6dc9357SAndroid Build Coastguard Worker     #endif
116*f6dc9357SAndroid Build Coastguard Worker     outSize2 = OutSize;
117*f6dc9357SAndroid Build Coastguard Worker   }
118*f6dc9357SAndroid Build Coastguard Worker 
119*f6dc9357SAndroid Build Coastguard Worker   if (_progress)
120*f6dc9357SAndroid Build Coastguard Worker     return _progress->SetRatioInfo(inSize, &outSize2);
121*f6dc9357SAndroid Build Coastguard Worker 
122*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
123*f6dc9357SAndroid Build Coastguard Worker }
124*f6dc9357SAndroid Build Coastguard Worker 
125*f6dc9357SAndroid Build Coastguard Worker 
126*f6dc9357SAndroid Build Coastguard Worker 
CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 * inSizeForReduce)127*f6dc9357SAndroid Build Coastguard Worker HRESULT CEncoder::CreateMixerCoder(
128*f6dc9357SAndroid Build Coastguard Worker     DECL_EXTERNAL_CODECS_LOC_VARS
129*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *inSizeForReduce)
130*f6dc9357SAndroid Build Coastguard Worker {
131*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_MIXER_MT
132*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_MIXER_ST
133*f6dc9357SAndroid Build Coastguard Worker   if (_options.MultiThreadMixer)
134*f6dc9357SAndroid Build Coastguard Worker   #endif
135*f6dc9357SAndroid Build Coastguard Worker   {
136*f6dc9357SAndroid Build Coastguard Worker     _mixerMT = new NCoderMixer2::CMixerMT(true);
137*f6dc9357SAndroid Build Coastguard Worker     _mixerRef = _mixerMT;
138*f6dc9357SAndroid Build Coastguard Worker     _mixer = _mixerMT;
139*f6dc9357SAndroid Build Coastguard Worker   }
140*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_MIXER_ST
141*f6dc9357SAndroid Build Coastguard Worker   else
142*f6dc9357SAndroid Build Coastguard Worker   #endif
143*f6dc9357SAndroid Build Coastguard Worker   #endif
144*f6dc9357SAndroid Build Coastguard Worker   {
145*f6dc9357SAndroid Build Coastguard Worker     #ifdef USE_MIXER_ST
146*f6dc9357SAndroid Build Coastguard Worker     _mixerST = new NCoderMixer2::CMixerST(true);
147*f6dc9357SAndroid Build Coastguard Worker     _mixerRef = _mixerST;
148*f6dc9357SAndroid Build Coastguard Worker     _mixer = _mixerST;
149*f6dc9357SAndroid Build Coastguard Worker     #endif
150*f6dc9357SAndroid Build Coastguard Worker   }
151*f6dc9357SAndroid Build Coastguard Worker 
152*f6dc9357SAndroid Build Coastguard Worker   RINOK(_mixer->SetBindInfo(_bindInfo))
153*f6dc9357SAndroid Build Coastguard Worker 
154*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (m, _options.Methods)
155*f6dc9357SAndroid Build Coastguard Worker   {
156*f6dc9357SAndroid Build Coastguard Worker     const CMethodFull &methodFull = _options.Methods[m];
157*f6dc9357SAndroid Build Coastguard Worker 
158*f6dc9357SAndroid Build Coastguard Worker     CCreatedCoder cod;
159*f6dc9357SAndroid Build Coastguard Worker 
160*f6dc9357SAndroid Build Coastguard Worker     if (methodFull.CodecIndex >= 0)
161*f6dc9357SAndroid Build Coastguard Worker     {
162*f6dc9357SAndroid Build Coastguard Worker       RINOK(CreateCoder_Index(
163*f6dc9357SAndroid Build Coastguard Worker         EXTERNAL_CODECS_LOC_VARS
164*f6dc9357SAndroid Build Coastguard Worker         (unsigned)methodFull.CodecIndex, true, cod))
165*f6dc9357SAndroid Build Coastguard Worker     }
166*f6dc9357SAndroid Build Coastguard Worker     else
167*f6dc9357SAndroid Build Coastguard Worker     {
168*f6dc9357SAndroid Build Coastguard Worker       RINOK(CreateCoder_Id(
169*f6dc9357SAndroid Build Coastguard Worker         EXTERNAL_CODECS_LOC_VARS
170*f6dc9357SAndroid Build Coastguard Worker         methodFull.Id, true, cod))
171*f6dc9357SAndroid Build Coastguard Worker     }
172*f6dc9357SAndroid Build Coastguard Worker 
173*f6dc9357SAndroid Build Coastguard Worker     if (!cod.Coder && !cod.Coder2)
174*f6dc9357SAndroid Build Coastguard Worker     {
175*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL; // unsupported method, if encoder
176*f6dc9357SAndroid Build Coastguard Worker       // return E_FAIL;
177*f6dc9357SAndroid Build Coastguard Worker     }
178*f6dc9357SAndroid Build Coastguard Worker 
179*f6dc9357SAndroid Build Coastguard Worker     if (cod.NumStreams != methodFull.NumStreams)
180*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
181*f6dc9357SAndroid Build Coastguard Worker 
182*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
183*f6dc9357SAndroid Build Coastguard Worker 
184*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
185*f6dc9357SAndroid Build Coastguard Worker     if (methodFull.Set_NumThreads)
186*f6dc9357SAndroid Build Coastguard Worker     {
187*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr<ICompressSetCoderMt> setCoderMt;
188*f6dc9357SAndroid Build Coastguard Worker       encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
189*f6dc9357SAndroid Build Coastguard Worker       if (setCoderMt)
190*f6dc9357SAndroid Build Coastguard Worker       {
191*f6dc9357SAndroid Build Coastguard Worker         RINOK(setCoderMt->SetNumberOfThreads(
192*f6dc9357SAndroid Build Coastguard Worker             /* _options.NumThreads */
193*f6dc9357SAndroid Build Coastguard Worker             methodFull.NumThreads
194*f6dc9357SAndroid Build Coastguard Worker             ))
195*f6dc9357SAndroid Build Coastguard Worker       }
196*f6dc9357SAndroid Build Coastguard Worker     }
197*f6dc9357SAndroid Build Coastguard Worker     #endif
198*f6dc9357SAndroid Build Coastguard Worker 
199*f6dc9357SAndroid Build Coastguard Worker     RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon))
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker     /*
202*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ICryptoResetSalt> resetSalt;
203*f6dc9357SAndroid Build Coastguard Worker     encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
204*f6dc9357SAndroid Build Coastguard Worker     if (resetSalt)
205*f6dc9357SAndroid Build Coastguard Worker     {
206*f6dc9357SAndroid Build Coastguard Worker       resetSalt->ResetSalt();
207*f6dc9357SAndroid Build Coastguard Worker     }
208*f6dc9357SAndroid Build Coastguard Worker     */
209*f6dc9357SAndroid Build Coastguard Worker 
210*f6dc9357SAndroid Build Coastguard Worker     // now there is no codec that uses another external codec
211*f6dc9357SAndroid Build Coastguard Worker     /*
212*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_EXTERNAL_CODECS
213*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
214*f6dc9357SAndroid Build Coastguard Worker     encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
215*f6dc9357SAndroid Build Coastguard Worker     if (setCompressCodecsInfo)
216*f6dc9357SAndroid Build Coastguard Worker     {
217*f6dc9357SAndroid Build Coastguard Worker       // we must use g_ExternalCodecs also
218*f6dc9357SAndroid Build Coastguard Worker       RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs));
219*f6dc9357SAndroid Build Coastguard Worker     }
220*f6dc9357SAndroid Build Coastguard Worker     #endif
221*f6dc9357SAndroid Build Coastguard Worker     */
222*f6dc9357SAndroid Build Coastguard Worker 
223*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
224*f6dc9357SAndroid Build Coastguard Worker     encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
225*f6dc9357SAndroid Build Coastguard Worker 
226*f6dc9357SAndroid Build Coastguard Worker     if (cryptoSetPassword)
227*f6dc9357SAndroid Build Coastguard Worker     {
228*f6dc9357SAndroid Build Coastguard Worker       const unsigned sizeInBytes = _options.Password.Len() * 2;
229*f6dc9357SAndroid Build Coastguard Worker       CByteBuffer_Wipe buffer(sizeInBytes);
230*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0; i < _options.Password.Len(); i++)
231*f6dc9357SAndroid Build Coastguard Worker       {
232*f6dc9357SAndroid Build Coastguard Worker         wchar_t c = _options.Password[i];
233*f6dc9357SAndroid Build Coastguard Worker         ((Byte *)buffer)[i * 2] = (Byte)c;
234*f6dc9357SAndroid Build Coastguard Worker         ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
235*f6dc9357SAndroid Build Coastguard Worker       }
236*f6dc9357SAndroid Build Coastguard Worker       RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes))
237*f6dc9357SAndroid Build Coastguard Worker     }
238*f6dc9357SAndroid Build Coastguard Worker 
239*f6dc9357SAndroid Build Coastguard Worker     _mixer->AddCoder(cod);
240*f6dc9357SAndroid Build Coastguard Worker   }
241*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
242*f6dc9357SAndroid Build Coastguard Worker }
243*f6dc9357SAndroid Build Coastguard Worker 
244*f6dc9357SAndroid Build Coastguard Worker 
245*f6dc9357SAndroid Build Coastguard Worker 
246*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1(
247*f6dc9357SAndroid Build Coastguard Worker   CSequentialOutTempBufferImp2
248*f6dc9357SAndroid Build Coastguard Worker   , ISequentialOutStream
249*f6dc9357SAndroid Build Coastguard Worker )
250*f6dc9357SAndroid Build Coastguard Worker public:
251*f6dc9357SAndroid Build Coastguard Worker   CInOutTempBuffer TempBuffer;
252*f6dc9357SAndroid Build Coastguard Worker   CMtEncMultiProgress *_mtProgressSpec;
253*f6dc9357SAndroid Build Coastguard Worker 
254*f6dc9357SAndroid Build Coastguard Worker   CSequentialOutTempBufferImp2(): _mtProgressSpec(NULL) {}
255*f6dc9357SAndroid Build Coastguard Worker };
256*f6dc9357SAndroid Build Coastguard Worker 
257*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed))
258*f6dc9357SAndroid Build Coastguard Worker {
259*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
260*f6dc9357SAndroid Build Coastguard Worker   if (processed)
261*f6dc9357SAndroid Build Coastguard Worker     *processed = 0;
262*f6dc9357SAndroid Build Coastguard Worker   RINOK(TempBuffer.Write_HRESULT(data, size))
263*f6dc9357SAndroid Build Coastguard Worker   if (processed)
264*f6dc9357SAndroid Build Coastguard Worker     *processed = size;
265*f6dc9357SAndroid Build Coastguard Worker   if (_mtProgressSpec)
266*f6dc9357SAndroid Build Coastguard Worker     _mtProgressSpec->AddOutSize(size);
267*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
268*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
269*f6dc9357SAndroid Build Coastguard Worker }
270*f6dc9357SAndroid Build Coastguard Worker 
271*f6dc9357SAndroid Build Coastguard Worker 
272*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1(
273*f6dc9357SAndroid Build Coastguard Worker   CSequentialOutMtNotify
274*f6dc9357SAndroid Build Coastguard Worker   , ISequentialOutStream
275*f6dc9357SAndroid Build Coastguard Worker )
276*f6dc9357SAndroid Build Coastguard Worker public:
277*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> _stream;
278*f6dc9357SAndroid Build Coastguard Worker   CMtEncMultiProgress *_mtProgressSpec;
279*f6dc9357SAndroid Build Coastguard Worker 
280*f6dc9357SAndroid Build Coastguard Worker   CSequentialOutMtNotify(): _mtProgressSpec(NULL) {}
281*f6dc9357SAndroid Build Coastguard Worker };
282*f6dc9357SAndroid Build Coastguard Worker 
283*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed))
284*f6dc9357SAndroid Build Coastguard Worker {
285*f6dc9357SAndroid Build Coastguard Worker   UInt32 realProcessed = 0;
286*f6dc9357SAndroid Build Coastguard Worker   HRESULT res = _stream->Write(data, size, &realProcessed);
287*f6dc9357SAndroid Build Coastguard Worker   if (processed)
288*f6dc9357SAndroid Build Coastguard Worker     *processed = realProcessed;
289*f6dc9357SAndroid Build Coastguard Worker   if (_mtProgressSpec)
290*f6dc9357SAndroid Build Coastguard Worker     _mtProgressSpec->AddOutSize(size);
291*f6dc9357SAndroid Build Coastguard Worker   return res;
292*f6dc9357SAndroid Build Coastguard Worker }
293*f6dc9357SAndroid Build Coastguard Worker 
294*f6dc9357SAndroid Build Coastguard Worker 
295*f6dc9357SAndroid Build Coastguard Worker static HRESULT FillProps_from_Coder(IUnknown *coder, CByteBuffer &props)
296*f6dc9357SAndroid Build Coastguard Worker {
297*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(
298*f6dc9357SAndroid Build Coastguard Worker       ICompressWriteCoderProperties,
299*f6dc9357SAndroid Build Coastguard Worker       writeCoderProperties, coder)
300*f6dc9357SAndroid Build Coastguard Worker   if (writeCoderProperties)
301*f6dc9357SAndroid Build Coastguard Worker   {
302*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr2_Create<ISequentialOutStream, CDynBufSeqOutStream> outStreamSpec;
303*f6dc9357SAndroid Build Coastguard Worker     outStreamSpec->Init();
304*f6dc9357SAndroid Build Coastguard Worker     RINOK(writeCoderProperties->WriteCoderProperties(outStreamSpec))
305*f6dc9357SAndroid Build Coastguard Worker     outStreamSpec->CopyToBuffer(props);
306*f6dc9357SAndroid Build Coastguard Worker   }
307*f6dc9357SAndroid Build Coastguard Worker   else
308*f6dc9357SAndroid Build Coastguard Worker     props.Free();
309*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
310*f6dc9357SAndroid Build Coastguard Worker }
311*f6dc9357SAndroid Build Coastguard Worker 
312*f6dc9357SAndroid Build Coastguard Worker HRESULT CEncoder::Encode1(
313*f6dc9357SAndroid Build Coastguard Worker     DECL_EXTERNAL_CODECS_LOC_VARS
314*f6dc9357SAndroid Build Coastguard Worker     ISequentialInStream *inStream,
315*f6dc9357SAndroid Build Coastguard Worker     // const UInt64 *inStreamSize,
316*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *inSizeForReduce,
317*f6dc9357SAndroid Build Coastguard Worker     UInt64 expectedDataSize,
318*f6dc9357SAndroid Build Coastguard Worker     CFolder &folderItem,
319*f6dc9357SAndroid Build Coastguard Worker     // CRecordVector<UInt64> &coderUnpackSizes,
320*f6dc9357SAndroid Build Coastguard Worker     // UInt64 &unpackSize,
321*f6dc9357SAndroid Build Coastguard Worker     ISequentialOutStream *outStream,
322*f6dc9357SAndroid Build Coastguard Worker     CRecordVector<UInt64> &packSizes,
323*f6dc9357SAndroid Build Coastguard Worker     ICompressProgressInfo *compressProgress)
324*f6dc9357SAndroid Build Coastguard Worker {
325*f6dc9357SAndroid Build Coastguard Worker   RINOK(EncoderConstr())
326*f6dc9357SAndroid Build Coastguard Worker 
327*f6dc9357SAndroid Build Coastguard Worker   if (!_mixerRef)
328*f6dc9357SAndroid Build Coastguard Worker   {
329*f6dc9357SAndroid Build Coastguard Worker     RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce))
330*f6dc9357SAndroid Build Coastguard Worker   }
331*f6dc9357SAndroid Build Coastguard Worker 
332*f6dc9357SAndroid Build Coastguard Worker   RINOK(_mixer->ReInit2())
333*f6dc9357SAndroid Build Coastguard Worker 
334*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2<ICompressProgressInfo, CMtEncMultiProgress> mtProgress;
335*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2<ISequentialOutStream, CSequentialOutMtNotify> mtOutStreamNotify;
336*f6dc9357SAndroid Build Coastguard Worker 
337*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
338*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
339*f6dc9357SAndroid Build Coastguard Worker 
340*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
341*f6dc9357SAndroid Build Coastguard Worker 
342*f6dc9357SAndroid Build Coastguard Worker   for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
343*f6dc9357SAndroid Build Coastguard Worker   {
344*f6dc9357SAndroid Build Coastguard Worker     CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2();
345*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
346*f6dc9357SAndroid Build Coastguard Worker     tempBufferSpecs.Add(tempBufferSpec);
347*f6dc9357SAndroid Build Coastguard Worker     tempBuffers.Add(tempBuffer);
348*f6dc9357SAndroid Build Coastguard Worker   }
349*f6dc9357SAndroid Build Coastguard Worker 
350*f6dc9357SAndroid Build Coastguard Worker   const unsigned numMethods = _bindInfo.Coders.Size();
351*f6dc9357SAndroid Build Coastguard Worker 
352*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numMethods; i++)
353*f6dc9357SAndroid Build Coastguard Worker     _mixer->SetCoderInfo(i, NULL, NULL, false);
354*f6dc9357SAndroid Build Coastguard Worker 
355*f6dc9357SAndroid Build Coastguard Worker 
356*f6dc9357SAndroid Build Coastguard Worker   /* inStreamSize can be used by BCJ2 to set optimal range of conversion.
357*f6dc9357SAndroid Build Coastguard Worker      But current BCJ2 encoder uses also another way to check exact size of current file.
358*f6dc9357SAndroid Build Coastguard Worker      So inStreamSize is not required. */
359*f6dc9357SAndroid Build Coastguard Worker 
360*f6dc9357SAndroid Build Coastguard Worker   /*
361*f6dc9357SAndroid Build Coastguard Worker   if (inStreamSize)
362*f6dc9357SAndroid Build Coastguard Worker     _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
363*f6dc9357SAndroid Build Coastguard Worker   */
364*f6dc9357SAndroid Build Coastguard Worker 
365*f6dc9357SAndroid Build Coastguard Worker 
366*f6dc9357SAndroid Build Coastguard Worker   /*
367*f6dc9357SAndroid Build Coastguard Worker   CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
368*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
369*f6dc9357SAndroid Build Coastguard Worker   */
370*f6dc9357SAndroid Build Coastguard Worker 
371*f6dc9357SAndroid Build Coastguard Worker   CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
372*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> outStreamSizeCount;
373*f6dc9357SAndroid Build Coastguard Worker 
374*f6dc9357SAndroid Build Coastguard Worker   // inStreamSizeCountSpec->Init(inStream);
375*f6dc9357SAndroid Build Coastguard Worker 
376*f6dc9357SAndroid Build Coastguard Worker   // ISequentialInStream *inStreamPointer = inStreamSizeCount;
377*f6dc9357SAndroid Build Coastguard Worker   ISequentialInStream *inStreamPointer = inStream;
378*f6dc9357SAndroid Build Coastguard Worker 
379*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<ISequentialOutStream *> outStreamPointers;
380*f6dc9357SAndroid Build Coastguard Worker 
381*f6dc9357SAndroid Build Coastguard Worker   SetFolder(folderItem);
382*f6dc9357SAndroid Build Coastguard Worker 
383*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numMethods; i++)
384*f6dc9357SAndroid Build Coastguard Worker   {
385*f6dc9357SAndroid Build Coastguard Worker     IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
386*f6dc9357SAndroid Build Coastguard Worker     /*
387*f6dc9357SAndroid Build Coastguard Worker     {
388*f6dc9357SAndroid Build Coastguard Worker       CEncoder *sfEncoder = NULL;
389*f6dc9357SAndroid Build Coastguard Worker       Z7_DECL_CMyComPtr_QI_FROM(
390*f6dc9357SAndroid Build Coastguard Worker           IGetSfEncoderInternal,
391*f6dc9357SAndroid Build Coastguard Worker           sf, coder)
392*f6dc9357SAndroid Build Coastguard Worker       if (sf)
393*f6dc9357SAndroid Build Coastguard Worker       {
394*f6dc9357SAndroid Build Coastguard Worker         RINOK(sf->GetSfEncoder(&sfEncoder));
395*f6dc9357SAndroid Build Coastguard Worker         if (!sfEncoder)
396*f6dc9357SAndroid Build Coastguard Worker           return E_FAIL;
397*f6dc9357SAndroid Build Coastguard Worker 
398*f6dc9357SAndroid Build Coastguard Worker       }
399*f6dc9357SAndroid Build Coastguard Worker     }
400*f6dc9357SAndroid Build Coastguard Worker     */
401*f6dc9357SAndroid Build Coastguard Worker     /*
402*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_EXTERNAL_CODECS
403*f6dc9357SAndroid Build Coastguard Worker     {
404*f6dc9357SAndroid Build Coastguard Worker       Z7_DECL_CMyComPtr_QI_FROM(
405*f6dc9357SAndroid Build Coastguard Worker           ISetCompressCodecsInfo,
406*f6dc9357SAndroid Build Coastguard Worker           setCompressCodecsInfo, coder)
407*f6dc9357SAndroid Build Coastguard Worker       if (setCompressCodecsInfo)
408*f6dc9357SAndroid Build Coastguard Worker       {
409*f6dc9357SAndroid Build Coastguard Worker         // we must use g_ExternalCodecs also
410*f6dc9357SAndroid Build Coastguard Worker         RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs))
411*f6dc9357SAndroid Build Coastguard Worker       }
412*f6dc9357SAndroid Build Coastguard Worker     }
413*f6dc9357SAndroid Build Coastguard Worker     #endif
414*f6dc9357SAndroid Build Coastguard Worker     */
415*f6dc9357SAndroid Build Coastguard Worker     {
416*f6dc9357SAndroid Build Coastguard Worker       Z7_DECL_CMyComPtr_QI_FROM(
417*f6dc9357SAndroid Build Coastguard Worker           ICryptoResetInitVector,
418*f6dc9357SAndroid Build Coastguard Worker           resetInitVector, coder)
419*f6dc9357SAndroid Build Coastguard Worker       if (resetInitVector)
420*f6dc9357SAndroid Build Coastguard Worker       {
421*f6dc9357SAndroid Build Coastguard Worker         RINOK(resetInitVector->ResetInitVector())
422*f6dc9357SAndroid Build Coastguard Worker       }
423*f6dc9357SAndroid Build Coastguard Worker     }
424*f6dc9357SAndroid Build Coastguard Worker     {
425*f6dc9357SAndroid Build Coastguard Worker       Z7_DECL_CMyComPtr_QI_FROM(
426*f6dc9357SAndroid Build Coastguard Worker           ICompressSetCoderPropertiesOpt,
427*f6dc9357SAndroid Build Coastguard Worker           optProps, coder)
428*f6dc9357SAndroid Build Coastguard Worker       if (optProps)
429*f6dc9357SAndroid Build Coastguard Worker       {
430*f6dc9357SAndroid Build Coastguard Worker         const PROPID propID = NCoderPropID::kExpectedDataSize;
431*f6dc9357SAndroid Build Coastguard Worker         NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;
432*f6dc9357SAndroid Build Coastguard Worker         RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1))
433*f6dc9357SAndroid Build Coastguard Worker       }
434*f6dc9357SAndroid Build Coastguard Worker     }
435*f6dc9357SAndroid Build Coastguard Worker     // we must write properties from coder after ResetInitVector()
436*f6dc9357SAndroid Build Coastguard Worker     RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))
437*f6dc9357SAndroid Build Coastguard Worker   }
438*f6dc9357SAndroid Build Coastguard Worker 
439*f6dc9357SAndroid Build Coastguard Worker   _mixer->SelectMainCoder(false);
440*f6dc9357SAndroid Build Coastguard Worker   const UInt32 mainCoder = _mixer->MainCoderIndex;
441*f6dc9357SAndroid Build Coastguard Worker 
442*f6dc9357SAndroid Build Coastguard Worker   bool useMtProgress = false;
443*f6dc9357SAndroid Build Coastguard Worker   if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
444*f6dc9357SAndroid Build Coastguard Worker   {
445*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_ST
446*f6dc9357SAndroid Build Coastguard Worker     if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
447*f6dc9357SAndroid Build Coastguard Worker     #endif
448*f6dc9357SAndroid Build Coastguard Worker       useMtProgress = true;
449*f6dc9357SAndroid Build Coastguard Worker   }
450*f6dc9357SAndroid Build Coastguard Worker 
451*f6dc9357SAndroid Build Coastguard Worker   if (useMtProgress)
452*f6dc9357SAndroid Build Coastguard Worker   {
453*f6dc9357SAndroid Build Coastguard Worker     mtProgress.SetFromCls(new CMtEncMultiProgress);
454*f6dc9357SAndroid Build Coastguard Worker     mtProgress->Init(compressProgress);
455*f6dc9357SAndroid Build Coastguard Worker 
456*f6dc9357SAndroid Build Coastguard Worker     mtOutStreamNotify.SetFromCls(new CSequentialOutMtNotify);
457*f6dc9357SAndroid Build Coastguard Worker     mtOutStreamNotify->_stream = outStream;
458*f6dc9357SAndroid Build Coastguard Worker     mtOutStreamNotify->_mtProgressSpec = mtProgress.ClsPtr();
459*f6dc9357SAndroid Build Coastguard Worker 
460*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (t, tempBufferSpecs)
461*f6dc9357SAndroid Build Coastguard Worker     {
462*f6dc9357SAndroid Build Coastguard Worker       tempBufferSpecs[t]->_mtProgressSpec = mtProgress.ClsPtr();
463*f6dc9357SAndroid Build Coastguard Worker     }
464*f6dc9357SAndroid Build Coastguard Worker   }
465*f6dc9357SAndroid Build Coastguard Worker 
466*f6dc9357SAndroid Build Coastguard Worker 
467*f6dc9357SAndroid Build Coastguard Worker   if (_bindInfo.PackStreams.Size() != 0)
468*f6dc9357SAndroid Build Coastguard Worker   {
469*f6dc9357SAndroid Build Coastguard Worker     outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
470*f6dc9357SAndroid Build Coastguard Worker     outStreamSizeCount = outStreamSizeCountSpec;
471*f6dc9357SAndroid Build Coastguard Worker     outStreamSizeCountSpec->SetStream(mtOutStreamNotify.IsDefined() ?
472*f6dc9357SAndroid Build Coastguard Worker         mtOutStreamNotify.Interface() : outStream);
473*f6dc9357SAndroid Build Coastguard Worker     outStreamSizeCountSpec->Init();
474*f6dc9357SAndroid Build Coastguard Worker     outStreamPointers.Add(outStreamSizeCount);
475*f6dc9357SAndroid Build Coastguard Worker   }
476*f6dc9357SAndroid Build Coastguard Worker 
477*f6dc9357SAndroid Build Coastguard Worker   for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
478*f6dc9357SAndroid Build Coastguard Worker     outStreamPointers.Add(tempBuffers[i - 1]);
479*f6dc9357SAndroid Build Coastguard Worker 
480*f6dc9357SAndroid Build Coastguard Worker   bool dataAfterEnd_Error;
481*f6dc9357SAndroid Build Coastguard Worker 
482*f6dc9357SAndroid Build Coastguard Worker   RINOK(_mixer->Code(
483*f6dc9357SAndroid Build Coastguard Worker       &inStreamPointer,
484*f6dc9357SAndroid Build Coastguard Worker       outStreamPointers.ConstData(),
485*f6dc9357SAndroid Build Coastguard Worker       mtProgress.IsDefined() ? mtProgress.Interface() :
486*f6dc9357SAndroid Build Coastguard Worker         compressProgress, dataAfterEnd_Error))
487*f6dc9357SAndroid Build Coastguard Worker 
488*f6dc9357SAndroid Build Coastguard Worker   if (_bindInfo.PackStreams.Size() != 0)
489*f6dc9357SAndroid Build Coastguard Worker     packSizes.Add(outStreamSizeCountSpec->GetSize());
490*f6dc9357SAndroid Build Coastguard Worker 
491*f6dc9357SAndroid Build Coastguard Worker   for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
492*f6dc9357SAndroid Build Coastguard Worker   {
493*f6dc9357SAndroid Build Coastguard Worker     CInOutTempBuffer &iotb = tempBufferSpecs[i - 1]->TempBuffer;
494*f6dc9357SAndroid Build Coastguard Worker     RINOK(iotb.WriteToStream(outStream))
495*f6dc9357SAndroid Build Coastguard Worker     packSizes.Add(iotb.GetDataSize());
496*f6dc9357SAndroid Build Coastguard Worker   }
497*f6dc9357SAndroid Build Coastguard Worker 
498*f6dc9357SAndroid Build Coastguard Worker   /* Code() in some future codec can change properties.
499*f6dc9357SAndroid Build Coastguard Worker      v23: so we fill properties again after Code() */
500*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numMethods; i++)
501*f6dc9357SAndroid Build Coastguard Worker   {
502*f6dc9357SAndroid Build Coastguard Worker     IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
503*f6dc9357SAndroid Build Coastguard Worker     RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))
504*f6dc9357SAndroid Build Coastguard Worker   }
505*f6dc9357SAndroid Build Coastguard Worker 
506*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
507*f6dc9357SAndroid Build Coastguard Worker }
508*f6dc9357SAndroid Build Coastguard Worker 
509*f6dc9357SAndroid Build Coastguard Worker 
510*f6dc9357SAndroid Build Coastguard Worker void CEncoder::Encode_Post(
511*f6dc9357SAndroid Build Coastguard Worker       UInt64 unpackSize,
512*f6dc9357SAndroid Build Coastguard Worker       CRecordVector<UInt64> &coderUnpackSizes)
513*f6dc9357SAndroid Build Coastguard Worker {
514*f6dc9357SAndroid Build Coastguard Worker   // unpackSize = 0;
515*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < _bindInfo.Coders.Size(); i++)
516*f6dc9357SAndroid Build Coastguard Worker   {
517*f6dc9357SAndroid Build Coastguard Worker     const int bond = _bindInfo.FindBond_for_UnpackStream(DestOut_to_SrcIn[i]);
518*f6dc9357SAndroid Build Coastguard Worker     UInt64 streamSize;
519*f6dc9357SAndroid Build Coastguard Worker     if (bond < 0)
520*f6dc9357SAndroid Build Coastguard Worker     {
521*f6dc9357SAndroid Build Coastguard Worker       // streamSize = inStreamSizeCountSpec->GetSize();
522*f6dc9357SAndroid Build Coastguard Worker       // unpackSize = streamSize;
523*f6dc9357SAndroid Build Coastguard Worker       streamSize = unpackSize;
524*f6dc9357SAndroid Build Coastguard Worker     }
525*f6dc9357SAndroid Build Coastguard Worker     else
526*f6dc9357SAndroid Build Coastguard Worker       streamSize = _mixer->GetBondStreamSize((unsigned)bond);
527*f6dc9357SAndroid Build Coastguard Worker     coderUnpackSizes.Add(streamSize);
528*f6dc9357SAndroid Build Coastguard Worker   }
529*f6dc9357SAndroid Build Coastguard Worker }
530*f6dc9357SAndroid Build Coastguard Worker 
531*f6dc9357SAndroid Build Coastguard Worker 
532*f6dc9357SAndroid Build Coastguard Worker CEncoder::CEncoder(const CCompressionMethodMode &options):
533*f6dc9357SAndroid Build Coastguard Worker     _constructed(false)
534*f6dc9357SAndroid Build Coastguard Worker {
535*f6dc9357SAndroid Build Coastguard Worker   if (options.IsEmpty())
536*f6dc9357SAndroid Build Coastguard Worker     throw 1;
537*f6dc9357SAndroid Build Coastguard Worker 
538*f6dc9357SAndroid Build Coastguard Worker   _options = options;
539*f6dc9357SAndroid Build Coastguard Worker 
540*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_MIXER_ST
541*f6dc9357SAndroid Build Coastguard Worker     _mixerST = NULL;
542*f6dc9357SAndroid Build Coastguard Worker   #endif
543*f6dc9357SAndroid Build Coastguard Worker 
544*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_MIXER_MT
545*f6dc9357SAndroid Build Coastguard Worker     _mixerMT = NULL;
546*f6dc9357SAndroid Build Coastguard Worker   #endif
547*f6dc9357SAndroid Build Coastguard Worker 
548*f6dc9357SAndroid Build Coastguard Worker   _mixer = NULL;
549*f6dc9357SAndroid Build Coastguard Worker }
550*f6dc9357SAndroid Build Coastguard Worker 
551*f6dc9357SAndroid Build Coastguard Worker 
552*f6dc9357SAndroid Build Coastguard Worker HRESULT CEncoder::EncoderConstr()
553*f6dc9357SAndroid Build Coastguard Worker {
554*f6dc9357SAndroid Build Coastguard Worker   if (_constructed)
555*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
556*f6dc9357SAndroid Build Coastguard Worker   if (_options.Methods.IsEmpty())
557*f6dc9357SAndroid Build Coastguard Worker   {
558*f6dc9357SAndroid Build Coastguard Worker     // it has only password method;
559*f6dc9357SAndroid Build Coastguard Worker     if (!_options.PasswordIsDefined)
560*f6dc9357SAndroid Build Coastguard Worker       throw 1;
561*f6dc9357SAndroid Build Coastguard Worker     if (!_options.Bonds.IsEmpty())
562*f6dc9357SAndroid Build Coastguard Worker       throw 1;
563*f6dc9357SAndroid Build Coastguard Worker 
564*f6dc9357SAndroid Build Coastguard Worker     CMethodFull method;
565*f6dc9357SAndroid Build Coastguard Worker     method.Id = k_AES;
566*f6dc9357SAndroid Build Coastguard Worker     method.NumStreams = 1;
567*f6dc9357SAndroid Build Coastguard Worker     _options.Methods.Add(method);
568*f6dc9357SAndroid Build Coastguard Worker 
569*f6dc9357SAndroid Build Coastguard Worker     NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
570*f6dc9357SAndroid Build Coastguard Worker     coderStreamsInfo.NumStreams = 1;
571*f6dc9357SAndroid Build Coastguard Worker     _bindInfo.Coders.Add(coderStreamsInfo);
572*f6dc9357SAndroid Build Coastguard Worker 
573*f6dc9357SAndroid Build Coastguard Worker     _bindInfo.PackStreams.Add(0);
574*f6dc9357SAndroid Build Coastguard Worker     _bindInfo.UnpackCoder = 0;
575*f6dc9357SAndroid Build Coastguard Worker   }
576*f6dc9357SAndroid Build Coastguard Worker   else
577*f6dc9357SAndroid Build Coastguard Worker   {
578*f6dc9357SAndroid Build Coastguard Worker 
579*f6dc9357SAndroid Build Coastguard Worker   UInt32 numOutStreams = 0;
580*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
581*f6dc9357SAndroid Build Coastguard Worker 
582*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < _options.Methods.Size(); i++)
583*f6dc9357SAndroid Build Coastguard Worker   {
584*f6dc9357SAndroid Build Coastguard Worker     const CMethodFull &methodFull = _options.Methods[i];
585*f6dc9357SAndroid Build Coastguard Worker     NCoderMixer2::CCoderStreamsInfo cod;
586*f6dc9357SAndroid Build Coastguard Worker 
587*f6dc9357SAndroid Build Coastguard Worker     cod.NumStreams = methodFull.NumStreams;
588*f6dc9357SAndroid Build Coastguard Worker 
589*f6dc9357SAndroid Build Coastguard Worker     if (_options.Bonds.IsEmpty())
590*f6dc9357SAndroid Build Coastguard Worker     {
591*f6dc9357SAndroid Build Coastguard Worker       // if there are no bonds in options, we create bonds via first streams of coders
592*f6dc9357SAndroid Build Coastguard Worker       if (i != _options.Methods.Size() - 1)
593*f6dc9357SAndroid Build Coastguard Worker       {
594*f6dc9357SAndroid Build Coastguard Worker         NCoderMixer2::CBond bond;
595*f6dc9357SAndroid Build Coastguard Worker         bond.PackIndex = numOutStreams;
596*f6dc9357SAndroid Build Coastguard Worker         bond.UnpackIndex = i + 1; // it's next coder
597*f6dc9357SAndroid Build Coastguard Worker         _bindInfo.Bonds.Add(bond);
598*f6dc9357SAndroid Build Coastguard Worker       }
599*f6dc9357SAndroid Build Coastguard Worker       else if (cod.NumStreams != 0)
600*f6dc9357SAndroid Build Coastguard Worker         _bindInfo.PackStreams.Insert(0, numOutStreams);
601*f6dc9357SAndroid Build Coastguard Worker 
602*f6dc9357SAndroid Build Coastguard Worker       for (UInt32 j = 1; j < cod.NumStreams; j++)
603*f6dc9357SAndroid Build Coastguard Worker         _bindInfo.PackStreams.Add(numOutStreams + j);
604*f6dc9357SAndroid Build Coastguard Worker     }
605*f6dc9357SAndroid Build Coastguard Worker 
606*f6dc9357SAndroid Build Coastguard Worker     numOutStreams += cod.NumStreams;
607*f6dc9357SAndroid Build Coastguard Worker 
608*f6dc9357SAndroid Build Coastguard Worker     _bindInfo.Coders.Add(cod);
609*f6dc9357SAndroid Build Coastguard Worker   }
610*f6dc9357SAndroid Build Coastguard Worker 
611*f6dc9357SAndroid Build Coastguard Worker   if (!_options.Bonds.IsEmpty())
612*f6dc9357SAndroid Build Coastguard Worker   {
613*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < _options.Bonds.Size(); i++)
614*f6dc9357SAndroid Build Coastguard Worker     {
615*f6dc9357SAndroid Build Coastguard Worker       NCoderMixer2::CBond mixerBond;
616*f6dc9357SAndroid Build Coastguard Worker       const CBond2 &bond = _options.Bonds[i];
617*f6dc9357SAndroid Build Coastguard Worker       if (bond.InCoder >= _bindInfo.Coders.Size()
618*f6dc9357SAndroid Build Coastguard Worker           || bond.OutCoder >= _bindInfo.Coders.Size()
619*f6dc9357SAndroid Build Coastguard Worker           || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)
620*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
621*f6dc9357SAndroid Build Coastguard Worker       mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;
622*f6dc9357SAndroid Build Coastguard Worker       mixerBond.UnpackIndex = bond.InCoder;
623*f6dc9357SAndroid Build Coastguard Worker       _bindInfo.Bonds.Add(mixerBond);
624*f6dc9357SAndroid Build Coastguard Worker     }
625*f6dc9357SAndroid Build Coastguard Worker 
626*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numOutStreams; i++)
627*f6dc9357SAndroid Build Coastguard Worker       if (_bindInfo.FindBond_for_PackStream(i) == -1)
628*f6dc9357SAndroid Build Coastguard Worker         _bindInfo.PackStreams.Add(i);
629*f6dc9357SAndroid Build Coastguard Worker   }
630*f6dc9357SAndroid Build Coastguard Worker 
631*f6dc9357SAndroid Build Coastguard Worker   if (!_bindInfo.SetUnpackCoder())
632*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
633*f6dc9357SAndroid Build Coastguard Worker 
634*f6dc9357SAndroid Build Coastguard Worker   if (!_bindInfo.CalcMapsAndCheck())
635*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
636*f6dc9357SAndroid Build Coastguard Worker 
637*f6dc9357SAndroid Build Coastguard Worker   if (_bindInfo.PackStreams.Size() != 1)
638*f6dc9357SAndroid Build Coastguard Worker   {
639*f6dc9357SAndroid Build Coastguard Worker     /* main_PackStream is pack stream of main path of coders tree.
640*f6dc9357SAndroid Build Coastguard Worker        We find main_PackStream, and place to start of list of out streams.
641*f6dc9357SAndroid Build Coastguard Worker        It allows to use more optimal memory usage for temp buffers,
642*f6dc9357SAndroid Build Coastguard Worker        if main_PackStream is largest stream. */
643*f6dc9357SAndroid Build Coastguard Worker 
644*f6dc9357SAndroid Build Coastguard Worker     UInt32 ci = _bindInfo.UnpackCoder;
645*f6dc9357SAndroid Build Coastguard Worker 
646*f6dc9357SAndroid Build Coastguard Worker     for (;;)
647*f6dc9357SAndroid Build Coastguard Worker     {
648*f6dc9357SAndroid Build Coastguard Worker       if (_bindInfo.Coders[ci].NumStreams == 0)
649*f6dc9357SAndroid Build Coastguard Worker         break;
650*f6dc9357SAndroid Build Coastguard Worker 
651*f6dc9357SAndroid Build Coastguard Worker       const UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
652*f6dc9357SAndroid Build Coastguard Worker       const int bond = _bindInfo.FindBond_for_PackStream(outIndex);
653*f6dc9357SAndroid Build Coastguard Worker       if (bond >= 0)
654*f6dc9357SAndroid Build Coastguard Worker       {
655*f6dc9357SAndroid Build Coastguard Worker         ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex;
656*f6dc9357SAndroid Build Coastguard Worker         continue;
657*f6dc9357SAndroid Build Coastguard Worker       }
658*f6dc9357SAndroid Build Coastguard Worker 
659*f6dc9357SAndroid Build Coastguard Worker       const int si = _bindInfo.FindStream_in_PackStreams(outIndex);
660*f6dc9357SAndroid Build Coastguard Worker       if (si >= 0)
661*f6dc9357SAndroid Build Coastguard Worker         _bindInfo.PackStreams.MoveToFront((unsigned)si);
662*f6dc9357SAndroid Build Coastguard Worker       break;
663*f6dc9357SAndroid Build Coastguard Worker     }
664*f6dc9357SAndroid Build Coastguard Worker   }
665*f6dc9357SAndroid Build Coastguard Worker 
666*f6dc9357SAndroid Build Coastguard Worker   if (_options.PasswordIsDefined)
667*f6dc9357SAndroid Build Coastguard Worker   {
668*f6dc9357SAndroid Build Coastguard Worker     unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
669*f6dc9357SAndroid Build Coastguard Worker 
670*f6dc9357SAndroid Build Coastguard Worker     unsigned numInStreams = _bindInfo.Coders.Size();
671*f6dc9357SAndroid Build Coastguard Worker 
672*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numCryptoStreams; i++)
673*f6dc9357SAndroid Build Coastguard Worker     {
674*f6dc9357SAndroid Build Coastguard Worker       NCoderMixer2::CBond bond;
675*f6dc9357SAndroid Build Coastguard Worker       bond.UnpackIndex = numInStreams + i;
676*f6dc9357SAndroid Build Coastguard Worker       bond.PackIndex = _bindInfo.PackStreams[i];
677*f6dc9357SAndroid Build Coastguard Worker       _bindInfo.Bonds.Add(bond);
678*f6dc9357SAndroid Build Coastguard Worker     }
679*f6dc9357SAndroid Build Coastguard Worker     _bindInfo.PackStreams.Clear();
680*f6dc9357SAndroid Build Coastguard Worker 
681*f6dc9357SAndroid Build Coastguard Worker     /*
682*f6dc9357SAndroid Build Coastguard Worker     if (numCryptoStreams == 0)
683*f6dc9357SAndroid Build Coastguard Worker       numCryptoStreams = 1;
684*f6dc9357SAndroid Build Coastguard Worker     */
685*f6dc9357SAndroid Build Coastguard Worker 
686*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numCryptoStreams; i++)
687*f6dc9357SAndroid Build Coastguard Worker     {
688*f6dc9357SAndroid Build Coastguard Worker       CMethodFull method;
689*f6dc9357SAndroid Build Coastguard Worker       method.NumStreams = 1;
690*f6dc9357SAndroid Build Coastguard Worker       method.Id = k_AES;
691*f6dc9357SAndroid Build Coastguard Worker       _options.Methods.Add(method);
692*f6dc9357SAndroid Build Coastguard Worker 
693*f6dc9357SAndroid Build Coastguard Worker       NCoderMixer2::CCoderStreamsInfo cod;
694*f6dc9357SAndroid Build Coastguard Worker       cod.NumStreams = 1;
695*f6dc9357SAndroid Build Coastguard Worker       _bindInfo.Coders.Add(cod);
696*f6dc9357SAndroid Build Coastguard Worker 
697*f6dc9357SAndroid Build Coastguard Worker       _bindInfo.PackStreams.Add(numOutStreams++);
698*f6dc9357SAndroid Build Coastguard Worker     }
699*f6dc9357SAndroid Build Coastguard Worker   }
700*f6dc9357SAndroid Build Coastguard Worker 
701*f6dc9357SAndroid Build Coastguard Worker   }
702*f6dc9357SAndroid Build Coastguard Worker 
703*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = _options.Methods.Size(); i != 0;)
704*f6dc9357SAndroid Build Coastguard Worker     _decompressionMethods.Add(_options.Methods[--i].Id);
705*f6dc9357SAndroid Build Coastguard Worker 
706*f6dc9357SAndroid Build Coastguard Worker   if (_bindInfo.Coders.Size() > 16)
707*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
708*f6dc9357SAndroid Build Coastguard Worker   if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)
709*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
710*f6dc9357SAndroid Build Coastguard Worker 
711*f6dc9357SAndroid Build Coastguard Worker   if (!_bindInfo.CalcMapsAndCheck())
712*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
713*f6dc9357SAndroid Build Coastguard Worker 
714*f6dc9357SAndroid Build Coastguard Worker   InitBindConv();
715*f6dc9357SAndroid Build Coastguard Worker   _constructed = true;
716*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
717*f6dc9357SAndroid Build Coastguard Worker }
718*f6dc9357SAndroid Build Coastguard Worker 
719*f6dc9357SAndroid Build Coastguard Worker CEncoder::~CEncoder() {}
720*f6dc9357SAndroid Build Coastguard Worker 
721*f6dc9357SAndroid Build Coastguard Worker }}
722