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