nengel@2: /* nengel@2: * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder nengel@2: * Copyright (c) 2003 Michael Niedermayer nengel@2: * nengel@2: * This file is part of FFmpeg. nengel@2: * nengel@2: * FFmpeg is free software; you can redistribute it and/or nengel@2: * modify it under the terms of the GNU Lesser General Public nengel@2: * License as published by the Free Software Foundation; either nengel@2: * version 2.1 of the License, or (at your option) any later version. nengel@2: * nengel@2: * FFmpeg is distributed in the hope that it will be useful, nengel@2: * but WITHOUT ANY WARRANTY; without even the implied warranty of nengel@2: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU nengel@2: * Lesser General Public License for more details. nengel@2: * nengel@2: * You should have received a copy of the GNU Lesser General Public nengel@2: * License along with FFmpeg; if not, write to the Free Software nengel@2: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA nengel@2: */ nengel@2: nengel@2: /** nengel@2: * @file nengel@2: * Context Adaptive Binary Arithmetic Coder. nengel@2: */ nengel@2: nengel@2: #ifndef AVCODEC_CABAC_H nengel@2: #define AVCODEC_CABAC_H nengel@2: nengel@2: //#undef NDEBUG nengel@2: #include nengel@2: #include "h264_dma.h" nengel@2: #include "libavutil/x86_cpu.h" nengel@2: #include "libavutil/attributes.h" nengel@2: nengel@2: #define CABAC_BITS 16 nengel@2: #define CABAC_MASK ((1<bytestream == c->bytestream_end){ nengel@2: if (c->bufsize>0){ nengel@2: int size = (c->bufsize > sizeof(bytestream_ls)) ? sizeof(bytestream_ls) : c->bufsize; nengel@2: int align = size &0xF; nengel@2: int dma_size = size + (align? 16-align : 0); nengel@2: nengel@2: spu_dma_get(bytestream_ls, (unsigned) c->bytestream_ea, dma_size, ED_raw); nengel@2: wait_dma_id(ED_raw); nengel@2: c->bytestream = bytestream_ls; nengel@2: c->bytestream_end = &bytestream_ls[size]; nengel@2: c->bytestream_ea += dma_size; nengel@2: c->bufsize -= size; nengel@2: } nengel@2: bytecount =0; nengel@2: }else if((unsigned)c->bytestream > (unsigned)c->bytestream_end +2){ nengel@2: //fprintf(stderr, "Read beyond end of frame %d\n", c->bufsize); nengel@2: bytecount =0; nengel@2: } nengel@2: } nengel@2: nengel@2: static void refill(CABACContext *c){ nengel@2: dma_cabac(c); nengel@2: nengel@2: c->low+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1); nengel@2: nengel@2: c->low -= CABAC_MASK; nengel@2: c->bytestream+= CABAC_BITS/8; nengel@2: } nengel@2: nengel@2: static void refill2(CABACContext *c){ nengel@2: int i, x; nengel@2: nengel@2: dma_cabac(c); nengel@2: nengel@2: x= c->low ^ (c->low-1); nengel@2: i= 7 - ff_h264_norm_shift[x>>(CABAC_BITS-1)]; nengel@2: nengel@2: x= -CABAC_MASK; nengel@2: nengel@2: x+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1); nengel@2: nengel@2: c->low += x<bytestream+= CABAC_BITS/8; nengel@2: } nengel@2: nengel@2: static inline void renorm_cabac_decoder(CABACContext *c){ nengel@2: while(c->range < 0x100){ nengel@2: c->range+= c->range; nengel@2: c->low+= c->low; nengel@2: if(!(c->low & CABAC_MASK)) nengel@2: refill(c); nengel@2: } nengel@2: } nengel@2: nengel@2: static inline void renorm_cabac_decoder_once(CABACContext *c){ nengel@2: nengel@2: int shift= (uint32_t)(c->range - 0x100)>>31; nengel@2: c->range<<= shift; nengel@2: c->low <<= shift; nengel@2: nengel@2: if(!(c->low & CABAC_MASK)) nengel@2: refill(c); nengel@2: } nengel@2: nengel@2: static av_always_inline int get_cabac_inline(CABACContext *c, uint8_t * const state){ nengel@2: nengel@2: int s = *state; nengel@2: int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + s]; nengel@2: int bit, lps_mask av_unused; nengel@2: nengel@2: c->range -= RangeLPS; nengel@2: #ifndef BRANCHLESS_CABAC_DECODER nengel@2: if(c->low < (c->range<<(CABAC_BITS+1))){ nengel@2: bit= s&1; nengel@2: *state= ff_h264_mps_state[s]; nengel@2: renorm_cabac_decoder_once(c); nengel@2: }else{ nengel@2: bit= ff_h264_norm_shift[RangeLPS]; nengel@2: c->low -= (c->range<<(CABAC_BITS+1)); nengel@2: *state= ff_h264_lps_state[s]; nengel@2: c->range = RangeLPS<low <<= bit; nengel@2: bit= (s&1)^1; nengel@2: nengel@2: if(!(c->low & CABAC_MASK)){ nengel@2: refill2(c); nengel@2: } nengel@2: } nengel@2: #else /* BRANCHLESS_CABAC_DECODER */ nengel@2: lps_mask= ((c->range<<(CABAC_BITS+1)) - c->low)>>31; nengel@2: nengel@2: c->low -= (c->range<<(CABAC_BITS+1)) & lps_mask; nengel@2: c->range += (RangeLPS - c->range) & lps_mask; nengel@2: nengel@2: s^=lps_mask; nengel@2: *state= (ff_h264_mlps_state+128)[s]; nengel@2: bit= s&1; nengel@2: nengel@2: lps_mask= ff_h264_norm_shift[c->range]; nengel@2: c->range<<= lps_mask; nengel@2: c->low <<= lps_mask; nengel@2: if(!(c->low & CABAC_MASK)) nengel@2: refill2(c); nengel@2: #endif /* BRANCHLESS_CABAC_DECODER */ nengel@2: nengel@2: return bit; nengel@2: } nengel@2: nengel@2: static int av_noinline av_unused get_cabac_noinline(CABACContext *c, uint8_t * const state){ nengel@2: return get_cabac_inline(c, state); nengel@2: } nengel@2: nengel@2: static int av_unused get_cabac(CABACContext *c, uint8_t * const state){ nengel@2: return get_cabac_inline(c, state); nengel@2: } nengel@2: nengel@2: static int av_unused get_cabac_bypass(CABACContext *c){ nengel@2: nengel@2: int range; nengel@2: c->low += c->low; nengel@2: nengel@2: if(!(c->low & CABAC_MASK)) nengel@2: refill(c); nengel@2: nengel@2: range= c->range<<(CABAC_BITS+1); nengel@2: if(c->low < range){ nengel@2: return 0; nengel@2: }else{ nengel@2: c->low -= range; nengel@2: return 1; nengel@2: } nengel@2: } nengel@2: nengel@2: static av_always_inline int get_cabac_bypass_sign(CABACContext *c, int val){ nengel@2: int range, mask; nengel@2: c->low += c->low; nengel@2: nengel@2: if(!(c->low & CABAC_MASK)) nengel@2: refill(c); nengel@2: nengel@2: range= c->range<<(CABAC_BITS+1); nengel@2: c->low -= range; nengel@2: mask= c->low >> 31; nengel@2: range &= mask; nengel@2: c->low += range; nengel@2: return (val^mask)-mask; nengel@2: } nengel@2: nengel@2: /** nengel@2: * nengel@2: * @return the number of bytes read or 0 if no end nengel@2: */ nengel@2: static int av_unused get_cabac_terminate(CABACContext *c){ nengel@2: c->range -= 2; nengel@2: if(c->low < c->range<<(CABAC_BITS+1)){ nengel@2: renorm_cabac_decoder_once(c); nengel@2: return 0; nengel@2: }else{ nengel@2: return c->bytestream - c->bytestream_start; nengel@2: } nengel@2: } nengel@2: nengel@2: #endif /* AVCODEC_CABAC_H */