diff options
author | Clément Bœsch <clement@stupeflix.com> | 2016-06-22 13:44:29 +0200 |
---|---|---|
committer | Clément Bœsch <clement@stupeflix.com> | 2016-06-22 13:44:34 +0200 |
commit | 5d48e4eafa6c4559683892b8638d10508125f3cf (patch) | |
tree | 0d5becbd08d6ae319497dd32cbe9b67f4670cc5e /libavcodec/tests/cabac.c | |
parent | 989a614b707dcff8abdffe28dc24ec64a83b2837 (diff) | |
parent | a6a750c7ef240b72ce01e9653343a0ddf247d196 (diff) | |
download | ffmpeg-5d48e4eafa6c4559683892b8638d10508125f3cf.tar.gz |
Merge commit 'a6a750c7ef240b72ce01e9653343a0ddf247d196'
* commit 'a6a750c7ef240b72ce01e9653343a0ddf247d196':
tests: Move all test programs to a subdirectory
Merged-by: Clément Bœsch <clement@stupeflix.com>
Diffstat (limited to 'libavcodec/tests/cabac.c')
-rw-r--r-- | libavcodec/tests/cabac.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/libavcodec/tests/cabac.c b/libavcodec/tests/cabac.c new file mode 100644 index 0000000000..affe4eb141 --- /dev/null +++ b/libavcodec/tests/cabac.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/cabac.c" + +#define SIZE 10240 + +#include "libavutil/lfg.h" +#include "libavcodec/avcodec.h" + +static inline void put_cabac_bit(CABACContext *c, int b){ + put_bits(&c->pb, 1, b); + for(;c->outstanding_count; c->outstanding_count--){ + put_bits(&c->pb, 1, 1-b); + } +} + +static inline void renorm_cabac_encoder(CABACContext *c){ + while(c->range < 0x100){ + //FIXME optimize + if(c->low<0x100){ + put_cabac_bit(c, 0); + }else if(c->low<0x200){ + c->outstanding_count++; + c->low -= 0x100; + }else{ + put_cabac_bit(c, 1); + c->low -= 0x200; + } + + c->range+= c->range; + c->low += c->low; + } +} + +static void put_cabac(CABACContext *c, uint8_t * const state, int bit){ + int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + *state]; + + if(bit == ((*state)&1)){ + c->range -= RangeLPS; + *state = ff_h264_mlps_state[128 + *state]; + }else{ + c->low += c->range - RangeLPS; + c->range = RangeLPS; + *state= ff_h264_mlps_state[127 - *state]; + } + + renorm_cabac_encoder(c); +} + +/** + * @param bit 0 -> write zero bit, !=0 write one bit + */ +static void put_cabac_bypass(CABACContext *c, int bit){ + c->low += c->low; + + if(bit){ + c->low += c->range; + } +//FIXME optimize + if(c->low<0x200){ + put_cabac_bit(c, 0); + }else if(c->low<0x400){ + c->outstanding_count++; + c->low -= 0x200; + }else{ + put_cabac_bit(c, 1); + c->low -= 0x400; + } +} + +/** + * + * @return the number of bytes written + */ +static int put_cabac_terminate(CABACContext *c, int bit){ + c->range -= 2; + + if(!bit){ + renorm_cabac_encoder(c); + }else{ + c->low += c->range; + c->range= 2; + + renorm_cabac_encoder(c); + + av_assert0(c->low <= 0x1FF); + put_cabac_bit(c, c->low>>9); + put_bits(&c->pb, 2, ((c->low>>7)&3)|1); + + flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong + } + + return (put_bits_count(&c->pb)+7)>>3; +} + +int main(void){ + CABACContext c; + uint8_t b[9*SIZE]; + uint8_t r[9*SIZE]; + int i, ret = 0; + uint8_t state[10]= {0}; + AVLFG prng; + + av_lfg_init(&prng, 1); + ff_init_cabac_encoder(&c, b, SIZE); + + for(i=0; i<SIZE; i++){ + if(2*i<SIZE) r[i] = av_lfg_get(&prng) % 7; + else r[i] = (i>>8)&1; + } + + for(i=0; i<SIZE; i++){ + put_cabac_bypass(&c, r[i]&1); + } + + for(i=0; i<SIZE; i++){ + put_cabac(&c, state, r[i]&1); + } + + i= put_cabac_terminate(&c, 1); + b[i++] = av_lfg_get(&prng); + b[i ] = av_lfg_get(&prng); + + ff_init_cabac_decoder(&c, b, SIZE); + + memset(state, 0, sizeof(state)); + + for(i=0; i<SIZE; i++){ + if( (r[i]&1) != get_cabac_bypass(&c) ) { + av_log(NULL, AV_LOG_ERROR, "CABAC bypass failure at %d\n", i); + ret = 1; + } + } + + for(i=0; i<SIZE; i++){ + if( (r[i]&1) != get_cabac_noinline(&c, state) ) { + av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i); + ret = 1; + } + } + if(!get_cabac_terminate(&c)) { + av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n"); + ret = 1; + } + + return ret; +} |