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 <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. */ 42typedef 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 s. 56 * 57 * @param buffer the buffer where to put bits 58 * @param buffer_size the size in bytes of buffer 59 */ 60static 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 */ 84static 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 */ 96static 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#if defined(ALT_BITSTREAM_WRITER) || defined(BITSTREAM_WRITER_LE) 121#define align_put_bits align_put_bits_unsupported_here 122#define ff_put_string ff_put_string_unsupported_here 123#define ff_copy_bits ff_copy_bits_unsupported_here 124#else 125/** 126 * Pads the bitstream with zeros up to the next byte boundary. 127 */ 128void align_put_bits(PutBitContext *s); 129 130/** 131 * Puts the string string in the bitstream. 132 * 133 * @param terminate_string 0-terminates the written string if value is 1 134 */ 135void ff_put_string(PutBitContext *pb, const char *string, int terminate_string); 136 137/** 138 * Copies the content of src to the bitstream. 139 * 140 * @param length the number of bits of src to copy 141 */ 142void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length); 143#endif 144 145/** 146 * Writes up to 31 bits into a bitstream. 147 * Use put_bits32 to write 32 bits. 148 */ 149static inline void put_bits(PutBitContext *s, int n, unsigned int value) 150#ifndef ALT_BITSTREAM_WRITER 151{ 152 unsigned int bit_buf; 153 int bit_left; 154 155 // printf("put_bits=%d %x\n", n, value); 156 assert(n <= 31 && value < (1U << n)); 157 158 bit_buf = s->bit_buf; 159 bit_left = s->bit_left; 160 161 // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); 162 /* XXX: optimize */ 163#ifdef BITSTREAM_WRITER_LE 164 bit_buf |= value << (32 - bit_left); 165 if (n >= bit_left) { 166#if !HAVE_FAST_UNALIGNED 167 if (3 & (intptr_t) s->buf_ptr) { 168 AV_WL32(s->buf_ptr, bit_buf); 169 } else 170#endif 171 *(uint32_t *)s->buf_ptr = le2me_32(bit_buf); 172 s->buf_ptr+=4; 173 bit_buf = (bit_left==32)?0:value >> bit_left; 174 bit_left+=32; 175 } 176 bit_left-=n; 177#else 178 if (n < bit_left) { 179 bit_buf = (bit_buf<<n) | value; 180 bit_left-=n; 181 } else { 182 bit_buf<<=bit_left; 183 bit_buf |= value >> (n - bit_left); 184#if !HAVE_FAST_UNALIGNED 185 if (3 & (intptr_t) s->buf_ptr) { 186 AV_WB32(s->buf_ptr, bit_buf); 187 } else 188#endif 189 *(uint32_t *)s->buf_ptr = be2me_32(bit_buf); 190 //printf("bitbuf = %08x\n", bit_buf); 191 s->buf_ptr+=4; 192 bit_left+=32 - n; 193 bit_buf = value; 194 } 195#endif 196 197 s->bit_buf = bit_buf; 198 s->bit_left = bit_left; 199} 200#else /* ALT_BITSTREAM_WRITER defined */ 201{ 202# ifdef ALIGNED_BITSTREAM_WRITER 203# if ARCH_X86 204 __asm__ volatile( 205 "movl %0, %%ecx \n\t" 206 "xorl %%eax, %%eax \n\t" 207 "shrdl %%cl, %1, %%eax \n\t" 208 "shrl %%cl, %1 \n\t" 209 "movl %0, %%ecx \n\t" 210 "shrl $3, %%ecx \n\t" 211 "andl $0xFFFFFFFC, %%ecx \n\t" 212 "bswapl %1 \n\t" 213 "orl %1, (%2, %%ecx) \n\t" 214 "bswapl %%eax \n\t" 215 "addl %3, %0 \n\t" 216 "movl %%eax, 4(%2, %%ecx) \n\t" 217 : "=&r" (s->index), "=&r" (value) 218 : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n)) 219 : "%eax", "%ecx" 220 ); 221# else 222 int index= s->index; 223 uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5); 224 225 value<<= 32-n; 226 227 ptr[0] |= be2me_32(value>>(index&31)); 228 ptr[1] = be2me_32(value<<(32-(index&31))); 229//if(n>24) printf("%d %d\n", n, value); 230 index+= n; 231 s->index= index; 232# endif 233# else //ALIGNED_BITSTREAM_WRITER 234# if ARCH_X86 235 __asm__ volatile( 236 "movl $7, %%ecx \n\t" 237 "andl %0, %%ecx \n\t" 238 "addl %3, %%ecx \n\t" 239 "negl %%ecx \n\t" 240 "shll %%cl, %1 \n\t" 241 "bswapl %1 \n\t" 242 "movl %0, %%ecx \n\t" 243 "shrl $3, %%ecx \n\t" 244 "orl %1, (%%ecx, %2) \n\t" 245 "addl %3, %0 \n\t" 246 "movl $0, 4(%%ecx, %2) \n\t" 247 : "=&r" (s->index), "=&r" (value) 248 : "r" (s->buf), "r" (n), "0" (s->index), "1" (value) 249 : "%ecx" 250 ); 251# else 252 int index= s->index; 253 uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); 254 255 ptr[0] |= be2me_32(value<<(32-n-(index&7) )); 256 ptr[1] = 0; 257//if(n>24) printf("%d %d\n", n, value); 258 index+= n; 259 s->index= index; 260# endif 261# endif //!ALIGNED_BITSTREAM_WRITER 262} 263#endif 264 265static inline void put_sbits(PutBitContext *pb, int n, int32_t value) 266{ 267 assert(n >= 0 && n <= 31); 268 269 put_bits(pb, n, value & ((1<<n)-1)); 270} 271 272/** 273 * Writes exactly 32 bits into a bitstream. 274 */ 275static void av_unused put_bits32(PutBitContext *s, uint32_t value) 276{ 277 int lo = value & 0xffff; 278 int hi = value >> 16; 279#ifdef BITSTREAM_WRITER_LE 280 put_bits(s, 16, lo); 281 put_bits(s, 16, hi); 282#else 283 put_bits(s, 16, hi); 284 put_bits(s, 16, lo); 285#endif 286} 287 288/** 289 * Returns the pointer to the byte where the bitstream writer will put 290 * the next bit. 291 */ 292static inline uint8_t* put_bits_ptr(PutBitContext *s) 293{ 294#ifdef ALT_BITSTREAM_WRITER 295 return s->buf + (s->index>>3); 296#else 297 return s->buf_ptr; 298#endif 299} 300 301/** 302 * Skips the given number of bytes. 303 * PutBitContext must be flushed & aligned to a byte boundary before calling this. 304 */ 305static inline void skip_put_bytes(PutBitContext *s, int n) 306{ 307 assert((put_bits_count(s)&7)==0); 308#ifdef ALT_BITSTREAM_WRITER 309 FIXME may need some cleaning of the buffer 310 s->index += n<<3; 311#else 312 assert(s->bit_left==32); 313 s->buf_ptr += n; 314#endif 315} 316 317/** 318 * Skips the given number of bits. 319 * Must only be used if the actual values in the bitstream do not matter. 320 * If n is 0 the behavior is undefined. 321 */ 322static inline void skip_put_bits(PutBitContext *s, int n) 323{ 324#ifdef ALT_BITSTREAM_WRITER 325 s->index += n; 326#else 327 s->bit_left -= n; 328 s->buf_ptr-= 4*(s->bit_left>>5); 329 s->bit_left &= 31; 330#endif 331} 332 333/** 334 * Changes the end of the buffer. 335 * 336 * @param size the new size in bytes of the buffer where to put bits 337 */ 338static inline void set_put_bits_buffer_size(PutBitContext *s, int size) 339{ 340 s->buf_end= s->buf + size; 341} 342 343#endif /* AVCODEC_PUT_BITS_H */ 344