libUTL++
ArithmeticEncoder.h
1 #pragma once
2 
4 
5 #include <libutl/Encoder.h>
6 #include <libutl/Vector.h>
7 
9 
10 UTL_NS_BEGIN;
11 
13 // ArithContext ////////////////////////////////////////////////////////////////////////////////////
15 
28 
30 class ArithContext : public Object
31 {
33 
34 public:
42  ArithContext(uint_t numSymbols, uint_t inc, uint_t incLimit)
43  {
44  _F = nullptr;
45  set(numSymbols, inc, incLimit);
46  }
47 
49  virtual void copy(const Object& rhs);
50 
52  uint_t
53  freq(uint_t symbol) const
54  {
55  uint_t low, high;
56  interval(&low, &high, symbol);
57  return high - low;
58  }
59 
64  void interval(uint_t* low, uint_t* high, uint_t symbol) const;
65 
67  uint_t
68  numSymbols() const
69  {
70  return _numSymbols;
71  }
72 
80  void set(uint_t numSymbols, uint_t inc, uint_t incLimit);
81 
86  uint_t symbol(uint_t target);
87 
89  uint_t
90  totFreq() const
91  {
92  return _totFreq;
93  }
94 
99  void update(uint_t symbol);
100 
101 private:
102  void
103  init()
104  {
105  _F = nullptr;
106  set(0, 0, 0);
107  }
108  void
109  deInit()
110  {
111  delete[] _F;
112  }
113  void halve();
114 
115 private:
116  uint_t _numSymbols;
117  uint_t _size;
118  uint_t _mid;
119  uint_t* _F;
120  uint_t _inc;
121  uint_t _incLimit;
122  uint_t _totFreq;
123 };
124 
126 
127 #undef _L
128 #undef _R
129 
131 // ArithmeticEncoder ///////////////////////////////////////////////////////////////////////////////
133 
154 
157 {
159 
160 public:
170  Stream* stream = nullptr,
171  bool owner = true,
172  ArithContext* ctx = nullptr,
173  bool eob = false)
174  {
175  _ctx = nullptr;
176  start(mode, stream, owner, ctx, eob);
177  }
178 
179  virtual size_t decode(byte_t* block, size_t num);
180 
186  inline uint_t decode(ArithContext* ctx);
187 
188  virtual size_t encode(const byte_t* block, size_t num);
189 
195  inline void encode(uint_t symbol, ArithContext* ctx);
196 
198  void
200  {
201  delete _ctx;
202  _ctx = ctx;
203  }
204 
213  void start(uint_t mode,
214  Stream* stream,
215  bool owner = true,
216  ArithContext* ctx = nullptr,
217  bool eob = false);
218 
219 protected:
220  virtual void clear();
221  virtual void finishEncoding();
222 
223 private:
224  void
225  init()
226  {
227  _ctx = nullptr;
228  clearSelf();
229  }
230  void
231  deInit()
232  {
233  close();
234  }
235  void clearSelf();
236  inline void putBit(bool b);
237 
238 private:
239  uint_t _half, _qtr;
240  uint_t _L, _R;
241  uint_t _followBits;
242  ArithContext* _ctx;
243  uint_t _eob;
244 };
245 
247 
248 void
249 ArithmeticEncoder::putBit(bool b)
250 {
251  _stream->putBit(b);
252  while (_followBits > 0)
253  {
254  _stream->putBit(!b);
255  _followBits--;
256  }
257 }
258 
260 
261 void
262 ArithmeticEncoder::encode(uint_t symbol, ArithContext* ctx)
263 {
264  uint_t l, h, t, r, rl;
265 
266  ctx->interval(&l, &h, symbol);
267  t = ctx->totFreq();
268  r = _R / t;
269  rl = r * l;
270 
271  // adjust _L, _R
272  _L += rl;
273  if (h < t)
274  {
275  _R = r * h - rl;
276  }
277  else
278  {
279  _R -= rl;
280  }
281 
282  // write bits as necessary
283  while (_R <= _qtr)
284  {
285  if (_L + _R <= _half)
286  {
287  putBit(0);
288  }
289  else if (_L >= _half)
290  {
291  putBit(1);
292  _L -= _half;
293  }
294  else
295  {
296  _followBits++;
297  _L -= _qtr;
298  }
299  _L <<= 1;
300  _R <<= 1;
301  }
302 
303  ctx->update(symbol);
304 }
305 
307 
308 uint_t
309 ArithmeticEncoder::decode(ArithContext* ctx)
310 {
311  uint_t l, h, t, r, rl, target, symbol;
312  bool bit;
313 
314  t = ctx->totFreq();
315  r = _R / t;
316 
317  // find l, h, symbol
318  target = min(t - 1, _L / r);
319  symbol = ctx->symbol(target);
320  ctx->interval(&l, &h, symbol);
321  rl = r * l;
322 
323  // adjust _L, _R
324  _L -= rl;
325  if (h < t)
326  {
327  _R = r * h - rl;
328  }
329  else
330  {
331  _R -= rl;
332  }
333 
334  // read bits as necessary
335  while (_R <= _qtr)
336  {
337  _R <<= 1;
338  bit = _stream->getBit();
339  _L = (_L << 1) | (bit ? 1 : 0);
340  }
341 
342  ctx->update(symbol);
343  return symbol;
344 }
345 
347 
348 UTL_NS_END;
void update(uint_t symbol)
Add inc to the frequency count for the given symbol.
void deInit()
De-initialize UTL++.
uint_t totFreq() const
Return the total frequency of all symbols.
Encoder/decoder abstraction.
Definition: Encoder.h:39
uint_t symbol(uint_t target)
Return the symbol whose cumulative frequency count is the least that exceeds the given target...
void interval(uint_t *low, uint_t *high, uint_t symbol) const
Return the total frequency of all symbols before the given symbol.
#define UTL_CLASS_DECL(DC, BC)
Declaration of standard UTL++ functionality for a non-template class.
Definition: macros.h:688
unsigned char byte_t
Unsigned character.
Definition: types.h:31
Statistical context for ArithmeticEncoder.
DCC95 arithmetic coder.
void copy(T *dest, const T *src, size_t len)
Copy one array of objects to another.
Definition: util_inl.h:690
uint_t freq(uint_t symbol) const
Get the frequency count for the given symbol.
unsigned int uint_t
Unsigned integer.
Definition: types.h:59
uint_t numSymbols() const
Return the number of symbols.
Stream I/O abstraction.
Definition: Stream.h:68
ArithmeticEncoder(uint_t mode, Stream *stream=nullptr, bool owner=true, ArithContext *ctx=nullptr, bool eob=false)
Constructor.
const T & min(const T &a, const T &b, const R &... args)
Return the smallest value among two or more provided values of the same type.
Definition: util_inl.h:61
Root of UTL++ class hierarchy.
Definition: Object.h:52
void init()
Initialize UTL++.
void setContext(ArithContext *ctx)
Set the default context.
ArithContext(uint_t numSymbols, uint_t inc, uint_t incLimit)
Constructor.