libavcodec/dirac_arith.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 Marco Gerards <marco@gnu.org>
00003  * Copyright (C) 2009 David Conrad
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00028 #ifndef AVCODEC_DIRAC_ARITH_H
00029 #define AVCODEC_DIRAC_ARITH_H
00030 
00031 #include "bytestream.h"
00032 #include "get_bits.h"
00033 
00034 enum dirac_arith_contexts {
00035 CTX_ZPZN_F1,
00036 CTX_ZPNN_F1,
00037 CTX_NPZN_F1,
00038 CTX_NPNN_F1,
00039 CTX_ZP_F2,
00040 CTX_ZP_F3,
00041 CTX_ZP_F4,
00042 CTX_ZP_F5,
00043 CTX_ZP_F6,
00044 CTX_NP_F2,
00045 CTX_NP_F3,
00046 CTX_NP_F4,
00047 CTX_NP_F5,
00048 CTX_NP_F6,
00049 CTX_COEFF_DATA,
00050 CTX_SIGN_NEG,
00051 CTX_SIGN_ZERO,
00052 CTX_SIGN_POS,
00053 CTX_ZERO_BLOCK,
00054 CTX_DELTA_Q_F,
00055 CTX_DELTA_Q_DATA,
00056 CTX_DELTA_Q_SIGN,
00057 
00058 DIRAC_CTX_COUNT
00059 };
00060 
00061 // Dirac resets the arith decoder between decoding various types of data,
00062 // so many contexts are never used simultaneously. Thus, we can reduce
00063 // the number of contexts needed by reusing them.
00064 #define CTX_SB_F1 CTX_ZP_F5
00065 #define CTX_SB_DATA 0
00066 #define CTX_PMODE_REF1 0
00067 #define CTX_PMODE_REF2 1
00068 #define CTX_GLOBAL_BLOCK 2
00069 #define CTX_MV_F1 CTX_ZP_F2
00070 #define CTX_MV_DATA 0
00071 #define CTX_DC_F1 CTX_ZP_F5
00072 #define CTX_DC_DATA 0
00073 
00074 typedef struct {
00075 unsigned low;
00076 uint16_t range;
00077 int16_t counter;
00078 
00079 const uint8_t *bytestream;
00080 const uint8_t *bytestream_end;
00081 
00082 uint16_t contexts[DIRAC_CTX_COUNT];
00083 } DiracArith;
00084 
00085 extern const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT];
00086 extern const uint16_t ff_dirac_prob[256];
00087 extern int16_t ff_dirac_prob_branchless[256][2];
00088 
00089 static inline void renorm(DiracArith *c)
00090 {
00091 #if HAVE_FAST_CLZ
00092 int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15);
00093 
00094 c->low <<= shift;
00095 c->range <<= shift;
00096 c->counter += shift;
00097 #else
00098 while (c->range <= 0x4000) {
00099 c->low <<= 1;
00100 c->range <<= 1;
00101 c->counter++;
00102 }
00103 #endif
00104 }
00105 
00106 static inline void refill(DiracArith *c)
00107 {
00108 int counter = c->counter;
00109 
00110 if (counter >= 0) {
00111 int new = bytestream_get_be16(&c->bytestream);
00112 
00113 // the spec defines overread bits to be 1, and streams rely on this
00114 if (c->bytestream > c->bytestream_end) {
00115 new |= 0xff;
00116 if (c->bytestream > c->bytestream_end+1)
00117 new |= 0xff00;
00118 
00119 c->bytestream = c->bytestream_end;
00120 }
00121 
00122 c->low += new << counter;
00123 counter -= 16;
00124 }
00125 c->counter = counter;
00126 }
00127 
00128 static inline int dirac_get_arith_bit(DiracArith *c, int ctx)
00129 {
00130 int prob_zero = c->contexts[ctx];
00131 int range_times_prob, bit;
00132 unsigned low = c->low;
00133 int range = c->range;
00134 
00135 range_times_prob = (c->range * prob_zero) >> 16;
00136 
00137 #if HAVE_FAST_CMOV
00138 low -= range_times_prob << 16;
00139 range -= range_times_prob;
00140 bit = 0;
00141 __asm__(
00142 "cmpl %5, %4 \n\t"
00143 "setae %b0 \n\t"
00144 "cmovb %3, %2 \n\t"
00145 "cmovb %5, %1 \n\t"
00146 : "+q"(bit), "+r"(range), "+r"(low)
00147 : "r"(c->low), "r"(c->low>>16),
00148 "r"(range_times_prob)
00149 );
00150 #else
00151 bit = (low >> 16) >= range_times_prob;
00152 if (bit) {
00153 low -= range_times_prob << 16;
00154 range -= range_times_prob;
00155 } else {
00156 range = range_times_prob;
00157 }
00158 #endif
00159 
00160 c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit];
00161 c->low = low;
00162 c->range = range;
00163 
00164 renorm(c);
00165 refill(c);
00166 return bit;
00167 }
00168 
00169 static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
00170 {
00171 int ret = 1;
00172 while (!dirac_get_arith_bit(c, follow_ctx)) {
00173 ret <<= 1;
00174 ret += dirac_get_arith_bit(c, data_ctx);
00175 follow_ctx = ff_dirac_next_ctx[follow_ctx];
00176 }
00177 return ret-1;
00178 }
00179 
00180 static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
00181 {
00182 int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx);
00183 if (ret && dirac_get_arith_bit(c, data_ctx+1))
00184 ret = -ret;
00185 return ret;
00186 }
00187 
00188 void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length);
00189 
00190 #endif /* AVCODEC_DIRAC_ARITH_H */

Generated on Fri Oct 26 02:43:34 2012 for FFmpeg by doxygen 1.5.8

AltStyle によって変換されたページ (->オリジナル) /