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   CCoder() {}
    205 
    206   void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes);
    207 
    208   IUnknown *GetUnknown() const
    209   {
    210     return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
    211   }
    212 
    213   HRESULT QueryInterface(REFGUID iid, void** pp) const
    214   {
    215     return GetUnknown()->QueryInterface(iid, pp);
    216   }
    217 };
    218 
    219 
    220 
    221 class CMixer
    222 {
    223   bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex);
    224 
    225 protected:
    226   CBindInfo _bi;
    227 
    228   int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const
    229   {
    230     if (EncodeMode == forInputStream)
    231       return _bi.FindBond_for_UnpackStream(streamIndex);
    232     else
    233       return _bi.FindBond_for_PackStream(streamIndex);
    234   }
    235 
    236   CBoolVector IsFilter_Vector;
    237   CBoolVector IsExternal_Vector;
    238   bool EncodeMode;
    239 public:
    240   unsigned MainCoderIndex;
    241 
    242   CMixer(bool encodeMode):
    243       EncodeMode(encodeMode),
    244       MainCoderIndex(0)
    245       {}
    246 
    247   /*
    248   Sequence of calling:
    249 
    250       SetBindInfo();
    251       for each coder
    252         AddCoder();
    253       SelectMainCoder();
    254 
    255       for each file
    256       {
    257         ReInit()
    258         for each coder
    259           SetCoderInfo();
    260         Code();
    261       }
    262   */
    263 
    264   virtual HRESULT SetBindInfo(const CBindInfo &bindInfo)
    265   {
    266     _bi = bindInfo;
    267     IsFilter_Vector.Clear();
    268     MainCoderIndex = 0;
    269     return S_OK;
    270   }
    271 
    272   virtual void AddCoder(const CCreatedCoder &cod) = 0;
    273   virtual CCoder &GetCoder(unsigned index) = 0;
    274   virtual void SelectMainCoder(bool useFirst) = 0;
    275   virtual void ReInit() = 0;
    276   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0;
    277   virtual HRESULT Code(
    278       ISequentialInStream * const *inStreams,
    279       ISequentialOutStream * const *outStreams,
    280       ICompressProgressInfo *progress) = 0;
    281   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;
    282 
    283   bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);
    284   bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex);
    285   bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex);
    286 };
    287 
    288 
    289 
    290 
    291 #ifdef USE_MIXER_ST
    292 
    293 struct CCoderST: public CCoder
    294 {
    295   bool CanRead;
    296   bool CanWrite;
    297 
    298   CCoderST(): CanRead(false), CanWrite(false) {}
    299 };
    300 
    301 
    302 struct CStBinderStream
    303 {
    304   CSequentialInStreamCalcSize *InStreamSpec;
    305   COutStreamCalcSize *OutStreamSpec;
    306   CMyComPtr<IUnknown> StreamRef;
    307 
    308   CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
    309 };
    310 
    311 
    312 class CMixerST:
    313   public IUnknown,
    314   public CMixer,
    315   public CMyUnknownImp
    316 {
    317   HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
    318       UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
    319   HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
    320       UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
    321   HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
    322       UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
    323 
    324   HRESULT FinishStream(UInt32 streamIndex);
    325   HRESULT FinishCoder(UInt32 coderIndex);
    326 
    327 public:
    328   CObjectVector<CCoderST> _coders;
    329 
    330   CObjectVector<CStBinderStream> _binderStreams;
    331 
    332   MY_UNKNOWN_IMP
    333 
    334   CMixerST(bool encodeMode);
    335   ~CMixerST();
    336 
    337   virtual void AddCoder(const CCreatedCoder &cod);
    338   virtual CCoder &GetCoder(unsigned index);
    339   virtual void SelectMainCoder(bool useFirst);
    340   virtual void ReInit();
    341   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
    342     { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
    343   virtual HRESULT Code(
    344       ISequentialInStream * const *inStreams,
    345       ISequentialOutStream * const *outStreams,
    346       ICompressProgressInfo *progress);
    347   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
    348 
    349   HRESULT GetMainUnpackStream(
    350       ISequentialInStream * const *inStreams,
    351       ISequentialInStream **inStreamRes);
    352 };
    353 
    354 #endif
    355 
    356 
    357 
    358 
    359 #ifdef USE_MIXER_MT
    360 
    361 class CCoderMT: public CCoder, public CVirtThread
    362 {
    363   CLASS_NO_COPY(CCoderMT)
    364   CRecordVector<ISequentialInStream*> InStreamPointers;
    365   CRecordVector<ISequentialOutStream*> OutStreamPointers;
    366 
    367 private:
    368   void Execute();
    369 public:
    370   bool EncodeMode;
    371   HRESULT Result;
    372   CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
    373   CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
    374 
    375   void Release()
    376   {
    377     InStreamPointers.Clear();
    378     OutStreamPointers.Clear();
    379     unsigned i;
    380     for (i = 0; i < InStreams.Size(); i++)
    381       InStreams[i].Release();
    382     for (i = 0; i < OutStreams.Size(); i++)
    383       OutStreams[i].Release();
    384   }
    385 
    386   class CReleaser
    387   {
    388     CLASS_NO_COPY(CReleaser)
    389     CCoderMT &_c;
    390   public:
    391     CReleaser(CCoderMT &c): _c(c) {}
    392     ~CReleaser() { _c.Release(); }
    393   };
    394 
    395   CCoderMT(): EncodeMode(false) {}
    396   ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
    397 
    398   void Code(ICompressProgressInfo *progress);
    399 };
    400 
    401 
    402 class CMixerMT:
    403   public IUnknown,
    404   public CMixer,
    405   public CMyUnknownImp
    406 {
    407   CObjectVector<CStreamBinder> _streamBinders;
    408 
    409   HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
    410   HRESULT ReturnIfError(HRESULT code);
    411 
    412 public:
    413   CObjectVector<CCoderMT> _coders;
    414 
    415   MY_UNKNOWN_IMP
    416 
    417   virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
    418   virtual void AddCoder(const CCreatedCoder &cod);
    419   virtual CCoder &GetCoder(unsigned index);
    420   virtual void SelectMainCoder(bool useFirst);
    421   virtual void ReInit();
    422   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
    423     { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
    424   virtual HRESULT Code(
    425       ISequentialInStream * const *inStreams,
    426       ISequentialOutStream * const *outStreams,
    427       ICompressProgressInfo *progress);
    428   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
    429 
    430   CMixerMT(bool encodeMode): CMixer(encodeMode) {}
    431 };
    432 
    433 #endif
    434 
    435 }
    436 
    437 #endif
    438