summaryrefslogtreecommitdiff
path: root/ext/tarkin/golomb.h
blob: 95e63c304f6cbf0dad7777e992e227f4f910859d (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
131
132
#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