Exemple #1
0
HRESULT CEncoder::Encode(
    DECL_EXTERNAL_CODECS_LOC_VARS
    ISequentialInStream *inStream,
    const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
    CFolder &folderItem,
    ISequentialOutStream *outStream,
    CRecordVector<UInt64> &packSizes,
    ICompressProgressInfo *compressProgress)
{
    RINOK(EncoderConstr());

    if (_mixerCoderSpec == NULL)
    {
        RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
    }
    _mixerCoderSpec->ReInit();
    // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);

    CObjectVector<CInOutTempBuffer> inOutTempBuffers;
    CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
    CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
    int numMethods = _bindInfo.Coders.Size();
    int i;
    for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
    {
        inOutTempBuffers.Add(CInOutTempBuffer());
        inOutTempBuffers.Back().Create();
        inOutTempBuffers.Back().InitWriting();
    }
    for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
    {
        CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp;
        CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
        tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
        tempBuffers.Add(tempBuffer);
        tempBufferSpecs.Add(tempBufferSpec);
    }

    for (i = 0; i < numMethods; i++)
        _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);

    if (_bindInfo.InStreams.IsEmpty())
        return E_FAIL;
    UInt32 mainCoderIndex, mainStreamIndex;
    _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);

    if (inStreamSize != NULL)
    {
        CRecordVector<const UInt64 *> sizePointers;
        for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
            if (i == mainStreamIndex)
                sizePointers.Add(inStreamSize);
            else
                sizePointers.Add(NULL);
        _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
    }


    // UInt64 outStreamStartPos;
    // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));

    CSequentialInStreamSizeCount2 *inStreamSizeCountSpec =
        new CSequentialInStreamSizeCount2;
    CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
    CSequentialOutStreamSizeCount *outStreamSizeCountSpec =
        new CSequentialOutStreamSizeCount;
    CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;

    inStreamSizeCountSpec->Init(inStream);
    outStreamSizeCountSpec->SetStream(outStream);
    outStreamSizeCountSpec->Init();

    CRecordVector<ISequentialInStream *> inStreamPointers;
    CRecordVector<ISequentialOutStream *> outStreamPointers;
    inStreamPointers.Add(inStreamSizeCount);
    outStreamPointers.Add(outStreamSizeCount);
    for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
        outStreamPointers.Add(tempBuffers[i - 1]);

    for (i = 0; i < _codersInfo.Size(); i++)
    {
        CCoderInfo &encodingInfo = _codersInfo[i];

        CMyComPtr<ICryptoResetInitVector> resetInitVector;
        _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
        if (resetInitVector != NULL)
        {
            resetInitVector->ResetInitVector();
        }

        CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
        _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
        if (writeCoderProperties != NULL)
        {
            CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
            CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
            outStreamSpec->Init();
            writeCoderProperties->WriteCoderProperties(outStream);
            size_t size = outStreamSpec->GetSize();
            encodingInfo.Props.SetCapacity(size);
            memmove(encodingInfo.Props, outStreamSpec->GetBuffer(), size);
        }
    }

    UInt32 progressIndex = mainCoderIndex;

    for (i = 0; i + 1 < _codersInfo.Size(); i++)
    {
        UInt64 m = _codersInfo[i].MethodID;
        if (m == k_Delta || m == k_BCJ || m == k_BCJ2)
            progressIndex = i + 1;
    }

    _mixerCoderSpec->SetProgressCoderIndex(progressIndex);

    RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
                            &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));

    ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods,
                                    folderItem);

    packSizes.Add(outStreamSizeCountSpec->GetSize());

    for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
    {
        CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
        RINOK(inOutTempBuffer.WriteToStream(outStream));
        packSizes.Add(inOutTempBuffer.GetDataSize());
    }

    for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
    {
        int binder = _bindInfo.FindBinderForInStream(
                         _bindReverseConverter->DestOutToSrcInMap[i]);
        UInt64 streamSize;
        if (binder < 0)
            streamSize = inStreamSizeCountSpec->GetSize();
        else
            streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
        folderItem.UnpackSizes.Add(streamSize);
    }
    for (i = numMethods - 1; i >= 0; i--)
        folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;
    return S_OK;
}