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)
125  c->error = AVERROR_INVALIDDATA;
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");
181  c->error = AVERROR_INVALIDDATA;
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 */
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:191
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:61
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
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:134
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:175
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:92
refill
static void refill(DiracArith *c)
Definition: dirac_arith.h:109
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
uint8_t
uint8_t
Definition: audio_convert.c:194
ret
ret
Definition: filter_design.txt:187
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:82
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
length
const char int length
Definition: avisynth_c.h:860
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
ff_dirac_prob
const uint16_t ff_dirac_prob[256]
Definition: dirac_arith.c:31