1/* 2 * Copyright (C) 2007 Marco Gerards <marco@gnu.org> 3 * Copyright (C) 2009 David Conrad 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * Arithmetic decoder for Dirac 25 * @author Marco Gerards <marco@gnu.org> 26 */ 27 28#ifndef AVCODEC_DIRAC_ARITH_H 29#define AVCODEC_DIRAC_ARITH_H 30 31#include "libavutil/x86/asm.h" 32#include "bytestream.h" 33#include "get_bits.h" 34 35enum dirac_arith_contexts { 36 CTX_ZPZN_F1, 37 CTX_ZPNN_F1, 38 CTX_NPZN_F1, 39 CTX_NPNN_F1, 40 CTX_ZP_F2, 41 CTX_ZP_F3, 42 CTX_ZP_F4, 43 CTX_ZP_F5, 44 CTX_ZP_F6, 45 CTX_NP_F2, 46 CTX_NP_F3, 47 CTX_NP_F4, 48 CTX_NP_F5, 49 CTX_NP_F6, 50 CTX_COEFF_DATA, 51 CTX_SIGN_NEG, 52 CTX_SIGN_ZERO, 53 CTX_SIGN_POS, 54 CTX_ZERO_BLOCK, 55 CTX_DELTA_Q_F, 56 CTX_DELTA_Q_DATA, 57 CTX_DELTA_Q_SIGN, 58 59 DIRAC_CTX_COUNT 60}; 61 62// Dirac resets the arith decoder between decoding various types of data, 63// so many contexts are never used simultaneously. Thus, we can reduce 64// the number of contexts needed by reusing them. 65#define CTX_SB_F1 CTX_ZP_F5 66#define CTX_SB_DATA 0 67#define CTX_PMODE_REF1 0 68#define CTX_PMODE_REF2 1 69#define CTX_GLOBAL_BLOCK 2 70#define CTX_MV_F1 CTX_ZP_F2 71#define CTX_MV_DATA 0 72#define CTX_DC_F1 CTX_ZP_F5 73#define CTX_DC_DATA 0 74 75typedef struct { 76 unsigned low; 77 uint16_t range; 78 int16_t counter; 79 80 const uint8_t *bytestream; 81 const uint8_t *bytestream_end; 82 83 uint16_t contexts[DIRAC_CTX_COUNT]; 84 int error; 85 int overread; 86} DiracArith; 87 88extern const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT]; 89extern int16_t ff_dirac_prob_branchless[256][2]; 90 91static inline void renorm(DiracArith *c) 92{ 93#if HAVE_FAST_CLZ 94 int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15); 95 96 c->low <<= shift; 97 c->range <<= shift; 98 c->counter += shift; 99#else 100 while (c->range <= 0x4000) { 101 c->low <<= 1; 102 c->range <<= 1; 103 c->counter++; 104 } 105#endif 106} 107 108static inline void refill(DiracArith *c) 109{ 110 int counter = c->counter; 111 112 if (counter >= 0) { 113 int new = bytestream_get_be16(&c->bytestream); 114 115 // the spec defines overread bits to be 1, and streams rely on this 116 if (c->bytestream > c->bytestream_end) { 117 new |= 0xff; 118 if (c->bytestream > c->bytestream_end+1) 119 new |= 0xff00; 120 121 c->bytestream = c->bytestream_end; 122 c->overread ++; 123 if (c->overread > 4) 124 c->error = AVERROR_INVALIDDATA; 125 } 126 127 c->low += new << counter; 128 counter -= 16; 129 } 130 c->counter = counter; 131} 132 133static inline int dirac_get_arith_bit(DiracArith *c, int ctx) 134{ 135 int prob_zero = c->contexts[ctx]; 136 int range_times_prob, bit; 137 unsigned low = c->low; 138 int range = c->range; 139 140 range_times_prob = (c->range * prob_zero) >> 16; 141 142#if ARCH_X86 && HAVE_FAST_CMOV && HAVE_INLINE_ASM && HAVE_6REGS 143 low -= range_times_prob << 16; 144 range -= range_times_prob; 145 bit = 0; 146 __asm__( 147 "cmpl %5, %4 \n\t" 148 "setae %b0 \n\t" 149 "cmovb %3, %2 \n\t" 150 "cmovb %5, %1 \n\t" 151 : "+q"(bit), "+r"(range), "+r"(low) 152 : "r"(c->low), "r"(c->low>>16), 153 "r"(range_times_prob) 154 ); 155#else 156 bit = (low >> 16) >= range_times_prob; 157 if (bit) { 158 low -= range_times_prob << 16; 159 range -= range_times_prob; 160 } else { 161 range = range_times_prob; 162 } 163#endif 164 165 c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit]; 166 c->low = low; 167 c->range = range; 168 169 renorm(c); 170 refill(c); 171 return bit; 172} 173 174static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx) 175{ 176 int ret = 1; 177 while (!dirac_get_arith_bit(c, follow_ctx)) { 178 if (ret >= 0x40000000) { 179 av_log(NULL, AV_LOG_ERROR, "dirac_get_arith_uint overflow\n"); 180 c->error = AVERROR_INVALIDDATA; 181 return -1; 182 } 183 ret <<= 1; 184 ret += dirac_get_arith_bit(c, data_ctx); 185 follow_ctx = ff_dirac_next_ctx[follow_ctx]; 186 } 187 return ret-1; 188} 189 190static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx) 191{ 192 int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx); 193 if (ret && dirac_get_arith_bit(c, data_ctx+1)) 194 ret = -ret; 195 return ret; 196} 197 198void ff_dirac_init_arith_tables(void); 199void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length); 200 201#endif /* AVCODEC_DIRAC_ARITH_H */ 202