summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/utils/put_bits.h (plain)
blob: 8b2aa15315d22c4d165e1463d39b3a75d5372c90
1#ifndef AVCODEC_PUT_BITS_H
2#define AVCODEC_PUT_BITS_H
3
4#include <linux/kernel.h>
5#include <linux/types.h>
6#include "common.h"
7
8struct put_bits_context {
9 u32 bit_buf;
10 int bit_left;
11 u8 *buf;
12 u8 *buf_ptr;
13 u8 *buf_end;
14 int size_in_bits;
15};
16
17/**
18 * Initialize the struct put_bits_context s.
19 *
20 * @param buffer the buffer where to put bits
21 * @param buffer_size the size in bytes of buffer
22 */
23static inline void init_put_bits(struct put_bits_context *s,
24 u8 *buffer, int buffer_size)
25{
26 if (buffer_size < 0) {
27 buffer_size = 0;
28 buffer = NULL;
29 }
30
31 s->size_in_bits = 8 * buffer_size;
32 s->buf = buffer;
33 s->buf_end = s->buf + buffer_size;
34 s->buf_ptr = s->buf;
35 s->bit_left = 32;
36 s->bit_buf = 0;
37}
38
39/**
40 * Rebase the bit writer onto a reallocated buffer.
41 *
42 * @param buffer the buffer where to put bits
43 * @param buffer_size the size in bytes of buffer,
44 * must be larger than the previous size
45 */
46static inline void rebase_put_bits(struct put_bits_context *s,
47 u8 *buffer, int buffer_size)
48{
49 s->buf_end = buffer + buffer_size;
50 s->buf_ptr = buffer + (s->buf_ptr - s->buf);
51 s->buf = buffer;
52 s->size_in_bits = 8 * buffer_size;
53}
54
55/**
56 * @return the total number of bits written to the bitstream.
57 */
58static inline int put_bits_count(struct put_bits_context *s)
59{
60 return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left;
61}
62
63/**
64 * @return the number of bits available in the bitstream.
65 */
66static inline int put_bits_left(struct put_bits_context* s)
67{
68 return (s->buf_end - s->buf_ptr) * 8 - 32 + s->bit_left;
69}
70
71/**
72 * Pad the end of the output stream with zeros.
73 */
74static inline void flush_put_bits(struct put_bits_context *s)
75{
76#ifndef BITSTREAM_WRITER_LE
77 if (s->bit_left < 32)
78 s->bit_buf <<= s->bit_left;
79#endif
80 while (s->bit_left < 32) {
81#ifdef BITSTREAM_WRITER_LE
82 *s->buf_ptr++ = s->bit_buf;
83 s->bit_buf >>= 8;
84#else
85 *s->buf_ptr++ = s->bit_buf >> 24;
86 s->bit_buf <<= 8;
87#endif
88 s->bit_left += 8;
89 }
90 s->bit_left = 32;
91 s->bit_buf = 0;
92}
93
94static inline void flush_put_bits_le(struct put_bits_context *s)
95{
96 while (s->bit_left < 32) {
97 *s->buf_ptr++ = s->bit_buf;
98 s->bit_buf >>= 8;
99 s->bit_left += 8;
100 }
101 s->bit_left = 32;
102 s->bit_buf = 0;
103}
104
105#ifdef BITSTREAM_WRITER_LE
106#define avpriv_align_put_bits align_put_bits_unsupported_here
107#define avpriv_put_string ff_put_string_unsupported_here
108#define avpriv_copy_bits avpriv_copy_bits_unsupported_here
109#else
110/**
111 * Pad the bitstream with zeros up to the next byte boundary.
112 */
113void avpriv_align_put_bits(struct put_bits_context *s);
114
115/**
116 * Put the string string in the bitstream.
117 *
118 * @param terminate_string 0-terminates the written string if value is 1
119 */
120void avpriv_put_string(struct put_bits_context *pb,
121 const char *string, int terminate_string);
122
123/**
124 * Copy the content of src to the bitstream.
125 *
126 * @param length the number of bits of src to copy
127 */
128void avpriv_copy_bits(struct put_bits_context *pb, const u8 *src, int length);
129#endif
130
131/**
132 * Write up to 31 bits into a bitstream.
133 * Use put_bits32 to write 32 bits.
134 */
135static inline void put_bits(struct put_bits_context *s, int n, u32 value)
136{
137 u32 bit_buf;
138 int bit_left;
139
140 bit_buf = s->bit_buf;
141 bit_left = s->bit_left;
142
143 /* XXX: optimize */
144#ifdef BITSTREAM_WRITER_LE
145 bit_buf |= value << (32 - bit_left);
146 if (n >= bit_left) {
147 if (3 < s->buf_end - s->buf_ptr) {
148 AV_WL32(s->buf_ptr, bit_buf);
149 s->buf_ptr += 4;
150 } else {
151 pr_err("Internal error, put_bits buffer too small\n");
152 }
153 bit_buf = value >> bit_left;
154 bit_left += 32;
155 }
156 bit_left -= n;
157#else
158 if (n < bit_left) {
159 bit_buf = (bit_buf << n) | value;
160 bit_left -= n;
161 } else {
162 bit_buf <<= bit_left;
163 bit_buf |= value >> (n - bit_left);
164 if (3 < s->buf_end - s->buf_ptr) {
165 AV_WB32(s->buf_ptr, bit_buf);
166 s->buf_ptr += 4;
167 } else {
168 pr_err("Internal error, put_bits buffer too small\n");
169 }
170 bit_left += 32 - n;
171 bit_buf = value;
172 }
173#endif
174 s->bit_buf = bit_buf;
175 s->bit_left = bit_left;
176}
177
178static inline void put_bits_le(struct put_bits_context *s, int n, u32 value)
179{
180 u32 bit_buf;
181 int bit_left;
182
183 bit_buf = s->bit_buf;
184 bit_left = s->bit_left;
185
186 bit_buf |= value << (32 - bit_left);
187 if (n >= bit_left) {
188 if (3 < s->buf_end - s->buf_ptr) {
189 AV_WL32(s->buf_ptr, bit_buf);
190 s->buf_ptr += 4;
191 } else {
192 pr_err("Internal error, put_bits buffer too small\n");
193 }
194 bit_buf = value >> bit_left;
195 bit_left += 32;
196 }
197 bit_left -= n;
198
199 s->bit_buf = bit_buf;
200 s->bit_left = bit_left;
201}
202
203static inline u32 av_mod_uintp2(u32 a, u32 p)
204{
205 return a & ((1 << p) - 1);
206}
207
208static inline void put_sbits(struct put_bits_context *pb, int n, int32_t value)
209{
210 put_bits(pb, n, av_mod_uintp2(value, n));
211}
212
213/**
214 * Write exactly 32 bits into a bitstream.
215 */
216static void put_bits32(struct put_bits_context *s, u32 value)
217{
218 u32 bit_buf;
219 int bit_left;
220
221 bit_buf = s->bit_buf;
222 bit_left = s->bit_left;
223
224#ifdef BITSTREAM_WRITER_LE
225 bit_buf |= value << (32 - bit_left);
226 if (3 < s->buf_end - s->buf_ptr) {
227 AV_WL32(s->buf_ptr, bit_buf);
228 s->buf_ptr += 4;
229 } else {
230 pr_err("Internal error, put_bits buffer too small\n");
231 }
232 bit_buf = (uint64_t)value >> bit_left;
233#else
234 bit_buf = (uint64_t)bit_buf << bit_left;
235 bit_buf |= value >> (32 - bit_left);
236 if (3 < s->buf_end - s->buf_ptr) {
237 AV_WB32(s->buf_ptr, bit_buf);
238 s->buf_ptr += 4;
239 } else {
240 pr_err("Internal error, put_bits buffer too small\n");
241 }
242 bit_buf = value;
243#endif
244
245 s->bit_buf = bit_buf;
246 s->bit_left = bit_left;
247}
248
249/**
250 * Write up to 64 bits into a bitstream.
251 */
252static inline void put_bits64(struct put_bits_context *s, int n, uint64_t value)
253{
254 if (n < 32)
255 put_bits(s, n, value);
256 else if (n == 32)
257 put_bits32(s, value);
258 else if (n < 64) {
259 u32 lo = value & 0xffffffff;
260 u32 hi = value >> 32;
261#ifdef BITSTREAM_WRITER_LE
262 put_bits32(s, lo);
263 put_bits(s, n - 32, hi);
264#else
265 put_bits(s, n - 32, hi);
266 put_bits32(s, lo);
267#endif
268 } else {
269 u32 lo = value & 0xffffffff;
270 u32 hi = value >> 32;
271#ifdef BITSTREAM_WRITER_LE
272 put_bits32(s, lo);
273 put_bits32(s, hi);
274#else
275 put_bits32(s, hi);
276 put_bits32(s, lo);
277#endif
278 }
279}
280
281/**
282 * Return the pointer to the byte where the bitstream writer will put
283 * the next bit.
284 */
285static inline u8 *put_bits_ptr(struct put_bits_context *s)
286{
287 return s->buf_ptr;
288}
289
290/**
291 * Skip the given number of bytes.
292 * struct put_bits_context must be flushed & aligned to a byte boundary before calling this.
293 */
294static inline void skip_put_bytes(struct put_bits_context *s, int n)
295{
296 s->buf_ptr += n;
297}
298
299/**
300 * Skip the given number of bits.
301 * Must only be used if the actual values in the bitstream do not matter.
302 * If n is 0 the behavior is undefined.
303 */
304static inline void skip_put_bits(struct put_bits_context *s, int n)
305{
306 s->bit_left -= n;
307 s->buf_ptr -= 4 * (s->bit_left >> 5);
308 s->bit_left &= 31;
309}
310
311/**
312 * Change the end of the buffer.
313 *
314 * @param size the new size in bytes of the buffer where to put bits
315 */
316static inline void set_put_bits_buffer_size(struct put_bits_context *s, int size)
317{
318 s->buf_end = s->buf + size;
319 s->size_in_bits = 8*size;
320}
321
322#endif /* AVCODEC_PUT_BITS_H */
323
324