xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/BZip2Encoder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // BZip2Encoder.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/BwtSort.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/HuffEnc.h"
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "BZip2Crc.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "BZip2Encoder.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "Mtf8.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
14*f6dc9357SAndroid Build Coastguard Worker namespace NBZip2 {
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker const unsigned kMaxHuffmanLenForEncoding = 16; // it must be < kMaxHuffmanLen = 20
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kBufferSize = (1 << 17);
19*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumHuffPasses = 4;
20*f6dc9357SAndroid Build Coastguard Worker 
Alloc()21*f6dc9357SAndroid Build Coastguard Worker bool CThreadInfo::Alloc()
22*f6dc9357SAndroid Build Coastguard Worker {
23*f6dc9357SAndroid Build Coastguard Worker   if (!m_BlockSorterIndex)
24*f6dc9357SAndroid Build Coastguard Worker   {
25*f6dc9357SAndroid Build Coastguard Worker     m_BlockSorterIndex = (UInt32 *)::BigAlloc(BLOCK_SORT_BUF_SIZE(kBlockSizeMax) * sizeof(UInt32));
26*f6dc9357SAndroid Build Coastguard Worker     if (!m_BlockSorterIndex)
27*f6dc9357SAndroid Build Coastguard Worker       return false;
28*f6dc9357SAndroid Build Coastguard Worker   }
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker   if (!m_Block)
31*f6dc9357SAndroid Build Coastguard Worker   {
32*f6dc9357SAndroid Build Coastguard Worker     m_Block = (Byte *)::MidAlloc(kBlockSizeMax * 5 + kBlockSizeMax / 10 + (20 << 10));
33*f6dc9357SAndroid Build Coastguard Worker     if (!m_Block)
34*f6dc9357SAndroid Build Coastguard Worker       return false;
35*f6dc9357SAndroid Build Coastguard Worker     m_MtfArray = m_Block + kBlockSizeMax;
36*f6dc9357SAndroid Build Coastguard Worker     m_TempArray = m_MtfArray + kBlockSizeMax * 2 + 2;
37*f6dc9357SAndroid Build Coastguard Worker   }
38*f6dc9357SAndroid Build Coastguard Worker   return true;
39*f6dc9357SAndroid Build Coastguard Worker }
40*f6dc9357SAndroid Build Coastguard Worker 
Free()41*f6dc9357SAndroid Build Coastguard Worker void CThreadInfo::Free()
42*f6dc9357SAndroid Build Coastguard Worker {
43*f6dc9357SAndroid Build Coastguard Worker   ::BigFree(m_BlockSorterIndex);
44*f6dc9357SAndroid Build Coastguard Worker   m_BlockSorterIndex = NULL;
45*f6dc9357SAndroid Build Coastguard Worker   ::MidFree(m_Block);
46*f6dc9357SAndroid Build Coastguard Worker   m_Block = NULL;
47*f6dc9357SAndroid Build Coastguard Worker }
48*f6dc9357SAndroid Build Coastguard Worker 
49*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
50*f6dc9357SAndroid Build Coastguard Worker 
MFThread(void * threadCoderInfo)51*f6dc9357SAndroid Build Coastguard Worker static THREAD_FUNC_DECL MFThread(void *threadCoderInfo)
52*f6dc9357SAndroid Build Coastguard Worker {
53*f6dc9357SAndroid Build Coastguard Worker   return ((CThreadInfo *)threadCoderInfo)->ThreadFunc();
54*f6dc9357SAndroid Build Coastguard Worker }
55*f6dc9357SAndroid Build Coastguard Worker 
Create()56*f6dc9357SAndroid Build Coastguard Worker HRESULT CThreadInfo::Create()
57*f6dc9357SAndroid Build Coastguard Worker {
58*f6dc9357SAndroid Build Coastguard Worker   WRes             wres = StreamWasFinishedEvent.Create();
59*f6dc9357SAndroid Build Coastguard Worker   if (wres == 0) { wres = WaitingWasStartedEvent.Create();
60*f6dc9357SAndroid Build Coastguard Worker   if (wres == 0) { wres = CanWriteEvent.Create();
61*f6dc9357SAndroid Build Coastguard Worker   if (wres == 0)
62*f6dc9357SAndroid Build Coastguard Worker   {
63*f6dc9357SAndroid Build Coastguard Worker     if (Encoder->_props.Affinity != 0)
64*f6dc9357SAndroid Build Coastguard Worker       wres = Thread.Create_With_Affinity(MFThread, this, (CAffinityMask)Encoder->_props.Affinity);
65*f6dc9357SAndroid Build Coastguard Worker     else
66*f6dc9357SAndroid Build Coastguard Worker       wres = Thread.Create(MFThread, this);
67*f6dc9357SAndroid Build Coastguard Worker   }}}
68*f6dc9357SAndroid Build Coastguard Worker   return HRESULT_FROM_WIN32(wres);
69*f6dc9357SAndroid Build Coastguard Worker }
70*f6dc9357SAndroid Build Coastguard Worker 
FinishStream(bool needLeave)71*f6dc9357SAndroid Build Coastguard Worker void CThreadInfo::FinishStream(bool needLeave)
72*f6dc9357SAndroid Build Coastguard Worker {
73*f6dc9357SAndroid Build Coastguard Worker   Encoder->StreamWasFinished = true;
74*f6dc9357SAndroid Build Coastguard Worker   StreamWasFinishedEvent.Set();
75*f6dc9357SAndroid Build Coastguard Worker   if (needLeave)
76*f6dc9357SAndroid Build Coastguard Worker     Encoder->CS.Leave();
77*f6dc9357SAndroid Build Coastguard Worker   Encoder->CanStartWaitingEvent.Lock();
78*f6dc9357SAndroid Build Coastguard Worker   WaitingWasStartedEvent.Set();
79*f6dc9357SAndroid Build Coastguard Worker }
80*f6dc9357SAndroid Build Coastguard Worker 
ThreadFunc()81*f6dc9357SAndroid Build Coastguard Worker THREAD_FUNC_RET_TYPE CThreadInfo::ThreadFunc()
82*f6dc9357SAndroid Build Coastguard Worker {
83*f6dc9357SAndroid Build Coastguard Worker   for (;;)
84*f6dc9357SAndroid Build Coastguard Worker   {
85*f6dc9357SAndroid Build Coastguard Worker     Encoder->CanProcessEvent.Lock();
86*f6dc9357SAndroid Build Coastguard Worker     Encoder->CS.Enter();
87*f6dc9357SAndroid Build Coastguard Worker     if (Encoder->CloseThreads)
88*f6dc9357SAndroid Build Coastguard Worker     {
89*f6dc9357SAndroid Build Coastguard Worker       Encoder->CS.Leave();
90*f6dc9357SAndroid Build Coastguard Worker       return 0;
91*f6dc9357SAndroid Build Coastguard Worker     }
92*f6dc9357SAndroid Build Coastguard Worker     if (Encoder->StreamWasFinished)
93*f6dc9357SAndroid Build Coastguard Worker     {
94*f6dc9357SAndroid Build Coastguard Worker       FinishStream(true);
95*f6dc9357SAndroid Build Coastguard Worker       continue;
96*f6dc9357SAndroid Build Coastguard Worker     }
97*f6dc9357SAndroid Build Coastguard Worker     HRESULT res = S_OK;
98*f6dc9357SAndroid Build Coastguard Worker     bool needLeave = true;
99*f6dc9357SAndroid Build Coastguard Worker     try
100*f6dc9357SAndroid Build Coastguard Worker     {
101*f6dc9357SAndroid Build Coastguard Worker       const UInt32 blockSize = Encoder->ReadRleBlock(m_Block);
102*f6dc9357SAndroid Build Coastguard Worker       m_UnpackSize = Encoder->m_InStream.GetProcessedSize();
103*f6dc9357SAndroid Build Coastguard Worker       m_BlockIndex = Encoder->NextBlockIndex;
104*f6dc9357SAndroid Build Coastguard Worker       if (++Encoder->NextBlockIndex == Encoder->NumThreads)
105*f6dc9357SAndroid Build Coastguard Worker         Encoder->NextBlockIndex = 0;
106*f6dc9357SAndroid Build Coastguard Worker       if (blockSize == 0)
107*f6dc9357SAndroid Build Coastguard Worker       {
108*f6dc9357SAndroid Build Coastguard Worker         FinishStream(true);
109*f6dc9357SAndroid Build Coastguard Worker         continue;
110*f6dc9357SAndroid Build Coastguard Worker       }
111*f6dc9357SAndroid Build Coastguard Worker       Encoder->CS.Leave();
112*f6dc9357SAndroid Build Coastguard Worker       needLeave = false;
113*f6dc9357SAndroid Build Coastguard Worker       res = EncodeBlock3(blockSize);
114*f6dc9357SAndroid Build Coastguard Worker     }
115*f6dc9357SAndroid Build Coastguard Worker     catch(const CInBufferException &e)  { res = e.ErrorCode; }
116*f6dc9357SAndroid Build Coastguard Worker     catch(const COutBufferException &e) { res = e.ErrorCode; }
117*f6dc9357SAndroid Build Coastguard Worker     catch(...) { res = E_FAIL; }
118*f6dc9357SAndroid Build Coastguard Worker     if (res != S_OK)
119*f6dc9357SAndroid Build Coastguard Worker     {
120*f6dc9357SAndroid Build Coastguard Worker       Encoder->Result = res;
121*f6dc9357SAndroid Build Coastguard Worker       FinishStream(needLeave);
122*f6dc9357SAndroid Build Coastguard Worker       continue;
123*f6dc9357SAndroid Build Coastguard Worker     }
124*f6dc9357SAndroid Build Coastguard Worker   }
125*f6dc9357SAndroid Build Coastguard Worker }
126*f6dc9357SAndroid Build Coastguard Worker 
127*f6dc9357SAndroid Build Coastguard Worker #endif
128*f6dc9357SAndroid Build Coastguard Worker 
Normalize(int level)129*f6dc9357SAndroid Build Coastguard Worker void CEncProps::Normalize(int level)
130*f6dc9357SAndroid Build Coastguard Worker {
131*f6dc9357SAndroid Build Coastguard Worker   if (level < 0) level = 5;
132*f6dc9357SAndroid Build Coastguard Worker   if (level > 9) level = 9;
133*f6dc9357SAndroid Build Coastguard Worker 
134*f6dc9357SAndroid Build Coastguard Worker   if (NumPasses == (UInt32)(Int32)-1)
135*f6dc9357SAndroid Build Coastguard Worker     NumPasses = (level >= 9 ? 7 : (level >= 7 ? 2 : 1));
136*f6dc9357SAndroid Build Coastguard Worker   if (NumPasses < 1) NumPasses = 1;
137*f6dc9357SAndroid Build Coastguard Worker   if (NumPasses > kNumPassesMax) NumPasses = kNumPassesMax;
138*f6dc9357SAndroid Build Coastguard Worker 
139*f6dc9357SAndroid Build Coastguard Worker   if (BlockSizeMult == (UInt32)(Int32)-1)
140*f6dc9357SAndroid Build Coastguard Worker     BlockSizeMult = (level >= 5 ? 9 : (level >= 1 ? (unsigned)level * 2 - 1: 1));
141*f6dc9357SAndroid Build Coastguard Worker   if (BlockSizeMult < kBlockSizeMultMin) BlockSizeMult = kBlockSizeMultMin;
142*f6dc9357SAndroid Build Coastguard Worker   if (BlockSizeMult > kBlockSizeMultMax) BlockSizeMult = kBlockSizeMultMax;
143*f6dc9357SAndroid Build Coastguard Worker }
144*f6dc9357SAndroid Build Coastguard Worker 
CEncoder()145*f6dc9357SAndroid Build Coastguard Worker CEncoder::CEncoder()
146*f6dc9357SAndroid Build Coastguard Worker {
147*f6dc9357SAndroid Build Coastguard Worker   _props.Normalize(-1);
148*f6dc9357SAndroid Build Coastguard Worker 
149*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
150*f6dc9357SAndroid Build Coastguard Worker   ThreadsInfo = NULL;
151*f6dc9357SAndroid Build Coastguard Worker   m_NumThreadsPrev = 0;
152*f6dc9357SAndroid Build Coastguard Worker   NumThreads = 1;
153*f6dc9357SAndroid Build Coastguard Worker   #endif
154*f6dc9357SAndroid Build Coastguard Worker }
155*f6dc9357SAndroid Build Coastguard Worker 
156*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
~CEncoder()157*f6dc9357SAndroid Build Coastguard Worker CEncoder::~CEncoder()
158*f6dc9357SAndroid Build Coastguard Worker {
159*f6dc9357SAndroid Build Coastguard Worker   Free();
160*f6dc9357SAndroid Build Coastguard Worker }
161*f6dc9357SAndroid Build Coastguard Worker 
Create()162*f6dc9357SAndroid Build Coastguard Worker HRESULT CEncoder::Create()
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker   {
165*f6dc9357SAndroid Build Coastguard Worker     WRes             wres = CanProcessEvent.CreateIfNotCreated_Reset();
166*f6dc9357SAndroid Build Coastguard Worker     if (wres == 0) { wres = CanStartWaitingEvent.CreateIfNotCreated_Reset(); }
167*f6dc9357SAndroid Build Coastguard Worker     if (wres != 0)
168*f6dc9357SAndroid Build Coastguard Worker       return HRESULT_FROM_WIN32(wres);
169*f6dc9357SAndroid Build Coastguard Worker   }
170*f6dc9357SAndroid Build Coastguard Worker 
171*f6dc9357SAndroid Build Coastguard Worker   if (ThreadsInfo && m_NumThreadsPrev == NumThreads)
172*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
173*f6dc9357SAndroid Build Coastguard Worker   try
174*f6dc9357SAndroid Build Coastguard Worker   {
175*f6dc9357SAndroid Build Coastguard Worker     Free();
176*f6dc9357SAndroid Build Coastguard Worker     MtMode = (NumThreads > 1);
177*f6dc9357SAndroid Build Coastguard Worker     m_NumThreadsPrev = NumThreads;
178*f6dc9357SAndroid Build Coastguard Worker     ThreadsInfo = new CThreadInfo[NumThreads];
179*f6dc9357SAndroid Build Coastguard Worker     if (!ThreadsInfo)
180*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
181*f6dc9357SAndroid Build Coastguard Worker   }
182*f6dc9357SAndroid Build Coastguard Worker   catch(...) { return E_OUTOFMEMORY; }
183*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 t = 0; t < NumThreads; t++)
184*f6dc9357SAndroid Build Coastguard Worker   {
185*f6dc9357SAndroid Build Coastguard Worker     CThreadInfo &ti = ThreadsInfo[t];
186*f6dc9357SAndroid Build Coastguard Worker     ti.Encoder = this;
187*f6dc9357SAndroid Build Coastguard Worker     if (MtMode)
188*f6dc9357SAndroid Build Coastguard Worker     {
189*f6dc9357SAndroid Build Coastguard Worker       HRESULT res = ti.Create();
190*f6dc9357SAndroid Build Coastguard Worker       if (res != S_OK)
191*f6dc9357SAndroid Build Coastguard Worker       {
192*f6dc9357SAndroid Build Coastguard Worker         NumThreads = t;
193*f6dc9357SAndroid Build Coastguard Worker         Free();
194*f6dc9357SAndroid Build Coastguard Worker         return res;
195*f6dc9357SAndroid Build Coastguard Worker       }
196*f6dc9357SAndroid Build Coastguard Worker     }
197*f6dc9357SAndroid Build Coastguard Worker   }
198*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
199*f6dc9357SAndroid Build Coastguard Worker }
200*f6dc9357SAndroid Build Coastguard Worker 
Free()201*f6dc9357SAndroid Build Coastguard Worker void CEncoder::Free()
202*f6dc9357SAndroid Build Coastguard Worker {
203*f6dc9357SAndroid Build Coastguard Worker   if (!ThreadsInfo)
204*f6dc9357SAndroid Build Coastguard Worker     return;
205*f6dc9357SAndroid Build Coastguard Worker   CloseThreads = true;
206*f6dc9357SAndroid Build Coastguard Worker   CanProcessEvent.Set();
207*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 t = 0; t < NumThreads; t++)
208*f6dc9357SAndroid Build Coastguard Worker   {
209*f6dc9357SAndroid Build Coastguard Worker     CThreadInfo &ti = ThreadsInfo[t];
210*f6dc9357SAndroid Build Coastguard Worker     if (MtMode)
211*f6dc9357SAndroid Build Coastguard Worker       ti.Thread.Wait_Close();
212*f6dc9357SAndroid Build Coastguard Worker     ti.Free();
213*f6dc9357SAndroid Build Coastguard Worker   }
214*f6dc9357SAndroid Build Coastguard Worker   delete []ThreadsInfo;
215*f6dc9357SAndroid Build Coastguard Worker   ThreadsInfo = NULL;
216*f6dc9357SAndroid Build Coastguard Worker }
217*f6dc9357SAndroid Build Coastguard Worker #endif
218*f6dc9357SAndroid Build Coastguard Worker 
ReadRleBlock(Byte * buffer)219*f6dc9357SAndroid Build Coastguard Worker UInt32 CEncoder::ReadRleBlock(Byte *buffer)
220*f6dc9357SAndroid Build Coastguard Worker {
221*f6dc9357SAndroid Build Coastguard Worker   UInt32 i = 0;
222*f6dc9357SAndroid Build Coastguard Worker   Byte prevByte;
223*f6dc9357SAndroid Build Coastguard Worker   if (m_InStream.ReadByte(prevByte))
224*f6dc9357SAndroid Build Coastguard Worker   {
225*f6dc9357SAndroid Build Coastguard Worker     NumBlocks++;
226*f6dc9357SAndroid Build Coastguard Worker     const UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1;
227*f6dc9357SAndroid Build Coastguard Worker     unsigned numReps = 1;
228*f6dc9357SAndroid Build Coastguard Worker     buffer[i++] = prevByte;
229*f6dc9357SAndroid Build Coastguard Worker     while (i < blockSize) // "- 1" to support RLE
230*f6dc9357SAndroid Build Coastguard Worker     {
231*f6dc9357SAndroid Build Coastguard Worker       Byte b;
232*f6dc9357SAndroid Build Coastguard Worker       if (!m_InStream.ReadByte(b))
233*f6dc9357SAndroid Build Coastguard Worker         break;
234*f6dc9357SAndroid Build Coastguard Worker       if (b != prevByte)
235*f6dc9357SAndroid Build Coastguard Worker       {
236*f6dc9357SAndroid Build Coastguard Worker         if (numReps >= kRleModeRepSize)
237*f6dc9357SAndroid Build Coastguard Worker           buffer[i++] = (Byte)(numReps - kRleModeRepSize);
238*f6dc9357SAndroid Build Coastguard Worker         buffer[i++] = b;
239*f6dc9357SAndroid Build Coastguard Worker         numReps = 1;
240*f6dc9357SAndroid Build Coastguard Worker         prevByte = b;
241*f6dc9357SAndroid Build Coastguard Worker         continue;
242*f6dc9357SAndroid Build Coastguard Worker       }
243*f6dc9357SAndroid Build Coastguard Worker       numReps++;
244*f6dc9357SAndroid Build Coastguard Worker       if (numReps <= kRleModeRepSize)
245*f6dc9357SAndroid Build Coastguard Worker         buffer[i++] = b;
246*f6dc9357SAndroid Build Coastguard Worker       else if (numReps == kRleModeRepSize + 255)
247*f6dc9357SAndroid Build Coastguard Worker       {
248*f6dc9357SAndroid Build Coastguard Worker         buffer[i++] = (Byte)(numReps - kRleModeRepSize);
249*f6dc9357SAndroid Build Coastguard Worker         numReps = 0;
250*f6dc9357SAndroid Build Coastguard Worker       }
251*f6dc9357SAndroid Build Coastguard Worker     }
252*f6dc9357SAndroid Build Coastguard Worker     // it's to support original BZip2 decoder
253*f6dc9357SAndroid Build Coastguard Worker     if (numReps >= kRleModeRepSize)
254*f6dc9357SAndroid Build Coastguard Worker       buffer[i++] = (Byte)(numReps - kRleModeRepSize);
255*f6dc9357SAndroid Build Coastguard Worker   }
256*f6dc9357SAndroid Build Coastguard Worker   return i;
257*f6dc9357SAndroid Build Coastguard Worker }
258*f6dc9357SAndroid Build Coastguard Worker 
WriteBits2(UInt32 value,unsigned numBits)259*f6dc9357SAndroid Build Coastguard Worker void CThreadInfo::WriteBits2(UInt32 value, unsigned numBits) { m_OutStreamCurrent->WriteBits(value, numBits); }
WriteByte2(Byte b)260*f6dc9357SAndroid Build Coastguard Worker void CThreadInfo::WriteByte2(Byte b) { WriteBits2(b, 8); }
WriteBit2(Byte v)261*f6dc9357SAndroid Build Coastguard Worker void CThreadInfo::WriteBit2(Byte v) { WriteBits2(v, 1); }
WriteCrc2(UInt32 v)262*f6dc9357SAndroid Build Coastguard Worker void CThreadInfo::WriteCrc2(UInt32 v)
263*f6dc9357SAndroid Build Coastguard Worker {
264*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < 4; i++)
265*f6dc9357SAndroid Build Coastguard Worker     WriteByte2(((Byte)(v >> (24 - i * 8))));
266*f6dc9357SAndroid Build Coastguard Worker }
267*f6dc9357SAndroid Build Coastguard Worker 
WriteBits(UInt32 value,unsigned numBits)268*f6dc9357SAndroid Build Coastguard Worker void CEncoder::WriteBits(UInt32 value, unsigned numBits) { m_OutStream.WriteBits(value, numBits); }
WriteByte(Byte b)269*f6dc9357SAndroid Build Coastguard Worker void CEncoder::WriteByte(Byte b) { WriteBits(b, 8); }
270*f6dc9357SAndroid Build Coastguard Worker // void CEncoder::WriteBit(Byte v) { WriteBits(v, 1); }
WriteCrc(UInt32 v)271*f6dc9357SAndroid Build Coastguard Worker void CEncoder::WriteCrc(UInt32 v)
272*f6dc9357SAndroid Build Coastguard Worker {
273*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < 4; i++)
274*f6dc9357SAndroid Build Coastguard Worker     WriteByte(((Byte)(v >> (24 - i * 8))));
275*f6dc9357SAndroid Build Coastguard Worker }
276*f6dc9357SAndroid Build Coastguard Worker 
277*f6dc9357SAndroid Build Coastguard Worker 
278*f6dc9357SAndroid Build Coastguard Worker // blockSize > 0
EncodeBlock(const Byte * block,UInt32 blockSize)279*f6dc9357SAndroid Build Coastguard Worker void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
280*f6dc9357SAndroid Build Coastguard Worker {
281*f6dc9357SAndroid Build Coastguard Worker   WriteBit2(0); // Randomised = false
282*f6dc9357SAndroid Build Coastguard Worker 
283*f6dc9357SAndroid Build Coastguard Worker   {
284*f6dc9357SAndroid Build Coastguard Worker     UInt32 origPtr = BlockSort(m_BlockSorterIndex, block, blockSize);
285*f6dc9357SAndroid Build Coastguard Worker     // if (m_BlockSorterIndex[origPtr] != 0) throw 1;
286*f6dc9357SAndroid Build Coastguard Worker     m_BlockSorterIndex[origPtr] = blockSize;
287*f6dc9357SAndroid Build Coastguard Worker     WriteBits2(origPtr, kNumOrigBits);
288*f6dc9357SAndroid Build Coastguard Worker   }
289*f6dc9357SAndroid Build Coastguard Worker 
290*f6dc9357SAndroid Build Coastguard Worker   CMtf8Encoder mtf;
291*f6dc9357SAndroid Build Coastguard Worker   unsigned numInUse = 0;
292*f6dc9357SAndroid Build Coastguard Worker   {
293*f6dc9357SAndroid Build Coastguard Worker     Byte inUse[256];
294*f6dc9357SAndroid Build Coastguard Worker     Byte inUse16[16];
295*f6dc9357SAndroid Build Coastguard Worker     UInt32 i;
296*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < 256; i++)
297*f6dc9357SAndroid Build Coastguard Worker       inUse[i] = 0;
298*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < 16; i++)
299*f6dc9357SAndroid Build Coastguard Worker       inUse16[i] = 0;
300*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < blockSize; i++)
301*f6dc9357SAndroid Build Coastguard Worker       inUse[block[i]] = 1;
302*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < 256; i++)
303*f6dc9357SAndroid Build Coastguard Worker       if (inUse[i])
304*f6dc9357SAndroid Build Coastguard Worker       {
305*f6dc9357SAndroid Build Coastguard Worker         inUse16[i >> 4] = 1;
306*f6dc9357SAndroid Build Coastguard Worker         mtf.Buf[numInUse++] = (Byte)i;
307*f6dc9357SAndroid Build Coastguard Worker       }
308*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < 16; i++)
309*f6dc9357SAndroid Build Coastguard Worker       WriteBit2(inUse16[i]);
310*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < 256; i++)
311*f6dc9357SAndroid Build Coastguard Worker       if (inUse16[i >> 4])
312*f6dc9357SAndroid Build Coastguard Worker         WriteBit2(inUse[i]);
313*f6dc9357SAndroid Build Coastguard Worker   }
314*f6dc9357SAndroid Build Coastguard Worker   unsigned alphaSize = numInUse + 2;
315*f6dc9357SAndroid Build Coastguard Worker 
316*f6dc9357SAndroid Build Coastguard Worker   Byte *mtfs = m_MtfArray;
317*f6dc9357SAndroid Build Coastguard Worker   UInt32 mtfArraySize = 0;
318*f6dc9357SAndroid Build Coastguard Worker   UInt32 symbolCounts[kMaxAlphaSize];
319*f6dc9357SAndroid Build Coastguard Worker   {
320*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < kMaxAlphaSize; i++)
321*f6dc9357SAndroid Build Coastguard Worker       symbolCounts[i] = 0;
322*f6dc9357SAndroid Build Coastguard Worker   }
323*f6dc9357SAndroid Build Coastguard Worker 
324*f6dc9357SAndroid Build Coastguard Worker   {
325*f6dc9357SAndroid Build Coastguard Worker     UInt32 rleSize = 0;
326*f6dc9357SAndroid Build Coastguard Worker     UInt32 i = 0;
327*f6dc9357SAndroid Build Coastguard Worker     const UInt32 *bsIndex = m_BlockSorterIndex;
328*f6dc9357SAndroid Build Coastguard Worker     block--;
329*f6dc9357SAndroid Build Coastguard Worker     do
330*f6dc9357SAndroid Build Coastguard Worker     {
331*f6dc9357SAndroid Build Coastguard Worker       unsigned pos = mtf.FindAndMove(block[bsIndex[i]]);
332*f6dc9357SAndroid Build Coastguard Worker       if (pos == 0)
333*f6dc9357SAndroid Build Coastguard Worker         rleSize++;
334*f6dc9357SAndroid Build Coastguard Worker       else
335*f6dc9357SAndroid Build Coastguard Worker       {
336*f6dc9357SAndroid Build Coastguard Worker         while (rleSize != 0)
337*f6dc9357SAndroid Build Coastguard Worker         {
338*f6dc9357SAndroid Build Coastguard Worker           rleSize--;
339*f6dc9357SAndroid Build Coastguard Worker           mtfs[mtfArraySize++] = (Byte)(rleSize & 1);
340*f6dc9357SAndroid Build Coastguard Worker           symbolCounts[rleSize & 1]++;
341*f6dc9357SAndroid Build Coastguard Worker           rleSize >>= 1;
342*f6dc9357SAndroid Build Coastguard Worker         }
343*f6dc9357SAndroid Build Coastguard Worker         if (pos >= 0xFE)
344*f6dc9357SAndroid Build Coastguard Worker         {
345*f6dc9357SAndroid Build Coastguard Worker           mtfs[mtfArraySize++] = 0xFF;
346*f6dc9357SAndroid Build Coastguard Worker           mtfs[mtfArraySize++] = (Byte)(pos - 0xFE);
347*f6dc9357SAndroid Build Coastguard Worker         }
348*f6dc9357SAndroid Build Coastguard Worker         else
349*f6dc9357SAndroid Build Coastguard Worker           mtfs[mtfArraySize++] = (Byte)(pos + 1);
350*f6dc9357SAndroid Build Coastguard Worker         symbolCounts[(size_t)pos + 1]++;
351*f6dc9357SAndroid Build Coastguard Worker       }
352*f6dc9357SAndroid Build Coastguard Worker     }
353*f6dc9357SAndroid Build Coastguard Worker     while (++i < blockSize);
354*f6dc9357SAndroid Build Coastguard Worker 
355*f6dc9357SAndroid Build Coastguard Worker     while (rleSize != 0)
356*f6dc9357SAndroid Build Coastguard Worker     {
357*f6dc9357SAndroid Build Coastguard Worker       rleSize--;
358*f6dc9357SAndroid Build Coastguard Worker       mtfs[mtfArraySize++] = (Byte)(rleSize & 1);
359*f6dc9357SAndroid Build Coastguard Worker       symbolCounts[rleSize & 1]++;
360*f6dc9357SAndroid Build Coastguard Worker       rleSize >>= 1;
361*f6dc9357SAndroid Build Coastguard Worker     }
362*f6dc9357SAndroid Build Coastguard Worker 
363*f6dc9357SAndroid Build Coastguard Worker     if (alphaSize < 256)
364*f6dc9357SAndroid Build Coastguard Worker       mtfs[mtfArraySize++] = (Byte)(alphaSize - 1);
365*f6dc9357SAndroid Build Coastguard Worker     else
366*f6dc9357SAndroid Build Coastguard Worker     {
367*f6dc9357SAndroid Build Coastguard Worker       mtfs[mtfArraySize++] = 0xFF;
368*f6dc9357SAndroid Build Coastguard Worker       mtfs[mtfArraySize++] = (Byte)(alphaSize - 256);
369*f6dc9357SAndroid Build Coastguard Worker     }
370*f6dc9357SAndroid Build Coastguard Worker     symbolCounts[(size_t)alphaSize - 1]++;
371*f6dc9357SAndroid Build Coastguard Worker   }
372*f6dc9357SAndroid Build Coastguard Worker 
373*f6dc9357SAndroid Build Coastguard Worker   UInt32 numSymbols = 0;
374*f6dc9357SAndroid Build Coastguard Worker   {
375*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < kMaxAlphaSize; i++)
376*f6dc9357SAndroid Build Coastguard Worker       numSymbols += symbolCounts[i];
377*f6dc9357SAndroid Build Coastguard Worker   }
378*f6dc9357SAndroid Build Coastguard Worker 
379*f6dc9357SAndroid Build Coastguard Worker   unsigned bestNumTables = kNumTablesMin;
380*f6dc9357SAndroid Build Coastguard Worker   UInt32 bestPrice = 0xFFFFFFFF;
381*f6dc9357SAndroid Build Coastguard Worker   UInt32 startPos = m_OutStreamCurrent->GetPos();
382*f6dc9357SAndroid Build Coastguard Worker   Byte startCurByte = m_OutStreamCurrent->GetCurByte();
383*f6dc9357SAndroid Build Coastguard Worker   for (unsigned nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++)
384*f6dc9357SAndroid Build Coastguard Worker   {
385*f6dc9357SAndroid Build Coastguard Worker     unsigned numTables;
386*f6dc9357SAndroid Build Coastguard Worker 
387*f6dc9357SAndroid Build Coastguard Worker     if (m_OptimizeNumTables)
388*f6dc9357SAndroid Build Coastguard Worker     {
389*f6dc9357SAndroid Build Coastguard Worker       m_OutStreamCurrent->SetPos(startPos);
390*f6dc9357SAndroid Build Coastguard Worker       m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte);
391*f6dc9357SAndroid Build Coastguard Worker       if (nt <= kNumTablesMax)
392*f6dc9357SAndroid Build Coastguard Worker         numTables = nt;
393*f6dc9357SAndroid Build Coastguard Worker       else
394*f6dc9357SAndroid Build Coastguard Worker         numTables = bestNumTables;
395*f6dc9357SAndroid Build Coastguard Worker     }
396*f6dc9357SAndroid Build Coastguard Worker     else
397*f6dc9357SAndroid Build Coastguard Worker     {
398*f6dc9357SAndroid Build Coastguard Worker       if (numSymbols < 200)  numTables = 2;
399*f6dc9357SAndroid Build Coastguard Worker       else if (numSymbols < 600) numTables = 3;
400*f6dc9357SAndroid Build Coastguard Worker       else if (numSymbols < 1200) numTables = 4;
401*f6dc9357SAndroid Build Coastguard Worker       else if (numSymbols < 2400) numTables = 5;
402*f6dc9357SAndroid Build Coastguard Worker       else numTables = 6;
403*f6dc9357SAndroid Build Coastguard Worker     }
404*f6dc9357SAndroid Build Coastguard Worker 
405*f6dc9357SAndroid Build Coastguard Worker     WriteBits2(numTables, kNumTablesBits);
406*f6dc9357SAndroid Build Coastguard Worker 
407*f6dc9357SAndroid Build Coastguard Worker     UInt32 numSelectors = (numSymbols + kGroupSize - 1) / kGroupSize;
408*f6dc9357SAndroid Build Coastguard Worker     WriteBits2(numSelectors, kNumSelectorsBits);
409*f6dc9357SAndroid Build Coastguard Worker 
410*f6dc9357SAndroid Build Coastguard Worker     {
411*f6dc9357SAndroid Build Coastguard Worker       UInt32 remFreq = numSymbols;
412*f6dc9357SAndroid Build Coastguard Worker       unsigned gs = 0;
413*f6dc9357SAndroid Build Coastguard Worker       unsigned t = numTables;
414*f6dc9357SAndroid Build Coastguard Worker       do
415*f6dc9357SAndroid Build Coastguard Worker       {
416*f6dc9357SAndroid Build Coastguard Worker         UInt32 tFreq = remFreq / t;
417*f6dc9357SAndroid Build Coastguard Worker         unsigned ge = gs;
418*f6dc9357SAndroid Build Coastguard Worker         UInt32 aFreq = 0;
419*f6dc9357SAndroid Build Coastguard Worker         while (aFreq < tFreq) //  && ge < alphaSize)
420*f6dc9357SAndroid Build Coastguard Worker           aFreq += symbolCounts[ge++];
421*f6dc9357SAndroid Build Coastguard Worker 
422*f6dc9357SAndroid Build Coastguard Worker         if (ge > gs + 1 && t != numTables && t != 1 && (((numTables - t) & 1) == 1))
423*f6dc9357SAndroid Build Coastguard Worker           aFreq -= symbolCounts[--ge];
424*f6dc9357SAndroid Build Coastguard Worker 
425*f6dc9357SAndroid Build Coastguard Worker         Byte *lens = Lens[(size_t)t - 1];
426*f6dc9357SAndroid Build Coastguard Worker         unsigned i = 0;
427*f6dc9357SAndroid Build Coastguard Worker         do
428*f6dc9357SAndroid Build Coastguard Worker           lens[i] = (Byte)((i >= gs && i < ge) ? 0 : 1);
429*f6dc9357SAndroid Build Coastguard Worker         while (++i < alphaSize);
430*f6dc9357SAndroid Build Coastguard Worker         gs = ge;
431*f6dc9357SAndroid Build Coastguard Worker         remFreq -= aFreq;
432*f6dc9357SAndroid Build Coastguard Worker       }
433*f6dc9357SAndroid Build Coastguard Worker       while (--t != 0);
434*f6dc9357SAndroid Build Coastguard Worker     }
435*f6dc9357SAndroid Build Coastguard Worker 
436*f6dc9357SAndroid Build Coastguard Worker 
437*f6dc9357SAndroid Build Coastguard Worker     for (unsigned pass = 0; pass < kNumHuffPasses; pass++)
438*f6dc9357SAndroid Build Coastguard Worker     {
439*f6dc9357SAndroid Build Coastguard Worker       {
440*f6dc9357SAndroid Build Coastguard Worker         unsigned t = 0;
441*f6dc9357SAndroid Build Coastguard Worker         do
442*f6dc9357SAndroid Build Coastguard Worker           memset(Freqs[t], 0, sizeof(Freqs[t]));
443*f6dc9357SAndroid Build Coastguard Worker         while (++t < numTables);
444*f6dc9357SAndroid Build Coastguard Worker       }
445*f6dc9357SAndroid Build Coastguard Worker 
446*f6dc9357SAndroid Build Coastguard Worker       {
447*f6dc9357SAndroid Build Coastguard Worker         UInt32 mtfPos = 0;
448*f6dc9357SAndroid Build Coastguard Worker         UInt32 g = 0;
449*f6dc9357SAndroid Build Coastguard Worker         do
450*f6dc9357SAndroid Build Coastguard Worker         {
451*f6dc9357SAndroid Build Coastguard Worker           UInt32 symbols[kGroupSize];
452*f6dc9357SAndroid Build Coastguard Worker           unsigned i = 0;
453*f6dc9357SAndroid Build Coastguard Worker           do
454*f6dc9357SAndroid Build Coastguard Worker           {
455*f6dc9357SAndroid Build Coastguard Worker             UInt32 symbol = mtfs[mtfPos++];
456*f6dc9357SAndroid Build Coastguard Worker             if (symbol >= 0xFF)
457*f6dc9357SAndroid Build Coastguard Worker               symbol += mtfs[mtfPos++];
458*f6dc9357SAndroid Build Coastguard Worker             symbols[i] = symbol;
459*f6dc9357SAndroid Build Coastguard Worker           }
460*f6dc9357SAndroid Build Coastguard Worker           while (++i < kGroupSize && mtfPos < mtfArraySize);
461*f6dc9357SAndroid Build Coastguard Worker 
462*f6dc9357SAndroid Build Coastguard Worker           UInt32 bestPrice2 = 0xFFFFFFFF;
463*f6dc9357SAndroid Build Coastguard Worker           unsigned t = 0;
464*f6dc9357SAndroid Build Coastguard Worker           do
465*f6dc9357SAndroid Build Coastguard Worker           {
466*f6dc9357SAndroid Build Coastguard Worker             const Byte *lens = Lens[t];
467*f6dc9357SAndroid Build Coastguard Worker             UInt32 price = 0;
468*f6dc9357SAndroid Build Coastguard Worker             unsigned j = 0;
469*f6dc9357SAndroid Build Coastguard Worker             do
470*f6dc9357SAndroid Build Coastguard Worker               price += lens[symbols[j]];
471*f6dc9357SAndroid Build Coastguard Worker             while (++j < i);
472*f6dc9357SAndroid Build Coastguard Worker             if (price < bestPrice2)
473*f6dc9357SAndroid Build Coastguard Worker             {
474*f6dc9357SAndroid Build Coastguard Worker               m_Selectors[g] = (Byte)t;
475*f6dc9357SAndroid Build Coastguard Worker               bestPrice2 = price;
476*f6dc9357SAndroid Build Coastguard Worker             }
477*f6dc9357SAndroid Build Coastguard Worker           }
478*f6dc9357SAndroid Build Coastguard Worker           while (++t < numTables);
479*f6dc9357SAndroid Build Coastguard Worker           UInt32 *freqs = Freqs[m_Selectors[g++]];
480*f6dc9357SAndroid Build Coastguard Worker           unsigned j = 0;
481*f6dc9357SAndroid Build Coastguard Worker           do
482*f6dc9357SAndroid Build Coastguard Worker             freqs[symbols[j]]++;
483*f6dc9357SAndroid Build Coastguard Worker           while (++j < i);
484*f6dc9357SAndroid Build Coastguard Worker         }
485*f6dc9357SAndroid Build Coastguard Worker         while (mtfPos < mtfArraySize);
486*f6dc9357SAndroid Build Coastguard Worker       }
487*f6dc9357SAndroid Build Coastguard Worker 
488*f6dc9357SAndroid Build Coastguard Worker       unsigned t = 0;
489*f6dc9357SAndroid Build Coastguard Worker       do
490*f6dc9357SAndroid Build Coastguard Worker       {
491*f6dc9357SAndroid Build Coastguard Worker         UInt32 *freqs = Freqs[t];
492*f6dc9357SAndroid Build Coastguard Worker         unsigned i = 0;
493*f6dc9357SAndroid Build Coastguard Worker         do
494*f6dc9357SAndroid Build Coastguard Worker           if (freqs[i] == 0)
495*f6dc9357SAndroid Build Coastguard Worker             freqs[i] = 1;
496*f6dc9357SAndroid Build Coastguard Worker         while (++i < alphaSize);
497*f6dc9357SAndroid Build Coastguard Worker         Huffman_Generate(freqs, Codes[t], Lens[t], kMaxAlphaSize, kMaxHuffmanLenForEncoding);
498*f6dc9357SAndroid Build Coastguard Worker       }
499*f6dc9357SAndroid Build Coastguard Worker       while (++t < numTables);
500*f6dc9357SAndroid Build Coastguard Worker     }
501*f6dc9357SAndroid Build Coastguard Worker 
502*f6dc9357SAndroid Build Coastguard Worker     {
503*f6dc9357SAndroid Build Coastguard Worker       Byte mtfSel[kNumTablesMax];
504*f6dc9357SAndroid Build Coastguard Worker       {
505*f6dc9357SAndroid Build Coastguard Worker         unsigned t = 0;
506*f6dc9357SAndroid Build Coastguard Worker         do
507*f6dc9357SAndroid Build Coastguard Worker           mtfSel[t] = (Byte)t;
508*f6dc9357SAndroid Build Coastguard Worker         while (++t < numTables);
509*f6dc9357SAndroid Build Coastguard Worker       }
510*f6dc9357SAndroid Build Coastguard Worker 
511*f6dc9357SAndroid Build Coastguard Worker       UInt32 i = 0;
512*f6dc9357SAndroid Build Coastguard Worker       do
513*f6dc9357SAndroid Build Coastguard Worker       {
514*f6dc9357SAndroid Build Coastguard Worker         Byte sel = m_Selectors[i];
515*f6dc9357SAndroid Build Coastguard Worker         unsigned pos;
516*f6dc9357SAndroid Build Coastguard Worker         for (pos = 0; mtfSel[pos] != sel; pos++)
517*f6dc9357SAndroid Build Coastguard Worker           WriteBit2(1);
518*f6dc9357SAndroid Build Coastguard Worker         WriteBit2(0);
519*f6dc9357SAndroid Build Coastguard Worker         for (; pos > 0; pos--)
520*f6dc9357SAndroid Build Coastguard Worker           mtfSel[pos] = mtfSel[(size_t)pos - 1];
521*f6dc9357SAndroid Build Coastguard Worker         mtfSel[0] = sel;
522*f6dc9357SAndroid Build Coastguard Worker       }
523*f6dc9357SAndroid Build Coastguard Worker       while (++i < numSelectors);
524*f6dc9357SAndroid Build Coastguard Worker     }
525*f6dc9357SAndroid Build Coastguard Worker 
526*f6dc9357SAndroid Build Coastguard Worker     {
527*f6dc9357SAndroid Build Coastguard Worker       unsigned t = 0;
528*f6dc9357SAndroid Build Coastguard Worker       do
529*f6dc9357SAndroid Build Coastguard Worker       {
530*f6dc9357SAndroid Build Coastguard Worker         const Byte *lens = Lens[t];
531*f6dc9357SAndroid Build Coastguard Worker         UInt32 len = lens[0];
532*f6dc9357SAndroid Build Coastguard Worker         WriteBits2(len, kNumLevelsBits);
533*f6dc9357SAndroid Build Coastguard Worker         unsigned i = 0;
534*f6dc9357SAndroid Build Coastguard Worker         do
535*f6dc9357SAndroid Build Coastguard Worker         {
536*f6dc9357SAndroid Build Coastguard Worker           UInt32 level = lens[i];
537*f6dc9357SAndroid Build Coastguard Worker           while (len != level)
538*f6dc9357SAndroid Build Coastguard Worker           {
539*f6dc9357SAndroid Build Coastguard Worker             WriteBit2(1);
540*f6dc9357SAndroid Build Coastguard Worker             if (len < level)
541*f6dc9357SAndroid Build Coastguard Worker             {
542*f6dc9357SAndroid Build Coastguard Worker               WriteBit2(0);
543*f6dc9357SAndroid Build Coastguard Worker               len++;
544*f6dc9357SAndroid Build Coastguard Worker             }
545*f6dc9357SAndroid Build Coastguard Worker             else
546*f6dc9357SAndroid Build Coastguard Worker             {
547*f6dc9357SAndroid Build Coastguard Worker               WriteBit2(1);
548*f6dc9357SAndroid Build Coastguard Worker               len--;
549*f6dc9357SAndroid Build Coastguard Worker             }
550*f6dc9357SAndroid Build Coastguard Worker           }
551*f6dc9357SAndroid Build Coastguard Worker           WriteBit2(0);
552*f6dc9357SAndroid Build Coastguard Worker         }
553*f6dc9357SAndroid Build Coastguard Worker         while (++i < alphaSize);
554*f6dc9357SAndroid Build Coastguard Worker       }
555*f6dc9357SAndroid Build Coastguard Worker       while (++t < numTables);
556*f6dc9357SAndroid Build Coastguard Worker     }
557*f6dc9357SAndroid Build Coastguard Worker 
558*f6dc9357SAndroid Build Coastguard Worker     {
559*f6dc9357SAndroid Build Coastguard Worker       UInt32 groupSize = 0;
560*f6dc9357SAndroid Build Coastguard Worker       UInt32 groupIndex = 0;
561*f6dc9357SAndroid Build Coastguard Worker       const Byte *lens = NULL;
562*f6dc9357SAndroid Build Coastguard Worker       const UInt32 *codes = NULL;
563*f6dc9357SAndroid Build Coastguard Worker       UInt32 mtfPos = 0;
564*f6dc9357SAndroid Build Coastguard Worker       do
565*f6dc9357SAndroid Build Coastguard Worker       {
566*f6dc9357SAndroid Build Coastguard Worker         UInt32 symbol = mtfs[mtfPos++];
567*f6dc9357SAndroid Build Coastguard Worker         if (symbol >= 0xFF)
568*f6dc9357SAndroid Build Coastguard Worker           symbol += mtfs[mtfPos++];
569*f6dc9357SAndroid Build Coastguard Worker         if (groupSize == 0)
570*f6dc9357SAndroid Build Coastguard Worker         {
571*f6dc9357SAndroid Build Coastguard Worker           groupSize = kGroupSize;
572*f6dc9357SAndroid Build Coastguard Worker           unsigned t = m_Selectors[groupIndex++];
573*f6dc9357SAndroid Build Coastguard Worker           lens = Lens[t];
574*f6dc9357SAndroid Build Coastguard Worker           codes = Codes[t];
575*f6dc9357SAndroid Build Coastguard Worker         }
576*f6dc9357SAndroid Build Coastguard Worker         groupSize--;
577*f6dc9357SAndroid Build Coastguard Worker         m_OutStreamCurrent->WriteBits(codes[symbol], lens[symbol]);
578*f6dc9357SAndroid Build Coastguard Worker       }
579*f6dc9357SAndroid Build Coastguard Worker       while (mtfPos < mtfArraySize);
580*f6dc9357SAndroid Build Coastguard Worker     }
581*f6dc9357SAndroid Build Coastguard Worker 
582*f6dc9357SAndroid Build Coastguard Worker     if (!m_OptimizeNumTables)
583*f6dc9357SAndroid Build Coastguard Worker       break;
584*f6dc9357SAndroid Build Coastguard Worker     UInt32 price = m_OutStreamCurrent->GetPos() - startPos;
585*f6dc9357SAndroid Build Coastguard Worker     if (price <= bestPrice)
586*f6dc9357SAndroid Build Coastguard Worker     {
587*f6dc9357SAndroid Build Coastguard Worker       if (nt == kNumTablesMax)
588*f6dc9357SAndroid Build Coastguard Worker         break;
589*f6dc9357SAndroid Build Coastguard Worker       bestPrice = price;
590*f6dc9357SAndroid Build Coastguard Worker       bestNumTables = nt;
591*f6dc9357SAndroid Build Coastguard Worker     }
592*f6dc9357SAndroid Build Coastguard Worker   }
593*f6dc9357SAndroid Build Coastguard Worker }
594*f6dc9357SAndroid Build Coastguard Worker 
595*f6dc9357SAndroid Build Coastguard Worker // blockSize > 0
EncodeBlockWithHeaders(const Byte * block,UInt32 blockSize)596*f6dc9357SAndroid Build Coastguard Worker UInt32 CThreadInfo::EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize)
597*f6dc9357SAndroid Build Coastguard Worker {
598*f6dc9357SAndroid Build Coastguard Worker   WriteByte2(kBlockSig0);
599*f6dc9357SAndroid Build Coastguard Worker   WriteByte2(kBlockSig1);
600*f6dc9357SAndroid Build Coastguard Worker   WriteByte2(kBlockSig2);
601*f6dc9357SAndroid Build Coastguard Worker   WriteByte2(kBlockSig3);
602*f6dc9357SAndroid Build Coastguard Worker   WriteByte2(kBlockSig4);
603*f6dc9357SAndroid Build Coastguard Worker   WriteByte2(kBlockSig5);
604*f6dc9357SAndroid Build Coastguard Worker 
605*f6dc9357SAndroid Build Coastguard Worker   CBZip2Crc crc;
606*f6dc9357SAndroid Build Coastguard Worker   unsigned numReps = 0;
607*f6dc9357SAndroid Build Coastguard Worker   Byte prevByte = block[0];
608*f6dc9357SAndroid Build Coastguard Worker   UInt32 i = 0;
609*f6dc9357SAndroid Build Coastguard Worker   do
610*f6dc9357SAndroid Build Coastguard Worker   {
611*f6dc9357SAndroid Build Coastguard Worker     Byte b = block[i];
612*f6dc9357SAndroid Build Coastguard Worker     if (numReps == kRleModeRepSize)
613*f6dc9357SAndroid Build Coastguard Worker     {
614*f6dc9357SAndroid Build Coastguard Worker       for (; b > 0; b--)
615*f6dc9357SAndroid Build Coastguard Worker         crc.UpdateByte(prevByte);
616*f6dc9357SAndroid Build Coastguard Worker       numReps = 0;
617*f6dc9357SAndroid Build Coastguard Worker       continue;
618*f6dc9357SAndroid Build Coastguard Worker     }
619*f6dc9357SAndroid Build Coastguard Worker     if (prevByte == b)
620*f6dc9357SAndroid Build Coastguard Worker       numReps++;
621*f6dc9357SAndroid Build Coastguard Worker     else
622*f6dc9357SAndroid Build Coastguard Worker     {
623*f6dc9357SAndroid Build Coastguard Worker       numReps = 1;
624*f6dc9357SAndroid Build Coastguard Worker       prevByte = b;
625*f6dc9357SAndroid Build Coastguard Worker     }
626*f6dc9357SAndroid Build Coastguard Worker     crc.UpdateByte(b);
627*f6dc9357SAndroid Build Coastguard Worker   }
628*f6dc9357SAndroid Build Coastguard Worker   while (++i < blockSize);
629*f6dc9357SAndroid Build Coastguard Worker   UInt32 crcRes = crc.GetDigest();
630*f6dc9357SAndroid Build Coastguard Worker   WriteCrc2(crcRes);
631*f6dc9357SAndroid Build Coastguard Worker   EncodeBlock(block, blockSize);
632*f6dc9357SAndroid Build Coastguard Worker   return crcRes;
633*f6dc9357SAndroid Build Coastguard Worker }
634*f6dc9357SAndroid Build Coastguard Worker 
EncodeBlock2(const Byte * block,UInt32 blockSize,UInt32 numPasses)635*f6dc9357SAndroid Build Coastguard Worker void CThreadInfo::EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses)
636*f6dc9357SAndroid Build Coastguard Worker {
637*f6dc9357SAndroid Build Coastguard Worker   UInt32 numCrcs = m_NumCrcs;
638*f6dc9357SAndroid Build Coastguard Worker   bool needCompare = false;
639*f6dc9357SAndroid Build Coastguard Worker 
640*f6dc9357SAndroid Build Coastguard Worker   UInt32 startBytePos = m_OutStreamCurrent->GetBytePos();
641*f6dc9357SAndroid Build Coastguard Worker   UInt32 startPos = m_OutStreamCurrent->GetPos();
642*f6dc9357SAndroid Build Coastguard Worker   Byte startCurByte = m_OutStreamCurrent->GetCurByte();
643*f6dc9357SAndroid Build Coastguard Worker   Byte endCurByte = 0;
644*f6dc9357SAndroid Build Coastguard Worker   UInt32 endPos = 0;
645*f6dc9357SAndroid Build Coastguard Worker   if (numPasses > 1 && blockSize >= (1 << 10))
646*f6dc9357SAndroid Build Coastguard Worker   {
647*f6dc9357SAndroid Build Coastguard Worker     UInt32 blockSize0 = blockSize / 2; // ????
648*f6dc9357SAndroid Build Coastguard Worker 
649*f6dc9357SAndroid Build Coastguard Worker     for (; (block[blockSize0] == block[(size_t)blockSize0 - 1]
650*f6dc9357SAndroid Build Coastguard Worker             || block[(size_t)blockSize0 - 1] == block[(size_t)blockSize0 - 2])
651*f6dc9357SAndroid Build Coastguard Worker           && blockSize0 < blockSize;
652*f6dc9357SAndroid Build Coastguard Worker         blockSize0++);
653*f6dc9357SAndroid Build Coastguard Worker 
654*f6dc9357SAndroid Build Coastguard Worker     if (blockSize0 < blockSize)
655*f6dc9357SAndroid Build Coastguard Worker     {
656*f6dc9357SAndroid Build Coastguard Worker       EncodeBlock2(block, blockSize0, numPasses - 1);
657*f6dc9357SAndroid Build Coastguard Worker       EncodeBlock2(block + blockSize0, blockSize - blockSize0, numPasses - 1);
658*f6dc9357SAndroid Build Coastguard Worker       endPos = m_OutStreamCurrent->GetPos();
659*f6dc9357SAndroid Build Coastguard Worker       endCurByte = m_OutStreamCurrent->GetCurByte();
660*f6dc9357SAndroid Build Coastguard Worker       if ((endPos & 7) > 0)
661*f6dc9357SAndroid Build Coastguard Worker         WriteBits2(0, 8 - (endPos & 7));
662*f6dc9357SAndroid Build Coastguard Worker       m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte);
663*f6dc9357SAndroid Build Coastguard Worker       needCompare = true;
664*f6dc9357SAndroid Build Coastguard Worker     }
665*f6dc9357SAndroid Build Coastguard Worker   }
666*f6dc9357SAndroid Build Coastguard Worker 
667*f6dc9357SAndroid Build Coastguard Worker   UInt32 startBytePos2 = m_OutStreamCurrent->GetBytePos();
668*f6dc9357SAndroid Build Coastguard Worker   UInt32 startPos2 = m_OutStreamCurrent->GetPos();
669*f6dc9357SAndroid Build Coastguard Worker   UInt32 crcVal = EncodeBlockWithHeaders(block, blockSize);
670*f6dc9357SAndroid Build Coastguard Worker   UInt32 endPos2 = m_OutStreamCurrent->GetPos();
671*f6dc9357SAndroid Build Coastguard Worker 
672*f6dc9357SAndroid Build Coastguard Worker   if (needCompare)
673*f6dc9357SAndroid Build Coastguard Worker   {
674*f6dc9357SAndroid Build Coastguard Worker     UInt32 size2 = endPos2 - startPos2;
675*f6dc9357SAndroid Build Coastguard Worker     if (size2 < endPos - startPos)
676*f6dc9357SAndroid Build Coastguard Worker     {
677*f6dc9357SAndroid Build Coastguard Worker       UInt32 numBytes = m_OutStreamCurrent->GetBytePos() - startBytePos2;
678*f6dc9357SAndroid Build Coastguard Worker       Byte *buffer = m_OutStreamCurrent->GetStream();
679*f6dc9357SAndroid Build Coastguard Worker       for (UInt32 i = 0; i < numBytes; i++)
680*f6dc9357SAndroid Build Coastguard Worker         buffer[startBytePos + i] = buffer[startBytePos2 + i];
681*f6dc9357SAndroid Build Coastguard Worker       m_OutStreamCurrent->SetPos(startPos + endPos2 - startPos2);
682*f6dc9357SAndroid Build Coastguard Worker       m_NumCrcs = numCrcs;
683*f6dc9357SAndroid Build Coastguard Worker       m_CRCs[m_NumCrcs++] = crcVal;
684*f6dc9357SAndroid Build Coastguard Worker     }
685*f6dc9357SAndroid Build Coastguard Worker     else
686*f6dc9357SAndroid Build Coastguard Worker     {
687*f6dc9357SAndroid Build Coastguard Worker       m_OutStreamCurrent->SetPos(endPos);
688*f6dc9357SAndroid Build Coastguard Worker       m_OutStreamCurrent->SetCurState((endPos & 7), endCurByte);
689*f6dc9357SAndroid Build Coastguard Worker     }
690*f6dc9357SAndroid Build Coastguard Worker   }
691*f6dc9357SAndroid Build Coastguard Worker   else
692*f6dc9357SAndroid Build Coastguard Worker   {
693*f6dc9357SAndroid Build Coastguard Worker     m_NumCrcs = numCrcs;
694*f6dc9357SAndroid Build Coastguard Worker     m_CRCs[m_NumCrcs++] = crcVal;
695*f6dc9357SAndroid Build Coastguard Worker   }
696*f6dc9357SAndroid Build Coastguard Worker }
697*f6dc9357SAndroid Build Coastguard Worker 
EncodeBlock3(UInt32 blockSize)698*f6dc9357SAndroid Build Coastguard Worker HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize)
699*f6dc9357SAndroid Build Coastguard Worker {
700*f6dc9357SAndroid Build Coastguard Worker   CMsbfEncoderTemp outStreamTemp;
701*f6dc9357SAndroid Build Coastguard Worker   outStreamTemp.SetStream(m_TempArray);
702*f6dc9357SAndroid Build Coastguard Worker   outStreamTemp.Init();
703*f6dc9357SAndroid Build Coastguard Worker   m_OutStreamCurrent = &outStreamTemp;
704*f6dc9357SAndroid Build Coastguard Worker 
705*f6dc9357SAndroid Build Coastguard Worker   m_NumCrcs = 0;
706*f6dc9357SAndroid Build Coastguard Worker 
707*f6dc9357SAndroid Build Coastguard Worker   EncodeBlock2(m_Block, blockSize, Encoder->_props.NumPasses);
708*f6dc9357SAndroid Build Coastguard Worker 
709*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
710*f6dc9357SAndroid Build Coastguard Worker   if (Encoder->MtMode)
711*f6dc9357SAndroid Build Coastguard Worker     Encoder->ThreadsInfo[m_BlockIndex].CanWriteEvent.Lock();
712*f6dc9357SAndroid Build Coastguard Worker   #endif
713*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < m_NumCrcs; i++)
714*f6dc9357SAndroid Build Coastguard Worker     Encoder->CombinedCrc.Update(m_CRCs[i]);
715*f6dc9357SAndroid Build Coastguard Worker   Encoder->WriteBytes(m_TempArray, outStreamTemp.GetPos(), outStreamTemp.GetCurByte());
716*f6dc9357SAndroid Build Coastguard Worker   HRESULT res = S_OK;
717*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
718*f6dc9357SAndroid Build Coastguard Worker   if (Encoder->MtMode)
719*f6dc9357SAndroid Build Coastguard Worker   {
720*f6dc9357SAndroid Build Coastguard Worker     UInt32 blockIndex = m_BlockIndex + 1;
721*f6dc9357SAndroid Build Coastguard Worker     if (blockIndex == Encoder->NumThreads)
722*f6dc9357SAndroid Build Coastguard Worker       blockIndex = 0;
723*f6dc9357SAndroid Build Coastguard Worker 
724*f6dc9357SAndroid Build Coastguard Worker     if (Encoder->Progress)
725*f6dc9357SAndroid Build Coastguard Worker     {
726*f6dc9357SAndroid Build Coastguard Worker       const UInt64 packSize = Encoder->m_OutStream.GetProcessedSize();
727*f6dc9357SAndroid Build Coastguard Worker       res = Encoder->Progress->SetRatioInfo(&m_UnpackSize, &packSize);
728*f6dc9357SAndroid Build Coastguard Worker     }
729*f6dc9357SAndroid Build Coastguard Worker 
730*f6dc9357SAndroid Build Coastguard Worker     Encoder->ThreadsInfo[blockIndex].CanWriteEvent.Set();
731*f6dc9357SAndroid Build Coastguard Worker   }
732*f6dc9357SAndroid Build Coastguard Worker   #endif
733*f6dc9357SAndroid Build Coastguard Worker   return res;
734*f6dc9357SAndroid Build Coastguard Worker }
735*f6dc9357SAndroid Build Coastguard Worker 
WriteBytes(const Byte * data,UInt32 sizeInBits,Byte lastByte)736*f6dc9357SAndroid Build Coastguard Worker void CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte)
737*f6dc9357SAndroid Build Coastguard Worker {
738*f6dc9357SAndroid Build Coastguard Worker   UInt32 bytesSize = (sizeInBits >> 3);
739*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < bytesSize; i++)
740*f6dc9357SAndroid Build Coastguard Worker     m_OutStream.WriteBits(data[i], 8);
741*f6dc9357SAndroid Build Coastguard Worker   WriteBits(lastByte, (sizeInBits & 7));
742*f6dc9357SAndroid Build Coastguard Worker }
743*f6dc9357SAndroid Build Coastguard Worker 
744*f6dc9357SAndroid Build Coastguard Worker 
CodeReal(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 *,ICompressProgressInfo * progress)745*f6dc9357SAndroid Build Coastguard Worker HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
746*f6dc9357SAndroid Build Coastguard Worker     const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
747*f6dc9357SAndroid Build Coastguard Worker {
748*f6dc9357SAndroid Build Coastguard Worker   NumBlocks = 0;
749*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
750*f6dc9357SAndroid Build Coastguard Worker   Progress = progress;
751*f6dc9357SAndroid Build Coastguard Worker   RINOK(Create())
752*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 t = 0; t < NumThreads; t++)
753*f6dc9357SAndroid Build Coastguard Worker   #endif
754*f6dc9357SAndroid Build Coastguard Worker   {
755*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
756*f6dc9357SAndroid Build Coastguard Worker     CThreadInfo &ti = ThreadsInfo[t];
757*f6dc9357SAndroid Build Coastguard Worker     if (MtMode)
758*f6dc9357SAndroid Build Coastguard Worker     {
759*f6dc9357SAndroid Build Coastguard Worker       WRes             wres = ti.StreamWasFinishedEvent.Reset();
760*f6dc9357SAndroid Build Coastguard Worker       if (wres == 0) { wres = ti.WaitingWasStartedEvent.Reset();
761*f6dc9357SAndroid Build Coastguard Worker       if (wres == 0) { wres = ti.CanWriteEvent.Reset(); }}
762*f6dc9357SAndroid Build Coastguard Worker       if (wres != 0)
763*f6dc9357SAndroid Build Coastguard Worker         return HRESULT_FROM_WIN32(wres);
764*f6dc9357SAndroid Build Coastguard Worker     }
765*f6dc9357SAndroid Build Coastguard Worker     #else
766*f6dc9357SAndroid Build Coastguard Worker     CThreadInfo &ti = ThreadsInfo;
767*f6dc9357SAndroid Build Coastguard Worker     ti.Encoder = this;
768*f6dc9357SAndroid Build Coastguard Worker     #endif
769*f6dc9357SAndroid Build Coastguard Worker 
770*f6dc9357SAndroid Build Coastguard Worker     ti.m_OptimizeNumTables = _props.DoOptimizeNumTables();
771*f6dc9357SAndroid Build Coastguard Worker 
772*f6dc9357SAndroid Build Coastguard Worker     if (!ti.Alloc())
773*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
774*f6dc9357SAndroid Build Coastguard Worker   }
775*f6dc9357SAndroid Build Coastguard Worker 
776*f6dc9357SAndroid Build Coastguard Worker 
777*f6dc9357SAndroid Build Coastguard Worker   if (!m_InStream.Create(kBufferSize))
778*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
779*f6dc9357SAndroid Build Coastguard Worker   if (!m_OutStream.Create(kBufferSize))
780*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
781*f6dc9357SAndroid Build Coastguard Worker 
782*f6dc9357SAndroid Build Coastguard Worker 
783*f6dc9357SAndroid Build Coastguard Worker   m_InStream.SetStream(inStream);
784*f6dc9357SAndroid Build Coastguard Worker   m_InStream.Init();
785*f6dc9357SAndroid Build Coastguard Worker 
786*f6dc9357SAndroid Build Coastguard Worker   m_OutStream.SetStream(outStream);
787*f6dc9357SAndroid Build Coastguard Worker   m_OutStream.Init();
788*f6dc9357SAndroid Build Coastguard Worker 
789*f6dc9357SAndroid Build Coastguard Worker   CombinedCrc.Init();
790*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
791*f6dc9357SAndroid Build Coastguard Worker   NextBlockIndex = 0;
792*f6dc9357SAndroid Build Coastguard Worker   StreamWasFinished = false;
793*f6dc9357SAndroid Build Coastguard Worker   CloseThreads = false;
794*f6dc9357SAndroid Build Coastguard Worker   CanStartWaitingEvent.Reset();
795*f6dc9357SAndroid Build Coastguard Worker   #endif
796*f6dc9357SAndroid Build Coastguard Worker 
797*f6dc9357SAndroid Build Coastguard Worker   WriteByte(kArSig0);
798*f6dc9357SAndroid Build Coastguard Worker   WriteByte(kArSig1);
799*f6dc9357SAndroid Build Coastguard Worker   WriteByte(kArSig2);
800*f6dc9357SAndroid Build Coastguard Worker   WriteByte((Byte)(kArSig3 + _props.BlockSizeMult));
801*f6dc9357SAndroid Build Coastguard Worker 
802*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
803*f6dc9357SAndroid Build Coastguard Worker 
804*f6dc9357SAndroid Build Coastguard Worker   if (MtMode)
805*f6dc9357SAndroid Build Coastguard Worker   {
806*f6dc9357SAndroid Build Coastguard Worker     ThreadsInfo[0].CanWriteEvent.Set();
807*f6dc9357SAndroid Build Coastguard Worker     Result = S_OK;
808*f6dc9357SAndroid Build Coastguard Worker     CanProcessEvent.Set();
809*f6dc9357SAndroid Build Coastguard Worker     UInt32 t;
810*f6dc9357SAndroid Build Coastguard Worker     for (t = 0; t < NumThreads; t++)
811*f6dc9357SAndroid Build Coastguard Worker       ThreadsInfo[t].StreamWasFinishedEvent.Lock();
812*f6dc9357SAndroid Build Coastguard Worker     CanProcessEvent.Reset();
813*f6dc9357SAndroid Build Coastguard Worker     CanStartWaitingEvent.Set();
814*f6dc9357SAndroid Build Coastguard Worker     for (t = 0; t < NumThreads; t++)
815*f6dc9357SAndroid Build Coastguard Worker       ThreadsInfo[t].WaitingWasStartedEvent.Lock();
816*f6dc9357SAndroid Build Coastguard Worker     CanStartWaitingEvent.Reset();
817*f6dc9357SAndroid Build Coastguard Worker     RINOK(Result)
818*f6dc9357SAndroid Build Coastguard Worker   }
819*f6dc9357SAndroid Build Coastguard Worker   else
820*f6dc9357SAndroid Build Coastguard Worker   #endif
821*f6dc9357SAndroid Build Coastguard Worker   {
822*f6dc9357SAndroid Build Coastguard Worker     for (;;)
823*f6dc9357SAndroid Build Coastguard Worker     {
824*f6dc9357SAndroid Build Coastguard Worker       CThreadInfo &ti =
825*f6dc9357SAndroid Build Coastguard Worker       #ifndef Z7_ST
826*f6dc9357SAndroid Build Coastguard Worker       ThreadsInfo[0];
827*f6dc9357SAndroid Build Coastguard Worker       #else
828*f6dc9357SAndroid Build Coastguard Worker       ThreadsInfo;
829*f6dc9357SAndroid Build Coastguard Worker       #endif
830*f6dc9357SAndroid Build Coastguard Worker       UInt32 blockSize = ReadRleBlock(ti.m_Block);
831*f6dc9357SAndroid Build Coastguard Worker       if (blockSize == 0)
832*f6dc9357SAndroid Build Coastguard Worker         break;
833*f6dc9357SAndroid Build Coastguard Worker       RINOK(ti.EncodeBlock3(blockSize))
834*f6dc9357SAndroid Build Coastguard Worker       if (progress)
835*f6dc9357SAndroid Build Coastguard Worker       {
836*f6dc9357SAndroid Build Coastguard Worker         const UInt64 unpackSize = m_InStream.GetProcessedSize();
837*f6dc9357SAndroid Build Coastguard Worker         const UInt64 packSize = m_OutStream.GetProcessedSize();
838*f6dc9357SAndroid Build Coastguard Worker         RINOK(progress->SetRatioInfo(&unpackSize, &packSize))
839*f6dc9357SAndroid Build Coastguard Worker       }
840*f6dc9357SAndroid Build Coastguard Worker     }
841*f6dc9357SAndroid Build Coastguard Worker   }
842*f6dc9357SAndroid Build Coastguard Worker   WriteByte(kFinSig0);
843*f6dc9357SAndroid Build Coastguard Worker   WriteByte(kFinSig1);
844*f6dc9357SAndroid Build Coastguard Worker   WriteByte(kFinSig2);
845*f6dc9357SAndroid Build Coastguard Worker   WriteByte(kFinSig3);
846*f6dc9357SAndroid Build Coastguard Worker   WriteByte(kFinSig4);
847*f6dc9357SAndroid Build Coastguard Worker   WriteByte(kFinSig5);
848*f6dc9357SAndroid Build Coastguard Worker 
849*f6dc9357SAndroid Build Coastguard Worker   WriteCrc(CombinedCrc.GetDigest());
850*f6dc9357SAndroid Build Coastguard Worker   RINOK(Flush())
851*f6dc9357SAndroid Build Coastguard Worker   if (!m_InStream.WasFinished())
852*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
853*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
854*f6dc9357SAndroid Build Coastguard Worker }
855*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CEncoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))856*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
857*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
858*f6dc9357SAndroid Build Coastguard Worker {
859*f6dc9357SAndroid Build Coastguard Worker   try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
860*f6dc9357SAndroid Build Coastguard Worker   catch(const CInBufferException &e) { return e.ErrorCode; }
861*f6dc9357SAndroid Build Coastguard Worker   catch(const COutBufferException &e) { return e.ErrorCode; }
862*f6dc9357SAndroid Build Coastguard Worker   catch(...) { return S_FALSE; }
863*f6dc9357SAndroid Build Coastguard Worker }
864*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CEncoder::SetCoderProperties (const PROPID * propIDs,const PROPVARIANT * coderProps,UInt32 numProps))865*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))
866*f6dc9357SAndroid Build Coastguard Worker {
867*f6dc9357SAndroid Build Coastguard Worker   int level = -1;
868*f6dc9357SAndroid Build Coastguard Worker   CEncProps props;
869*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < numProps; i++)
870*f6dc9357SAndroid Build Coastguard Worker   {
871*f6dc9357SAndroid Build Coastguard Worker     const PROPVARIANT &prop = coderProps[i];
872*f6dc9357SAndroid Build Coastguard Worker     PROPID propID = propIDs[i];
873*f6dc9357SAndroid Build Coastguard Worker 
874*f6dc9357SAndroid Build Coastguard Worker     if (propID == NCoderPropID::kAffinity)
875*f6dc9357SAndroid Build Coastguard Worker     {
876*f6dc9357SAndroid Build Coastguard Worker       if (prop.vt == VT_UI8)
877*f6dc9357SAndroid Build Coastguard Worker         props.Affinity = prop.uhVal.QuadPart;
878*f6dc9357SAndroid Build Coastguard Worker       else
879*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
880*f6dc9357SAndroid Build Coastguard Worker       continue;
881*f6dc9357SAndroid Build Coastguard Worker     }
882*f6dc9357SAndroid Build Coastguard Worker 
883*f6dc9357SAndroid Build Coastguard Worker     if (propID >= NCoderPropID::kReduceSize)
884*f6dc9357SAndroid Build Coastguard Worker       continue;
885*f6dc9357SAndroid Build Coastguard Worker     if (prop.vt != VT_UI4)
886*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
887*f6dc9357SAndroid Build Coastguard Worker     UInt32 v = (UInt32)prop.ulVal;
888*f6dc9357SAndroid Build Coastguard Worker     switch (propID)
889*f6dc9357SAndroid Build Coastguard Worker     {
890*f6dc9357SAndroid Build Coastguard Worker       case NCoderPropID::kNumPasses: props.NumPasses = v; break;
891*f6dc9357SAndroid Build Coastguard Worker       case NCoderPropID::kDictionarySize: props.BlockSizeMult = v / kBlockSizeStep; break;
892*f6dc9357SAndroid Build Coastguard Worker       case NCoderPropID::kLevel: level = (int)v; break;
893*f6dc9357SAndroid Build Coastguard Worker       case NCoderPropID::kNumThreads:
894*f6dc9357SAndroid Build Coastguard Worker       {
895*f6dc9357SAndroid Build Coastguard Worker         #ifndef Z7_ST
896*f6dc9357SAndroid Build Coastguard Worker         SetNumberOfThreads(v);
897*f6dc9357SAndroid Build Coastguard Worker         #endif
898*f6dc9357SAndroid Build Coastguard Worker         break;
899*f6dc9357SAndroid Build Coastguard Worker       }
900*f6dc9357SAndroid Build Coastguard Worker       default: return E_INVALIDARG;
901*f6dc9357SAndroid Build Coastguard Worker     }
902*f6dc9357SAndroid Build Coastguard Worker   }
903*f6dc9357SAndroid Build Coastguard Worker   props.Normalize(level);
904*f6dc9357SAndroid Build Coastguard Worker   _props = props;
905*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
906*f6dc9357SAndroid Build Coastguard Worker }
907*f6dc9357SAndroid Build Coastguard Worker 
908*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
Z7_COM7F_IMF(CEncoder::SetNumberOfThreads (UInt32 numThreads))909*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CEncoder::SetNumberOfThreads(UInt32 numThreads))
910*f6dc9357SAndroid Build Coastguard Worker {
911*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kNumThreadsMax = 64;
912*f6dc9357SAndroid Build Coastguard Worker   if (numThreads < 1) numThreads = 1;
913*f6dc9357SAndroid Build Coastguard Worker   if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;
914*f6dc9357SAndroid Build Coastguard Worker   NumThreads = numThreads;
915*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
916*f6dc9357SAndroid Build Coastguard Worker }
917*f6dc9357SAndroid Build Coastguard Worker #endif
918*f6dc9357SAndroid Build Coastguard Worker 
919*f6dc9357SAndroid Build Coastguard Worker }}
920