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 
80  const uint8_t *bytestream;
81  const uint8_t *bytestream_end;
82 
83  uint16_t contexts[DIRAC_CTX_COUNT];
84  int error;
85  int overread;
86 } DiracArith;
87 
88 extern const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT];
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)
124  c->error = AVERROR_INVALIDDATA;
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");
180  c->error = AVERROR_INVALIDDATA;
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);
199 void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length);
200 
201 #endif /* AVCODEC_DIRAC_ARITH_H */
CTX_COEFF_DATA
@ CTX_COEFF_DATA
Definition: dirac_arith.h:50
CTX_ZP_F2
@ CTX_ZP_F2
Definition: dirac_arith.h:40
av_log2_16bit
int av_log2_16bit(unsigned v)
Definition: intmath.c:31
CTX_ZPZN_F1
@ CTX_ZPZN_F1
Definition: dirac_arith.h:36
CTX_ZERO_BLOCK
@ CTX_ZERO_BLOCK
Definition: dirac_arith.h:54
DiracArith::counter
int16_t counter
Definition: dirac_arith.h:78
CTX_SIGN_NEG
@ CTX_SIGN_NEG
Definition: dirac_arith.h:51
CTX_ZP_F4
@ CTX_ZP_F4
Definition: dirac_arith.h:42
DiracArith
Definition: dirac_arith.h:75
dirac_get_arith_int
static int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
Definition: dirac_arith.h:190
CTX_ZP_F5
@ CTX_ZP_F5
Definition: dirac_arith.h:43
CTX_ZP_F3
@ CTX_ZP_F3
Definition: dirac_arith.h:41
bit
#define bit(string, value)
Definition: cbs_mpeg2.c:58
ff_dirac_init_arith_decoder
void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length)
Definition: dirac_arith.c:96
GetBitContext
Definition: get_bits.h:62
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
DIRAC_CTX_COUNT
@ DIRAC_CTX_COUNT
Definition: dirac_arith.h:59
CTX_NP_F3
@ CTX_NP_F3
Definition: dirac_arith.h:46
CTX_DELTA_Q_F
@ CTX_DELTA_Q_F
Definition: dirac_arith.h:55
ctx
AVFormatContext * ctx
Definition: movenc.c:48
get_bits.h
DiracArith::bytestream
const uint8_t * bytestream
Definition: dirac_arith.h:80
dirac_get_arith_bit
static int dirac_get_arith_bit(DiracArith *c, int ctx)
Definition: dirac_arith.h:133
NULL
#define NULL
Definition: coverity.c:32
ff_dirac_prob_branchless
int16_t ff_dirac_prob_branchless[256][2]
Definition: dirac_arith.c:84
dirac_get_arith_uint
static int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
Definition: dirac_arith.h:174
CTX_NP_F6
@ CTX_NP_F6
Definition: dirac_arith.h:49
DiracArith::range
uint16_t range
Definition: dirac_arith.h:77
ff_dirac_init_arith_tables
void ff_dirac_init_arith_tables(void)
Definition: dirac_arith.c:86
c
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
CTX_SIGN_POS
@ CTX_SIGN_POS
Definition: dirac_arith.h:53
renorm
static void renorm(DiracArith *c)
Definition: dirac_arith.h:91
refill
static void refill(DiracArith *c)
Definition: dirac_arith.h:108
CTX_ZPNN_F1
@ CTX_ZPNN_F1
Definition: dirac_arith.h:37
asm.h
CTX_NPZN_F1
@ CTX_NPZN_F1
Definition: dirac_arith.h:38
DiracArith::bytestream_end
const uint8_t * bytestream_end
Definition: dirac_arith.h:81
dirac_arith_contexts
dirac_arith_contexts
Definition: dirac_arith.h:35
CTX_NP_F5
@ CTX_NP_F5
Definition: dirac_arith.h:48
ret
ret
Definition: filter_design.txt:187
__asm__
__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")
CTX_ZP_F6
@ CTX_ZP_F6
Definition: dirac_arith.h:44
CTX_NP_F2
@ CTX_NP_F2
Definition: dirac_arith.h:45
CTX_DELTA_Q_SIGN
@ CTX_DELTA_Q_SIGN
Definition: dirac_arith.h:57
CTX_SIGN_ZERO
@ CTX_SIGN_ZERO
Definition: dirac_arith.h:52
DiracArith::low
unsigned low
Definition: dirac_arith.h:76
DiracArith::overread
int overread
Definition: dirac_arith.h:85
shift
static int shift(int a, int b)
Definition: sonic.c:83
bytestream.h
CTX_NPNN_F1
@ CTX_NPNN_F1
Definition: dirac_arith.h:39
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
CTX_DELTA_Q_DATA
@ CTX_DELTA_Q_DATA
Definition: dirac_arith.h:56
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
CTX_NP_F4
@ CTX_NP_F4
Definition: dirac_arith.h:47
DiracArith::error
int error
Definition: dirac_arith.h:84
ff_dirac_next_ctx
const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT]
Definition: dirac_arith.c:66