FFmpeg
bitstream_template.c
Go to the documentation of this file.
1 /*
2  * cached bitstream reader test
3  * copyright (c) 2022 Anton Khirnov <anton@khirnov.net>
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 #define ASSERT_LEVEL 2
23 
24 #include "libavutil/avassert.h"
25 #include "libavutil/lfg.h"
26 #include "libavutil/random_seed.h"
27 
28 #include "libavcodec/bitstream.h"
29 #include "libavcodec/defs.h"
30 
31 #ifdef BITSTREAM_LE
32 #define BITSTREAM_WRITER_LE
33 #endif
34 #include "libavcodec/put_bits.h"
35 
36 #define SIZE 157
37 
38 enum Op {
49 };
50 
51 int main(int argc, char **argv)
52 {
54  PutBitContext pb;
55  AVLFG lfg;
56 
57  uint8_t buf[SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
59 
60  uint32_t random_seed;
61  uint64_t val, val1;
62  int32_t sval, sval1;
63  unsigned count;
64  int ret;
65 
66  /* generate random input, using a given or random seed */
67  if (argc > 1)
68  random_seed = strtoul(argv[1], NULL, 0);
69  else
70  random_seed = av_get_random_seed();
71 
72  fprintf(stderr, "Testing with LFG seed: %"PRIu32"\n", random_seed);
73  av_lfg_init(&lfg, random_seed);
74 
75  for (unsigned i = 0; i < SIZE; i++)
76  buf[i] = av_lfg_get(&lfg);
77 
78  ret = bits_init8 (&bc, buf, SIZE);
79  av_assert0(ret >= 0);
80  init_put_bits(&pb, dst, SIZE);
81 
82  /* use a random sequence of bitreading operations to transfer data
83  * from BitstreamContext to PutBitContext */
84  while (bits_left(&bc) > 0) {
85  enum Op op = av_lfg_get(&lfg) % OP_NB;
86 
87  switch (op) {
88  case OP_READ:
89  count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1);
90  val1 = bits_peek(&bc, count);
91  val = bits_read(&bc, count);
92 
93  fprintf(stderr, "%d read %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val);
94 
95  av_assert0(val == val1);
96 
97  put_bits64(&pb, count, val);
98  break;
99  case OP_READ_NZ:
100  count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1);
101  count = FFMAX(count, 1);
102  val1 = bits_peek_nz(&bc, count);
103  val = bits_read_nz(&bc, count);
104 
105  fprintf(stderr, "%d read_nz %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val);
106 
107  av_assert0(val == val1);
108 
109  put_bits64(&pb, count, val);
110  break;
111  case OP_READ_BIT:
112  val = bits_read_bit(&bc);
113 
114  fprintf(stderr, "%d read_bit: %"PRIu64"\n", bits_tell(&bc) - 1, val);
115 
116  put_bits(&pb, 1, val);
117  break;
118  case OP_READ_63:
119  count = av_lfg_get(&lfg) % FFMIN(64, bits_left(&bc) + 1);
120  val = bits_read_63(&bc, count);
121 
122  fprintf(stderr, "%d read_63 %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val);
123 
124  put_bits64(&pb, count, val);
125  break;
126  case OP_READ_64:
127  count = av_lfg_get(&lfg) % FFMIN(65, bits_left(&bc) + 1);
128  val = bits_read_64(&bc, count);
129 
130  fprintf(stderr, "%d read_64 %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val);
131 
132  put_bits64(&pb, count, val);
133  break;
134  case OP_READ_SIGNED:
135  count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1);
136  sval1 = bits_peek_signed(&bc, count);
137  sval = bits_read_signed(&bc, count);
138 
139  fprintf(stderr, "%d read_signed %u: %"PRId32"\n", bits_tell(&bc) - count, count, sval);
140 
141  av_assert0(sval == sval1);
142 
143  if (count == 32) put_bits32(&pb, sval);
144  else put_sbits(&pb, count, sval);
145  break;
146  case OP_READ_SIGNED_NZ:
147  count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1);
148  count = FFMAX(count, 1);
149  sval1 = bits_peek_signed_nz(&bc, count);
150  sval = bits_read_signed_nz(&bc, count);
151 
152  fprintf(stderr, "%d read_signed_nz %u: %"PRId32"\n", bits_tell(&bc) - count, count, sval);
153 
154  av_assert0(sval == sval1);
155 
156  if (count == 32) put_bits32(&pb, sval);
157  else put_sbits(&pb, count, sval);
158  break;
159  case OP_ALIGN:
160  count = (bits_tell(&bc) + 7) / 8 * 8 - bits_tell(&bc);
161 
162  fprintf(stderr, "%d align %u\n", bits_tell(&bc), count);
163 
164  put_bits(&pb, count, bits_peek(&bc, count));
165  bits_align(&bc);
166  break;
167  case OP_APPLY_SIGN:
168  if (bits_left(&bc) < 2)
169  continue;
170 
171  count = av_lfg_get(&lfg) % FFMIN(32, bits_left(&bc));
172  count = FFMAX(count, 1);
173 
174  if (!bits_peek(&bc, count))
175  continue;
176 
177  val = bits_read(&bc, count);
178  sval = bits_apply_sign(&bc, val);
179 
180  fprintf(stderr, "%d apply_sign %u %"PRId32"\n",
181  bits_tell(&bc) - count - 1, count, sval);
182 
183  put_bits64(&pb, count, FFABS(sval));
184  put_bits(&pb, 1, sval < 0);
185 
186  break;
187  default:
188  av_assert0(0);
189  }
190  }
191 
192  flush_put_bits(&pb);
193 
194  for (unsigned i = 0; i < SIZE; i++)
195  if (buf[i] != dst[i]) {
196  fprintf(stderr, "Mismatch at byte %u: %hhu %hhu; seed %"PRIu32"\n",
197  i, buf[i], dst[i], random_seed);
198  return 1;
199  }
200 
201  return 0;
202 }
put_bits32
static void av_unused put_bits32(PutBitContext *s, uint32_t value)
Write exactly 32 bits into a bitstream.
Definition: put_bits.h:291
bits_read_nz
#define bits_read_nz
Definition: bitstream.h:116
bits_read_63
#define bits_read_63
Definition: bitstream.h:118
av_lfg_init
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:32
OP_READ
@ OP_READ
Definition: bitstream_template.c:39
put_sbits
static void put_sbits(PutBitContext *pb, int n, int32_t value)
Definition: put_bits.h:281
init_put_bits
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition: put_bits.h:62
bits_peek
#define bits_peek
Definition: bitstream.h:123
put_bits
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
Definition: j2kenc.c:223
bits_read_signed_nz
#define bits_read_signed_nz
Definition: bitstream.h:121
put_bits64
static void put_bits64(PutBitContext *s, int n, uint64_t value)
Write up to 64 bits into a bitstream.
Definition: put_bits.h:334
bits_read
#define bits_read
Definition: bitstream.h:117
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
OP_READ_63
@ OP_READ_63
Definition: bitstream_template.c:42
bits_peek_signed_nz
#define bits_peek_signed_nz
Definition: bitstream.h:125
bits_read_bit
#define bits_read_bit
Definition: bitstream.h:115
bits_apply_sign
#define bits_apply_sign
Definition: bitstream.h:132
OP_READ_64
@ OP_READ_64
Definition: bitstream_template.c:43
OP_READ_NZ
@ OP_READ_NZ
Definition: bitstream_template.c:40
av_get_random_seed
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
Definition: random_seed.c:167
val
static double val(void *priv, double ch)
Definition: aeval.c:77
BitstreamContext
#define BitstreamContext
Definition: bitstream.h:109
avassert.h
av_lfg_get
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:53
op
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
Definition: anm.c:76
lfg.h
OP_APPLY_SIGN
@ OP_APPLY_SIGN
Definition: bitstream_template.c:46
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
OP_NB
@ OP_NB
Definition: bitstream_template.c:48
PutBitContext
Definition: put_bits.h:50
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:74
NULL
#define NULL
Definition: coverity.c:32
bits_left
#define bits_left
Definition: bitstream.h:114
OP_READ_BIT
@ OP_READ_BIT
Definition: bitstream_template.c:41
OP_ALIGN
@ OP_ALIGN
Definition: bitstream_template.c:47
AVLFG
Context structure for the Lagged Fibonacci PRNG.
Definition: lfg.h:33
Op
Op
Definition: bitstream_template.c:38
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
SIZE
#define SIZE
Definition: bitstream_template.c:36
bits_peek_nz
#define bits_peek_nz
Definition: bitstream.h:122
OP_READ_SIGNED
@ OP_READ_SIGNED
Definition: bitstream_template.c:44
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
OP_READ_SIGNED_NZ
@ OP_READ_SIGNED_NZ
Definition: bitstream_template.c:45
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
bitstream.h
bits_read_signed
#define bits_read_signed
Definition: bitstream.h:120
ret
ret
Definition: filter_design.txt:187
bits_read_64
#define bits_read_64
Definition: bitstream.h:119
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
random_seed.h
bits_tell
#define bits_tell
Definition: bitstream.h:112
defs.h
bits_peek_signed
#define bits_peek_signed
Definition: bitstream.h:124
flush_put_bits
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition: put_bits.h:143
bits_align
#define bits_align
Definition: bitstream.h:128
int32_t
int32_t
Definition: audioconvert.c:56
bits_init8
#define bits_init8
Definition: bitstream.h:111
put_bits.h
main
int main(int argc, char **argv)
Definition: bitstream_template.c:51