/src/vlc/contrib/contrib-build/bpg/libavcodec/cabac.c
Line | Count | Source |
1 | | /* |
2 | | * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder |
3 | | * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> |
4 | | * |
5 | | * This file is part of FFmpeg. |
6 | | * |
7 | | * FFmpeg is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * FFmpeg is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with FFmpeg; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | /** |
23 | | * @file |
24 | | * Context Adaptive Binary Arithmetic Coder. |
25 | | */ |
26 | | |
27 | | #include <string.h> |
28 | | |
29 | | #include "libavutil/common.h" |
30 | | #include "libavutil/timer.h" |
31 | | #include "get_bits.h" |
32 | | #include "cabac.h" |
33 | | #include "cabac_functions.h" |
34 | | |
35 | | #include "cabac_tablegen.h" |
36 | | |
37 | | /** |
38 | | * |
39 | | * @param buf_size size of buf in bits |
40 | | */ |
41 | 0 | void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size){ |
42 | 0 | init_put_bits(&c->pb, buf, buf_size); |
43 | |
|
44 | 0 | c->low= 0; |
45 | 0 | c->range= 0x1FE; |
46 | 0 | c->outstanding_count= 0; |
47 | 0 | c->pb.bit_left++; //avoids firstBitFlag |
48 | 0 | } |
49 | | |
50 | | /** |
51 | | * |
52 | | * @param buf_size size of buf in bits |
53 | | */ |
54 | 0 | void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size){ |
55 | 0 | c->bytestream_start= |
56 | 0 | c->bytestream= buf; |
57 | 0 | c->bytestream_end= buf + buf_size; |
58 | |
|
59 | 0 | #if CABAC_BITS == 16 |
60 | 0 | c->low = (*c->bytestream++)<<18; |
61 | 0 | c->low+= (*c->bytestream++)<<10; |
62 | | #else |
63 | | c->low = (*c->bytestream++)<<10; |
64 | | #endif |
65 | 0 | c->low+= ((*c->bytestream++)<<2) + 2; |
66 | 0 | c->range= 0x1FE; |
67 | 0 | } |
68 | | |
69 | | void ff_init_cabac_states(void) |
70 | 0 | { |
71 | 0 | static int initialized = 0; |
72 | |
|
73 | 0 | if (initialized) |
74 | 0 | return; |
75 | | |
76 | 0 | cabac_tableinit(); |
77 | |
|
78 | 0 | initialized = 1; |
79 | 0 | } |
80 | | |
81 | | #ifdef TEST |
82 | | #define SIZE 10240 |
83 | | |
84 | | #include "libavutil/lfg.h" |
85 | | #include "avcodec.h" |
86 | | |
87 | | static inline void put_cabac_bit(CABACContext *c, int b){ |
88 | | put_bits(&c->pb, 1, b); |
89 | | for(;c->outstanding_count; c->outstanding_count--){ |
90 | | put_bits(&c->pb, 1, 1-b); |
91 | | } |
92 | | } |
93 | | |
94 | | static inline void renorm_cabac_encoder(CABACContext *c){ |
95 | | while(c->range < 0x100){ |
96 | | //FIXME optimize |
97 | | if(c->low<0x100){ |
98 | | put_cabac_bit(c, 0); |
99 | | }else if(c->low<0x200){ |
100 | | c->outstanding_count++; |
101 | | c->low -= 0x100; |
102 | | }else{ |
103 | | put_cabac_bit(c, 1); |
104 | | c->low -= 0x200; |
105 | | } |
106 | | |
107 | | c->range+= c->range; |
108 | | c->low += c->low; |
109 | | } |
110 | | } |
111 | | |
112 | | static void put_cabac(CABACContext *c, uint8_t * const state, int bit){ |
113 | | int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + *state]; |
114 | | |
115 | | if(bit == ((*state)&1)){ |
116 | | c->range -= RangeLPS; |
117 | | *state = ff_h264_mlps_state[128 + *state]; |
118 | | }else{ |
119 | | c->low += c->range - RangeLPS; |
120 | | c->range = RangeLPS; |
121 | | *state= ff_h264_mlps_state[127 - *state]; |
122 | | } |
123 | | |
124 | | renorm_cabac_encoder(c); |
125 | | } |
126 | | |
127 | | /** |
128 | | * @param bit 0 -> write zero bit, !=0 write one bit |
129 | | */ |
130 | | static void put_cabac_bypass(CABACContext *c, int bit){ |
131 | | c->low += c->low; |
132 | | |
133 | | if(bit){ |
134 | | c->low += c->range; |
135 | | } |
136 | | //FIXME optimize |
137 | | if(c->low<0x200){ |
138 | | put_cabac_bit(c, 0); |
139 | | }else if(c->low<0x400){ |
140 | | c->outstanding_count++; |
141 | | c->low -= 0x200; |
142 | | }else{ |
143 | | put_cabac_bit(c, 1); |
144 | | c->low -= 0x400; |
145 | | } |
146 | | } |
147 | | |
148 | | /** |
149 | | * |
150 | | * @return the number of bytes written |
151 | | */ |
152 | | static int put_cabac_terminate(CABACContext *c, int bit){ |
153 | | c->range -= 2; |
154 | | |
155 | | if(!bit){ |
156 | | renorm_cabac_encoder(c); |
157 | | }else{ |
158 | | c->low += c->range; |
159 | | c->range= 2; |
160 | | |
161 | | renorm_cabac_encoder(c); |
162 | | |
163 | | av_assert0(c->low <= 0x1FF); |
164 | | put_cabac_bit(c, c->low>>9); |
165 | | put_bits(&c->pb, 2, ((c->low>>7)&3)|1); |
166 | | |
167 | | flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong |
168 | | } |
169 | | |
170 | | return (put_bits_count(&c->pb)+7)>>3; |
171 | | } |
172 | | |
173 | | int main(void){ |
174 | | CABACContext c; |
175 | | uint8_t b[9*SIZE]; |
176 | | uint8_t r[9*SIZE]; |
177 | | int i; |
178 | | uint8_t state[10]= {0}; |
179 | | AVLFG prng; |
180 | | |
181 | | av_lfg_init(&prng, 1); |
182 | | ff_init_cabac_encoder(&c, b, SIZE); |
183 | | ff_init_cabac_states(); |
184 | | |
185 | | for(i=0; i<SIZE; i++){ |
186 | | if(2*i<SIZE) r[i] = av_lfg_get(&prng) % 7; |
187 | | else r[i] = (i>>8)&1; |
188 | | } |
189 | | |
190 | | for(i=0; i<SIZE; i++){ |
191 | | START_TIMER |
192 | | put_cabac_bypass(&c, r[i]&1); |
193 | | STOP_TIMER("put_cabac_bypass") |
194 | | } |
195 | | |
196 | | for(i=0; i<SIZE; i++){ |
197 | | START_TIMER |
198 | | put_cabac(&c, state, r[i]&1); |
199 | | STOP_TIMER("put_cabac") |
200 | | } |
201 | | |
202 | | put_cabac_terminate(&c, 1); |
203 | | |
204 | | ff_init_cabac_decoder(&c, b, SIZE); |
205 | | |
206 | | memset(state, 0, sizeof(state)); |
207 | | |
208 | | for(i=0; i<SIZE; i++){ |
209 | | START_TIMER |
210 | | if( (r[i]&1) != get_cabac_bypass(&c) ) |
211 | | av_log(NULL, AV_LOG_ERROR, "CABAC bypass failure at %d\n", i); |
212 | | STOP_TIMER("get_cabac_bypass") |
213 | | } |
214 | | |
215 | | for(i=0; i<SIZE; i++){ |
216 | | START_TIMER |
217 | | if( (r[i]&1) != get_cabac_noinline(&c, state) ) |
218 | | av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i); |
219 | | STOP_TIMER("get_cabac") |
220 | | } |
221 | | if(!get_cabac_terminate(&c)) |
222 | | av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n"); |
223 | | |
224 | | return 0; |
225 | | } |
226 | | |
227 | | #endif /* TEST */ |