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 #ifndef PUT_BITS_H
22 #define PUT_BITS_H
23
24 #ifdef WORDS_BIGENDIAN
25 #define be2me_32(x) (x)
26 #else
27 #define be2me_32(x) bswap_32(x)
28 #endif
29
30 #ifndef bswap_32
bswap_32(uint32_t x)31 static inline uint32_t bswap_32(uint32_t x)
32 {
33 x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff);
34 x = (x >> 16) | (x << 16);
35 return x;
36 }
37 #endif
38
39 typedef struct PutBitContext {
40 uint32_t bit_buf;
41 int bit_left;
42 uint8_t *buf;
43 uint8_t *buf_ptr;
44 uint8_t *buf_end;
45 int size_in_bits;
46 } PutBitContext;
47
48 /**
49 * Initializes the PutBitContext s.
50 *
51 * @param buffer the buffer where to put bits
52 * @param buffer_size the size in bytes of buffer
53 */
init_put_bits(PutBitContext * s,uint8_t * buffer,int buffer_size)54 static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
55 {
56 if (buffer_size < 0) {
57 buffer_size = 0;
58 buffer = NULL;
59 }
60
61 s->size_in_bits = 8 * buffer_size;
62 s->buf = buffer;
63 s->buf_end = s->buf + buffer_size;
64 s->buf_ptr = s->buf;
65 s->bit_left = 32;
66 s->bit_buf = 0;
67 }
68
69 /**
70 * Returns the total number of bits written to the bitstream.
71 */
put_bits_count(PutBitContext * s)72 static inline int put_bits_count(PutBitContext *s)
73 {
74 return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left;
75 }
76
77 /**
78 * Pads the end of the output stream with zeros.
79 */
flush_put_bits(PutBitContext * s)80 static inline void flush_put_bits(PutBitContext *s)
81 {
82 s->bit_buf <<= s->bit_left;
83 while (s->bit_left < 32) {
84 /* XXX: should test end of buffer */
85 *s->buf_ptr++ = s->bit_buf >> 24;
86 s->bit_buf <<= 8;
87 s->bit_left += 8;
88 }
89 s->bit_left = 32;
90 s->bit_buf = 0;
91 }
92
93 /**
94 * Write up to 31 bits into a bitstream.
95 * Use put_bits32 to write 32 bits.
96 */
put_bits(PutBitContext * s,int n,unsigned int value)97 static inline void put_bits(PutBitContext *s, int n, unsigned int value)
98 {
99 unsigned int bit_buf;
100 int bit_left;
101
102 assert(n <= 31 && value < (1U << n));
103
104 bit_buf = s->bit_buf;
105 bit_left = s->bit_left;
106
107 if (n < bit_left) {
108 bit_buf = (bit_buf << n) | value;
109 bit_left -= n;
110 }
111 else {
112 bit_buf <<= bit_left;
113 bit_buf |= value >> (n - bit_left);
114 if (3 & (uintptr_t)s->buf_ptr) {
115 s->buf_ptr[0] = bit_buf >> 24;
116 s->buf_ptr[1] = bit_buf >> 16;
117 s->buf_ptr[2] = bit_buf >> 8;
118 s->buf_ptr[3] = bit_buf;
119 }
120 else
121 *(uint32_t *)s->buf_ptr = be2me_32(bit_buf);
122 s->buf_ptr += 4;
123 bit_left += 32 - n;
124 bit_buf = value;
125 }
126
127 s->bit_buf = bit_buf;
128 s->bit_left = bit_left;
129 }
130
131 /**
132 * Pads the bitstream with zeros up to the next byte boundary.
133 */
align_put_bits(PutBitContext * s)134 static inline void align_put_bits(PutBitContext *s)
135 {
136 put_bits(s, s->bit_left & 7, 0);
137 }
138
139 #endif /* PUT_BITS_H */
140