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