This commit is contained in:
Igor Pavlov
2005-05-30 00:00:00 +00:00
committed by Kornel Lesiński
parent 8c1b5c7b7e
commit 3c510ba80b
926 changed files with 40559 additions and 23519 deletions

View File

@@ -1,7 +1,5 @@
// CodecsPath.h
#pragma once
#ifndef __CODECSPATH_H
#define __CODECSPATH_H

View File

@@ -0,0 +1,31 @@
// CoderLoader.cpp
#include "StdAfx.h"
#include "CoderLoader.h"
#include "FilterCoder.h"
HRESULT CCoderLibrary::CreateCoderSpec(REFGUID clsID, ICompressCoder **coder)
{
HRESULT result = CreateObject(clsID, IID_ICompressCoder, (void **)coder);
if (result == S_OK || result != E_NOINTERFACE)
return result;
CMyComPtr<ICompressFilter> filter;
RINOK(CreateObject(clsID, IID_ICompressFilter, (void **)&filter));
CFilterCoder *filterCoderSpec = new CFilterCoder;
CMyComPtr<ICompressCoder> filterCoder = filterCoderSpec;
filterCoderSpec->Filter = filter;
*coder = filterCoder.Detach();
return S_OK;
}
HRESULT CCoderLibrary::LoadAndCreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder)
{
CCoderLibrary libTemp;
if (!libTemp.Load(filePath))
return GetLastError();
RINOK(libTemp.CreateCoderSpec(clsID, coder));
Attach(libTemp.Detach());
return S_OK;
}

View File

@@ -1,16 +1,14 @@
// CoderLoader.h
#pragma once
#ifndef __CODERLOADER_H
#define __CODERLOADER_H
#include "../../../Common/String.h"
#include "../../../Common/MyCom.h"
#include "../../../Windows/DLL.h"
// #include "../../../Windows/Defs.h"
#include "../../ICoder.h"
typedef UINT32 (WINAPI * CreateObjectPointer)(
typedef UInt32 (WINAPI * CreateObjectPointer)(
const GUID *clsID,
const GUID *interfaceID,
void **outObject);
@@ -18,14 +16,38 @@ typedef UINT32 (WINAPI * CreateObjectPointer)(
class CCoderLibrary: public NWindows::NDLL::CLibrary
{
public:
HRESULT CreateCoder(REFGUID clsID, ICompressCoder **coder)
HRESULT CreateObject(REFGUID clsID, REFGUID iid, void **obj)
{
CreateObjectPointer createObject = (CreateObjectPointer)
GetProcAddress("CreateObject");
GetProcAddress("CreateObject");
if (createObject == NULL)
return GetLastError();
return createObject(&clsID, &IID_ICompressCoder, (void **)coder);
return createObject(&clsID, &iid, obj);
}
HRESULT CreateFilter(REFGUID clsID, ICompressFilter **filter)
{
return CreateObject(clsID, IID_ICompressFilter, (void **)filter);
}
HRESULT CreateCoder(REFGUID clsID, ICompressCoder **coder)
{
return CreateObject(clsID, IID_ICompressCoder, (void **)coder);
}
HRESULT CreateCoderSpec(REFGUID clsID, ICompressCoder **coder);
HRESULT LoadAndCreateFilter(LPCTSTR filePath, REFGUID clsID, ICompressFilter **filter)
{
CCoderLibrary libTemp;
if (!libTemp.Load(filePath))
return GetLastError();
RINOK(libTemp.CreateFilter(clsID, filter));
Attach(libTemp.Detach());
return S_OK;
}
HRESULT LoadAndCreateCoder(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder)
{
CCoderLibrary libTemp;
@@ -35,6 +57,8 @@ public:
Attach(libTemp.Detach());
return S_OK;
}
HRESULT LoadAndCreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder);
HRESULT CreateCoder2(REFGUID clsID, ICompressCoder2 **coder)
{
CreateObjectPointer createObject = (CreateObjectPointer)
@@ -87,6 +111,21 @@ public:
return Pairs[index].Libary.CreateCoder(clsID, coder);
}
HRESULT CreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder)
{
int index = FindPath(filePath);
if (index < 0)
{
CPathToLibraryPair pair;
RINOK(pair.Libary.LoadAndCreateCoderSpec(filePath, clsID, coder));
pair.Path = filePath;
Pairs.Add(pair);
pair.Libary.Detach();
return S_OK;
}
return Pairs[index].Libary.CreateCoderSpec(clsID, coder);
}
HRESULT CreateCoder2(LPCTSTR filePath, REFGUID clsID, ICompressCoder2 **coder)
{
int index = FindPath(filePath);

View File

@@ -1,238 +0,0 @@
// CoderMixer.cpp
#include "StdAfx.h"
#include "CoderMixer.h"
#include "Common/Defs.h"
#include "CrossThreadProgress.h"
using namespace NWindows;
using namespace NSynchronization;
//////////////////////////
// CThreadCoderInfo
void CThreadCoderInfo::CreateEvents()
{
CompressEvent = new CAutoResetEvent(false);
CompressionCompletedEvent = new CAutoResetEvent(false);
}
CThreadCoderInfo::~CThreadCoderInfo()
{
if (CompressEvent != NULL)
delete CompressEvent;
if (CompressionCompletedEvent != NULL)
delete CompressionCompletedEvent;
}
class CCoderInfoFlusher
{
CThreadCoderInfo *m_CoderInfo;
public:
CCoderInfoFlusher(CThreadCoderInfo *coderInfo): m_CoderInfo(coderInfo) {}
~CCoderInfoFlusher()
{
m_CoderInfo->InStream.Release();
m_CoderInfo->OutStream.Release();
m_CoderInfo->CompressionCompletedEvent->Set();
}
};
bool CThreadCoderInfo::WaitAndCode()
{
HANDLE events[2] = { ExitEvent, *CompressEvent };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 0)
return false;
{
CCoderInfoFlusher coderInfoFlusher(this);
Result = Coder->Code(InStream, OutStream,
InSizeAssigned ? &InSizeValue : NULL,
OutSizeAssigned ? &OutSizeValue : NULL,
Progress);
}
return true;
}
DWORD WINAPI CoderThread(void *threadCoderInfo)
{
while(true)
{
if (!((CThreadCoderInfo *)threadCoderInfo)->WaitAndCode())
return 0;
}
}
//////////////////////////
// CCoderMixer
static DWORD WINAPI MainCoderThread(void *threadCoderInfo)
{
while(true)
{
if (!((CCoderMixer *)threadCoderInfo)->MyCode())
return 0;
}
}
CCoderMixer::CCoderMixer()
{
if (!m_MainThread.Create(MainCoderThread, this))
throw 271825;
}
CCoderMixer::~CCoderMixer()
{
ExitEvent.Set();
::WaitForSingleObject(m_MainThread, INFINITE);
DWORD result = ::WaitForMultipleObjects(m_Threads.Size(),
&m_Threads.Front(), TRUE, INFINITE);
for(int i = 0; i < m_Threads.Size(); i++)
::CloseHandle(m_Threads[i]);
}
void CCoderMixer::AddCoder(ICompressCoder *coder)
{
CThreadCoderInfo threadCoderInfo;
threadCoderInfo.Coder = coder;
m_CoderInfoVector.Add(threadCoderInfo);
m_CoderInfoVector.Back().CreateEvents();
m_CoderInfoVector.Back().ExitEvent = ExitEvent;
m_CompressingCompletedEvents.Add(*m_CoderInfoVector.Back().CompressionCompletedEvent);
}
void CCoderMixer::FinishAddingCoders()
{
for(int i = 0; i < m_CoderInfoVector.Size(); i++)
{
DWORD id;
HANDLE newThread = ::CreateThread(NULL, 0, CoderThread,
&m_CoderInfoVector[i], 0, &id);
if (newThread == 0)
throw 271824;
m_Threads.Add(newThread);
if (i >= 1)
{
CStreamBinder streamBinder;
m_StreamBinders.Add(streamBinder);
m_StreamBinders.Back().CreateEvents();
}
}
}
void CCoderMixer::ReInit()
{
int i;
for(i = 0; i < m_CoderInfoVector.Size(); i++)
{
CThreadCoderInfo &coderInfo = m_CoderInfoVector[i];
coderInfo.InSizeAssigned = false;
coderInfo.OutSizeAssigned = false;
coderInfo.Progress = NULL;
}
for(i = 0; i < m_StreamBinders.Size(); i++)
{
m_StreamBinders[i].ReInit();
}
}
void CCoderMixer::SetCoderInfo(UINT32 coderIndex, const UINT64 *inSize,
const UINT64 *outSize)
{
CThreadCoderInfo &coderInfo = m_CoderInfoVector[coderIndex];
coderInfo.InSizeAssigned = (inSize != NULL);
if (coderInfo.InSizeAssigned)
coderInfo.InSizeValue = *inSize;
coderInfo.OutSizeAssigned = (outSize != NULL);
if (coderInfo.OutSizeAssigned)
coderInfo.OutSizeValue = *outSize;
coderInfo.Progress = NULL;
}
STDMETHODIMP CCoderMixer::Init(ISequentialInStream *inStreamMain,
ISequentialOutStream *outStreamMain)
{
m_CoderInfoVector.Front().InStream = inStreamMain;
for(int i = 0; i < m_StreamBinders.Size(); i++)
m_StreamBinders[i].CreateStreams(&m_CoderInfoVector[i+1].InStream,
&m_CoderInfoVector[i].OutStream);
m_CoderInfoVector.Back().OutStream = outStreamMain;
return S_OK;
}
bool CCoderMixer::MyCode()
{
HANDLE events[2] = { ExitEvent, m_StartCompressingEvent };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 0)
return false;
for(int i = 0; i < m_CoderInfoVector.Size(); i++)
m_CoderInfoVector[i].CompressEvent->Set();
DWORD result = ::WaitForMultipleObjects(m_CompressingCompletedEvents.Size(),
&m_CompressingCompletedEvents.Front(), TRUE, INFINITE);
m_CompressingFinishedEvent.Set();
return true;
}
STDMETHODIMP CCoderMixer::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress)
{
Init(inStream, outStream);
m_CompressingFinishedEvent.Reset(); // ?
CCrossThreadProgress *progressSpec = new CCrossThreadProgress;
CMyComPtr<ICompressProgressInfo> crossProgress = progressSpec;
progressSpec->Init();
m_CoderInfoVector[m_ProgressCoderIndex].Progress = crossProgress;
m_StartCompressingEvent.Set();
while (true)
{
HANDLE events[2] = {m_CompressingFinishedEvent, progressSpec->ProgressEvent };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 0)
break;
if (progress != NULL)
progressSpec->Result = progress->SetRatioInfo(progressSpec->InSize,
progressSpec->OutSize);
else
progressSpec->Result = S_OK;
progressSpec->WaitEvent.Set();
}
int i;
for(i = 0; i < m_CoderInfoVector.Size(); i++)
{
HRESULT result = m_CoderInfoVector[i].Result;
if (result == S_FALSE)
return result;
}
for(i = 0; i < m_CoderInfoVector.Size(); i++)
{
HRESULT result = m_CoderInfoVector[i].Result;
if (result != S_OK)
return result;
}
return S_OK;
}
UINT64 CCoderMixer::GetWriteProcessedSize(UINT32 coderIndex)
{
return m_StreamBinders[coderIndex].ProcessedSize;
}

View File

@@ -1,87 +0,0 @@
// CoderMixer.h
#pragma once
#ifndef __CODERMIXER_H
#define __CODERMIXER_H
#include "Common/Vector.h"
#include "Common/MyCom.h"
#include "Windows/Thread.h"
#include "../../Common/StreamBinder.h"
#include "../../ICoder.h"
struct CThreadCoderInfo
{
NWindows::NSynchronization::CAutoResetEvent *CompressEvent;
HANDLE ExitEvent;
NWindows::NSynchronization::CAutoResetEvent *CompressionCompletedEvent;
CMyComPtr<ICompressCoder> Coder;
CMyComPtr<ISequentialInStream> InStream;
CMyComPtr<ISequentialOutStream> OutStream;
UINT64 InSizeValue;
UINT64 OutSizeValue;
bool InSizeAssigned;
bool OutSizeAssigned;
ICompressProgressInfo *Progress;
HRESULT Result;
CThreadCoderInfo(): ExitEvent(NULL), CompressEvent(NULL),
CompressionCompletedEvent(NULL),
InSizeAssigned(false),
OutSizeAssigned(false), Progress(NULL){}
~CThreadCoderInfo();
bool WaitAndCode();
void CreateEvents();
};
class CCoderMixer:
public ICompressCoder,
public CMyUnknownImp
{
MY_UNKNOWN_IMP
public:
STDMETHOD(Init)(ISequentialInStream *inStream,
ISequentialOutStream *outStream);
// STDMETHOD(ReleaseStreams)();
// STDMETHOD(Code)(UINT32 size, UINT32 &processedSize);
// STDMETHOD(Flush)();
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UINT64 *inSize, const UINT64 *outSize,
ICompressProgressInfo *progress);
CCoderMixer();
~CCoderMixer();
void AddCoder(ICompressCoder *aCoder);
void FinishAddingCoders();
void ReInit();
void SetCoderInfo(UINT32 coderIndex,
const UINT64 *inSize, const UINT64 *outSize);
void SetProgressCoderIndex(UINT32 coderIndex)
{ m_ProgressCoderIndex = coderIndex; }
UINT64 GetWriteProcessedSize(UINT32 coderIndex);
bool MyCode();
private:
CObjectVector<CStreamBinder> m_StreamBinders;
CObjectVector<CThreadCoderInfo> m_CoderInfoVector;
CRecordVector<HANDLE> m_Threads;
NWindows::CThread m_MainThread;
NWindows::NSynchronization::CAutoResetEvent m_StartCompressingEvent;
CRecordVector<HANDLE> m_CompressingCompletedEvents;
NWindows::NSynchronization::CAutoResetEvent m_CompressingFinishedEvent;
NWindows::NSynchronization::CManualResetEvent ExitEvent;
UINT32 m_ProgressCoderIndex;
};
#endif

View File

@@ -3,13 +3,6 @@
#include "StdAfx.h"
#include "CoderMixer2.h"
#include "CrossThreadProgress.h"
using namespace NWindows;
using namespace NSynchronization;
//////////////////////////
// CThreadCoderInfo2
namespace NCoderMixer2 {
@@ -18,7 +11,7 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
{
srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);
UINT32 j;
UInt32 j;
for (j = 0; j < NumSrcInStreams; j++)
{
_srcInToDestOutMap.Add(0);
@@ -30,10 +23,10 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
_destInToSrcOutMap.Add(0);
}
UINT32 destInOffset = 0;
UINT32 destOutOffset = 0;
UINT32 srcInOffset = NumSrcInStreams;
UINT32 srcOutOffset = _numSrcOutStreams;
UInt32 destInOffset = 0;
UInt32 destOutOffset = 0;
UInt32 srcInOffset = NumSrcInStreams;
UInt32 srcOutOffset = _numSrcOutStreams;
for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)
{
@@ -42,16 +35,16 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
srcInOffset -= srcCoderInfo.NumInStreams;
srcOutOffset -= srcCoderInfo.NumOutStreams;
UINT32 j;
UInt32 j;
for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)
{
UINT32 index = srcInOffset + j;
UInt32 index = srcInOffset + j;
_srcInToDestOutMap[index] = destOutOffset;
DestOutToSrcInMap[destOutOffset] = index;
}
for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)
{
UINT32 index = srcOutOffset + j;
UInt32 index = srcOutOffset + j;
_srcOutToDestInMap[index] = destInOffset;
_destInToSrcOutMap[destInOffset] = index;
}
@@ -88,102 +81,22 @@ void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)
destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
}
CThreadCoderInfo2::CThreadCoderInfo2(UINT32 numInStreams, UINT32 numOutStreams):
ExitEvent(NULL),
CompressEvent(NULL),
CompressionCompletedEvent(NULL),
CCoderInfo::CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams):
NumInStreams(numInStreams),
NumOutStreams(numOutStreams)
{
InStreams.Reserve(NumInStreams);
InStreamPointers.Reserve(NumInStreams);
InSizes.Reserve(NumInStreams);
InSizePointers.Reserve(NumInStreams);
OutStreams.Reserve(NumOutStreams);
OutStreamPointers.Reserve(NumOutStreams);
OutSizes.Reserve(NumOutStreams);
OutSizePointers.Reserve(NumOutStreams);
OutSizePointers.Reserve(NumOutStreams);
}
void CThreadCoderInfo2::CreateEvents()
{
CompressEvent = new CAutoResetEvent(false);
CompressionCompletedEvent = new CAutoResetEvent(false);
}
CThreadCoderInfo2::~CThreadCoderInfo2()
{
if (CompressEvent != NULL)
delete CompressEvent;
if (CompressionCompletedEvent != NULL)
delete CompressionCompletedEvent;
}
class CCoderInfoFlusher2
{
CThreadCoderInfo2 *m_CoderInfo;
public:
CCoderInfoFlusher2(CThreadCoderInfo2 *coderInfo): m_CoderInfo(coderInfo) {}
~CCoderInfoFlusher2()
{
int i;
for (i = 0; i < m_CoderInfo->InStreams.Size(); i++)
m_CoderInfo->InStreams[i].Release();
for (i = 0; i < m_CoderInfo->OutStreams.Size(); i++)
m_CoderInfo->OutStreams[i].Release();
m_CoderInfo->CompressionCompletedEvent->Set();
}
};
bool CThreadCoderInfo2::WaitAndCode()
{
HANDLE events[2] = { ExitEvent, *CompressEvent };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 0)
return false;
{
InStreamPointers.Clear();
OutStreamPointers.Clear();
UINT32 i;
for (i = 0; i < NumInStreams; i++)
{
if (InSizePointers[i] != NULL)
InSizePointers[i] = &InSizes[i];
InStreamPointers.Add(InStreams[i]);
}
for (i = 0; i < NumOutStreams; i++)
{
if (OutSizePointers[i] != NULL)
OutSizePointers[i] = &OutSizes[i];
OutStreamPointers.Add(OutStreams[i]);
}
CCoderInfoFlusher2 coderInfoFlusher(this);
if (CompressorIsCoder2)
Result = Coder2->Code(&InStreamPointers.Front(),
&InSizePointers.Front(),
NumInStreams,
&OutStreamPointers.Front(),
&OutSizePointers.Front(),
NumOutStreams,
Progress);
else
Result = Coder->Code(InStreamPointers[0],
OutStreamPointers[0],
InSizePointers[0],
OutSizePointers[0],
Progress);
}
return true;
}
void SetSizes(const UINT64 **srcSizes, CRecordVector<UINT64> &sizes,
CRecordVector<const UINT64 *> &sizePointers, UINT32 numItems)
static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
{
sizes.Clear();
sizePointers.Clear();
for(UINT32 i = 0; i < numItems; i++)
for(UInt32 i = 0; i < numItems; i++)
{
if (srcSizes == 0 || srcSizes[i] == NULL)
{
@@ -198,251 +111,11 @@ void SetSizes(const UINT64 **srcSizes, CRecordVector<UINT64> &sizes,
}
}
void CThreadCoderInfo2::SetCoderInfo(const UINT64 **inSizes,
const UINT64 **outSizes, ICompressProgressInfo *progress)
void CCoderInfo::SetCoderInfo(const UInt64 **inSizes,
const UInt64 **outSizes)
{
Progress = progress;
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
}
static DWORD WINAPI CoderThread(void *threadCoderInfo)
{
while(true)
{
if (!((CThreadCoderInfo2 *)threadCoderInfo)->WaitAndCode())
return 0;
}
}
//////////////////////////////////////
// CCoderMixer2
static DWORD WINAPI MainCoderThread(void *threadCoderInfo)
{
while(true)
{
if (!((CCoderMixer2 *)threadCoderInfo)->MyCode())
return 0;
}
}
CCoderMixer2::CCoderMixer2()
{
if (!_mainThread.Create(MainCoderThread, this))
throw 271825;
}
CCoderMixer2::~CCoderMixer2()
{
_exitEvent.Set();
::WaitForSingleObject(_mainThread, INFINITE);
DWORD result = ::WaitForMultipleObjects(_threads.Size(),
&_threads.Front(), TRUE, INFINITE);
for(int i = 0; i < _threads.Size(); i++)
::CloseHandle(_threads[i]);
}
void CCoderMixer2::SetBindInfo(const CBindInfo &bindInfo)
{
_bindInfo = bindInfo;
_streamBinders.Clear();
for(int i = 0; i < _bindInfo.BindPairs.Size(); i++)
{
_streamBinders.Add(CStreamBinder());
_streamBinders.Back().CreateEvents();
}
}
void CCoderMixer2::AddCoderCommon()
{
int index = _coderInfoVector.Size();
const CCoderStreamsInfo &CoderStreamsInfo = _bindInfo.Coders[index];
CThreadCoderInfo2 threadCoderInfo(CoderStreamsInfo.NumInStreams,
CoderStreamsInfo.NumOutStreams);
_coderInfoVector.Add(threadCoderInfo);
_coderInfoVector.Back().CreateEvents();
_coderInfoVector.Back().ExitEvent = _exitEvent;
_compressingCompletedEvents.Add(*_coderInfoVector.Back().CompressionCompletedEvent);
DWORD id;
HANDLE newThread = ::CreateThread(NULL, 0, CoderThread,
&_coderInfoVector.Back(), 0, &id);
if (newThread == 0)
throw 271824;
_threads.Add(newThread);
}
void CCoderMixer2::AddCoder(ICompressCoder *coder)
{
AddCoderCommon();
_coderInfoVector.Back().CompressorIsCoder2 = false;
_coderInfoVector.Back().Coder = coder;
}
void CCoderMixer2::AddCoder2(ICompressCoder2 *coder)
{
AddCoderCommon();
_coderInfoVector.Back().CompressorIsCoder2 = true;
_coderInfoVector.Back().Coder2 = coder;
}
/*
void CCoderMixer2::FinishAddingCoders()
{
for(int i = 0; i < _coderInfoVector.Size(); i++)
{
DWORD id;
HANDLE newThread = ::CreateThread(NULL, 0, CoderThread,
&_coderInfoVector[i], 0, &id);
if (newThread == 0)
throw 271824;
_threads.Add(newThread);
}
}
*/
void CCoderMixer2::ReInit()
{
for(int i = 0; i < _streamBinders.Size(); i++)
_streamBinders[i].ReInit();
}
STDMETHODIMP CCoderMixer2::Init(ISequentialInStream **inStreams,
ISequentialOutStream **outStreams)
{
if (_coderInfoVector.Size() != _bindInfo.Coders.Size())
throw 0;
UINT32 numInStreams = 0, numOutStreams = 0;
int i;
for(i = 0; i < _coderInfoVector.Size(); i++)
{
CThreadCoderInfo2 &coderInfo = _coderInfoVector[i];
const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
coderInfo.InStreams.Clear();
UINT32 j;
for(j = 0; j < coderStreamsInfo.NumInStreams; j++)
coderInfo.InStreams.Add(NULL);
coderInfo.OutStreams.Clear();
for(j = 0; j < coderStreamsInfo.NumOutStreams; j++)
coderInfo.OutStreams.Add(NULL);
}
for(i = 0; i < _bindInfo.BindPairs.Size(); i++)
{
const CBindPair &bindPair = _bindInfo.BindPairs[i];
UINT32 inCoderIndex, inCoderStreamIndex;
UINT32 outCoderIndex, outCoderStreamIndex;
_bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
_bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
_streamBinders[i].CreateStreams(
&_coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex],
&_coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex]);
}
for(i = 0; i < _bindInfo.InStreams.Size(); i++)
{
UINT32 inCoderIndex, inCoderStreamIndex;
_bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
_coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
}
for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
{
UINT32 outCoderIndex, outCoderStreamIndex;
_bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
_coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
}
return S_OK;
}
bool CCoderMixer2::MyCode()
{
HANDLE events[2] = { _exitEvent, _startCompressingEvent };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 0)
return false;
for(int i = 0; i < _coderInfoVector.Size(); i++)
_coderInfoVector[i].CompressEvent->Set();
DWORD result = ::WaitForMultipleObjects(_compressingCompletedEvents.Size(),
&_compressingCompletedEvents.Front(), TRUE, INFINITE);
_compressingFinishedEvent.Set();
return true;
}
STDMETHODIMP CCoderMixer2::Code(ISequentialInStream **inStreams,
const UINT64 **inSizes,
UINT32 numInStreams,
ISequentialOutStream **outStreams,
const UINT64 **outSizes,
UINT32 numOutStreams,
ICompressProgressInfo *progress)
{
if (numInStreams != (UINT32)_bindInfo.InStreams.Size() ||
numOutStreams != (UINT32)_bindInfo.OutStreams.Size())
return E_INVALIDARG;
Init(inStreams, outStreams);
_compressingFinishedEvent.Reset(); // ?
CCrossThreadProgress *progressSpec = new CCrossThreadProgress;
CMyComPtr<ICompressProgressInfo> crossProgress = progressSpec;
progressSpec->Init();
_coderInfoVector[_progressCoderIndex].Progress = crossProgress;
_startCompressingEvent.Set();
while (true)
{
HANDLE events[2] = {_compressingFinishedEvent, progressSpec->ProgressEvent };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 0)
break;
if (progress != NULL)
progressSpec->Result = progress->SetRatioInfo(progressSpec->InSize,
progressSpec->OutSize);
else
progressSpec->Result = S_OK;
progressSpec->WaitEvent.Set();
}
int i;
for(i = 0; i < _coderInfoVector.Size(); i++)
{
HRESULT result = _coderInfoVector[i].Result;
if (result == S_FALSE)
return result;
}
for(i = 0; i < _coderInfoVector.Size(); i++)
{
HRESULT result = _coderInfoVector[i].Result;
if (result != S_OK && result != E_FAIL)
return result;
}
for(i = 0; i < _coderInfoVector.Size(); i++)
{
HRESULT result = _coderInfoVector[i].Result;
if (result != S_OK)
return result;
}
return S_OK;
}
UINT64 CCoderMixer2::GetWriteProcessedSize(UINT32 binderIndex) const
{
return _streamBinders[binderIndex].ProcessedSize;
}
}

View File

@@ -1,49 +1,54 @@
// CoderMixer2.h
#pragma once
#ifndef __CODERMIXER2_H
#define __CODERMIXER2_H
#ifndef __CODER_MIXER2_H
#define __CODER_MIXER2_H
#include "../../../Common/Vector.h"
#include "../../../Common/Types.h"
#include "../../../Common/MyCom.h"
#include "../../../Windows/Thread.h"
#include "../../Common/StreamBinder.h"
#include "../../ICoder.h"
// #include "../../../Compress/Interface/CompressInterface.h"
namespace NCoderMixer2 {
struct CBindPair
{
UINT32 InIndex;
UINT32 OutIndex;
UInt32 InIndex;
UInt32 OutIndex;
};
struct CCoderStreamsInfo
{
UINT32 NumInStreams;
UINT32 NumOutStreams;
UInt32 NumInStreams;
UInt32 NumOutStreams;
};
struct CBindInfo
{
CRecordVector<CCoderStreamsInfo> Coders;
CRecordVector<CBindPair> BindPairs;
CRecordVector<UINT32> InStreams;
CRecordVector<UINT32> OutStreams;
UINT32 GetCoderStartOutStream(UINT32 coderIndex) const
CRecordVector<UInt32> InStreams;
CRecordVector<UInt32> OutStreams;
void Clear()
{
UINT32 numOutStreams = 0;
for (UINT32 i = 0; i < coderIndex; i++)
Coders.Clear();
BindPairs.Clear();
InStreams.Clear();
OutStreams.Clear();
}
/*
UInt32 GetCoderStartOutStream(UInt32 coderIndex) const
{
UInt32 numOutStreams = 0;
for (UInt32 i = 0; i < coderIndex; i++)
numOutStreams += Coders[i].NumOutStreams;
return numOutStreams;
}
*/
void GetNumStreams(UINT32 &numInStreams, UINT32 &numOutStreams) const
void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const
{
numInStreams = 0;
numOutStreams = 0;
@@ -55,14 +60,14 @@ struct CBindInfo
}
}
int FindBinderForInStream(UINT32 inStream) const
int FindBinderForInStream(UInt32 inStream) const
{
for (int i = 0; i < BindPairs.Size(); i++)
if (BindPairs[i].InIndex == inStream)
return i;
return -1;
}
int FindBinderForOutStream(UINT32 outStream) const
int FindBinderForOutStream(UInt32 outStream) const
{
for (int i = 0; i < BindPairs.Size(); i++)
if (BindPairs[i].OutIndex == outStream)
@@ -70,29 +75,29 @@ struct CBindInfo
return -1;
}
UINT32 GetCoderInStreamIndex(UINT32 coderIndex) const
UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const
{
UINT32 streamIndex = 0;
for (UINT32 i = 0; i < coderIndex; i++)
UInt32 streamIndex = 0;
for (UInt32 i = 0; i < coderIndex; i++)
streamIndex += Coders[i].NumInStreams;
return streamIndex;
}
UINT32 GetCoderOutStreamIndex(UINT32 coderIndex) const
UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const
{
UINT32 streamIndex = 0;
for (UINT32 i = 0; i < coderIndex; i++)
UInt32 streamIndex = 0;
for (UInt32 i = 0; i < coderIndex; i++)
streamIndex += Coders[i].NumOutStreams;
return streamIndex;
}
void FindInStream(UINT32 streamIndex, UINT32 &coderIndex,
UINT32 &coderStreamIndex) const
void FindInStream(UInt32 streamIndex, UInt32 &coderIndex,
UInt32 &coderStreamIndex) const
{
for (coderIndex = 0; coderIndex < (UINT32)Coders.Size(); coderIndex++)
for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
{
UINT32 curSize = Coders[coderIndex].NumInStreams;
UInt32 curSize = Coders[coderIndex].NumInStreams;
if (streamIndex < curSize)
{
coderStreamIndex = streamIndex;
@@ -102,12 +107,12 @@ struct CBindInfo
}
throw 1;
}
void FindOutStream(UINT32 streamIndex, UINT32 &coderIndex,
UINT32 &coderStreamIndex) const
void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex,
UInt32 &coderStreamIndex) const
{
for (coderIndex = 0; coderIndex < (UINT32)Coders.Size(); coderIndex++)
for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
{
UINT32 curSize = Coders[coderIndex].NumOutStreams;
UInt32 curSize = Coders[coderIndex].NumOutStreams;
if (streamIndex < curSize)
{
coderStreamIndex = streamIndex;
@@ -121,132 +126,41 @@ struct CBindInfo
class CBindReverseConverter
{
UINT32 _numSrcOutStreams;
UInt32 _numSrcOutStreams;
const NCoderMixer2::CBindInfo _srcBindInfo;
CRecordVector<UINT32> _srcInToDestOutMap;
CRecordVector<UINT32> _srcOutToDestInMap;
CRecordVector<UINT32> _destInToSrcOutMap;
CRecordVector<UInt32> _srcInToDestOutMap;
CRecordVector<UInt32> _srcOutToDestInMap;
CRecordVector<UInt32> _destInToSrcOutMap;
public:
UINT32 NumSrcInStreams;
CRecordVector<UINT32> DestOutToSrcInMap;
UInt32 NumSrcInStreams;
CRecordVector<UInt32> DestOutToSrcInMap;
CBindReverseConverter(const NCoderMixer2::CBindInfo &srcBindInfo);
void CreateReverseBindInfo(NCoderMixer2::CBindInfo &destBindInfo);
};
// CreateEvents();
// {
// SetCoderInfo()
// Init Streams
// set CompressEvent()
// wait CompressionCompletedEvent
// }
struct CThreadCoderInfo2
struct CCoderInfo
{
NWindows::NSynchronization::CAutoResetEvent *CompressEvent;
HANDLE ExitEvent;
NWindows::NSynchronization::CAutoResetEvent *CompressionCompletedEvent;
bool CompressorIsCoder2;
CMyComPtr<ICompressCoder> Coder;
CMyComPtr<ICompressCoder2> Coder2;
UINT32 NumInStreams;
UINT32 NumOutStreams;
UInt32 NumInStreams;
UInt32 NumOutStreams;
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
CRecordVector<ISequentialInStream *> InStreamPointers;
CRecordVector<ISequentialOutStream *> OutStreamPointers;
CRecordVector<UINT64> InSizes;
CRecordVector<UINT64> OutSizes;
CRecordVector<const UINT64 *> InSizePointers;
CRecordVector<const UINT64 *> OutSizePointers;
CRecordVector<UInt64> InSizes;
CRecordVector<UInt64> OutSizes;
CRecordVector<const UInt64 *> InSizePointers;
CRecordVector<const UInt64 *> OutSizePointers;
CMyComPtr<ICompressProgressInfo> Progress; // CMyComPtr
HRESULT Result;
CThreadCoderInfo2(UINT32 numInStreams, UINT32 numOutStreams);
void SetCoderInfo(const UINT64 **inSizes,
const UINT64 **outSizes, ICompressProgressInfo *progress);
~CThreadCoderInfo2();
bool WaitAndCode();
void CreateEvents();
CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams);
void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
};
// SetBindInfo()
// for each coder
// {
// AddCoder[2]()
// }
//
// for each file
// {
// ReInit()
// for each coder
// {
// SetCoderInfo
// }
// SetProgressIndex(UINT32 coderIndex);
// Code
// }
class CCoderMixer2:
public ICompressCoder2,
public CMyUnknownImp
class CCoderMixer2
{
MY_UNKNOWN_IMP
public:
STDMETHOD(Init)(ISequentialInStream **inStreams,
ISequentialOutStream **outStreams);
STDMETHOD(Code)(ISequentialInStream **inStreams,
const UINT64 **inSizes,
UINT32 numInStreams,
ISequentialOutStream **outStreams,
const UINT64 **outSizes,
UINT32 numOutStreams,
ICompressProgressInfo *progress);
CCoderMixer2();
~CCoderMixer2();
void AddCoderCommon();
void AddCoder(ICompressCoder *coder);
void AddCoder2(ICompressCoder2 *coder);
void ReInit();
void SetCoderInfo(UINT32 coderIndex, const UINT64 **anInSize, const UINT64 **outSize)
{ _coderInfoVector[coderIndex].SetCoderInfo(anInSize, outSize, NULL); }
void SetProgressCoderIndex(UINT32 coderIndex)
{ _progressCoderIndex = coderIndex; }
UINT64 GetWriteProcessedSize(UINT32 binderIndex) const;
bool MyCode();
private:
CBindInfo _bindInfo;
CObjectVector<CStreamBinder> _streamBinders;
CObjectVector<CThreadCoderInfo2> _coderInfoVector;
CRecordVector<HANDLE> _threads;
NWindows::CThread _mainThread;
NWindows::NSynchronization::CAutoResetEvent _startCompressingEvent;
CRecordVector<HANDLE> _compressingCompletedEvents;
NWindows::NSynchronization::CAutoResetEvent _compressingFinishedEvent;
NWindows::NSynchronization::CManualResetEvent _exitEvent;
UINT32 _progressCoderIndex;
public:
void SetBindInfo(const CBindInfo &bindInfo);
virtual void SetBindInfo(const CBindInfo &bindInfo) = 0;
virtual void ReInit() = 0;
virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;
};
}

View File

@@ -0,0 +1,360 @@
// CoderMixer2MT.cpp
#include "StdAfx.h"
#include "CoderMixer2MT.h"
#include "CrossThreadProgress.h"
using namespace NWindows;
using namespace NSynchronization;
namespace NCoderMixer2 {
CThreadCoderInfo::CThreadCoderInfo(UInt32 numInStreams, UInt32 numOutStreams):
ExitEvent(NULL),
CompressEvent(NULL),
CompressionCompletedEvent(NULL),
CCoderInfo(numInStreams, numOutStreams)
{
InStreams.Reserve(NumInStreams);
InStreamPointers.Reserve(NumInStreams);
OutStreams.Reserve(NumOutStreams);
OutStreamPointers.Reserve(NumOutStreams);
}
void CThreadCoderInfo::CreateEvents()
{
CompressEvent = new CAutoResetEvent(false);
CompressionCompletedEvent = new CAutoResetEvent(false);
}
CThreadCoderInfo::~CThreadCoderInfo()
{
if (CompressEvent != NULL)
delete CompressEvent;
if (CompressionCompletedEvent != NULL)
delete CompressionCompletedEvent;
}
class CCoderInfoFlusher2
{
CThreadCoderInfo *m_CoderInfo;
public:
CCoderInfoFlusher2(CThreadCoderInfo *coderInfo): m_CoderInfo(coderInfo) {}
~CCoderInfoFlusher2()
{
int i;
for (i = 0; i < m_CoderInfo->InStreams.Size(); i++)
m_CoderInfo->InStreams[i].Release();
for (i = 0; i < m_CoderInfo->OutStreams.Size(); i++)
m_CoderInfo->OutStreams[i].Release();
m_CoderInfo->CompressionCompletedEvent->Set();
}
};
bool CThreadCoderInfo::WaitAndCode()
{
HANDLE events[2] = { ExitEvent, *CompressEvent };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 0)
return false;
{
InStreamPointers.Clear();
OutStreamPointers.Clear();
UInt32 i;
for (i = 0; i < NumInStreams; i++)
{
if (InSizePointers[i] != NULL)
InSizePointers[i] = &InSizes[i];
InStreamPointers.Add(InStreams[i]);
}
for (i = 0; i < NumOutStreams; i++)
{
if (OutSizePointers[i] != NULL)
OutSizePointers[i] = &OutSizes[i];
OutStreamPointers.Add(OutStreams[i]);
}
CCoderInfoFlusher2 coderInfoFlusher(this);
if (Coder)
Result = Coder->Code(InStreamPointers[0],
OutStreamPointers[0],
InSizePointers[0],
OutSizePointers[0],
Progress);
else
Result = Coder2->Code(&InStreamPointers.Front(),
&InSizePointers.Front(),
NumInStreams,
&OutStreamPointers.Front(),
&OutSizePointers.Front(),
NumOutStreams,
Progress);
}
return true;
}
static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
{
sizes.Clear();
sizePointers.Clear();
for(UInt32 i = 0; i < numItems; i++)
{
if (srcSizes == 0 || srcSizes[i] == NULL)
{
sizes.Add(0);
sizePointers.Add(NULL);
}
else
{
sizes.Add(*srcSizes[i]);
sizePointers.Add(&sizes.Back());
}
}
}
void CThreadCoderInfo::SetCoderInfo(const UInt64 **inSizes,
const UInt64 **outSizes, ICompressProgressInfo *progress)
{
Progress = progress;
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
}
static DWORD WINAPI CoderThread(void *threadCoderInfo)
{
while(true)
{
if (!((CThreadCoderInfo *)threadCoderInfo)->WaitAndCode())
return 0;
}
}
//////////////////////////////////////
// CCoderMixer2MT
static DWORD WINAPI MainCoderThread(void *threadCoderInfo)
{
while(true)
{
if (!((CCoderMixer2MT *)threadCoderInfo)->MyCode())
return 0;
}
}
CCoderMixer2MT::CCoderMixer2MT()
{
if (!_mainThread.Create(MainCoderThread, this))
throw 271825;
}
CCoderMixer2MT::~CCoderMixer2MT()
{
_exitEvent.Set();
_mainThread.Wait();
for(int i = 0; i < _threads.Size(); i++)
{
_threads[i].Wait();
_threads[i].Close();
}
}
void CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
{
_bindInfo = bindInfo;
_streamBinders.Clear();
for(int i = 0; i < _bindInfo.BindPairs.Size(); i++)
{
_streamBinders.Add(CStreamBinder());
_streamBinders.Back().CreateEvents();
}
}
void CCoderMixer2MT::AddCoderCommon()
{
int index = _coderInfoVector.Size();
const CCoderStreamsInfo &CoderStreamsInfo = _bindInfo.Coders[index];
CThreadCoderInfo threadCoderInfo(CoderStreamsInfo.NumInStreams,
CoderStreamsInfo.NumOutStreams);
_coderInfoVector.Add(threadCoderInfo);
_coderInfoVector.Back().CreateEvents();
_coderInfoVector.Back().ExitEvent = _exitEvent;
_compressingCompletedEvents.Add(*_coderInfoVector.Back().CompressionCompletedEvent);
NWindows::CThread newThread;
_threads.Add(newThread);
if (!_threads.Back().Create(CoderThread, &_coderInfoVector.Back()))
throw 271824;
}
void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
{
AddCoderCommon();
_coderInfoVector.Back().Coder = coder;
}
void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
{
AddCoderCommon();
_coderInfoVector.Back().Coder2 = coder;
}
/*
void CCoderMixer2MT::FinishAddingCoders()
{
for(int i = 0; i < _coderInfoVector.Size(); i++)
{
DWORD id;
HANDLE newThread = ::CreateThread(NULL, 0, CoderThread,
&_coderInfoVector[i], 0, &id);
if (newThread == 0)
throw 271824;
_threads.Add(newThread);
}
}
*/
void CCoderMixer2MT::ReInit()
{
for(int i = 0; i < _streamBinders.Size(); i++)
_streamBinders[i].ReInit();
}
STDMETHODIMP CCoderMixer2MT::Init(ISequentialInStream **inStreams,
ISequentialOutStream **outStreams)
{
if (_coderInfoVector.Size() != _bindInfo.Coders.Size())
throw 0;
UInt32 numInStreams = 0, numOutStreams = 0;
int i;
for(i = 0; i < _coderInfoVector.Size(); i++)
{
CThreadCoderInfo &coderInfo = _coderInfoVector[i];
const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
coderInfo.InStreams.Clear();
UInt32 j;
for(j = 0; j < coderStreamsInfo.NumInStreams; j++)
coderInfo.InStreams.Add(NULL);
coderInfo.OutStreams.Clear();
for(j = 0; j < coderStreamsInfo.NumOutStreams; j++)
coderInfo.OutStreams.Add(NULL);
}
for(i = 0; i < _bindInfo.BindPairs.Size(); i++)
{
const CBindPair &bindPair = _bindInfo.BindPairs[i];
UInt32 inCoderIndex, inCoderStreamIndex;
UInt32 outCoderIndex, outCoderStreamIndex;
_bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
_bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
_streamBinders[i].CreateStreams(
&_coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex],
&_coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex]);
}
for(i = 0; i < _bindInfo.InStreams.Size(); i++)
{
UInt32 inCoderIndex, inCoderStreamIndex;
_bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
_coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
}
for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
{
UInt32 outCoderIndex, outCoderStreamIndex;
_bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
_coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
}
return S_OK;
}
bool CCoderMixer2MT::MyCode()
{
HANDLE events[2] = { _exitEvent, _startCompressingEvent };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 0)
return false;
for(int i = 0; i < _coderInfoVector.Size(); i++)
_coderInfoVector[i].CompressEvent->Set();
DWORD result = ::WaitForMultipleObjects(_compressingCompletedEvents.Size(),
&_compressingCompletedEvents.Front(), TRUE, INFINITE);
_compressingFinishedEvent.Set();
return true;
}
STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
return E_INVALIDARG;
Init(inStreams, outStreams);
_compressingFinishedEvent.Reset(); // ?
CCrossThreadProgress *progressSpec = new CCrossThreadProgress;
CMyComPtr<ICompressProgressInfo> crossProgress = progressSpec;
progressSpec->Init();
_coderInfoVector[_progressCoderIndex].Progress = crossProgress;
_startCompressingEvent.Set();
while (true)
{
HANDLE events[2] = {_compressingFinishedEvent, progressSpec->ProgressEvent };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 0)
break;
if (progress != NULL)
progressSpec->Result = progress->SetRatioInfo(progressSpec->InSize,
progressSpec->OutSize);
else
progressSpec->Result = S_OK;
progressSpec->WaitEvent.Set();
}
int i;
for(i = 0; i < _coderInfoVector.Size(); i++)
{
HRESULT result = _coderInfoVector[i].Result;
if (result == S_FALSE)
return result;
}
for(i = 0; i < _coderInfoVector.Size(); i++)
{
HRESULT result = _coderInfoVector[i].Result;
if (result != S_OK && result != E_FAIL)
return result;
}
for(i = 0; i < _coderInfoVector.Size(); i++)
{
HRESULT result = _coderInfoVector[i].Result;
if (result != S_OK)
return result;
}
return S_OK;
}
UInt64 CCoderMixer2MT::GetWriteProcessedSize(UInt32 binderIndex) const
{
return _streamBinders[binderIndex].ProcessedSize;
}
}

View File

@@ -0,0 +1,121 @@
// CoderMixer2MT.h
#ifndef __CODER_MIXER2_MT_H
#define __CODER_MIXER2_MT_H
#include "CoderMixer2.h"
#include "../../../Common/MyCom.h"
#include "../../../Windows/Thread.h"
#include "../../Common/StreamBinder.h"
namespace NCoderMixer2 {
// CreateEvents();
// {
// SetCoderInfo()
// Init Streams
// set CompressEvent()
// wait CompressionCompletedEvent
// }
struct CThreadCoderInfo: public CCoderInfo
{
NWindows::NSynchronization::CAutoResetEvent *CompressEvent;
HANDLE ExitEvent;
NWindows::NSynchronization::CAutoResetEvent *CompressionCompletedEvent;
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
CRecordVector<ISequentialInStream *> InStreamPointers;
CRecordVector<ISequentialOutStream *> OutStreamPointers;
CMyComPtr<ICompressProgressInfo> Progress; // CMyComPtr
HRESULT Result;
CThreadCoderInfo(UInt32 numInStreams, UInt32 numOutStreams);
void SetCoderInfo(const UInt64 **inSizes,
const UInt64 **outSizes, ICompressProgressInfo *progress);
~CThreadCoderInfo();
bool WaitAndCode();
void CreateEvents();
};
// SetBindInfo()
// for each coder
// {
// AddCoder[2]()
// }
//
// for each file
// {
// ReInit()
// for each coder
// {
// SetCoderInfo
// }
// SetProgressIndex(UInt32 coderIndex);
// Code
// }
class CCoderMixer2MT:
public ICompressCoder2,
public CCoderMixer2,
public CMyUnknownImp
{
MY_UNKNOWN_IMP
public:
STDMETHOD(Init)(ISequentialInStream **inStreams,
ISequentialOutStream **outStreams);
STDMETHOD(Code)(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
CCoderMixer2MT();
~CCoderMixer2MT();
void AddCoderCommon();
void AddCoder(ICompressCoder *coder);
void AddCoder2(ICompressCoder2 *coder);
void ReInit();
void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
{ _coderInfoVector[coderIndex].SetCoderInfo(inSizes, outSizes, NULL); }
void SetProgressCoderIndex(UInt32 coderIndex)
{ _progressCoderIndex = coderIndex; }
UInt64 GetWriteProcessedSize(UInt32 binderIndex) const;
bool MyCode();
private:
CBindInfo _bindInfo;
CObjectVector<CStreamBinder> _streamBinders;
CObjectVector<CThreadCoderInfo> _coderInfoVector;
CRecordVector<NWindows::CThread> _threads;
NWindows::CThread _mainThread;
NWindows::NSynchronization::CAutoResetEvent _startCompressingEvent;
CRecordVector<HANDLE> _compressingCompletedEvents;
NWindows::NSynchronization::CAutoResetEvent _compressingFinishedEvent;
NWindows::NSynchronization::CManualResetEvent _exitEvent;
UInt32 _progressCoderIndex;
public:
void SetBindInfo(const CBindInfo &bindInfo);
};
}
#endif

View File

@@ -0,0 +1,238 @@
// CoderMixer2ST.cpp
#include "StdAfx.h"
#include "CoderMixer2ST.h"
namespace NCoderMixer2 {
CCoderMixer2ST::CCoderMixer2ST() {}
CCoderMixer2ST::~CCoderMixer2ST(){ }
void CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo)
{
_bindInfo = bindInfo;
}
void CCoderMixer2ST::AddCoderCommon(bool isMain)
{
const CCoderStreamsInfo &csi = _bindInfo.Coders[_coders.Size()];
_coders.Add(CSTCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain));
}
void CCoderMixer2ST::AddCoder(ICompressCoder *coder, bool isMain)
{
AddCoderCommon(isMain);
_coders.Back().Coder = coder;
}
void CCoderMixer2ST::AddCoder2(ICompressCoder2 *coder, bool isMain)
{
AddCoderCommon(isMain);
_coders.Back().Coder2 = coder;
}
void CCoderMixer2ST::ReInit() { }
HRESULT CCoderMixer2ST::GetInStream(
ISequentialInStream **inStreams, const UInt64 **inSizes,
UInt32 streamIndex, ISequentialInStream **inStreamRes)
{
CMyComPtr<ISequentialInStream> seqInStream;
int i;
for(i = 0; i < _bindInfo.InStreams.Size(); i++)
if (_bindInfo.InStreams[i] == streamIndex)
{
seqInStream = inStreams[i];
*inStreamRes = seqInStream.Detach();
return S_OK;
}
int binderIndex = _bindInfo.FindBinderForInStream(streamIndex);
if (binderIndex < 0)
return E_INVALIDARG;
UInt32 coderIndex, coderStreamIndex;
_bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex,
coderIndex, coderStreamIndex);
CCoderInfo &coder = _coders[coderIndex];
if (!coder.Coder)
return E_NOTIMPL;
coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream);
if (!seqInStream)
return E_NOTIMPL;
UInt32 startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex);
CMyComPtr<ICompressSetInStream> setInStream;
if (!coder.Coder)
return E_NOTIMPL;
coder.Coder.QueryInterface(IID_ICompressSetInStream, &setInStream);
if (!setInStream)
return E_NOTIMPL;
if (coder.NumInStreams > 1)
return E_NOTIMPL;
for (i = 0; i < (int)coder.NumInStreams; i++)
{
CMyComPtr<ISequentialInStream> seqInStream2;
RINOK(GetInStream(inStreams, inSizes, startIndex + i, &seqInStream2));
RINOK(setInStream->SetInStream(seqInStream2));
}
*inStreamRes = seqInStream.Detach();
return S_OK;
}
HRESULT CCoderMixer2ST::GetOutStream(
ISequentialOutStream **outStreams, const UInt64 **outSizes,
UInt32 streamIndex, ISequentialOutStream **outStreamRes)
{
CMyComPtr<ISequentialOutStream> seqOutStream;
int i;
for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
if (_bindInfo.OutStreams[i] == streamIndex)
{
seqOutStream = outStreams[i];
*outStreamRes = seqOutStream.Detach();
return S_OK;
}
int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex);
if (binderIndex < 0)
return E_INVALIDARG;
UInt32 coderIndex, coderStreamIndex;
_bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex,
coderIndex, coderStreamIndex);
CCoderInfo &coder = _coders[coderIndex];
if (!coder.Coder)
return E_NOTIMPL;
coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream);
if (!seqOutStream)
return E_NOTIMPL;
UInt32 startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
CMyComPtr<ICompressSetOutStream> setOutStream;
if (!coder.Coder)
return E_NOTIMPL;
coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
if (!setOutStream)
return E_NOTIMPL;
if (coder.NumOutStreams > 1)
return E_NOTIMPL;
for (i = 0; i < (int)coder.NumOutStreams; i++)
{
CMyComPtr<ISequentialOutStream> seqOutStream2;
RINOK(GetOutStream(outStreams, outSizes, startIndex + i, &seqOutStream2));
RINOK(setOutStream->SetOutStream(seqOutStream2));
}
*outStreamRes = seqOutStream.Detach();
return S_OK;
}
STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
return E_INVALIDARG;
// Find main coder
int _mainCoderIndex = -1;
int i;
for (i = 0; i < _coders.Size(); i++)
if (_coders[i].IsMain)
{
_mainCoderIndex = i;
break;
}
if (_mainCoderIndex < 0)
for (i = 0; i < _coders.Size(); i++)
if (_coders[i].NumInStreams > 1)
{
if (_mainCoderIndex >= 0)
return E_NOTIMPL;
_mainCoderIndex = i;
}
if (_mainCoderIndex < 0)
_mainCoderIndex = 0;
// _mainCoderIndex = 0;
// _mainCoderIndex = _coders.Size() - 1;
CCoderInfo &mainCoder = _coders[_mainCoderIndex];
CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex);
UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex);
for (i = 0; i < (int)mainCoder.NumInStreams; i++)
{
CMyComPtr<ISequentialInStream> seqInStream;
RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream));
seqInStreams.Add(seqInStream);
}
for (i = 0; i < (int)mainCoder.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 < (int)mainCoder.NumInStreams; i++)
seqInStreamsSpec.Add(seqInStreams[i]);
for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
seqOutStreamsSpec.Add(seqOutStreams[i]);
for (i = 0; i < _coders.Size(); i++)
{
if (i == _mainCoderIndex)
continue;
CCoderInfo &coder = _coders[i];
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
if (setOutStreamSize)
{
RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0]));
}
}
if (mainCoder.Coder)
{
RINOK(mainCoder.Coder->Code(
seqInStreamsSpec[0], seqOutStreamsSpec[0],
mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0],
progress));
}
else
{
RINOK(mainCoder.Coder2->Code(
&seqInStreamsSpec.Front(),
&mainCoder.InSizePointers.Front(), mainCoder.NumInStreams,
&seqOutStreamsSpec.Front(),
&mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams,
progress));
}
CMyComPtr<IOutStreamFlush> flush;
seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush);
if (flush)
return flush->Flush();
return S_OK;
}
/*
UInt64 CCoderMixer2ST::GetWriteProcessedSize(UInt32 binderIndex) const
{
return _streamBinders[binderIndex].ProcessedSize;
}
*/
}

View File

@@ -0,0 +1,87 @@
// CoderMixer2ST.h
#ifndef __CODER_MIXER2_ST_H
#define __CODER_MIXER2_ST_H
#include "CoderMixer2.h"
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
namespace NCoderMixer2 {
// SetBindInfo()
// for each coder
// {
// AddCoder[2]()
// }
//
// for each file
// {
// ReInit()
// for each coder
// {
// SetCoderInfo
// }
// SetProgressIndex(UInt32 coderIndex);
// Code
// }
struct CSTCoderInfo: public CCoderInfo
{
bool IsMain;
CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain):
CCoderInfo(numInStreams, numOutStreams),IsMain(isMain) {}
};
class CCoderMixer2ST:
public ICompressCoder2,
public CCoderMixer2,
public CMyUnknownImp
{
MY_UNKNOWN_IMP
HRESULT GetInStream(
ISequentialInStream **inStreams, const UInt64 **inSizes,
UInt32 streamIndex, ISequentialInStream **inStreamRes);
HRESULT GetOutStream(
ISequentialOutStream **outStreams, const UInt64 **outSizes,
UInt32 streamIndex, ISequentialOutStream **outStreamRes);
public:
STDMETHOD(Code)(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
CCoderMixer2ST();
~CCoderMixer2ST();
void AddCoderCommon(bool isMain);
void AddCoder(ICompressCoder *coder, bool isMain);
void AddCoder2(ICompressCoder2 *coder, bool isMain);
void ReInit();
void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
{
{ _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
}
void SetProgressCoderIndex(UInt32 coderIndex)
{
// _progressCoderIndex = coderIndex;
}
// UInt64 GetWriteProcessedSize(UInt32 binderIndex) const;
private:
CBindInfo _bindInfo;
CObjectVector<CSTCoderInfo> _coders;
int _mainCoderIndex;
public:
void SetBindInfo(const CBindInfo &bindInfo);
};
}
#endif

View File

@@ -1,34 +0,0 @@
// CodersPath.cpp
#include "StdAfx.h"
#include "../../../Common/String.h"
extern HINSTANCE g_hInstance;
static CSysString GetLibraryPath()
{
TCHAR fullPath[MAX_PATH + 1];
::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);
return fullPath;
}
static CSysString GetLibraryFolderPrefix()
{
CSysString path = GetLibraryPath();
int pos = path.ReverseFind(TEXT('\\'));
return path.Left(pos + 1);
}
CSysString GetBaseFolderPrefix()
{
CSysString libPrefix = GetLibraryFolderPrefix();
CSysString temp = libPrefix;
temp.Delete(temp.Length() - 1);
int pos = temp.ReverseFind(TEXT('\\'));
return temp.Left(pos + 1);
}
CSysString GetCodecsFolderPrefix()
{
return GetBaseFolderPrefix() + TEXT("Compress\\");
}

View File

@@ -4,7 +4,7 @@
#include "CrossThreadProgress.h"
STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UINT64 *inSize, const UINT64 *outSize)
STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
{
InSize = inSize;
OutSize = outSize;

View File

@@ -1,7 +1,5 @@
// CrossThreadProgress.h
#pragma once
#ifndef __CROSSTHREADPROGRESS_H
#define __CROSSTHREADPROGRESS_H
@@ -14,8 +12,8 @@ class CCrossThreadProgress:
public CMyUnknownImp
{
public:
const UINT64 *InSize;
const UINT64 *OutSize;
const UInt64 *InSize;
const UInt64 *OutSize;
HRESULT Result;
NWindows::NSynchronization::CAutoResetEvent ProgressEvent;
NWindows::NSynchronization::CAutoResetEvent WaitEvent;
@@ -27,7 +25,7 @@ public:
MY_UNKNOWN_IMP
STDMETHOD(SetRatioInfo)(const UINT64 *inSize, const UINT64 *outSize);
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
#endif

View File

@@ -10,7 +10,7 @@ void CDummyOutStream::Init(ISequentialOutStream *outStream)
}
STDMETHODIMP CDummyOutStream::Write(const void *data,
UINT32 size, UINT32 *processedSize)
UInt32 size, UInt32 *processedSize)
{
if(m_Stream)
return m_Stream->Write(data, size, processedSize);
@@ -20,7 +20,7 @@ STDMETHODIMP CDummyOutStream::Write(const void *data,
}
STDMETHODIMP CDummyOutStream::WritePart(const void *data,
UINT32 size, UINT32 *processedSize)
UInt32 size, UInt32 *processedSize)
{
if(m_Stream)
return m_Stream->WritePart(data, size, processedSize);

View File

@@ -1,7 +1,5 @@
// DummyOutStream.h
#pragma once
#ifndef __DUMMYOUTSTREAM_H
#define __DUMMYOUTSTREAM_H
@@ -15,8 +13,8 @@ class CDummyOutStream:
public:
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
private:
CMyComPtr<ISequentialOutStream> m_Stream;
public:

View File

@@ -0,0 +1,244 @@
// FilterCoder.cpp
#include "StdAfx.h"
#include "FilterCoder.h"
#include "../../../Common/Alloc.h"
#include "../../../Common/Defs.h"
static const int kBufferSize = 1 << 17;
CFilterCoder::CFilterCoder()
{
_buffer = (Byte *)::BigAlloc(kBufferSize);
}
CFilterCoder::~CFilterCoder()
{
BigFree(_buffer);
}
HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
{
if (_outSizeIsDefined)
{
UInt64 remSize = _outSize - _nowPos64;
if (size > remSize)
size = (UInt32)remSize;
}
UInt32 processedSize = 0;
RINOK(outStream->Write(_buffer, size, &processedSize));
if (size != processedSize)
return E_FAIL;
_nowPos64 += processedSize;
return S_OK;
}
STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
Init();
UInt32 bufferPos = 0;
if (_outSizeIsDefined = (outSize != 0))
_outSize = *outSize;
while(NeedMore())
{
UInt32 processedSize;
UInt32 size = kBufferSize - bufferPos;
RINOK(inStream->Read(_buffer + bufferPos, size, &processedSize));
UInt32 endPos = bufferPos + processedSize;
bufferPos = Filter->Filter(_buffer, endPos);
if (bufferPos > endPos)
{
for (; endPos< bufferPos; endPos++)
_buffer[endPos] = 0;
bufferPos = Filter->Filter(_buffer, endPos);
}
if (bufferPos == 0)
{
if (endPos > 0)
return WriteWithLimit(outStream, endPos);
return S_OK;
}
RINOK(WriteWithLimit(outStream, bufferPos));
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));
}
UInt32 i = 0;
while(bufferPos < endPos)
_buffer[i++] = _buffer[bufferPos++];
bufferPos = i;
}
return S_OK;
}
// #ifdef _ST_MODE
STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
{
_bufferPos = 0;
_outStream = outStream;
Init();
return S_OK;
}
STDMETHODIMP CFilterCoder::ReleaseOutStream()
{
_outStream.Release();
return S_OK;
};
STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 processedSizeTotal = 0;
while(size > 0)
{
UInt32 sizeMax = kBufferSize - _bufferPos;
UInt32 sizeTemp = size;
if (sizeTemp > sizeMax)
sizeTemp = sizeMax;
memmove(_buffer + _bufferPos, data, sizeTemp);
size -= sizeTemp;
processedSizeTotal += sizeTemp;
data = (const Byte *)data + sizeTemp;
UInt32 endPos = _bufferPos + sizeTemp;
_bufferPos = Filter->Filter(_buffer, endPos);
if (_bufferPos == 0)
{
_bufferPos = endPos;
break;
}
if (_bufferPos > endPos)
{
if (size != 0)
return E_FAIL;
break;
}
RINOK(WriteWithLimit(_outStream, _bufferPos));
UInt32 i = 0;
while(_bufferPos < endPos)
_buffer[i++] = _buffer[_bufferPos++];
_bufferPos = i;
}
if (processedSize != NULL)
*processedSize = processedSizeTotal;
return S_OK;
}
STDMETHODIMP CFilterCoder::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
{
return Write(data, size, processedSize);
}
STDMETHODIMP CFilterCoder::Flush()
{
if (_bufferPos != 0)
{
UInt32 endPos = Filter->Filter(_buffer, _bufferPos);
if (endPos > _bufferPos)
{
for (; _bufferPos < endPos; _bufferPos++)
_buffer[_bufferPos] = 0;
if (Filter->Filter(_buffer, endPos) != endPos)
return E_FAIL;
}
UInt32 processedSize;
RINOK(_outStream->Write(_buffer, _bufferPos, &processedSize));
if (_bufferPos != processedSize)
return E_FAIL;
_bufferPos = 0;
}
CMyComPtr<IOutStreamFlush> flush;
_outStream.QueryInterface(IID_IOutStreamFlush, &flush);
if (flush)
return flush->Flush();
return S_OK;
}
STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
{
_convertedPosBegin = _convertedPosEnd = _bufferPos = 0;
_inStream = inStream;
Init();
return S_OK;
}
STDMETHODIMP CFilterCoder::ReleaseInStream()
{
_inStream.Release();
return S_OK;
};
STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 processedSizeTotal = 0;
while(size > 0)
{
if (_convertedPosBegin != _convertedPosEnd)
{
UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);
memmove(data, _buffer + _convertedPosBegin, sizeTemp);
_convertedPosBegin += sizeTemp;
data = (void *)((Byte *)data + sizeTemp);
size -= sizeTemp;
processedSizeTotal += sizeTemp;
continue;
}
int i;
for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
_buffer[i] = _buffer[i + _convertedPosEnd];
_bufferPos = i;
_convertedPosBegin = _convertedPosEnd = 0;
UInt32 processedSizeTemp;
UInt32 size0 = kBufferSize - _bufferPos;
RINOK(_inStream->Read(_buffer + _bufferPos, size0, &processedSizeTemp));
_bufferPos = _bufferPos + processedSizeTemp;
_convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
if (_convertedPosEnd == 0)
{
break;
}
if (_convertedPosEnd > _bufferPos)
{
for (; _bufferPos < _convertedPosEnd; _bufferPos++)
_buffer[_bufferPos] = 0;
_convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
}
}
if (processedSize != NULL)
*processedSize = processedSizeTotal;
return S_OK;
}
STDMETHODIMP CFilterCoder::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
{
return Read(data, size, processedSize);
}
// #endif // _ST_MODE
#ifndef _NO_CRYPTO
STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
{
return _setPassword->CryptoSetPassword(data, size);
}
#endif
#ifndef EXTRACT_ONLY
STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
return _writeCoderProperties->WriteCoderProperties(outStream);
}
#endif
STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
return _setDecoderProperties->SetDecoderProperties2(data, size);
}

132
7zip/Archive/Common/FilterCoder.h Executable file
View File

@@ -0,0 +1,132 @@
// FilterCoder.h
#ifndef __FILTERCODER_H
#define __FILTERCODER_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../IPassword.h"
#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \
{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
*outObject = (void *)(i *)this; AddRef(); return S_OK; }
class CFilterCoder:
public ICompressCoder,
// #ifdef _ST_MODE
public ICompressSetInStream,
public ISequentialInStream,
public ICompressSetOutStream,
public ISequentialOutStream,
public IOutStreamFlush,
// #endif
#ifndef _NO_CRYPTO
public ICryptoSetPassword,
#endif
#ifndef EXTRACT_ONLY
public ICompressWriteCoderProperties,
#endif
public ICompressSetDecoderProperties2,
public CMyUnknownImp
{
protected:
Byte *_buffer;
// #ifdef _ST_MODE
CMyComPtr<ISequentialInStream> _inStream;
CMyComPtr<ISequentialOutStream> _outStream;
UInt32 _bufferPos;
UInt32 _convertedPosBegin;
UInt32 _convertedPosEnd;
// #endif
bool _outSizeIsDefined;
UInt64 _outSize;
UInt64 _nowPos64;
void Init()
{
Filter->Init();
_nowPos64 = 0;
_outSizeIsDefined = false;
}
CMyComPtr<ICryptoSetPassword> _setPassword;
#ifndef EXTRACT_ONLY
CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;
#endif
CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties;
public:
CMyComPtr<ICompressFilter> Filter;
CFilterCoder();
~CFilterCoder();
HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size);
bool NeedMore() const
{ return (!_outSizeIsDefined || (_nowPos64 < _outSize)); }
public:
MY_QUERYINTERFACE_BEGIN
MY_QUERYINTERFACE_ENTRY(ICompressCoder)
// #ifdef _ST_MODE
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)
MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)
MY_QUERYINTERFACE_ENTRY(IOutStreamFlush)
// #endif
#ifndef _NO_CRYPTO
MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)
#endif
#ifndef EXTRACT_ONLY
MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)
#endif
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties)
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// #ifdef _ST_MODE
STDMETHOD(ReleaseInStream)();
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); \
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
STDMETHOD(ReleaseOutStream)();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Flush)();
// #endif
#ifndef _NO_CRYPTO
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
#endif
#ifndef EXTRACT_ONLY
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
#endif
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
};
// #ifdef _ST_MODE
class CInStreamReleaser
{
public:
CFilterCoder *FilterCoder;
CInStreamReleaser(): FilterCoder(0) {}
~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }
};
class COutStreamReleaser
{
public:
CFilterCoder *FilterCoder;
COutStreamReleaser(): FilterCoder(0) {}
~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
};
// #endif
#endif

View File

@@ -4,10 +4,34 @@
#include "InStreamWithCRC.h"
STDMETHODIMP CInStreamWithCRC::Read(void *data,
UINT32 size, UINT32 *processedSize)
STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data,
UInt32 size, UInt32 *processedSize)
{
UINT32 realProcessedSize;
UInt32 realProcessedSize;
HRESULT result = _stream->Read(data, size, &realProcessedSize);
_size += realProcessedSize;
_crc.Update(data, realProcessedSize);
if(processedSize != NULL)
*processedSize = realProcessedSize;
return result;
}
STDMETHODIMP CSequentialInStreamWithCRC::ReadPart(void *data,
UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize;
HRESULT result = _stream->ReadPart(data, size, &realProcessedSize);
_size += realProcessedSize;
_crc.Update(data, realProcessedSize);
if(processedSize != NULL)
*processedSize = realProcessedSize;
return result;
}
STDMETHODIMP CInStreamWithCRC::Read(void *data,
UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize;
HRESULT result = _stream->Read(data, size, &realProcessedSize);
_size += realProcessedSize;
_crc.Update(data, realProcessedSize);
@@ -17,9 +41,9 @@ STDMETHODIMP CInStreamWithCRC::Read(void *data,
}
STDMETHODIMP CInStreamWithCRC::ReadPart(void *data,
UINT32 size, UINT32 *processedSize)
UInt32 size, UInt32 *processedSize)
{
UINT32 realProcessedSize;
UInt32 realProcessedSize;
HRESULT result = _stream->ReadPart(data, size, &realProcessedSize);
_size += realProcessedSize;
_crc.Update(data, realProcessedSize);
@@ -28,8 +52,8 @@ STDMETHODIMP CInStreamWithCRC::ReadPart(void *data,
return result;
}
STDMETHODIMP CInStreamWithCRC::Seek(INT64 offset,
UINT32 seekOrigin, UINT64 *newPosition)
STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset,
UInt32 seekOrigin, UInt64 *newPosition)
{
if (seekOrigin != STREAM_SEEK_SET || offset != 0)
return E_FAIL;

View File

@@ -1,7 +1,5 @@
// InStreamWithCRC.h
// #pragma once
#ifndef __INSTREAMWITHCRC_H
#define __INSTREAMWITHCRC_H
@@ -9,6 +7,31 @@
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
class CSequentialInStreamWithCRC:
public ISequentialInStream,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
private:
CMyComPtr<ISequentialInStream> _stream;
UInt64 _size;
CCRC _crc;
public:
void Init(ISequentialInStream *stream)
{
_stream = stream;
_size = 0;
_crc.Init();
}
void ReleaseStream() { _stream.Release(); }
UInt32 GetCRC() const { return _crc.GetDigest(); }
UInt64 GetSize() const { return _size; }
};
class CInStreamWithCRC:
public IInStream,
public CMyUnknownImp
@@ -16,12 +39,12 @@ class CInStreamWithCRC:
public:
MY_UNKNOWN_IMP
STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(Seek)(INT64 offset, UINT32 seekOrigin, UINT64 *newPosition);
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
private:
CMyComPtr<IInStream> _stream;
UINT64 _size;
UInt64 _size;
CCRC _crc;
public:
void Init(IInStream *stream)
@@ -31,8 +54,8 @@ public:
_crc.Init();
}
void ReleaseStream() { _stream.Release(); }
UINT32 GetCRC() const { return _crc.GetDigest(); }
UINT64 GetSize() const { return _size; }
UInt32 GetCRC() const { return _crc.GetDigest(); }
UInt64 GetSize() const { return _size; }
};
#endif

View File

@@ -10,28 +10,41 @@ namespace NItemName {
static const wchar_t kOSDirDelimiter = '\\';
static const wchar_t kDirDelimiter = '/';
UString MakeLegalName(const UString &aName)
UString MakeLegalName(const UString &name)
{
UString aZipName = aName;
aZipName.Replace(kOSDirDelimiter, kDirDelimiter);
return aZipName;
UString zipName = name;
zipName.Replace(kOSDirDelimiter, kDirDelimiter);
return zipName;
}
UString GetOSName(const UString &aName)
UString GetOSName(const UString &name)
{
UString aNewName = aName;
aNewName.Replace(kDirDelimiter, kOSDirDelimiter);
return aNewName;
UString newName = name;
newName.Replace(kDirDelimiter, kOSDirDelimiter);
return newName;
}
UString GetOSName2(const UString &aName)
UString GetOSName2(const UString &name)
{
if (aName.IsEmpty())
if (name.IsEmpty())
return UString();
UString aNewName = GetOSName(aName);
if (aNewName[aNewName.Length() - 1] == kOSDirDelimiter)
aNewName.Delete(aNewName.Length() - 1);
return aNewName;
UString newName = GetOSName(name);
if (newName[newName.Length() - 1] == kOSDirDelimiter)
newName.Delete(newName.Length() - 1);
return newName;
}
bool HasTailSlash(const AString &name, UINT codePage)
{
if (name.IsEmpty())
return false;
LPCSTR prev =
#ifdef _WIN32
CharPrevExA(codePage, name, &name[name.Length()], 0);
#else
(LPCSTR)(name) + (name.Length() - 1);
#endif
return (*prev == '/');
}
}}

View File

@@ -1,7 +1,5 @@
// Archive/Common/ItemNameUtils.h
#pragma once
#ifndef __ARCHIVE_ITEMNAMEUTILS_H
#define __ARCHIVE_ITEMNAMEUTILS_H
@@ -10,9 +8,10 @@
namespace NArchive {
namespace NItemName {
UString MakeLegalName(const UString &aName);
UString GetOSName(const UString &aName);
UString GetOSName2(const UString &aName);
UString MakeLegalName(const UString &name);
UString GetOSName(const UString &name);
UString GetOSName2(const UString &name);
bool HasTailSlash(const AString &name, UINT codePage);
}}

View File

@@ -0,0 +1,213 @@
// MultiStream.cpp
#include "StdAfx.h"
#include "MultiStream.h"
STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if(processedSize != NULL)
*processedSize = 0;
while(_streamIndex < Streams.Size() && size > 0)
{
CSubStreamInfo &s = Streams[_streamIndex];
if (_pos == s.Size)
{
_streamIndex++;
_pos = 0;
continue;
}
RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0));
UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos));
UInt32 realProcessed;
HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed);
data = (void *)((Byte *)data + realProcessed);
size -= realProcessed;
if(processedSize != NULL)
*processedSize += realProcessed;
_pos += realProcessed;
_seekPos += realProcessed;
RINOK(result);
if (realProcessed == 0)
break;
}
return S_OK;
}
STDMETHODIMP CMultiStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
{
return Read(data, size, processedSize);
}
STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin,
UInt64 *newPosition)
{
UInt64 newPos;
if(seekOrigin >= 3)
return STG_E_INVALIDFUNCTION;
switch(seekOrigin)
{
case STREAM_SEEK_SET:
newPos = offset;
break;
case STREAM_SEEK_CUR:
newPos = _seekPos + offset;
break;
case STREAM_SEEK_END:
newPos = _totalLength + offset;
break;
}
_seekPos = 0;
for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++)
{
UInt64 size = Streams[_streamIndex].Size;
if (newPos < _seekPos + size)
{
_pos = newPos - _seekPos;
_seekPos += _pos;
if (newPosition != 0)
*newPosition = newPos;
return S_OK;
}
_seekPos += size;
}
if (newPos == _seekPos)
{
if (newPosition != 0)
*newPosition = newPos;
return S_OK;
}
return E_FAIL;
}
/*
class COutVolumeStream:
public ISequentialOutStream,
public CMyUnknownImp
{
int _volIndex;
UInt64 _volSize;
UInt64 _curPos;
CMyComPtr<ISequentialOutStream> _volumeStream;
COutArchive _archive;
CCRC _crc;
public:
MY_UNKNOWN_IMP
CFileItem _file;
CUpdateOptions _options;
CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
void Init(IArchiveUpdateCallback2 *volumeCallback,
const UString &name)
{
_file.Name = name;
_file.IsStartPosDefined = true;
_file.StartPos = 0;
VolumeCallback = volumeCallback;
_volIndex = 0;
_volSize = 0;
}
HRESULT Flush();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
};
HRESULT COutVolumeStream::Flush()
{
if (_volumeStream)
{
_file.UnPackSize = _curPos;
_file.FileCRC = _crc.GetDigest();
RINOK(WriteVolumeHeader(_archive, _file, _options));
_archive.Close();
_volumeStream.Release();
_file.StartPos += _file.UnPackSize;
}
return S_OK;
}
*/
/*
STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if(processedSize != NULL)
*processedSize = 0;
while(size > 0)
{
if (_streamIndex >= Streams.Size())
{
CSubStreamInfo subStream;
RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));
RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));
subStream.Pos = 0;
Streams.Add(subStream);
continue;
}
CSubStreamInfo &subStream = Streams[_streamIndex];
if (_offsetPos >= subStream.Size)
{
_offsetPos -= subStream.Size;
_streamIndex++;
continue;
}
if (_offsetPos != subStream.Pos)
{
CMyComPtr<IOutStream> outStream;
RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
subStream.Pos = _offsetPos;
}
UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
UInt32 realProcessed;
RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
data = (void *)((Byte *)data + realProcessed);
size -= realProcessed;
subStream.Pos += realProcessed;
_offsetPos += realProcessed;
_absPos += realProcessed;
if (_absPos > _length)
_length = _absPos;
if(processedSize != NULL)
*processedSize += realProcessed;
if (subStream.Pos == subStream.Size)
{
_streamIndex++;
_offsetPos = 0;
}
if (realProcessed != curSize)
return E_FAIL;
}
return S_OK;
}
STDMETHODIMP COutMultiStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
{
return Write(data, size, processedSize);
}
STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
if(seekOrigin >= 3)
return STG_E_INVALIDFUNCTION;
switch(seekOrigin)
{
case STREAM_SEEK_SET:
_absPos = offset;
break;
case STREAM_SEEK_CUR:
_absPos += offset;
break;
case STREAM_SEEK_END:
_absPos = _length + offset;
break;
}
_offsetPos = _absPos;
_streamIndex = 0;
return S_OK;
}
*/

View File

@@ -0,0 +1,78 @@
// MultiStream.h
#ifndef __MULTISTREAM_H
#define __MULTISTREAM_H
#include "../../../Common/MyCom.h"
#include "../../../Common/Vector.h"
#include "../../Archive/IArchive.h"
class CMultiStream:
public IInStream,
public CMyUnknownImp
{
int _streamIndex;
UInt64 _pos;
UInt64 _seekPos;
UInt64 _totalLength;
public:
struct CSubStreamInfo
{
CMyComPtr<IInStream> Stream;
UInt64 Pos;
UInt64 Size;
};
CObjectVector<CSubStreamInfo> Streams;
void Init()
{
_streamIndex = 0;
_pos = 0;
_seekPos = 0;
_totalLength = 0;
for (int i = 0; i < Streams.Size(); i++)
_totalLength += Streams[i].Size;
}
MY_UNKNOWN_IMP1(IInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
};
/*
class COutMultiStream:
public IOutStream,
public CMyUnknownImp
{
int _streamIndex; // required stream
UInt64 _offsetPos; // offset from start of _streamIndex index
UInt64 _absPos;
UInt64 _length;
struct CSubStreamInfo
{
CMyComPtr<ISequentialOutStream> Stream;
UInt64 Size;
UInt64 Pos;
};
CObjectVector<CSubStreamInfo> Streams;
public:
CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
void Init()
{
_streamIndex = 0;
_offsetPos = 0;
_absPos = 0;
_length = 0;
}
MY_UNKNOWN_IMP1(IOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
};
*/
#endif

View File

@@ -5,10 +5,10 @@
#include "OutStreamWithCRC.h"
STDMETHODIMP COutStreamWithCRC::Write(const void *data,
UINT32 size, UINT32 *processedSize)
UInt32 size, UInt32 *processedSize)
{
HRESULT result;
UINT32 realProcessedSize;
UInt32 realProcessedSize;
if(!_stream)
{
realProcessedSize = size;
@@ -23,9 +23,9 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data,
}
STDMETHODIMP COutStreamWithCRC::WritePart(const void *data,
UINT32 size, UINT32 *processedSize)
UInt32 size, UInt32 *processedSize)
{
UINT32 realProcessedSize;
UInt32 realProcessedSize;
HRESULT result;
if(!_stream)
{

View File

@@ -1,7 +1,5 @@
// OutStreamWithCRC.h
// #pragma once
#ifndef __OUTSTREAMWITHCRC_H
#define __OUTSTREAMWITHCRC_H
@@ -16,8 +14,8 @@ class COutStreamWithCRC:
public:
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize);
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
private:
CCRC _crc;
CMyComPtr<ISequentialOutStream> _stream;
@@ -28,7 +26,7 @@ public:
_crc.Init();
}
void ReleaseStream() { _stream.Release(); }
UINT32 GetCRC() const { return _crc.GetDigest(); }
UInt32 GetCRC() const { return _crc.GetDigest(); }
void InitCRC() { _crc.Init(); }
};

View File

@@ -1,8 +1,8 @@
// stdafx.h
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#include "../../../Common/MyWindows.h"
#endif
#endif