tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CoderMixer2.cpp (28161B)


      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 }