xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/DeflateEncoder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // DeflateEncoder.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Alloc.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/HuffEnc.h"
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #include "../Common/CWrappers.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "DeflateEncoder.h"
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker #undef NO_INLINE
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker #ifdef _MSC_VER
17*f6dc9357SAndroid Build Coastguard Worker #define NO_INLINE Z7_NO_INLINE
18*f6dc9357SAndroid Build Coastguard Worker #else
19*f6dc9357SAndroid Build Coastguard Worker #define NO_INLINE
20*f6dc9357SAndroid Build Coastguard Worker #endif
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
23*f6dc9357SAndroid Build Coastguard Worker namespace NDeflate {
24*f6dc9357SAndroid Build Coastguard Worker namespace NEncoder {
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio.
27*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNumTables = (1 << kNumDivPassesMax);
28*f6dc9357SAndroid Build Coastguard Worker 
29*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio.
30*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
31*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.
32*f6dc9357SAndroid Build Coastguard Worker 
33*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMaxUncompressedBlockSize = ((1 << 16) - 1) * 1; // [1, (1 << 32))
34*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMatchArraySize = kMaxUncompressedBlockSize * 10; // [kMatchMaxLen * 2, (1 << 32))
35*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMatchArrayLimit = kMatchArraySize - kMatchMaxLen * 4 * sizeof(UInt16);
36*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize -
37*f6dc9357SAndroid Build Coastguard Worker     kMatchMaxLen - kNumOpts;
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker // static const unsigned kMaxCodeBitLength = 11;
40*f6dc9357SAndroid Build Coastguard Worker static const unsigned kMaxLevelBitLength = 7;
41*f6dc9357SAndroid Build Coastguard Worker 
42*f6dc9357SAndroid Build Coastguard Worker static const Byte kNoLiteralStatPrice = 11;
43*f6dc9357SAndroid Build Coastguard Worker static const Byte kNoLenStatPrice = 11;
44*f6dc9357SAndroid Build Coastguard Worker static const Byte kNoPosStatPrice = 6;
45*f6dc9357SAndroid Build Coastguard Worker 
46*f6dc9357SAndroid Build Coastguard Worker MY_ALIGN(64)
47*f6dc9357SAndroid Build Coastguard Worker static Byte g_LenSlots[kNumLenSymbolsMax];
48*f6dc9357SAndroid Build Coastguard Worker 
49*f6dc9357SAndroid Build Coastguard Worker #define kNumLogBits 9    // do not change it
50*f6dc9357SAndroid Build Coastguard Worker MY_ALIGN(64)
51*f6dc9357SAndroid Build Coastguard Worker static Byte g_FastPos[1 << kNumLogBits];
52*f6dc9357SAndroid Build Coastguard Worker 
53*f6dc9357SAndroid Build Coastguard Worker class CFastPosInit
54*f6dc9357SAndroid Build Coastguard Worker {
55*f6dc9357SAndroid Build Coastguard Worker public:
CFastPosInit()56*f6dc9357SAndroid Build Coastguard Worker   CFastPosInit()
57*f6dc9357SAndroid Build Coastguard Worker   {
58*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
59*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < kNumLenSlots; i++)
60*f6dc9357SAndroid Build Coastguard Worker     {
61*f6dc9357SAndroid Build Coastguard Worker       unsigned c = kLenStart32[i];
62*f6dc9357SAndroid Build Coastguard Worker       const unsigned j = 1u << kLenDirectBits32[i];
63*f6dc9357SAndroid Build Coastguard Worker       for (unsigned k = 0; k < j; k++, c++)
64*f6dc9357SAndroid Build Coastguard Worker         g_LenSlots[c] = (Byte)i;
65*f6dc9357SAndroid Build Coastguard Worker     }
66*f6dc9357SAndroid Build Coastguard Worker 
67*f6dc9357SAndroid Build Coastguard Worker     const unsigned kFastSlots = kNumLogBits * 2;
68*f6dc9357SAndroid Build Coastguard Worker     unsigned c = 0;
69*f6dc9357SAndroid Build Coastguard Worker     for (Byte slotFast = 0; slotFast < kFastSlots; slotFast++)
70*f6dc9357SAndroid Build Coastguard Worker     {
71*f6dc9357SAndroid Build Coastguard Worker       const unsigned k = 1u << kDistDirectBits[slotFast];
72*f6dc9357SAndroid Build Coastguard Worker       for (unsigned j = 0; j < k; j++, c++)
73*f6dc9357SAndroid Build Coastguard Worker         g_FastPos[c] = slotFast;
74*f6dc9357SAndroid Build Coastguard Worker     }
75*f6dc9357SAndroid Build Coastguard Worker   }
76*f6dc9357SAndroid Build Coastguard Worker };
77*f6dc9357SAndroid Build Coastguard Worker 
78*f6dc9357SAndroid Build Coastguard Worker static CFastPosInit g_FastPosInit;
79*f6dc9357SAndroid Build Coastguard Worker 
GetPosSlot(UInt32 pos)80*f6dc9357SAndroid Build Coastguard Worker inline UInt32 GetPosSlot(UInt32 pos)
81*f6dc9357SAndroid Build Coastguard Worker {
82*f6dc9357SAndroid Build Coastguard Worker   /*
83*f6dc9357SAndroid Build Coastguard Worker   if (pos < 0x200)
84*f6dc9357SAndroid Build Coastguard Worker     return g_FastPos[pos];
85*f6dc9357SAndroid Build Coastguard Worker   return g_FastPos[pos >> 8] + 16;
86*f6dc9357SAndroid Build Coastguard Worker   */
87*f6dc9357SAndroid Build Coastguard Worker   // const unsigned zz = (pos < ((UInt32)1 << (kNumLogBits))) ? 0 : 8;
88*f6dc9357SAndroid Build Coastguard Worker   /*
89*f6dc9357SAndroid Build Coastguard Worker   const unsigned zz = (kNumLogBits - 1) &
90*f6dc9357SAndroid Build Coastguard Worker       ((UInt32)0 - (((((UInt32)1 << kNumLogBits) - 1) - pos) >> 31));
91*f6dc9357SAndroid Build Coastguard Worker   */
92*f6dc9357SAndroid Build Coastguard Worker   const unsigned zz = (kNumLogBits - 1) &
93*f6dc9357SAndroid Build Coastguard Worker       (((((UInt32)1 << kNumLogBits) - 1) - pos) >> (31 - 3));
94*f6dc9357SAndroid Build Coastguard Worker   return g_FastPos[pos >> zz] + (zz * 2);
95*f6dc9357SAndroid Build Coastguard Worker }
96*f6dc9357SAndroid Build Coastguard Worker 
97*f6dc9357SAndroid Build Coastguard Worker 
Normalize()98*f6dc9357SAndroid Build Coastguard Worker void CEncProps::Normalize()
99*f6dc9357SAndroid Build Coastguard Worker {
100*f6dc9357SAndroid Build Coastguard Worker   int level = Level;
101*f6dc9357SAndroid Build Coastguard Worker   if (level < 0) level = 5;
102*f6dc9357SAndroid Build Coastguard Worker   Level = level;
103*f6dc9357SAndroid Build Coastguard Worker   if (algo < 0) algo = (level < 5 ? 0 : 1);
104*f6dc9357SAndroid Build Coastguard Worker   if (fb < 0) fb = (level < 7 ? 32 : (level < 9 ? 64 : 128));
105*f6dc9357SAndroid Build Coastguard Worker   if (btMode < 0) btMode = (algo == 0 ? 0 : 1);
106*f6dc9357SAndroid Build Coastguard Worker   if (mc == 0) mc = (16 + ((unsigned)fb >> 1));
107*f6dc9357SAndroid Build Coastguard Worker   if (numPasses == (UInt32)(Int32)-1) numPasses = (level < 7 ? 1 : (level < 9 ? 3 : 10));
108*f6dc9357SAndroid Build Coastguard Worker }
109*f6dc9357SAndroid Build Coastguard Worker 
SetProps(const CEncProps * props2)110*f6dc9357SAndroid Build Coastguard Worker void CCoder::SetProps(const CEncProps *props2)
111*f6dc9357SAndroid Build Coastguard Worker {
112*f6dc9357SAndroid Build Coastguard Worker   CEncProps props = *props2;
113*f6dc9357SAndroid Build Coastguard Worker   props.Normalize();
114*f6dc9357SAndroid Build Coastguard Worker 
115*f6dc9357SAndroid Build Coastguard Worker   m_MatchFinderCycles = props.mc;
116*f6dc9357SAndroid Build Coastguard Worker   {
117*f6dc9357SAndroid Build Coastguard Worker     unsigned fb = (unsigned)props.fb;
118*f6dc9357SAndroid Build Coastguard Worker     if (fb < kMatchMinLen)
119*f6dc9357SAndroid Build Coastguard Worker       fb = kMatchMinLen;
120*f6dc9357SAndroid Build Coastguard Worker     if (fb > m_MatchMaxLen)
121*f6dc9357SAndroid Build Coastguard Worker       fb = m_MatchMaxLen;
122*f6dc9357SAndroid Build Coastguard Worker     m_NumFastBytes = fb;
123*f6dc9357SAndroid Build Coastguard Worker   }
124*f6dc9357SAndroid Build Coastguard Worker   _fastMode = (props.algo == 0);
125*f6dc9357SAndroid Build Coastguard Worker   _btMode = (props.btMode != 0);
126*f6dc9357SAndroid Build Coastguard Worker 
127*f6dc9357SAndroid Build Coastguard Worker   m_NumDivPasses = props.numPasses;
128*f6dc9357SAndroid Build Coastguard Worker   if (m_NumDivPasses == 0)
129*f6dc9357SAndroid Build Coastguard Worker     m_NumDivPasses = 1;
130*f6dc9357SAndroid Build Coastguard Worker   if (m_NumDivPasses == 1)
131*f6dc9357SAndroid Build Coastguard Worker     m_NumPasses = 1;
132*f6dc9357SAndroid Build Coastguard Worker   else if (m_NumDivPasses <= kNumDivPassesMax)
133*f6dc9357SAndroid Build Coastguard Worker     m_NumPasses = 2;
134*f6dc9357SAndroid Build Coastguard Worker   else
135*f6dc9357SAndroid Build Coastguard Worker   {
136*f6dc9357SAndroid Build Coastguard Worker     m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax);
137*f6dc9357SAndroid Build Coastguard Worker     m_NumDivPasses = kNumDivPassesMax;
138*f6dc9357SAndroid Build Coastguard Worker   }
139*f6dc9357SAndroid Build Coastguard Worker }
140*f6dc9357SAndroid Build Coastguard Worker 
CCoder(bool deflate64Mode)141*f6dc9357SAndroid Build Coastguard Worker CCoder::CCoder(bool deflate64Mode):
142*f6dc9357SAndroid Build Coastguard Worker   m_Values(NULL),
143*f6dc9357SAndroid Build Coastguard Worker   m_OnePosMatchesMemory(NULL),
144*f6dc9357SAndroid Build Coastguard Worker   m_DistanceMemory(NULL),
145*f6dc9357SAndroid Build Coastguard Worker   m_Created(false),
146*f6dc9357SAndroid Build Coastguard Worker   m_Deflate64Mode(deflate64Mode),
147*f6dc9357SAndroid Build Coastguard Worker   m_Tables(NULL)
148*f6dc9357SAndroid Build Coastguard Worker {
149*f6dc9357SAndroid Build Coastguard Worker   m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;
150*f6dc9357SAndroid Build Coastguard Worker   m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;
151*f6dc9357SAndroid Build Coastguard Worker   m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;
152*f6dc9357SAndroid Build Coastguard Worker   m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32;
153*f6dc9357SAndroid Build Coastguard Worker   {
154*f6dc9357SAndroid Build Coastguard Worker     CEncProps props;
155*f6dc9357SAndroid Build Coastguard Worker     SetProps(&props);
156*f6dc9357SAndroid Build Coastguard Worker   }
157*f6dc9357SAndroid Build Coastguard Worker   MatchFinder_Construct(&_lzInWindow);
158*f6dc9357SAndroid Build Coastguard Worker }
159*f6dc9357SAndroid Build Coastguard Worker 
Create()160*f6dc9357SAndroid Build Coastguard Worker HRESULT CCoder::Create()
161*f6dc9357SAndroid Build Coastguard Worker {
162*f6dc9357SAndroid Build Coastguard Worker   // COM_TRY_BEGIN
163*f6dc9357SAndroid Build Coastguard Worker   if (!m_Values)
164*f6dc9357SAndroid Build Coastguard Worker   {
165*f6dc9357SAndroid Build Coastguard Worker     m_Values = (CCodeValue *)MyAlloc((kMaxUncompressedBlockSize) * sizeof(CCodeValue));
166*f6dc9357SAndroid Build Coastguard Worker     if (!m_Values)
167*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
168*f6dc9357SAndroid Build Coastguard Worker   }
169*f6dc9357SAndroid Build Coastguard Worker   if (!m_Tables)
170*f6dc9357SAndroid Build Coastguard Worker   {
171*f6dc9357SAndroid Build Coastguard Worker     m_Tables = (CTables *)MyAlloc((kNumTables) * sizeof(CTables));
172*f6dc9357SAndroid Build Coastguard Worker     if (!m_Tables)
173*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
174*f6dc9357SAndroid Build Coastguard Worker   }
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker   if (m_IsMultiPass)
177*f6dc9357SAndroid Build Coastguard Worker   {
178*f6dc9357SAndroid Build Coastguard Worker     if (!m_OnePosMatchesMemory)
179*f6dc9357SAndroid Build Coastguard Worker     {
180*f6dc9357SAndroid Build Coastguard Worker       m_OnePosMatchesMemory = (UInt16 *)::MidAlloc(kMatchArraySize * sizeof(UInt16));
181*f6dc9357SAndroid Build Coastguard Worker       if (!m_OnePosMatchesMemory)
182*f6dc9357SAndroid Build Coastguard Worker         return E_OUTOFMEMORY;
183*f6dc9357SAndroid Build Coastguard Worker     }
184*f6dc9357SAndroid Build Coastguard Worker   }
185*f6dc9357SAndroid Build Coastguard Worker   else
186*f6dc9357SAndroid Build Coastguard Worker   {
187*f6dc9357SAndroid Build Coastguard Worker     if (!m_DistanceMemory)
188*f6dc9357SAndroid Build Coastguard Worker     {
189*f6dc9357SAndroid Build Coastguard Worker       m_DistanceMemory = (UInt16 *)MyAlloc((kMatchMaxLen + 2) * 2 * sizeof(UInt16));
190*f6dc9357SAndroid Build Coastguard Worker       if (!m_DistanceMemory)
191*f6dc9357SAndroid Build Coastguard Worker         return E_OUTOFMEMORY;
192*f6dc9357SAndroid Build Coastguard Worker       m_MatchDistances = m_DistanceMemory;
193*f6dc9357SAndroid Build Coastguard Worker     }
194*f6dc9357SAndroid Build Coastguard Worker   }
195*f6dc9357SAndroid Build Coastguard Worker 
196*f6dc9357SAndroid Build Coastguard Worker   if (!m_Created)
197*f6dc9357SAndroid Build Coastguard Worker   {
198*f6dc9357SAndroid Build Coastguard Worker     _lzInWindow.btMode = (Byte)(_btMode ? 1 : 0);
199*f6dc9357SAndroid Build Coastguard Worker     _lzInWindow.numHashBytes = 3;
200*f6dc9357SAndroid Build Coastguard Worker     _lzInWindow.numHashBytes_Min = 3;
201*f6dc9357SAndroid Build Coastguard Worker     if (!MatchFinder_Create(&_lzInWindow,
202*f6dc9357SAndroid Build Coastguard Worker         m_Deflate64Mode ? kHistorySize64 : kHistorySize32,
203*f6dc9357SAndroid Build Coastguard Worker         kNumOpts + kMaxUncompressedBlockSize,
204*f6dc9357SAndroid Build Coastguard Worker         m_NumFastBytes, m_MatchMaxLen - m_NumFastBytes, &g_AlignedAlloc))
205*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
206*f6dc9357SAndroid Build Coastguard Worker     if (!m_OutStream.Create(1 << 20))
207*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
208*f6dc9357SAndroid Build Coastguard Worker   }
209*f6dc9357SAndroid Build Coastguard Worker   if (m_MatchFinderCycles != 0)
210*f6dc9357SAndroid Build Coastguard Worker     _lzInWindow.cutValue = m_MatchFinderCycles;
211*f6dc9357SAndroid Build Coastguard Worker   m_Created = true;
212*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
213*f6dc9357SAndroid Build Coastguard Worker   // COM_TRY_END
214*f6dc9357SAndroid Build Coastguard Worker }
215*f6dc9357SAndroid Build Coastguard Worker 
BaseSetEncoderProperties2(const PROPID * propIDs,const PROPVARIANT * coderProps,UInt32 numProps)216*f6dc9357SAndroid Build Coastguard Worker HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
217*f6dc9357SAndroid Build Coastguard Worker {
218*f6dc9357SAndroid Build Coastguard Worker   CEncProps props;
219*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < numProps; i++)
220*f6dc9357SAndroid Build Coastguard Worker   {
221*f6dc9357SAndroid Build Coastguard Worker     const PROPVARIANT &prop = coderProps[i];
222*f6dc9357SAndroid Build Coastguard Worker     PROPID propID = propIDs[i];
223*f6dc9357SAndroid Build Coastguard Worker     if (propID >= NCoderPropID::kReduceSize)
224*f6dc9357SAndroid Build Coastguard Worker       continue;
225*f6dc9357SAndroid Build Coastguard Worker     if (prop.vt != VT_UI4)
226*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
227*f6dc9357SAndroid Build Coastguard Worker     UInt32 v = (UInt32)prop.ulVal;
228*f6dc9357SAndroid Build Coastguard Worker     switch (propID)
229*f6dc9357SAndroid Build Coastguard Worker     {
230*f6dc9357SAndroid Build Coastguard Worker       case NCoderPropID::kNumPasses: props.numPasses = v; break;
231*f6dc9357SAndroid Build Coastguard Worker       case NCoderPropID::kNumFastBytes: props.fb = (int)v; break;
232*f6dc9357SAndroid Build Coastguard Worker       case NCoderPropID::kMatchFinderCycles: props.mc = v; break;
233*f6dc9357SAndroid Build Coastguard Worker       case NCoderPropID::kAlgorithm: props.algo = (int)v; break;
234*f6dc9357SAndroid Build Coastguard Worker       case NCoderPropID::kLevel: props.Level = (int)v; break;
235*f6dc9357SAndroid Build Coastguard Worker       case NCoderPropID::kNumThreads: break;
236*f6dc9357SAndroid Build Coastguard Worker       default: return E_INVALIDARG;
237*f6dc9357SAndroid Build Coastguard Worker     }
238*f6dc9357SAndroid Build Coastguard Worker   }
239*f6dc9357SAndroid Build Coastguard Worker   SetProps(&props);
240*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
241*f6dc9357SAndroid Build Coastguard Worker }
242*f6dc9357SAndroid Build Coastguard Worker 
Free()243*f6dc9357SAndroid Build Coastguard Worker void CCoder::Free()
244*f6dc9357SAndroid Build Coastguard Worker {
245*f6dc9357SAndroid Build Coastguard Worker   ::MidFree(m_OnePosMatchesMemory); m_OnePosMatchesMemory = NULL;
246*f6dc9357SAndroid Build Coastguard Worker   ::MyFree(m_DistanceMemory); m_DistanceMemory = NULL;
247*f6dc9357SAndroid Build Coastguard Worker   ::MyFree(m_Values); m_Values = NULL;
248*f6dc9357SAndroid Build Coastguard Worker   ::MyFree(m_Tables); m_Tables = NULL;
249*f6dc9357SAndroid Build Coastguard Worker }
250*f6dc9357SAndroid Build Coastguard Worker 
~CCoder()251*f6dc9357SAndroid Build Coastguard Worker CCoder::~CCoder()
252*f6dc9357SAndroid Build Coastguard Worker {
253*f6dc9357SAndroid Build Coastguard Worker   Free();
254*f6dc9357SAndroid Build Coastguard Worker   MatchFinder_Free(&_lzInWindow, &g_AlignedAlloc);
255*f6dc9357SAndroid Build Coastguard Worker }
256*f6dc9357SAndroid Build Coastguard Worker 
GetMatches()257*f6dc9357SAndroid Build Coastguard Worker NO_INLINE void CCoder::GetMatches()
258*f6dc9357SAndroid Build Coastguard Worker {
259*f6dc9357SAndroid Build Coastguard Worker   if (m_IsMultiPass)
260*f6dc9357SAndroid Build Coastguard Worker   {
261*f6dc9357SAndroid Build Coastguard Worker     m_MatchDistances = m_OnePosMatchesMemory + m_Pos;
262*f6dc9357SAndroid Build Coastguard Worker     if (m_SecondPass)
263*f6dc9357SAndroid Build Coastguard Worker     {
264*f6dc9357SAndroid Build Coastguard Worker       m_Pos += *m_MatchDistances + 1;
265*f6dc9357SAndroid Build Coastguard Worker       return;
266*f6dc9357SAndroid Build Coastguard Worker     }
267*f6dc9357SAndroid Build Coastguard Worker   }
268*f6dc9357SAndroid Build Coastguard Worker 
269*f6dc9357SAndroid Build Coastguard Worker   UInt32 distanceTmp[kMatchMaxLen * 2 + 3];
270*f6dc9357SAndroid Build Coastguard Worker 
271*f6dc9357SAndroid Build Coastguard Worker   const UInt32 numPairs = (UInt32)((_btMode ?
272*f6dc9357SAndroid Build Coastguard Worker       Bt3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp):
273*f6dc9357SAndroid Build Coastguard Worker       Hc3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp)) - distanceTmp);
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker   *m_MatchDistances = (UInt16)numPairs;
276*f6dc9357SAndroid Build Coastguard Worker 
277*f6dc9357SAndroid Build Coastguard Worker   if (numPairs != 0)
278*f6dc9357SAndroid Build Coastguard Worker   {
279*f6dc9357SAndroid Build Coastguard Worker     UInt32 i;
280*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numPairs; i += 2)
281*f6dc9357SAndroid Build Coastguard Worker     {
282*f6dc9357SAndroid Build Coastguard Worker       m_MatchDistances[(size_t)i + 1] = (UInt16)distanceTmp[i];
283*f6dc9357SAndroid Build Coastguard Worker       m_MatchDistances[(size_t)i + 2] = (UInt16)distanceTmp[(size_t)i + 1];
284*f6dc9357SAndroid Build Coastguard Worker     }
285*f6dc9357SAndroid Build Coastguard Worker     UInt32 len = distanceTmp[(size_t)numPairs - 2];
286*f6dc9357SAndroid Build Coastguard Worker     if (len == m_NumFastBytes && m_NumFastBytes != m_MatchMaxLen)
287*f6dc9357SAndroid Build Coastguard Worker     {
288*f6dc9357SAndroid Build Coastguard Worker       UInt32 numAvail = Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) + 1;
289*f6dc9357SAndroid Build Coastguard Worker       const Byte *pby = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - 1;
290*f6dc9357SAndroid Build Coastguard Worker       const Byte *pby2 = pby - (distanceTmp[(size_t)numPairs - 1] + 1);
291*f6dc9357SAndroid Build Coastguard Worker       if (numAvail > m_MatchMaxLen)
292*f6dc9357SAndroid Build Coastguard Worker         numAvail = m_MatchMaxLen;
293*f6dc9357SAndroid Build Coastguard Worker       for (; len < numAvail && pby[len] == pby2[len]; len++);
294*f6dc9357SAndroid Build Coastguard Worker       m_MatchDistances[(size_t)i - 1] = (UInt16)len;
295*f6dc9357SAndroid Build Coastguard Worker     }
296*f6dc9357SAndroid Build Coastguard Worker   }
297*f6dc9357SAndroid Build Coastguard Worker   if (m_IsMultiPass)
298*f6dc9357SAndroid Build Coastguard Worker     m_Pos += numPairs + 1;
299*f6dc9357SAndroid Build Coastguard Worker   if (!m_SecondPass)
300*f6dc9357SAndroid Build Coastguard Worker     m_AdditionalOffset++;
301*f6dc9357SAndroid Build Coastguard Worker }
302*f6dc9357SAndroid Build Coastguard Worker 
MovePos(UInt32 num)303*f6dc9357SAndroid Build Coastguard Worker void CCoder::MovePos(UInt32 num)
304*f6dc9357SAndroid Build Coastguard Worker {
305*f6dc9357SAndroid Build Coastguard Worker   if (!m_SecondPass && num > 0)
306*f6dc9357SAndroid Build Coastguard Worker   {
307*f6dc9357SAndroid Build Coastguard Worker     if (_btMode)
308*f6dc9357SAndroid Build Coastguard Worker       Bt3Zip_MatchFinder_Skip(&_lzInWindow, num);
309*f6dc9357SAndroid Build Coastguard Worker     else
310*f6dc9357SAndroid Build Coastguard Worker       Hc3Zip_MatchFinder_Skip(&_lzInWindow, num);
311*f6dc9357SAndroid Build Coastguard Worker     m_AdditionalOffset += num;
312*f6dc9357SAndroid Build Coastguard Worker   }
313*f6dc9357SAndroid Build Coastguard Worker }
314*f6dc9357SAndroid Build Coastguard Worker 
315*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kIfinityPrice = 0xFFFFFFF;
316*f6dc9357SAndroid Build Coastguard Worker 
Backward(UInt32 & backRes,UInt32 cur)317*f6dc9357SAndroid Build Coastguard Worker NO_INLINE UInt32 CCoder::Backward(UInt32 &backRes, UInt32 cur)
318*f6dc9357SAndroid Build Coastguard Worker {
319*f6dc9357SAndroid Build Coastguard Worker   m_OptimumEndIndex = cur;
320*f6dc9357SAndroid Build Coastguard Worker   UInt32 posMem = m_Optimum[cur].PosPrev;
321*f6dc9357SAndroid Build Coastguard Worker   UInt16 backMem = m_Optimum[cur].BackPrev;
322*f6dc9357SAndroid Build Coastguard Worker   do
323*f6dc9357SAndroid Build Coastguard Worker   {
324*f6dc9357SAndroid Build Coastguard Worker     UInt32 posPrev = posMem;
325*f6dc9357SAndroid Build Coastguard Worker     UInt16 backCur = backMem;
326*f6dc9357SAndroid Build Coastguard Worker     backMem = m_Optimum[posPrev].BackPrev;
327*f6dc9357SAndroid Build Coastguard Worker     posMem = m_Optimum[posPrev].PosPrev;
328*f6dc9357SAndroid Build Coastguard Worker     m_Optimum[posPrev].BackPrev = backCur;
329*f6dc9357SAndroid Build Coastguard Worker     m_Optimum[posPrev].PosPrev = (UInt16)cur;
330*f6dc9357SAndroid Build Coastguard Worker     cur = posPrev;
331*f6dc9357SAndroid Build Coastguard Worker   }
332*f6dc9357SAndroid Build Coastguard Worker   while (cur > 0);
333*f6dc9357SAndroid Build Coastguard Worker   backRes = m_Optimum[0].BackPrev;
334*f6dc9357SAndroid Build Coastguard Worker   m_OptimumCurrentIndex = m_Optimum[0].PosPrev;
335*f6dc9357SAndroid Build Coastguard Worker   return m_OptimumCurrentIndex;
336*f6dc9357SAndroid Build Coastguard Worker }
337*f6dc9357SAndroid Build Coastguard Worker 
GetOptimal(UInt32 & backRes)338*f6dc9357SAndroid Build Coastguard Worker NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)
339*f6dc9357SAndroid Build Coastguard Worker {
340*f6dc9357SAndroid Build Coastguard Worker   if (m_OptimumEndIndex != m_OptimumCurrentIndex)
341*f6dc9357SAndroid Build Coastguard Worker   {
342*f6dc9357SAndroid Build Coastguard Worker     UInt32 len = m_Optimum[m_OptimumCurrentIndex].PosPrev - m_OptimumCurrentIndex;
343*f6dc9357SAndroid Build Coastguard Worker     backRes = m_Optimum[m_OptimumCurrentIndex].BackPrev;
344*f6dc9357SAndroid Build Coastguard Worker     m_OptimumCurrentIndex = m_Optimum[m_OptimumCurrentIndex].PosPrev;
345*f6dc9357SAndroid Build Coastguard Worker     return len;
346*f6dc9357SAndroid Build Coastguard Worker   }
347*f6dc9357SAndroid Build Coastguard Worker   m_OptimumCurrentIndex = m_OptimumEndIndex = 0;
348*f6dc9357SAndroid Build Coastguard Worker 
349*f6dc9357SAndroid Build Coastguard Worker   GetMatches();
350*f6dc9357SAndroid Build Coastguard Worker 
351*f6dc9357SAndroid Build Coastguard Worker   UInt32 lenEnd;
352*f6dc9357SAndroid Build Coastguard Worker   {
353*f6dc9357SAndroid Build Coastguard Worker     const UInt32 numDistancePairs = m_MatchDistances[0];
354*f6dc9357SAndroid Build Coastguard Worker     if (numDistancePairs == 0)
355*f6dc9357SAndroid Build Coastguard Worker       return 1;
356*f6dc9357SAndroid Build Coastguard Worker     const UInt16 *matchDistances = m_MatchDistances + 1;
357*f6dc9357SAndroid Build Coastguard Worker     lenEnd = matchDistances[(size_t)numDistancePairs - 2];
358*f6dc9357SAndroid Build Coastguard Worker 
359*f6dc9357SAndroid Build Coastguard Worker     if (lenEnd > m_NumFastBytes)
360*f6dc9357SAndroid Build Coastguard Worker     {
361*f6dc9357SAndroid Build Coastguard Worker       backRes = matchDistances[(size_t)numDistancePairs - 1];
362*f6dc9357SAndroid Build Coastguard Worker       MovePos(lenEnd - 1);
363*f6dc9357SAndroid Build Coastguard Worker       return lenEnd;
364*f6dc9357SAndroid Build Coastguard Worker     }
365*f6dc9357SAndroid Build Coastguard Worker 
366*f6dc9357SAndroid Build Coastguard Worker     m_Optimum[1].Price = m_LiteralPrices[*(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - m_AdditionalOffset)];
367*f6dc9357SAndroid Build Coastguard Worker     m_Optimum[1].PosPrev = 0;
368*f6dc9357SAndroid Build Coastguard Worker 
369*f6dc9357SAndroid Build Coastguard Worker     m_Optimum[2].Price = kIfinityPrice;
370*f6dc9357SAndroid Build Coastguard Worker     m_Optimum[2].PosPrev = 1;
371*f6dc9357SAndroid Build Coastguard Worker 
372*f6dc9357SAndroid Build Coastguard Worker     UInt32 offs = 0;
373*f6dc9357SAndroid Build Coastguard Worker 
374*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = kMatchMinLen; i <= lenEnd; i++)
375*f6dc9357SAndroid Build Coastguard Worker     {
376*f6dc9357SAndroid Build Coastguard Worker       UInt32 distance = matchDistances[(size_t)offs + 1];
377*f6dc9357SAndroid Build Coastguard Worker       m_Optimum[i].PosPrev = 0;
378*f6dc9357SAndroid Build Coastguard Worker       m_Optimum[i].BackPrev = (UInt16)distance;
379*f6dc9357SAndroid Build Coastguard Worker       m_Optimum[i].Price = m_LenPrices[(size_t)i - kMatchMinLen] + m_PosPrices[GetPosSlot(distance)];
380*f6dc9357SAndroid Build Coastguard Worker       if (i == matchDistances[offs])
381*f6dc9357SAndroid Build Coastguard Worker         offs += 2;
382*f6dc9357SAndroid Build Coastguard Worker     }
383*f6dc9357SAndroid Build Coastguard Worker   }
384*f6dc9357SAndroid Build Coastguard Worker 
385*f6dc9357SAndroid Build Coastguard Worker   UInt32 cur = 0;
386*f6dc9357SAndroid Build Coastguard Worker 
387*f6dc9357SAndroid Build Coastguard Worker   for (;;)
388*f6dc9357SAndroid Build Coastguard Worker   {
389*f6dc9357SAndroid Build Coastguard Worker     ++cur;
390*f6dc9357SAndroid Build Coastguard Worker     if (cur == lenEnd || cur == kNumOptsBase || m_Pos >= kMatchArrayLimit)
391*f6dc9357SAndroid Build Coastguard Worker       return Backward(backRes, cur);
392*f6dc9357SAndroid Build Coastguard Worker     GetMatches();
393*f6dc9357SAndroid Build Coastguard Worker     const UInt16 *matchDistances = m_MatchDistances + 1;
394*f6dc9357SAndroid Build Coastguard Worker     const UInt32 numDistancePairs = m_MatchDistances[0];
395*f6dc9357SAndroid Build Coastguard Worker     UInt32 newLen = 0;
396*f6dc9357SAndroid Build Coastguard Worker     if (numDistancePairs != 0)
397*f6dc9357SAndroid Build Coastguard Worker     {
398*f6dc9357SAndroid Build Coastguard Worker       newLen = matchDistances[(size_t)numDistancePairs - 2];
399*f6dc9357SAndroid Build Coastguard Worker       if (newLen > m_NumFastBytes)
400*f6dc9357SAndroid Build Coastguard Worker       {
401*f6dc9357SAndroid Build Coastguard Worker         UInt32 len = Backward(backRes, cur);
402*f6dc9357SAndroid Build Coastguard Worker         m_Optimum[cur].BackPrev = matchDistances[(size_t)numDistancePairs - 1];
403*f6dc9357SAndroid Build Coastguard Worker         m_OptimumEndIndex = cur + newLen;
404*f6dc9357SAndroid Build Coastguard Worker         m_Optimum[cur].PosPrev = (UInt16)m_OptimumEndIndex;
405*f6dc9357SAndroid Build Coastguard Worker         MovePos(newLen - 1);
406*f6dc9357SAndroid Build Coastguard Worker         return len;
407*f6dc9357SAndroid Build Coastguard Worker       }
408*f6dc9357SAndroid Build Coastguard Worker     }
409*f6dc9357SAndroid Build Coastguard Worker     UInt32 curPrice = m_Optimum[cur].Price;
410*f6dc9357SAndroid Build Coastguard Worker     {
411*f6dc9357SAndroid Build Coastguard Worker       const UInt32 curAnd1Price = curPrice + m_LiteralPrices[*(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) + cur - m_AdditionalOffset)];
412*f6dc9357SAndroid Build Coastguard Worker       COptimal &optimum = m_Optimum[(size_t)cur + 1];
413*f6dc9357SAndroid Build Coastguard Worker       if (curAnd1Price < optimum.Price)
414*f6dc9357SAndroid Build Coastguard Worker       {
415*f6dc9357SAndroid Build Coastguard Worker         optimum.Price = curAnd1Price;
416*f6dc9357SAndroid Build Coastguard Worker         optimum.PosPrev = (UInt16)cur;
417*f6dc9357SAndroid Build Coastguard Worker       }
418*f6dc9357SAndroid Build Coastguard Worker     }
419*f6dc9357SAndroid Build Coastguard Worker     if (numDistancePairs == 0)
420*f6dc9357SAndroid Build Coastguard Worker       continue;
421*f6dc9357SAndroid Build Coastguard Worker     while (lenEnd < cur + newLen)
422*f6dc9357SAndroid Build Coastguard Worker       m_Optimum[++lenEnd].Price = kIfinityPrice;
423*f6dc9357SAndroid Build Coastguard Worker     UInt32 offs = 0;
424*f6dc9357SAndroid Build Coastguard Worker     UInt32 distance = matchDistances[(size_t)offs + 1];
425*f6dc9357SAndroid Build Coastguard Worker     curPrice += m_PosPrices[GetPosSlot(distance)];
426*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 lenTest = kMatchMinLen; ; lenTest++)
427*f6dc9357SAndroid Build Coastguard Worker     {
428*f6dc9357SAndroid Build Coastguard Worker       UInt32 curAndLenPrice = curPrice + m_LenPrices[(size_t)lenTest - kMatchMinLen];
429*f6dc9357SAndroid Build Coastguard Worker       COptimal &optimum = m_Optimum[cur + lenTest];
430*f6dc9357SAndroid Build Coastguard Worker       if (curAndLenPrice < optimum.Price)
431*f6dc9357SAndroid Build Coastguard Worker       {
432*f6dc9357SAndroid Build Coastguard Worker         optimum.Price = curAndLenPrice;
433*f6dc9357SAndroid Build Coastguard Worker         optimum.PosPrev = (UInt16)cur;
434*f6dc9357SAndroid Build Coastguard Worker         optimum.BackPrev = (UInt16)distance;
435*f6dc9357SAndroid Build Coastguard Worker       }
436*f6dc9357SAndroid Build Coastguard Worker       if (lenTest == matchDistances[offs])
437*f6dc9357SAndroid Build Coastguard Worker       {
438*f6dc9357SAndroid Build Coastguard Worker         offs += 2;
439*f6dc9357SAndroid Build Coastguard Worker         if (offs == numDistancePairs)
440*f6dc9357SAndroid Build Coastguard Worker           break;
441*f6dc9357SAndroid Build Coastguard Worker         curPrice -= m_PosPrices[GetPosSlot(distance)];
442*f6dc9357SAndroid Build Coastguard Worker         distance = matchDistances[(size_t)offs + 1];
443*f6dc9357SAndroid Build Coastguard Worker         curPrice += m_PosPrices[GetPosSlot(distance)];
444*f6dc9357SAndroid Build Coastguard Worker       }
445*f6dc9357SAndroid Build Coastguard Worker     }
446*f6dc9357SAndroid Build Coastguard Worker   }
447*f6dc9357SAndroid Build Coastguard Worker }
448*f6dc9357SAndroid Build Coastguard Worker 
GetOptimalFast(UInt32 & backRes)449*f6dc9357SAndroid Build Coastguard Worker UInt32 CCoder::GetOptimalFast(UInt32 &backRes)
450*f6dc9357SAndroid Build Coastguard Worker {
451*f6dc9357SAndroid Build Coastguard Worker   GetMatches();
452*f6dc9357SAndroid Build Coastguard Worker   UInt32 numDistancePairs = m_MatchDistances[0];
453*f6dc9357SAndroid Build Coastguard Worker   if (numDistancePairs == 0)
454*f6dc9357SAndroid Build Coastguard Worker     return 1;
455*f6dc9357SAndroid Build Coastguard Worker   UInt32 lenMain = m_MatchDistances[(size_t)numDistancePairs - 1];
456*f6dc9357SAndroid Build Coastguard Worker   backRes = m_MatchDistances[numDistancePairs];
457*f6dc9357SAndroid Build Coastguard Worker   MovePos(lenMain - 1);
458*f6dc9357SAndroid Build Coastguard Worker   return lenMain;
459*f6dc9357SAndroid Build Coastguard Worker }
460*f6dc9357SAndroid Build Coastguard Worker 
InitStructures()461*f6dc9357SAndroid Build Coastguard Worker void CTables::InitStructures()
462*f6dc9357SAndroid Build Coastguard Worker {
463*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
464*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < 256; i++)
465*f6dc9357SAndroid Build Coastguard Worker     litLenLevels[i] = 8;
466*f6dc9357SAndroid Build Coastguard Worker   litLenLevels[i++] = 13;
467*f6dc9357SAndroid Build Coastguard Worker   for (;i < kFixedMainTableSize; i++)
468*f6dc9357SAndroid Build Coastguard Worker     litLenLevels[i] = 5;
469*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < kFixedDistTableSize; i++)
470*f6dc9357SAndroid Build Coastguard Worker     distLevels[i] = 5;
471*f6dc9357SAndroid Build Coastguard Worker }
472*f6dc9357SAndroid Build Coastguard Worker 
LevelTableDummy(const Byte * levels,unsigned numLevels,UInt32 * freqs)473*f6dc9357SAndroid Build Coastguard Worker NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, unsigned numLevels, UInt32 *freqs)
474*f6dc9357SAndroid Build Coastguard Worker {
475*f6dc9357SAndroid Build Coastguard Worker   unsigned prevLen = 0xFF;
476*f6dc9357SAndroid Build Coastguard Worker   unsigned nextLen = levels[0];
477*f6dc9357SAndroid Build Coastguard Worker   unsigned count = 0;
478*f6dc9357SAndroid Build Coastguard Worker   unsigned maxCount = 7;
479*f6dc9357SAndroid Build Coastguard Worker   unsigned minCount = 4;
480*f6dc9357SAndroid Build Coastguard Worker 
481*f6dc9357SAndroid Build Coastguard Worker   if (nextLen == 0)
482*f6dc9357SAndroid Build Coastguard Worker   {
483*f6dc9357SAndroid Build Coastguard Worker     maxCount = 138;
484*f6dc9357SAndroid Build Coastguard Worker     minCount = 3;
485*f6dc9357SAndroid Build Coastguard Worker   }
486*f6dc9357SAndroid Build Coastguard Worker 
487*f6dc9357SAndroid Build Coastguard Worker   for (unsigned n = 0; n < numLevels; n++)
488*f6dc9357SAndroid Build Coastguard Worker   {
489*f6dc9357SAndroid Build Coastguard Worker     unsigned curLen = nextLen;
490*f6dc9357SAndroid Build Coastguard Worker     nextLen = (n < numLevels - 1) ? levels[(size_t)n + 1] : 0xFF;
491*f6dc9357SAndroid Build Coastguard Worker     count++;
492*f6dc9357SAndroid Build Coastguard Worker     if (count < maxCount && curLen == nextLen)
493*f6dc9357SAndroid Build Coastguard Worker       continue;
494*f6dc9357SAndroid Build Coastguard Worker 
495*f6dc9357SAndroid Build Coastguard Worker     if (count < minCount)
496*f6dc9357SAndroid Build Coastguard Worker       freqs[curLen] += (UInt32)count;
497*f6dc9357SAndroid Build Coastguard Worker     else if (curLen != 0)
498*f6dc9357SAndroid Build Coastguard Worker     {
499*f6dc9357SAndroid Build Coastguard Worker       if (curLen != prevLen)
500*f6dc9357SAndroid Build Coastguard Worker       {
501*f6dc9357SAndroid Build Coastguard Worker         freqs[curLen]++;
502*f6dc9357SAndroid Build Coastguard Worker         count--;
503*f6dc9357SAndroid Build Coastguard Worker       }
504*f6dc9357SAndroid Build Coastguard Worker       freqs[kTableLevelRepNumber]++;
505*f6dc9357SAndroid Build Coastguard Worker     }
506*f6dc9357SAndroid Build Coastguard Worker     else if (count <= 10)
507*f6dc9357SAndroid Build Coastguard Worker       freqs[kTableLevel0Number]++;
508*f6dc9357SAndroid Build Coastguard Worker     else
509*f6dc9357SAndroid Build Coastguard Worker       freqs[kTableLevel0Number2]++;
510*f6dc9357SAndroid Build Coastguard Worker 
511*f6dc9357SAndroid Build Coastguard Worker     count = 0;
512*f6dc9357SAndroid Build Coastguard Worker     prevLen = curLen;
513*f6dc9357SAndroid Build Coastguard Worker 
514*f6dc9357SAndroid Build Coastguard Worker     if (nextLen == 0)
515*f6dc9357SAndroid Build Coastguard Worker     {
516*f6dc9357SAndroid Build Coastguard Worker       maxCount = 138;
517*f6dc9357SAndroid Build Coastguard Worker       minCount = 3;
518*f6dc9357SAndroid Build Coastguard Worker     }
519*f6dc9357SAndroid Build Coastguard Worker     else if (curLen == nextLen)
520*f6dc9357SAndroid Build Coastguard Worker     {
521*f6dc9357SAndroid Build Coastguard Worker       maxCount = 6;
522*f6dc9357SAndroid Build Coastguard Worker       minCount = 3;
523*f6dc9357SAndroid Build Coastguard Worker     }
524*f6dc9357SAndroid Build Coastguard Worker     else
525*f6dc9357SAndroid Build Coastguard Worker     {
526*f6dc9357SAndroid Build Coastguard Worker       maxCount = 7;
527*f6dc9357SAndroid Build Coastguard Worker       minCount = 4;
528*f6dc9357SAndroid Build Coastguard Worker     }
529*f6dc9357SAndroid Build Coastguard Worker   }
530*f6dc9357SAndroid Build Coastguard Worker }
531*f6dc9357SAndroid Build Coastguard Worker 
WriteBits(UInt32 value,unsigned numBits)532*f6dc9357SAndroid Build Coastguard Worker NO_INLINE void CCoder::WriteBits(UInt32 value, unsigned numBits)
533*f6dc9357SAndroid Build Coastguard Worker {
534*f6dc9357SAndroid Build Coastguard Worker   m_OutStream.WriteBits(value, numBits);
535*f6dc9357SAndroid Build Coastguard Worker }
536*f6dc9357SAndroid Build Coastguard Worker 
537*f6dc9357SAndroid Build Coastguard Worker #define WRITE_HF2(codes, lens, i) m_OutStream.WriteBits(codes[i], lens[i])
538*f6dc9357SAndroid Build Coastguard Worker #define WRITE_HF(i) WriteBits(codes[i], lens[i])
539*f6dc9357SAndroid Build Coastguard Worker 
LevelTableCode(const Byte * levels,unsigned numLevels,const Byte * lens,const UInt32 * codes)540*f6dc9357SAndroid Build Coastguard Worker NO_INLINE void CCoder::LevelTableCode(const Byte *levels, unsigned numLevels, const Byte *lens, const UInt32 *codes)
541*f6dc9357SAndroid Build Coastguard Worker {
542*f6dc9357SAndroid Build Coastguard Worker   unsigned prevLen = 0xFF;
543*f6dc9357SAndroid Build Coastguard Worker   unsigned nextLen = levels[0];
544*f6dc9357SAndroid Build Coastguard Worker   unsigned count = 0;
545*f6dc9357SAndroid Build Coastguard Worker   unsigned maxCount = 7;
546*f6dc9357SAndroid Build Coastguard Worker   unsigned minCount = 4;
547*f6dc9357SAndroid Build Coastguard Worker 
548*f6dc9357SAndroid Build Coastguard Worker   if (nextLen == 0)
549*f6dc9357SAndroid Build Coastguard Worker   {
550*f6dc9357SAndroid Build Coastguard Worker     maxCount = 138;
551*f6dc9357SAndroid Build Coastguard Worker     minCount = 3;
552*f6dc9357SAndroid Build Coastguard Worker   }
553*f6dc9357SAndroid Build Coastguard Worker 
554*f6dc9357SAndroid Build Coastguard Worker   for (unsigned n = 0; n < numLevels; n++)
555*f6dc9357SAndroid Build Coastguard Worker   {
556*f6dc9357SAndroid Build Coastguard Worker     unsigned curLen = nextLen;
557*f6dc9357SAndroid Build Coastguard Worker     nextLen = (n < numLevels - 1) ? levels[(size_t)n + 1] : 0xFF;
558*f6dc9357SAndroid Build Coastguard Worker     count++;
559*f6dc9357SAndroid Build Coastguard Worker     if (count < maxCount && curLen == nextLen)
560*f6dc9357SAndroid Build Coastguard Worker       continue;
561*f6dc9357SAndroid Build Coastguard Worker 
562*f6dc9357SAndroid Build Coastguard Worker     if (count < minCount)
563*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0; i < count; i++)
564*f6dc9357SAndroid Build Coastguard Worker         WRITE_HF(curLen);
565*f6dc9357SAndroid Build Coastguard Worker     else if (curLen != 0)
566*f6dc9357SAndroid Build Coastguard Worker     {
567*f6dc9357SAndroid Build Coastguard Worker       if (curLen != prevLen)
568*f6dc9357SAndroid Build Coastguard Worker       {
569*f6dc9357SAndroid Build Coastguard Worker         WRITE_HF(curLen);
570*f6dc9357SAndroid Build Coastguard Worker         count--;
571*f6dc9357SAndroid Build Coastguard Worker       }
572*f6dc9357SAndroid Build Coastguard Worker       WRITE_HF(kTableLevelRepNumber);
573*f6dc9357SAndroid Build Coastguard Worker       WriteBits(count - 3, 2);
574*f6dc9357SAndroid Build Coastguard Worker     }
575*f6dc9357SAndroid Build Coastguard Worker     else if (count <= 10)
576*f6dc9357SAndroid Build Coastguard Worker     {
577*f6dc9357SAndroid Build Coastguard Worker       WRITE_HF(kTableLevel0Number);
578*f6dc9357SAndroid Build Coastguard Worker       WriteBits(count - 3, 3);
579*f6dc9357SAndroid Build Coastguard Worker     }
580*f6dc9357SAndroid Build Coastguard Worker     else
581*f6dc9357SAndroid Build Coastguard Worker     {
582*f6dc9357SAndroid Build Coastguard Worker       WRITE_HF(kTableLevel0Number2);
583*f6dc9357SAndroid Build Coastguard Worker       WriteBits(count - 11, 7);
584*f6dc9357SAndroid Build Coastguard Worker     }
585*f6dc9357SAndroid Build Coastguard Worker 
586*f6dc9357SAndroid Build Coastguard Worker     count = 0;
587*f6dc9357SAndroid Build Coastguard Worker     prevLen = curLen;
588*f6dc9357SAndroid Build Coastguard Worker 
589*f6dc9357SAndroid Build Coastguard Worker     if (nextLen == 0)
590*f6dc9357SAndroid Build Coastguard Worker     {
591*f6dc9357SAndroid Build Coastguard Worker       maxCount = 138;
592*f6dc9357SAndroid Build Coastguard Worker       minCount = 3;
593*f6dc9357SAndroid Build Coastguard Worker     }
594*f6dc9357SAndroid Build Coastguard Worker     else if (curLen == nextLen)
595*f6dc9357SAndroid Build Coastguard Worker     {
596*f6dc9357SAndroid Build Coastguard Worker       maxCount = 6;
597*f6dc9357SAndroid Build Coastguard Worker       minCount = 3;
598*f6dc9357SAndroid Build Coastguard Worker     }
599*f6dc9357SAndroid Build Coastguard Worker     else
600*f6dc9357SAndroid Build Coastguard Worker     {
601*f6dc9357SAndroid Build Coastguard Worker       maxCount = 7;
602*f6dc9357SAndroid Build Coastguard Worker       minCount = 4;
603*f6dc9357SAndroid Build Coastguard Worker     }
604*f6dc9357SAndroid Build Coastguard Worker   }
605*f6dc9357SAndroid Build Coastguard Worker }
606*f6dc9357SAndroid Build Coastguard Worker 
MakeTables(unsigned maxHuffLen)607*f6dc9357SAndroid Build Coastguard Worker NO_INLINE void CCoder::MakeTables(unsigned maxHuffLen)
608*f6dc9357SAndroid Build Coastguard Worker {
609*f6dc9357SAndroid Build Coastguard Worker   Huffman_Generate(mainFreqs, mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize, maxHuffLen);
610*f6dc9357SAndroid Build Coastguard Worker   Huffman_Generate(distFreqs, distCodes, m_NewLevels.distLevels, kDistTableSize64, maxHuffLen);
611*f6dc9357SAndroid Build Coastguard Worker }
612*f6dc9357SAndroid Build Coastguard Worker 
Huffman_GetPrice(const UInt32 * freqs,const Byte * lens,UInt32 num)613*f6dc9357SAndroid Build Coastguard Worker static NO_INLINE UInt32 Huffman_GetPrice(const UInt32 *freqs, const Byte *lens, UInt32 num)
614*f6dc9357SAndroid Build Coastguard Worker {
615*f6dc9357SAndroid Build Coastguard Worker   UInt32 price = 0;
616*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
617*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < num; i++)
618*f6dc9357SAndroid Build Coastguard Worker     price += lens[i] * freqs[i];
619*f6dc9357SAndroid Build Coastguard Worker   return price;
620*f6dc9357SAndroid Build Coastguard Worker }
621*f6dc9357SAndroid Build Coastguard Worker 
Huffman_GetPrice_Spec(const UInt32 * freqs,const Byte * lens,UInt32 num,const Byte * extraBits,UInt32 extraBase)622*f6dc9357SAndroid Build Coastguard Worker static NO_INLINE UInt32 Huffman_GetPrice_Spec(const UInt32 *freqs, const Byte *lens, UInt32 num, const Byte *extraBits, UInt32 extraBase)
623*f6dc9357SAndroid Build Coastguard Worker {
624*f6dc9357SAndroid Build Coastguard Worker   return Huffman_GetPrice(freqs, lens, num) +
625*f6dc9357SAndroid Build Coastguard Worker     Huffman_GetPrice(freqs + extraBase, extraBits, num - extraBase);
626*f6dc9357SAndroid Build Coastguard Worker }
627*f6dc9357SAndroid Build Coastguard Worker 
GetLzBlockPrice() const628*f6dc9357SAndroid Build Coastguard Worker NO_INLINE UInt32 CCoder::GetLzBlockPrice() const
629*f6dc9357SAndroid Build Coastguard Worker {
630*f6dc9357SAndroid Build Coastguard Worker   return
631*f6dc9357SAndroid Build Coastguard Worker     Huffman_GetPrice_Spec(mainFreqs, m_NewLevels.litLenLevels, kFixedMainTableSize, m_LenDirectBits, kSymbolMatch) +
632*f6dc9357SAndroid Build Coastguard Worker     Huffman_GetPrice_Spec(distFreqs, m_NewLevels.distLevels, kDistTableSize64, kDistDirectBits, 0);
633*f6dc9357SAndroid Build Coastguard Worker }
634*f6dc9357SAndroid Build Coastguard Worker 
TryBlock()635*f6dc9357SAndroid Build Coastguard Worker NO_INLINE void CCoder::TryBlock()
636*f6dc9357SAndroid Build Coastguard Worker {
637*f6dc9357SAndroid Build Coastguard Worker   memset(mainFreqs, 0, sizeof(mainFreqs));
638*f6dc9357SAndroid Build Coastguard Worker   memset(distFreqs, 0, sizeof(distFreqs));
639*f6dc9357SAndroid Build Coastguard Worker 
640*f6dc9357SAndroid Build Coastguard Worker   m_ValueIndex = 0;
641*f6dc9357SAndroid Build Coastguard Worker   UInt32 blockSize = BlockSizeRes;
642*f6dc9357SAndroid Build Coastguard Worker   BlockSizeRes = 0;
643*f6dc9357SAndroid Build Coastguard Worker   for (;;)
644*f6dc9357SAndroid Build Coastguard Worker   {
645*f6dc9357SAndroid Build Coastguard Worker     if (m_OptimumCurrentIndex == m_OptimumEndIndex)
646*f6dc9357SAndroid Build Coastguard Worker     {
647*f6dc9357SAndroid Build Coastguard Worker       if (m_Pos >= kMatchArrayLimit
648*f6dc9357SAndroid Build Coastguard Worker           || BlockSizeRes >= blockSize
649*f6dc9357SAndroid Build Coastguard Worker           || (!m_SecondPass && ((Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0) || m_ValueIndex >= m_ValueBlockSize)))
650*f6dc9357SAndroid Build Coastguard Worker         break;
651*f6dc9357SAndroid Build Coastguard Worker     }
652*f6dc9357SAndroid Build Coastguard Worker     UInt32 pos;
653*f6dc9357SAndroid Build Coastguard Worker     UInt32 len;
654*f6dc9357SAndroid Build Coastguard Worker     if (_fastMode)
655*f6dc9357SAndroid Build Coastguard Worker       len = GetOptimalFast(pos);
656*f6dc9357SAndroid Build Coastguard Worker     else
657*f6dc9357SAndroid Build Coastguard Worker       len = GetOptimal(pos);
658*f6dc9357SAndroid Build Coastguard Worker     CCodeValue &codeValue = m_Values[m_ValueIndex++];
659*f6dc9357SAndroid Build Coastguard Worker     if (len >= kMatchMinLen)
660*f6dc9357SAndroid Build Coastguard Worker     {
661*f6dc9357SAndroid Build Coastguard Worker       UInt32 newLen = len - kMatchMinLen;
662*f6dc9357SAndroid Build Coastguard Worker       codeValue.Len = (UInt16)newLen;
663*f6dc9357SAndroid Build Coastguard Worker       mainFreqs[kSymbolMatch + (size_t)g_LenSlots[newLen]]++;
664*f6dc9357SAndroid Build Coastguard Worker       codeValue.Pos = (UInt16)pos;
665*f6dc9357SAndroid Build Coastguard Worker       distFreqs[GetPosSlot(pos)]++;
666*f6dc9357SAndroid Build Coastguard Worker     }
667*f6dc9357SAndroid Build Coastguard Worker     else
668*f6dc9357SAndroid Build Coastguard Worker     {
669*f6dc9357SAndroid Build Coastguard Worker       Byte b = *(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - m_AdditionalOffset);
670*f6dc9357SAndroid Build Coastguard Worker       mainFreqs[b]++;
671*f6dc9357SAndroid Build Coastguard Worker       codeValue.SetAsLiteral();
672*f6dc9357SAndroid Build Coastguard Worker       codeValue.Pos = b;
673*f6dc9357SAndroid Build Coastguard Worker     }
674*f6dc9357SAndroid Build Coastguard Worker     m_AdditionalOffset -= len;
675*f6dc9357SAndroid Build Coastguard Worker     BlockSizeRes += len;
676*f6dc9357SAndroid Build Coastguard Worker   }
677*f6dc9357SAndroid Build Coastguard Worker   mainFreqs[kSymbolEndOfBlock]++;
678*f6dc9357SAndroid Build Coastguard Worker   m_AdditionalOffset += BlockSizeRes;
679*f6dc9357SAndroid Build Coastguard Worker   m_SecondPass = true;
680*f6dc9357SAndroid Build Coastguard Worker }
681*f6dc9357SAndroid Build Coastguard Worker 
SetPrices(const CLevels & levels)682*f6dc9357SAndroid Build Coastguard Worker NO_INLINE void CCoder::SetPrices(const CLevels &levels)
683*f6dc9357SAndroid Build Coastguard Worker {
684*f6dc9357SAndroid Build Coastguard Worker   if (_fastMode)
685*f6dc9357SAndroid Build Coastguard Worker     return;
686*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
687*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < 256; i++)
688*f6dc9357SAndroid Build Coastguard Worker   {
689*f6dc9357SAndroid Build Coastguard Worker     Byte price = levels.litLenLevels[i];
690*f6dc9357SAndroid Build Coastguard Worker     m_LiteralPrices[i] = ((price != 0) ? price : kNoLiteralStatPrice);
691*f6dc9357SAndroid Build Coastguard Worker   }
692*f6dc9357SAndroid Build Coastguard Worker 
693*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < m_NumLenCombinations; i++)
694*f6dc9357SAndroid Build Coastguard Worker   {
695*f6dc9357SAndroid Build Coastguard Worker     UInt32 slot = g_LenSlots[i];
696*f6dc9357SAndroid Build Coastguard Worker     Byte price = levels.litLenLevels[kSymbolMatch + (size_t)slot];
697*f6dc9357SAndroid Build Coastguard Worker     m_LenPrices[i] = (Byte)(((price != 0) ? price : kNoLenStatPrice) + m_LenDirectBits[slot]);
698*f6dc9357SAndroid Build Coastguard Worker   }
699*f6dc9357SAndroid Build Coastguard Worker 
700*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < kDistTableSize64; i++)
701*f6dc9357SAndroid Build Coastguard Worker   {
702*f6dc9357SAndroid Build Coastguard Worker     Byte price = levels.distLevels[i];
703*f6dc9357SAndroid Build Coastguard Worker     m_PosPrices[i] = (Byte)(((price != 0) ? price: kNoPosStatPrice) + kDistDirectBits[i]);
704*f6dc9357SAndroid Build Coastguard Worker   }
705*f6dc9357SAndroid Build Coastguard Worker }
706*f6dc9357SAndroid Build Coastguard Worker 
Huffman_ReverseBits(UInt32 * codes,const Byte * lens,UInt32 num)707*f6dc9357SAndroid Build Coastguard Worker static NO_INLINE void Huffman_ReverseBits(UInt32 *codes, const Byte *lens, UInt32 num)
708*f6dc9357SAndroid Build Coastguard Worker {
709*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < num; i++)
710*f6dc9357SAndroid Build Coastguard Worker   {
711*f6dc9357SAndroid Build Coastguard Worker     UInt32 x = codes[i];
712*f6dc9357SAndroid Build Coastguard Worker     x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1);
713*f6dc9357SAndroid Build Coastguard Worker     x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2);
714*f6dc9357SAndroid Build Coastguard Worker     x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4);
715*f6dc9357SAndroid Build Coastguard Worker     codes[i] = (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)) >> (16 - lens[i]);
716*f6dc9357SAndroid Build Coastguard Worker   }
717*f6dc9357SAndroid Build Coastguard Worker }
718*f6dc9357SAndroid Build Coastguard Worker 
WriteBlock()719*f6dc9357SAndroid Build Coastguard Worker NO_INLINE void CCoder::WriteBlock()
720*f6dc9357SAndroid Build Coastguard Worker {
721*f6dc9357SAndroid Build Coastguard Worker   Huffman_ReverseBits(mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize);
722*f6dc9357SAndroid Build Coastguard Worker   Huffman_ReverseBits(distCodes, m_NewLevels.distLevels, kDistTableSize64);
723*f6dc9357SAndroid Build Coastguard Worker 
724*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < m_ValueIndex; i++)
725*f6dc9357SAndroid Build Coastguard Worker   {
726*f6dc9357SAndroid Build Coastguard Worker     const CCodeValue &codeValue = m_Values[i];
727*f6dc9357SAndroid Build Coastguard Worker     if (codeValue.IsLiteral())
728*f6dc9357SAndroid Build Coastguard Worker       WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, codeValue.Pos);
729*f6dc9357SAndroid Build Coastguard Worker     else
730*f6dc9357SAndroid Build Coastguard Worker     {
731*f6dc9357SAndroid Build Coastguard Worker       UInt32 len = codeValue.Len;
732*f6dc9357SAndroid Build Coastguard Worker       UInt32 lenSlot = g_LenSlots[len];
733*f6dc9357SAndroid Build Coastguard Worker       WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolMatch + lenSlot);
734*f6dc9357SAndroid Build Coastguard Worker       m_OutStream.WriteBits(len - m_LenStart[lenSlot], m_LenDirectBits[lenSlot]);
735*f6dc9357SAndroid Build Coastguard Worker       UInt32 dist = codeValue.Pos;
736*f6dc9357SAndroid Build Coastguard Worker       UInt32 posSlot = GetPosSlot(dist);
737*f6dc9357SAndroid Build Coastguard Worker       WRITE_HF2(distCodes, m_NewLevels.distLevels, posSlot);
738*f6dc9357SAndroid Build Coastguard Worker       m_OutStream.WriteBits(dist - kDistStart[posSlot], kDistDirectBits[posSlot]);
739*f6dc9357SAndroid Build Coastguard Worker     }
740*f6dc9357SAndroid Build Coastguard Worker   }
741*f6dc9357SAndroid Build Coastguard Worker   WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolEndOfBlock);
742*f6dc9357SAndroid Build Coastguard Worker }
743*f6dc9357SAndroid Build Coastguard Worker 
GetStorePrice(UInt32 blockSize,unsigned bitPosition)744*f6dc9357SAndroid Build Coastguard Worker static UInt32 GetStorePrice(UInt32 blockSize, unsigned bitPosition)
745*f6dc9357SAndroid Build Coastguard Worker {
746*f6dc9357SAndroid Build Coastguard Worker   UInt32 price = 0;
747*f6dc9357SAndroid Build Coastguard Worker   do
748*f6dc9357SAndroid Build Coastguard Worker   {
749*f6dc9357SAndroid Build Coastguard Worker     UInt32 nextBitPosition = (bitPosition + kFinalBlockFieldSize + kBlockTypeFieldSize) & 7;
750*f6dc9357SAndroid Build Coastguard Worker     unsigned numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0;
751*f6dc9357SAndroid Build Coastguard Worker     UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1;
752*f6dc9357SAndroid Build Coastguard Worker     price += kFinalBlockFieldSize + kBlockTypeFieldSize + numBitsForAlign + (2 + 2) * 8 + curBlockSize * 8;
753*f6dc9357SAndroid Build Coastguard Worker     bitPosition = 0;
754*f6dc9357SAndroid Build Coastguard Worker     blockSize -= curBlockSize;
755*f6dc9357SAndroid Build Coastguard Worker   }
756*f6dc9357SAndroid Build Coastguard Worker   while (blockSize != 0);
757*f6dc9357SAndroid Build Coastguard Worker   return price;
758*f6dc9357SAndroid Build Coastguard Worker }
759*f6dc9357SAndroid Build Coastguard Worker 
WriteStoreBlock(UInt32 blockSize,UInt32 additionalOffset,bool finalBlock)760*f6dc9357SAndroid Build Coastguard Worker void CCoder::WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool finalBlock)
761*f6dc9357SAndroid Build Coastguard Worker {
762*f6dc9357SAndroid Build Coastguard Worker   do
763*f6dc9357SAndroid Build Coastguard Worker   {
764*f6dc9357SAndroid Build Coastguard Worker     UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1;
765*f6dc9357SAndroid Build Coastguard Worker     blockSize -= curBlockSize;
766*f6dc9357SAndroid Build Coastguard Worker     WriteBits((finalBlock && (blockSize == 0) ? NFinalBlockField::kFinalBlock: NFinalBlockField::kNotFinalBlock), kFinalBlockFieldSize);
767*f6dc9357SAndroid Build Coastguard Worker     WriteBits(NBlockType::kStored, kBlockTypeFieldSize);
768*f6dc9357SAndroid Build Coastguard Worker     m_OutStream.FlushByte();
769*f6dc9357SAndroid Build Coastguard Worker     WriteBits((UInt16)curBlockSize, kStoredBlockLengthFieldSize);
770*f6dc9357SAndroid Build Coastguard Worker     WriteBits((UInt16)~curBlockSize, kStoredBlockLengthFieldSize);
771*f6dc9357SAndroid Build Coastguard Worker     const Byte *data = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow)- additionalOffset;
772*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = 0; i < curBlockSize; i++)
773*f6dc9357SAndroid Build Coastguard Worker       m_OutStream.WriteByte(data[i]);
774*f6dc9357SAndroid Build Coastguard Worker     additionalOffset -= curBlockSize;
775*f6dc9357SAndroid Build Coastguard Worker   }
776*f6dc9357SAndroid Build Coastguard Worker   while (blockSize != 0);
777*f6dc9357SAndroid Build Coastguard Worker }
778*f6dc9357SAndroid Build Coastguard Worker 
TryDynBlock(unsigned tableIndex,UInt32 numPasses)779*f6dc9357SAndroid Build Coastguard Worker NO_INLINE UInt32 CCoder::TryDynBlock(unsigned tableIndex, UInt32 numPasses)
780*f6dc9357SAndroid Build Coastguard Worker {
781*f6dc9357SAndroid Build Coastguard Worker   CTables &t = m_Tables[tableIndex];
782*f6dc9357SAndroid Build Coastguard Worker   BlockSizeRes = t.BlockSizeRes;
783*f6dc9357SAndroid Build Coastguard Worker   UInt32 posTemp = t.m_Pos;
784*f6dc9357SAndroid Build Coastguard Worker   SetPrices(t);
785*f6dc9357SAndroid Build Coastguard Worker 
786*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 p = 0; p < numPasses; p++)
787*f6dc9357SAndroid Build Coastguard Worker   {
788*f6dc9357SAndroid Build Coastguard Worker     m_Pos = posTemp;
789*f6dc9357SAndroid Build Coastguard Worker     TryBlock();
790*f6dc9357SAndroid Build Coastguard Worker     unsigned numHuffBits =
791*f6dc9357SAndroid Build Coastguard Worker         (m_ValueIndex > 18000 ? 12 :
792*f6dc9357SAndroid Build Coastguard Worker         (m_ValueIndex >  7000 ? 11 :
793*f6dc9357SAndroid Build Coastguard Worker         (m_ValueIndex >  2000 ? 10 : 9)));
794*f6dc9357SAndroid Build Coastguard Worker     MakeTables(numHuffBits);
795*f6dc9357SAndroid Build Coastguard Worker     SetPrices(m_NewLevels);
796*f6dc9357SAndroid Build Coastguard Worker   }
797*f6dc9357SAndroid Build Coastguard Worker 
798*f6dc9357SAndroid Build Coastguard Worker   (CLevels &)t = m_NewLevels;
799*f6dc9357SAndroid Build Coastguard Worker 
800*f6dc9357SAndroid Build Coastguard Worker   m_NumLitLenLevels = kMainTableSize;
801*f6dc9357SAndroid Build Coastguard Worker   while (m_NumLitLenLevels > kNumLitLenCodesMin && m_NewLevels.litLenLevels[(size_t)m_NumLitLenLevels - 1] == 0)
802*f6dc9357SAndroid Build Coastguard Worker     m_NumLitLenLevels--;
803*f6dc9357SAndroid Build Coastguard Worker 
804*f6dc9357SAndroid Build Coastguard Worker   m_NumDistLevels = kDistTableSize64;
805*f6dc9357SAndroid Build Coastguard Worker   while (m_NumDistLevels > kNumDistCodesMin && m_NewLevels.distLevels[(size_t)m_NumDistLevels - 1] == 0)
806*f6dc9357SAndroid Build Coastguard Worker     m_NumDistLevels--;
807*f6dc9357SAndroid Build Coastguard Worker 
808*f6dc9357SAndroid Build Coastguard Worker   UInt32 levelFreqs[kLevelTableSize];
809*f6dc9357SAndroid Build Coastguard Worker   memset(levelFreqs, 0, sizeof(levelFreqs));
810*f6dc9357SAndroid Build Coastguard Worker 
811*f6dc9357SAndroid Build Coastguard Worker   LevelTableDummy(m_NewLevels.litLenLevels, m_NumLitLenLevels, levelFreqs);
812*f6dc9357SAndroid Build Coastguard Worker   LevelTableDummy(m_NewLevels.distLevels, m_NumDistLevels, levelFreqs);
813*f6dc9357SAndroid Build Coastguard Worker 
814*f6dc9357SAndroid Build Coastguard Worker   Huffman_Generate(levelFreqs, levelCodes, levelLens, kLevelTableSize, kMaxLevelBitLength);
815*f6dc9357SAndroid Build Coastguard Worker 
816*f6dc9357SAndroid Build Coastguard Worker   m_NumLevelCodes = kNumLevelCodesMin;
817*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < kLevelTableSize; i++)
818*f6dc9357SAndroid Build Coastguard Worker   {
819*f6dc9357SAndroid Build Coastguard Worker     Byte level = levelLens[kCodeLengthAlphabetOrder[i]];
820*f6dc9357SAndroid Build Coastguard Worker     if (level > 0 && i >= m_NumLevelCodes)
821*f6dc9357SAndroid Build Coastguard Worker       m_NumLevelCodes = i + 1;
822*f6dc9357SAndroid Build Coastguard Worker     m_LevelLevels[i] = level;
823*f6dc9357SAndroid Build Coastguard Worker   }
824*f6dc9357SAndroid Build Coastguard Worker 
825*f6dc9357SAndroid Build Coastguard Worker   return GetLzBlockPrice() +
826*f6dc9357SAndroid Build Coastguard Worker       Huffman_GetPrice_Spec(levelFreqs, levelLens, kLevelTableSize, kLevelDirectBits, kTableDirectLevels) +
827*f6dc9357SAndroid Build Coastguard Worker       kNumLenCodesFieldSize + kNumDistCodesFieldSize + kNumLevelCodesFieldSize +
828*f6dc9357SAndroid Build Coastguard Worker       m_NumLevelCodes * kLevelFieldSize + kFinalBlockFieldSize + kBlockTypeFieldSize;
829*f6dc9357SAndroid Build Coastguard Worker }
830*f6dc9357SAndroid Build Coastguard Worker 
TryFixedBlock(unsigned tableIndex)831*f6dc9357SAndroid Build Coastguard Worker NO_INLINE UInt32 CCoder::TryFixedBlock(unsigned tableIndex)
832*f6dc9357SAndroid Build Coastguard Worker {
833*f6dc9357SAndroid Build Coastguard Worker   CTables &t = m_Tables[tableIndex];
834*f6dc9357SAndroid Build Coastguard Worker   BlockSizeRes = t.BlockSizeRes;
835*f6dc9357SAndroid Build Coastguard Worker   m_Pos = t.m_Pos;
836*f6dc9357SAndroid Build Coastguard Worker   m_NewLevels.SetFixedLevels();
837*f6dc9357SAndroid Build Coastguard Worker   SetPrices(m_NewLevels);
838*f6dc9357SAndroid Build Coastguard Worker   TryBlock();
839*f6dc9357SAndroid Build Coastguard Worker   return kFinalBlockFieldSize + kBlockTypeFieldSize + GetLzBlockPrice();
840*f6dc9357SAndroid Build Coastguard Worker }
841*f6dc9357SAndroid Build Coastguard Worker 
GetBlockPrice(unsigned tableIndex,unsigned numDivPasses)842*f6dc9357SAndroid Build Coastguard Worker NO_INLINE UInt32 CCoder::GetBlockPrice(unsigned tableIndex, unsigned numDivPasses)
843*f6dc9357SAndroid Build Coastguard Worker {
844*f6dc9357SAndroid Build Coastguard Worker   CTables &t = m_Tables[tableIndex];
845*f6dc9357SAndroid Build Coastguard Worker   t.StaticMode = false;
846*f6dc9357SAndroid Build Coastguard Worker   UInt32 price = TryDynBlock(tableIndex, m_NumPasses);
847*f6dc9357SAndroid Build Coastguard Worker   t.BlockSizeRes = BlockSizeRes;
848*f6dc9357SAndroid Build Coastguard Worker   UInt32 numValues = m_ValueIndex;
849*f6dc9357SAndroid Build Coastguard Worker   UInt32 posTemp = m_Pos;
850*f6dc9357SAndroid Build Coastguard Worker   UInt32 additionalOffsetEnd = m_AdditionalOffset;
851*f6dc9357SAndroid Build Coastguard Worker 
852*f6dc9357SAndroid Build Coastguard Worker   if (m_CheckStatic && m_ValueIndex <= kFixedHuffmanCodeBlockSizeMax)
853*f6dc9357SAndroid Build Coastguard Worker   {
854*f6dc9357SAndroid Build Coastguard Worker     const UInt32 fixedPrice = TryFixedBlock(tableIndex);
855*f6dc9357SAndroid Build Coastguard Worker     t.StaticMode = (fixedPrice < price);
856*f6dc9357SAndroid Build Coastguard Worker     if (t.StaticMode)
857*f6dc9357SAndroid Build Coastguard Worker       price = fixedPrice;
858*f6dc9357SAndroid Build Coastguard Worker   }
859*f6dc9357SAndroid Build Coastguard Worker 
860*f6dc9357SAndroid Build Coastguard Worker   const UInt32 storePrice = GetStorePrice(BlockSizeRes, 0); // bitPosition
861*f6dc9357SAndroid Build Coastguard Worker   t.StoreMode = (storePrice <= price);
862*f6dc9357SAndroid Build Coastguard Worker   if (t.StoreMode)
863*f6dc9357SAndroid Build Coastguard Worker     price = storePrice;
864*f6dc9357SAndroid Build Coastguard Worker 
865*f6dc9357SAndroid Build Coastguard Worker   t.UseSubBlocks = false;
866*f6dc9357SAndroid Build Coastguard Worker 
867*f6dc9357SAndroid Build Coastguard Worker   if (numDivPasses > 1 && numValues >= kDivideCodeBlockSizeMin)
868*f6dc9357SAndroid Build Coastguard Worker   {
869*f6dc9357SAndroid Build Coastguard Worker     CTables &t0 = m_Tables[(tableIndex << 1)];
870*f6dc9357SAndroid Build Coastguard Worker     (CLevels &)t0 = t;
871*f6dc9357SAndroid Build Coastguard Worker     t0.BlockSizeRes = t.BlockSizeRes >> 1;
872*f6dc9357SAndroid Build Coastguard Worker     t0.m_Pos = t.m_Pos;
873*f6dc9357SAndroid Build Coastguard Worker     UInt32 subPrice = GetBlockPrice((tableIndex << 1), numDivPasses - 1);
874*f6dc9357SAndroid Build Coastguard Worker 
875*f6dc9357SAndroid Build Coastguard Worker     UInt32 blockSize2 = t.BlockSizeRes - t0.BlockSizeRes;
876*f6dc9357SAndroid Build Coastguard Worker     if (t0.BlockSizeRes >= kDivideBlockSizeMin && blockSize2 >= kDivideBlockSizeMin)
877*f6dc9357SAndroid Build Coastguard Worker     {
878*f6dc9357SAndroid Build Coastguard Worker       CTables &t1 = m_Tables[(tableIndex << 1) + 1];
879*f6dc9357SAndroid Build Coastguard Worker       (CLevels &)t1 = t;
880*f6dc9357SAndroid Build Coastguard Worker       t1.BlockSizeRes = blockSize2;
881*f6dc9357SAndroid Build Coastguard Worker       t1.m_Pos = m_Pos;
882*f6dc9357SAndroid Build Coastguard Worker       m_AdditionalOffset -= t0.BlockSizeRes;
883*f6dc9357SAndroid Build Coastguard Worker       subPrice += GetBlockPrice((tableIndex << 1) + 1, numDivPasses - 1);
884*f6dc9357SAndroid Build Coastguard Worker       t.UseSubBlocks = (subPrice < price);
885*f6dc9357SAndroid Build Coastguard Worker       if (t.UseSubBlocks)
886*f6dc9357SAndroid Build Coastguard Worker         price = subPrice;
887*f6dc9357SAndroid Build Coastguard Worker     }
888*f6dc9357SAndroid Build Coastguard Worker   }
889*f6dc9357SAndroid Build Coastguard Worker 
890*f6dc9357SAndroid Build Coastguard Worker   m_AdditionalOffset = additionalOffsetEnd;
891*f6dc9357SAndroid Build Coastguard Worker   m_Pos = posTemp;
892*f6dc9357SAndroid Build Coastguard Worker   return price;
893*f6dc9357SAndroid Build Coastguard Worker }
894*f6dc9357SAndroid Build Coastguard Worker 
CodeBlock(unsigned tableIndex,bool finalBlock)895*f6dc9357SAndroid Build Coastguard Worker void CCoder::CodeBlock(unsigned tableIndex, bool finalBlock)
896*f6dc9357SAndroid Build Coastguard Worker {
897*f6dc9357SAndroid Build Coastguard Worker   CTables &t = m_Tables[tableIndex];
898*f6dc9357SAndroid Build Coastguard Worker   if (t.UseSubBlocks)
899*f6dc9357SAndroid Build Coastguard Worker   {
900*f6dc9357SAndroid Build Coastguard Worker     CodeBlock((tableIndex << 1), false);
901*f6dc9357SAndroid Build Coastguard Worker     CodeBlock((tableIndex << 1) + 1, finalBlock);
902*f6dc9357SAndroid Build Coastguard Worker   }
903*f6dc9357SAndroid Build Coastguard Worker   else
904*f6dc9357SAndroid Build Coastguard Worker   {
905*f6dc9357SAndroid Build Coastguard Worker     if (t.StoreMode)
906*f6dc9357SAndroid Build Coastguard Worker       WriteStoreBlock(t.BlockSizeRes, m_AdditionalOffset, finalBlock);
907*f6dc9357SAndroid Build Coastguard Worker     else
908*f6dc9357SAndroid Build Coastguard Worker     {
909*f6dc9357SAndroid Build Coastguard Worker       WriteBits((finalBlock ? NFinalBlockField::kFinalBlock: NFinalBlockField::kNotFinalBlock), kFinalBlockFieldSize);
910*f6dc9357SAndroid Build Coastguard Worker       if (t.StaticMode)
911*f6dc9357SAndroid Build Coastguard Worker       {
912*f6dc9357SAndroid Build Coastguard Worker         WriteBits(NBlockType::kFixedHuffman, kBlockTypeFieldSize);
913*f6dc9357SAndroid Build Coastguard Worker         TryFixedBlock(tableIndex);
914*f6dc9357SAndroid Build Coastguard Worker         unsigned i;
915*f6dc9357SAndroid Build Coastguard Worker         const unsigned kMaxStaticHuffLen = 9;
916*f6dc9357SAndroid Build Coastguard Worker         for (i = 0; i < kFixedMainTableSize; i++)
917*f6dc9357SAndroid Build Coastguard Worker           mainFreqs[i] = (UInt32)1 << (kMaxStaticHuffLen - m_NewLevels.litLenLevels[i]);
918*f6dc9357SAndroid Build Coastguard Worker         for (i = 0; i < kFixedDistTableSize; i++)
919*f6dc9357SAndroid Build Coastguard Worker           distFreqs[i] = (UInt32)1 << (kMaxStaticHuffLen - m_NewLevels.distLevels[i]);
920*f6dc9357SAndroid Build Coastguard Worker         MakeTables(kMaxStaticHuffLen);
921*f6dc9357SAndroid Build Coastguard Worker       }
922*f6dc9357SAndroid Build Coastguard Worker       else
923*f6dc9357SAndroid Build Coastguard Worker       {
924*f6dc9357SAndroid Build Coastguard Worker         if (m_NumDivPasses > 1 || m_CheckStatic)
925*f6dc9357SAndroid Build Coastguard Worker           TryDynBlock(tableIndex, 1);
926*f6dc9357SAndroid Build Coastguard Worker         WriteBits(NBlockType::kDynamicHuffman, kBlockTypeFieldSize);
927*f6dc9357SAndroid Build Coastguard Worker         WriteBits(m_NumLitLenLevels - kNumLitLenCodesMin, kNumLenCodesFieldSize);
928*f6dc9357SAndroid Build Coastguard Worker         WriteBits(m_NumDistLevels - kNumDistCodesMin, kNumDistCodesFieldSize);
929*f6dc9357SAndroid Build Coastguard Worker         WriteBits(m_NumLevelCodes - kNumLevelCodesMin, kNumLevelCodesFieldSize);
930*f6dc9357SAndroid Build Coastguard Worker 
931*f6dc9357SAndroid Build Coastguard Worker         for (UInt32 i = 0; i < m_NumLevelCodes; i++)
932*f6dc9357SAndroid Build Coastguard Worker           WriteBits(m_LevelLevels[i], kLevelFieldSize);
933*f6dc9357SAndroid Build Coastguard Worker 
934*f6dc9357SAndroid Build Coastguard Worker         Huffman_ReverseBits(levelCodes, levelLens, kLevelTableSize);
935*f6dc9357SAndroid Build Coastguard Worker         LevelTableCode(m_NewLevels.litLenLevels, m_NumLitLenLevels, levelLens, levelCodes);
936*f6dc9357SAndroid Build Coastguard Worker         LevelTableCode(m_NewLevels.distLevels, m_NumDistLevels, levelLens, levelCodes);
937*f6dc9357SAndroid Build Coastguard Worker       }
938*f6dc9357SAndroid Build Coastguard Worker       WriteBlock();
939*f6dc9357SAndroid Build Coastguard Worker     }
940*f6dc9357SAndroid Build Coastguard Worker     m_AdditionalOffset -= t.BlockSizeRes;
941*f6dc9357SAndroid Build Coastguard Worker   }
942*f6dc9357SAndroid Build Coastguard Worker }
943*f6dc9357SAndroid Build Coastguard Worker 
944*f6dc9357SAndroid Build Coastguard Worker 
CodeReal(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 *,ICompressProgressInfo * progress)945*f6dc9357SAndroid Build Coastguard Worker HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
946*f6dc9357SAndroid Build Coastguard Worker     const UInt64 * /* inSize */ , const UInt64 * /* outSize */ , ICompressProgressInfo *progress)
947*f6dc9357SAndroid Build Coastguard Worker {
948*f6dc9357SAndroid Build Coastguard Worker   m_CheckStatic = (m_NumPasses != 1 || m_NumDivPasses != 1);
949*f6dc9357SAndroid Build Coastguard Worker   m_IsMultiPass = (m_CheckStatic || (m_NumPasses != 1 || m_NumDivPasses != 1));
950*f6dc9357SAndroid Build Coastguard Worker 
951*f6dc9357SAndroid Build Coastguard Worker   /* we can set stream mode before MatchFinder_Create
952*f6dc9357SAndroid Build Coastguard Worker     if default MatchFinder mode was not STREAM_MODE) */
953*f6dc9357SAndroid Build Coastguard Worker   // MatchFinder_SET_STREAM_MODE(&_lzInWindow);
954*f6dc9357SAndroid Build Coastguard Worker 
955*f6dc9357SAndroid Build Coastguard Worker   CSeqInStreamWrap _seqInStream;
956*f6dc9357SAndroid Build Coastguard Worker   _seqInStream.Init(inStream);
957*f6dc9357SAndroid Build Coastguard Worker   MatchFinder_SET_STREAM(&_lzInWindow, &_seqInStream.vt)
958*f6dc9357SAndroid Build Coastguard Worker 
959*f6dc9357SAndroid Build Coastguard Worker   RINOK(Create())
960*f6dc9357SAndroid Build Coastguard Worker 
961*f6dc9357SAndroid Build Coastguard Worker   m_ValueBlockSize = (7 << 10) + (1 << 12) * m_NumDivPasses;
962*f6dc9357SAndroid Build Coastguard Worker 
963*f6dc9357SAndroid Build Coastguard Worker   UInt64 nowPos = 0;
964*f6dc9357SAndroid Build Coastguard Worker 
965*f6dc9357SAndroid Build Coastguard Worker   MatchFinder_Init(&_lzInWindow);
966*f6dc9357SAndroid Build Coastguard Worker   m_OutStream.SetStream(outStream);
967*f6dc9357SAndroid Build Coastguard Worker   m_OutStream.Init();
968*f6dc9357SAndroid Build Coastguard Worker 
969*f6dc9357SAndroid Build Coastguard Worker   m_OptimumEndIndex = m_OptimumCurrentIndex = 0;
970*f6dc9357SAndroid Build Coastguard Worker 
971*f6dc9357SAndroid Build Coastguard Worker   CTables &t = m_Tables[1];
972*f6dc9357SAndroid Build Coastguard Worker   t.m_Pos = 0;
973*f6dc9357SAndroid Build Coastguard Worker   t.InitStructures();
974*f6dc9357SAndroid Build Coastguard Worker 
975*f6dc9357SAndroid Build Coastguard Worker   m_AdditionalOffset = 0;
976*f6dc9357SAndroid Build Coastguard Worker   do
977*f6dc9357SAndroid Build Coastguard Worker   {
978*f6dc9357SAndroid Build Coastguard Worker     t.BlockSizeRes = kBlockUncompressedSizeThreshold;
979*f6dc9357SAndroid Build Coastguard Worker     m_SecondPass = false;
980*f6dc9357SAndroid Build Coastguard Worker     GetBlockPrice(1, m_NumDivPasses);
981*f6dc9357SAndroid Build Coastguard Worker     CodeBlock(1, Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0);
982*f6dc9357SAndroid Build Coastguard Worker     nowPos += m_Tables[1].BlockSizeRes;
983*f6dc9357SAndroid Build Coastguard Worker     if (progress != NULL)
984*f6dc9357SAndroid Build Coastguard Worker     {
985*f6dc9357SAndroid Build Coastguard Worker       UInt64 packSize = m_OutStream.GetProcessedSize();
986*f6dc9357SAndroid Build Coastguard Worker       RINOK(progress->SetRatioInfo(&nowPos, &packSize))
987*f6dc9357SAndroid Build Coastguard Worker     }
988*f6dc9357SAndroid Build Coastguard Worker   }
989*f6dc9357SAndroid Build Coastguard Worker   while (Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) != 0);
990*f6dc9357SAndroid Build Coastguard Worker 
991*f6dc9357SAndroid Build Coastguard Worker   if (_seqInStream.Res != S_OK)
992*f6dc9357SAndroid Build Coastguard Worker     return _seqInStream.Res;
993*f6dc9357SAndroid Build Coastguard Worker 
994*f6dc9357SAndroid Build Coastguard Worker   if (_lzInWindow.result != SZ_OK)
995*f6dc9357SAndroid Build Coastguard Worker     return SResToHRESULT(_lzInWindow.result);
996*f6dc9357SAndroid Build Coastguard Worker   return m_OutStream.Flush();
997*f6dc9357SAndroid Build Coastguard Worker }
998*f6dc9357SAndroid Build Coastguard Worker 
BaseCode(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress)999*f6dc9357SAndroid Build Coastguard Worker HRESULT CCoder::BaseCode(ISequentialInStream *inStream, ISequentialOutStream *outStream,
1000*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
1001*f6dc9357SAndroid Build Coastguard Worker {
1002*f6dc9357SAndroid Build Coastguard Worker   try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
1003*f6dc9357SAndroid Build Coastguard Worker   catch(const COutBufferException &e) { return e.ErrorCode; }
1004*f6dc9357SAndroid Build Coastguard Worker   catch(...) { return E_FAIL; }
1005*f6dc9357SAndroid Build Coastguard Worker }
1006*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CCOMCoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))1007*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CCOMCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
1008*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
1009*f6dc9357SAndroid Build Coastguard Worker   { return BaseCode(inStream, outStream, inSize, outSize, progress); }
1010*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CCOMCoder::SetCoderProperties (const PROPID * propIDs,const PROPVARIANT * props,UInt32 numProps))1011*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CCOMCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))
1012*f6dc9357SAndroid Build Coastguard Worker   { return BaseSetEncoderProperties2(propIDs, props, numProps); }
1013*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CCOMCoder64::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))1014*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CCOMCoder64::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
1015*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
1016*f6dc9357SAndroid Build Coastguard Worker   { return BaseCode(inStream, outStream, inSize, outSize, progress); }
1017*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CCOMCoder64::SetCoderProperties (const PROPID * propIDs,const PROPVARIANT * props,UInt32 numProps))1018*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CCOMCoder64::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))
1019*f6dc9357SAndroid Build Coastguard Worker   { return BaseSetEncoderProperties2(propIDs, props, numProps); }
1020*f6dc9357SAndroid Build Coastguard Worker 
1021*f6dc9357SAndroid Build Coastguard Worker }}}
1022