summaryrefslogtreecommitdiff
path: root/ext/tarkin/golomb.h
blob: 47c23b441cbb24dcb6239251f36619b1582f6cf6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef __GOLOMB_H
#define __GOLOMB_H


#include "bitcoder.h"


static inline unsigned int
required_bits (unsigned int x)
{
  int bits = 31;

  while ((x & (1 << bits)) == 0 && bits)
    bits--;

  return bits;
}


static inline void
write_number_binary (BitCoderState * b, unsigned int x, int bits, int u)
{
/*printf ("wrote %i with %i bits (%i+%i)\n", x, u+bits, u, bits); */
  while (bits) {
    bits--;
    bitcoder_write_bit (b, (x >> bits) & 1);
  }
}


static inline unsigned int
read_number_binary (BitCoderState * b, int bits)
{
  unsigned int x = 0;

  while (bits) {
    bits--;
    x |= bitcoder_read_bit (b) << bits;
  }

  return x;
}


static inline void
golomb_write_number (BitCoderState * b, unsigned int x, int bits)
{
  unsigned int q, r;
  int i = 0;

  assert (x > 0);

  while ((q = (x - 1) >> bits) > 0) {
    bitcoder_write_bit (b, 1);	/* fast temporary adaption, write  */
    bits++;			/* unary representation of q       */
    i++;
  };

  bitcoder_write_bit (b, 0);

  r = x - 1 - (q << bits);

  write_number_binary (b, r, bits, i + 1);
}


static inline unsigned int
golomb_read_number (BitCoderState * b, int bits)
{
  unsigned int q = 0, r, x;

  while (bitcoder_read_bit (b) != 0) {
    bits++;
  }

  r = read_number_binary (b, bits);
  x = (q << bits) + r + 1;

  return x;
}


typedef struct
{
  uint8_t count;
  uint8_t bits;			/* a 5.3 fixed point integer  */
} GolombAdaptiveCoderState;

#define GOLOMB_ADAPTIVE_CODER_STATE_INITIALIZER { 8<<3, 0 }


static const int golomb_w_tab[] = { 256, 128, 64 };




static inline void
golombcoder_encode_number (GolombAdaptiveCoderState * g,
    BitCoderState * b, unsigned int x)
{
  golomb_write_number (b, x, g->bits >> 3);

  g->bits = ((256 - golomb_w_tab[g->count]) * (int) g->bits +
      golomb_w_tab[g->count] * (required_bits (x) << 3)) / 256;
  g->count++;

  if (g->count > 2)
    g->count = 2;
}


static inline unsigned int
golombcoder_decode_number (GolombAdaptiveCoderState * g, BitCoderState * b)
{
  unsigned int x;

  x = golomb_read_number (b, g->bits >> 3);

  g->bits = ((256 - golomb_w_tab[g->count]) * g->bits +
      golomb_w_tab[g->count] * (required_bits (x) << 3)) / 256;
  g->count++;

  if (g->count > 2)
    g->count = 2;

  return x;
}


#endif