"Fossies" - the Fresh Open Source Software Archive

Member "UXP-2019.06.08/other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.cpp" (8 Jun 2019, 28161 Bytes) of package /linux/www/UXP-2019.06.08.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

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