source: 3DVCSoftware/branches/0.3-poznan-univ/source/Lib/TLibCommon/TComBitStream.cpp @ 28

Last change on this file since 28 was 5, checked in by hhi, 13 years ago

Clean version with cfg-files

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