Mercurial > libavcodec.hg
comparison put_bits.h @ 9411:4cb7c65fc775 libavcodec
Split bitstream.h, put the bitstream writer stuff in the new file
put_bits.h.
author | stefano |
---|---|
date | Sun, 12 Apr 2009 08:35:26 +0000 |
parents | |
children | a61f0c7f40a8 |
comparison
equal
deleted
inserted
replaced
9410:f7bd7e90ef9f | 9411:4cb7c65fc775 |
---|---|
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 libavcodec/put_bits.h | |
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 <stdlib.h> | |
31 #include <assert.h> | |
32 #include "libavutil/bswap.h" | |
33 #include "libavutil/common.h" | |
34 #include "libavutil/intreadwrite.h" | |
35 #include "libavutil/log.h" | |
36 #include "mathops.h" | |
37 | |
38 //#define ALT_BITSTREAM_WRITER | |
39 //#define ALIGNED_BITSTREAM_WRITER | |
40 | |
41 /* buf and buf_end must be present and used by every alternative writer. */ | |
42 typedef struct PutBitContext { | |
43 #ifdef ALT_BITSTREAM_WRITER | |
44 uint8_t *buf, *buf_end; | |
45 int index; | |
46 #else | |
47 uint32_t bit_buf; | |
48 int bit_left; | |
49 uint8_t *buf, *buf_ptr, *buf_end; | |
50 #endif | |
51 int size_in_bits; | |
52 } PutBitContext; | |
53 | |
54 /** | |
55 * Initializes the PutBitContext \p s. | |
56 * | |
57 * @param buffer the buffer where to put bits | |
58 * @param buffer_size the size in bytes of \p buffer | |
59 */ | |
60 static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size) | |
61 { | |
62 if(buffer_size < 0) { | |
63 buffer_size = 0; | |
64 buffer = NULL; | |
65 } | |
66 | |
67 s->size_in_bits= 8*buffer_size; | |
68 s->buf = buffer; | |
69 s->buf_end = s->buf + buffer_size; | |
70 #ifdef ALT_BITSTREAM_WRITER | |
71 s->index=0; | |
72 ((uint32_t*)(s->buf))[0]=0; | |
73 // memset(buffer, 0, buffer_size); | |
74 #else | |
75 s->buf_ptr = s->buf; | |
76 s->bit_left=32; | |
77 s->bit_buf=0; | |
78 #endif | |
79 } | |
80 | |
81 /** | |
82 * Returns the total number of bits written to the bitstream. | |
83 */ | |
84 static inline int put_bits_count(PutBitContext *s) | |
85 { | |
86 #ifdef ALT_BITSTREAM_WRITER | |
87 return s->index; | |
88 #else | |
89 return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left; | |
90 #endif | |
91 } | |
92 | |
93 /** | |
94 * Pads the end of the output stream with zeros. | |
95 */ | |
96 static inline void flush_put_bits(PutBitContext *s) | |
97 { | |
98 #ifdef ALT_BITSTREAM_WRITER | |
99 align_put_bits(s); | |
100 #else | |
101 #ifndef BITSTREAM_WRITER_LE | |
102 s->bit_buf<<= s->bit_left; | |
103 #endif | |
104 while (s->bit_left < 32) { | |
105 /* XXX: should test end of buffer */ | |
106 #ifdef BITSTREAM_WRITER_LE | |
107 *s->buf_ptr++=s->bit_buf; | |
108 s->bit_buf>>=8; | |
109 #else | |
110 *s->buf_ptr++=s->bit_buf >> 24; | |
111 s->bit_buf<<=8; | |
112 #endif | |
113 s->bit_left+=8; | |
114 } | |
115 s->bit_left=32; | |
116 s->bit_buf=0; | |
117 #endif | |
118 } | |
119 | |
120 /** | |
121 * Pads the bitstream with zeros up to the next byte boundary. | |
122 */ | |
123 void align_put_bits(PutBitContext *s); | |
124 | |
125 /** | |
126 * Puts the string \p s in the bitstream. | |
127 * | |
128 * @param terminate_string 0-terminates the written string if value is 1 | |
129 */ | |
130 void ff_put_string(PutBitContext * pbc, const char *s, int terminate_string); | |
131 | |
132 /** | |
133 * Copies the content of \p src to the bitstream. | |
134 * | |
135 * @param length the number of bits of \p src to copy | |
136 */ | |
137 void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length); | |
138 | |
139 static inline void put_bits(PutBitContext *s, int n, unsigned int value) | |
140 #ifndef ALT_BITSTREAM_WRITER | |
141 { | |
142 unsigned int bit_buf; | |
143 int bit_left; | |
144 | |
145 // printf("put_bits=%d %x\n", n, value); | |
146 assert(n == 32 || value < (1U << n)); | |
147 | |
148 bit_buf = s->bit_buf; | |
149 bit_left = s->bit_left; | |
150 | |
151 // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); | |
152 /* XXX: optimize */ | |
153 #ifdef BITSTREAM_WRITER_LE | |
154 bit_buf |= value << (32 - bit_left); | |
155 if (n >= bit_left) { | |
156 #if !HAVE_FAST_UNALIGNED | |
157 if (3 & (intptr_t) s->buf_ptr) { | |
158 AV_WL32(s->buf_ptr, bit_buf); | |
159 } else | |
160 #endif | |
161 *(uint32_t *)s->buf_ptr = le2me_32(bit_buf); | |
162 s->buf_ptr+=4; | |
163 bit_buf = (bit_left==32)?0:value >> bit_left; | |
164 bit_left+=32; | |
165 } | |
166 bit_left-=n; | |
167 #else | |
168 if (n < bit_left) { | |
169 bit_buf = (bit_buf<<n) | value; | |
170 bit_left-=n; | |
171 } else { | |
172 bit_buf<<=bit_left; | |
173 bit_buf |= value >> (n - bit_left); | |
174 #if !HAVE_FAST_UNALIGNED | |
175 if (3 & (intptr_t) s->buf_ptr) { | |
176 AV_WB32(s->buf_ptr, bit_buf); | |
177 } else | |
178 #endif | |
179 *(uint32_t *)s->buf_ptr = be2me_32(bit_buf); | |
180 //printf("bitbuf = %08x\n", bit_buf); | |
181 s->buf_ptr+=4; | |
182 bit_left+=32 - n; | |
183 bit_buf = value; | |
184 } | |
185 #endif | |
186 | |
187 s->bit_buf = bit_buf; | |
188 s->bit_left = bit_left; | |
189 } | |
190 #else /* ALT_BITSTREAM_WRITER defined */ | |
191 { | |
192 # ifdef ALIGNED_BITSTREAM_WRITER | |
193 # if ARCH_X86 | |
194 __asm__ volatile( | |
195 "movl %0, %%ecx \n\t" | |
196 "xorl %%eax, %%eax \n\t" | |
197 "shrdl %%cl, %1, %%eax \n\t" | |
198 "shrl %%cl, %1 \n\t" | |
199 "movl %0, %%ecx \n\t" | |
200 "shrl $3, %%ecx \n\t" | |
201 "andl $0xFFFFFFFC, %%ecx \n\t" | |
202 "bswapl %1 \n\t" | |
203 "orl %1, (%2, %%ecx) \n\t" | |
204 "bswapl %%eax \n\t" | |
205 "addl %3, %0 \n\t" | |
206 "movl %%eax, 4(%2, %%ecx) \n\t" | |
207 : "=&r" (s->index), "=&r" (value) | |
208 : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n)) | |
209 : "%eax", "%ecx" | |
210 ); | |
211 # else | |
212 int index= s->index; | |
213 uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5); | |
214 | |
215 value<<= 32-n; | |
216 | |
217 ptr[0] |= be2me_32(value>>(index&31)); | |
218 ptr[1] = be2me_32(value<<(32-(index&31))); | |
219 //if(n>24) printf("%d %d\n", n, value); | |
220 index+= n; | |
221 s->index= index; | |
222 # endif | |
223 # else //ALIGNED_BITSTREAM_WRITER | |
224 # if ARCH_X86 | |
225 __asm__ volatile( | |
226 "movl $7, %%ecx \n\t" | |
227 "andl %0, %%ecx \n\t" | |
228 "addl %3, %%ecx \n\t" | |
229 "negl %%ecx \n\t" | |
230 "shll %%cl, %1 \n\t" | |
231 "bswapl %1 \n\t" | |
232 "movl %0, %%ecx \n\t" | |
233 "shrl $3, %%ecx \n\t" | |
234 "orl %1, (%%ecx, %2) \n\t" | |
235 "addl %3, %0 \n\t" | |
236 "movl $0, 4(%%ecx, %2) \n\t" | |
237 : "=&r" (s->index), "=&r" (value) | |
238 : "r" (s->buf), "r" (n), "0" (s->index), "1" (value) | |
239 : "%ecx" | |
240 ); | |
241 # else | |
242 int index= s->index; | |
243 uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); | |
244 | |
245 ptr[0] |= be2me_32(value<<(32-n-(index&7) )); | |
246 ptr[1] = 0; | |
247 //if(n>24) printf("%d %d\n", n, value); | |
248 index+= n; | |
249 s->index= index; | |
250 # endif | |
251 # endif //!ALIGNED_BITSTREAM_WRITER | |
252 } | |
253 #endif | |
254 | |
255 static inline void put_sbits(PutBitContext *pb, int bits, int32_t val) | |
256 { | |
257 assert(bits >= 0 && bits <= 31); | |
258 | |
259 put_bits(pb, bits, val & ((1<<bits)-1)); | |
260 } | |
261 | |
262 | |
263 static inline uint8_t* pbBufPtr(PutBitContext *s) | |
264 { | |
265 #ifdef ALT_BITSTREAM_WRITER | |
266 return s->buf + (s->index>>3); | |
267 #else | |
268 return s->buf_ptr; | |
269 #endif | |
270 } | |
271 | |
272 /** | |
273 * Skips the given number of bytes. | |
274 * PutBitContext must be flushed & aligned to a byte boundary before calling this. | |
275 */ | |
276 static inline void skip_put_bytes(PutBitContext *s, int n){ | |
277 assert((put_bits_count(s)&7)==0); | |
278 #ifdef ALT_BITSTREAM_WRITER | |
279 FIXME may need some cleaning of the buffer | |
280 s->index += n<<3; | |
281 #else | |
282 assert(s->bit_left==32); | |
283 s->buf_ptr += n; | |
284 #endif | |
285 } | |
286 | |
287 /** | |
288 * Skips the given number of bits. | |
289 * Must only be used if the actual values in the bitstream do not matter. | |
290 * If \p n is 0 the behavior is undefined. | |
291 */ | |
292 static inline void skip_put_bits(PutBitContext *s, int n){ | |
293 #ifdef ALT_BITSTREAM_WRITER | |
294 s->index += n; | |
295 #else | |
296 s->bit_left -= n; | |
297 s->buf_ptr-= s->bit_left>>5; | |
298 s->bit_left &= 31; | |
299 #endif | |
300 } | |
301 | |
302 /** | |
303 * Changes the end of the buffer. | |
304 * | |
305 * @param size the new size in bytes of the buffer where to put bits | |
306 */ | |
307 static inline void set_put_bits_buffer_size(PutBitContext *s, int size){ | |
308 s->buf_end= s->buf + size; | |
309 } | |
310 | |
311 #endif /* AVCODEC_PUT_BITS_H */ |