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