FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dirac_arith.h
Go to the documentation of this file.
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 "bytestream.h"
32 #include "get_bits.h"
33 
57 
59 };
60 
61 // Dirac resets the arith decoder between decoding various types of data,
62 // so many contexts are never used simultaneously. Thus, we can reduce
63 // the number of contexts needed by reusing them.
64 #define CTX_SB_F1 CTX_ZP_F5
65 #define CTX_SB_DATA 0
66 #define CTX_PMODE_REF1 0
67 #define CTX_PMODE_REF2 1
68 #define CTX_GLOBAL_BLOCK 2
69 #define CTX_MV_F1 CTX_ZP_F2
70 #define CTX_MV_DATA 0
71 #define CTX_DC_F1 CTX_ZP_F5
72 #define CTX_DC_DATA 0
73 
74 typedef struct {
75  unsigned low;
76  uint16_t range;
77  int16_t counter;
78 
81 
82  uint16_t contexts[DIRAC_CTX_COUNT];
83 } DiracArith;
84 
86 extern const uint16_t ff_dirac_prob[256];
87 extern int16_t ff_dirac_prob_branchless[256][2];
88 
89 static inline void renorm(DiracArith *c)
90 {
91 #if HAVE_FAST_CLZ
92  int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15);
93 
94  c->low <<= shift;
95  c->range <<= shift;
96  c->counter += shift;
97 #else
98  while (c->range <= 0x4000) {
99  c->low <<= 1;
100  c->range <<= 1;
101  c->counter++;
102  }
103 #endif
104 }
105 
106 static inline void refill(DiracArith *c)
107 {
108  int counter = c->counter;
109 
110  if (counter >= 0) {
111  int new = bytestream_get_be16(&c->bytestream);
112 
113  // the spec defines overread bits to be 1, and streams rely on this
114  if (c->bytestream > c->bytestream_end) {
115  new |= 0xff;
116  if (c->bytestream > c->bytestream_end+1)
117  new |= 0xff00;
118 
119  c->bytestream = c->bytestream_end;
120  }
121 
122  c->low += new << counter;
123  counter -= 16;
124  }
125  c->counter = counter;
126 }
127 
128 static inline int dirac_get_arith_bit(DiracArith *c, int ctx)
129 {
130  int prob_zero = c->contexts[ctx];
131  int range_times_prob, bit;
132  unsigned low = c->low;
133  int range = c->range;
134 
135  range_times_prob = (c->range * prob_zero) >> 16;
136 
137 #if HAVE_FAST_CMOV && HAVE_INLINE_ASM
138  low -= range_times_prob << 16;
139  range -= range_times_prob;
140  bit = 0;
141  __asm__(
142  "cmpl %5, %4 \n\t"
143  "setae %b0 \n\t"
144  "cmovb %3, %2 \n\t"
145  "cmovb %5, %1 \n\t"
146  : "+q"(bit), "+r"(range), "+r"(low)
147  : "r"(c->low), "r"(c->low>>16),
148  "r"(range_times_prob)
149  );
150 #else
151  bit = (low >> 16) >= range_times_prob;
152  if (bit) {
153  low -= range_times_prob << 16;
154  range -= range_times_prob;
155  } else {
156  range = range_times_prob;
157  }
158 #endif
159 
160  c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit];
161  c->low = low;
162  c->range = range;
163 
164  renorm(c);
165  refill(c);
166  return bit;
167 }
168 
169 static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
170 {
171  int ret = 1;
172  while (!dirac_get_arith_bit(c, follow_ctx)) {
173  ret <<= 1;
174  ret += dirac_get_arith_bit(c, data_ctx);
175  follow_ctx = ff_dirac_next_ctx[follow_ctx];
176  }
177  return ret-1;
178 }
179 
180 static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
181 {
182  int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx);
183  if (ret && dirac_get_arith_bit(c, data_ctx+1))
184  ret = -ret;
185  return ret;
186 }
187 
189 
190 #endif /* AVCODEC_DIRAC_ARITH_H */