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