// CoderMixer2.h #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../ICoder.h" #include "../../Common/CreateCoder.h" #ifdef _7ZIP_ST #define USE_MIXER_ST #else #define USE_MIXER_MT #ifndef _SFX #define USE_MIXER_ST #endif #endif #ifdef USE_MIXER_MT #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" #endif #ifdef USE_MIXER_ST class CSequentialInStreamCalcSize: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ISequentialInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr _stream; UInt64 _size; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; } void ReleaseStream() { _stream.Release(); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; class COutStreamCalcSize: public ISequentialOutStream, public IOutStreamFinish, public CMyUnknownImp { CMyComPtr _stream; UInt64 _size; public: MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(OutStreamFinish)(); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } }; #endif namespace NCoderMixer2 { struct CBond { UInt32 PackIndex; UInt32 UnpackIndex; UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; } UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; } }; struct CCoderStreamsInfo { UInt32 NumStreams; }; struct CBindInfo { CRecordVector Coders; CRecordVector Bonds; CRecordVector PackStreams; unsigned UnpackCoder; unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); } int FindBond_for_PackStream(UInt32 packStream) const { FOR_VECTOR (i, Bonds) if (Bonds[i].PackIndex == packStream) return i; return -1; } int FindBond_for_UnpackStream(UInt32 unpackStream) const { FOR_VECTOR (i, Bonds) if (Bonds[i].UnpackIndex == unpackStream) return i; return -1; } bool SetUnpackCoder() { bool isOk = false; FOR_VECTOR(i, Coders) { if (FindBond_for_UnpackStream(i) < 0) { if (isOk) return false; UnpackCoder = i; isOk = true; } } return isOk; } bool IsStream_in_PackStreams(UInt32 streamIndex) const { return FindStream_in_PackStreams(streamIndex) >= 0; } int FindStream_in_PackStreams(UInt32 streamIndex) const { FOR_VECTOR(i, PackStreams) if (PackStreams[i] == streamIndex) return i; return -1; } // that function is used before Maps is calculated UInt32 GetStream_for_Coder(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumStreams; return streamIndex; } // ---------- Maps Section ---------- CRecordVector Coder_to_Stream; CRecordVector Stream_to_Coder; void ClearMaps(); bool CalcMapsAndCheck(); // ---------- End of Maps Section ---------- void Clear() { Coders.Clear(); Bonds.Clear(); PackStreams.Clear(); ClearMaps(); } void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { coderIndex = Stream_to_Coder[streamIndex]; coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex]; } }; class CCoder { CLASS_NO_COPY(CCoder); public: CMyComPtr Coder; CMyComPtr Coder2; UInt32 NumStreams; UInt64 UnpackSize; const UInt64 *UnpackSizePointer; CRecordVector PackSizes; CRecordVector PackSizePointers; CCoder() {} void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes); IUnknown *GetUnknown() const { return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; } HRESULT QueryInterface(REFGUID iid, void** pp) const { return GetUnknown()->QueryInterface(iid, pp); } }; class CMixer { bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex); protected: CBindInfo _bi; int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const { if (EncodeMode == forInputStream) return _bi.FindBond_for_UnpackStream(streamIndex); else return _bi.FindBond_for_PackStream(streamIndex); } CBoolVector IsFilter_Vector; CBoolVector IsExternal_Vector; bool EncodeMode; public: unsigned MainCoderIndex; CMixer(bool encodeMode): EncodeMode(encodeMode), MainCoderIndex(0) {} /* Sequence of calling: SetBindInfo(); for each coder AddCoder(); SelectMainCoder(); for each file { ReInit() for each coder SetCoderInfo(); Code(); } */ virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) { _bi = bindInfo; IsFilter_Vector.Clear(); MainCoderIndex = 0; return S_OK; } virtual void AddCoder(const CCreatedCoder &cod) = 0; virtual CCoder &GetCoder(unsigned index) = 0; virtual void SelectMainCoder(bool useFirst) = 0; virtual void ReInit() = 0; virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0; virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress) = 0; virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0; bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex); bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex); bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex); }; #ifdef USE_MIXER_ST struct CCoderST: public CCoder { bool CanRead; bool CanWrite; CCoderST(): CanRead(false), CanWrite(false) {} }; struct CStBinderStream { CSequentialInStreamCalcSize *InStreamSpec; COutStreamCalcSize *OutStreamSpec; CMyComPtr StreamRef; CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {} }; class CMixerST: public IUnknown, public CMixer, public CMyUnknownImp { HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ UInt32 outStreamIndex, ISequentialInStream **inStreamRes); HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ UInt32 inStreamIndex, ISequentialInStream **inStreamRes); HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes); HRESULT FinishStream(UInt32 streamIndex); HRESULT FinishCoder(UInt32 coderIndex); public: CObjectVector _coders; CObjectVector _binderStreams; MY_UNKNOWN_IMP CMixerST(bool encodeMode); ~CMixerST(); virtual void AddCoder(const CCreatedCoder &cod); virtual CCoder &GetCoder(unsigned index); virtual void SelectMainCoder(bool useFirst); virtual void ReInit(); virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); } virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress); virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; HRESULT GetMainUnpackStream( ISequentialInStream * const *inStreams, ISequentialInStream **inStreamRes); }; #endif #ifdef USE_MIXER_MT class CCoderMT: public CCoder, public CVirtThread { CLASS_NO_COPY(CCoderMT) CRecordVector InStreamPointers; CRecordVector OutStreamPointers; private: void Execute(); public: bool EncodeMode; HRESULT Result; CObjectVector< CMyComPtr > InStreams; CObjectVector< CMyComPtr > OutStreams; void Release() { InStreamPointers.Clear(); OutStreamPointers.Clear(); unsigned i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) OutStreams[i].Release(); } class CReleaser { CLASS_NO_COPY(CReleaser) CCoderMT &_c; public: CReleaser(CCoderMT &c): _c(c) {} ~CReleaser() { _c.Release(); } }; CCoderMT(): EncodeMode(false) {} ~CCoderMT() { CVirtThread::WaitThreadFinish(); } void Code(ICompressProgressInfo *progress); }; class CMixerMT: public IUnknown, public CMixer, public CMyUnknownImp { CObjectVector _streamBinders; HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); HRESULT ReturnIfError(HRESULT code); public: CObjectVector _coders; MY_UNKNOWN_IMP virtual HRESULT SetBindInfo(const CBindInfo &bindInfo); virtual void AddCoder(const CCreatedCoder &cod); virtual CCoder &GetCoder(unsigned index); virtual void SelectMainCoder(bool useFirst); virtual void ReInit(); virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); } virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress); virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; CMixerMT(bool encodeMode): CMixer(encodeMode) {} }; #endif } #endif