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