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 int16_t ff_dirac_prob_branchless[256][2];
90 
91 static 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 
108 static 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)
125  }
126 
127  c->low += new << counter;
128  counter -= 16;
129  }
130  c->counter = counter;
131 }
132 
133 static 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 
174 static 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");
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 
190 static 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 
198 void ff_dirac_init_arith_tables(void);
200 
201 #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:174
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:91
bitstream reader API header.
static void refill(DiracArith *c)
Definition: dirac_arith.h:108
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:194
GLsizei GLsizei * length
Definition: opengl_enc.c:114
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:133
unsigned low
Definition: dirac_arith.h:76
#define bit(string, value)
Definition: cbs_mpeg2.c:58
__asm__(".macro parse_r var r\n\t""\\var = -1\n\t"_IFC_REG(0) _IFC_REG(1) _IFC_REG(2) _IFC_REG(3) _IFC_REG(4) _IFC_REG(5) _IFC_REG(6) _IFC_REG(7) _IFC_REG(8) _IFC_REG(9) _IFC_REG(10) _IFC_REG(11) _IFC_REG(12) _IFC_REG(13) _IFC_REG(14) _IFC_REG(15) _IFC_REG(16) _IFC_REG(17) _IFC_REG(18) _IFC_REG(19) _IFC_REG(20) _IFC_REG(21) _IFC_REG(22) _IFC_REG(23) _IFC_REG(24) _IFC_REG(25) _IFC_REG(26) _IFC_REG(27) _IFC_REG(28) _IFC_REG(29) _IFC_REG(30) _IFC_REG(31)".iflt \\var\n\t"".error \"Unable to parse register name \\r\"\n\t"".endif\n\t"".endm")
static int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
Definition: dirac_arith.h:190
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