FFmpeg
Loading...
Searching...
No Matches
apv.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "libavutil/lfg.h"
21
23#include "libavcodec/apv_dsp.h"
24#include "libavcodec/put_bits.h"
25
26
27// Whole file included here to get internal symbols.
29
30
31// As defined in 7.1.4, for testing.
32// Adds a check to limit loop after reading 16 zero bits to avoid
33// getting stuck reading a stream of zeroes forever (this matches
34// the behaviour of the faster version).
35
36static unsigned int apv_read_vlc_spec(GetBitContext *gbc, int k_param)
37{
38 unsigned int symbol_value = 0;
39 int parse_exp_golomb = 1;
40 int k = k_param;
41 int stop_loop = 0;
42
43 if(get_bits1(gbc) == 1) {
44 parse_exp_golomb = 0;
45 } else {
46 if (get_bits1(gbc) == 0) {
47 symbol_value += (1 << k);
48 parse_exp_golomb = 0;
49 } else {
50 symbol_value += (2 << k);
51 parse_exp_golomb = 1;
52 }
53 }
54 if (parse_exp_golomb) {
55 int read_limit = 0;
56 do {
57 if (get_bits1(gbc) == 1) {
58 stop_loop = 1;
59 } else {
60 if (++read_limit == 16)
61 break;
62 symbol_value += (1 << k);
63 k++;
64 }
65 } while (!stop_loop);
66 }
67 if (k > 0)
68 symbol_value += get_bits(gbc, k);
69
70 return symbol_value;
71}
72
73// As defined in 7.2.4, for testing.
74
76 unsigned int symbol_val, int k_param)
77{
78 int prefix_vlc_table[3][2] = {{1, 0}, {0, 0}, {0, 1}};
79
80 unsigned int symbol_value = symbol_val;
81 int val_prefix_vlc = av_clip(symbol_val >> k_param, 0, 2);
82 int bit_count = 0;
83 int k = k_param;
84
85 while (symbol_value >= (1 << k)) {
86 symbol_value -= (1 << k);
87 if (bit_count < 2)
88 put_bits(pbc, 1, prefix_vlc_table[val_prefix_vlc][bit_count]);
89 else
90 put_bits(pbc, 1, 0);
91 if (bit_count >= 2)
92 ++k;
93 ++bit_count;
94 }
95
96 if(bit_count < 2)
97 put_bits(pbc, 1, prefix_vlc_table[val_prefix_vlc][bit_count]);
98 else
99 put_bits(pbc, 1, 1);
100
101 if(k > 0)
102 put_bits(pbc, k, symbol_value);
103}
104
105// Old version of ff_apv_entropy_decode_block, for test comparison.
106
107static int apv_entropy_decode_block(int16_t *restrict coeff,
108 GetBitContext *restrict gbc,
109 APVEntropyState *restrict state)
110{
111 const APVVLCLUT *lut = state->decode_lut;
112
113 // DC coefficient.
114 {
115 int abs_dc_coeff_diff;
116 int sign_dc_coeff_diff;
117 int dc_coeff;
118
119 abs_dc_coeff_diff = apv_read_vlc(gbc, state->prev_k_dc, lut);
120
121 if (abs_dc_coeff_diff > 0)
122 sign_dc_coeff_diff = get_bits1(gbc);
123 else
124 sign_dc_coeff_diff = 0;
125
126 if (sign_dc_coeff_diff)
127 dc_coeff = state->prev_dc - abs_dc_coeff_diff;
128 else
129 dc_coeff = state->prev_dc + abs_dc_coeff_diff;
130
131 if (dc_coeff < APV_MIN_TRANS_COEFF ||
132 dc_coeff > APV_MAX_TRANS_COEFF) {
133 av_log(state->log_ctx, AV_LOG_ERROR,
134 "Out-of-range DC coefficient value: %d "
135 "(from prev_dc %d abs_dc_coeff_diff %d sign_dc_coeff_diff %d)\n",
136 dc_coeff, state->prev_dc, abs_dc_coeff_diff, sign_dc_coeff_diff);
137 return AVERROR_INVALIDDATA;
138 }
139
140 coeff[0] = dc_coeff;
141
142 state->prev_dc = dc_coeff;
143 state->prev_k_dc = FFMIN(abs_dc_coeff_diff >> 1, 5);
144 }
145
146 // AC coefficients.
147 {
148 int scan_pos = 1;
149 int first_ac = 1;
150 int k_run = 0;
151 int k_level = state->prev_k_level;
152
153 do {
154 int coeff_zero_run;
155
156 coeff_zero_run = apv_read_vlc(gbc, k_run, lut);
157
158 if (coeff_zero_run > APV_BLK_COEFFS - scan_pos) {
159 av_log(state->log_ctx, AV_LOG_ERROR,
160 "Out-of-range zero-run value: %d (at scan pos %d)\n",
161 coeff_zero_run, scan_pos);
162 return AVERROR_INVALIDDATA;
163 }
164
165 for (int i = 0; i < coeff_zero_run; i++) {
166 coeff[ff_zigzag_direct[scan_pos]] = 0;
167 ++scan_pos;
168 }
169 k_run = FFMIN(coeff_zero_run >> 2, 2);
170
171 if (scan_pos < APV_BLK_COEFFS) {
172 int abs_ac_coeff_minus1;
173 int sign_ac_coeff;
174 int abs_level, level;
175
176 abs_ac_coeff_minus1 = apv_read_vlc(gbc, k_level, lut);
177 sign_ac_coeff = get_bits(gbc, 1);
178
179 abs_level = abs_ac_coeff_minus1 + 1;
180 if (sign_ac_coeff)
181 level = -abs_level;
182 else
183 level = abs_level;
184
187 av_log(state->log_ctx, AV_LOG_ERROR,
188 "Out-of-range AC coefficient value: %d "
189 "(from k_param %d abs_ac_coeff_minus1 %d sign_ac_coeff %d)\n",
190 level, k_level, abs_ac_coeff_minus1, sign_ac_coeff);
191 }
192
193 coeff[ff_zigzag_direct[scan_pos]] = level;
194
195 k_level = FFMIN(abs_level >> 2, 4);
196 if (first_ac) {
197 state->prev_k_level = k_level;
198 first_ac = 0;
199 }
200
201 ++scan_pos;
202 }
203
204 } while (scan_pos < APV_BLK_COEFFS);
205 }
206
207 return 0;
208}
209
210static void binary(char *buf, uint32_t value, int bits)
211{
212 for (int i = 0; i < bits; i++)
213 buf[i] = (value >> (bits - i - 1) & 1) ? '1' : '0';
214 buf[bits] = '\0';
215}
216
217static int test_apv_read_vlc(void)
218{
219 APVVLCLUT lut;
220 int err = 0;
221
223
224 // Generate all possible 20 bit sequences (padded with zeroes), then
225 // verify that spec and improved parsing functions get the same result
226 // and consume the same number of bits for each possible k_param.
227
228 for (int k = 0; k <= 5; k++) {
229 for (uint32_t b = 0; b < (1 << 20); b++) {
230 uint8_t buf[8] = {
231 b >> 12,
232 b >> 4,
233 b << 4,
234 0, 0, 0, 0, 0
235 };
236
237 GetBitContext gbc_test, gbc_spec;
238 unsigned int res_test, res_spec;
239 int con_test, con_spec;
240
241 init_get_bits8(&gbc_test, buf, 8);
242 init_get_bits8(&gbc_spec, buf, 8);
243
244 res_test = apv_read_vlc (&gbc_test, k, &lut);
245 res_spec = apv_read_vlc_spec(&gbc_spec, k);
246
247 con_test = get_bits_count(&gbc_test);
248 con_spec = get_bits_count(&gbc_spec);
249
250 if (res_test != res_spec ||
251 con_test != con_spec) {
252 char str[21];
253 binary(str, b, 20);
255 "Mismatch reading %s (%d) with k=%d:\n", str, b, k);
257 "Test function result %d consumed %d bits.\n",
258 res_test, con_test);
260 "Spec function result %d consumed %d bits.\n",
261 res_spec, con_spec);
262 ++err;
263 if (err > 10)
264 return err;
265 }
266 }
267 }
268
269 return err;
270}
271
272static int random_coeff(AVLFG *lfg)
273{
274 // Geometric distribution of code lengths (1-14 bits),
275 // uniform distribution within codes of the length,
276 // equal probability of either sign.
277 int length = (av_lfg_get(lfg) / (UINT_MAX / 14 + 1));
278 int random = av_lfg_get(lfg);
279 int value = (1 << length) + (random & (1 << length) - 1);
280 if (random & (1 << length))
281 return value;
282 else
283 return -value;
284}
285
286static int random_run(AVLFG *lfg)
287{
288 // Expoenential distribution of run lengths.
289 unsigned int random = av_lfg_get(lfg);
290 for (int len = 0;; len++) {
291 if (random & (1 << len))
292 return len;
293 }
294 // You rolled zero on a 2^32 sided die; well done!
295 return 64;
296}
297
299{
300 // Generate random entropy blocks, code them, then ensure they
301 // decode to the same block with both implementations.
302
303 APVVLCLUT decode_lut;
304 AVLFG lfg;
305 unsigned int seed = av_get_random_seed();
306 av_lfg_init(&lfg, seed);
307
308 av_log(NULL, AV_LOG_INFO, "seed = %u\n", seed);
309
311
312 for (int t = 0; t < 100; t++) {
313 APVEntropyState state, save_state;
314 int16_t block[64];
315 int16_t block_test1[64];
316 int16_t block_test2[64];
317 uint8_t buffer[1024];
318 PutBitContext pbc;
319 GetBitContext gbc;
320 int bits_written;
321 int pos, run, coeff, level, err;
322 int k_dc, k_run, k_level;
323
324 memset(block, 0, sizeof(block));
325 memset(buffer, 0, sizeof(buffer));
326 init_put_bits(&pbc, buffer, sizeof(buffer));
327
328 // Randomly-constructed state.
329 memset(&state, 0, sizeof(state));
330 state.decode_lut = &decode_lut;
331 state.prev_dc = random_coeff(&lfg);
332 state.prev_k_dc = av_lfg_get(&lfg) % 5;
333 state.prev_k_level = av_lfg_get(&lfg) % 4;
334 save_state = state;
335
336 k_dc = state.prev_k_dc;
337 k_run = 0;
338 k_level = state.prev_k_level;
339
340 coeff = random_coeff(&lfg) / 2;
341 block[ff_zigzag_direct[0]] = state.prev_dc + coeff;
342 apv_write_vlc_spec(&pbc, FFABS(coeff), k_dc);
343 if (coeff != 0)
344 put_bits(&pbc, 1, coeff < 0);
345
346 pos = 1;
347 while (pos < 64) {
348 run = random_run(&lfg);
349 if (pos + run > 64)
350 run = 64 - pos;
351 apv_write_vlc_spec(&pbc, run, k_run);
352 k_run = av_clip(run >> 2, 0, 2);
353 pos += run;
354 if (pos < 64) {
355 coeff = random_coeff(&lfg);
356 level = FFABS(coeff) - 1;
358 apv_write_vlc_spec(&pbc, level, k_level);
359 put_bits(&pbc, 1, coeff < 0);
360 k_level = av_clip((level + 1) >> 2, 0, 4);
361 ++pos;
362 }
363 }
364 bits_written = put_bits_count(&pbc);
365 flush_put_bits(&pbc);
366
367 // Fill output block with a distinctive error value.
368 for (int i = 0; i < 64; i++)
369 block_test1[i] = -9999;
370 init_get_bits8(&gbc, buffer, sizeof(buffer));
371
372 err = apv_entropy_decode_block(block_test1, &gbc, &state);
373 if (err < 0) {
374 av_log(NULL, AV_LOG_ERROR, "Entropy decode returned error.\n");
375 return 1;
376 } else {
377 int bits_read = get_bits_count(&gbc);
378 if (bits_written != bits_read) {
379 av_log(NULL, AV_LOG_ERROR, "Wrote %d bits but read %d.\n",
380 bits_written, bits_read);
381 return 1;
382 } else {
383 err = 0;
384 for (int i = 0; i < 64; i++) {
385 if (block[i] != block_test1[i])
386 ++err;
387 }
388 if (err > 0) {
389 av_log(NULL, AV_LOG_ERROR, "%d mismatches in output block.\n", err);
390 return err;
391 }
392 }
393 }
394
395 init_get_bits8(&gbc, buffer, sizeof(buffer));
396 memset(block_test2, 0, 64 * sizeof(int16_t));
397
398 err = ff_apv_entropy_decode_block(block_test2, &gbc, &save_state);
399 if (err < 0) {
400 av_log(NULL, AV_LOG_ERROR, "Entropy decode returned error.\n");
401 return 1;
402 } else {
403 int bits_read = get_bits_count(&gbc);
404 if (bits_written != bits_read) {
405 av_log(NULL, AV_LOG_ERROR, "Wrote %d bits but read %d.\n",
406 bits_written, bits_read);
407 return 1;
408 } else {
409 err = 0;
410 for (int i = 0; i < 64; i++) {
411 if (block[i] != block_test2[i])
412 ++err;
413 }
414 if (err > 0) {
415 av_log(NULL, AV_LOG_ERROR, "%d mismatches in output block.\n", err);
416 return err;
417 }
418 }
419 }
420
421 if (state.prev_dc != save_state.prev_dc ||
422 state.prev_k_dc != save_state.prev_k_dc ||
423 state.prev_k_level != save_state.prev_k_level) {
424 av_log(NULL, AV_LOG_ERROR, "Entropy state mismatch.\n");
425 return 1;
426 }
427 }
428
429 return 0;
430}
431
432int main(void)
433{
434 int err;
435
436 err = test_apv_read_vlc();
437 if (err) {
438 av_log(NULL, AV_LOG_ERROR, "Read VLC test failed.\n");
439 return err;
440 }
441
443 if (err) {
444 av_log(NULL, AV_LOG_ERROR, "Entropy decode block test failed.\n");
445 return err;
446 }
447
448 return 0;
449}
int ff_apv_entropy_decode_block(int16_t *restrict coeff, GetBitContext *restrict gbc, APVEntropyState *restrict state)
Entropy decode a single 8x8 block to coefficients.
void ff_apv_entropy_build_decode_lut(APVVLCLUT *decode_lut)
Build the decoder VLC look-up tables.
Definition apv_entropy.c:62
static av_always_inline unsigned int apv_read_vlc(GetBitContext *restrict gbc, int k_param, const APVVLCLUT *restrict lut)
Definition apv_entropy.c:26
#define bits_read
Definition bitstream.h:119
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define av_clip
Definition common.h:100
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition common.h:74
#define NULL
Definition coverity.c:32
static int16_t block[64]
Definition dct.c:125
double value
Definition eval.c:102
static struct @346255127015250356166251341105367306144006377143 state
static const uint8_t bits[8]
Definition fastaudio.c:100
static unsigned int get_bits1(GetBitContext *s)
Definition get_bits.h:391
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition get_bits.h:544
static int get_bits_count(const GetBitContext *s)
Definition get_bits.h:254
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition get_bits.h:337
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
#define b
Definition input.c:43
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
Definition j2kenc.c:154
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition lfg.c:32
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition lfg.h:53
@ APV_MIN_TRANS_COEFF
Definition apv.h:56
@ APV_MAX_TRANS_COEFF
Definition apv.h:57
@ APV_BLK_COEFFS
Definition apv.h:55
static int test_apv_read_vlc(void)
Definition apv.c:217
static void binary(char *buf, uint32_t value, int bits)
Definition apv.c:210
static int apv_entropy_decode_block(int16_t *restrict coeff, GetBitContext *restrict gbc, APVEntropyState *restrict state)
Definition apv.c:107
int main(void)
Definition apv.c:432
static int test_apv_entropy_decode_block(void)
Definition apv.c:298
static int random_run(AVLFG *lfg)
Definition apv.c:286
static unsigned int apv_read_vlc_spec(GetBitContext *gbc, int k_param)
Definition apv.c:36
static int random_coeff(AVLFG *lfg)
Definition apv.c:272
static void apv_write_vlc_spec(PutBitContext *pbc, unsigned int symbol_val, int k_param)
Definition apv.c:75
#define FFMIN(a, b)
Definition macros.h:49
const uint8_t ff_zigzag_direct[64]
Definition mathtables.c:137
bitstream writer API
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition put_bits.h:62
static int put_bits_count(PutBitContext *s)
Definition put_bits.h:90
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition put_bits.h:153
unsigned int pos
Definition spdifenc.c:431
int16_t prev_dc
Definition apv_decode.h:81
uint8_t prev_k_level
Definition apv_decode.h:85
uint8_t prev_k_dc
Definition apv_decode.h:83
Context structure for the Lagged Fibonacci PRNG.
Definition lfg.h:33
uint8_t run
Definition svq3.c:207
uint8_t level
Definition svq3.c:208
#define av_log(a,...)
static char buffer[20]
Definition seek.c:32
static const double coeff[2][5]
static unsigned int seed
Definition videogen.c:78
int len