1// CoderMixer2MT.cpp
2
3#include "StdAfx.h"
4
5#include "CoderMixer2MT.h"
6
7namespace NCoderMixer {
8
9CCoder2::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
18void CCoder2::Execute() { Code(NULL); }
19
20void 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
52static 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
73void 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
82HRESULT 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
94void CCoderMixer2MT::AddCoderCommon()
95{
96  const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
97  CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
98  _coders.Add(threadCoderInfo);
99}
100
101void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
102{
103  AddCoderCommon();
104  _coders.Back().Coder = coder;
105}
106
107void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
108{
109  AddCoderCommon();
110  _coders.Back().Coder2 = coder;
111}
112
113
114void CCoderMixer2MT::ReInit()
115{
116  for (int i = 0; i < _streamBinders.Size(); i++)
117    _streamBinders[i].ReInit();
118}
119
120
121HRESULT 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
180HRESULT 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
188STDMETHODIMP 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