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