| // CoderMixer2.cpp |
| |
| #include "StdAfx.h" |
| |
| #include "CoderMixer2.h" |
| |
| #ifdef USE_MIXER_ST |
| |
| Z7_COM7F_IMF(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; |
| } |
| |
| |
| Z7_COM7F_IMF(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; |
| } |
| |
| Z7_COM7F_IMF(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); |
| if (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; |
| |
| const 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; |
| |
| const int bond = BindInfo->FindBond_for_PackStream(ind); |
| if (bond < 0) |
| return false; |
| if (!CheckCoder(BindInfo->Bonds[(unsigned)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; |
| |
| const int bond = _bi.FindBond_for_UnpackStream(coderIndex); |
| if (bond < 0) |
| throw 20150213; |
| |
| /* |
| UInt32 coderIndex, coderStreamIndex; |
| _bi.GetCoder_for_Stream(_bi.Bonds[(unsigned)bond].PackIndex, coderIndex, coderStreamIndex); |
| */ |
| const UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[(unsigned)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; |
| |
| const int bond = _bi.FindBond_for_PackStream(streamIndex); |
| if (bond < 0) |
| throw 20150213; |
| |
| const UInt32 nextCoder = _bi.Bonds[(unsigned)bond].UnpackIndex; |
| |
| if (!IsFilter_Vector[nextCoder]) |
| return false; |
| |
| return Is_PackSize_Correct_for_Coder(nextCoder); |
| } |
| |
| bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex) |
| { |
| const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; |
| const 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; |
| const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; |
| const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; |
| for (UInt32 i = 0; i < numStreams; i++) |
| { |
| const UInt32 si = startIndex + i; |
| if (_bi.IsStream_in_PackStreams(si)) |
| continue; |
| |
| const int bond = _bi.FindBond_for_PackStream(si); |
| if (bond < 0) |
| throw 20150213; |
| |
| if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[(unsigned)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); |
| { |
| Z7_DECL_CMyComPtr_QI_FROM(ISequentialInStream, s, unk) |
| c2.CanRead = (s != NULL); |
| } |
| { |
| Z7_DECL_CMyComPtr_QI_FROM(ISequentialOutStream, s, unk) |
| c2.CanWrite = (s != NULL); |
| } |
| } |
| } |
| |
| CCoder &CMixerST::GetCoder(unsigned index) |
| { |
| return _coders[index]; |
| } |
| |
| HRESULT CMixerST::ReInit2() { return S_OK; } |
| |
| 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; |
| |
| const UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams; |
| const 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; |
| } |
| } |
| |
| const int bond = FindBond_for_Stream( |
| true, // forInputStream |
| inStreamIndex); |
| if (bond < 0) |
| return E_INVALIDARG; |
| |
| RINOK(GetInStream2(inStreams, /* inSizes, */ |
| _bi.Bonds[(unsigned)bond].Get_OutIndex(EncodeMode), &seqInStream)) |
| |
| while (_binderStreams.Size() <= (unsigned)bond) |
| _binderStreams.AddNew(); |
| CStBinderStream &bs = _binderStreams[(unsigned)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; |
| } |
| } |
| |
| const int bond = FindBond_for_Stream( |
| false, // forInputStream |
| outStreamIndex); |
| if (bond < 0) |
| return E_INVALIDARG; |
| |
| const UInt32 inStreamIndex = _bi.Bonds[(unsigned)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; |
| |
| const UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; |
| const 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[(unsigned)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; |
| } |
| |
| const int bond = FindBond_for_Stream( |
| false, // forInputStream |
| streamIndex); |
| if (bond < 0) |
| return E_INVALIDARG; |
| |
| const UInt32 inStreamIndex = _bi.Bonds[(unsigned)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]; |
| |
| const UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; |
| const 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; |
| unsigned 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; |
| |
| const UInt32 st = _bi.Coder_to_Stream[ci]; |
| if (_bi.IsStream_in_PackStreams(st)) |
| break; |
| const 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 = (int)ci; |
| |
| ci = _bi.Bonds[(unsigned)bond].UnpackIndex; |
| } |
| |
| if (useFirst) |
| ci = firstAllowed; |
| else if (firstNonFilter >= 0) |
| ci = (unsigned)firstNonFilter; |
| |
| MainCoderIndex = ci; |
| } |
| |
| |
| HRESULT CMixerST::Code( |
| ISequentialInStream * const *inStreams, |
| ISequentialOutStream * const *outStreams, |
| ICompressProgressInfo *progress, |
| bool &dataAfterEnd_Error) |
| { |
| // InternalPackSizeError = false; |
| dataAfterEnd_Error = false; |
| |
| _binderStreams.Clear(); |
| const unsigned ci = MainCoderIndex; |
| |
| const CCoder &mainCoder = _coders[MainCoderIndex]; |
| |
| CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams; |
| CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams; |
| |
| const UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams; |
| const UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams; |
| |
| const UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci]; |
| const 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()) |
| _streamBinders.AddNew(); |
| } |
| 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]; |
| } |
| |
| HRESULT CMixerMT::ReInit2() |
| { |
| FOR_VECTOR (i, _streamBinders) |
| { |
| RINOK(_streamBinders[i].Create_ReInit()) |
| } |
| return S_OK; |
| } |
| |
| 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; |
| const int bond = _bi.FindBond_for_PackStream(st); |
| if (bond < 0) |
| throw 20150213; |
| ci = _bi.Bonds[(unsigned)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; |
| |
| const unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams; |
| const 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].CreateStreams2( |
| _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) |
| { |
| const WRes wres = _coders[i].Create(); |
| if (wres != 0) |
| return HRESULT_FROM_WIN32(wres); |
| } |
| |
| for (i = 0; i < _coders.Size(); i++) |
| if (i != MainCoderIndex) |
| { |
| const WRes wres = _coders[i].Start(); |
| if (wres != 0) |
| return HRESULT_FROM_WIN32(wres); |
| } |
| |
| _coders[MainCoderIndex].Code(progress); |
| |
| WRes wres = 0; |
| for (i = 0; i < _coders.Size(); i++) |
| if (i != MainCoderIndex) |
| { |
| WRes wres2 = _coders[i].WaitExecuteFinish(); |
| if (wres == 0) |
| wres = wres2; |
| } |
| if (wres != 0) |
| return HRESULT_FROM_WIN32(wres); |
| |
| 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 |
| |
| } |