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