Coverage Report

Created: 2026-01-25 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/put_bits.h
Line
Count
Source
1
/*
2
 * copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
/**
22
 * @file
23
 * bitstream writer API
24
 */
25
26
#ifndef AVCODEC_PUT_BITS_H
27
#define AVCODEC_PUT_BITS_H
28
29
#include <stdint.h>
30
#include <stddef.h>
31
32
#include "config.h"
33
#include "libavutil/intreadwrite.h"
34
#include "libavutil/avassert.h"
35
#include "libavutil/common.h"
36
37
#if ARCH_X86_64
38
// TODO: Benchmark and optionally enable on other 64-bit architectures.
39
typedef uint64_t BitBuf;
40
0
#define AV_WBBUF AV_WB64
41
#define AV_WLBUF AV_WL64
42
0
#define BUF_BITS 64
43
#else
44
typedef uint32_t BitBuf;
45
#define AV_WBBUF AV_WB32
46
#define AV_WLBUF AV_WL32
47
#define BUF_BITS 32
48
#endif
49
50
typedef struct PutBitContext {
51
    BitBuf bit_buf;
52
    int bit_left;
53
    uint8_t *buf, *buf_ptr, *buf_end;
54
} PutBitContext;
55
56
/**
57
 * Initialize the PutBitContext s.
58
 *
59
 * @param buffer the buffer where to put bits
60
 * @param buffer_size the size in bytes of buffer
61
 */
62
static inline void init_put_bits(PutBitContext *s, uint8_t *buffer,
63
                                 int buffer_size)
64
0
{
65
0
    if (buffer_size < 0) {
66
0
        buffer_size = 0;
67
0
        buffer      = NULL;
68
0
    }
69
70
0
    s->buf          = buffer;
71
0
    s->buf_end      = s->buf + buffer_size;
72
0
    s->buf_ptr      = s->buf;
73
0
    s->bit_left     = BUF_BITS;
74
0
    s->bit_buf      = 0;
75
0
}
76
77
/**
78
 * Inform the compiler that a PutBitContext is flushed (i.e. if it has just
79
 * been initialized or flushed). Undefined behaviour occurs if this is used
80
 * with a PutBitContext for which this is not true.
81
 */
82
static inline void put_bits_assume_flushed(const PutBitContext *s)
83
0
{
84
0
    av_assume(s->bit_left == BUF_BITS);
85
0
}
86
87
/**
88
 * @return the total number of bits written to the bitstream.
89
 */
90
static inline int put_bits_count(PutBitContext *s)
91
0
{
92
0
    return (s->buf_ptr - s->buf) * 8 + BUF_BITS - s->bit_left;
93
0
}
94
95
/**
96
 * @return the number of bytes output so far; may only be called
97
 *         when the PutBitContext is freshly initialized or flushed.
98
 */
99
static inline int put_bytes_output(const PutBitContext *s)
100
0
{
101
0
    av_assert2(s->bit_left == BUF_BITS);
102
0
    return s->buf_ptr - s->buf;
103
0
}
104
105
/**
106
 * @param  round_up  When set, the number of bits written so far will be
107
 *                   rounded up to the next byte.
108
 * @return the number of bytes output so far.
109
 */
110
static inline int put_bytes_count(const PutBitContext *s, int round_up)
111
0
{
112
0
    return s->buf_ptr - s->buf + ((BUF_BITS - s->bit_left + (round_up ? 7 : 0)) >> 3);
113
0
}
114
115
/**
116
 * Rebase the bit writer onto a reallocated buffer.
117
 *
118
 * @param buffer the buffer where to put bits
119
 * @param buffer_size the size in bytes of buffer,
120
 *                    must be large enough to hold everything written so far
121
 */
122
static inline void rebase_put_bits(PutBitContext *s, uint8_t *buffer,
123
                                   int buffer_size)
124
0
{
125
0
    av_assert0(8*buffer_size >= put_bits_count(s));
126
0
127
0
    s->buf_end = buffer + buffer_size;
128
0
    s->buf_ptr = buffer + (s->buf_ptr - s->buf);
129
0
    s->buf     = buffer;
130
0
}
131
132
/**
133
 * @return the number of bits available in the bitstream.
134
 */
135
static inline int put_bits_left(PutBitContext* s)
136
0
{
137
0
    return (s->buf_end - s->buf_ptr) * 8 - BUF_BITS + s->bit_left;
138
0
}
139
140
/**
141
 * @param  round_up  When set, the number of bits written will be
142
 *                   rounded up to the next byte.
143
 * @return the number of bytes left.
144
 */
145
static inline int put_bytes_left(const PutBitContext *s, int round_up)
146
0
{
147
0
    return s->buf_end - s->buf_ptr - ((BUF_BITS - s->bit_left + (round_up ? 7 : 0)) >> 3);
148
0
}
149
150
/**
151
 * Pad the end of the output stream with zeros.
152
 */
153
static inline void flush_put_bits(PutBitContext *s)
154
0
{
155
0
#ifndef BITSTREAM_WRITER_LE
156
0
    if (s->bit_left < BUF_BITS)
157
0
        s->bit_buf <<= s->bit_left;
158
0
#endif
159
0
    while (s->bit_left < BUF_BITS) {
160
0
        av_assert0(s->buf_ptr < s->buf_end);
161
#ifdef BITSTREAM_WRITER_LE
162
        *s->buf_ptr++ = s->bit_buf;
163
        s->bit_buf  >>= 8;
164
#else
165
0
        *s->buf_ptr++ = s->bit_buf >> (BUF_BITS - 8);
166
0
        s->bit_buf  <<= 8;
167
0
#endif
168
0
        s->bit_left  += 8;
169
0
    }
170
0
    s->bit_left = BUF_BITS;
171
0
    s->bit_buf  = 0;
172
0
}
173
174
static inline void flush_put_bits_le(PutBitContext *s)
175
0
{
176
0
    while (s->bit_left < BUF_BITS) {
177
0
        av_assert0(s->buf_ptr < s->buf_end);
178
0
        *s->buf_ptr++ = s->bit_buf;
179
0
        s->bit_buf  >>= 8;
180
0
        s->bit_left  += 8;
181
0
    }
182
0
    s->bit_left = BUF_BITS;
183
0
    s->bit_buf  = 0;
184
0
}
185
186
#ifdef BITSTREAM_WRITER_LE
187
#define ff_put_string ff_put_string_unsupported_here
188
#define ff_copy_bits ff_copy_bits_unsupported_here
189
#else
190
191
/**
192
 * Put the string string in the bitstream.
193
 *
194
 * @param terminate_string 0-terminates the written string if value is 1
195
 */
196
void ff_put_string(PutBitContext *pb, const char *string,
197
                       int terminate_string);
198
199
/**
200
 * Copy the content of src to the bitstream.
201
 *
202
 * @param length the number of bits of src to copy
203
 */
204
void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length);
205
#endif
206
207
static inline void put_bits_no_assert(PutBitContext *s, int n, BitBuf value)
208
0
{
209
0
    BitBuf bit_buf;
210
0
    int bit_left;
211
212
0
    bit_buf  = s->bit_buf;
213
0
    bit_left = s->bit_left;
214
215
    /* XXX: optimize */
216
#ifdef BITSTREAM_WRITER_LE
217
    bit_buf |= value << (BUF_BITS - bit_left);
218
    if (n >= bit_left) {
219
        if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
220
            AV_WLBUF(s->buf_ptr, bit_buf);
221
            s->buf_ptr += sizeof(BitBuf);
222
        } else {
223
            av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
224
            av_assert2(0);
225
        }
226
        bit_buf     = value >> bit_left;
227
        bit_left   += BUF_BITS;
228
    }
229
    bit_left -= n;
230
#else
231
0
    if (n < bit_left) {
232
0
        bit_buf     = (bit_buf << n) | value;
233
0
        bit_left   -= n;
234
0
    } else {
235
0
        bit_buf   <<= bit_left;
236
0
        bit_buf    |= value >> (n - bit_left);
237
0
        if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
238
0
            AV_WBBUF(s->buf_ptr, bit_buf);
239
0
            s->buf_ptr += sizeof(BitBuf);
240
0
        } else {
241
0
            av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
242
0
            av_assert2(0);
243
0
        }
244
0
        bit_left   += BUF_BITS - n;
245
0
        bit_buf     = value;
246
0
    }
247
0
#endif
248
249
0
    s->bit_buf  = bit_buf;
250
0
    s->bit_left = bit_left;
251
0
}
252
253
/**
254
 * Write up to 31 bits into a bitstream.
255
 * Use put_bits32 to write 32 bits.
256
 */
257
static inline void put_bits(PutBitContext *s, int n, BitBuf value)
258
0
{
259
0
    av_assert2(n <= 31 && value < (BitBuf)(1U << n));
260
0
    put_bits_no_assert(s, n, value);
261
0
}
262
263
static inline void put_bits_le(PutBitContext *s, int n, BitBuf value)
264
0
{
265
0
    BitBuf bit_buf;
266
0
    int bit_left;
267
0
268
0
    av_assert2(n <= 31 && value < (BitBuf)(1U << n));
269
0
270
0
    bit_buf  = s->bit_buf;
271
0
    bit_left = s->bit_left;
272
0
273
0
    bit_buf |= value << (BUF_BITS - bit_left);
274
0
    if (n >= bit_left) {
275
0
        if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
276
0
            AV_WLBUF(s->buf_ptr, bit_buf);
277
0
            s->buf_ptr += sizeof(BitBuf);
278
0
        } else {
279
0
            av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
280
0
            av_assert2(0);
281
0
        }
282
0
        bit_buf     = value >> bit_left;
283
0
        bit_left   += BUF_BITS;
284
0
    }
285
0
    bit_left -= n;
286
0
287
0
    s->bit_buf  = bit_buf;
288
0
    s->bit_left = bit_left;
289
0
}
290
291
static inline void put_sbits(PutBitContext *pb, int n, int32_t value)
292
0
{
293
0
    av_assert2(n >= 0 && n <= 31);
294
0
295
0
    put_bits(pb, n, av_zero_extend(value, n));
296
0
}
297
298
/**
299
 * Write exactly 32 bits into a bitstream.
300
 */
301
av_unused static void put_bits32(PutBitContext *s, uint32_t value)
302
0
{
303
0
    BitBuf bit_buf;
304
0
    int bit_left;
305
0
306
0
    if (BUF_BITS > 32) {
307
0
        put_bits_no_assert(s, 32, value);
308
0
        return;
309
0
    }
310
0
311
0
    bit_buf  = s->bit_buf;
312
0
    bit_left = s->bit_left;
313
0
314
0
#ifdef BITSTREAM_WRITER_LE
315
0
    bit_buf |= (BitBuf)value << (BUF_BITS - bit_left);
316
0
    if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
317
0
        AV_WLBUF(s->buf_ptr, bit_buf);
318
0
        s->buf_ptr += sizeof(BitBuf);
319
0
    } else {
320
0
        av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
321
0
        av_assert2(0);
322
0
    }
323
0
    bit_buf     = (uint64_t)value >> bit_left;
324
0
#else
325
0
    bit_buf     = (uint64_t)bit_buf << bit_left;
326
0
    bit_buf    |= (BitBuf)value >> (BUF_BITS - bit_left);
327
0
    if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
328
0
        AV_WBBUF(s->buf_ptr, bit_buf);
329
0
        s->buf_ptr += sizeof(BitBuf);
330
0
    } else {
331
0
        av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
332
0
        av_assert2(0);
333
0
    }
334
0
    bit_buf     = value;
335
0
#endif
336
0
337
0
    s->bit_buf  = bit_buf;
338
0
    s->bit_left = bit_left;
339
0
}
340
341
/**
342
 * Write up to 63 bits into a bitstream.
343
 */
344
static inline void put_bits63(PutBitContext *s, int n, uint64_t value)
345
0
{
346
0
    av_assert2(n < 64U && value < (UINT64_C(1) << n));
347
0
348
0
#if BUF_BITS >= 64
349
0
    put_bits_no_assert(s, n, value);
350
0
#else
351
0
    if (n < 32)
352
0
        put_bits(s, n, value);
353
0
    else if (n == 32)
354
0
        put_bits32(s, value);
355
0
    else if (n < 64) {
356
0
        uint32_t lo = value & 0xffffffff;
357
0
        uint32_t hi = value >> 32;
358
0
#ifdef BITSTREAM_WRITER_LE
359
0
        put_bits32(s, lo);
360
0
        put_bits(s, n - 32, hi);
361
0
#else
362
0
        put_bits(s, n - 32, hi);
363
0
        put_bits32(s, lo);
364
0
#endif
365
0
    }
366
0
#endif
367
0
}
368
369
/**
370
 * Write up to 64 bits into a bitstream.
371
 */
372
static inline void put_bits64(PutBitContext *s, int n, uint64_t value)
373
0
{
374
0
    av_assert2((n == 64) || (n < 64 && value < (UINT64_C(1) << n)));
375
0
376
0
    if (n < 64) {
377
0
        put_bits63(s, n, value);
378
0
    } else {
379
0
        uint32_t lo = value & 0xffffffff;
380
0
        uint32_t hi = value >> 32;
381
0
#ifdef BITSTREAM_WRITER_LE
382
0
        put_bits32(s, lo);
383
0
        put_bits32(s, hi);
384
0
#else
385
0
        put_bits32(s, hi);
386
0
        put_bits32(s, lo);
387
0
#endif
388
0
    }
389
0
}
390
391
static inline void put_sbits63(PutBitContext *pb, int n, int64_t value)
392
0
{
393
0
    av_assert2(n >= 0 && n < 64);
394
0
395
0
    put_bits63(pb, n, (uint64_t)(value) & (~(UINT64_MAX << n)));
396
0
}
397
398
/**
399
 * Return the pointer to the byte where the bitstream writer will put
400
 * the next bit.
401
 */
402
static inline uint8_t *put_bits_ptr(PutBitContext *s)
403
0
{
404
0
    return s->buf_ptr;
405
0
}
406
407
/**
408
 * Skip the given number of bytes.
409
 * PutBitContext must be flushed & aligned to a byte boundary before calling this.
410
 */
411
static inline void skip_put_bytes(PutBitContext *s, int n)
412
0
{
413
0
    av_assert2((put_bits_count(s) & 7) == 0);
414
0
    av_assert2(s->bit_left == BUF_BITS);
415
0
    av_assert0(n <= s->buf_end - s->buf_ptr);
416
0
    s->buf_ptr += n;
417
0
}
418
419
/**
420
 * Skip the given number of bits.
421
 * Must only be used if the actual values in the bitstream do not matter.
422
 * If n is < 0 the behavior is undefined.
423
 */
424
static inline void skip_put_bits(PutBitContext *s, int n)
425
0
{
426
0
    unsigned bits = BUF_BITS - s->bit_left + n;
427
0
    s->buf_ptr += sizeof(BitBuf) * (bits / BUF_BITS);
428
0
    s->bit_left = BUF_BITS - (bits & (BUF_BITS - 1));
429
0
}
430
431
/**
432
 * Change the end of the buffer.
433
 *
434
 * @param size the new size in bytes of the buffer where to put bits
435
 */
436
static inline void set_put_bits_buffer_size(PutBitContext *s, int size)
437
0
{
438
0
    av_assert0(size <= INT_MAX/8 - BUF_BITS);
439
0
    s->buf_end = s->buf + size;
440
0
}
441
442
/**
443
 * Pad the bitstream with zeros up to the next byte boundary.
444
 */
445
static inline void align_put_bits(PutBitContext *s)
446
0
{
447
0
    put_bits(s, s->bit_left & 7, 0);
448
0
}
449
450
#undef AV_WBBUF
451
#undef AV_WLBUF
452
453
#endif /* AVCODEC_PUT_BITS_H */