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 29typedef struct CABACTestContext { 30 CABACContext dec; 31 int outstanding_count; 32 PutBitContext pb; 33} CABACTestContext; 34 35static 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 43static 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 62static 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 */ 81static 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 */ 104static 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 */ 129static 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 139int 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} 191