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 
     64 HRESULT 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 
    120 class CBondsChecks
    121 {
    122   CBoolVector _coderUsed;
    123 
    124   bool Init();
    125   bool CheckCoder(unsigned coderIndex);
    126 public:
    127   const CBindInfo *BindInfo;
    128 
    129   bool Check();
    130 };
    131 
    132 bool 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   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     int bond = BindInfo->FindBond_for_PackStream(ind);
    150     if (bond < 0)
    151       return false;
    152     if (!CheckCoder(BindInfo->Bonds[bond].UnpackIndex))
    153       return false;
    154   }
    155 
    156   return true;
    157 }
    158 
    159 bool 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 
    173 void CBindInfo::ClearMaps()
    174 {
    175   Coder_to_Stream.Clear();
    176   Stream_to_Coder.Clear();
    177 }
    178 
    179 bool 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 
    211 void 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 
    244 bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex)
    245 {
    246   if (coderIndex == _bi.UnpackCoder)
    247     return true;
    248 
    249   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[bond].PackIndex, coderIndex, coderStreamIndex);
    256   */
    257   UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[bond].PackIndex];
    258 
    259   if (!IsFilter_Vector[nextCoder])
    260     return false;
    261 
    262   return Is_UnpackSize_Correct_for_Coder(nextCoder);
    263 }
    264 
    265 bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex)
    266 {
    267   if (_bi.IsStream_in_PackStreams(streamIndex))
    268     return true;
    269 
    270   int bond = _bi.FindBond_for_PackStream(streamIndex);
    271   if (bond < 0)
    272     throw 20150213;
    273 
    274   UInt32 nextCoder = _bi.Bonds[bond].UnpackIndex;
    275 
    276   if (!IsFilter_Vector[nextCoder])
    277     return false;
    278 
    279   return Is_PackSize_Correct_for_Coder(nextCoder);
    280 }
    281 
    282 bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex)
    283 {
    284   UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
    285   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 
    292 bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex)
    293 {
    294   if (IsExternal_Vector[coderIndex])
    295     return true;
    296   UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
    297   UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
    298   for (UInt32 i = 0; i < numStreams; i++)
    299   {
    300     UInt32 si = startIndex + i;
    301     if (_bi.IsStream_in_PackStreams(si))
    302       continue;
    303 
    304     int bond = _bi.FindBond_for_PackStream(si);
    305     if (bond < 0)
    306       throw 20150213;
    307 
    308     if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[bond].UnpackIndex))
    309       return true;
    310   }
    311   return false;
    312 }
    313 
    314 
    315 
    316 
    317 #ifdef USE_MIXER_ST
    318 
    319 CMixerST::CMixerST(bool encodeMode):
    320     CMixer(encodeMode)
    321     {}
    322 
    323 CMixerST::~CMixerST() {}
    324 
    325 void 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       CMyComPtr<ISequentialInStream> s;
    347       unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
    348       c2.CanRead = (s != NULL);
    349     }
    350     {
    351       CMyComPtr<ISequentialOutStream> s;
    352       unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
    353       c2.CanWrite = (s != NULL);
    354     }
    355   }
    356 }
    357 
    358 CCoder &CMixerST::GetCoder(unsigned index)
    359 {
    360   return _coders[index];
    361 }
    362 
    363 void CMixerST::ReInit() {}
    364 
    365 HRESULT CMixerST::GetInStream2(
    366     ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
    367     UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
    368 {
    369   UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
    370 
    371   if (EncodeMode)
    372   {
    373     _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
    374     if (coderStreamIndex != 0)
    375       return E_NOTIMPL;
    376   }
    377 
    378   const CCoder &coder = _coders[coderIndex];
    379 
    380   CMyComPtr<ISequentialInStream> seqInStream;
    381   coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
    382   if (!seqInStream)
    383     return E_NOTIMPL;
    384 
    385   UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
    386   UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
    387 
    388   bool isSet = false;
    389 
    390   if (numInStreams == 1)
    391   {
    392     CMyComPtr<ICompressSetInStream> setStream;
    393     coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
    394     if (setStream)
    395     {
    396       CMyComPtr<ISequentialInStream> seqInStream2;
    397       RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
    398       RINOK(setStream->SetInStream(seqInStream2));
    399       isSet = true;
    400     }
    401   }
    402 
    403   if (!isSet && numInStreams != 0)
    404   {
    405     CMyComPtr<ICompressSetInStream2> setStream2;
    406     coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
    407     if (!setStream2)
    408       return E_NOTIMPL;
    409 
    410     for (UInt32 i = 0; i < numInStreams; i++)
    411     {
    412       CMyComPtr<ISequentialInStream> seqInStream2;
    413       RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
    414       RINOK(setStream2->SetInStream2(i, seqInStream2));
    415     }
    416   }
    417 
    418   *inStreamRes = seqInStream.Detach();
    419   return S_OK;
    420 }
    421 
    422 
    423 HRESULT CMixerST::GetInStream(
    424     ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
    425     UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
    426 {
    427   CMyComPtr<ISequentialInStream> seqInStream;
    428 
    429   {
    430     int index = -1;
    431     if (EncodeMode)
    432     {
    433       if (_bi.UnpackCoder == inStreamIndex)
    434         index = 0;
    435     }
    436     else
    437       index = _bi.FindStream_in_PackStreams(inStreamIndex);
    438 
    439     if (index >= 0)
    440     {
    441       seqInStream = inStreams[(unsigned)index];
    442       *inStreamRes = seqInStream.Detach();
    443       return S_OK;
    444     }
    445   }
    446 
    447   int bond = FindBond_for_Stream(
    448       true, // forInputStream
    449       inStreamIndex);
    450   if (bond < 0)
    451     return E_INVALIDARG;
    452 
    453   RINOK(GetInStream2(inStreams, /* inSizes, */
    454       _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
    455 
    456   while (_binderStreams.Size() <= (unsigned)bond)
    457     _binderStreams.AddNew();
    458   CStBinderStream &bs = _binderStreams[bond];
    459 
    460   if (bs.StreamRef || bs.InStreamSpec)
    461     return E_NOTIMPL;
    462 
    463   CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
    464   bs.StreamRef = spec;
    465   bs.InStreamSpec = spec;
    466 
    467   spec->SetStream(seqInStream);
    468   spec->Init();
    469 
    470   seqInStream = bs.InStreamSpec;
    471 
    472   *inStreamRes = seqInStream.Detach();
    473   return S_OK;
    474 }
    475 
    476 
    477 HRESULT CMixerST::GetOutStream(
    478     ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
    479     UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
    480 {
    481   CMyComPtr<ISequentialOutStream> seqOutStream;
    482 
    483   {
    484     int index = -1;
    485     if (!EncodeMode)
    486     {
    487       if (_bi.UnpackCoder == outStreamIndex)
    488         index = 0;
    489     }
    490     else
    491       index = _bi.FindStream_in_PackStreams(outStreamIndex);
    492 
    493     if (index >= 0)
    494     {
    495       seqOutStream = outStreams[(unsigned)index];
    496       *outStreamRes = seqOutStream.Detach();
    497       return S_OK;
    498     }
    499   }
    500 
    501   int bond = FindBond_for_Stream(
    502       false, // forInputStream
    503       outStreamIndex);
    504   if (bond < 0)
    505     return E_INVALIDARG;
    506 
    507   UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
    508 
    509   UInt32 coderIndex = inStreamIndex;
    510   UInt32 coderStreamIndex = 0;
    511 
    512   if (!EncodeMode)
    513     _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
    514 
    515   CCoder &coder = _coders[coderIndex];
    516 
    517   /*
    518   if (!coder.Coder)
    519     return E_NOTIMPL;
    520   */
    521 
    522   coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
    523   if (!seqOutStream)
    524     return E_NOTIMPL;
    525 
    526   UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
    527   UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
    528 
    529   bool isSet = false;
    530 
    531   if (numOutStreams == 1)
    532   {
    533     CMyComPtr<ICompressSetOutStream> setOutStream;
    534     coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
    535     if (setOutStream)
    536     {
    537       CMyComPtr<ISequentialOutStream> seqOutStream2;
    538       RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
    539       RINOK(setOutStream->SetOutStream(seqOutStream2));
    540       isSet = true;
    541     }
    542   }
    543 
    544   if (!isSet && numOutStreams != 0)
    545   {
    546     return E_NOTIMPL;
    547     /*
    548     CMyComPtr<ICompressSetOutStream2> setStream2;
    549     coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
    550     if (!setStream2)
    551       return E_NOTIMPL;
    552     for (UInt32 i = 0; i < numOutStreams; i++)
    553     {
    554       CMyComPtr<ISequentialOutStream> seqOutStream2;
    555       RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
    556       RINOK(setStream2->SetOutStream2(i, seqOutStream2));
    557     }
    558     */
    559   }
    560 
    561   while (_binderStreams.Size() <= (unsigned)bond)
    562     _binderStreams.AddNew();
    563   CStBinderStream &bs = _binderStreams[bond];
    564 
    565   if (bs.StreamRef || bs.OutStreamSpec)
    566     return E_NOTIMPL;
    567 
    568   COutStreamCalcSize *spec = new COutStreamCalcSize;
    569   bs.StreamRef = (ISequentialOutStream *)spec;
    570   bs.OutStreamSpec = spec;
    571 
    572   spec->SetStream(seqOutStream);
    573   spec->Init();
    574 
    575   seqOutStream = bs.OutStreamSpec;
    576 
    577   *outStreamRes = seqOutStream.Detach();
    578   return S_OK;
    579 }
    580 
    581 
    582 static HRESULT GetError(HRESULT res, HRESULT res2)
    583 {
    584   if (res == res2)
    585     return res;
    586   if (res == S_OK)
    587     return res2;
    588   if (res == k_My_HRESULT_WritingWasCut)
    589   {
    590     if (res2 != S_OK)
    591       return res2;
    592   }
    593   return res;
    594 }
    595 
    596 
    597 HRESULT CMixerST::FinishStream(UInt32 streamIndex)
    598 {
    599   {
    600     int index = -1;
    601     if (!EncodeMode)
    602     {
    603       if (_bi.UnpackCoder == streamIndex)
    604         index = 0;
    605     }
    606     else
    607       index = _bi.FindStream_in_PackStreams(streamIndex);
    608 
    609     if (index >= 0)
    610       return S_OK;
    611   }
    612 
    613   int bond = FindBond_for_Stream(
    614       false, // forInputStream
    615       streamIndex);
    616   if (bond < 0)
    617     return E_INVALIDARG;
    618 
    619   UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
    620 
    621   UInt32 coderIndex = inStreamIndex;
    622   UInt32 coderStreamIndex = 0;
    623   if (!EncodeMode)
    624     _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
    625 
    626   CCoder &coder = _coders[coderIndex];
    627   CMyComPtr<IOutStreamFinish> finish;
    628   coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish);
    629   HRESULT res = S_OK;
    630   if (finish)
    631   {
    632     res = finish->OutStreamFinish();
    633   }
    634   return GetError(res, FinishCoder(coderIndex));
    635 }
    636 
    637 
    638 HRESULT CMixerST::FinishCoder(UInt32 coderIndex)
    639 {
    640   CCoder &coder = _coders[coderIndex];
    641 
    642   UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
    643   UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
    644 
    645   HRESULT res = S_OK;
    646   for (unsigned i = 0; i < numOutStreams; i++)
    647     res = GetError(res, FinishStream(startIndex + i));
    648   return res;
    649 }
    650 
    651 
    652 void CMixerST::SelectMainCoder(bool useFirst)
    653 {
    654   unsigned ci = _bi.UnpackCoder;
    655 
    656   int firstNonFilter = -1;
    657   int firstAllowed = ci;
    658 
    659   for (;;)
    660   {
    661     const CCoderST &coder = _coders[ci];
    662     // break;
    663 
    664     if (ci != _bi.UnpackCoder)
    665       if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
    666       {
    667         firstAllowed = ci;
    668         firstNonFilter = -2;
    669       }
    670 
    671     if (coder.NumStreams != 1)
    672       break;
    673 
    674     UInt32 st = _bi.Coder_to_Stream[ci];
    675     if (_bi.IsStream_in_PackStreams(st))
    676       break;
    677     int bond = _bi.FindBond_for_PackStream(st);
    678     if (bond < 0)
    679       throw 20150213;
    680 
    681     if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
    682       break;
    683 
    684     if (firstNonFilter == -1 && !IsFilter_Vector[ci])
    685       firstNonFilter = ci;
    686 
    687     ci = _bi.Bonds[bond].UnpackIndex;
    688   }
    689 
    690   if (useFirst)
    691     ci = firstAllowed;
    692   else if (firstNonFilter >= 0)
    693     ci = firstNonFilter;
    694 
    695   MainCoderIndex = ci;
    696 }
    697 
    698 
    699 HRESULT CMixerST::Code(
    700     ISequentialInStream * const *inStreams,
    701     ISequentialOutStream * const *outStreams,
    702     ICompressProgressInfo *progress,
    703     bool &dataAfterEnd_Error)
    704 {
    705   // InternalPackSizeError = false;
    706   dataAfterEnd_Error = false;
    707 
    708   _binderStreams.Clear();
    709   unsigned ci = MainCoderIndex;
    710 
    711   const CCoder &mainCoder = _coders[MainCoderIndex];
    712 
    713   CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
    714   CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
    715 
    716   UInt32 numInStreams  =  EncodeMode ? 1 : mainCoder.NumStreams;
    717   UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
    718 
    719   UInt32 startInIndex  =  EncodeMode ? ci : _bi.Coder_to_Stream[ci];
    720   UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
    721 
    722   UInt32 i;
    723 
    724   for (i = 0; i < numInStreams; i++)
    725   {
    726     CMyComPtr<ISequentialInStream> seqInStream;
    727     RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
    728     seqInStreams.Add(seqInStream);
    729   }
    730 
    731   for (i = 0; i < numOutStreams; i++)
    732   {
    733     CMyComPtr<ISequentialOutStream> seqOutStream;
    734     RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
    735     seqOutStreams.Add(seqOutStream);
    736   }
    737 
    738   CRecordVector< ISequentialInStream * > seqInStreamsSpec;
    739   CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
    740 
    741   for (i = 0; i < numInStreams; i++)
    742     seqInStreamsSpec.Add(seqInStreams[i]);
    743   for (i = 0; i < numOutStreams; i++)
    744     seqOutStreamsSpec.Add(seqOutStreams[i]);
    745 
    746   for (i = 0; i < _coders.Size(); i++)
    747   {
    748     if (i == ci)
    749       continue;
    750 
    751     CCoder &coder = _coders[i];
    752 
    753     if (EncodeMode)
    754     {
    755       CMyComPtr<ICompressInitEncoder> initEncoder;
    756       coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder);
    757       if (initEncoder)
    758         RINOK(initEncoder->InitEncoder());
    759     }
    760     else
    761     {
    762       CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
    763       coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
    764       if (setOutStreamSize)
    765         RINOK(setOutStreamSize->SetOutStreamSize(
    766             EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
    767     }
    768   }
    769 
    770   const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
    771   const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
    772 
    773   HRESULT res;
    774   if (mainCoder.Coder)
    775   {
    776     res = mainCoder.Coder->Code(
    777         seqInStreamsSpec[0], seqOutStreamsSpec[0],
    778         isSizes2[0], outSizes2[0],
    779         progress);
    780   }
    781   else
    782   {
    783     res = mainCoder.Coder2->Code(
    784         &seqInStreamsSpec.Front(), isSizes2, numInStreams,
    785         &seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
    786         progress);
    787   }
    788 
    789   if (res == k_My_HRESULT_WritingWasCut)
    790     res = S_OK;
    791 
    792   if (res == S_OK || res == S_FALSE)
    793   {
    794     res = GetError(res, FinishCoder(ci));
    795   }
    796 
    797   for (i = 0; i < _binderStreams.Size(); i++)
    798   {
    799     const CStBinderStream &bs = _binderStreams[i];
    800     if (bs.InStreamSpec)
    801       bs.InStreamSpec->ReleaseStream();
    802     else
    803       bs.OutStreamSpec->ReleaseStream();
    804   }
    805 
    806   if (res == k_My_HRESULT_WritingWasCut)
    807     res = S_OK;
    808 
    809   if (res != S_OK)
    810     return res;
    811 
    812   for (i = 0; i < _coders.Size(); i++)
    813   {
    814     RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */));
    815   }
    816 
    817   return S_OK;
    818 }
    819 
    820 
    821 HRESULT CMixerST::GetMainUnpackStream(
    822     ISequentialInStream * const *inStreams,
    823     ISequentialInStream **inStreamRes)
    824 {
    825   CMyComPtr<ISequentialInStream> seqInStream;
    826 
    827   RINOK(GetInStream2(inStreams, /* inSizes, */
    828       _bi.UnpackCoder, &seqInStream))
    829 
    830   FOR_VECTOR (i, _coders)
    831   {
    832     CCoder &coder = _coders[i];
    833     CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
    834     coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
    835     if (setOutStreamSize)
    836     {
    837       RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
    838     }
    839   }
    840 
    841   *inStreamRes = seqInStream.Detach();
    842   return S_OK;
    843 }
    844 
    845 
    846 UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
    847 {
    848   const CStBinderStream &bs = _binderStreams[bondIndex];
    849   if (bs.InStreamSpec)
    850     return bs.InStreamSpec->GetSize();
    851   return bs.OutStreamSpec->GetSize();
    852 }
    853 
    854 #endif
    855 
    856 
    857 
    858 
    859 
    860 
    861 #ifdef USE_MIXER_MT
    862 
    863 
    864 void CCoderMT::Execute()
    865 {
    866   try
    867   {
    868     Code(NULL);
    869   }
    870   catch(...)
    871   {
    872     Result = E_FAIL;
    873   }
    874 }
    875 
    876 void CCoderMT::Code(ICompressProgressInfo *progress)
    877 {
    878   unsigned numInStreams = EncodeMode ? 1 : NumStreams;
    879   unsigned numOutStreams = EncodeMode ? NumStreams : 1;
    880 
    881   InStreamPointers.ClearAndReserve(numInStreams);
    882   OutStreamPointers.ClearAndReserve(numOutStreams);
    883 
    884   unsigned i;
    885 
    886   for (i = 0; i < numInStreams; i++)
    887     InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
    888 
    889   for (i = 0; i < numOutStreams; i++)
    890     OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
    891 
    892   // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
    893   /*
    894   if (UnpackSizePointer)
    895     UnpackSizePointer = &UnpackSize;
    896   for (i = 0; i < NumStreams; i++)
    897     if (PackSizePointers[i])
    898       PackSizePointers[i] = &PackSizes[i];
    899   */
    900 
    901   CReleaser releaser(*this);
    902 
    903   if (Coder)
    904     Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
    905         EncodeMode ? UnpackSizePointer : PackSizePointers[0],
    906         EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
    907         progress);
    908   else
    909     Result = Coder2->Code(
    910         &InStreamPointers.Front(),  EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
    911         &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
    912         progress);
    913 }
    914 
    915 HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
    916 {
    917   CMixer::SetBindInfo(bindInfo);
    918 
    919   _streamBinders.Clear();
    920   FOR_VECTOR (i, _bi.Bonds)
    921   {
    922     RINOK(_streamBinders.AddNew().CreateEvents());
    923   }
    924   return S_OK;
    925 }
    926 
    927 void CMixerMT::AddCoder(const CCreatedCoder &cod)
    928 {
    929   IsFilter_Vector.Add(cod.IsFilter);
    930   IsExternal_Vector.Add(cod.IsExternal);
    931   // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
    932   CCoderMT &c2 = _coders.AddNew();
    933   c2.NumStreams = cod.NumStreams;
    934   c2.Coder = cod.Coder;
    935   c2.Coder2 = cod.Coder2;
    936   c2.EncodeMode = EncodeMode;
    937 }
    938 
    939 CCoder &CMixerMT::GetCoder(unsigned index)
    940 {
    941   return _coders[index];
    942 }
    943 
    944 void CMixerMT::ReInit()
    945 {
    946   FOR_VECTOR (i, _streamBinders)
    947     _streamBinders[i].ReInit();
    948 }
    949 
    950 void CMixerMT::SelectMainCoder(bool useFirst)
    951 {
    952   unsigned ci = _bi.UnpackCoder;
    953 
    954   if (!useFirst)
    955   for (;;)
    956   {
    957     if (_coders[ci].NumStreams != 1)
    958       break;
    959     if (!IsFilter_Vector[ci])
    960       break;
    961 
    962     UInt32 st = _bi.Coder_to_Stream[ci];
    963     if (_bi.IsStream_in_PackStreams(st))
    964       break;
    965     int bond = _bi.FindBond_for_PackStream(st);
    966     if (bond < 0)
    967       throw 20150213;
    968     ci = _bi.Bonds[bond].UnpackIndex;
    969   }
    970 
    971   MainCoderIndex = ci;
    972 }
    973 
    974 HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
    975 {
    976   unsigned i;
    977 
    978   for (i = 0; i < _coders.Size(); i++)
    979   {
    980     CCoderMT &coderInfo = _coders[i];
    981     const CCoderStreamsInfo &csi = _bi.Coders[i];
    982 
    983     UInt32 j;
    984 
    985     unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
    986     unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
    987 
    988     coderInfo.InStreams.Clear();
    989     for (j = 0; j < numInStreams; j++)
    990       coderInfo.InStreams.AddNew();
    991 
    992     coderInfo.OutStreams.Clear();
    993     for (j = 0; j < numOutStreams; j++)
    994       coderInfo.OutStreams.AddNew();
    995   }
    996 
    997   for (i = 0; i < _bi.Bonds.Size(); i++)
    998   {
    999     const CBond &bond = _bi.Bonds[i];
   1000 
   1001     UInt32 inCoderIndex, inCoderStreamIndex;
   1002     UInt32 outCoderIndex, outCoderStreamIndex;
   1003 
   1004     {
   1005       UInt32 coderIndex, coderStreamIndex;
   1006       _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
   1007 
   1008       inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
   1009       outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
   1010 
   1011       inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
   1012       outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
   1013     }
   1014 
   1015     _streamBinders[i].CreateStreams(
   1016         &_coders[inCoderIndex].InStreams[inCoderStreamIndex],
   1017         &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
   1018 
   1019     CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
   1020     _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
   1021     _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
   1022     if (inSetSize && outSetSize)
   1023     {
   1024       const UInt32 kBufSize = 1 << 19;
   1025       inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
   1026       outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
   1027     }
   1028   }
   1029 
   1030   {
   1031     CCoderMT &cod = _coders[_bi.UnpackCoder];
   1032     if (EncodeMode)
   1033       cod.InStreams[0] = inStreams[0];
   1034     else
   1035       cod.OutStreams[0] = outStreams[0];
   1036   }
   1037 
   1038   for (i = 0; i < _bi.PackStreams.Size(); i++)
   1039   {
   1040     UInt32 coderIndex, coderStreamIndex;
   1041     _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
   1042     CCoderMT &cod = _coders[coderIndex];
   1043     if (EncodeMode)
   1044       cod.OutStreams[coderStreamIndex] = outStreams[i];
   1045     else
   1046       cod.InStreams[coderStreamIndex] = inStreams[i];
   1047   }
   1048 
   1049   return S_OK;
   1050 }
   1051 
   1052 HRESULT CMixerMT::ReturnIfError(HRESULT code)
   1053 {
   1054   FOR_VECTOR (i, _coders)
   1055     if (_coders[i].Result == code)
   1056       return code;
   1057   return S_OK;
   1058 }
   1059 
   1060 HRESULT CMixerMT::Code(
   1061     ISequentialInStream * const *inStreams,
   1062     ISequentialOutStream * const *outStreams,
   1063     ICompressProgressInfo *progress,
   1064     bool &dataAfterEnd_Error)
   1065 {
   1066   // InternalPackSizeError = false;
   1067   dataAfterEnd_Error = false;
   1068 
   1069   Init(inStreams, outStreams);
   1070 
   1071   unsigned i;
   1072   for (i = 0; i < _coders.Size(); i++)
   1073     if (i != MainCoderIndex)
   1074     {
   1075       RINOK(_coders[i].Create());
   1076     }
   1077 
   1078   for (i = 0; i < _coders.Size(); i++)
   1079     if (i != MainCoderIndex)
   1080       _coders[i].Start();
   1081 
   1082   _coders[MainCoderIndex].Code(progress);
   1083 
   1084   for (i = 0; i < _coders.Size(); i++)
   1085     if (i != MainCoderIndex)
   1086       _coders[i].WaitExecuteFinish();
   1087 
   1088   RINOK(ReturnIfError(E_ABORT));
   1089   RINOK(ReturnIfError(E_OUTOFMEMORY));
   1090 
   1091   for (i = 0; i < _coders.Size(); i++)
   1092   {
   1093     HRESULT result = _coders[i].Result;
   1094     if (result != S_OK
   1095         && result != k_My_HRESULT_WritingWasCut
   1096         && result != S_FALSE
   1097         && result != E_FAIL)
   1098       return result;
   1099   }
   1100 
   1101   RINOK(ReturnIfError(S_FALSE));
   1102 
   1103   for (i = 0; i < _coders.Size(); i++)
   1104   {
   1105     HRESULT result = _coders[i].Result;
   1106     if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
   1107       return result;
   1108   }
   1109 
   1110   for (i = 0; i < _coders.Size(); i++)
   1111   {
   1112     RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */));
   1113   }
   1114 
   1115   return S_OK;
   1116 }
   1117 
   1118 UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
   1119 {
   1120   return _streamBinders[bondIndex].ProcessedSize;
   1121 }
   1122 
   1123 #endif
   1124 
   1125 }
   1126