ffmpeg / libavcodec / rangecoder.h @ 5509bffa
History | View | Annotate | Download (3.42 KB)
1 |
/*
|
---|---|
2 |
* Range coder
|
3 |
* Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
|
4 |
*
|
5 |
* This library is free software; you can redistribute it and/or
|
6 |
* modify it under the terms of the GNU Lesser General Public
|
7 |
* License as published by the Free Software Foundation; either
|
8 |
* version 2 of the License, or (at your option) any later version.
|
9 |
*
|
10 |
* This library is distributed in the hope that it will be useful,
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13 |
* Lesser General Public License for more details.
|
14 |
*
|
15 |
* You should have received a copy of the GNU Lesser General Public
|
16 |
* License along with this library; if not, write to the Free Software
|
17 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18 |
*
|
19 |
*/
|
20 |
|
21 |
/**
|
22 |
* @file rangecoder.h
|
23 |
* Range coder.
|
24 |
*/
|
25 |
|
26 |
typedef struct RangeCoder{ |
27 |
int low;
|
28 |
int range;
|
29 |
int outstanding_count;
|
30 |
int outstanding_byte;
|
31 |
uint8_t zero_state[256];
|
32 |
uint8_t one_state[256];
|
33 |
uint8_t *bytestream_start; |
34 |
uint8_t *bytestream; |
35 |
uint8_t *bytestream_end; |
36 |
}RangeCoder; |
37 |
|
38 |
void ff_init_range_encoder(RangeCoder *c, uint8_t *buf, int buf_size); |
39 |
void ff_init_range_decoder(RangeCoder *c, const uint8_t *buf, int buf_size); |
40 |
int ff_rac_terminate(RangeCoder *c);
|
41 |
void ff_build_rac_states(RangeCoder *c, int factor, int max_p); |
42 |
|
43 |
static inline void renorm_encoder(RangeCoder *c){ |
44 |
//FIXME optimize
|
45 |
while(c->range < 0x100){ |
46 |
if(c->outstanding_byte < 0){ |
47 |
c->outstanding_byte= c->low>>8;
|
48 |
}else if(c->low <= 0xFF00){ |
49 |
*c->bytestream++ = c->outstanding_byte; |
50 |
for(;c->outstanding_count; c->outstanding_count--)
|
51 |
*c->bytestream++ = 0xFF;
|
52 |
c->outstanding_byte= c->low>>8;
|
53 |
}else if(c->low >= 0x10000){ |
54 |
*c->bytestream++ = c->outstanding_byte + 1;
|
55 |
for(;c->outstanding_count; c->outstanding_count--)
|
56 |
*c->bytestream++ = 0x00;
|
57 |
c->outstanding_byte= (c->low>>8) & 0xFF; |
58 |
}else{
|
59 |
c->outstanding_count++; |
60 |
} |
61 |
|
62 |
c->low = (c->low & 0xFF)<<8; |
63 |
c->range <<= 8;
|
64 |
} |
65 |
} |
66 |
|
67 |
static inline void put_rac(RangeCoder *c, uint8_t * const state, int bit){ |
68 |
int range1= (c->range * (*state)) >> 8; |
69 |
|
70 |
assert(*state); |
71 |
assert(range1 < c->range); |
72 |
assert(range1 > 0);
|
73 |
if(!bit){
|
74 |
c->range -= range1; |
75 |
*state= c->zero_state[*state]; |
76 |
}else{
|
77 |
c->low += c->range - range1; |
78 |
c->range = range1; |
79 |
*state= c->one_state[*state]; |
80 |
} |
81 |
|
82 |
renorm_encoder(c); |
83 |
} |
84 |
|
85 |
static inline void refill(RangeCoder *c){ |
86 |
if(c->range < 0x100){ |
87 |
c->range <<= 8;
|
88 |
c->low <<= 8;
|
89 |
if(c->bytestream < c->bytestream_end)
|
90 |
c->low+= c->bytestream[0];
|
91 |
c->bytestream++; |
92 |
} |
93 |
} |
94 |
|
95 |
static inline int get_rac(RangeCoder *c, uint8_t * const state){ |
96 |
int range1= (c->range * (*state)) >> 8; |
97 |
int attribute_unused one_mask;
|
98 |
|
99 |
c->range -= range1; |
100 |
#if 1 |
101 |
if(c->low < c->range){
|
102 |
*state= c->zero_state[*state]; |
103 |
refill(c); |
104 |
return 0; |
105 |
}else{
|
106 |
c->low -= c->range; |
107 |
*state= c->one_state[*state]; |
108 |
c->range = range1; |
109 |
refill(c); |
110 |
return 1; |
111 |
} |
112 |
#else
|
113 |
one_mask= (c->range - c->low-1)>>31; |
114 |
|
115 |
c->low -= c->range & one_mask; |
116 |
c->range += (range1 - c->range) & one_mask; |
117 |
|
118 |
*state= c->zero_state[(*state) + (256&one_mask)];
|
119 |
|
120 |
refill(c); |
121 |
|
122 |
return one_mask&1; |
123 |
#endif
|
124 |
} |
125 |
|