You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
8.2KB

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