FFmpeg
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 "libavutil/x86/asm.h"
32 #include "bytestream.h"
33 #include "get_bits.h"
34 
58 
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 
75 typedef struct {
76  unsigned low;
77  uint16_t range;
78  int16_t counter;
79 
82 
83  uint16_t contexts[DIRAC_CTX_COUNT];
84  int error;
85  int overread;
86 } DiracArith;
87 
89 extern const uint16_t ff_dirac_prob[256];
90 extern int16_t ff_dirac_prob_branchless[256][2];
91 
92 static inline void renorm(DiracArith *c)
93 {
94 #if HAVE_FAST_CLZ
95  int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15);
96 
97  c->low <<= shift;
98  c->range <<= shift;
99  c->counter += shift;
100 #else
101  while (c->range <= 0x4000) {
102  c->low <<= 1;
103  c->range <<= 1;
104  c->counter++;
105  }
106 #endif
107 }
108 
109 static inline void refill(DiracArith *c)
110 {
111  int counter = c->counter;
112 
113  if (counter >= 0) {
114  int new = bytestream_get_be16(&c->bytestream);
115 
116  // the spec defines overread bits to be 1, and streams rely on this
117  if (c->bytestream > c->bytestream_end) {
118  new |= 0xff;
119  if (c->bytestream > c->bytestream_end+1)
120  new |= 0xff00;
121 
122  c->bytestream = c->bytestream_end;
123  c->overread ++;
124  if (c->overread > 4)
126  }
127 
128  c->low += new << counter;
129  counter -= 16;
130  }
131  c->counter = counter;
132 }
133 
134 static inline int dirac_get_arith_bit(DiracArith *c, int ctx)
135 {
136  int prob_zero = c->contexts[ctx];
137  int range_times_prob, bit;
138  unsigned low = c->low;
139  int range = c->range;
140 
141  range_times_prob = (c->range * prob_zero) >> 16;
142 
143 #if ARCH_X86 && HAVE_FAST_CMOV && HAVE_INLINE_ASM && HAVE_6REGS
144  low -= range_times_prob << 16;
145  range -= range_times_prob;
146  bit = 0;
147  __asm__(
148  "cmpl %5, %4 \n\t"
149  "setae %b0 \n\t"
150  "cmovb %3, %2 \n\t"
151  "cmovb %5, %1 \n\t"
152  : "+q"(bit), "+r"(range), "+r"(low)
153  : "r"(c->low), "r"(c->low>>16),
154  "r"(range_times_prob)
155  );
156 #else
157  bit = (low >> 16) >= range_times_prob;
158  if (bit) {
159  low -= range_times_prob << 16;
160  range -= range_times_prob;
161  } else {
162  range = range_times_prob;
163  }
164 #endif
165 
166  c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit];
167  c->low = low;
168  c->range = range;
169 
170  renorm(c);
171  refill(c);
172  return bit;
173 }
174 
175 static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
176 {
177  int ret = 1;
178  while (!dirac_get_arith_bit(c, follow_ctx)) {
179  if (ret >= 0x40000000) {
180  av_log(NULL, AV_LOG_ERROR, "dirac_get_arith_uint overflow\n");
182  return -1;
183  }
184  ret <<= 1;
185  ret += dirac_get_arith_bit(c, data_ctx);
186  follow_ctx = ff_dirac_next_ctx[follow_ctx];
187  }
188  return ret-1;
189 }
190 
191 static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
192 {
193  int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx);
194  if (ret && dirac_get_arith_bit(c, data_ctx+1))
195  ret = -ret;
196  return ret;
197 }
198 
199 void ff_dirac_init_arith_tables(void);
201 
202 #endif /* AVCODEC_DIRAC_ARITH_H */
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static int shift(int a, int b)
Definition: sonic.c:82
int16_t ff_dirac_prob_branchless[256][2]
Definition: dirac_arith.c:84
uint16_t contexts[DIRAC_CTX_COUNT]
Definition: dirac_arith.h:83
static int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
Definition: dirac_arith.h:175
int av_log2_16bit(unsigned v)
Definition: intmath.c:31
int16_t counter
Definition: dirac_arith.h:78
const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT]
Definition: dirac_arith.c:66
uint8_t
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
static void renorm(DiracArith *c)
Definition: dirac_arith.h:92
bitstream reader API header.
static void refill(DiracArith *c)
Definition: dirac_arith.h:109
uint16_t range
Definition: dirac_arith.h:77
#define av_log(a,...)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
GLsizei GLsizei * length
Definition: opengl_enc.c:115
AVFormatContext * ctx
Definition: movenc.c:48
const uint8_t * bytestream
Definition: dirac_arith.h:80
const uint8_t * bytestream_end
Definition: dirac_arith.h:81
int overread
Definition: dirac_arith.h:85
static int dirac_get_arith_bit(DiracArith *c, int ctx)
Definition: dirac_arith.h:134
const uint16_t ff_dirac_prob[256]
Definition: dirac_arith.c:31
unsigned low
Definition: dirac_arith.h:76
static int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
Definition: dirac_arith.h:191
void ff_dirac_init_arith_tables(void)
Definition: dirac_arith.c:86
dirac_arith_contexts
Definition: dirac_arith.h:35
void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length)
Definition: dirac_arith.c:96