Home | History | Annotate | Download | only in Common
      1 // CoderMixer2MT.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "CoderMixer2MT.h"
      6 
      7 namespace NCoderMixer {
      8 
      9 CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):
     10     CCoderInfo2(numInStreams, numOutStreams)
     11 {
     12   InStreams.Reserve(NumInStreams);
     13   InStreamPointers.Reserve(NumInStreams);
     14   OutStreams.Reserve(NumOutStreams);
     15   OutStreamPointers.Reserve(NumOutStreams);
     16 }
     17 
     18 void CCoder2::Execute() { Code(NULL); }
     19 
     20 void CCoder2::Code(ICompressProgressInfo *progress)
     21 {
     22   InStreamPointers.Clear();
     23   OutStreamPointers.Clear();
     24   UInt32 i;
     25   for (i = 0; i < NumInStreams; i++)
     26   {
     27     if (InSizePointers[i] != NULL)
     28       InSizePointers[i] = &InSizes[i];
     29     InStreamPointers.Add((ISequentialInStream *)InStreams[i]);
     30   }
     31   for (i = 0; i < NumOutStreams; i++)
     32   {
     33     if (OutSizePointers[i] != NULL)
     34       OutSizePointers[i] = &OutSizes[i];
     35     OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]);
     36   }
     37   if (Coder)
     38     Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
     39         InSizePointers[0], OutSizePointers[0], progress);
     40   else
     41     Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,
     42       &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);
     43   {
     44     int i;
     45     for (i = 0; i < InStreams.Size(); i++)
     46       InStreams[i].Release();
     47     for (i = 0; i < OutStreams.Size(); i++)
     48       OutStreams[i].Release();
     49   }
     50 }
     51 
     52 static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
     53     CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
     54 {
     55   sizes.Clear();
     56   sizePointers.Clear();
     57   for (UInt32 i = 0; i < numItems; i++)
     58   {
     59     if (srcSizes == 0 || srcSizes[i] == NULL)
     60     {
     61       sizes.Add(0);
     62       sizePointers.Add(NULL);
     63     }
     64     else
     65     {
     66       sizes.Add(*srcSizes[i]);
     67       sizePointers.Add(&sizes.Back());
     68     }
     69   }
     70 }
     71 
     72 
     73 void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
     74 {
     75   SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
     76   SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
     77 }
     78 
     79 //////////////////////////////////////
     80 // CCoderMixer2MT
     81 
     82 HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
     83 {
     84   _bindInfo = bindInfo;
     85   _streamBinders.Clear();
     86   for (int i = 0; i < _bindInfo.BindPairs.Size(); i++)
     87   {
     88     _streamBinders.Add(CStreamBinder());
     89     RINOK(_streamBinders.Back().CreateEvents());
     90   }
     91   return S_OK;
     92 }
     93 
     94 void CCoderMixer2MT::AddCoderCommon()
     95 {
     96   const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
     97   CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
     98   _coders.Add(threadCoderInfo);
     99 }
    100 
    101 void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
    102 {
    103   AddCoderCommon();
    104   _coders.Back().Coder = coder;
    105 }
    106 
    107 void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
    108 {
    109   AddCoderCommon();
    110   _coders.Back().Coder2 = coder;
    111 }
    112 
    113 
    114 void CCoderMixer2MT::ReInit()
    115 {
    116   for (int i = 0; i < _streamBinders.Size(); i++)
    117     _streamBinders[i].ReInit();
    118 }
    119 
    120 
    121 HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams)
    122 {
    123   /*
    124   if (_coders.Size() != _bindInfo.Coders.Size())
    125     throw 0;
    126   */
    127   int i;
    128   for (i = 0; i < _coders.Size(); i++)
    129   {
    130     CCoder2 &coderInfo = _coders[i];
    131     const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
    132     coderInfo.InStreams.Clear();
    133     UInt32 j;
    134     for (j = 0; j < coderStreamsInfo.NumInStreams; j++)
    135       coderInfo.InStreams.Add(NULL);
    136     coderInfo.OutStreams.Clear();
    137     for (j = 0; j < coderStreamsInfo.NumOutStreams; j++)
    138       coderInfo.OutStreams.Add(NULL);
    139   }
    140 
    141   for (i = 0; i < _bindInfo.BindPairs.Size(); i++)
    142   {
    143     const CBindPair &bindPair = _bindInfo.BindPairs[i];
    144     UInt32 inCoderIndex, inCoderStreamIndex;
    145     UInt32 outCoderIndex, outCoderStreamIndex;
    146     _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
    147     _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
    148 
    149     _streamBinders[i].CreateStreams(
    150         &_coders[inCoderIndex].InStreams[inCoderStreamIndex],
    151         &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
    152 
    153     CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
    154     _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
    155     _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
    156     if (inSetSize && outSetSize)
    157     {
    158       const UInt32 kBufSize = 1 << 19;
    159       inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
    160       outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
    161     }
    162   }
    163 
    164   for (i = 0; i < _bindInfo.InStreams.Size(); i++)
    165   {
    166     UInt32 inCoderIndex, inCoderStreamIndex;
    167     _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
    168     _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
    169   }
    170 
    171   for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
    172   {
    173     UInt32 outCoderIndex, outCoderStreamIndex;
    174     _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
    175     _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
    176   }
    177   return S_OK;
    178 }
    179 
    180 HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
    181 {
    182   for (int i = 0; i < _coders.Size(); i++)
    183     if (_coders[i].Result == code)
    184       return code;
    185   return S_OK;
    186 }
    187 
    188 STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
    189       const UInt64 ** /* inSizes */,
    190       UInt32 numInStreams,
    191       ISequentialOutStream **outStreams,
    192       const UInt64 ** /* outSizes */,
    193       UInt32 numOutStreams,
    194       ICompressProgressInfo *progress)
    195 {
    196   if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
    197       numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
    198     return E_INVALIDARG;
    199 
    200   Init(inStreams, outStreams);
    201 
    202   int i;
    203   for (i = 0; i < _coders.Size(); i++)
    204     if (i != _progressCoderIndex)
    205     {
    206       RINOK(_coders[i].Create());
    207     }
    208 
    209   for (i = 0; i < _coders.Size(); i++)
    210     if (i != _progressCoderIndex)
    211       _coders[i].Start();
    212 
    213   _coders[_progressCoderIndex].Code(progress);
    214 
    215   for (i = 0; i < _coders.Size(); i++)
    216     if (i != _progressCoderIndex)
    217       _coders[i].WaitFinish();
    218 
    219   RINOK(ReturnIfError(E_ABORT));
    220   RINOK(ReturnIfError(E_OUTOFMEMORY));
    221 
    222   for (i = 0; i < _coders.Size(); i++)
    223   {
    224     HRESULT result = _coders[i].Result;
    225     if (result != S_OK && result != E_FAIL && result != S_FALSE)
    226       return result;
    227   }
    228 
    229   RINOK(ReturnIfError(S_FALSE));
    230 
    231   for (i = 0; i < _coders.Size(); i++)
    232   {
    233     HRESULT result = _coders[i].Result;
    234     if (result != S_OK)
    235       return result;
    236   }
    237   return S_OK;
    238 }
    239 
    240 }
    241