]> git.sesse.net Git - ffmpeg/blob - libavcodec/tests/cabac.c
avutil/pixdesc: Remove deprecated AV_PIX_FMT_FLAG_PSEUDOPAL
[ffmpeg] / libavcodec / tests / cabac.c
1 /*
2  * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "libavcodec/cabac.c"
22
23 #define SIZE 10240
24
25 #include "libavutil/lfg.h"
26 #include "libavcodec/avcodec.h"
27 #include "libavcodec/put_bits.h"
28
29 typedef struct CABACTestContext {
30     CABACContext dec;
31     int outstanding_count;
32     PutBitContext pb;
33 } CABACTestContext;
34
35 static inline void put_cabac_bit(CABACTestContext *c, int b)
36 {
37     put_bits(&c->pb, 1, b);
38     for(;c->outstanding_count; c->outstanding_count--){
39         put_bits(&c->pb, 1, 1-b);
40     }
41 }
42
43 static inline void renorm_cabac_encoder(CABACTestContext *c)
44 {
45     while (c->dec.range < 0x100) {
46         //FIXME optimize
47         if (c->dec.low < 0x100) {
48             put_cabac_bit(c, 0);
49         } else if (c->dec.low < 0x200) {
50             c->outstanding_count++;
51             c->dec.low -= 0x100;
52         }else{
53             put_cabac_bit(c, 1);
54             c->dec.low -= 0x200;
55         }
56
57         c->dec.range += c->dec.range;
58         c->dec.low   += c->dec.low;
59     }
60 }
61
62 static void put_cabac(CABACTestContext *c, uint8_t * const state, int bit)
63 {
64     int RangeLPS = ff_h264_lps_range[2 * (c->dec.range & 0xC0) + *state];
65
66     if(bit == ((*state)&1)){
67         c->dec.range -= RangeLPS;
68         *state    = ff_h264_mlps_state[128 + *state];
69     }else{
70         c->dec.low  += c->dec.range - RangeLPS;
71         c->dec.range = RangeLPS;
72         *state= ff_h264_mlps_state[127 - *state];
73     }
74
75     renorm_cabac_encoder(c);
76 }
77
78 /**
79  * @param bit 0 -> write zero bit, !=0 write one bit
80  */
81 static void put_cabac_bypass(CABACTestContext *c, int bit)
82 {
83     c->dec.low += c->dec.low;
84
85     if(bit){
86         c->dec.low += c->dec.range;
87     }
88 //FIXME optimize
89     if (c->dec.low < 0x200) {
90         put_cabac_bit(c, 0);
91     } else if (c->dec.low < 0x400) {
92         c->outstanding_count++;
93         c->dec.low -= 0x200;
94     }else{
95         put_cabac_bit(c, 1);
96         c->dec.low -= 0x400;
97     }
98 }
99
100 /**
101  *
102  * @return the number of bytes written
103  */
104 static int put_cabac_terminate(CABACTestContext *c, int bit)
105 {
106     c->dec.range -= 2;
107
108     if(!bit){
109         renorm_cabac_encoder(c);
110     }else{
111         c->dec.low  += c->dec.range;
112         c->dec.range = 2;
113
114         renorm_cabac_encoder(c);
115
116         av_assert0(c->dec.low <= 0x1FF);
117         put_cabac_bit(c, c->dec.low >> 9);
118         put_bits(&c->pb, 2, ((c->dec.low >> 7) & 3) | 1);
119
120         flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong
121     }
122
123     return put_bytes_count(&c->pb, 1);
124 }
125
126 /**
127  * @param buf_size size of buf in bits
128  */
129 static void init_cabac_encoder(CABACTestContext *c, uint8_t *buf, int buf_size)
130 {
131     init_put_bits(&c->pb, buf, buf_size);
132
133     c->dec.low   = 0;
134     c->dec.range = 0x1FE;
135     c->outstanding_count = 0;
136     c->pb.bit_left++; //avoids firstBitFlag
137 }
138
139 int main(void){
140     CABACTestContext c;
141     uint8_t b[9*SIZE];
142     uint8_t r[9*SIZE];
143     int i, ret = 0;
144     uint8_t state[10]= {0};
145     AVLFG prng;
146
147     av_lfg_init(&prng, 1);
148     init_cabac_encoder(&c, b, SIZE);
149
150     for(i=0; i<SIZE; i++){
151         if(2*i<SIZE) r[i] = av_lfg_get(&prng) % 7;
152         else         r[i] = (i>>8)&1;
153     }
154
155     for(i=0; i<SIZE; i++){
156         put_cabac_bypass(&c, r[i]&1);
157     }
158
159     for(i=0; i<SIZE; i++){
160         put_cabac(&c, state, r[i]&1);
161     }
162
163     i= put_cabac_terminate(&c, 1);
164     b[i++] = av_lfg_get(&prng);
165     b[i  ] = av_lfg_get(&prng);
166
167     ff_init_cabac_decoder(&c.dec, b, SIZE);
168
169     memset(state, 0, sizeof(state));
170
171     for(i=0; i<SIZE; i++){
172         if ((r[i] & 1) != get_cabac_bypass(&c.dec)) {
173             av_log(NULL, AV_LOG_ERROR, "CABAC bypass failure at %d\n", i);
174             ret = 1;
175         }
176     }
177
178     for(i=0; i<SIZE; i++){
179         if ((r[i] & 1) != get_cabac_noinline(&c.dec, state)) {
180             av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i);
181             ret = 1;
182         }
183     }
184     if (!get_cabac_terminate(&c.dec)) {
185         av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n");
186         ret = 1;
187     }
188
189     return ret;
190 }