Imported Upstream version 1.4
[deb_x265.git] / source / common / bitstream.cpp
CommitLineData
72b9787e
JB
1#include "common.h"
2#include "bitstream.h"
3
4using namespace x265;
5
6#if defined(_MSC_VER)
7#pragma warning(disable: 4244)
8#endif
9
10#define MIN_FIFO_SIZE 1000
11
12Bitstream::Bitstream()
13{
14 m_fifo = X265_MALLOC(uint8_t, MIN_FIFO_SIZE);
15 m_byteAlloc = MIN_FIFO_SIZE;
16 resetBits();
17}
18
19void Bitstream::push_back(uint8_t val)
20{
21 if (!m_fifo)
22 return;
23
24 if (m_byteOccupancy >= m_byteAlloc)
25 {
26 /** reallocate buffer with doubled size */
27 uint8_t *temp = X265_MALLOC(uint8_t, m_byteAlloc * 2);
28 if (temp)
29 {
30 ::memcpy(temp, m_fifo, m_byteOccupancy);
31 X265_FREE(m_fifo);
32 m_fifo = temp;
33 m_byteAlloc *= 2;
34 }
35 else
36 {
37 x265_log(NULL, X265_LOG_ERROR, "Unable to realloc bitstream buffer");
38 return;
39 }
40 }
41 m_fifo[m_byteOccupancy++] = val;
42}
43
44void Bitstream::write(uint32_t val, uint32_t numBits)
45{
46 X265_CHECK(numBits <= 32, "numBits out of range\n");
47 X265_CHECK(numBits == 32 || ((val & (~0 << numBits)) == 0), "numBits & val out of range\n");
48
49 uint32_t totalPartialBits = m_partialByteBits + numBits;
50 uint32_t nextPartialBits = totalPartialBits & 7;
51 uint8_t nextHeldByte = val << (8 - nextPartialBits);
52 uint32_t writeBytes = totalPartialBits >> 3;
53
54 if (writeBytes)
55 {
56 /* topword aligns m_partialByte with the msb of val */
57 uint32_t topword = (numBits - nextPartialBits) & ~7;
58 uint32_t write_bits = (m_partialByte << topword) | (val >> nextPartialBits);
59
60 switch (writeBytes)
61 {
62 case 4: push_back(write_bits >> 24);
63 case 3: push_back(write_bits >> 16);
64 case 2: push_back(write_bits >> 8);
65 case 1: push_back(write_bits);
66 }
67
68 m_partialByte = nextHeldByte;
69 m_partialByteBits = nextPartialBits;
70 }
71 else
72 {
73 m_partialByte |= nextHeldByte;
74 m_partialByteBits = nextPartialBits;
75 }
76}
77
78void Bitstream::writeByte(uint32_t val)
79{
80 // Only CABAC will call writeByte, the fifo must be byte aligned
81 X265_CHECK(!m_partialByteBits, "expecting m_partialByteBits = 0\n");
82
83 push_back(val);
84}
85
86void Bitstream::writeAlignOne()
87{
88 uint32_t numBits = (8 - m_partialByteBits) & 0x7;
89
90 write((1 << numBits) - 1, numBits);
91}
92
93void Bitstream::writeAlignZero()
94{
95 if (m_partialByteBits)
96 {
97 push_back(m_partialByte);
98 m_partialByte = 0;
99 m_partialByteBits = 0;
100 }
101}
102
103void Bitstream::writeByteAlignment()
104{
105 write(1, 1);
106 writeAlignZero();
107}
108
109void SyntaxElementWriter::writeUvlc(uint32_t code)
110{
111 uint32_t length = 1;
112 uint32_t temp = ++code;
113
114 X265_CHECK(temp, "writing -1 code, will cause infinite loop\n");
115
116 while (1 != temp)
117 {
118 temp >>= 1;
119 length += 2;
120 }
121
122 // Take care of cases where length > 32
123 m_bitIf->write(0, length >> 1);
124 m_bitIf->write(code, (length + 1) >> 1);
125}