3 #ifndef __COMPRESS_QUANTUM_DECODER_H
\r
4 #define __COMPRESS_QUANTUM_DECODER_H
\r
6 #include "../../Common/MyCom.h"
\r
8 #include "../ICoder.h"
\r
10 #include "../Common/InBuffer.h"
\r
12 #include "LzOutWindow.h"
\r
14 namespace NCompress {
\r
15 namespace NQuantum {
\r
17 class CStreamBitDecoder
\r
22 bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
\r
23 void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
\r
24 void ReleaseStream() { Stream.ReleaseStream(); }
\r
26 void Finish() { Value = 0x10000; }
\r
34 UInt64 GetProcessedSize() const { return Stream.GetProcessedSize(); }
\r
35 bool WasFinished() const { return Stream.WasFinished(); }
\r
39 if (Value >= 0x10000)
\r
40 Value = 0x100 | Stream.ReadByte();
\r
41 UInt32 res = (Value >> 7) & 1;
\r
46 UInt32 ReadBits(int numBits) // numBits > 0
\r
50 res = (res << 1) | ReadBit();
\r
51 while (--numBits != 0);
\r
56 const unsigned kNumLitSelectorBits = 2;
\r
57 const unsigned kNumLitSelectors = (1 << kNumLitSelectorBits);
\r
58 const unsigned kNumLitSymbols = 1 << (8 - kNumLitSelectorBits);
\r
59 const unsigned kNumMatchSelectors = 3;
\r
60 const unsigned kNumSelectors = kNumLitSelectors + kNumMatchSelectors;
\r
61 const unsigned kNumSymbolsMax = kNumLitSymbols; // 64
\r
63 namespace NRangeCoder {
\r
71 CStreamBitDecoder Stream;
\r
72 bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
\r
73 void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
\r
74 void ReleaseStream() { Stream.ReleaseStream(); }
\r
81 Code = Stream.ReadBits(16);
\r
86 // we need these extra two Bit_reads
\r
92 UInt64 GetProcessedSize() const { return Stream.GetProcessedSize(); }
\r
94 UInt32 GetThreshold(UInt32 total) const
\r
96 return ((Code + 1) * total - 1) / Range; // & 0xFFFF is not required;
\r
99 void Decode(UInt32 start, UInt32 end, UInt32 total)
\r
101 UInt32 high = Low + end * Range / total - 1;
\r
102 UInt32 offset = start * Range / total;
\r
107 if ((Low & 0x8000) != (high & 0x8000))
\r
109 if ((Low & 0x4000) == 0 || (high & 0x4000) != 0)
\r
114 Low = (Low << 1) & 0xFFFF;
\r
115 high = ((high << 1) | 1) & 0xFFFF;
\r
116 Code = ((Code << 1) | Stream.ReadBit());
\r
118 Range = high - Low + 1;
\r
122 const UInt16 kUpdateStep = 8;
\r
123 const UInt16 kFreqSumMax = 3800;
\r
124 const UInt16 kReorderCountStart = 4;
\r
125 const UInt16 kReorderCount = 50;
\r
127 class CModelDecoder
\r
130 unsigned ReorderCount;
\r
131 UInt16 Freqs[kNumSymbolsMax + 1];
\r
132 Byte Values[kNumSymbolsMax];
\r
134 void Init(unsigned numItems)
\r
136 NumItems = numItems;
\r
137 ReorderCount = kReorderCountStart;
\r
138 for (unsigned i = 0; i < numItems; i++)
\r
140 Freqs[i] = (UInt16)(numItems - i);
\r
141 Values[i] = (Byte)i;
\r
143 Freqs[numItems] = 0;
\r
146 unsigned Decode(CDecoder *rangeDecoder)
\r
148 UInt32 threshold = rangeDecoder->GetThreshold(Freqs[0]);
\r
150 for (i = 1; Freqs[i] > threshold; i++);
\r
151 rangeDecoder->Decode(Freqs[i], Freqs[i - 1], Freqs[0]);
\r
152 unsigned res = Values[--i];
\r
154 Freqs[i] += kUpdateStep;
\r
157 if (Freqs[0] > kFreqSumMax)
\r
159 if (--ReorderCount == 0)
\r
161 ReorderCount = kReorderCount;
\r
162 for (i = 0; i < NumItems; i++)
\r
163 Freqs[i] = (UInt16)(((Freqs[i] - Freqs[i + 1]) + 1) >> 1);
\r
164 for (i = 0; i < NumItems - 1; i++)
\r
165 for (unsigned j = i + 1; j < NumItems; j++)
\r
166 if (Freqs[i] < Freqs[j])
\r
168 UInt16 tmpFreq = Freqs[i];
\r
169 Byte tmpVal = Values[i];
\r
170 Freqs[i] = Freqs[j];
\r
171 Values[i] = Values[j];
\r
172 Freqs[j] = tmpFreq;
\r
173 Values[j] = tmpVal;
\r
176 Freqs[i] = (UInt16)(Freqs[i] + Freqs[i + 1]);
\r
185 if (Freqs[i] <= Freqs[i + 1])
\r
186 Freqs[i] = (UInt16)(Freqs[i + 1] + 1);
\r
198 public ICompressCoder,
\r
199 public ICompressSetInStream,
\r
200 public ICompressSetOutStreamSize,
\r
201 public CMyUnknownImp
\r
203 CLzOutWindow _outWindowStream;
\r
204 NRangeCoder::CDecoder _rangeDecoder;
\r
207 int _remainLen; // -1 means end of stream. // -2 means need Init
\r
213 NRangeCoder::CModelDecoder m_Selector;
\r
214 NRangeCoder::CModelDecoder m_Literals[kNumLitSelectors];
\r
215 NRangeCoder::CModelDecoder m_PosSlot[kNumMatchSelectors];
\r
216 NRangeCoder::CModelDecoder m_LenSlot;
\r
218 HRESULT CodeSpec(UInt32 size);
\r
221 ICompressSetInStream,
\r
222 ICompressSetOutStreamSize)
\r
224 void ReleaseStreams()
\r
226 _outWindowStream.ReleaseStream();
\r
230 class CDecoderFlusher
\r
232 CDecoder *_decoder;
\r
235 CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}
\r
240 _decoder->ReleaseStreams();
\r
244 HRESULT Flush() { return _outWindowStream.Flush(); }
\r
246 HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
\r
247 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
\r
249 STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
\r
250 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
\r
252 STDMETHOD(SetInStream)(ISequentialInStream *inStream);
\r
253 STDMETHOD(ReleaseInStream)();
\r
254 STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
\r
256 void SetParams(int numDictBits) { _numDictBits = numDictBits; }
\r
257 void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; }
\r
258 CDecoder(): _keepHistory(false) {}
\r
259 virtual ~CDecoder() {}
\r