Merge commit 'a6a750c7ef240b72ce01e9653343a0ddf247d196'
[ffmpeg.git] / 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
28 static inline void put_cabac_bit(CABACContext *c, int b){
29     put_bits(&c->pb, 1, b);
30     for(;c->outstanding_count; c->outstanding_count--){
31         put_bits(&c->pb, 1, 1-b);
32     }
33 }
34
35 static inline void renorm_cabac_encoder(CABACContext *c){
36     while(c->range < 0x100){
37         //FIXME optimize
38         if(c->low<0x100){
39             put_cabac_bit(c, 0);
40         }else if(c->low<0x200){
41             c->outstanding_count++;
42             c->low -= 0x100;
43         }else{
44             put_cabac_bit(c, 1);
45             c->low -= 0x200;
46         }
47
48         c->range+= c->range;
49         c->low += c->low;
50     }
51 }
52
53 static void put_cabac(CABACContext *c, uint8_t * const state, int bit){
54     int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + *state];
55
56     if(bit == ((*state)&1)){
57         c->range -= RangeLPS;
58         *state    = ff_h264_mlps_state[128 + *state];
59     }else{
60         c->low += c->range - RangeLPS;
61         c->range = RangeLPS;
62         *state= ff_h264_mlps_state[127 - *state];
63     }
64
65     renorm_cabac_encoder(c);
66 }
67
68 /**
69  * @param bit 0 -> write zero bit, !=0 write one bit
70  */
71 static void put_cabac_bypass(CABACContext *c, int bit){
72     c->low += c->low;
73
74     if(bit){
75         c->low += c->range;
76     }
77 //FIXME optimize
78     if(c->low<0x200){
79         put_cabac_bit(c, 0);
80     }else if(c->low<0x400){
81         c->outstanding_count++;
82         c->low -= 0x200;
83     }else{
84         put_cabac_bit(c, 1);
85         c->low -= 0x400;
86     }
87 }
88
89 /**
90  *
91  * @return the number of bytes written
92  */
93 static int put_cabac_terminate(CABACContext *c, int bit){
94     c->range -= 2;
95
96     if(!bit){
97         renorm_cabac_encoder(c);
98     }else{
99         c->low += c->range;
100         c->range= 2;
101
102         renorm_cabac_encoder(c);
103
104         av_assert0(c->low <= 0x1FF);
105         put_cabac_bit(c, c->low>>9);
106         put_bits(&c->pb, 2, ((c->low>>7)&3)|1);
107
108         flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong
109     }
110
111     return (put_bits_count(&c->pb)+7)>>3;
112 }
113
114 int main(void){
115     CABACContext c;
116     uint8_t b[9*SIZE];
117     uint8_t r[9*SIZE];
118     int i, ret = 0;
119     uint8_t state[10]= {0};
120     AVLFG prng;
121
122     av_lfg_init(&prng, 1);
123     ff_init_cabac_encoder(&c, b, SIZE);
124
125     for(i=0; i<SIZE; i++){
126         if(2*i<SIZE) r[i] = av_lfg_get(&prng) % 7;
127         else         r[i] = (i>>8)&1;
128     }
129
130     for(i=0; i<SIZE; i++){
131         put_cabac_bypass(&c, r[i]&1);
132     }
133
134     for(i=0; i<SIZE; i++){
135         put_cabac(&c, state, r[i]&1);
136     }
137
138     i= put_cabac_terminate(&c, 1);
139     b[i++] = av_lfg_get(&prng);
140     b[i  ] = av_lfg_get(&prng);
141
142     ff_init_cabac_decoder(&c, b, SIZE);
143
144     memset(state, 0, sizeof(state));
145
146     for(i=0; i<SIZE; i++){
147         if( (r[i]&1) != get_cabac_bypass(&c) ) {
148             av_log(NULL, AV_LOG_ERROR, "CABAC bypass failure at %d\n", i);
149             ret = 1;
150         }
151     }
152
153     for(i=0; i<SIZE; i++){
154         if( (r[i]&1) != get_cabac_noinline(&c, state) ) {
155             av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i);
156             ret = 1;
157         }
158     }
159     if(!get_cabac_terminate(&c)) {
160         av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n");
161         ret = 1;
162     }
163
164     return ret;
165 }