1045 lines
24 KiB
C++
1045 lines
24 KiB
C++
// CoderMixer2.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "CoderMixer2.h"
|
|
|
|
#ifdef USE_MIXER_ST
|
|
|
|
STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)
|
|
{
|
|
UInt32 realProcessed = 0;
|
|
HRESULT result = S_OK;
|
|
if (_stream)
|
|
result = _stream->Read(data, size, &realProcessed);
|
|
_size += realProcessed;
|
|
if (size != 0 && realProcessed == 0)
|
|
_wasFinished = true;
|
|
if (processedSize)
|
|
*processedSize = realProcessed;
|
|
return result;
|
|
}
|
|
|
|
|
|
STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
|
{
|
|
HRESULT result = S_OK;
|
|
if (_stream)
|
|
result = _stream->Write(data, size, &size);
|
|
_size += size;
|
|
if (processedSize)
|
|
*processedSize = size;
|
|
return result;
|
|
}
|
|
|
|
STDMETHODIMP COutStreamCalcSize::OutStreamFinish()
|
|
{
|
|
HRESULT result = S_OK;
|
|
if (_stream)
|
|
{
|
|
CMyComPtr<IOutStreamFinish> outStreamFinish;
|
|
_stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish);
|
|
if (outStreamFinish)
|
|
result = outStreamFinish->OutStreamFinish();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace NCoderMixer2 {
|
|
|
|
static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
|
|
{
|
|
v.ClearAndSetSize(size);
|
|
bool *p = &v[0];
|
|
for (unsigned i = 0; i < size; i++)
|
|
p[i] = false;
|
|
}
|
|
|
|
class CBondsChecks
|
|
{
|
|
CBoolVector _coderUsed;
|
|
|
|
bool Init();
|
|
bool CheckCoder(unsigned coderIndex);
|
|
public:
|
|
const CBindInfo *BindInfo;
|
|
|
|
bool Check();
|
|
};
|
|
|
|
bool CBondsChecks::CheckCoder(unsigned coderIndex)
|
|
{
|
|
const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex];
|
|
|
|
if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex])
|
|
return false;
|
|
_coderUsed[coderIndex] = true;
|
|
|
|
UInt32 start = BindInfo->Coder_to_Stream[coderIndex];
|
|
|
|
for (unsigned i = 0; i < coder.NumStreams; i++)
|
|
{
|
|
UInt32 ind = start + i;
|
|
|
|
if (BindInfo->IsStream_in_PackStreams(ind))
|
|
continue;
|
|
|
|
int bond = BindInfo->FindBond_for_PackStream(ind);
|
|
if (bond < 0)
|
|
return false;
|
|
if (!CheckCoder(BindInfo->Bonds[bond].UnpackIndex))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CBondsChecks::Check()
|
|
{
|
|
BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size());
|
|
|
|
if (!CheckCoder(BindInfo->UnpackCoder))
|
|
return false;
|
|
|
|
FOR_VECTOR(i, _coderUsed)
|
|
if (!_coderUsed[i])
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void CBindInfo::ClearMaps()
|
|
{
|
|
Coder_to_Stream.Clear();
|
|
Stream_to_Coder.Clear();
|
|
}
|
|
|
|
bool CBindInfo::CalcMapsAndCheck()
|
|
{
|
|
ClearMaps();
|
|
|
|
UInt32 numStreams = 0;
|
|
|
|
if (Coders.Size() == 0)
|
|
return false;
|
|
if (Coders.Size() - 1 != Bonds.Size())
|
|
return false;
|
|
|
|
FOR_VECTOR(i, Coders)
|
|
{
|
|
Coder_to_Stream.Add(numStreams);
|
|
|
|
const CCoderStreamsInfo &c = Coders[i];
|
|
|
|
for (unsigned j = 0; j < c.NumStreams; j++)
|
|
Stream_to_Coder.Add(i);
|
|
|
|
numStreams += c.NumStreams;
|
|
}
|
|
|
|
if (numStreams != GetNum_Bonds_and_PackStreams())
|
|
return false;
|
|
|
|
CBondsChecks bc;
|
|
bc.BindInfo = this;
|
|
return bc.Check();
|
|
}
|
|
|
|
|
|
void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes)
|
|
{
|
|
if (unpackSize)
|
|
{
|
|
UnpackSize = *unpackSize;
|
|
UnpackSizePointer = &UnpackSize;
|
|
}
|
|
else
|
|
{
|
|
UnpackSize = 0;
|
|
UnpackSizePointer = NULL;
|
|
}
|
|
|
|
PackSizes.ClearAndSetSize((unsigned)NumStreams);
|
|
PackSizePointers.ClearAndSetSize((unsigned)NumStreams);
|
|
|
|
for (unsigned i = 0; i < NumStreams; i++)
|
|
{
|
|
if (packSizes && packSizes[i])
|
|
{
|
|
PackSizes[i] = *(packSizes[i]);
|
|
PackSizePointers[i] = &PackSizes[i];
|
|
}
|
|
else
|
|
{
|
|
PackSizes[i] = 0;
|
|
PackSizePointers[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex)
|
|
{
|
|
if (coderIndex == _bi.UnpackCoder)
|
|
return true;
|
|
|
|
int bond = _bi.FindBond_for_UnpackStream(coderIndex);
|
|
if (bond < 0)
|
|
throw 20150213;
|
|
|
|
/*
|
|
UInt32 coderIndex, coderStreamIndex;
|
|
_bi.GetCoder_for_Stream(_bi.Bonds[bond].PackIndex, coderIndex, coderStreamIndex);
|
|
*/
|
|
UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[bond].PackIndex];
|
|
|
|
if (!IsFilter_Vector[nextCoder])
|
|
return false;
|
|
|
|
return Is_UnpackSize_Correct_for_Coder(nextCoder);
|
|
}
|
|
|
|
bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex)
|
|
{
|
|
if (_bi.IsStream_in_PackStreams(streamIndex))
|
|
return true;
|
|
|
|
int bond = _bi.FindBond_for_PackStream(streamIndex);
|
|
if (bond < 0)
|
|
throw 20150213;
|
|
|
|
UInt32 nextCoder = _bi.Bonds[bond].UnpackIndex;
|
|
|
|
if (!IsFilter_Vector[nextCoder])
|
|
return false;
|
|
|
|
return Is_PackSize_Correct_for_Coder(nextCoder);
|
|
}
|
|
|
|
bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex)
|
|
{
|
|
UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
|
|
UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
|
|
for (UInt32 i = 0; i < numStreams; i++)
|
|
if (!Is_PackSize_Correct_for_Stream(startIndex + i))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex)
|
|
{
|
|
if (IsExternal_Vector[coderIndex])
|
|
return true;
|
|
UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
|
|
UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
|
|
for (UInt32 i = 0; i < numStreams; i++)
|
|
{
|
|
UInt32 si = startIndex + i;
|
|
if (_bi.IsStream_in_PackStreams(si))
|
|
continue;
|
|
|
|
int bond = _bi.FindBond_for_PackStream(si);
|
|
if (bond < 0)
|
|
throw 20150213;
|
|
|
|
if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[bond].UnpackIndex))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef USE_MIXER_ST
|
|
|
|
CMixerST::CMixerST(bool encodeMode):
|
|
CMixer(encodeMode)
|
|
{}
|
|
|
|
CMixerST::~CMixerST() {}
|
|
|
|
void CMixerST::AddCoder(const CCreatedCoder &cod)
|
|
{
|
|
IsFilter_Vector.Add(cod.IsFilter);
|
|
IsExternal_Vector.Add(cod.IsExternal);
|
|
// const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
|
|
CCoderST &c2 = _coders.AddNew();
|
|
c2.NumStreams = cod.NumStreams;
|
|
c2.Coder = cod.Coder;
|
|
c2.Coder2 = cod.Coder2;
|
|
|
|
/*
|
|
if (isFilter)
|
|
{
|
|
c2.CanRead = true;
|
|
c2.CanWrite = true;
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2);
|
|
{
|
|
CMyComPtr<ISequentialInStream> s;
|
|
unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
|
|
c2.CanRead = (s != NULL);
|
|
}
|
|
{
|
|
CMyComPtr<ISequentialOutStream> s;
|
|
unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
|
|
c2.CanWrite = (s != NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
CCoder &CMixerST::GetCoder(unsigned index)
|
|
{
|
|
return _coders[index];
|
|
}
|
|
|
|
void CMixerST::ReInit() {}
|
|
|
|
HRESULT CMixerST::GetInStream2(
|
|
ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
|
UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
|
|
{
|
|
UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
|
|
|
|
if (EncodeMode)
|
|
{
|
|
_bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
|
|
if (coderStreamIndex != 0)
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
const CCoder &coder = _coders[coderIndex];
|
|
|
|
CMyComPtr<ISequentialInStream> seqInStream;
|
|
coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
|
|
if (!seqInStream)
|
|
return E_NOTIMPL;
|
|
|
|
UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
|
|
UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
|
|
|
|
bool isSet = false;
|
|
|
|
if (numInStreams == 1)
|
|
{
|
|
CMyComPtr<ICompressSetInStream> setStream;
|
|
coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
|
|
if (setStream)
|
|
{
|
|
CMyComPtr<ISequentialInStream> seqInStream2;
|
|
RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
|
|
RINOK(setStream->SetInStream(seqInStream2));
|
|
isSet = true;
|
|
}
|
|
}
|
|
|
|
if (!isSet && numInStreams != 0)
|
|
{
|
|
CMyComPtr<ICompressSetInStream2> setStream2;
|
|
coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
|
|
if (!setStream2)
|
|
return E_NOTIMPL;
|
|
|
|
for (UInt32 i = 0; i < numInStreams; i++)
|
|
{
|
|
CMyComPtr<ISequentialInStream> seqInStream2;
|
|
RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
|
|
RINOK(setStream2->SetInStream2(i, seqInStream2));
|
|
}
|
|
}
|
|
|
|
*inStreamRes = seqInStream.Detach();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CMixerST::GetInStream(
|
|
ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
|
UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
|
|
{
|
|
CMyComPtr<ISequentialInStream> seqInStream;
|
|
|
|
{
|
|
int index = -1;
|
|
if (EncodeMode)
|
|
{
|
|
if (_bi.UnpackCoder == inStreamIndex)
|
|
index = 0;
|
|
}
|
|
else
|
|
index = _bi.FindStream_in_PackStreams(inStreamIndex);
|
|
|
|
if (index >= 0)
|
|
{
|
|
seqInStream = inStreams[(unsigned)index];
|
|
*inStreamRes = seqInStream.Detach();
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
int bond = FindBond_for_Stream(
|
|
true, // forInputStream
|
|
inStreamIndex);
|
|
if (bond < 0)
|
|
return E_INVALIDARG;
|
|
|
|
RINOK(GetInStream2(inStreams, /* inSizes, */
|
|
_bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
|
|
|
|
while (_binderStreams.Size() <= (unsigned)bond)
|
|
_binderStreams.AddNew();
|
|
CStBinderStream &bs = _binderStreams[bond];
|
|
|
|
if (bs.StreamRef || bs.InStreamSpec)
|
|
return E_NOTIMPL;
|
|
|
|
CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
|
|
bs.StreamRef = spec;
|
|
bs.InStreamSpec = spec;
|
|
|
|
spec->SetStream(seqInStream);
|
|
spec->Init();
|
|
|
|
seqInStream = bs.InStreamSpec;
|
|
|
|
*inStreamRes = seqInStream.Detach();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CMixerST::GetOutStream(
|
|
ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
|
|
UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
|
|
{
|
|
CMyComPtr<ISequentialOutStream> seqOutStream;
|
|
|
|
{
|
|
int index = -1;
|
|
if (!EncodeMode)
|
|
{
|
|
if (_bi.UnpackCoder == outStreamIndex)
|
|
index = 0;
|
|
}
|
|
else
|
|
index = _bi.FindStream_in_PackStreams(outStreamIndex);
|
|
|
|
if (index >= 0)
|
|
{
|
|
seqOutStream = outStreams[(unsigned)index];
|
|
*outStreamRes = seqOutStream.Detach();
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
int bond = FindBond_for_Stream(
|
|
false, // forInputStream
|
|
outStreamIndex);
|
|
if (bond < 0)
|
|
return E_INVALIDARG;
|
|
|
|
UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
|
|
|
|
UInt32 coderIndex = inStreamIndex;
|
|
UInt32 coderStreamIndex = 0;
|
|
|
|
if (!EncodeMode)
|
|
_bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
|
|
|
|
CCoder &coder = _coders[coderIndex];
|
|
|
|
/*
|
|
if (!coder.Coder)
|
|
return E_NOTIMPL;
|
|
*/
|
|
|
|
coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
|
|
if (!seqOutStream)
|
|
return E_NOTIMPL;
|
|
|
|
UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
|
|
UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
|
|
|
|
bool isSet = false;
|
|
|
|
if (numOutStreams == 1)
|
|
{
|
|
CMyComPtr<ICompressSetOutStream> setOutStream;
|
|
coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
|
|
if (setOutStream)
|
|
{
|
|
CMyComPtr<ISequentialOutStream> seqOutStream2;
|
|
RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
|
|
RINOK(setOutStream->SetOutStream(seqOutStream2));
|
|
isSet = true;
|
|
}
|
|
}
|
|
|
|
if (!isSet && numOutStreams != 0)
|
|
{
|
|
return E_NOTIMPL;
|
|
/*
|
|
CMyComPtr<ICompressSetOutStream2> setStream2;
|
|
coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
|
|
if (!setStream2)
|
|
return E_NOTIMPL;
|
|
for (UInt32 i = 0; i < numOutStreams; i++)
|
|
{
|
|
CMyComPtr<ISequentialOutStream> seqOutStream2;
|
|
RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
|
|
RINOK(setStream2->SetOutStream2(i, seqOutStream2));
|
|
}
|
|
*/
|
|
}
|
|
|
|
while (_binderStreams.Size() <= (unsigned)bond)
|
|
_binderStreams.AddNew();
|
|
CStBinderStream &bs = _binderStreams[bond];
|
|
|
|
if (bs.StreamRef || bs.OutStreamSpec)
|
|
return E_NOTIMPL;
|
|
|
|
COutStreamCalcSize *spec = new COutStreamCalcSize;
|
|
bs.StreamRef = (ISequentialOutStream *)spec;
|
|
bs.OutStreamSpec = spec;
|
|
|
|
spec->SetStream(seqOutStream);
|
|
spec->Init();
|
|
|
|
seqOutStream = bs.OutStreamSpec;
|
|
|
|
*outStreamRes = seqOutStream.Detach();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
static HRESULT GetError(HRESULT res, HRESULT res2)
|
|
{
|
|
if (res == res2)
|
|
return res;
|
|
if (res == S_OK)
|
|
return res2;
|
|
if (res == k_My_HRESULT_WritingWasCut)
|
|
{
|
|
if (res2 != S_OK)
|
|
return res2;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
|
|
HRESULT CMixerST::FinishStream(UInt32 streamIndex)
|
|
{
|
|
{
|
|
int index = -1;
|
|
if (!EncodeMode)
|
|
{
|
|
if (_bi.UnpackCoder == streamIndex)
|
|
index = 0;
|
|
}
|
|
else
|
|
index = _bi.FindStream_in_PackStreams(streamIndex);
|
|
|
|
if (index >= 0)
|
|
return S_OK;
|
|
}
|
|
|
|
int bond = FindBond_for_Stream(
|
|
false, // forInputStream
|
|
streamIndex);
|
|
if (bond < 0)
|
|
return E_INVALIDARG;
|
|
|
|
UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
|
|
|
|
UInt32 coderIndex = inStreamIndex;
|
|
UInt32 coderStreamIndex = 0;
|
|
if (!EncodeMode)
|
|
_bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
|
|
|
|
CCoder &coder = _coders[coderIndex];
|
|
CMyComPtr<IOutStreamFinish> finish;
|
|
coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish);
|
|
HRESULT res = S_OK;
|
|
if (finish)
|
|
{
|
|
res = finish->OutStreamFinish();
|
|
}
|
|
return GetError(res, FinishCoder(coderIndex));
|
|
}
|
|
|
|
|
|
HRESULT CMixerST::FinishCoder(UInt32 coderIndex)
|
|
{
|
|
CCoder &coder = _coders[coderIndex];
|
|
|
|
UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
|
|
UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
|
|
|
|
HRESULT res = S_OK;
|
|
for (unsigned i = 0; i < numOutStreams; i++)
|
|
res = GetError(res, FinishStream(startIndex + i));
|
|
return res;
|
|
}
|
|
|
|
|
|
void CMixerST::SelectMainCoder(bool useFirst)
|
|
{
|
|
unsigned ci = _bi.UnpackCoder;
|
|
|
|
int firstNonFilter = -1;
|
|
int firstAllowed = ci;
|
|
|
|
for (;;)
|
|
{
|
|
const CCoderST &coder = _coders[ci];
|
|
// break;
|
|
|
|
if (ci != _bi.UnpackCoder)
|
|
if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
|
|
{
|
|
firstAllowed = ci;
|
|
firstNonFilter = -2;
|
|
}
|
|
|
|
if (coder.NumStreams != 1)
|
|
break;
|
|
|
|
UInt32 st = _bi.Coder_to_Stream[ci];
|
|
if (_bi.IsStream_in_PackStreams(st))
|
|
break;
|
|
int bond = _bi.FindBond_for_PackStream(st);
|
|
if (bond < 0)
|
|
throw 20150213;
|
|
|
|
if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
|
|
break;
|
|
|
|
if (firstNonFilter == -1 && !IsFilter_Vector[ci])
|
|
firstNonFilter = ci;
|
|
|
|
ci = _bi.Bonds[bond].UnpackIndex;
|
|
}
|
|
|
|
if (useFirst)
|
|
ci = firstAllowed;
|
|
else if (firstNonFilter >= 0)
|
|
ci = firstNonFilter;
|
|
|
|
MainCoderIndex = ci;
|
|
}
|
|
|
|
|
|
HRESULT CMixerST::Code(
|
|
ISequentialInStream * const *inStreams,
|
|
ISequentialOutStream * const *outStreams,
|
|
ICompressProgressInfo *progress)
|
|
{
|
|
_binderStreams.Clear();
|
|
unsigned ci = MainCoderIndex;
|
|
|
|
const CCoder &mainCoder = _coders[MainCoderIndex];
|
|
|
|
CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
|
|
CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
|
|
|
|
UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams;
|
|
UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
|
|
|
|
UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci];
|
|
UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
|
|
|
|
UInt32 i;
|
|
|
|
for (i = 0; i < numInStreams; i++)
|
|
{
|
|
CMyComPtr<ISequentialInStream> seqInStream;
|
|
RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
|
|
seqInStreams.Add(seqInStream);
|
|
}
|
|
|
|
for (i = 0; i < numOutStreams; i++)
|
|
{
|
|
CMyComPtr<ISequentialOutStream> seqOutStream;
|
|
RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
|
|
seqOutStreams.Add(seqOutStream);
|
|
}
|
|
|
|
CRecordVector< ISequentialInStream * > seqInStreamsSpec;
|
|
CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
|
|
|
|
for (i = 0; i < numInStreams; i++)
|
|
seqInStreamsSpec.Add(seqInStreams[i]);
|
|
for (i = 0; i < numOutStreams; i++)
|
|
seqOutStreamsSpec.Add(seqOutStreams[i]);
|
|
|
|
for (i = 0; i < _coders.Size(); i++)
|
|
{
|
|
if (i == ci)
|
|
continue;
|
|
|
|
CCoder &coder = _coders[i];
|
|
|
|
if (EncodeMode)
|
|
{
|
|
CMyComPtr<ICompressInitEncoder> initEncoder;
|
|
coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder);
|
|
if (initEncoder)
|
|
RINOK(initEncoder->InitEncoder());
|
|
}
|
|
else
|
|
{
|
|
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
|
|
coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
|
|
if (setOutStreamSize)
|
|
RINOK(setOutStreamSize->SetOutStreamSize(
|
|
EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
|
|
}
|
|
}
|
|
|
|
const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
|
|
const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
|
|
|
|
HRESULT res;
|
|
if (mainCoder.Coder)
|
|
{
|
|
res = mainCoder.Coder->Code(
|
|
seqInStreamsSpec[0], seqOutStreamsSpec[0],
|
|
isSizes2[0], outSizes2[0],
|
|
progress);
|
|
}
|
|
else
|
|
{
|
|
res = mainCoder.Coder2->Code(
|
|
&seqInStreamsSpec.Front(), isSizes2, numInStreams,
|
|
&seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
|
|
progress);
|
|
}
|
|
|
|
if (res == k_My_HRESULT_WritingWasCut)
|
|
res = S_OK;
|
|
|
|
if (res == S_OK || res == S_FALSE)
|
|
{
|
|
res = GetError(res, FinishCoder(ci));
|
|
}
|
|
|
|
for (i = 0; i < _binderStreams.Size(); i++)
|
|
{
|
|
const CStBinderStream &bs = _binderStreams[i];
|
|
if (bs.InStreamSpec)
|
|
bs.InStreamSpec->ReleaseStream();
|
|
else
|
|
bs.OutStreamSpec->ReleaseStream();
|
|
}
|
|
|
|
if (res == k_My_HRESULT_WritingWasCut)
|
|
res = S_OK;
|
|
return res;
|
|
}
|
|
|
|
|
|
HRESULT CMixerST::GetMainUnpackStream(
|
|
ISequentialInStream * const *inStreams,
|
|
ISequentialInStream **inStreamRes)
|
|
{
|
|
CMyComPtr<ISequentialInStream> seqInStream;
|
|
|
|
RINOK(GetInStream2(inStreams, /* inSizes, */
|
|
_bi.UnpackCoder, &seqInStream))
|
|
|
|
FOR_VECTOR (i, _coders)
|
|
{
|
|
CCoder &coder = _coders[i];
|
|
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
|
|
coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
|
|
if (setOutStreamSize)
|
|
{
|
|
RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
|
|
}
|
|
}
|
|
|
|
*inStreamRes = seqInStream.Detach();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
|
|
{
|
|
const CStBinderStream &bs = _binderStreams[bondIndex];
|
|
if (bs.InStreamSpec)
|
|
return bs.InStreamSpec->GetSize();
|
|
return bs.OutStreamSpec->GetSize();
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_MIXER_MT
|
|
|
|
|
|
void CCoderMT::Execute()
|
|
{
|
|
try
|
|
{
|
|
Code(NULL);
|
|
}
|
|
catch(...)
|
|
{
|
|
Result = E_FAIL;
|
|
}
|
|
}
|
|
|
|
void CCoderMT::Code(ICompressProgressInfo *progress)
|
|
{
|
|
unsigned numInStreams = EncodeMode ? 1 : NumStreams;
|
|
unsigned numOutStreams = EncodeMode ? NumStreams : 1;
|
|
|
|
InStreamPointers.ClearAndReserve(numInStreams);
|
|
OutStreamPointers.ClearAndReserve(numOutStreams);
|
|
|
|
unsigned i;
|
|
|
|
for (i = 0; i < numInStreams; i++)
|
|
InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
|
|
|
|
for (i = 0; i < numOutStreams; i++)
|
|
OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
|
|
|
|
// we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
|
|
/*
|
|
if (UnpackSizePointer)
|
|
UnpackSizePointer = &UnpackSize;
|
|
for (i = 0; i < NumStreams; i++)
|
|
if (PackSizePointers[i])
|
|
PackSizePointers[i] = &PackSizes[i];
|
|
*/
|
|
|
|
CReleaser releaser(*this);
|
|
|
|
if (Coder)
|
|
Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
|
|
EncodeMode ? UnpackSizePointer : PackSizePointers[0],
|
|
EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
|
|
progress);
|
|
else
|
|
Result = Coder2->Code(
|
|
&InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
|
|
&OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
|
|
progress);
|
|
}
|
|
|
|
HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
|
|
{
|
|
CMixer::SetBindInfo(bindInfo);
|
|
|
|
_streamBinders.Clear();
|
|
FOR_VECTOR (i, _bi.Bonds)
|
|
{
|
|
RINOK(_streamBinders.AddNew().CreateEvents());
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
void CMixerMT::AddCoder(const CCreatedCoder &cod)
|
|
{
|
|
IsFilter_Vector.Add(cod.IsFilter);
|
|
IsExternal_Vector.Add(cod.IsExternal);
|
|
// const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
|
|
CCoderMT &c2 = _coders.AddNew();
|
|
c2.NumStreams = cod.NumStreams;
|
|
c2.Coder = cod.Coder;
|
|
c2.Coder2 = cod.Coder2;
|
|
c2.EncodeMode = EncodeMode;
|
|
}
|
|
|
|
CCoder &CMixerMT::GetCoder(unsigned index)
|
|
{
|
|
return _coders[index];
|
|
}
|
|
|
|
void CMixerMT::ReInit()
|
|
{
|
|
FOR_VECTOR (i, _streamBinders)
|
|
_streamBinders[i].ReInit();
|
|
}
|
|
|
|
void CMixerMT::SelectMainCoder(bool useFirst)
|
|
{
|
|
unsigned ci = _bi.UnpackCoder;
|
|
|
|
if (!useFirst)
|
|
for (;;)
|
|
{
|
|
if (_coders[ci].NumStreams != 1)
|
|
break;
|
|
if (!IsFilter_Vector[ci])
|
|
break;
|
|
|
|
UInt32 st = _bi.Coder_to_Stream[ci];
|
|
if (_bi.IsStream_in_PackStreams(st))
|
|
break;
|
|
int bond = _bi.FindBond_for_PackStream(st);
|
|
if (bond < 0)
|
|
throw 20150213;
|
|
ci = _bi.Bonds[bond].UnpackIndex;
|
|
}
|
|
|
|
MainCoderIndex = ci;
|
|
}
|
|
|
|
HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
|
|
{
|
|
unsigned i;
|
|
|
|
for (i = 0; i < _coders.Size(); i++)
|
|
{
|
|
CCoderMT &coderInfo = _coders[i];
|
|
const CCoderStreamsInfo &csi = _bi.Coders[i];
|
|
|
|
UInt32 j;
|
|
|
|
unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
|
|
unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
|
|
|
|
coderInfo.InStreams.Clear();
|
|
for (j = 0; j < numInStreams; j++)
|
|
coderInfo.InStreams.AddNew();
|
|
|
|
coderInfo.OutStreams.Clear();
|
|
for (j = 0; j < numOutStreams; j++)
|
|
coderInfo.OutStreams.AddNew();
|
|
}
|
|
|
|
for (i = 0; i < _bi.Bonds.Size(); i++)
|
|
{
|
|
const CBond &bond = _bi.Bonds[i];
|
|
|
|
UInt32 inCoderIndex, inCoderStreamIndex;
|
|
UInt32 outCoderIndex, outCoderStreamIndex;
|
|
|
|
{
|
|
UInt32 coderIndex, coderStreamIndex;
|
|
_bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
|
|
|
|
inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
|
|
outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
|
|
|
|
inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
|
|
outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
|
|
}
|
|
|
|
_streamBinders[i].CreateStreams(
|
|
&_coders[inCoderIndex].InStreams[inCoderStreamIndex],
|
|
&_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
|
|
|
|
CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
|
|
_coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
|
|
_coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
|
|
if (inSetSize && outSetSize)
|
|
{
|
|
const UInt32 kBufSize = 1 << 19;
|
|
inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
|
|
outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
|
|
}
|
|
}
|
|
|
|
{
|
|
CCoderMT &cod = _coders[_bi.UnpackCoder];
|
|
if (EncodeMode)
|
|
cod.InStreams[0] = inStreams[0];
|
|
else
|
|
cod.OutStreams[0] = outStreams[0];
|
|
}
|
|
|
|
for (i = 0; i < _bi.PackStreams.Size(); i++)
|
|
{
|
|
UInt32 coderIndex, coderStreamIndex;
|
|
_bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
|
|
CCoderMT &cod = _coders[coderIndex];
|
|
if (EncodeMode)
|
|
cod.OutStreams[coderStreamIndex] = outStreams[i];
|
|
else
|
|
cod.InStreams[coderStreamIndex] = inStreams[i];
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CMixerMT::ReturnIfError(HRESULT code)
|
|
{
|
|
FOR_VECTOR (i, _coders)
|
|
if (_coders[i].Result == code)
|
|
return code;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CMixerMT::Code(
|
|
ISequentialInStream * const *inStreams,
|
|
ISequentialOutStream * const *outStreams,
|
|
ICompressProgressInfo *progress)
|
|
{
|
|
Init(inStreams, outStreams);
|
|
|
|
unsigned i;
|
|
for (i = 0; i < _coders.Size(); i++)
|
|
if (i != MainCoderIndex)
|
|
{
|
|
RINOK(_coders[i].Create());
|
|
}
|
|
|
|
for (i = 0; i < _coders.Size(); i++)
|
|
if (i != MainCoderIndex)
|
|
_coders[i].Start();
|
|
|
|
_coders[MainCoderIndex].Code(progress);
|
|
|
|
for (i = 0; i < _coders.Size(); i++)
|
|
if (i != MainCoderIndex)
|
|
_coders[i].WaitExecuteFinish();
|
|
|
|
RINOK(ReturnIfError(E_ABORT));
|
|
RINOK(ReturnIfError(E_OUTOFMEMORY));
|
|
|
|
for (i = 0; i < _coders.Size(); i++)
|
|
{
|
|
HRESULT result = _coders[i].Result;
|
|
if (result != S_OK
|
|
&& result != k_My_HRESULT_WritingWasCut
|
|
&& result != S_FALSE
|
|
&& result != E_FAIL)
|
|
return result;
|
|
}
|
|
|
|
RINOK(ReturnIfError(S_FALSE));
|
|
|
|
for (i = 0; i < _coders.Size(); i++)
|
|
{
|
|
HRESULT result = _coders[i].Result;
|
|
if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
|
|
return result;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
|
|
{
|
|
return _streamBinders[bondIndex].ProcessedSize;
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|