1// CoderMixer2.cpp
2
3#include "StdAfx.h"
4
5#include "CoderMixer2.h"
6
7#ifdef USE_MIXER_ST
8
9Z7_COM7F_IMF(CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize))
10{
11  UInt32 realProcessed = 0;
12  HRESULT result = S_OK;
13  if (_stream)
14    result = _stream->Read(data, size, &realProcessed);
15  _size += realProcessed;
16  if (size != 0 && realProcessed == 0)
17    _wasFinished = true;
18  if (processedSize)
19    *processedSize = realProcessed;
20  return result;
21}
22
23
24Z7_COM7F_IMF(COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize))
25{
26  HRESULT result = S_OK;
27  if (_stream)
28    result = _stream->Write(data, size, &size);
29  _size += size;
30  if (processedSize)
31    *processedSize = size;
32  return result;
33}
34
35Z7_COM7F_IMF(COutStreamCalcSize::OutStreamFinish())
36{
37  HRESULT result = S_OK;
38  if (_stream)
39  {
40    CMyComPtr<IOutStreamFinish> outStreamFinish;
41    _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish);
42    if (outStreamFinish)
43      result = outStreamFinish->OutStreamFinish();
44  }
45  return result;
46}
47
48#endif
49
50
51
52
53namespace NCoderMixer2 {
54
55static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
56{
57  v.ClearAndSetSize(size);
58  bool *p = &v[0];
59  for (unsigned i = 0; i < size; i++)
60    p[i] = false;
61}
62
63
64HRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const
65{
66  if (Coder)
67  {
68    if (PackSizePointers.IsEmpty() || !PackSizePointers[0])
69      return S_OK;
70    CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
71    Coder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);
72    // if (!getInStreamProcessedSize) return E_FAIL;
73    if (getInStreamProcessedSize)
74    {
75      UInt64 processed;
76      RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed))
77      if (processed != (UInt64)(Int64)-1)
78      {
79        const UInt64 size = PackSizes[0];
80        if (processed < size && Finish)
81          dataAfterEnd_Error = true;
82        if (processed > size)
83        {
84          // InternalPackSizeError = true;
85          // return S_FALSE;
86        }
87      }
88    }
89  }
90  else if (Coder2)
91  {
92    CMyComPtr<ICompressGetInStreamProcessedSize2> getInStreamProcessedSize2;
93    Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2);
94    if (getInStreamProcessedSize2)
95    FOR_VECTOR (i, PackSizePointers)
96    {
97      if (!PackSizePointers[i])
98        continue;
99      UInt64 processed;
100      RINOK(getInStreamProcessedSize2->GetInStreamProcessedSize2(i, &processed))
101      if (processed != (UInt64)(Int64)-1)
102      {
103        const UInt64 size = PackSizes[i];
104        if (processed < size && Finish)
105          dataAfterEnd_Error = true;
106        else if (processed > size)
107        {
108          // InternalPackSizeError = true;
109          // return S_FALSE;
110        }
111      }
112    }
113  }
114
115  return S_OK;
116}
117
118
119
120class CBondsChecks
121{
122  CBoolVector _coderUsed;
123
124  bool Init();
125  bool CheckCoder(unsigned coderIndex);
126public:
127  const CBindInfo *BindInfo;
128
129  bool Check();
130};
131
132bool CBondsChecks::CheckCoder(unsigned coderIndex)
133{
134  const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex];
135
136  if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex])
137    return false;
138  _coderUsed[coderIndex] = true;
139
140  const UInt32 start = BindInfo->Coder_to_Stream[coderIndex];
141
142  for (unsigned i = 0; i < coder.NumStreams; i++)
143  {
144    UInt32 ind = start + i;
145
146    if (BindInfo->IsStream_in_PackStreams(ind))
147      continue;
148
149    const int bond = BindInfo->FindBond_for_PackStream(ind);
150    if (bond < 0)
151      return false;
152    if (!CheckCoder(BindInfo->Bonds[(unsigned)bond].UnpackIndex))
153      return false;
154  }
155
156  return true;
157}
158
159bool CBondsChecks::Check()
160{
161  BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size());
162
163  if (!CheckCoder(BindInfo->UnpackCoder))
164    return false;
165
166  FOR_VECTOR(i, _coderUsed)
167    if (!_coderUsed[i])
168      return false;
169
170  return true;
171}
172
173void CBindInfo::ClearMaps()
174{
175  Coder_to_Stream.Clear();
176  Stream_to_Coder.Clear();
177}
178
179bool CBindInfo::CalcMapsAndCheck()
180{
181  ClearMaps();
182
183  UInt32 numStreams = 0;
184
185  if (Coders.Size() == 0)
186    return false;
187  if (Coders.Size() - 1 != Bonds.Size())
188    return false;
189
190  FOR_VECTOR(i, Coders)
191  {
192    Coder_to_Stream.Add(numStreams);
193
194    const CCoderStreamsInfo &c = Coders[i];
195
196    for (unsigned j = 0; j < c.NumStreams; j++)
197      Stream_to_Coder.Add(i);
198
199    numStreams += c.NumStreams;
200  }
201
202  if (numStreams != GetNum_Bonds_and_PackStreams())
203    return false;
204
205  CBondsChecks bc;
206  bc.BindInfo = this;
207  return bc.Check();
208}
209
210
211void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
212{
213  Finish = finish;
214
215  if (unpackSize)
216  {
217    UnpackSize = *unpackSize;
218    UnpackSizePointer = &UnpackSize;
219  }
220  else
221  {
222    UnpackSize = 0;
223    UnpackSizePointer = NULL;
224  }
225
226  PackSizes.ClearAndSetSize((unsigned)NumStreams);
227  PackSizePointers.ClearAndSetSize((unsigned)NumStreams);
228
229  for (unsigned i = 0; i < NumStreams; i++)
230  {
231    if (packSizes && packSizes[i])
232    {
233      PackSizes[i] = *(packSizes[i]);
234      PackSizePointers[i] = &PackSizes[i];
235    }
236    else
237    {
238      PackSizes[i] = 0;
239      PackSizePointers[i] = NULL;
240    }
241  }
242}
243
244bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex)
245{
246  if (coderIndex == _bi.UnpackCoder)
247    return true;
248
249  const int bond = _bi.FindBond_for_UnpackStream(coderIndex);
250  if (bond < 0)
251    throw 20150213;
252
253  /*
254  UInt32 coderIndex, coderStreamIndex;
255  _bi.GetCoder_for_Stream(_bi.Bonds[(unsigned)bond].PackIndex, coderIndex, coderStreamIndex);
256  */
257  const UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[(unsigned)bond].PackIndex];
258
259  if (!IsFilter_Vector[nextCoder])
260    return false;
261
262  return Is_UnpackSize_Correct_for_Coder(nextCoder);
263}
264
265bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex)
266{
267  if (_bi.IsStream_in_PackStreams(streamIndex))
268    return true;
269
270  const int bond = _bi.FindBond_for_PackStream(streamIndex);
271  if (bond < 0)
272    throw 20150213;
273
274  const UInt32 nextCoder = _bi.Bonds[(unsigned)bond].UnpackIndex;
275
276  if (!IsFilter_Vector[nextCoder])
277    return false;
278
279  return Is_PackSize_Correct_for_Coder(nextCoder);
280}
281
282bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex)
283{
284  const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
285  const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
286  for (UInt32 i = 0; i < numStreams; i++)
287    if (!Is_PackSize_Correct_for_Stream(startIndex + i))
288      return false;
289  return true;
290}
291
292bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex)
293{
294  if (IsExternal_Vector[coderIndex])
295    return true;
296  const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
297  const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
298  for (UInt32 i = 0; i < numStreams; i++)
299  {
300    const UInt32 si = startIndex + i;
301    if (_bi.IsStream_in_PackStreams(si))
302      continue;
303
304    const int bond = _bi.FindBond_for_PackStream(si);
305    if (bond < 0)
306      throw 20150213;
307
308    if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[(unsigned)bond].UnpackIndex))
309      return true;
310  }
311  return false;
312}
313
314
315
316
317#ifdef USE_MIXER_ST
318
319CMixerST::CMixerST(bool encodeMode):
320    CMixer(encodeMode)
321    {}
322
323CMixerST::~CMixerST() {}
324
325void CMixerST::AddCoder(const CCreatedCoder &cod)
326{
327  IsFilter_Vector.Add(cod.IsFilter);
328  IsExternal_Vector.Add(cod.IsExternal);
329  // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
330  CCoderST &c2 = _coders.AddNew();
331  c2.NumStreams = cod.NumStreams;
332  c2.Coder = cod.Coder;
333  c2.Coder2 = cod.Coder2;
334
335  /*
336  if (isFilter)
337  {
338    c2.CanRead = true;
339    c2.CanWrite = true;
340  }
341  else
342  */
343  {
344    IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2);
345    {
346      Z7_DECL_CMyComPtr_QI_FROM(ISequentialInStream, s, unk)
347      c2.CanRead = (s != NULL);
348    }
349    {
350      Z7_DECL_CMyComPtr_QI_FROM(ISequentialOutStream, s, unk)
351      c2.CanWrite = (s != NULL);
352    }
353  }
354}
355
356CCoder &CMixerST::GetCoder(unsigned index)
357{
358  return _coders[index];
359}
360
361HRESULT CMixerST::ReInit2() { return S_OK; }
362
363HRESULT CMixerST::GetInStream2(
364    ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
365    UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
366{
367  UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
368
369  if (EncodeMode)
370  {
371    _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
372    if (coderStreamIndex != 0)
373      return E_NOTIMPL;
374  }
375
376  const CCoder &coder = _coders[coderIndex];
377
378  CMyComPtr<ISequentialInStream> seqInStream;
379  coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
380  if (!seqInStream)
381    return E_NOTIMPL;
382
383  const UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
384  const UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
385
386  bool isSet = false;
387
388  if (numInStreams == 1)
389  {
390    CMyComPtr<ICompressSetInStream> setStream;
391    coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
392    if (setStream)
393    {
394      CMyComPtr<ISequentialInStream> seqInStream2;
395      RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2))
396      RINOK(setStream->SetInStream(seqInStream2))
397      isSet = true;
398    }
399  }
400
401  if (!isSet && numInStreams != 0)
402  {
403    CMyComPtr<ICompressSetInStream2> setStream2;
404    coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
405    if (!setStream2)
406      return E_NOTIMPL;
407
408    for (UInt32 i = 0; i < numInStreams; i++)
409    {
410      CMyComPtr<ISequentialInStream> seqInStream2;
411      RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2))
412      RINOK(setStream2->SetInStream2(i, seqInStream2))
413    }
414  }
415
416  *inStreamRes = seqInStream.Detach();
417  return S_OK;
418}
419
420
421HRESULT CMixerST::GetInStream(
422    ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
423    UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
424{
425  CMyComPtr<ISequentialInStream> seqInStream;
426
427  {
428    int index = -1;
429    if (EncodeMode)
430    {
431      if (_bi.UnpackCoder == inStreamIndex)
432        index = 0;
433    }
434    else
435      index = _bi.FindStream_in_PackStreams(inStreamIndex);
436
437    if (index >= 0)
438    {
439      seqInStream = inStreams[(unsigned)index];
440      *inStreamRes = seqInStream.Detach();
441      return S_OK;
442    }
443  }
444
445  const int bond = FindBond_for_Stream(
446      true, // forInputStream
447      inStreamIndex);
448  if (bond < 0)
449    return E_INVALIDARG;
450
451  RINOK(GetInStream2(inStreams, /* inSizes, */
452      _bi.Bonds[(unsigned)bond].Get_OutIndex(EncodeMode), &seqInStream))
453
454  while (_binderStreams.Size() <= (unsigned)bond)
455    _binderStreams.AddNew();
456  CStBinderStream &bs = _binderStreams[(unsigned)bond];
457
458  if (bs.StreamRef || bs.InStreamSpec)
459    return E_NOTIMPL;
460
461  CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
462  bs.StreamRef = spec;
463  bs.InStreamSpec = spec;
464
465  spec->SetStream(seqInStream);
466  spec->Init();
467
468  seqInStream = bs.InStreamSpec;
469
470  *inStreamRes = seqInStream.Detach();
471  return S_OK;
472}
473
474
475HRESULT CMixerST::GetOutStream(
476    ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
477    UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
478{
479  CMyComPtr<ISequentialOutStream> seqOutStream;
480
481  {
482    int index = -1;
483    if (!EncodeMode)
484    {
485      if (_bi.UnpackCoder == outStreamIndex)
486        index = 0;
487    }
488    else
489      index = _bi.FindStream_in_PackStreams(outStreamIndex);
490
491    if (index >= 0)
492    {
493      seqOutStream = outStreams[(unsigned)index];
494      *outStreamRes = seqOutStream.Detach();
495      return S_OK;
496    }
497  }
498
499  const int bond = FindBond_for_Stream(
500      false, // forInputStream
501      outStreamIndex);
502  if (bond < 0)
503    return E_INVALIDARG;
504
505  const UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode);
506
507  UInt32 coderIndex = inStreamIndex;
508  UInt32 coderStreamIndex = 0;
509
510  if (!EncodeMode)
511    _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
512
513  CCoder &coder = _coders[coderIndex];
514
515  /*
516  if (!coder.Coder)
517    return E_NOTIMPL;
518  */
519
520  coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
521  if (!seqOutStream)
522    return E_NOTIMPL;
523
524  const UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
525  const UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
526
527  bool isSet = false;
528
529  if (numOutStreams == 1)
530  {
531    CMyComPtr<ICompressSetOutStream> setOutStream;
532    coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
533    if (setOutStream)
534    {
535      CMyComPtr<ISequentialOutStream> seqOutStream2;
536      RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2))
537      RINOK(setOutStream->SetOutStream(seqOutStream2))
538      isSet = true;
539    }
540  }
541
542  if (!isSet && numOutStreams != 0)
543  {
544    return E_NOTIMPL;
545    /*
546    CMyComPtr<ICompressSetOutStream2> setStream2;
547    coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
548    if (!setStream2)
549      return E_NOTIMPL;
550    for (UInt32 i = 0; i < numOutStreams; i++)
551    {
552      CMyComPtr<ISequentialOutStream> seqOutStream2;
553      RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2))
554      RINOK(setStream2->SetOutStream2(i, seqOutStream2))
555    }
556    */
557  }
558
559  while (_binderStreams.Size() <= (unsigned)bond)
560    _binderStreams.AddNew();
561  CStBinderStream &bs = _binderStreams[(unsigned)bond];
562
563  if (bs.StreamRef || bs.OutStreamSpec)
564    return E_NOTIMPL;
565
566  COutStreamCalcSize *spec = new COutStreamCalcSize;
567  bs.StreamRef = (ISequentialOutStream *)spec;
568  bs.OutStreamSpec = spec;
569
570  spec->SetStream(seqOutStream);
571  spec->Init();
572
573  seqOutStream = bs.OutStreamSpec;
574
575  *outStreamRes = seqOutStream.Detach();
576  return S_OK;
577}
578
579
580static HRESULT GetError(HRESULT res, HRESULT res2)
581{
582  if (res == res2)
583    return res;
584  if (res == S_OK)
585    return res2;
586  if (res == k_My_HRESULT_WritingWasCut)
587  {
588    if (res2 != S_OK)
589      return res2;
590  }
591  return res;
592}
593
594
595HRESULT CMixerST::FinishStream(UInt32 streamIndex)
596{
597  {
598    int index = -1;
599    if (!EncodeMode)
600    {
601      if (_bi.UnpackCoder == streamIndex)
602        index = 0;
603    }
604    else
605      index = _bi.FindStream_in_PackStreams(streamIndex);
606
607    if (index >= 0)
608      return S_OK;
609  }
610
611  const int bond = FindBond_for_Stream(
612      false, // forInputStream
613      streamIndex);
614  if (bond < 0)
615    return E_INVALIDARG;
616
617  const UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode);
618
619  UInt32 coderIndex = inStreamIndex;
620  UInt32 coderStreamIndex = 0;
621  if (!EncodeMode)
622    _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
623
624  CCoder &coder = _coders[coderIndex];
625  CMyComPtr<IOutStreamFinish> finish;
626  coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish);
627  HRESULT res = S_OK;
628  if (finish)
629  {
630    res = finish->OutStreamFinish();
631  }
632  return GetError(res, FinishCoder(coderIndex));
633}
634
635
636HRESULT CMixerST::FinishCoder(UInt32 coderIndex)
637{
638  CCoder &coder = _coders[coderIndex];
639
640  const UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
641  const UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
642
643  HRESULT res = S_OK;
644  for (unsigned i = 0; i < numOutStreams; i++)
645    res = GetError(res, FinishStream(startIndex + i));
646  return res;
647}
648
649
650void CMixerST::SelectMainCoder(bool useFirst)
651{
652  unsigned ci = _bi.UnpackCoder;
653
654  int firstNonFilter = -1;
655  unsigned firstAllowed = ci;
656
657  for (;;)
658  {
659    const CCoderST &coder = _coders[ci];
660    // break;
661
662    if (ci != _bi.UnpackCoder)
663      if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
664      {
665        firstAllowed = ci;
666        firstNonFilter = -2;
667      }
668
669    if (coder.NumStreams != 1)
670      break;
671
672    const UInt32 st = _bi.Coder_to_Stream[ci];
673    if (_bi.IsStream_in_PackStreams(st))
674      break;
675    const int bond = _bi.FindBond_for_PackStream(st);
676    if (bond < 0)
677      throw 20150213;
678
679    if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
680      break;
681
682    if (firstNonFilter == -1 && !IsFilter_Vector[ci])
683      firstNonFilter = (int)ci;
684
685    ci = _bi.Bonds[(unsigned)bond].UnpackIndex;
686  }
687
688  if (useFirst)
689    ci = firstAllowed;
690  else if (firstNonFilter >= 0)
691    ci = (unsigned)firstNonFilter;
692
693  MainCoderIndex = ci;
694}
695
696
697HRESULT CMixerST::Code(
698    ISequentialInStream * const *inStreams,
699    ISequentialOutStream * const *outStreams,
700    ICompressProgressInfo *progress,
701    bool &dataAfterEnd_Error)
702{
703  // InternalPackSizeError = false;
704  dataAfterEnd_Error = false;
705
706  _binderStreams.Clear();
707  const unsigned ci = MainCoderIndex;
708
709  const CCoder &mainCoder = _coders[MainCoderIndex];
710
711  CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
712  CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
713
714  const UInt32 numInStreams  =  EncodeMode ? 1 : mainCoder.NumStreams;
715  const UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
716
717  const UInt32 startInIndex  =  EncodeMode ? ci : _bi.Coder_to_Stream[ci];
718  const UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
719
720  UInt32 i;
721
722  for (i = 0; i < numInStreams; i++)
723  {
724    CMyComPtr<ISequentialInStream> seqInStream;
725    RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream))
726    seqInStreams.Add(seqInStream);
727  }
728
729  for (i = 0; i < numOutStreams; i++)
730  {
731    CMyComPtr<ISequentialOutStream> seqOutStream;
732    RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream))
733    seqOutStreams.Add(seqOutStream);
734  }
735
736  CRecordVector< ISequentialInStream * > seqInStreamsSpec;
737  CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
738
739  for (i = 0; i < numInStreams; i++)
740    seqInStreamsSpec.Add(seqInStreams[i]);
741  for (i = 0; i < numOutStreams; i++)
742    seqOutStreamsSpec.Add(seqOutStreams[i]);
743
744  for (i = 0; i < _coders.Size(); i++)
745  {
746    if (i == ci)
747      continue;
748
749    CCoder &coder = _coders[i];
750
751    if (EncodeMode)
752    {
753      CMyComPtr<ICompressInitEncoder> initEncoder;
754      coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder);
755      if (initEncoder)
756      {
757        RINOK(initEncoder->InitEncoder())
758      }
759    }
760    else
761    {
762      CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
763      coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
764      if (setOutStreamSize)
765      {
766        RINOK(setOutStreamSize->SetOutStreamSize(
767            EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer))
768      }
769    }
770  }
771
772  const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
773  const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
774
775  HRESULT res;
776  if (mainCoder.Coder)
777  {
778    res = mainCoder.Coder->Code(
779        seqInStreamsSpec[0], seqOutStreamsSpec[0],
780        isSizes2[0], outSizes2[0],
781        progress);
782  }
783  else
784  {
785    res = mainCoder.Coder2->Code(
786        &seqInStreamsSpec.Front(), isSizes2, numInStreams,
787        &seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
788        progress);
789  }
790
791  if (res == k_My_HRESULT_WritingWasCut)
792    res = S_OK;
793
794  if (res == S_OK || res == S_FALSE)
795  {
796    res = GetError(res, FinishCoder(ci));
797  }
798
799  for (i = 0; i < _binderStreams.Size(); i++)
800  {
801    const CStBinderStream &bs = _binderStreams[i];
802    if (bs.InStreamSpec)
803      bs.InStreamSpec->ReleaseStream();
804    else
805      bs.OutStreamSpec->ReleaseStream();
806  }
807
808  if (res == k_My_HRESULT_WritingWasCut)
809    res = S_OK;
810
811  if (res != S_OK)
812    return res;
813
814  for (i = 0; i < _coders.Size(); i++)
815  {
816    RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */))
817  }
818
819  return S_OK;
820}
821
822
823HRESULT CMixerST::GetMainUnpackStream(
824    ISequentialInStream * const *inStreams,
825    ISequentialInStream **inStreamRes)
826{
827  CMyComPtr<ISequentialInStream> seqInStream;
828
829  RINOK(GetInStream2(inStreams, /* inSizes, */
830      _bi.UnpackCoder, &seqInStream))
831
832  FOR_VECTOR (i, _coders)
833  {
834    CCoder &coder = _coders[i];
835    CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
836    coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
837    if (setOutStreamSize)
838    {
839      RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer))
840    }
841  }
842
843  *inStreamRes = seqInStream.Detach();
844  return S_OK;
845}
846
847
848UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
849{
850  const CStBinderStream &bs = _binderStreams[bondIndex];
851  if (bs.InStreamSpec)
852    return bs.InStreamSpec->GetSize();
853  return bs.OutStreamSpec->GetSize();
854}
855
856#endif
857
858
859
860
861
862
863#ifdef USE_MIXER_MT
864
865
866void CCoderMT::Execute()
867{
868  try
869  {
870    Code(NULL);
871  }
872  catch(...)
873  {
874    Result = E_FAIL;
875  }
876}
877
878void CCoderMT::Code(ICompressProgressInfo *progress)
879{
880  unsigned numInStreams = EncodeMode ? 1 : NumStreams;
881  unsigned numOutStreams = EncodeMode ? NumStreams : 1;
882
883  InStreamPointers.ClearAndReserve(numInStreams);
884  OutStreamPointers.ClearAndReserve(numOutStreams);
885
886  unsigned i;
887
888  for (i = 0; i < numInStreams; i++)
889    InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
890
891  for (i = 0; i < numOutStreams; i++)
892    OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
893
894  // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
895  /*
896  if (UnpackSizePointer)
897    UnpackSizePointer = &UnpackSize;
898  for (i = 0; i < NumStreams; i++)
899    if (PackSizePointers[i])
900      PackSizePointers[i] = &PackSizes[i];
901  */
902
903  CReleaser releaser(*this);
904
905  if (Coder)
906    Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
907        EncodeMode ? UnpackSizePointer : PackSizePointers[0],
908        EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
909        progress);
910  else
911    Result = Coder2->Code(
912        &InStreamPointers.Front(),  EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
913        &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
914        progress);
915}
916
917HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
918{
919  CMixer::SetBindInfo(bindInfo);
920
921  _streamBinders.Clear();
922  FOR_VECTOR (i, _bi.Bonds)
923  {
924    // RINOK(_streamBinders.AddNew().CreateEvents())
925    _streamBinders.AddNew();
926  }
927  return S_OK;
928}
929
930void CMixerMT::AddCoder(const CCreatedCoder &cod)
931{
932  IsFilter_Vector.Add(cod.IsFilter);
933  IsExternal_Vector.Add(cod.IsExternal);
934  // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
935  CCoderMT &c2 = _coders.AddNew();
936  c2.NumStreams = cod.NumStreams;
937  c2.Coder = cod.Coder;
938  c2.Coder2 = cod.Coder2;
939  c2.EncodeMode = EncodeMode;
940}
941
942CCoder &CMixerMT::GetCoder(unsigned index)
943{
944  return _coders[index];
945}
946
947HRESULT CMixerMT::ReInit2()
948{
949  FOR_VECTOR (i, _streamBinders)
950  {
951    RINOK(_streamBinders[i].Create_ReInit())
952  }
953  return S_OK;
954}
955
956void CMixerMT::SelectMainCoder(bool useFirst)
957{
958  unsigned ci = _bi.UnpackCoder;
959
960  if (!useFirst)
961  for (;;)
962  {
963    if (_coders[ci].NumStreams != 1)
964      break;
965    if (!IsFilter_Vector[ci])
966      break;
967
968    UInt32 st = _bi.Coder_to_Stream[ci];
969    if (_bi.IsStream_in_PackStreams(st))
970      break;
971    const int bond = _bi.FindBond_for_PackStream(st);
972    if (bond < 0)
973      throw 20150213;
974    ci = _bi.Bonds[(unsigned)bond].UnpackIndex;
975  }
976
977  MainCoderIndex = ci;
978}
979
980HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
981{
982  unsigned i;
983
984  for (i = 0; i < _coders.Size(); i++)
985  {
986    CCoderMT &coderInfo = _coders[i];
987    const CCoderStreamsInfo &csi = _bi.Coders[i];
988
989    UInt32 j;
990
991    const unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
992    const unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
993
994    coderInfo.InStreams.Clear();
995    for (j = 0; j < numInStreams; j++)
996      coderInfo.InStreams.AddNew();
997
998    coderInfo.OutStreams.Clear();
999    for (j = 0; j < numOutStreams; j++)
1000      coderInfo.OutStreams.AddNew();
1001  }
1002
1003  for (i = 0; i < _bi.Bonds.Size(); i++)
1004  {
1005    const CBond &bond = _bi.Bonds[i];
1006
1007    UInt32 inCoderIndex, inCoderStreamIndex;
1008    UInt32 outCoderIndex, outCoderStreamIndex;
1009
1010    {
1011      UInt32 coderIndex, coderStreamIndex;
1012      _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
1013
1014      inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
1015      outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
1016
1017      inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
1018      outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
1019    }
1020
1021    _streamBinders[i].CreateStreams2(
1022        _coders[inCoderIndex].InStreams[inCoderStreamIndex],
1023        _coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
1024
1025    CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
1026    _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
1027    _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
1028    if (inSetSize && outSetSize)
1029    {
1030      const UInt32 kBufSize = 1 << 19;
1031      inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
1032      outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
1033    }
1034  }
1035
1036  {
1037    CCoderMT &cod = _coders[_bi.UnpackCoder];
1038    if (EncodeMode)
1039      cod.InStreams[0] = inStreams[0];
1040    else
1041      cod.OutStreams[0] = outStreams[0];
1042  }
1043
1044  for (i = 0; i < _bi.PackStreams.Size(); i++)
1045  {
1046    UInt32 coderIndex, coderStreamIndex;
1047    _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
1048    CCoderMT &cod = _coders[coderIndex];
1049    if (EncodeMode)
1050      cod.OutStreams[coderStreamIndex] = outStreams[i];
1051    else
1052      cod.InStreams[coderStreamIndex] = inStreams[i];
1053  }
1054
1055  return S_OK;
1056}
1057
1058HRESULT CMixerMT::ReturnIfError(HRESULT code)
1059{
1060  FOR_VECTOR (i, _coders)
1061    if (_coders[i].Result == code)
1062      return code;
1063  return S_OK;
1064}
1065
1066HRESULT CMixerMT::Code(
1067    ISequentialInStream * const *inStreams,
1068    ISequentialOutStream * const *outStreams,
1069    ICompressProgressInfo *progress,
1070    bool &dataAfterEnd_Error)
1071{
1072  // InternalPackSizeError = false;
1073  dataAfterEnd_Error = false;
1074
1075  Init(inStreams, outStreams);
1076
1077  unsigned i;
1078  for (i = 0; i < _coders.Size(); i++)
1079    if (i != MainCoderIndex)
1080    {
1081      const WRes wres = _coders[i].Create();
1082      if (wres != 0)
1083        return HRESULT_FROM_WIN32(wres);
1084    }
1085
1086  for (i = 0; i < _coders.Size(); i++)
1087    if (i != MainCoderIndex)
1088    {
1089      const WRes wres = _coders[i].Start();
1090      if (wres != 0)
1091        return HRESULT_FROM_WIN32(wres);
1092    }
1093
1094  _coders[MainCoderIndex].Code(progress);
1095
1096  WRes wres = 0;
1097  for (i = 0; i < _coders.Size(); i++)
1098    if (i != MainCoderIndex)
1099    {
1100      WRes wres2 = _coders[i].WaitExecuteFinish();
1101      if (wres == 0)
1102        wres = wres2;
1103    }
1104  if (wres != 0)
1105    return HRESULT_FROM_WIN32(wres);
1106
1107  RINOK(ReturnIfError(E_ABORT))
1108  RINOK(ReturnIfError(E_OUTOFMEMORY))
1109
1110  for (i = 0; i < _coders.Size(); i++)
1111  {
1112    HRESULT result = _coders[i].Result;
1113    if (result != S_OK
1114        && result != k_My_HRESULT_WritingWasCut
1115        && result != S_FALSE
1116        && result != E_FAIL)
1117      return result;
1118  }
1119
1120  RINOK(ReturnIfError(S_FALSE))
1121
1122  for (i = 0; i < _coders.Size(); i++)
1123  {
1124    HRESULT result = _coders[i].Result;
1125    if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
1126      return result;
1127  }
1128
1129  for (i = 0; i < _coders.Size(); i++)
1130  {
1131    RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */))
1132  }
1133
1134  return S_OK;
1135}
1136
1137UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
1138{
1139  return _streamBinders[bondIndex].ProcessedSize;
1140}
1141
1142#endif
1143
1144}
1145