source: 3DVCSoftware/branches/0.1-poznan-univ/source/Lib/TLibCommon/TComBitStream.cpp @ 1417

Last change on this file since 1417 was 2, checked in by hhi, 13 years ago

inital import

  • Property svn:eol-style set to native
File size: 11.2 KB
Line 
1
2
3/** \file     TComBitStream.cpp
4    \brief    class for handling bitstream
5*/
6
7#include "TComBitStream.h"
8#include <string.h>
9#include <memory.h>
10
11// ====================================================================================================================
12// Constructor / destructor / create / destroy
13// ====================================================================================================================
14
15Void TComBitstream::create( UInt uiSizeInBytes )
16{
17  UInt uiSize = uiSizeInBytes / sizeof(UInt);
18 
19  m_apulStreamPacketBegin = new UInt[uiSize];
20  m_uiBufSize       = uiSize;
21  m_uiBitSize       = 0;
22  m_iValidBits      = 32;
23 
24  m_ulCurrentBits   = 0;
25  m_uiBitsWritten   = 0;
26 
27  m_pulStreamPacket = m_apulStreamPacketBegin;
28  m_auiSliceByteLocation = NULL;
29  m_uiSliceCount         = 0;
30}
31
32Void TComBitstream::destroy()
33{
34  delete [] m_apulStreamPacketBegin;     m_apulStreamPacketBegin = NULL;
35}
36
37// ====================================================================================================================
38// Public member functions
39// ====================================================================================================================
40
41Void TComBitstream::write   ( UInt uiBits, UInt uiNumberOfBits )
42{
43  assert( m_uiBufSize > 0 );
44  assert( uiNumberOfBits <= 32 );
45  assert( ! ( (uiBits >> 1) >> (uiNumberOfBits - 1)) ); // because shift with 32 has no effect
46 
47  m_uiBitsWritten += uiNumberOfBits;
48 
49  if( (Int)uiNumberOfBits < m_iValidBits)  // one word
50  {
51    m_iValidBits -= uiNumberOfBits;
52   
53    m_ulCurrentBits |= uiBits << m_iValidBits;
54   
55    return;
56  }
57 
58  UInt uiShift = uiNumberOfBits - m_iValidBits;
59 
60  // add the last bits
61  m_ulCurrentBits |= uiBits >> uiShift;
62 
63  *m_pulStreamPacket++ = xSwap( m_ulCurrentBits );
64 
65 
66  // note: there is a problem with left shift with 32
67  m_iValidBits = 32 - uiShift;
68 
69  m_ulCurrentBits = uiBits << m_iValidBits;
70 
71  if( 0 == uiShift )
72  {
73    m_ulCurrentBits = 0;
74  }
75}
76
77Void TComBitstream::writeAlignOne()
78{
79  write( ( 1 << (m_iValidBits & 0x7) ) - 1, m_iValidBits & 0x7 );
80  return;
81}
82
83Void TComBitstream::writeAlignZero()
84{
85  write( 0, m_iValidBits & 0x7 );
86  return;
87}
88
89Void  TComBitstream::flushBuffer()
90{
91  if (m_iValidBits == 0)
92    return;
93 
94  *m_pulStreamPacket = xSwap( m_ulCurrentBits );
95 
96  m_uiBitsWritten = (m_uiBitsWritten+7)/8;
97 
98  m_uiBitsWritten *= 8;
99}
100
101Void TComBitstream::initParsing ( UInt uiNumBytes )
102{
103  m_ulCurrentBits     = 0xdeaddead;
104  m_uiNextBits        = 0xdeaddead;
105  m_uiBitsLeft        = 0;
106  m_iValidBits        = 0;
107  m_uiDWordsLeft      = 0;
108 
109  m_uiBitsLeft        = uiNumBytes << 3;
110 
111  m_uiDWordsLeft      = m_uiBitsLeft >> 5;
112  m_iValidBits        = -32;
113 
114  xReadNextWord();
115  xReadNextWord();
116}
117
118#if LCEC_INTRA_MODE || QC_LCEC_INTER_MODE
119Void TComBitstream::pseudoRead ( UInt uiNumberOfBits, UInt& ruiBits )
120{
121  UInt ui_right_shift;
122
123  // check the number_of_bits parameter matches the range
124  assert( uiNumberOfBits <= 32 );
125
126  if( uiNumberOfBits > m_uiBitsLeft )
127  {
128    //assert (0);
129  }
130
131  Int  iValidBits = m_iValidBits - uiNumberOfBits;
132  UInt ulCurrentBits=m_ulCurrentBits;
133  UInt uiNextBits= m_uiNextBits;
134  if( 0 <= iValidBits )
135  {
136    // calculate the number of bits to extract the desired number of bits
137    ui_right_shift = 32 - uiNumberOfBits ;
138    // mask out the value
139    ruiBits  = ulCurrentBits >> ui_right_shift;
140    //prepare for next access
141    ulCurrentBits = ulCurrentBits << uiNumberOfBits;
142  }
143  else
144  {
145    // mask out the value in the current word
146    ruiBits = ulCurrentBits;
147    // calculate the number of bits to extract the desired number of bits
148    ui_right_shift = iValidBits + uiNumberOfBits ;
149    // mask out the value in the next word
150    ruiBits |= uiNextBits >> ui_right_shift;
151    ruiBits >>= 32 - uiNumberOfBits;
152    uiNextBits <<=  -iValidBits;
153  }
154
155  // check the current word for being empty
156  //-- baekeun.lee@samsung.com
157  if ( 0 < m_iValidBits)
158  {
159    return ;
160  }
161}
162#endif
163
164
165Void TComBitstream::read (UInt uiNumberOfBits, UInt& ruiBits)
166{
167  UInt ui_right_shift;
168 
169  // check the number_of_bits parameter matches the range
170  assert( uiNumberOfBits <= 32 );
171 
172  if( uiNumberOfBits > m_uiBitsLeft )
173  {
174    assert (0);
175  }
176 
177  m_uiBitsLeft -= uiNumberOfBits;
178  m_iValidBits -= uiNumberOfBits;
179 
180  if( 0 <= m_iValidBits )
181  {
182    // calculate the number of bits to extract the desired number of bits
183    ui_right_shift = 32 - uiNumberOfBits ;
184   
185    // mask out the value
186    ruiBits  = m_ulCurrentBits >> ui_right_shift;
187   
188    //prepare for next access
189    m_ulCurrentBits = m_ulCurrentBits << uiNumberOfBits;
190  }
191  else
192  {
193    // mask out the value in the current word
194    ruiBits = m_ulCurrentBits;
195   
196    // calculate the number of bits to extract the desired number of bits
197    ui_right_shift = m_iValidBits + uiNumberOfBits ;
198   
199    // mask out the value in the next word
200    ruiBits |= m_uiNextBits >> ui_right_shift;
201   
202    ruiBits >>= 32 - uiNumberOfBits;
203   
204    m_uiNextBits <<=  -m_iValidBits;
205  }
206 
207  // check the current word for being empty
208  //-- baekeun.lee@samsung.com
209  if ( 0 < m_iValidBits)
210  {
211    return ;
212  }
213  xReadNextWord();
214}
215
216Void TComBitstream::readAlignOne()
217{
218  UInt uiNumberOfBits = getBitsUntilByteAligned();
219 
220  // check the number_of_bits parameter matches the range
221  assert (uiNumberOfBits <= 32);
222  assert (uiNumberOfBits <= m_uiBitsLeft);
223 
224  // sub the desired number of bits
225  m_uiBitsLeft -= uiNumberOfBits;
226  m_iValidBits -= uiNumberOfBits;
227 
228  assert (m_uiBitsLeft%8 == 0);
229  assert (m_iValidBits%8 == 0);
230 
231  // check the current word for beeing still valid
232  if( 0 < m_iValidBits )
233  {
234    m_ulCurrentBits <<= uiNumberOfBits;
235    return;
236  }
237 
238  xReadNextWord();
239 
240  // shift to the right position
241  m_ulCurrentBits <<= 32 - m_iValidBits;
242 
243  return;
244}
245
246// ====================================================================================================================
247// Protected member functions
248// ====================================================================================================================
249
250__inline Void TComBitstream::xReadNextWord()
251{
252  m_ulCurrentBits = m_uiNextBits;
253  m_iValidBits += 32;
254 
255  // chech if there are bytes left in the packet
256  if( m_uiDWordsLeft )
257  {
258    // read 32 bit from the packet
259    m_uiNextBits = xSwap( *m_pulStreamPacket++ );
260    m_uiDWordsLeft--;
261  }
262  else
263  {
264    Int iBytesLeft  = ((Int)m_uiBitsLeft - m_iValidBits+7) >> 3;
265    UChar* puc      = (UChar*) m_pulStreamPacket;
266    m_uiNextBits  = 0;
267   
268    if( iBytesLeft > 0)
269    {
270      for( Int iByte = 0; iByte < iBytesLeft; iByte++ )
271      {
272        m_uiNextBits <<= 8;
273        m_uiNextBits += puc[iByte];
274      }
275      m_uiNextBits <<= (4-iBytesLeft)<<3;
276    }
277  }
278}
279
280Void TComBitstream::initParsingConvertPayloadToRBSP( const UInt uiBytesRead )
281{
282  UInt uiZeroCount    = 0;
283  UInt uiReadOffset   = 0;
284  UInt uiWriteOffset  = 0;
285  const UChar* pucRead = reinterpret_cast<UChar*> (getBuffer());
286  UChar* pucWrite      = reinterpret_cast<UChar*> (getBuffer());
287 
288  for( ; uiReadOffset < uiBytesRead; uiReadOffset++ )
289  {
290    if( 2 == uiZeroCount && 0x03 == pucRead[uiReadOffset] )
291    {
292      uiReadOffset++;
293      uiZeroCount = 0;
294      if (uiReadOffset>=uiBytesRead)
295      {
296        break;
297      }
298    }
299   
300    pucWrite[uiWriteOffset++] = pucRead[uiReadOffset];
301   
302    if( 0x00 == pucRead[uiReadOffset] )
303    {
304      uiZeroCount++;
305    }
306    else
307    {
308      uiZeroCount = 0;
309    }
310  }
311 
312  // th just clear the remaining bits in the buffer
313  for( UInt ui = uiWriteOffset; ui < uiBytesRead; ui++)
314  {
315    pucWrite[ui] = 0;
316  }
317 
318  initParsing( uiWriteOffset );
319}
320
321Void TComBitstream::convertRBSPToPayload( UInt uiStartPos )
322{
323  UInt uiZeroCount    = 0;
324 
325  //make sure the buffer is flushed
326  assert( 0 == getBitsUntilByteAligned() );
327 
328  const UInt uiBytesInBuffer = getNumberOfWrittenBits()>>3;
329  //make sure there's something in the buffer
330  assert( 0 != uiBytesInBuffer );
331 
332  //make sure start pos is inside the buffer
333  //  assert( uiStartPos > uiBytesInBuffer );
334 
335  UChar* pucRead = new UChar[ uiBytesInBuffer ];
336  //th this is not nice but ...
337  memcpy( pucRead, getStartStream(), uiBytesInBuffer );
338 
339  UChar* pucWrite      =  reinterpret_cast<UChar*> (getStartStream());
340 
341  UInt uiWriteOffset  = uiStartPos;
342  UInt uiReadOffset = uiStartPos;
343  UInt uiSliceIdx   = 0;
344  while ( uiReadOffset < uiBytesInBuffer )
345  {
346    if (uiSliceIdx < m_uiSliceCount && uiReadOffset == m_auiSliceByteLocation[uiSliceIdx]) // skip over start codes introduced before slice headers
347    {
348      assert(pucRead[uiReadOffset] == 0); pucWrite[uiWriteOffset++] =  pucRead[uiReadOffset++];
349      assert(pucRead[uiReadOffset] == 0); pucWrite[uiWriteOffset++] =  pucRead[uiReadOffset++];
350      assert(pucRead[uiReadOffset] == 0); pucWrite[uiWriteOffset++] =  pucRead[uiReadOffset++];
351      assert(pucRead[uiReadOffset] == 1); pucWrite[uiWriteOffset++] =  pucRead[uiReadOffset++];
352
353      uiSliceIdx++;
354    }
355    if( 2 == uiZeroCount && 0 == (pucRead[uiReadOffset] & 0xfc) )
356    {
357      pucWrite[uiWriteOffset++] = 0x03;
358      uiZeroCount = 0;
359    }
360   
361    pucWrite[uiWriteOffset++] = pucRead[uiReadOffset];
362   
363    if( 0 == pucRead[uiReadOffset] )
364    {
365      uiZeroCount++;
366    }
367    else
368    {
369      uiZeroCount = 0;
370    }
371    uiReadOffset++;
372  }
373 
374  delete [] pucRead;
375  m_uiBitsWritten = uiWriteOffset << 3;
376}
377
378Void TComBitstream::allocateMemoryForSliceLocations ( UInt uiMaxNumOfSlices )
379{
380  m_auiSliceByteLocation     = new UInt[ uiMaxNumOfSlices ];
381  m_uiSliceCount             = 0;
382}
383
384Void TComBitstream::freeMemoryAllocatedForSliceLocations ()
385{
386  if (m_auiSliceByteLocation!=NULL)
387  {
388    delete [] m_auiSliceByteLocation;
389    m_auiSliceByteLocation   = NULL;
390  }
391  m_uiSliceCount             = 0;
392}
393
394/**
395 * insert the contents of the bytealigned (and flushed) bitstream @src
396 * into @this at byte position @pos.
397 *
398 * NB, there is currently a restriction that src_bytes must be a
399 * multiple of sizeof(UInt) if @this->write(...) is going to be called
400 * again.  This restriction will be removed when TComBitstream is refactored
401 * to work on bytes.
402 */
403void TComBitstream::insertAt(const TComBitstream& src, unsigned pos)
404{
405  unsigned src_bits = src.getNumberOfWrittenBits();
406  assert(0 == src_bits % 8);
407  unsigned src_bytes = src_bits/8;
408
409  /* check that there is enough space in the current buffer to accommodate @src */
410  unsigned this_buf_size = m_uiBufSize * sizeof(UInt);
411  unsigned this_bytes = this->getNumberOfWrittenBits()/8;
412  assert(this_buf_size - this_bytes > src_bytes);
413
414  /* make space */
415  unsigned char *this_dest = pos + src_bytes + (unsigned char*) this->getStartStream();
416  unsigned char *this_src = pos + (unsigned char*) this->getStartStream();
417  memmove(this_dest, this_src, this_bytes - pos);
418
419  /* splice src */
420  memcpy(this_src, src.getStartStream(), src_bytes);
421
422  /* update state */
423  this->m_uiBitsWritten += src_bits;
424  this->m_pulStreamPacket += src_bytes / sizeof(UInt);
425  /* XXX: this will go horribly wrong if data being inserted isn't a
426   * multiple of UInt. To work correctly, some data would have to be
427   * pulled back from the fifo into currentBits. */
428  /* Since davidf has rewritten this to work in bytes, i'm not going
429   * to make this work for UInt words.  This will be fine as long as
430   * no further data is pushed after this splice.
431   */
432}
Note: See TracBrowser for help on using the repository browser.