Imported Upstream version 9.20
[platform/upstream/7zip.git] / CPP / 7zip / Archive / Common / CoderMixer2MT.cpp
1 // CoderMixer2MT.cpp\r
2 \r
3 #include "StdAfx.h"\r
4 \r
5 #include "CoderMixer2MT.h"\r
6 \r
7 namespace NCoderMixer {\r
8 \r
9 CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):\r
10     CCoderInfo2(numInStreams, numOutStreams)\r
11 {\r
12   InStreams.Reserve(NumInStreams);\r
13   InStreamPointers.Reserve(NumInStreams);\r
14   OutStreams.Reserve(NumOutStreams);\r
15   OutStreamPointers.Reserve(NumOutStreams);\r
16 }\r
17 \r
18 void CCoder2::Execute() { Code(NULL); }\r
19 \r
20 void CCoder2::Code(ICompressProgressInfo *progress)\r
21 {\r
22   InStreamPointers.Clear();\r
23   OutStreamPointers.Clear();\r
24   UInt32 i;\r
25   for (i = 0; i < NumInStreams; i++)\r
26   {\r
27     if (InSizePointers[i] != NULL)\r
28       InSizePointers[i] = &InSizes[i];\r
29     InStreamPointers.Add((ISequentialInStream *)InStreams[i]);\r
30   }\r
31   for (i = 0; i < NumOutStreams; i++)\r
32   {\r
33     if (OutSizePointers[i] != NULL)\r
34       OutSizePointers[i] = &OutSizes[i];\r
35     OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]);\r
36   }\r
37   if (Coder)\r
38     Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],\r
39         InSizePointers[0], OutSizePointers[0], progress);\r
40   else\r
41     Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,\r
42       &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);\r
43   {\r
44     int i;\r
45     for (i = 0; i < InStreams.Size(); i++)\r
46       InStreams[i].Release();\r
47     for (i = 0; i < OutStreams.Size(); i++)\r
48       OutStreams[i].Release();\r
49   }\r
50 }\r
51 \r
52 static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,\r
53     CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)\r
54 {\r
55   sizes.Clear();\r
56   sizePointers.Clear();\r
57   for (UInt32 i = 0; i < numItems; i++)\r
58   {\r
59     if (srcSizes == 0 || srcSizes[i] == NULL)\r
60     {\r
61       sizes.Add(0);\r
62       sizePointers.Add(NULL);\r
63     }\r
64     else\r
65     {\r
66       sizes.Add(*srcSizes[i]);\r
67       sizePointers.Add(&sizes.Back());\r
68     }\r
69   }\r
70 }\r
71 \r
72 \r
73 void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)\r
74 {\r
75   SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);\r
76   SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);\r
77 }\r
78 \r
79 //////////////////////////////////////\r
80 // CCoderMixer2MT\r
81 \r
82 HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)\r
83 {\r
84   _bindInfo = bindInfo;\r
85   _streamBinders.Clear();\r
86   for (int i = 0; i < _bindInfo.BindPairs.Size(); i++)\r
87   {\r
88     _streamBinders.Add(CStreamBinder());\r
89     RINOK(_streamBinders.Back().CreateEvents());\r
90   }\r
91   return S_OK;\r
92 }\r
93 \r
94 void CCoderMixer2MT::AddCoderCommon()\r
95 {\r
96   const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];\r
97   CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);\r
98   _coders.Add(threadCoderInfo);\r
99 }\r
100 \r
101 void CCoderMixer2MT::AddCoder(ICompressCoder *coder)\r
102 {\r
103   AddCoderCommon();\r
104   _coders.Back().Coder = coder;\r
105 }\r
106 \r
107 void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)\r
108 {\r
109   AddCoderCommon();\r
110   _coders.Back().Coder2 = coder;\r
111 }\r
112 \r
113 \r
114 void CCoderMixer2MT::ReInit()\r
115 {\r
116   for (int i = 0; i < _streamBinders.Size(); i++)\r
117     _streamBinders[i].ReInit();\r
118 }\r
119 \r
120 \r
121 HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams)\r
122 {\r
123   /*\r
124   if (_coders.Size() != _bindInfo.Coders.Size())\r
125     throw 0;\r
126   */\r
127   int i;\r
128   for (i = 0; i < _coders.Size(); i++)\r
129   {\r
130     CCoder2 &coderInfo = _coders[i];\r
131     const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];\r
132     coderInfo.InStreams.Clear();\r
133     UInt32 j;\r
134     for (j = 0; j < coderStreamsInfo.NumInStreams; j++)\r
135       coderInfo.InStreams.Add(NULL);\r
136     coderInfo.OutStreams.Clear();\r
137     for (j = 0; j < coderStreamsInfo.NumOutStreams; j++)\r
138       coderInfo.OutStreams.Add(NULL);\r
139   }\r
140 \r
141   for (i = 0; i < _bindInfo.BindPairs.Size(); i++)\r
142   {\r
143     const CBindPair &bindPair = _bindInfo.BindPairs[i];\r
144     UInt32 inCoderIndex, inCoderStreamIndex;\r
145     UInt32 outCoderIndex, outCoderStreamIndex;\r
146     _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);\r
147     _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);\r
148 \r
149     _streamBinders[i].CreateStreams(\r
150         &_coders[inCoderIndex].InStreams[inCoderStreamIndex],\r
151         &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);\r
152 \r
153     CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;\r
154     _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);\r
155     _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);\r
156     if (inSetSize && outSetSize)\r
157     {\r
158       const UInt32 kBufSize = 1 << 19;\r
159       inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);\r
160       outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);\r
161     }\r
162   }\r
163 \r
164   for (i = 0; i < _bindInfo.InStreams.Size(); i++)\r
165   {\r
166     UInt32 inCoderIndex, inCoderStreamIndex;\r
167     _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);\r
168     _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];\r
169   }\r
170   \r
171   for (i = 0; i < _bindInfo.OutStreams.Size(); i++)\r
172   {\r
173     UInt32 outCoderIndex, outCoderStreamIndex;\r
174     _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);\r
175     _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];\r
176   }\r
177   return S_OK;\r
178 }\r
179 \r
180 HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)\r
181 {\r
182   for (int i = 0; i < _coders.Size(); i++)\r
183     if (_coders[i].Result == code)\r
184       return code;\r
185   return S_OK;\r
186 }\r
187 \r
188 STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,\r
189       const UInt64 ** /* inSizes */,\r
190       UInt32 numInStreams,\r
191       ISequentialOutStream **outStreams,\r
192       const UInt64 ** /* outSizes */,\r
193       UInt32 numOutStreams,\r
194       ICompressProgressInfo *progress)\r
195 {\r
196   if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||\r
197       numOutStreams != (UInt32)_bindInfo.OutStreams.Size())\r
198     return E_INVALIDARG;\r
199 \r
200   Init(inStreams, outStreams);\r
201 \r
202   int i;\r
203   for (i = 0; i < _coders.Size(); i++)\r
204     if (i != _progressCoderIndex)\r
205     {\r
206       RINOK(_coders[i].Create());\r
207     }\r
208 \r
209   for (i = 0; i < _coders.Size(); i++)\r
210     if (i != _progressCoderIndex)\r
211       _coders[i].Start();\r
212 \r
213   _coders[_progressCoderIndex].Code(progress);\r
214 \r
215   for (i = 0; i < _coders.Size(); i++)\r
216     if (i != _progressCoderIndex)\r
217       _coders[i].WaitFinish();\r
218 \r
219   RINOK(ReturnIfError(E_ABORT));\r
220   RINOK(ReturnIfError(E_OUTOFMEMORY));\r
221 \r
222   for (i = 0; i < _coders.Size(); i++)\r
223   {\r
224     HRESULT result = _coders[i].Result;\r
225     if (result != S_OK && result != E_FAIL && result != S_FALSE)\r
226       return result;\r
227   }\r
228 \r
229   RINOK(ReturnIfError(S_FALSE));\r
230 \r
231   for (i = 0; i < _coders.Size(); i++)\r
232   {\r
233     HRESULT result = _coders[i].Result;\r
234     if (result != S_OK)\r
235       return result;\r
236   }\r
237   return S_OK;\r
238 }\r
239 \r
240 }\r