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 "config.h"
32 
33 #if ARCH_X86
34 #include "libavutil/x86/asm.h"
35 #endif
36 #include "bytestream.h"
37 #include "get_bits.h"
38 
62 
64 };
65 
66 // Dirac resets the arith decoder between decoding various types of data,
67 // so many contexts are never used simultaneously. Thus, we can reduce
68 // the number of contexts needed by reusing them.
69 #define CTX_SB_F1 CTX_ZP_F5
70 #define CTX_SB_DATA 0
71 #define CTX_PMODE_REF1 0
72 #define CTX_PMODE_REF2 1
73 #define CTX_GLOBAL_BLOCK 2
74 #define CTX_MV_F1 CTX_ZP_F2
75 #define CTX_MV_DATA 0
76 #define CTX_DC_F1 CTX_ZP_F5
77 #define CTX_DC_DATA 0
78 
79 typedef struct {
80  unsigned low;
81  uint16_t range;
82  int16_t counter;
83 
84  const uint8_t *bytestream;
85  const uint8_t *bytestream_end;
86 
87  uint16_t contexts[DIRAC_CTX_COUNT];
88  int error;
89  int overread;
90 } DiracArith;
91 
92 extern const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT];
93 extern int16_t ff_dirac_prob_branchless[256][2];
94 
95 static inline void renorm(DiracArith *c)
96 {
97 #if HAVE_FAST_CLZ
98  int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15);
99 
100  c->low <<= shift;
101  c->range <<= shift;
102  c->counter += shift;
103 #else
104  while (c->range <= 0x4000) {
105  c->low <<= 1;
106  c->range <<= 1;
107  c->counter++;
108  }
109 #endif
110 }
111 
112 static inline void refill(DiracArith *c)
113 {
114  int counter = c->counter;
115 
116  if (counter >= 0) {
117  int new = bytestream_get_be16(&c->bytestream);
118 
119  // the spec defines overread bits to be 1, and streams rely on this
120  if (c->bytestream > c->bytestream_end) {
121  new |= 0xff;
122  if (c->bytestream > c->bytestream_end+1)
123  new |= 0xff00;
124 
125  c->bytestream = c->bytestream_end;
126  c->overread ++;
127  if (c->overread > 4)
128  c->error = AVERROR_INVALIDDATA;
129  }
130 
131  c->low += new << counter;
132  counter -= 16;
133  }
134  c->counter = counter;
135 }
136 
137 static inline int dirac_get_arith_bit(DiracArith *c, int ctx)
138 {
139  int prob_zero = c->contexts[ctx];
140  int range_times_prob, bit;
141  unsigned low = c->low;
142  int range = c->range;
143 
144  range_times_prob = (c->range * prob_zero) >> 16;
145 
146 #if ARCH_X86 && HAVE_FAST_CMOV && HAVE_INLINE_ASM && HAVE_6REGS
147  low -= range_times_prob << 16;
148  range -= range_times_prob;
149  bit = 0;
150  __asm__(
151  "cmpl %5, %4 \n\t"
152  "setae %b0 \n\t"
153  "cmovb %3, %2 \n\t"
154  "cmovb %5, %1 \n\t"
155  : "+q"(bit), "+r"(range), "+r"(low)
156  : "r"(c->low), "r"(c->low>>16),
157  "r"(range_times_prob)
158  );
159 #else
160  bit = (low >> 16) >= range_times_prob;
161  if (bit) {
162  low -= range_times_prob << 16;
163  range -= range_times_prob;
164  } else {
165  range = range_times_prob;
166  }
167 #endif
168 
169  c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit];
170  c->low = low;
171  c->range = range;
172 
173  renorm(c);
174  refill(c);
175  return bit;
176 }
177 
178 static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
179 {
180  int ret = 1;
181  while (!dirac_get_arith_bit(c, follow_ctx)) {
182  if (ret >= 0x40000000) {
183  av_log(NULL, AV_LOG_ERROR, "dirac_get_arith_uint overflow\n");
184  c->error = AVERROR_INVALIDDATA;
185  return -1;
186  }
187  ret <<= 1;
188  ret += dirac_get_arith_bit(c, data_ctx);
189  follow_ctx = ff_dirac_next_ctx[follow_ctx];
190  }
191  return ret-1;
192 }
193 
194 static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
195 {
196  int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx);
197  if (ret && dirac_get_arith_bit(c, data_ctx+1))
198  ret = -ret;
199  return ret;
200 }
201 
202 void ff_dirac_init_arith_tables(void);
203 void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length);
204 
205 #endif /* AVCODEC_DIRAC_ARITH_H */
CTX_COEFF_DATA
@ CTX_COEFF_DATA
Definition: dirac_arith.h:54
CTX_ZP_F2
@ CTX_ZP_F2
Definition: dirac_arith.h:44
av_log2_16bit
int av_log2_16bit(unsigned v)
Definition: intmath.c:31
CTX_ZPZN_F1
@ CTX_ZPZN_F1
Definition: dirac_arith.h:40
CTX_ZERO_BLOCK
@ CTX_ZERO_BLOCK
Definition: dirac_arith.h:58
DiracArith::counter
int16_t counter
Definition: dirac_arith.h:82
CTX_SIGN_NEG
@ CTX_SIGN_NEG
Definition: dirac_arith.h:55
CTX_ZP_F4
@ CTX_ZP_F4
Definition: dirac_arith.h:46
DiracArith
Definition: dirac_arith.h:79
dirac_get_arith_int
static int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
Definition: dirac_arith.h:194
CTX_ZP_F5
@ CTX_ZP_F5
Definition: dirac_arith.h:47
CTX_ZP_F3
@ CTX_ZP_F3
Definition: dirac_arith.h:45
bit
#define bit(string, value)
Definition: cbs_mpeg2.c:56
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:108
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:63
CTX_NP_F3
@ CTX_NP_F3
Definition: dirac_arith.h:50
CTX_DELTA_Q_F
@ CTX_DELTA_Q_F
Definition: dirac_arith.h:59
ctx
AVFormatContext * ctx
Definition: movenc.c:48
get_bits.h
DiracArith::bytestream
const uint8_t * bytestream
Definition: dirac_arith.h:84
dirac_get_arith_bit
static int dirac_get_arith_bit(DiracArith *c, int ctx)
Definition: dirac_arith.h:137
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:178
CTX_NP_F6
@ CTX_NP_F6
Definition: dirac_arith.h:53
DiracArith::range
uint16_t range
Definition: dirac_arith.h:81
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:57
renorm
static void renorm(DiracArith *c)
Definition: dirac_arith.h:95
shift
static int shift(int a, int b)
Definition: bonk.c:262
refill
static void refill(DiracArith *c)
Definition: dirac_arith.h:112
CTX_ZPNN_F1
@ CTX_ZPNN_F1
Definition: dirac_arith.h:41
asm.h
range
enum AVColorRange range
Definition: mediacodec_wrapper.c:2557
CTX_NPZN_F1
@ CTX_NPZN_F1
Definition: dirac_arith.h:42
DiracArith::bytestream_end
const uint8_t * bytestream_end
Definition: dirac_arith.h:85
dirac_arith_contexts
dirac_arith_contexts
Definition: dirac_arith.h:39
CTX_NP_F5
@ CTX_NP_F5
Definition: dirac_arith.h:52
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:48
CTX_NP_F2
@ CTX_NP_F2
Definition: dirac_arith.h:49
CTX_DELTA_Q_SIGN
@ CTX_DELTA_Q_SIGN
Definition: dirac_arith.h:61
CTX_SIGN_ZERO
@ CTX_SIGN_ZERO
Definition: dirac_arith.h:56
DiracArith::low
unsigned low
Definition: dirac_arith.h:80
DiracArith::overread
int overread
Definition: dirac_arith.h:89
bytestream.h
CTX_NPNN_F1
@ CTX_NPNN_F1
Definition: dirac_arith.h:43
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
CTX_DELTA_Q_DATA
@ CTX_DELTA_Q_DATA
Definition: dirac_arith.h:60
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
CTX_NP_F4
@ CTX_NP_F4
Definition: dirac_arith.h:51
DiracArith::error
int error
Definition: dirac_arith.h:88
ff_dirac_next_ctx
const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT]
Definition: dirac_arith.c:66