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 */ |
