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.ClearAndReserve(NumInStreams);
13  OutStreams.ClearAndReserve(NumOutStreams);
14}
15
16void CCoder2::Execute() { Code(NULL); }
17
18void 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/*
51void 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
61HRESULT 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
72void CCoderMixer2MT::AddCoderCommon()
73{
74  const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
75  CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
76  _coders.Add(threadCoderInfo);
77}
78
79void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
80{
81  AddCoderCommon();
82  _coders.Back().Coder = coder;
83}
84
85void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
86{
87  AddCoderCommon();
88  _coders.Back().Coder2 = coder;
89}
90
91
92void CCoderMixer2MT::ReInit()
93{
94  FOR_VECTOR (i, _streamBinders)
95    _streamBinders[i].ReInit();
96}
97
98
99HRESULT 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
158HRESULT 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
166STDMETHODIMP 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