Home | History | Annotate | Download | only in Common
      1 // CoderMixer2.h
      2 
      3 #ifndef __CODER_MIXER2_H
      4 #define __CODER_MIXER2_H
      5 
      6 #include "../../../Common/MyCom.h"
      7 #include "../../../Common/MyVector.h"
      8 
      9 #include "../../ICoder.h"
     10 
     11 #include "../../Common/CreateCoder.h"
     12 
     13 #ifdef _7ZIP_ST
     14   #define USE_MIXER_ST
     15 #else
     16   #define USE_MIXER_MT
     17   #ifndef _SFX
     18     #define USE_MIXER_ST
     19   #endif
     20 #endif
     21 
     22 #ifdef USE_MIXER_MT
     23 #include "../../Common/StreamBinder.h"
     24 #include "../../Common/VirtThread.h"
     25 #endif
     26 
     27 
     28 
     29 #ifdef USE_MIXER_ST
     30 
     31 class CSequentialInStreamCalcSize:
     32   public ISequentialInStream,
     33   public CMyUnknownImp
     34 {
     35 public:
     36   MY_UNKNOWN_IMP1(ISequentialInStream)
     37 
     38   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
     39 private:
     40   CMyComPtr<ISequentialInStream> _stream;
     41   UInt64 _size;
     42   bool _wasFinished;
     43 public:
     44   void SetStream(ISequentialInStream *stream) { _stream = stream;  }
     45   void Init()
     46   {
     47     _size = 0;
     48     _wasFinished = false;
     49   }
     50   void ReleaseStream() { _stream.Release(); }
     51   UInt64 GetSize() const { return _size; }
     52   bool WasFinished() const { return _wasFinished; }
     53 };
     54 
     55 
     56 class COutStreamCalcSize:
     57   public ISequentialOutStream,
     58   public IOutStreamFinish,
     59   public CMyUnknownImp
     60 {
     61   CMyComPtr<ISequentialOutStream> _stream;
     62   UInt64 _size;
     63 public:
     64   MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish)
     65 
     66   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
     67   STDMETHOD(OutStreamFinish)();
     68 
     69   void SetStream(ISequentialOutStream *stream) { _stream = stream; }
     70   void ReleaseStream() { _stream.Release(); }
     71   void Init() { _size = 0; }
     72   UInt64 GetSize() const { return _size; }
     73 };
     74 
     75 #endif
     76 
     77 
     78 
     79 namespace NCoderMixer2 {
     80 
     81 struct CBond
     82 {
     83   UInt32 PackIndex;
     84   UInt32 UnpackIndex;
     85 
     86   UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; }
     87   UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; }
     88 };
     89 
     90 
     91 struct CCoderStreamsInfo
     92 {
     93   UInt32 NumStreams;
     94 };
     95 
     96 
     97 struct CBindInfo
     98 {
     99   CRecordVector<CCoderStreamsInfo> Coders;
    100   CRecordVector<CBond> Bonds;
    101   CRecordVector<UInt32> PackStreams;
    102   unsigned UnpackCoder;
    103 
    104   unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); }
    105 
    106   int FindBond_for_PackStream(UInt32 packStream) const
    107   {
    108     FOR_VECTOR (i, Bonds)
    109       if (Bonds[i].PackIndex == packStream)
    110         return i;
    111     return -1;
    112   }
    113 
    114   int FindBond_for_UnpackStream(UInt32 unpackStream) const
    115   {
    116     FOR_VECTOR (i, Bonds)
    117       if (Bonds[i].UnpackIndex == unpackStream)
    118         return i;
    119     return -1;
    120   }
    121 
    122   bool SetUnpackCoder()
    123   {
    124     bool isOk = false;
    125     FOR_VECTOR(i, Coders)
    126     {
    127       if (FindBond_for_UnpackStream(i) < 0)
    128       {
    129         if (isOk)
    130           return false;
    131         UnpackCoder = i;
    132         isOk = true;
    133       }
    134     }
    135     return isOk;
    136   }
    137 
    138   bool IsStream_in_PackStreams(UInt32 streamIndex) const
    139   {
    140     return FindStream_in_PackStreams(streamIndex) >= 0;
    141   }
    142 
    143   int FindStream_in_PackStreams(UInt32 streamIndex) const
    144   {
    145     FOR_VECTOR(i, PackStreams)
    146       if (PackStreams[i] == streamIndex)
    147         return i;
    148     return -1;
    149   }
    150 
    151 
    152   // that function is used before Maps is calculated
    153 
    154   UInt32 GetStream_for_Coder(UInt32 coderIndex) const
    155   {
    156     UInt32 streamIndex = 0;
    157     for (UInt32 i = 0; i < coderIndex; i++)
    158       streamIndex += Coders[i].NumStreams;
    159     return streamIndex;
    160   }
    161 
    162   // ---------- Maps Section ----------
    163 
    164   CRecordVector<UInt32> Coder_to_Stream;
    165   CRecordVector<UInt32> Stream_to_Coder;
    166 
    167   void ClearMaps();
    168   bool CalcMapsAndCheck();
    169 
    170   // ---------- End of Maps Section ----------
    171 
    172   void Clear()
    173   {
    174     Coders.Clear();
    175     Bonds.Clear();
    176     PackStreams.Clear();
    177 
    178     ClearMaps();
    179   }
    180 
    181   void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const
    182   {
    183     coderIndex = Stream_to_Coder[streamIndex];
    184     coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex];
    185   }
    186 };
    187 
    188 
    189 
    190 class CCoder
    191 {
    192   CLASS_NO_COPY(CCoder);
    193 public:
    194   CMyComPtr<ICompressCoder> Coder;
    195   CMyComPtr<ICompressCoder2> Coder2;
    196   UInt32 NumStreams;
    197 
    198   UInt64 UnpackSize;
    199   const UInt64 *UnpackSizePointer;
    200 
    201   CRecordVector<UInt64> PackSizes;
    202   CRecordVector<const UInt64 *> PackSizePointers;
    203 
    204   bool Finish;
    205 
    206   CCoder(): Finish(false) {}
    207 
    208   void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish);
    209 
    210   HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const;
    211 
    212   IUnknown *GetUnknown() const
    213   {
    214     return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
    215   }
    216 
    217   HRESULT QueryInterface(REFGUID iid, void** pp) const
    218   {
    219     return GetUnknown()->QueryInterface(iid, pp);
    220   }
    221 };
    222 
    223 
    224 
    225 class CMixer
    226 {
    227   bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex);
    228 
    229 protected:
    230   CBindInfo _bi;
    231 
    232   int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const
    233   {
    234     if (EncodeMode == forInputStream)
    235       return _bi.FindBond_for_UnpackStream(streamIndex);
    236     else
    237       return _bi.FindBond_for_PackStream(streamIndex);
    238   }
    239 
    240   CBoolVector IsFilter_Vector;
    241   CBoolVector IsExternal_Vector;
    242   bool EncodeMode;
    243 public:
    244   unsigned MainCoderIndex;
    245 
    246   // bool InternalPackSizeError;
    247 
    248   CMixer(bool encodeMode):
    249       EncodeMode(encodeMode),
    250       MainCoderIndex(0)
    251       // , InternalPackSizeError(false)
    252       {}
    253 
    254   /*
    255   Sequence of calling:
    256 
    257       SetBindInfo();
    258       for each coder
    259         AddCoder();
    260       SelectMainCoder();
    261 
    262       for each file
    263       {
    264         ReInit()
    265         for each coder
    266           SetCoderInfo();
    267         Code();
    268       }
    269   */
    270 
    271   virtual HRESULT SetBindInfo(const CBindInfo &bindInfo)
    272   {
    273     _bi = bindInfo;
    274     IsFilter_Vector.Clear();
    275     MainCoderIndex = 0;
    276     return S_OK;
    277   }
    278 
    279   virtual void AddCoder(const CCreatedCoder &cod) = 0;
    280   virtual CCoder &GetCoder(unsigned index) = 0;
    281   virtual void SelectMainCoder(bool useFirst) = 0;
    282   virtual void ReInit() = 0;
    283   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0;
    284   virtual HRESULT Code(
    285       ISequentialInStream * const *inStreams,
    286       ISequentialOutStream * const *outStreams,
    287       ICompressProgressInfo *progress,
    288       bool &dataAfterEnd_Error) = 0;
    289   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;
    290 
    291   bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);
    292   bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex);
    293   bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex);
    294 };
    295 
    296 
    297 
    298 
    299 #ifdef USE_MIXER_ST
    300 
    301 struct CCoderST: public CCoder
    302 {
    303   bool CanRead;
    304   bool CanWrite;
    305 
    306   CCoderST(): CanRead(false), CanWrite(false) {}
    307 };
    308 
    309 
    310 struct CStBinderStream
    311 {
    312   CSequentialInStreamCalcSize *InStreamSpec;
    313   COutStreamCalcSize *OutStreamSpec;
    314   CMyComPtr<IUnknown> StreamRef;
    315 
    316   CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
    317 };
    318 
    319 
    320 class CMixerST:
    321   public IUnknown,
    322   public CMixer,
    323   public CMyUnknownImp
    324 {
    325   HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
    326       UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
    327   HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
    328       UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
    329   HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
    330       UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
    331 
    332   HRESULT FinishStream(UInt32 streamIndex);
    333   HRESULT FinishCoder(UInt32 coderIndex);
    334 
    335 public:
    336   CObjectVector<CCoderST> _coders;
    337 
    338   CObjectVector<CStBinderStream> _binderStreams;
    339 
    340   MY_UNKNOWN_IMP
    341 
    342   CMixerST(bool encodeMode);
    343   ~CMixerST();
    344 
    345   virtual void AddCoder(const CCreatedCoder &cod);
    346   virtual CCoder &GetCoder(unsigned index);
    347   virtual void SelectMainCoder(bool useFirst);
    348   virtual void ReInit();
    349   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
    350     { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
    351   virtual HRESULT Code(
    352       ISequentialInStream * const *inStreams,
    353       ISequentialOutStream * const *outStreams,
    354       ICompressProgressInfo *progress,
    355       bool &dataAfterEnd_Error);
    356   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
    357 
    358   HRESULT GetMainUnpackStream(
    359       ISequentialInStream * const *inStreams,
    360       ISequentialInStream **inStreamRes);
    361 };
    362 
    363 #endif
    364 
    365 
    366 
    367 
    368 #ifdef USE_MIXER_MT
    369 
    370 class CCoderMT: public CCoder, public CVirtThread
    371 {
    372   CLASS_NO_COPY(CCoderMT)
    373   CRecordVector<ISequentialInStream*> InStreamPointers;
    374   CRecordVector<ISequentialOutStream*> OutStreamPointers;
    375 
    376 private:
    377   void Execute();
    378 public:
    379   bool EncodeMode;
    380   HRESULT Result;
    381   CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
    382   CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
    383 
    384   void Release()
    385   {
    386     InStreamPointers.Clear();
    387     OutStreamPointers.Clear();
    388     unsigned i;
    389     for (i = 0; i < InStreams.Size(); i++)
    390       InStreams[i].Release();
    391     for (i = 0; i < OutStreams.Size(); i++)
    392       OutStreams[i].Release();
    393   }
    394 
    395   class CReleaser
    396   {
    397     CLASS_NO_COPY(CReleaser)
    398     CCoderMT &_c;
    399   public:
    400     CReleaser(CCoderMT &c): _c(c) {}
    401     ~CReleaser() { _c.Release(); }
    402   };
    403 
    404   CCoderMT(): EncodeMode(false) {}
    405   ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
    406 
    407   void Code(ICompressProgressInfo *progress);
    408 };
    409 
    410 
    411 class CMixerMT:
    412   public IUnknown,
    413   public CMixer,
    414   public CMyUnknownImp
    415 {
    416   CObjectVector<CStreamBinder> _streamBinders;
    417 
    418   HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
    419   HRESULT ReturnIfError(HRESULT code);
    420 
    421 public:
    422   CObjectVector<CCoderMT> _coders;
    423 
    424   MY_UNKNOWN_IMP
    425 
    426   virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
    427   virtual void AddCoder(const CCreatedCoder &cod);
    428   virtual CCoder &GetCoder(unsigned index);
    429   virtual void SelectMainCoder(bool useFirst);
    430   virtual void ReInit();
    431   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
    432     { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
    433   virtual HRESULT Code(
    434       ISequentialInStream * const *inStreams,
    435       ISequentialOutStream * const *outStreams,
    436       ICompressProgressInfo *progress,
    437       bool &dataAfterEnd_Error);
    438   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
    439 
    440   CMixerMT(bool encodeMode): CMixer(encodeMode) {}
    441 };
    442 
    443 #endif
    444 
    445 }
    446 
    447 #endif
    448