| 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 | void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size){ |
| 42 | init_put_bits(&c->pb, buf, buf_size); |
| 43 | |
| 44 | c->low= 0; |
| 45 | c->range= 0x1FE; |
| 46 | c->outstanding_count= 0; |
| 47 | c->pb.bit_left++; //avoids firstBitFlag |
| 48 | } |
| 49 | |
| 50 | /** |
| 51 | * |
| 52 | * @param buf_size size of buf in bits |
| 53 | */ |
| 54 | void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size){ |
| 55 | c->bytestream_start= |
| 56 | c->bytestream= buf; |
| 57 | c->bytestream_end= buf + buf_size; |
| 58 | |
| 59 | #if CABAC_BITS == 16 |
| 60 | c->low = (*c->bytestream++)<<18; |
| 61 | c->low+= (*c->bytestream++)<<10; |
| 62 | #else |
| 63 | c->low = (*c->bytestream++)<<10; |
| 64 | #endif |
| 65 | c->low+= ((*c->bytestream++)<<2) + 2; |
| 66 | c->range= 0x1FE; |
| 67 | } |
| 68 | |
| 69 | void ff_init_cabac_states(void) |
| 70 | { |
| 71 | static int initialized = 0; |
| 72 | |
| 73 | if (initialized) |
| 74 | return; |
| 75 | |
| 76 | cabac_tableinit(); |
| 77 | |
| 78 | initialized = 1; |
| 79 | } |
| 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 */ |