⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cabac.h

📁 播放H264文件的播放器
💻 H
📖 第 1 页 / 共 2 页
字号:
/* * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder * 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 *//** * @file libavcodec/cabac.h * Context Adaptive Binary Arithmetic Coder. */#ifndef AVCODEC_CABAC_H#define AVCODEC_CABAC_H#include "bitstream.h"//#undef NDEBUG#include <assert.h>#define CABAC_BITS 16#define CABAC_MASK ((1<<CABAC_BITS)-1)#define BRANCHLESS_CABAC_DECODER 1//#define ARCH_X86_DISABLED 1typedef struct CABACContext{    int low;    int range;    int outstanding_count;#ifdef STRICT_LIMITS    int symCount;#endif    const uint8_t *bytestream_start;    const uint8_t *bytestream;    const uint8_t *bytestream_end;    PutBitContext pb;}CABACContext;extern uint8_t ff_h264_mlps_state[4*64];extern uint8_t ff_h264_lps_range[4*2*64];  ///< rangeTabLPSextern uint8_t ff_h264_mps_state[2*64];     ///< transIdxMPSextern uint8_t ff_h264_lps_state[2*64];     ///< transIdxLPSextern const uint8_t ff_h264_norm_shift[512];void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size);void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size);void ff_init_cabac_states(CABACContext *c);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;    }}#ifdef TESTstatic 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_mps_state[*state];    }else{        c->low += c->range - RangeLPS;        c->range = RangeLPS;        *state= ff_h264_lps_state[*state];    }    renorm_cabac_encoder(c);#ifdef STRICT_LIMITS    c->symCount++;#endif}static void put_cabac_static(CABACContext *c, int RangeLPS, int bit){    assert(c->range > RangeLPS);    if(!bit){        c->range -= RangeLPS;    }else{        c->low += c->range - RangeLPS;        c->range = RangeLPS;    }    renorm_cabac_encoder(c);#ifdef STRICT_LIMITS    c->symCount++;#endif}/** * @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;    }#ifdef STRICT_LIMITS    c->symCount++;#endif}/** * * @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);        assert(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    }#ifdef STRICT_LIMITS    c->symCount++;#endif    return (put_bits_count(&c->pb)+7)>>3;}/** * put (truncated) unary binarization. */static void put_cabac_u(CABACContext *c, uint8_t * state, int v, int max, int max_index, int truncated){    int i;    assert(v <= max);#if 1    for(i=0; i<v; i++){        put_cabac(c, state, 1);        if(i < max_index) state++;    }    if(truncated==0 || v<max)        put_cabac(c, state, 0);#else    if(v <= max_index){        for(i=0; i<v; i++){            put_cabac(c, state+i, 1);        }        if(truncated==0 || v<max)            put_cabac(c, state+i, 0);    }else{        for(i=0; i<=max_index; i++){            put_cabac(c, state+i, 1);        }        for(; i<v; i++){            put_cabac(c, state+max_index, 1);        }        if(truncated==0 || v<max)            put_cabac(c, state+max_index, 0);    }#endif}/** * put unary exp golomb k-th order binarization. */static void put_cabac_ueg(CABACContext *c, uint8_t * state, int v, int max, int is_signed, int k, int max_index){    int i;    if(v==0)        put_cabac(c, state, 0);    else{        const int sign= v < 0;        if(is_signed) v= FFABS(v);        if(v<max){            for(i=0; i<v; i++){                put_cabac(c, state, 1);                if(i < max_index) state++;            }            put_cabac(c, state, 0);        }else{            int m= 1<<k;            for(i=0; i<max; i++){                put_cabac(c, state, 1);                if(i < max_index) state++;            }            v -= max;            while(v >= m){ //FIXME optimize                put_cabac_bypass(c, 1);                v-= m;                m+= m;            }            put_cabac_bypass(c, 0);            while(m>>=1){                put_cabac_bypass(c, v&m);            }        }        if(is_signed)            put_cabac_bypass(c, sign);    }}#endif /* TEST */static void refill(CABACContext *c){#if CABAC_BITS == 16        c->low+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1);#else        c->low+= c->bytestream[0]<<1;#endif    c->low -= CABAC_MASK;    c->bytestream+= CABAC_BITS/8;}#if ! ( ARCH_X86 && HAVE_7REGS && HAVE_EBX_AVAILABLE && !defined(BROKEN_RELOCATIONS) )static void refill2(CABACContext *c){    int i, x;    x= c->low ^ (c->low-1);    i= 7 - ff_h264_norm_shift[x>>(CABAC_BITS-1)];    x= -CABAC_MASK;#if CABAC_BITS == 16        x+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1);#else        x+= c->bytestream[0]<<1;#endif    c->low += x<<i;    c->bytestream+= CABAC_BITS/8;}#endifstatic _inline void renorm_cabac_decoder(CABACContext *c){    while(c->range < 0x100){        c->range+= c->range;        c->low+= c->low;        if(!(c->low & CABAC_MASK))            refill(c);    }}static _inline void renorm_cabac_decoder_once(CABACContext *c){#ifdef ARCH_X86_DISABLED    int temp;#if 0    //P3:683    athlon:475    __asm__(        "lea -0x100(%0), %2         \n\t"        "shr $31, %2                \n\t"  //FIXME 31->63 for x86-64        "shl %%cl, %0               \n\t"        "shl %%cl, %1               \n\t"        : "+r"(c->range), "+r"(c->low), "+c"(temp)    );#elif 0    //P3:680    athlon:474    __asm__(        "cmp $0x100, %0             \n\t"        "setb %%cl                  \n\t"  //FIXME 31->63 for x86-64        "shl %%cl, %0               \n\t"        "shl %%cl, %1               \n\t"        : "+r"(c->range), "+r"(c->low), "+c"(temp)    );#elif 1    int temp2;    //P3:665    athlon:517    __asm__(        "lea -0x100(%0), %%eax      \n\t"        "cltd                       \n\t"        "mov %0, %%eax              \n\t"        "and %%edx, %0              \n\t"        "and %1, %%edx              \n\t"        "add %%eax, %0              \n\t"        "add %%edx, %1              \n\t"        : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2)    );#elif 0    int temp2;    //P3:673    athlon:509    __asm__(        "cmp $0x100, %0             \n\t"        "sbb %%edx, %%edx           \n\t"        "mov %0, %%eax              \n\t"        "and %%edx, %0              \n\t"        "and %1, %%edx              \n\t"        "add %%eax, %0              \n\t"        "add %%edx, %1              \n\t"        : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2)    );#else    int temp2;    //P3:677    athlon:511    __asm__(        "cmp $0x100, %0             \n\t"        "lea (%0, %0), %%eax        \n\t"        "lea (%1, %1), %%edx        \n\t"        "cmovb %%eax, %0            \n\t"        "cmovb %%edx, %1            \n\t"        : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2)    );#endif#else    //P3:675    athlon:476    int shift= (uint32_t)(c->range - 0x100)>>31;    c->range<<= shift;    c->low  <<= shift;#endif    if(!(c->low & CABAC_MASK))        refill(c);}static av_always_inline int get_cabac_inline(CABACContext *c, uint8_t * const state){    //FIXME gcc generates duplicate load/stores for c->low and c->range#define LOW          "0"#define RANGE        "4"#if ARCH_X86_64#define BYTESTART   "16"#define BYTE        "24"#define BYTEEND     "32"#else#define BYTESTART   "12"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -