annotate cabac.c @ 1306:799839d1e2e1 libavcodec

golomb rice codes use gradients instead of prediction errors as context model store independant quantization tables for each point merge contexts with opposit sign
author michaelni
date Fri, 13 Jun 2003 21:31:28 +0000
parents e18667d1e94d
children 79dddc5cd990
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1287
michaelni
parents:
diff changeset
1 /*
michaelni
parents:
diff changeset
2 * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
michaelni
parents:
diff changeset
3 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
michaelni
parents:
diff changeset
4 *
michaelni
parents:
diff changeset
5 * This library is free software; you can redistribute it and/or
michaelni
parents:
diff changeset
6 * modify it under the terms of the GNU Lesser General Public
michaelni
parents:
diff changeset
7 * License as published by the Free Software Foundation; either
michaelni
parents:
diff changeset
8 * version 2 of the License, or (at your option) any later version.
michaelni
parents:
diff changeset
9 *
michaelni
parents:
diff changeset
10 * This library is distributed in the hope that it will be useful,
michaelni
parents:
diff changeset
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
michaelni
parents:
diff changeset
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
michaelni
parents:
diff changeset
13 * Lesser General Public License for more details.
michaelni
parents:
diff changeset
14 *
michaelni
parents:
diff changeset
15 * You should have received a copy of the GNU Lesser General Public
michaelni
parents:
diff changeset
16 * License along with this library; if not, write to the Free Software
michaelni
parents:
diff changeset
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
michaelni
parents:
diff changeset
18 *
michaelni
parents:
diff changeset
19 */
michaelni
parents:
diff changeset
20
michaelni
parents:
diff changeset
21 /**
michaelni
parents:
diff changeset
22 * @file cabac.c
michaelni
parents:
diff changeset
23 * Context Adaptive Binary Arithmetic Coder.
michaelni
parents:
diff changeset
24 */
michaelni
parents:
diff changeset
25
michaelni
parents:
diff changeset
26 #include <string.h>
michaelni
parents:
diff changeset
27
michaelni
parents:
diff changeset
28 #include "common.h"
michaelni
parents:
diff changeset
29 #include "cabac.h"
michaelni
parents:
diff changeset
30
michaelni
parents:
diff changeset
31 const uint8_t ff_h264_lps_range[64][4]= {
michaelni
parents:
diff changeset
32 {128,176,208,240}, {128,167,197,227}, {128,158,187,216}, {123,150,178,205},
michaelni
parents:
diff changeset
33 {116,142,169,195}, {111,135,160,185}, {105,128,152,175}, {100,122,144,166},
michaelni
parents:
diff changeset
34 { 95,116,137,158}, { 90,110,130,150}, { 85,104,123,142}, { 81, 99,117,135},
michaelni
parents:
diff changeset
35 { 77, 94,111,128}, { 73, 89,105,122}, { 69, 85,100,116}, { 66, 80, 95,110},
michaelni
parents:
diff changeset
36 { 62, 76, 90,104}, { 59, 72, 86, 99}, { 56, 69, 81, 94}, { 53, 65, 77, 89},
michaelni
parents:
diff changeset
37 { 51, 62, 73, 85}, { 48, 59, 69, 80}, { 46, 56, 66, 76}, { 43, 53, 63, 72},
michaelni
parents:
diff changeset
38 { 41, 50, 59, 69}, { 39, 48, 56, 65}, { 37, 45, 54, 62}, { 35, 43, 51, 59},
michaelni
parents:
diff changeset
39 { 33, 41, 48, 56}, { 32, 39, 46, 53}, { 30, 37, 43, 50}, { 29, 35, 41, 48},
michaelni
parents:
diff changeset
40 { 27, 33, 39, 45}, { 26, 31, 37, 43}, { 24, 30, 35, 41}, { 23, 28, 33, 39},
michaelni
parents:
diff changeset
41 { 22, 27, 32, 37}, { 21, 26, 30, 35}, { 20, 24, 29, 33}, { 19, 23, 27, 31},
michaelni
parents:
diff changeset
42 { 18, 22, 26, 30}, { 17, 21, 25, 28}, { 16, 20, 23, 27}, { 15, 19, 22, 25},
michaelni
parents:
diff changeset
43 { 14, 18, 21, 24}, { 14, 17, 20, 23}, { 13, 16, 19, 22}, { 12, 15, 18, 21},
michaelni
parents:
diff changeset
44 { 12, 14, 17, 20}, { 11, 14, 16, 19}, { 11, 13, 15, 18}, { 10, 12, 15, 17},
michaelni
parents:
diff changeset
45 { 10, 12, 14, 16}, { 9, 11, 13, 15}, { 9, 11, 12, 14}, { 8, 10, 12, 14},
michaelni
parents:
diff changeset
46 { 8, 9, 11, 13}, { 7, 9, 11, 12}, { 7, 9, 10, 12}, { 7, 8, 10, 11},
michaelni
parents:
diff changeset
47 { 6, 8, 9, 11}, { 6, 7, 9, 10}, { 6, 7, 8, 9}, { 2, 2, 2, 2},
michaelni
parents:
diff changeset
48 };
michaelni
parents:
diff changeset
49
michaelni
parents:
diff changeset
50 const uint8_t ff_h264_mps_state[64]= {
michaelni
parents:
diff changeset
51 1, 2, 3, 4, 5, 6, 7, 8,
michaelni
parents:
diff changeset
52 9,10,11,12,13,14,15,16,
michaelni
parents:
diff changeset
53 17,18,19,20,21,22,23,24,
michaelni
parents:
diff changeset
54 25,26,27,28,29,30,31,32,
michaelni
parents:
diff changeset
55 33,34,35,36,37,38,39,40,
michaelni
parents:
diff changeset
56 41,42,43,44,45,46,47,48,
michaelni
parents:
diff changeset
57 49,50,51,52,53,54,55,56,
michaelni
parents:
diff changeset
58 57,58,59,60,61,62,62,63,
michaelni
parents:
diff changeset
59 };
michaelni
parents:
diff changeset
60
michaelni
parents:
diff changeset
61 const uint8_t ff_h264_lps_state[64]= {
michaelni
parents:
diff changeset
62 0, 0, 1, 2, 2, 4, 4, 5,
michaelni
parents:
diff changeset
63 6, 7, 8, 9, 9,11,11,12,
michaelni
parents:
diff changeset
64 13,13,15,15,16,16,18,18,
michaelni
parents:
diff changeset
65 19,19,21,21,22,22,23,24,
michaelni
parents:
diff changeset
66 24,25,26,26,27,27,28,29,
michaelni
parents:
diff changeset
67 29,30,30,30,31,32,32,33,
michaelni
parents:
diff changeset
68 33,33,34,34,35,35,35,36,
michaelni
parents:
diff changeset
69 36,36,37,37,37,38,38,63,
michaelni
parents:
diff changeset
70 };
michaelni
parents:
diff changeset
71
michaelni
parents:
diff changeset
72 /**
michaelni
parents:
diff changeset
73 *
michaelni
parents:
diff changeset
74 * @param buf_size size of buf in bits
michaelni
parents:
diff changeset
75 */
michaelni
parents:
diff changeset
76 void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size){
michaelni
parents:
diff changeset
77 init_put_bits(&c->pb, buf, buf_size, NULL, NULL);
michaelni
parents:
diff changeset
78
michaelni
parents:
diff changeset
79 c->low= 0;
michaelni
parents:
diff changeset
80 c->range= 0x1FE;
michaelni
parents:
diff changeset
81 c->outstanding_count= 0;
michaelni
parents:
diff changeset
82 #ifdef STRICT_LIMITS
michaelni
parents:
diff changeset
83 c->sym_count =0;
michaelni
parents:
diff changeset
84 #endif
michaelni
parents:
diff changeset
85
michaelni
parents:
diff changeset
86 c->pb.bit_left++; //avoids firstBitFlag
michaelni
parents:
diff changeset
87 }
michaelni
parents:
diff changeset
88
michaelni
parents:
diff changeset
89 /**
michaelni
parents:
diff changeset
90 *
michaelni
parents:
diff changeset
91 * @param buf_size size of buf in bits
michaelni
parents:
diff changeset
92 */
michaelni
parents:
diff changeset
93 void ff_init_cabac_decoder(CABACContext *c, uint8_t *buf, int buf_size){
1300
e18667d1e94d FFV1 codec (our very simple lossless intra only codec, compresses much better then huffyuv)
michaelni
parents: 1298
diff changeset
94 c->bytestream_start=
1287
michaelni
parents:
diff changeset
95 c->bytestream= buf;
michaelni
parents:
diff changeset
96
michaelni
parents:
diff changeset
97 c->low= *c->bytestream++;
michaelni
parents:
diff changeset
98 c->low= (c->low<<9) + ((*c->bytestream++)<<1);
michaelni
parents:
diff changeset
99 c->range= 0x1FE00;
michaelni
parents:
diff changeset
100 c->bits_left= 7;
michaelni
parents:
diff changeset
101 }
michaelni
parents:
diff changeset
102
michaelni
parents:
diff changeset
103 void ff_init_cabac_states(CABACContext *c, uint8_t const (*lps_range)[4],
michaelni
parents:
diff changeset
104 uint8_t const *mps_state, uint8_t const *lps_state, int state_count){
michaelni
parents:
diff changeset
105 int i, j;
michaelni
parents:
diff changeset
106
michaelni
parents:
diff changeset
107 for(i=0; i<state_count; i++){
michaelni
parents:
diff changeset
108 for(j=0; j<4; j++){ //FIXME check if this is worth the 1 shift we save
michaelni
parents:
diff changeset
109 c->lps_range[2*i+0][j]=
michaelni
parents:
diff changeset
110 c->lps_range[2*i+1][j]= lps_range[i][j];
michaelni
parents:
diff changeset
111 }
michaelni
parents:
diff changeset
112
michaelni
parents:
diff changeset
113 c->mps_state[2*i+0]= 2*mps_state[i];
michaelni
parents:
diff changeset
114 c->mps_state[2*i+1]= 2*mps_state[i]+1;
michaelni
parents:
diff changeset
115
michaelni
parents:
diff changeset
116 if(lps_state[i]){
michaelni
parents:
diff changeset
117 c->lps_state[2*i+0]= 2*lps_state[i];
michaelni
parents:
diff changeset
118 c->lps_state[2*i+1]= 2*lps_state[i]+1;
michaelni
parents:
diff changeset
119 }else{
michaelni
parents:
diff changeset
120 c->lps_state[2*i+0]= 1;
michaelni
parents:
diff changeset
121 c->lps_state[2*i+1]= 0;
michaelni
parents:
diff changeset
122 }
michaelni
parents:
diff changeset
123 }
michaelni
parents:
diff changeset
124 }
michaelni
parents:
diff changeset
125
michaelni
parents:
diff changeset
126 #if 0 //selftest
michaelni
parents:
diff changeset
127 #define SIZE 10240
michaelni
parents:
diff changeset
128 int main(){
michaelni
parents:
diff changeset
129 CABACContext c;
michaelni
parents:
diff changeset
130 uint8_t b[9*SIZE];
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
131 uint8_t r[9*SIZE];
1287
michaelni
parents:
diff changeset
132 int i;
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
133 uint8_t state[10]= {0};
1287
michaelni
parents:
diff changeset
134
michaelni
parents:
diff changeset
135 ff_init_cabac_encoder(&c, b, SIZE);
michaelni
parents:
diff changeset
136 ff_init_cabac_states(&c, ff_h264_lps_range, ff_h264_mps_state, ff_h264_lps_state, 64);
michaelni
parents:
diff changeset
137
michaelni
parents:
diff changeset
138 for(i=0; i<SIZE; i++){
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
139 r[i]= random()%7;
1287
michaelni
parents:
diff changeset
140 }
michaelni
parents:
diff changeset
141
michaelni
parents:
diff changeset
142 for(i=0; i<SIZE; i++){
michaelni
parents:
diff changeset
143 START_TIMER
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
144 put_cabac_bypass(&c, r[i]&1);
1287
michaelni
parents:
diff changeset
145 STOP_TIMER("put_cabac_bypass")
michaelni
parents:
diff changeset
146 }
michaelni
parents:
diff changeset
147
michaelni
parents:
diff changeset
148 for(i=0; i<SIZE; i++){
michaelni
parents:
diff changeset
149 START_TIMER
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
150 put_cabac(&c, state, r[i]&1);
1287
michaelni
parents:
diff changeset
151 STOP_TIMER("put_cabac")
michaelni
parents:
diff changeset
152 }
michaelni
parents:
diff changeset
153
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
154 for(i=0; i<SIZE; i++){
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
155 START_TIMER
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
156 put_cabac_u(&c, state, r[i], 6, 3, i&1);
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
157 STOP_TIMER("put_cabac_u")
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
158 }
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
159
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
160 for(i=0; i<SIZE; i++){
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
161 START_TIMER
1298
5bc3184810dc cleanup
michaelni
parents: 1290
diff changeset
162 put_cabac_ueg(&c, state, r[i], 3, 0, 1, 2);
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
163 STOP_TIMER("put_cabac_ueg")
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
164 }
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
165
1287
michaelni
parents:
diff changeset
166 put_cabac_terminate(&c, 1);
michaelni
parents:
diff changeset
167
michaelni
parents:
diff changeset
168 ff_init_cabac_decoder(&c, b, SIZE);
michaelni
parents:
diff changeset
169
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
170 memset(state, 0, sizeof(state));
1287
michaelni
parents:
diff changeset
171
michaelni
parents:
diff changeset
172 for(i=0; i<SIZE; i++){
michaelni
parents:
diff changeset
173 START_TIMER
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
174 if( (r[i]&1) != get_cabac_bypass(&c) )
1287
michaelni
parents:
diff changeset
175 printf("CABAC bypass failure at %d\n", i);
michaelni
parents:
diff changeset
176 STOP_TIMER("get_cabac_bypass")
michaelni
parents:
diff changeset
177 }
michaelni
parents:
diff changeset
178
michaelni
parents:
diff changeset
179 for(i=0; i<SIZE; i++){
michaelni
parents:
diff changeset
180 START_TIMER
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
181 if( (r[i]&1) != get_cabac(&c, state) )
1287
michaelni
parents:
diff changeset
182 printf("CABAC failure at %d\n", i);
michaelni
parents:
diff changeset
183 STOP_TIMER("get_cabac")
michaelni
parents:
diff changeset
184 }
1290
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
185
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
186 for(i=0; i<SIZE; i++){
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
187 START_TIMER
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
188 if( r[i] != get_cabac_u(&c, state, (i&1) ? 6 : 7, 3, i&1) )
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
189 printf("CABAC unary (truncated) binarization failure at %d\n", i);
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
190 STOP_TIMER("get_cabac_u")
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
191 }
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
192
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
193 for(i=0; i<SIZE; i++){
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
194 START_TIMER
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
195 if( r[i] != get_cabac_ueg(&c, state, 3, 0, 1, 2))
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
196 printf("CABAC unary (truncated) binarization failure at %d\n", i);
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
197 STOP_TIMER("get_cabac_ueg")
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
198 }
dae280b939ca (truncated) unary binerization
michaelni
parents: 1287
diff changeset
199
1287
michaelni
parents:
diff changeset
200 if(!get_cabac_terminate(&c))
michaelni
parents:
diff changeset
201 printf("where's the Terminator?\n");
michaelni
parents:
diff changeset
202
michaelni
parents:
diff changeset
203 return 0;
michaelni
parents:
diff changeset
204 }
michaelni
parents:
diff changeset
205
michaelni
parents:
diff changeset
206 #endif