Source code

Revision control

Copy as Markdown

Other Tools

// 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;↩
}↩
HRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const
{↩
if (Coder)↩
{↩
if (PackSizePointers.IsEmpty() || !PackSizePointers[0])↩
return S_OK;↩
CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;↩
Coder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);↩
// if (!getInStreamProcessedSize) return E_FAIL;↩
if (getInStreamProcessedSize)↩
{↩
UInt64 processed;↩
RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed));↩
if (processed != (UInt64)(Int64)-1)↩
{↩
const UInt64 size = PackSizes[0];↩
if (processed < size && Finish)↩
dataAfterEnd_Error = true;↩
if (processed > size)↩
{↩
// InternalPackSizeError = true;↩
// return S_FALSE;↩
}↩
}↩
}↩
}↩
else if (Coder2)↩
{↩
CMyComPtr<ICompressGetInStreamProcessedSize2> getInStreamProcessedSize2;↩
Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2);↩
FOR_VECTOR (i, PackSizePointers)↩
{↩
if (!PackSizePointers[i])↩
continue;↩
UInt64 processed;↩
RINOK(getInStreamProcessedSize2->GetInStreamProcessedSize2(i, &processed));↩
if (processed != (UInt64)(Int64)-1)↩
{↩
const UInt64 size = PackSizes[i];↩
if (processed < size && Finish)↩
dataAfterEnd_Error = true;↩
else if (processed > size)↩
{↩
// InternalPackSizeError = true;↩
// return S_FALSE;↩
}↩
}↩
}↩
}↩
return S_OK;↩
}↩
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, bool finish)↩
{↩
Finish = finish;↩
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,↩
bool &dataAfterEnd_Error)↩
{↩
// InternalPackSizeError = false;↩
dataAfterEnd_Error = false;↩
_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;↩
if (res != S_OK)↩
return res;↩
for (i = 0; i < _coders.Size(); i++)↩
{↩
RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */));↩
}↩
return S_OK;↩
}↩
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,↩
bool &dataAfterEnd_Error)↩
{↩
// InternalPackSizeError = false;↩
dataAfterEnd_Error = false;↩
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;↩
}↩
for (i = 0; i < _coders.Size(); i++)↩
{↩
RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */));↩
}↩
return S_OK;↩
}↩
UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
{↩
return _streamBinders[bondIndex].ProcessedSize;↩
}↩
#endif
}↩