source: 3DVCSoftware/branches/0.3-ericsson/source/Lib/TLibCommon/TComBitStream.cpp

Last change on this file was 40, checked in by ericsson, 13 years ago

Ericsson integration: integrated bitstream extractor; implemented NALu header according to HEVC CD, using reserved_one_5bit as layer_id_plus1

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