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 }