This commit is contained in:
Igor Pavlov
2011-04-11 00:00:00 +00:00
committed by Kornel Lesiński
parent de4f8c22fe
commit 35596517f2
322 changed files with 9989 additions and 7759 deletions

View File

@@ -122,11 +122,24 @@ DWORD CThreadInfo::ThreadFunc()
#endif
CEncoder::CEncoder():
NumPasses(1),
m_OptimizeNumTables(false),
m_BlockSizeMult(kBlockSizeMultMax)
void CEncProps::Normalize(int level)
{
if (level < 0) level = 5;
if (level > 9) level = 9;
if (NumPasses == (UInt32)(Int32)-1)
NumPasses = (level >= 9 ? 7 : (level >= 7 ? 2 : 1));
if (NumPasses < kBlockSizeMultMin) NumPasses = kBlockSizeMultMin;
if (NumPasses > kBlockSizeMultMax) NumPasses = kBlockSizeMultMax;
if (BlockSizeMult == (UInt32)(Int32)-1)
BlockSizeMult = (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1));
if (BlockSizeMult == 0) BlockSizeMult = 1;
if (BlockSizeMult > kNumPassesMax) BlockSizeMult = kNumPassesMax;
}
CEncoder::CEncoder()
{
_props.Normalize(-1);
#ifndef _7ZIP_ST
ThreadsInfo = 0;
m_NumThreadsPrev = 0;
@@ -198,7 +211,7 @@ UInt32 CEncoder::ReadRleBlock(Byte *buffer)
Byte prevByte;
if (m_InStream.ReadByte(prevByte))
{
UInt32 blockSize = m_BlockSizeMult * kBlockSizeStep - 1;
UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1;
int numReps = 1;
buffer[i++] = prevByte;
while (i < blockSize) // "- 1" to support RLE
@@ -678,7 +691,7 @@ HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize)
m_NumCrcs = 0;
EncodeBlock2(m_Block, blockSize, Encoder->NumPasses);
EncodeBlock2(m_Block, blockSize, Encoder->_props.NumPasses);
#ifndef _7ZIP_ST
if (Encoder->MtMode)
@@ -738,7 +751,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
ti.Encoder = this;
#endif
ti.m_OptimizeNumTables = m_OptimizeNumTables;
ti.m_OptimizeNumTables = _props.DoOptimizeNumTables();
if (!ti.Alloc())
return E_OUTOFMEMORY;
@@ -770,7 +783,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
WriteByte(kArSig0);
WriteByte(kArSig1);
WriteByte(kArSig2);
WriteByte((Byte)(kArSig3 + m_BlockSizeMult));
WriteByte((Byte)(kArSig3 + _props.BlockSizeMult));
#ifndef _7ZIP_ST
@@ -832,62 +845,46 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream
catch(...) { return S_FALSE; }
}
HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
{
for(UInt32 i = 0; i < numProps; i++)
int level = -1;
CEncProps props;
for (UInt32 i = 0; i < numProps; i++)
{
const PROPVARIANT &prop = props[i];
switch(propIDs[i])
const PROPVARIANT &prop = coderProps[i];
PROPID propID = propIDs[i];
if (propID >= NCoderPropID::kReduceSize)
continue;
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 v = (UInt32)prop.ulVal;
switch (propID)
{
case NCoderPropID::kNumPasses:
{
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 numPasses = prop.ulVal;
if (numPasses == 0)
numPasses = 1;
if (numPasses > kNumPassesMax)
numPasses = kNumPassesMax;
NumPasses = numPasses;
m_OptimizeNumTables = (NumPasses > 1);
break;
}
case NCoderPropID::kDictionarySize:
{
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 dictionary = prop.ulVal / kBlockSizeStep;
if (dictionary < kBlockSizeMultMin)
dictionary = kBlockSizeMultMin;
else if (dictionary > kBlockSizeMultMax)
dictionary = kBlockSizeMultMax;
m_BlockSizeMult = dictionary;
break;
}
case NCoderPropID::kNumPasses: props.NumPasses = v; break;
case NCoderPropID::kDictionarySize: props.BlockSizeMult = v / kBlockSizeStep; break;
case NCoderPropID::kLevel: level = v; break;
case NCoderPropID::kNumThreads:
{
#ifndef _7ZIP_ST
if (prop.vt != VT_UI4)
return E_INVALIDARG;
NumThreads = prop.ulVal;
if (NumThreads < 1)
NumThreads = 1;
SetNumberOfThreads(v);
#endif
break;
}
default:
return E_INVALIDARG;
default: return E_INVALIDARG;
}
}
props.Normalize(level);
_props = props;
return S_OK;
}
#ifndef _7ZIP_ST
STDMETHODIMP CEncoder::SetNumberOfThreads(UInt32 numThreads)
{
const UInt32 kNumThreadsMax = 64;
if (numThreads < 1) numThreads = 1;
if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;
NumThreads = numThreads;
if (NumThreads < 1)
NumThreads = 1;
return S_OK;
}
#endif

View File

@@ -145,6 +145,20 @@ public:
HRESULT EncodeBlock3(UInt32 blockSize);
};
struct CEncProps
{
UInt32 BlockSizeMult;
UInt32 NumPasses;
CEncProps()
{
BlockSizeMult = (UInt32)(Int32)-1;
NumPasses = (UInt32)(Int32)-1;
}
void Normalize(int level);
bool DoOptimizeNumTables() const { return NumPasses > 1; }
};
class CEncoder :
public ICompressCoder,
public ICompressSetCoderProperties,
@@ -153,17 +167,12 @@ class CEncoder :
#endif
public CMyUnknownImp
{
UInt32 m_BlockSizeMult;
bool m_OptimizeNumTables;
UInt32 m_NumPassesPrev;
UInt32 m_NumThreadsPrev;
public:
CInBuffer m_InStream;
Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.
CBitmEncoder<COutBuffer> m_OutStream;
UInt32 NumPasses;
CEncProps _props;
CBZip2CombinedCrc CombinedCrc;
#ifndef _7ZIP_ST

View File

@@ -21,12 +21,12 @@ namespace NCompress {
namespace NDeflate {
namespace NEncoder {
const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio.
const UInt32 kNumTables = (1 << kNumDivPassesMax);
static const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio.
static const UInt32 kNumTables = (1 << kNumDivPassesMax);
static UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio.
static UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
static UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
static const UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio.
static const UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
static const UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
static const UInt32 kMaxUncompressedBlockSize = ((1 << 16) - 1) * 1; // [1, (1 << 32))
static const UInt32 kMatchArraySize = kMaxUncompressedBlockSize * 10; // [kMatchMaxLen * 2, (1 << 32))
@@ -37,9 +37,9 @@ static const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize
static const int kMaxCodeBitLength = 11;
static const int kMaxLevelBitLength = 7;
static Byte kNoLiteralStatPrice = 11;
static Byte kNoLenStatPrice = 11;
static Byte kNoPosStatPrice = 6;
static const Byte kNoLiteralStatPrice = 11;
static const Byte kNoLenStatPrice = 11;
static const Byte kNoPosStatPrice = 6;
static Byte g_LenSlots[kNumLenSymbolsMax];
static Byte g_FastPos[1 << 9];
@@ -83,21 +83,61 @@ static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
void CEncProps::Normalize()
{
int level = Level;
if (level < 0) level = 5;
Level = level;
if (algo < 0) algo = (level < 5 ? 0 : 1);
if (fb < 0) fb = (level < 7 ? 32 : (level < 9 ? 64 : 128));
if (btMode < 0) btMode = (algo == 0 ? 0 : 1);
if (mc == 0) mc = (16 + (fb >> 1));
if (numPasses == (UInt32)(Int32)-1) numPasses = (level < 7 ? 1 : (level < 9 ? 3 : 10));
}
void CCoder::SetProps(const CEncProps *props2)
{
CEncProps props = *props2;
props.Normalize();
m_MatchFinderCycles = props.mc;
{
unsigned fb = props.fb;
if (fb < kMatchMinLen)
fb = kMatchMinLen;
if (fb > m_MatchMaxLen)
fb = m_MatchMaxLen;
m_NumFastBytes = fb;
}
_fastMode = (props.algo == 0);
_btMode = (props.btMode != 0);
m_NumDivPasses = props.numPasses;
if (m_NumDivPasses == 0)
m_NumDivPasses = 1;
if (m_NumDivPasses == 1)
m_NumPasses = 1;
else if (m_NumDivPasses <= kNumDivPassesMax)
m_NumPasses = 2;
else
{
m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax);
m_NumDivPasses = kNumDivPassesMax;
}
}
CCoder::CCoder(bool deflate64Mode):
m_Deflate64Mode(deflate64Mode),
m_NumPasses(1),
m_NumDivPasses(1),
m_NumFastBytes(32),
_fastMode(false),
_btMode(true),
m_OnePosMatchesMemory(0),
m_DistanceMemory(0),
m_Created(false),
m_Values(0),
m_Tables(0),
m_MatchFinderCycles(0)
// m_SetMfPasses(0)
m_Tables(0)
{
{
CEncProps props;
SetProps(&props);
}
m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;
m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;
m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;
@@ -160,56 +200,30 @@ HRESULT CCoder::Create()
COM_TRY_END
}
HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
{
CEncProps props;
for (UInt32 i = 0; i < numProps; i++)
{
const PROPVARIANT &prop = props[i];
switch(propIDs[i])
const PROPVARIANT &prop = coderProps[i];
PROPID propID = propIDs[i];
if (propID >= NCoderPropID::kReduceSize)
continue;
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 v = (UInt32)prop.ulVal;
switch (propID)
{
case NCoderPropID::kNumPasses:
if (prop.vt != VT_UI4)
return E_INVALIDARG;
m_NumDivPasses = prop.ulVal;
if (m_NumDivPasses == 0)
m_NumDivPasses = 1;
if (m_NumDivPasses == 1)
m_NumPasses = 1;
else if (m_NumDivPasses <= kNumDivPassesMax)
m_NumPasses = 2;
else
{
m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax);
m_NumDivPasses = kNumDivPassesMax;
}
break;
case NCoderPropID::kNumFastBytes:
if (prop.vt != VT_UI4)
return E_INVALIDARG;
m_NumFastBytes = prop.ulVal;
if(m_NumFastBytes < kMatchMinLen || m_NumFastBytes > m_MatchMaxLen)
return E_INVALIDARG;
break;
case NCoderPropID::kMatchFinderCycles:
{
if (prop.vt != VT_UI4)
return E_INVALIDARG;
m_MatchFinderCycles = prop.ulVal;
break;
}
case NCoderPropID::kAlgorithm:
{
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 maximize = prop.ulVal;
_fastMode = (maximize == 0);
_btMode = !_fastMode;
break;
}
default:
return E_INVALIDARG;
case NCoderPropID::kNumPasses: props.numPasses = v; break;
case NCoderPropID::kNumFastBytes: props.fb = v; break;
case NCoderPropID::kMatchFinderCycles: props.mc = v; break;
case NCoderPropID::kAlgorithm: props.algo = v; break;
case NCoderPropID::kLevel: props.Level = v; break;
case NCoderPropID::kNumThreads: break;
default: return E_INVALIDARG;
}
}
SetProps(&props);
return S_OK;
}

View File

@@ -52,6 +52,25 @@ typedef struct _CSeqInStream
CMyComPtr<ISequentialInStream> RealStream;
} CSeqInStream;
struct CEncProps
{
int Level;
int algo;
int fb;
int btMode;
UInt32 mc;
UInt32 numPasses;
CEncProps()
{
Level = -1;
mc = 0;
algo = fb = btMode = -1;
numPasses = (UInt32)(Int32)-1;
}
void Normalize();
};
class CCoder
{
CMatchFinder _lzInWindow;
@@ -116,7 +135,6 @@ public:
COptimal m_Optimum[kNumOpts];
UInt32 m_MatchFinderCycles;
// IMatchFinderSetNumPasses *m_SetMfPasses;
void GetMatches();
void MovePos(UInt32 num);
@@ -164,6 +182,7 @@ public:
UInt32 GetBlockPrice(int tableIndex, int numDivPasses);
void CodeBlock(int tableIndex, bool finalBlock);
void SetProps(const CEncProps *props2);
public:
CCoder(bool deflate64Mode = false);
~CCoder();

View File

@@ -62,9 +62,22 @@ STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROP
for (UInt32 i = 0; i < numProps; i++)
{
const PROPVARIANT &prop = props[i];
if (propIDs[i] != NCoderPropID::kDefaultProp || prop.vt != VT_UI4 || prop.ulVal < 1 || prop.ulVal > 256)
PROPID propID = propIDs[i];
if (propID >= NCoderPropID::kReduceSize)
continue;
if (prop.vt != VT_UI4)
return E_INVALIDARG;
delta = prop.ulVal;
switch (propID)
{
case NCoderPropID::kDefaultProp:
delta = (UInt32)prop.ulVal;
if (delta < 1 || delta > 256)
return E_INVALIDARG;
break;
case NCoderPropID::kNumThreads: break;
case NCoderPropID::kLevel: break;
default: return E_INVALIDARG;
}
}
_delta = delta;
return S_OK;

View File

@@ -9,7 +9,13 @@
#include "../Common/RegisterCodec.h"
extern "C"
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
BOOL WINAPI DllMain(
#ifdef UNDER_CE
HANDLE
#else
HINSTANCE
#endif
/* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
{
return TRUE;
}
@@ -25,4 +31,3 @@ STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
{
return CreateCoder(clsid, iid, outObject);
}

View File

@@ -73,6 +73,8 @@ static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes)
return 1;
}
#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break;
HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)
{
if (propID == NCoderPropID::kMatchFinder)
@@ -81,18 +83,29 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)
return E_INVALIDARG;
return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;
}
if (propID > NCoderPropID::kReduceSize)
return S_OK;
if (propID == NCoderPropID::kReduceSize)
{
if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1)
ep.reduceSize = (UInt32)prop.uhVal.QuadPart;
return S_OK;
}
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 v = prop.ulVal;
switch (propID)
{
case NCoderPropID::kNumFastBytes: ep.fb = v; break;
case NCoderPropID::kMatchFinderCycles: ep.mc = v; break;
case NCoderPropID::kAlgorithm: ep.algo = v; break;
case NCoderPropID::kDictionarySize: ep.dictSize = v; break;
case NCoderPropID::kPosStateBits: ep.pb = v; break;
case NCoderPropID::kLitPosBits: ep.lp = v; break;
case NCoderPropID::kLitContextBits: ep.lc = v; break;
case NCoderPropID::kDefaultProp: if (v > 31) return E_INVALIDARG; ep.dictSize = (UInt32)1 << (unsigned)v; break;
SET_PROP_32(kLevel, level)
SET_PROP_32(kNumFastBytes, fb)
SET_PROP_32(kMatchFinderCycles, mc)
SET_PROP_32(kAlgorithm, algo)
SET_PROP_32(kDictionarySize, dictSize)
SET_PROP_32(kPosStateBits, pb)
SET_PROP_32(kLitPosBits, lp)
SET_PROP_32(kLitContextBits, lc)
SET_PROP_32(kNumThreads, numThreads)
default: return E_INVALIDARG;
}
return S_OK;
@@ -112,8 +125,6 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
{
case NCoderPropID::kEndMarker:
if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break;
case NCoderPropID::kNumThreads:
if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break;
default:
RINOK(SetLzmaProp(propID, prop, props));
}

View File

@@ -360,6 +360,9 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
{
if (outSize == NULL)
return E_FAIL;
// flush calls m_x86ConvertOutStreamSpec->flush, so we must init x86Convert.
if (!_keepHistory)
m_x86ConvertOutStreamSpec->Init(false, 0);
_remainLen = kLenIdNeedInit;
m_OutWindowStream.Init(_keepHistory);
return S_OK;

View File

@@ -1,5 +1,4 @@
// PpmdEncoder.cpp
// 2009-03-11 : Igor Pavlov : Public domain
#include "StdAfx.h"
@@ -19,11 +18,35 @@ static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
static void SzBigFree(void *, void *address) { BigFree(address); }
static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
CEncoder::CEncoder():
_inBuf(NULL),
_usedMemSize(1 << 24),
_order(6)
static const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 };
void CEncProps::Normalize(int level)
{
if (level < 0) level = 5;
if (level > 9) level = 9;
if (MemSize == (UInt32)(Int32)-1)
MemSize = level >= 9 ? ((UInt32)192 << 20) : ((UInt32)1 << (level + 19));
const unsigned kMult = 16;
if (MemSize / kMult > ReduceSize)
{
for (unsigned i = 16; i <= 31; i++)
{
UInt32 m = (UInt32)1 << i;
if (ReduceSize <= m / kMult)
{
if (MemSize > m)
MemSize = m;
break;
}
}
}
if (Order == -1) Order = kOrders[level];
}
CEncoder::CEncoder():
_inBuf(NULL)
{
_props.Normalize(-1);
_rangeEnc.Stream = &_outStream.p;
Ppmd7_Construct(&_ppmd);
}
@@ -34,30 +57,44 @@ CEncoder::~CEncoder()
Ppmd7_Free(&_ppmd, &g_BigAlloc);
}
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
{
int level = -1;
CEncProps props;
for (UInt32 i = 0; i < numProps; i++)
{
const PROPVARIANT &prop = props[i];
const PROPVARIANT &prop = coderProps[i];
PROPID propID = propIDs[i];
if (propID > NCoderPropID::kReduceSize)
continue;
if (propID == NCoderPropID::kReduceSize)
{
if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1)
props.ReduceSize = (UInt32)prop.uhVal.QuadPart;
continue;
}
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 v = (UInt32)prop.ulVal;
switch(propIDs[i])
switch (propID)
{
case NCoderPropID::kUsedMemorySize:
if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0)
return E_INVALIDARG;
_usedMemSize = v;
props.MemSize = v;
break;
case NCoderPropID::kOrder:
if (v < 2 || v > 32)
return E_INVALIDARG;
_order = (Byte)v;
props.Order = (Byte)v;
break;
default:
return E_INVALIDARG;
case NCoderPropID::kNumThreads: break;
case NCoderPropID::kLevel: level = (int)v; break;
default: return E_INVALIDARG;
}
}
props.Normalize(level);
_props = props;
return S_OK;
}
@@ -65,8 +102,8 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
const UInt32 kPropSize = 5;
Byte props[kPropSize];
props[0] = _order;
SetUi32(props + 1, _usedMemSize);
props[0] = (Byte)_props.Order;
SetUi32(props + 1, _props.MemSize);
return WriteStream(outStream, props, kPropSize);
}
@@ -81,14 +118,14 @@ HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS
}
if (!_outStream.Alloc(1 << 20))
return E_OUTOFMEMORY;
if (!Ppmd7_Alloc(&_ppmd, _usedMemSize, &g_BigAlloc))
if (!Ppmd7_Alloc(&_ppmd, _props.MemSize, &g_BigAlloc))
return E_OUTOFMEMORY;
_outStream.Stream = outStream;
_outStream.Init();
Ppmd7z_RangeEnc_Init(&_rangeEnc);
Ppmd7_Init(&_ppmd, _order);
Ppmd7_Init(&_ppmd, _props.Order);
UInt64 processed = 0;
for (;;)

View File

@@ -1,5 +1,4 @@
// PpmdEncoder.h
// 2009-03-11 : Igor Pavlov : Public domain
#ifndef __COMPRESS_PPMD_ENCODER_H
#define __COMPRESS_PPMD_ENCODER_H
@@ -15,6 +14,21 @@
namespace NCompress {
namespace NPpmd {
struct CEncProps
{
UInt32 MemSize;
UInt32 ReduceSize;
int Order;
CEncProps()
{
MemSize = (UInt32)(Int32)-1;
ReduceSize = (UInt32)(Int32)-1;
Order = -1;
}
void Normalize(int level);
};
class CEncoder :
public ICompressCoder,
public ICompressSetCoderProperties,
@@ -25,20 +39,15 @@ class CEncoder :
CByteOutBufWrap _outStream;
CPpmd7z_RangeEnc _rangeEnc;
CPpmd7 _ppmd;
UInt32 _usedMemSize;
Byte _order;
CEncProps _props;
public:
MY_UNKNOWN_IMP2(
ICompressSetCoderProperties,
ICompressWriteCoderProperties)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
CEncoder();
~CEncoder();
};

View File

@@ -1,10 +1,10 @@
// PpmdZip.cpp
// 2010-03-24 : Igor Pavlov : Public domain
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "../Common/RegisterCodec.h"
#include "../Common/StreamUtils.h"
#include "PpmdZip.h"
@@ -128,69 +128,109 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
// ---------- Encoder ----------
void CEncProps::Normalize(int level)
{
if (level < 0) level = 5;
if (level == 0) level = 1;
if (level > 9) level = 9;
if (MemSizeMB == (UInt32)(Int32)-1)
MemSizeMB = (1 << ((level > 8 ? 8 : level) - 1));
const unsigned kMult = 16;
if ((MemSizeMB << 20) / kMult > ReduceSize)
{
for (UInt32 m = (1 << 20); m <= (1 << 28); m <<= 1)
{
if (ReduceSize <= m / kMult)
{
m >>= 20;
if (MemSizeMB > m)
MemSizeMB = m;
break;
}
}
}
if (Order == -1) Order = 3 + level;
if (Restor == -1)
Restor = level < 7 ?
PPMD8_RESTORE_METHOD_RESTART :
PPMD8_RESTORE_METHOD_CUT_OFF;
}
CEncoder::~CEncoder()
{
Ppmd8_Free(&_ppmd, &g_BigAlloc);
}
HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
{
int level = -1;
CEncProps props;
for (UInt32 i = 0; i < numProps; i++)
{
const PROPVARIANT &prop = props[i];
const PROPVARIANT &prop = coderProps[i];
PROPID propID = propIDs[i];
if (propID > NCoderPropID::kReduceSize)
continue;
if (propID == NCoderPropID::kReduceSize)
{
if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1)
props.ReduceSize = (UInt32)prop.uhVal.QuadPart;
continue;
}
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 v = (UInt32)prop.ulVal;
switch(propIDs[i])
switch (propID)
{
case NCoderPropID::kAlgorithm:
if (v > 1)
return E_INVALIDARG;
_restor = v;
break;
case NCoderPropID::kUsedMemorySize:
if (v < (1 << 20) || v > (1 << 28))
return E_INVALIDARG;
_usedMemInMB = v >> 20;
props.MemSizeMB = v >> 20;
break;
case NCoderPropID::kOrder:
if (v < PPMD8_MIN_ORDER || v > PPMD8_MAX_ORDER)
return E_INVALIDARG;
_order = (Byte)v;
props.Order = (Byte)v;
break;
default:
return E_INVALIDARG;
case NCoderPropID::kNumThreads: break;
case NCoderPropID::kLevel: level = (int)v; break;
case NCoderPropID::kAlgorithm:
if (v > 1)
return E_INVALIDARG;
props.Restor = v;
break;
default: return E_INVALIDARG;
}
}
props.Normalize(level);
_props = props;
return S_OK;
}
CEncoder::CEncoder():
_usedMemInMB(16),
_order(6),
_restor(PPMD8_RESTORE_METHOD_RESTART)
CEncoder::CEncoder()
{
_props.Normalize(-1);
_ppmd.Stream.Out = &_outStream.p;
Ppmd8_Construct(&_ppmd);
}
HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
{
if (!_inStream.Alloc())
return E_OUTOFMEMORY;
if (!_outStream.Alloc(1 << 20))
return E_OUTOFMEMORY;
if (!Ppmd8_Alloc(&_ppmd, _usedMemInMB << 20, &g_BigAlloc))
if (!Ppmd8_Alloc(&_ppmd, _props.MemSizeMB << 20, &g_BigAlloc))
return E_OUTOFMEMORY;
_outStream.Stream = outStream;
_outStream.Init();
Ppmd8_RangeEnc_Init(&_ppmd);
Ppmd8_Init(&_ppmd, _order, _restor);
Ppmd8_Init(&_ppmd, _props.Order, _props.Restor);
UInt32 val = (UInt32)((_order - 1) + ((_usedMemInMB - 1) << 4) + (_restor << 12));
UInt32 val = (UInt32)((_props.Order - 1) + ((_props.MemSizeMB - 1) << 4) + (_props.Restor << 12));
_outStream.WriteByte((Byte)(val & 0xFF));
_outStream.WriteByte((Byte)(val >> 8));
RINOK(_outStream.Res);
@@ -220,4 +260,14 @@ HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS
}
}
/*
static void *CreateCodec() { return (void *)(ICompressCoder *)(new CDecoder(false)); }
static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new CEncoder); }
static CCodecInfo g_CodecInfo =
{ CreateCodec, CreateCodecOut, 0x040162, L"PPMdZIP", 1, false };
REGISTER_CODEC(PPMdZIP)
*/
}}

View File

@@ -1,5 +1,4 @@
// PpmdZip.h
// 2010-03-11 : Igor Pavlov : Public domain
#ifndef __COMPRESS_PPMD_ZIP_H
#define __COMPRESS_PPMD_ZIP_H
@@ -48,21 +47,37 @@ public:
~CDecoder();
};
struct CEncProps
{
UInt32 MemSizeMB;
UInt32 ReduceSize;
int Order;
int Restor;
CEncProps()
{
MemSizeMB = (UInt32)(Int32)-1;
ReduceSize = (UInt32)(Int32)-1;
Order = -1;
Restor = -1;
}
void Normalize(int level);
};
class CEncoder :
public ICompressCoder,
public ICompressSetCoderProperties,
public CMyUnknownImp
{
CByteOutBufWrap _outStream;
CBuf _inStream;
CPpmd8 _ppmd;
UInt32 _usedMemInMB;
unsigned _order;
unsigned _restor;
CEncProps _props;
public:
MY_UNKNOWN_IMP
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
CEncoder();
~CEncoder();
};

View File

@@ -33,14 +33,6 @@ HRESULT CDecoder::CodeSpec(UInt32 curSize)
{
if (_remainLen == kLenIdNeedInit)
{
if (!_keepHistory)
{
if (!_outWindowStream.Create((UInt32)1 << _numDictBits))
return E_OUTOFMEMORY;
Init();
}
if (!_rangeDecoder.Create(1 << 20))
return E_OUTOFMEMORY;
_rangeDecoder.Init();
_remainLen = 0;
}
@@ -169,6 +161,20 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
return E_FAIL;
_remainLen = kLenIdNeedInit;
_outWindowStream.Init(_keepHistory);
if (!_keepHistory)
Init();
return S_OK;
}
HRESULT CDecoder::SetParams(int numDictBits)
{
if (numDictBits > 21)
return E_INVALIDARG;
_numDictBits = numDictBits;
if (!_outWindowStream.Create((UInt32)1 << _numDictBits))
return E_OUTOFMEMORY;
if (!_rangeDecoder.Create(1 << 20))
return E_OUTOFMEMORY;
return S_OK;
}

View File

@@ -253,7 +253,7 @@ public:
STDMETHOD(ReleaseInStream)();
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
void SetParams(int numDictBits) { _numDictBits = numDictBits; }
HRESULT SetParams(int numDictBits);
void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; }
CDecoder(): _keepHistory(false) {}
virtual ~CDecoder() {}