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];
58  uint8_t dst[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 
65  /* generate random input, using a given or random seed */
66  if (argc > 1)
67  random_seed = strtoul(argv[1], NULL, 0);
68  else
69  random_seed = av_get_random_seed();
70 
71  fprintf(stderr, "Testing with LFG seed: %"PRIu32"\n", random_seed);
72  av_lfg_init(&lfg, random_seed);
73 
74  for (unsigned i = 0; i < SIZE; i++)
75  buf[i] = av_lfg_get(&lfg);
76 
77  bits_init8 (&bc, buf, SIZE);
78  init_put_bits(&pb, dst, SIZE);
79 
80  /* use a random sequence of bitreading operations to transfer data
81  * from BitstreamContext to PutBitContext */
82  while (bits_left(&bc) > 0) {
83  enum Op op = av_lfg_get(&lfg) % OP_NB;
84 
85  switch (op) {
86  case OP_READ:
87  count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1);
88  val1 = bits_peek(&bc, count);
89  val = bits_read(&bc, count);
90 
91  fprintf(stderr, "%d read %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val);
92 
93  av_assert0(val == val1);
94 
95  put_bits64(&pb, count, val);
96  break;
97  case OP_READ_NZ:
98  count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1);
99  count = FFMAX(count, 1);
100  val1 = bits_peek_nz(&bc, count);
101  val = bits_read_nz(&bc, count);
102 
103  fprintf(stderr, "%d read_nz %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val);
104 
105  av_assert0(val == val1);
106 
107  put_bits64(&pb, count, val);
108  break;
109  case OP_READ_BIT:
110  val = bits_read_bit(&bc);
111 
112  fprintf(stderr, "%d read_bit: %"PRIu64"\n", bits_tell(&bc) - 1, val);
113 
114  put_bits(&pb, 1, val);
115  break;
116  case OP_READ_63:
117  count = av_lfg_get(&lfg) % FFMIN(64, bits_left(&bc) + 1);
118  val = bits_read_63(&bc, count);
119 
120  fprintf(stderr, "%d read_63 %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val);
121 
122  put_bits64(&pb, count, val);
123  break;
124  case OP_READ_64:
125  count = av_lfg_get(&lfg) % FFMIN(65, bits_left(&bc) + 1);
126  val = bits_read_64(&bc, count);
127 
128  fprintf(stderr, "%d read_64 %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val);
129 
130  put_bits64(&pb, count, val);
131  break;
132  case OP_READ_SIGNED:
133  count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1);
134  sval1 = bits_peek_signed(&bc, count);
135  sval = bits_read_signed(&bc, count);
136 
137  fprintf(stderr, "%d read_signed %u: %"PRId32"\n", bits_tell(&bc) - count, count, sval);
138 
139  av_assert0(sval == sval1);
140 
141  if (count == 32) put_bits32(&pb, sval);
142  else put_sbits(&pb, count, sval);
143  break;
144  case OP_READ_SIGNED_NZ:
145  count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1);
146  count = FFMAX(count, 1);
147  sval1 = bits_peek_signed_nz(&bc, count);
148  sval = bits_read_signed_nz(&bc, count);
149 
150  fprintf(stderr, "%d read_signed_nz %u: %"PRId32"\n", bits_tell(&bc) - count, count, sval);
151 
152  av_assert0(sval == sval1);
153 
154  if (count == 32) put_bits32(&pb, sval);
155  else put_sbits(&pb, count, sval);
156  break;
157  case OP_ALIGN:
158  count = (bits_tell(&bc) + 7) / 8 * 8 - bits_tell(&bc);
159 
160  fprintf(stderr, "%d align %u\n", bits_tell(&bc), count);
161 
162  put_bits(&pb, count, bits_peek(&bc, count));
163  bits_align(&bc);
164  break;
165  case OP_APPLY_SIGN:
166  if (bits_left(&bc) < 2)
167  continue;
168 
169  count = av_lfg_get(&lfg) % FFMIN(32, bits_left(&bc));
170  count = FFMAX(count, 1);
171 
172  if (!bits_peek(&bc, count))
173  continue;
174 
175  val = bits_read(&bc, count);
176  sval = bits_apply_sign(&bc, val);
177 
178  fprintf(stderr, "%d apply_sign %u %"PRId32"\n",
179  bits_tell(&bc) - count - 1, count, sval);
180 
181  put_bits64(&pb, count, FFABS(sval));
182  put_bits(&pb, 1, sval < 0);
183 
184  break;
185  default:
186  av_assert0(0);
187  }
188  }
189 
190  flush_put_bits(&pb);
191 
192  for (unsigned i = 0; i < SIZE; i++)
193  if (buf[i] != dst[i]) {
194  fprintf(stderr, "Mismatch at byte %u: %hhu %hhu; seed %"PRIu32"\n",
195  i, buf[i], dst[i], random_seed);
196  return 1;
197  }
198 
199  return 0;
200 }
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:222
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:78
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:72
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
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:255
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
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