blob: 484a6089ad47eda567c0eeec5b850814fab12837 [file] [log] [blame]
// 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<ISequentialInStream> _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<ISequentialOutStream> _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<CCoderStreamsInfo> Coders;
CRecordVector<CBond> Bonds;
CRecordVector<UInt32> 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<UInt32> Coder_to_Stream;
CRecordVector<UInt32> 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<ICompressCoder> Coder;
CMyComPtr<ICompressCoder2> Coder2;
UInt32 NumStreams;
bool Finish;
UInt64 UnpackSize;
const UInt64 *UnpackSizePointer;
CRecordVector<UInt64> PackSizes;
CRecordVector<const UInt64 *> 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<IUnknown> 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<CCoderST> _coders;
CObjectVector<CStBinderStream> _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<ISequentialInStream*> InStreamPointers;
CRecordVector<ISequentialOutStream*> OutStreamPointers;
private:
virtual void Execute() Z7_override;
public:
bool EncodeMode;
HRESULT Result;
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > 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<CStreamBinder> _streamBinders;
HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
HRESULT ReturnIfError(HRESULT code);
// virtual ~CMixerMT() {}
public:
CObjectVector<CCoderMT> _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