1 /*
2 * Copyright (c) 2020, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #include "bitstream_writer.h"
24 #include <assert.h>
25
BitstreamWriter(mfxU8 * bs,mfxU32 size,mfxU8 bitOffset)26 BitstreamWriter::BitstreamWriter(mfxU8 *bs, mfxU32 size, mfxU8 bitOffset)
27 : m_bsStart(bs), m_bsEnd(bs + size), m_bs(bs), m_bitStart(bitOffset & 7), m_bitOffset(bitOffset & 7), m_codILow(0) // cabac variables
28 ,
29 m_codIRange(510),
30 m_bitsOutstanding(0),
31 m_BinCountsInNALunits(0),
32 m_firstBitFlag(true)
33 {
34 assert(bitOffset < 8);
35 *m_bs &= 0xFF << (8 - m_bitOffset);
36 }
37
~BitstreamWriter()38 BitstreamWriter::~BitstreamWriter()
39 {
40 }
41
Reset(mfxU8 * bs,mfxU32 size,mfxU8 bitOffset)42 void BitstreamWriter::Reset(mfxU8 *bs, mfxU32 size, mfxU8 bitOffset)
43 {
44 if (bs)
45 {
46 m_bsStart = bs;
47 m_bsEnd = bs + size;
48 unsigned char *curr = m_bsStart;
49 /*
50 while (curr<m_bsEnd)//Not Necessary
51 {
52 *curr = 0;
53 curr++;
54 }
55 */
56 m_bs = bs;
57 m_bitOffset = (bitOffset & 7);
58 m_bitStart = (bitOffset & 7);
59 }
60 else
61 {
62 m_bs = m_bsStart;
63 m_bitOffset = m_bitStart;
64 }
65 }
66
PutBitsBuffer(mfxU32 n,void * bb,mfxU32 o)67 void BitstreamWriter::PutBitsBuffer(mfxU32 n, void *bb, mfxU32 o)
68 {}
69
PutBits(mfxU32 n,mfxU32 b)70 void BitstreamWriter::PutBits(mfxU32 n, mfxU32 b)
71 {
72 assert(n <= sizeof(b) * 8);
73 while (n > 24)
74 {
75 n -= 16;
76 PutBits(16, (b >> n));
77 }
78
79 b <<= (32 - n);
80
81 if (!m_bitOffset)
82 {
83 m_bs[0] = (mfxU8)(b >> 24);
84 m_bs[1] = (mfxU8)(b >> 16);
85 }
86 else
87 {
88 b >>= m_bitOffset;
89 n += m_bitOffset;
90
91 m_bs[0] |= (mfxU8)(b >> 24);
92 m_bs[1] = (mfxU8)(b >> 16);
93 }
94
95 if (n > 16)
96 {
97 m_bs[2] = (mfxU8)(b >> 8);
98 m_bs[3] = (mfxU8)b;
99 }
100
101 m_bs += (n >> 3);
102 m_bitOffset = (n & 7);
103 }
104
PutBit(mfxU32 b)105 void BitstreamWriter::PutBit(mfxU32 b)
106 {
107 switch (m_bitOffset)
108 {
109 case 0:
110 m_bs[0] = (mfxU8)(b << 7);
111 m_bitOffset = 1;
112 break;
113 case 7:
114 m_bs[0] |= (mfxU8)(b & 1);
115 m_bs++;
116 m_bitOffset = 0;
117 break;
118 default:
119 if (b & 1)
120 m_bs[0] |= (mfxU8)(1 << (7 - m_bitOffset));
121 m_bitOffset++;
122 break;
123 }
124 }
125
PutGolomb(mfxU32 b)126 void BitstreamWriter::PutGolomb(mfxU32 b)
127 {
128 if (!b)
129 {
130 PutBit(1);
131 }
132 else
133 {
134 mfxU32 n = 1;
135
136 b++;
137
138 while (b >> n)
139 n++;
140
141 PutBits(n - 1, 0);
142 PutBits(n, b);
143 }
144 }
145
PutTrailingBits(bool bCheckAligened)146 void BitstreamWriter::PutTrailingBits(bool bCheckAligened)
147 {
148 if ((!bCheckAligened) || m_bitOffset)
149 PutBit(1);
150
151 if (m_bitOffset)
152 {
153 *(++m_bs) = 0;
154 m_bitOffset = 0;
155 }
156 }
157
PutBitC(mfxU32 B)158 void BitstreamWriter::PutBitC(mfxU32 B)
159 {
160 if (m_firstBitFlag)
161 m_firstBitFlag = false;
162 else
163 PutBit(B);
164
165 while (m_bitsOutstanding > 0)
166 {
167 PutBit(1 - B);
168 m_bitsOutstanding--;
169 }
170 }
RenormE()171 void BitstreamWriter::RenormE()
172 {
173 while (m_codIRange < 256)
174 {
175 if (m_codILow < 256)
176 {
177 PutBitC(0);
178 }
179 else if (m_codILow >= 512)
180 {
181 m_codILow -= 512;
182 PutBitC(1);
183 }
184 else
185 {
186 m_codILow -= 256;
187 m_bitsOutstanding++;
188 }
189 m_codIRange <<= 1;
190 m_codILow <<= 1;
191 }
192 }
193
EncodeBin(mfxU8 & ctx,mfxU8 binVal)194 void BitstreamWriter::EncodeBin(mfxU8 &ctx, mfxU8 binVal)
195 {
196 mfxU8 pStateIdx = (ctx >> 1);
197 mfxU8 valMPS = (ctx & 1);
198 mfxU32 qCodIRangeIdx = (m_codIRange >> 6) & 3;
199 mfxU32 codIRangeLPS = tab_cabacRangeTabLps[pStateIdx][qCodIRangeIdx];
200
201 m_codIRange -= codIRangeLPS;
202
203 if (binVal != valMPS)
204 {
205 m_codILow += m_codIRange;
206 m_codIRange = codIRangeLPS;
207
208 if (pStateIdx == 0)
209 valMPS = 1 - valMPS;
210
211 pStateIdx = tab_cabacTransTbl[1][pStateIdx]; //transIdxLPS[pStateIdx];
212 }
213 else
214 {
215 pStateIdx = tab_cabacTransTbl[0][pStateIdx]; //transIdxMPS[pStateIdx];
216 }
217
218 ctx = (pStateIdx << 1) | valMPS;
219
220 RenormE();
221 m_BinCountsInNALunits++;
222 }
223
EncodeBinEP(mfxU8 binVal)224 void BitstreamWriter::EncodeBinEP(mfxU8 binVal)
225 {
226 m_codILow += m_codILow + m_codIRange * (binVal == 1);
227 RenormE();
228 m_BinCountsInNALunits++;
229 }
230
SliceFinish()231 void BitstreamWriter::SliceFinish()
232 {
233 m_codIRange -= 2;
234 m_codILow += m_codIRange;
235 m_codIRange = 2;
236
237 RenormE();
238 PutBitC((m_codILow >> 9) & 1);
239 PutBit(m_codILow >> 8);
240 PutTrailingBits();
241
242 m_BinCountsInNALunits++;
243 }
244
cabacInit()245 void BitstreamWriter::cabacInit()
246 {
247 m_codILow = 0;
248 m_codIRange = 510;
249 m_bitsOutstanding = 0;
250 m_BinCountsInNALunits = 0;
251 m_firstBitFlag = true;
252 }