FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/dirac_arith.h
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 50 54 92.6%
Functions: 5 5 100.0%
Branches: 14 16 87.5%

Line Branch Exec Source
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
39 enum dirac_arith_contexts {
40 CTX_ZPZN_F1,
41 CTX_ZPNN_F1,
42 CTX_NPZN_F1,
43 CTX_NPNN_F1,
44 CTX_ZP_F2,
45 CTX_ZP_F3,
46 CTX_ZP_F4,
47 CTX_ZP_F5,
48 CTX_ZP_F6,
49 CTX_NP_F2,
50 CTX_NP_F3,
51 CTX_NP_F4,
52 CTX_NP_F5,
53 CTX_NP_F6,
54 CTX_COEFF_DATA,
55 CTX_SIGN_NEG,
56 CTX_SIGN_ZERO,
57 CTX_SIGN_POS,
58 CTX_ZERO_BLOCK,
59 CTX_DELTA_Q_F,
60 CTX_DELTA_Q_DATA,
61 CTX_DELTA_Q_SIGN,
62
63 DIRAC_CTX_COUNT
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 1024041 static inline void renorm(DiracArith *c)
96 {
97 #if HAVE_FAST_CLZ
98 1024041 int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15);
99
100 1024041 c->low <<= shift;
101 1024041 c->range <<= shift;
102 1024041 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 1024041 }
111
112 1024041 static inline void refill(DiracArith *c)
113 {
114 1024041 int counter = c->counter;
115
116
2/2
✓ Branch 0 taken 46510 times.
✓ Branch 1 taken 977531 times.
1024041 if (counter >= 0) {
117 46510 int new = bytestream_get_be16(&c->bytestream);
118
119 // the spec defines overread bits to be 1, and streams rely on this
120
2/2
✓ Branch 0 taken 495 times.
✓ Branch 1 taken 46015 times.
46510 if (c->bytestream > c->bytestream_end) {
121 495 new |= 0xff;
122
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 404 times.
495 if (c->bytestream > c->bytestream_end+1)
123 91 new |= 0xff00;
124
125 495 c->bytestream = c->bytestream_end;
126 495 c->overread ++;
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 495 times.
495 if (c->overread > 4)
128 c->error = AVERROR_INVALIDDATA;
129 }
130
131 46510 c->low += new << counter;
132 46510 counter -= 16;
133 }
134 1024041 c->counter = counter;
135 1024041 }
136
137 1024041 static inline int dirac_get_arith_bit(DiracArith *c, int ctx)
138 {
139 1024041 int prob_zero = c->contexts[ctx];
140 int range_times_prob, bit;
141 1024041 unsigned low = c->low;
142 1024041 int range = c->range;
143
144 1024041 range_times_prob = (c->range * prob_zero) >> 16;
145
146 #if ARCH_X86 && HAVE_FAST_CMOV && HAVE_INLINE_ASM && HAVE_6REGS
147 1024041 low -= range_times_prob << 16;
148 1024041 range -= range_times_prob;
149 1024041 bit = 0;
150 1024041 __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 1024041 : "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 1024041 c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit];
170 1024041 c->low = low;
171 1024041 c->range = range;
172
173 1024041 renorm(c);
174 1024041 refill(c);
175 1024041 return bit;
176 }
177
178 353584 static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
179 {
180 353584 int ret = 1;
181
2/2
✓ Branch 1 taken 219922 times.
✓ Branch 2 taken 353584 times.
573506 while (!dirac_get_arith_bit(c, follow_ctx)) {
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219922 times.
219922 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 219922 ret <<= 1;
188 219922 ret += dirac_get_arith_bit(c, data_ctx);
189 219922 follow_ctx = ff_dirac_next_ctx[follow_ctx];
190 }
191 353584 return ret-1;
192 }
193
194 14164 static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
195 {
196 14164 int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx);
197
4/4
✓ Branch 0 taken 2620 times.
✓ Branch 1 taken 11544 times.
✓ Branch 3 taken 1346 times.
✓ Branch 4 taken 1274 times.
14164 if (ret && dirac_get_arith_bit(c, data_ctx+1))
198 1346 ret = -ret;
199 14164 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 */
206