xref: /third_party/ffmpeg/libavcodec/put_bits.h (revision cabdff1a)
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.
39typedef uint64_t BitBuf;
40#define AV_WBBUF AV_WB64
41#define AV_WLBUF AV_WL64
42#else
43typedef uint32_t BitBuf;
44#define AV_WBBUF AV_WB32
45#define AV_WLBUF AV_WL32
46#endif
47
48static const int BUF_BITS = 8 * sizeof(BitBuf);
49
50typedef 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 */
62static inline void init_put_bits(PutBitContext *s, uint8_t *buffer,
63                                 int buffer_size)
64{
65    if (buffer_size < 0) {
66        buffer_size = 0;
67        buffer      = NULL;
68    }
69
70    s->buf          = buffer;
71    s->buf_end      = s->buf + buffer_size;
72    s->buf_ptr      = s->buf;
73    s->bit_left     = BUF_BITS;
74    s->bit_buf      = 0;
75}
76
77/**
78 * @return the total number of bits written to the bitstream.
79 */
80static inline int put_bits_count(PutBitContext *s)
81{
82    return (s->buf_ptr - s->buf) * 8 + BUF_BITS - s->bit_left;
83}
84
85/**
86 * @return the number of bytes output so far; may only be called
87 *         when the PutBitContext is freshly initialized or flushed.
88 */
89static inline int put_bytes_output(const PutBitContext *s)
90{
91    av_assert2(s->bit_left == BUF_BITS);
92    return s->buf_ptr - s->buf;
93}
94
95/**
96 * @param  round_up  When set, the number of bits written so far will be
97 *                   rounded up to the next byte.
98 * @return the number of bytes output so far.
99 */
100static inline int put_bytes_count(const PutBitContext *s, int round_up)
101{
102    return s->buf_ptr - s->buf + ((BUF_BITS - s->bit_left + (round_up ? 7 : 0)) >> 3);
103}
104
105/**
106 * Rebase the bit writer onto a reallocated buffer.
107 *
108 * @param buffer the buffer where to put bits
109 * @param buffer_size the size in bytes of buffer,
110 *                    must be large enough to hold everything written so far
111 */
112static inline void rebase_put_bits(PutBitContext *s, uint8_t *buffer,
113                                   int buffer_size)
114{
115    av_assert0(8*buffer_size >= put_bits_count(s));
116
117    s->buf_end = buffer + buffer_size;
118    s->buf_ptr = buffer + (s->buf_ptr - s->buf);
119    s->buf     = buffer;
120}
121
122/**
123 * @return the number of bits available in the bitstream.
124 */
125static inline int put_bits_left(PutBitContext* s)
126{
127    return (s->buf_end - s->buf_ptr) * 8 - BUF_BITS + s->bit_left;
128}
129
130/**
131 * @param  round_up  When set, the number of bits written will be
132 *                   rounded up to the next byte.
133 * @return the number of bytes left.
134 */
135static inline int put_bytes_left(const PutBitContext *s, int round_up)
136{
137    return s->buf_end - s->buf_ptr - ((BUF_BITS - s->bit_left + (round_up ? 7 : 0)) >> 3);
138}
139
140/**
141 * Pad the end of the output stream with zeros.
142 */
143static inline void flush_put_bits(PutBitContext *s)
144{
145#ifndef BITSTREAM_WRITER_LE
146    if (s->bit_left < BUF_BITS)
147        s->bit_buf <<= s->bit_left;
148#endif
149    while (s->bit_left < BUF_BITS) {
150        av_assert0(s->buf_ptr < s->buf_end);
151#ifdef BITSTREAM_WRITER_LE
152        *s->buf_ptr++ = s->bit_buf;
153        s->bit_buf  >>= 8;
154#else
155        *s->buf_ptr++ = s->bit_buf >> (BUF_BITS - 8);
156        s->bit_buf  <<= 8;
157#endif
158        s->bit_left  += 8;
159    }
160    s->bit_left = BUF_BITS;
161    s->bit_buf  = 0;
162}
163
164static inline void flush_put_bits_le(PutBitContext *s)
165{
166    while (s->bit_left < BUF_BITS) {
167        av_assert0(s->buf_ptr < s->buf_end);
168        *s->buf_ptr++ = s->bit_buf;
169        s->bit_buf  >>= 8;
170        s->bit_left  += 8;
171    }
172    s->bit_left = BUF_BITS;
173    s->bit_buf  = 0;
174}
175
176#ifdef BITSTREAM_WRITER_LE
177#define ff_put_string ff_put_string_unsupported_here
178#define ff_copy_bits ff_copy_bits_unsupported_here
179#else
180
181/**
182 * Put the string string in the bitstream.
183 *
184 * @param terminate_string 0-terminates the written string if value is 1
185 */
186void ff_put_string(PutBitContext *pb, const char *string,
187                       int terminate_string);
188
189/**
190 * Copy the content of src to the bitstream.
191 *
192 * @param length the number of bits of src to copy
193 */
194void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length);
195#endif
196
197static inline void put_bits_no_assert(PutBitContext *s, int n, BitBuf value)
198{
199    BitBuf bit_buf;
200    int bit_left;
201
202    bit_buf  = s->bit_buf;
203    bit_left = s->bit_left;
204
205    /* XXX: optimize */
206#ifdef BITSTREAM_WRITER_LE
207    bit_buf |= value << (BUF_BITS - bit_left);
208    if (n >= bit_left) {
209        if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
210            AV_WLBUF(s->buf_ptr, bit_buf);
211            s->buf_ptr += sizeof(BitBuf);
212        } else {
213            av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
214            av_assert2(0);
215        }
216        bit_buf     = value >> bit_left;
217        bit_left   += BUF_BITS;
218    }
219    bit_left -= n;
220#else
221    if (n < bit_left) {
222        bit_buf     = (bit_buf << n) | value;
223        bit_left   -= n;
224    } else {
225        bit_buf   <<= bit_left;
226        bit_buf    |= value >> (n - bit_left);
227        if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
228            AV_WBBUF(s->buf_ptr, bit_buf);
229            s->buf_ptr += sizeof(BitBuf);
230        } else {
231            av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
232            av_assert2(0);
233        }
234        bit_left   += BUF_BITS - n;
235        bit_buf     = value;
236    }
237#endif
238
239    s->bit_buf  = bit_buf;
240    s->bit_left = bit_left;
241}
242
243/**
244 * Write up to 31 bits into a bitstream.
245 * Use put_bits32 to write 32 bits.
246 */
247static inline void put_bits(PutBitContext *s, int n, BitBuf value)
248{
249    av_assert2(n <= 31 && value < (1UL << n));
250    put_bits_no_assert(s, n, value);
251}
252
253static inline void put_bits_le(PutBitContext *s, int n, BitBuf value)
254{
255    BitBuf bit_buf;
256    int bit_left;
257
258    av_assert2(n <= 31 && value < (1UL << n));
259
260    bit_buf  = s->bit_buf;
261    bit_left = s->bit_left;
262
263    bit_buf |= value << (BUF_BITS - bit_left);
264    if (n >= bit_left) {
265        if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
266            AV_WLBUF(s->buf_ptr, bit_buf);
267            s->buf_ptr += sizeof(BitBuf);
268        } else {
269            av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
270            av_assert2(0);
271        }
272        bit_buf     = value >> bit_left;
273        bit_left   += BUF_BITS;
274    }
275    bit_left -= n;
276
277    s->bit_buf  = bit_buf;
278    s->bit_left = bit_left;
279}
280
281static inline void put_sbits(PutBitContext *pb, int n, int32_t value)
282{
283    av_assert2(n >= 0 && n <= 31);
284
285    put_bits(pb, n, av_mod_uintp2(value, n));
286}
287
288/**
289 * Write exactly 32 bits into a bitstream.
290 */
291static void av_unused put_bits32(PutBitContext *s, uint32_t value)
292{
293    BitBuf bit_buf;
294    int bit_left;
295
296    if (BUF_BITS > 32) {
297        put_bits_no_assert(s, 32, value);
298        return;
299    }
300
301    bit_buf  = s->bit_buf;
302    bit_left = s->bit_left;
303
304#ifdef BITSTREAM_WRITER_LE
305    bit_buf |= (BitBuf)value << (BUF_BITS - bit_left);
306    if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
307        AV_WLBUF(s->buf_ptr, bit_buf);
308        s->buf_ptr += sizeof(BitBuf);
309    } else {
310        av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
311        av_assert2(0);
312    }
313    bit_buf     = (uint64_t)value >> bit_left;
314#else
315    bit_buf     = (uint64_t)bit_buf << bit_left;
316    bit_buf    |= (BitBuf)value >> (BUF_BITS - bit_left);
317    if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) {
318        AV_WBBUF(s->buf_ptr, bit_buf);
319        s->buf_ptr += sizeof(BitBuf);
320    } else {
321        av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n");
322        av_assert2(0);
323    }
324    bit_buf     = value;
325#endif
326
327    s->bit_buf  = bit_buf;
328    s->bit_left = bit_left;
329}
330
331/**
332 * Write up to 64 bits into a bitstream.
333 */
334static inline void put_bits64(PutBitContext *s, int n, uint64_t value)
335{
336    av_assert2((n == 64) || (n < 64 && value < (UINT64_C(1) << n)));
337
338    if (n < 32)
339        put_bits(s, n, value);
340    else if (n == 32)
341        put_bits32(s, value);
342    else if (n < 64) {
343        uint32_t lo = value & 0xffffffff;
344        uint32_t hi = value >> 32;
345#ifdef BITSTREAM_WRITER_LE
346        put_bits32(s, lo);
347        put_bits(s, n - 32, hi);
348#else
349        put_bits(s, n - 32, hi);
350        put_bits32(s, lo);
351#endif
352    } else {
353        uint32_t lo = value & 0xffffffff;
354        uint32_t hi = value >> 32;
355#ifdef BITSTREAM_WRITER_LE
356        put_bits32(s, lo);
357        put_bits32(s, hi);
358#else
359        put_bits32(s, hi);
360        put_bits32(s, lo);
361#endif
362
363    }
364}
365
366/**
367 * Return the pointer to the byte where the bitstream writer will put
368 * the next bit.
369 */
370static inline uint8_t *put_bits_ptr(PutBitContext *s)
371{
372    return s->buf_ptr;
373}
374
375/**
376 * Skip the given number of bytes.
377 * PutBitContext must be flushed & aligned to a byte boundary before calling this.
378 */
379static inline void skip_put_bytes(PutBitContext *s, int n)
380{
381    av_assert2((put_bits_count(s) & 7) == 0);
382    av_assert2(s->bit_left == BUF_BITS);
383    av_assert0(n <= s->buf_end - s->buf_ptr);
384    s->buf_ptr += n;
385}
386
387/**
388 * Skip the given number of bits.
389 * Must only be used if the actual values in the bitstream do not matter.
390 * If n is < 0 the behavior is undefined.
391 */
392static inline void skip_put_bits(PutBitContext *s, int n)
393{
394    unsigned bits = BUF_BITS - s->bit_left + n;
395    s->buf_ptr += sizeof(BitBuf) * (bits / BUF_BITS);
396    s->bit_left = BUF_BITS - (bits & (BUF_BITS - 1));
397}
398
399/**
400 * Change the end of the buffer.
401 *
402 * @param size the new size in bytes of the buffer where to put bits
403 */
404static inline void set_put_bits_buffer_size(PutBitContext *s, int size)
405{
406    av_assert0(size <= INT_MAX/8 - BUF_BITS);
407    s->buf_end = s->buf + size;
408}
409
410/**
411 * Pad the bitstream with zeros up to the next byte boundary.
412 */
413static inline void align_put_bits(PutBitContext *s)
414{
415    put_bits(s, s->bit_left & 7, 0);
416}
417
418#undef AV_WBBUF
419#undef AV_WLBUF
420
421#endif /* AVCODEC_PUT_BITS_H */
422