• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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 Feb 1 2013 14:34:32 for FFmpeg by doxygen 1.7.1