annotate libavcodec/cell/cabac_spu.h @ 9:ea1ba68cf0ed

update to match api changes + add sscc produced source
author Nina Engelhardt <nengel@mailbox.tu-berlin.de>
date Wed, 05 Jun 2013 14:43:26 +0200
parents
children
rev   line source
nengel@2 1 /*
nengel@2 2 * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
nengel@2 3 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
nengel@2 4 *
nengel@2 5 * This file is part of FFmpeg.
nengel@2 6 *
nengel@2 7 * FFmpeg is free software; you can redistribute it and/or
nengel@2 8 * modify it under the terms of the GNU Lesser General Public
nengel@2 9 * License as published by the Free Software Foundation; either
nengel@2 10 * version 2.1 of the License, or (at your option) any later version.
nengel@2 11 *
nengel@2 12 * FFmpeg is distributed in the hope that it will be useful,
nengel@2 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nengel@2 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
nengel@2 15 * Lesser General Public License for more details.
nengel@2 16 *
nengel@2 17 * You should have received a copy of the GNU Lesser General Public
nengel@2 18 * License along with FFmpeg; if not, write to the Free Software
nengel@2 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
nengel@2 20 */
nengel@2 21
nengel@2 22 /**
nengel@2 23 * @file
nengel@2 24 * Context Adaptive Binary Arithmetic Coder.
nengel@2 25 */
nengel@2 26
nengel@2 27 #ifndef AVCODEC_CABAC_H
nengel@2 28 #define AVCODEC_CABAC_H
nengel@2 29
nengel@2 30 //#undef NDEBUG
nengel@2 31 #include <assert.h>
nengel@2 32 #include "h264_dma.h"
nengel@2 33 #include "libavutil/x86_cpu.h"
nengel@2 34 #include "libavutil/attributes.h"
nengel@2 35
nengel@2 36 #define CABAC_BITS 16
nengel@2 37 #define CABAC_MASK ((1<<CABAC_BITS)-1)
nengel@2 38 #define BRANCHLESS_CABAC_DECODER 1
nengel@2 39
nengel@2 40 typedef struct CABACContext{
nengel@2 41 int low;
nengel@2 42 int range;
nengel@2 43 int outstanding_count;
nengel@2 44 #ifdef STRICT_LIMITS
nengel@2 45 int symCount;
nengel@2 46 #endif
nengel@2 47 const uint8_t *bytestream_ea_start;
nengel@2 48 const uint8_t *bytestream_ea;
nengel@2 49 const uint8_t *bytestream_ea_end;
nengel@2 50 int slot;
nengel@2 51 int bufsize;
nengel@2 52
nengel@2 53 uint8_t *bytestream_start;
nengel@2 54 uint8_t *bytestream;
nengel@2 55 uint8_t *bytestream_end;
nengel@2 56 uint8_t cabac_state[460];
nengel@2 57 }CABACContext;
nengel@2 58
nengel@2 59 extern uint8_t ff_h264_mlps_state[4*64];
nengel@2 60 extern uint8_t ff_h264_lps_range[4*2*64]; ///< rangeTabLPS
nengel@2 61 extern uint8_t ff_h264_mps_state[2*64]; ///< transIdxMPS
nengel@2 62 extern uint8_t ff_h264_lps_state[2*64]; ///< transIdxLPS
nengel@2 63 extern const uint8_t ff_h264_norm_shift[512];
nengel@2 64
nengel@2 65 void ff_init_cabac_states(void);
nengel@2 66
nengel@2 67 extern DECLARE_ALIGNED(128,uint8_t, bytestream_ls[4096]);
nengel@2 68 extern int bytecount;
nengel@2 69 static inline void dma_cabac(CABACContext *c){
nengel@2 70 bytecount++;
nengel@2 71 if (c->bytestream == c->bytestream_end){
nengel@2 72 if (c->bufsize>0){
nengel@2 73 int size = (c->bufsize > sizeof(bytestream_ls)) ? sizeof(bytestream_ls) : c->bufsize;
nengel@2 74 int align = size &0xF;
nengel@2 75 int dma_size = size + (align? 16-align : 0);
nengel@2 76
nengel@2 77 spu_dma_get(bytestream_ls, (unsigned) c->bytestream_ea, dma_size, ED_raw);
nengel@2 78 wait_dma_id(ED_raw);
nengel@2 79 c->bytestream = bytestream_ls;
nengel@2 80 c->bytestream_end = &bytestream_ls[size];
nengel@2 81 c->bytestream_ea += dma_size;
nengel@2 82 c->bufsize -= size;
nengel@2 83 }
nengel@2 84 bytecount =0;
nengel@2 85 }else if((unsigned)c->bytestream > (unsigned)c->bytestream_end +2){
nengel@2 86 //fprintf(stderr, "Read beyond end of frame %d\n", c->bufsize);
nengel@2 87 bytecount =0;
nengel@2 88 }
nengel@2 89 }
nengel@2 90
nengel@2 91 static void refill(CABACContext *c){
nengel@2 92 dma_cabac(c);
nengel@2 93
nengel@2 94 c->low+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1);
nengel@2 95
nengel@2 96 c->low -= CABAC_MASK;
nengel@2 97 c->bytestream+= CABAC_BITS/8;
nengel@2 98 }
nengel@2 99
nengel@2 100 static void refill2(CABACContext *c){
nengel@2 101 int i, x;
nengel@2 102
nengel@2 103 dma_cabac(c);
nengel@2 104
nengel@2 105 x= c->low ^ (c->low-1);
nengel@2 106 i= 7 - ff_h264_norm_shift[x>>(CABAC_BITS-1)];
nengel@2 107
nengel@2 108 x= -CABAC_MASK;
nengel@2 109
nengel@2 110 x+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1);
nengel@2 111
nengel@2 112 c->low += x<<i;
nengel@2 113 c->bytestream+= CABAC_BITS/8;
nengel@2 114 }
nengel@2 115
nengel@2 116 static inline void renorm_cabac_decoder(CABACContext *c){
nengel@2 117 while(c->range < 0x100){
nengel@2 118 c->range+= c->range;
nengel@2 119 c->low+= c->low;
nengel@2 120 if(!(c->low & CABAC_MASK))
nengel@2 121 refill(c);
nengel@2 122 }
nengel@2 123 }
nengel@2 124
nengel@2 125 static inline void renorm_cabac_decoder_once(CABACContext *c){
nengel@2 126
nengel@2 127 int shift= (uint32_t)(c->range - 0x100)>>31;
nengel@2 128 c->range<<= shift;
nengel@2 129 c->low <<= shift;
nengel@2 130
nengel@2 131 if(!(c->low & CABAC_MASK))
nengel@2 132 refill(c);
nengel@2 133 }
nengel@2 134
nengel@2 135 static av_always_inline int get_cabac_inline(CABACContext *c, uint8_t * const state){
nengel@2 136
nengel@2 137 int s = *state;
nengel@2 138 int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + s];
nengel@2 139 int bit, lps_mask av_unused;
nengel@2 140
nengel@2 141 c->range -= RangeLPS;
nengel@2 142 #ifndef BRANCHLESS_CABAC_DECODER
nengel@2 143 if(c->low < (c->range<<(CABAC_BITS+1))){
nengel@2 144 bit= s&1;
nengel@2 145 *state= ff_h264_mps_state[s];
nengel@2 146 renorm_cabac_decoder_once(c);
nengel@2 147 }else{
nengel@2 148 bit= ff_h264_norm_shift[RangeLPS];
nengel@2 149 c->low -= (c->range<<(CABAC_BITS+1));
nengel@2 150 *state= ff_h264_lps_state[s];
nengel@2 151 c->range = RangeLPS<<bit;
nengel@2 152 c->low <<= bit;
nengel@2 153 bit= (s&1)^1;
nengel@2 154
nengel@2 155 if(!(c->low & CABAC_MASK)){
nengel@2 156 refill2(c);
nengel@2 157 }
nengel@2 158 }
nengel@2 159 #else /* BRANCHLESS_CABAC_DECODER */
nengel@2 160 lps_mask= ((c->range<<(CABAC_BITS+1)) - c->low)>>31;
nengel@2 161
nengel@2 162 c->low -= (c->range<<(CABAC_BITS+1)) & lps_mask;
nengel@2 163 c->range += (RangeLPS - c->range) & lps_mask;
nengel@2 164
nengel@2 165 s^=lps_mask;
nengel@2 166 *state= (ff_h264_mlps_state+128)[s];
nengel@2 167 bit= s&1;
nengel@2 168
nengel@2 169 lps_mask= ff_h264_norm_shift[c->range];
nengel@2 170 c->range<<= lps_mask;
nengel@2 171 c->low <<= lps_mask;
nengel@2 172 if(!(c->low & CABAC_MASK))
nengel@2 173 refill2(c);
nengel@2 174 #endif /* BRANCHLESS_CABAC_DECODER */
nengel@2 175
nengel@2 176 return bit;
nengel@2 177 }
nengel@2 178
nengel@2 179 static int av_noinline av_unused get_cabac_noinline(CABACContext *c, uint8_t * const state){
nengel@2 180 return get_cabac_inline(c, state);
nengel@2 181 }
nengel@2 182
nengel@2 183 static int av_unused get_cabac(CABACContext *c, uint8_t * const state){
nengel@2 184 return get_cabac_inline(c, state);
nengel@2 185 }
nengel@2 186
nengel@2 187 static int av_unused get_cabac_bypass(CABACContext *c){
nengel@2 188
nengel@2 189 int range;
nengel@2 190 c->low += c->low;
nengel@2 191
nengel@2 192 if(!(c->low & CABAC_MASK))
nengel@2 193 refill(c);
nengel@2 194
nengel@2 195 range= c->range<<(CABAC_BITS+1);
nengel@2 196 if(c->low < range){
nengel@2 197 return 0;
nengel@2 198 }else{
nengel@2 199 c->low -= range;
nengel@2 200 return 1;
nengel@2 201 }
nengel@2 202 }
nengel@2 203
nengel@2 204 static av_always_inline int get_cabac_bypass_sign(CABACContext *c, int val){
nengel@2 205 int range, mask;
nengel@2 206 c->low += c->low;
nengel@2 207
nengel@2 208 if(!(c->low & CABAC_MASK))
nengel@2 209 refill(c);
nengel@2 210
nengel@2 211 range= c->range<<(CABAC_BITS+1);
nengel@2 212 c->low -= range;
nengel@2 213 mask= c->low >> 31;
nengel@2 214 range &= mask;
nengel@2 215 c->low += range;
nengel@2 216 return (val^mask)-mask;
nengel@2 217 }
nengel@2 218
nengel@2 219 /**
nengel@2 220 *
nengel@2 221 * @return the number of bytes read or 0 if no end
nengel@2 222 */
nengel@2 223 static int av_unused get_cabac_terminate(CABACContext *c){
nengel@2 224 c->range -= 2;
nengel@2 225 if(c->low < c->range<<(CABAC_BITS+1)){
nengel@2 226 renorm_cabac_decoder_once(c);
nengel@2 227 return 0;
nengel@2 228 }else{
nengel@2 229 return c->bytestream - c->bytestream_start;
nengel@2 230 }
nengel@2 231 }
nengel@2 232
nengel@2 233 #endif /* AVCODEC_CABAC_H */