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