// CoderMixer2.h #ifndef ZIP7_INC_CODER_MIXER2_H #define ZIP7_INC_CODER_MIXER2_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../ICoder.h" #include "../../Common/CreateCoder.h" #ifdef Z7_ST #define USE_MIXER_ST #else #define USE_MIXER_MT #ifndef Z7_SFX #define USE_MIXER_ST #endif #endif #ifdef USE_MIXER_MT #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" #endif #ifdef USE_MIXER_ST Z7_CLASS_IMP_COM_1( CSequentialInStreamCalcSize , ISequentialInStream ) bool _wasFinished; CMyComPtr _stream; UInt64 _size; 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; } }; Z7_CLASS_IMP_COM_2( COutStreamCalcSize , ISequentialOutStream , IOutStreamFinish ) CMyComPtr _stream; UInt64 _size; public: 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 (int)i; return -1; } int FindBond_for_UnpackStream(UInt32 unpackStream) const { FOR_VECTOR (i, Bonds) if (Bonds[i].UnpackIndex == unpackStream) return (int)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 (int)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 { Z7_CLASS_NO_COPY(CCoder) public: CMyComPtr Coder; CMyComPtr Coder2; UInt32 NumStreams; bool Finish; UInt64 UnpackSize; const UInt64 *UnpackSizePointer; CRecordVector PackSizes; CRecordVector PackSizePointers; CCoder(): Finish(false) {} void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish); HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const; 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; // bool InternalPackSizeError; CMixer(bool encodeMode): EncodeMode(encodeMode), MainCoderIndex(0) // , InternalPackSizeError(false) {} virtual ~CMixer() {} /* 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 HRESULT ReInit2() = 0; virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0; virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress, bool &dataAfterEnd_Error) = 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 { Z7_COM_UNKNOWN_IMP_0 Z7_CLASS_NO_COPY(CMixerST) 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; CMixerST(bool encodeMode); ~CMixerST() Z7_DESTRUCTOR_override; virtual void AddCoder(const CCreatedCoder &cod) Z7_override; virtual CCoder &GetCoder(unsigned index) Z7_override; virtual void SelectMainCoder(bool useFirst) Z7_override; virtual HRESULT ReInit2() Z7_override; virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) Z7_override { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress, bool &dataAfterEnd_Error) Z7_override; virtual UInt64 GetBondStreamSize(unsigned bondIndex) const Z7_override; HRESULT GetMainUnpackStream( ISequentialInStream * const *inStreams, ISequentialInStream **inStreamRes); }; #endif #ifdef USE_MIXER_MT class CCoderMT: public CCoder, public CVirtThread { Z7_CLASS_NO_COPY(CCoderMT) CRecordVector InStreamPointers; CRecordVector OutStreamPointers; private: virtual void Execute() Z7_override; 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 { Z7_CLASS_NO_COPY(CReleaser) CCoderMT &_c; public: CReleaser(CCoderMT &c): _c(c) {} ~CReleaser() { _c.Release(); } }; CCoderMT(): EncodeMode(false) {} ~CCoderMT() Z7_DESTRUCTOR_override { /* WaitThreadFinish() will be called in ~CVirtThread(). But we need WaitThreadFinish() call before CCoder destructor, and before destructors of this class members. */ CVirtThread::WaitThreadFinish(); } void Code(ICompressProgressInfo *progress); }; class CMixerMT: public IUnknown, public CMixer, public CMyUnknownImp { Z7_COM_UNKNOWN_IMP_0 Z7_CLASS_NO_COPY(CMixerMT) CObjectVector _streamBinders; HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); HRESULT ReturnIfError(HRESULT code); // virtual ~CMixerMT() {} public: CObjectVector _coders; virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) Z7_override; virtual void AddCoder(const CCreatedCoder &cod) Z7_override; virtual CCoder &GetCoder(unsigned index) Z7_override; virtual void SelectMainCoder(bool useFirst) Z7_override; virtual HRESULT ReInit2() Z7_override; virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) Z7_override { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress, bool &dataAfterEnd_Error) Z7_override; virtual UInt64 GetBondStreamSize(unsigned bondIndex) const Z7_override; CMixerMT(bool encodeMode): CMixer(encodeMode) {} }; #endif } #endif