Line | Branch | Exec | Source |
---|---|---|---|
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_functions.h" | ||
22 | #include "libavcodec/cabac.c" | ||
23 | |||
24 | #define SIZE 10240 | ||
25 | |||
26 | #include "libavutil/lfg.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 | 8410 | static inline void put_cabac_bit(CABACTestContext *c, int b) | |
36 | { | ||
37 | 8410 | put_bits(&c->pb, 1, b); | |
38 |
2/2✓ Branch 0 taken 7994 times.
✓ Branch 1 taken 8410 times.
|
16404 | for(;c->outstanding_count; c->outstanding_count--){ |
39 | 7994 | put_bits(&c->pb, 1, 1-b); | |
40 | } | ||
41 | 8410 | } | |
42 | |||
43 | 10241 | static inline void renorm_cabac_encoder(CABACTestContext *c) | |
44 | { | ||
45 |
2/2✓ Branch 0 taken 6163 times.
✓ Branch 1 taken 10241 times.
|
16404 | while (c->dec.range < 0x100) { |
46 | //FIXME optimize | ||
47 |
2/2✓ Branch 0 taken 2370 times.
✓ Branch 1 taken 3793 times.
|
6163 | if (c->dec.low < 0x100) { |
48 | 2370 | put_cabac_bit(c, 0); | |
49 |
2/2✓ Branch 0 taken 2944 times.
✓ Branch 1 taken 849 times.
|
3793 | } else if (c->dec.low < 0x200) { |
50 | 2944 | c->outstanding_count++; | |
51 | 2944 | c->dec.low -= 0x100; | |
52 | }else{ | ||
53 | 849 | put_cabac_bit(c, 1); | |
54 | 849 | c->dec.low -= 0x200; | |
55 | } | ||
56 | |||
57 | 6163 | c->dec.range += c->dec.range; | |
58 | 6163 | c->dec.low += c->dec.low; | |
59 | } | ||
60 | 10241 | } | |
61 | |||
62 | 10240 | static void put_cabac(CABACTestContext *c, uint8_t * const state, int bit) | |
63 | { | ||
64 | 10240 | int RangeLPS = ff_h264_lps_range[2 * (c->dec.range & 0xC0) + *state]; | |
65 | |||
66 |
2/2✓ Branch 0 taken 7637 times.
✓ Branch 1 taken 2603 times.
|
10240 | if(bit == ((*state)&1)){ |
67 | 7637 | c->dec.range -= RangeLPS; | |
68 | 7637 | *state = ff_h264_mlps_state[128 + *state]; | |
69 | }else{ | ||
70 | 2603 | c->dec.low += c->dec.range - RangeLPS; | |
71 | 2603 | c->dec.range = RangeLPS; | |
72 | 2603 | *state= ff_h264_mlps_state[127 - *state]; | |
73 | } | ||
74 | |||
75 | 10240 | renorm_cabac_encoder(c); | |
76 | 10240 | } | |
77 | |||
78 | /** | ||
79 | * @param bit 0 -> write zero bit, !=0 write one bit | ||
80 | */ | ||
81 | 10240 | static void put_cabac_bypass(CABACTestContext *c, int bit) | |
82 | { | ||
83 | 10240 | c->dec.low += c->dec.low; | |
84 | |||
85 |
2/2✓ Branch 0 taken 4761 times.
✓ Branch 1 taken 5479 times.
|
10240 | if(bit){ |
86 | 4761 | c->dec.low += c->dec.range; | |
87 | } | ||
88 | //FIXME optimize | ||
89 |
2/2✓ Branch 0 taken 3869 times.
✓ Branch 1 taken 6371 times.
|
10240 | if (c->dec.low < 0x200) { |
90 | 3869 | put_cabac_bit(c, 0); | |
91 |
2/2✓ Branch 0 taken 5050 times.
✓ Branch 1 taken 1321 times.
|
6371 | } else if (c->dec.low < 0x400) { |
92 | 5050 | c->outstanding_count++; | |
93 | 5050 | c->dec.low -= 0x200; | |
94 | }else{ | ||
95 | 1321 | put_cabac_bit(c, 1); | |
96 | 1321 | c->dec.low -= 0x400; | |
97 | } | ||
98 | 10240 | } | |
99 | |||
100 | /** | ||
101 | * | ||
102 | * @return the number of bytes written | ||
103 | */ | ||
104 | 1 | static int put_cabac_terminate(CABACTestContext *c, int bit) | |
105 | { | ||
106 | 1 | c->dec.range -= 2; | |
107 | |||
108 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if(!bit){ |
109 | ✗ | renorm_cabac_encoder(c); | |
110 | }else{ | ||
111 | 1 | c->dec.low += c->dec.range; | |
112 | 1 | c->dec.range = 2; | |
113 | |||
114 | 1 | renorm_cabac_encoder(c); | |
115 | |||
116 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | av_assert0(c->dec.low <= 0x1FF); |
117 | 1 | put_cabac_bit(c, c->dec.low >> 9); | |
118 | 1 | put_bits(&c->pb, 2, ((c->dec.low >> 7) & 3) | 1); | |
119 | |||
120 | 1 | flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong | |
121 | } | ||
122 | |||
123 | 1 | return put_bytes_count(&c->pb, 1); | |
124 | } | ||
125 | |||
126 | /** | ||
127 | * @param buf_size size of buf in bits | ||
128 | */ | ||
129 | 1 | static void init_cabac_encoder(CABACTestContext *c, uint8_t *buf, int buf_size) | |
130 | { | ||
131 | 1 | init_put_bits(&c->pb, buf, buf_size); | |
132 | |||
133 | 1 | c->dec.low = 0; | |
134 | 1 | c->dec.range = 0x1FE; | |
135 | 1 | c->outstanding_count = 0; | |
136 | 1 | c->pb.bit_left++; //avoids firstBitFlag | |
137 | 1 | } | |
138 | |||
139 | 1 | int main(void){ | |
140 | CABACTestContext c; | ||
141 | uint8_t b[9*SIZE]; | ||
142 | uint8_t r[9*SIZE]; | ||
143 | 1 | int i, ret = 0; | |
144 | 1 | uint8_t state[10]= {0}; | |
145 | AVLFG prng; | ||
146 | |||
147 | 1 | av_lfg_init(&prng, 1); | |
148 | 1 | init_cabac_encoder(&c, b, SIZE); | |
149 | |||
150 |
2/2✓ Branch 0 taken 10240 times.
✓ Branch 1 taken 1 times.
|
10241 | for(i=0; i<SIZE; i++){ |
151 |
2/2✓ Branch 0 taken 5120 times.
✓ Branch 1 taken 5120 times.
|
10240 | if(2*i<SIZE) r[i] = av_lfg_get(&prng) % 7; |
152 | 5120 | else r[i] = (i>>8)&1; | |
153 | } | ||
154 | |||
155 |
2/2✓ Branch 0 taken 10240 times.
✓ Branch 1 taken 1 times.
|
10241 | for(i=0; i<SIZE; i++){ |
156 | 10240 | put_cabac_bypass(&c, r[i]&1); | |
157 | } | ||
158 | |||
159 |
2/2✓ Branch 0 taken 10240 times.
✓ Branch 1 taken 1 times.
|
10241 | for(i=0; i<SIZE; i++){ |
160 | 10240 | put_cabac(&c, state, r[i]&1); | |
161 | } | ||
162 | |||
163 | 1 | i= put_cabac_terminate(&c, 1); | |
164 | 1 | b[i++] = av_lfg_get(&prng); | |
165 | 1 | b[i ] = av_lfg_get(&prng); | |
166 | |||
167 | 1 | ff_init_cabac_decoder(&c.dec, b, SIZE); | |
168 | |||
169 | 1 | memset(state, 0, sizeof(state)); | |
170 | |||
171 |
2/2✓ Branch 0 taken 10240 times.
✓ Branch 1 taken 1 times.
|
10241 | for(i=0; i<SIZE; i++){ |
172 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10240 times.
|
10240 | 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 |
2/2✓ Branch 0 taken 10240 times.
✓ Branch 1 taken 1 times.
|
10241 | for(i=0; i<SIZE; i++){ |
179 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10240 times.
|
10240 | 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 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!get_cabac_terminate(&c.dec)) { |
185 | ✗ | av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n"); | |
186 | ✗ | ret = 1; | |
187 | } | ||
188 | |||
189 | 1 | return ret; | |
190 | } | ||
191 |