source: 3DVCSoftware/trunk/source/Lib/TLibCommon/TComBitStream.cpp @ 114

Last change on this file since 114 was 56, checked in by hschwarz, 13 years ago

updated trunk (move to HM6.1)

  • Property svn:eol-style set to native
File size: 10.8 KB
RevLine 
[5]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
[56]4 * granted under this license. 
[5]5 *
[56]6 * Copyright (c) 2010-2012, ITU/ISO/IEC
[5]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.
[56]17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
[5]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 */
[2]33
34/** \file     TComBitStream.cpp
35    \brief    class for handling bitstream
36*/
37
[56]38#include <stdint.h>
39#include <vector>
[2]40#include "TComBitStream.h"
41#include <string.h>
42#include <memory.h>
43
[56]44using namespace std;
45
46//! \ingroup TLibCommon
47//! \{
48
[2]49// ====================================================================================================================
50// Constructor / destructor / create / destroy
51// ====================================================================================================================
52
[56]53TComOutputBitstream::TComOutputBitstream()
[2]54{
[56]55  m_fifo = new vector<uint8_t>;
56  clear();
57  m_puiTileMarkerLocation     = new UInt[MAX_MARKER_PER_NALU];
58  m_uiTileMarkerLocationCount = 0;
[2]59}
60
[56]61TComOutputBitstream::~TComOutputBitstream()
[2]62{
[56]63  delete m_fifo;
64  delete [] m_puiTileMarkerLocation;
65}
66
67TComInputBitstream::TComInputBitstream(std::vector<uint8_t>* buf)
68{
69  m_fifo = buf;
70  m_fifo_idx = 0;
71  m_held_bits = 0;
72  m_num_held_bits = 0;
73  m_puiTileMarkerLocation     = new UInt[MAX_MARKER_PER_NALU];
74  m_uiTileMarkerLocationCount = 0;
75#if TILES_WPP_ENTRY_POINT_SIGNALLING
76  m_numBitsRead = 0;
[42]77#endif
[2]78}
79
[56]80TComInputBitstream::~TComInputBitstream()
81{
82  delete [] m_puiTileMarkerLocation;
83}
84
[2]85// ====================================================================================================================
86// Public member functions
87// ====================================================================================================================
88
[56]89char* TComOutputBitstream::getByteStream() const
[2]90{
[56]91  return (char*) &m_fifo->front();
[2]92}
93
[56]94unsigned int TComOutputBitstream::getByteStreamLength()
[2]95{
[56]96  return unsigned(m_fifo->size());
[2]97}
98
[56]99void TComOutputBitstream::clear()
[2]100{
[56]101  m_fifo->clear();
102  m_held_bits = 0;
103  m_num_held_bits = 0;
104  m_uiTileMarkerLocationCount = 0;
[2]105}
106
[56]107Void TComOutputBitstream::write   ( UInt uiBits, UInt uiNumberOfBits )
[2]108{
[56]109  assert( uiNumberOfBits <= 32 );
110
111  /* any modulo 8 remainder of num_total_bits cannot be written this time,
112   * and will be held until next time. */
113  unsigned num_total_bits = uiNumberOfBits + m_num_held_bits;
114  unsigned next_num_held_bits = num_total_bits % 8;
115
116  /* form a byte aligned word (write_bits), by concatenating any held bits
117   * with the new bits, discarding the bits that will form the next_held_bits.
118   * eg: H = held bits, V = n new bits        /---- next_held_bits
119   * len(H)=7, len(V)=1: ... ---- HHHH HHHV . 0000 0000, next_num_held_bits=0
120   * len(H)=7, len(V)=2: ... ---- HHHH HHHV . V000 0000, next_num_held_bits=1
121   * if total_bits < 8, the value of v_ is not used */
122  unsigned char next_held_bits = uiBits << (8 - next_num_held_bits);
123
124  if (!(num_total_bits >> 3))
125  {
126    /* insufficient bits accumulated to write out, append new_held_bits to
127     * current held_bits */
128    /* NB, this requires that v only contains 0 in bit positions {31..n} */
129    m_held_bits |= next_held_bits;
130    m_num_held_bits = next_num_held_bits;
[2]131    return;
[56]132  }
133
134  /* topword serves to justify held_bits to align with the msb of uiBits */
135  unsigned topword = (uiNumberOfBits - next_num_held_bits) & ~((1 << 3) -1);
136  unsigned int write_bits = (m_held_bits << topword) | (uiBits >> next_num_held_bits);
137
138  switch (num_total_bits >> 3)
139  {
140  case 4: m_fifo->push_back(write_bits >> 24);
141  case 3: m_fifo->push_back(write_bits >> 16);
142  case 2: m_fifo->push_back(write_bits >> 8);
143  case 1: m_fifo->push_back(write_bits);
144  }
145
146  m_held_bits = next_held_bits;
147  m_num_held_bits = next_num_held_bits;
[2]148}
149
[56]150Void TComOutputBitstream::writeAlignOne()
[2]151{
[56]152  unsigned int num_bits = getNumBitsUntilByteAligned();
153  write((1 << num_bits) - 1, num_bits);
154  return;
[2]155}
156
[56]157Void TComOutputBitstream::writeAlignZero()
[42]158{
[56]159  if (0 == m_num_held_bits)
160    return;
161  m_fifo->push_back(m_held_bits);
162  m_held_bits = 0;
163  m_num_held_bits = 0;
[42]164}
165
[56]166/**
167 - add substream to the end of the current bitstream
168 .
169 \param  pcSubstream  substream to be added
170 */
171Void   TComOutputBitstream::addSubstream( TComOutputBitstream* pcSubstream )
[2]172{
[56]173  UInt uiNumBits = pcSubstream->getNumberOfWrittenBits();
[2]174
[56]175  const vector<uint8_t>& rbsp = pcSubstream->getFIFO();
176  for (vector<uint8_t>::const_iterator it = rbsp.begin(); it != rbsp.end();)
[2]177  {
[56]178    write(*it++, 8);
[2]179  }
[56]180  if (uiNumBits&0x7)
[2]181  {
[56]182    write(pcSubstream->getHeldBits()>>(8-(uiNumBits&0x7)), uiNumBits&0x7);
[2]183  }
[56]184}
[2]185
[56]186/**
187 * read #uiNumberOfBits# from bitstream without updating the bitstream
188 * state, storing the result in #ruiBits#.
189 *
190 * If reading #uiNumberOfBits# would overrun the bitstream buffer,
191 * the bitsream is effectively padded with sufficient zero-bits to
192 * avoid the overrun.
193 */
194Void TComInputBitstream::pseudoRead ( UInt uiNumberOfBits, UInt& ruiBits )
195{
196  unsigned int saved_num_held_bits = m_num_held_bits;
197  unsigned char saved_held_bits = m_held_bits;
198  unsigned int saved_fifo_idx = m_fifo_idx;
199
200  unsigned num_bits_to_read = min(uiNumberOfBits, getNumBitsLeft());
201  read(num_bits_to_read, ruiBits);
202  ruiBits <<= (uiNumberOfBits - num_bits_to_read);
203
204  m_fifo_idx = saved_fifo_idx;
205  m_held_bits = saved_held_bits;
206  m_num_held_bits = saved_num_held_bits;
[2]207}
208
209
[56]210Void TComInputBitstream::read (UInt uiNumberOfBits, UInt& ruiBits)
[2]211{
212  assert( uiNumberOfBits <= 32 );
213 
[56]214#if TILES_WPP_ENTRY_POINT_SIGNALLING
215  m_numBitsRead += uiNumberOfBits;
216#endif
[2]217
[56]218  /* NB, bits are extracted from the MSB of each byte. */
219  unsigned retval = 0;
220  if (uiNumberOfBits <= m_num_held_bits)
[2]221  {
[56]222    /* n=1, len(H)=7:   -VHH HHHH, shift_down=6, mask=0xfe
223     * n=3, len(H)=7:   -VVV HHHH, shift_down=4, mask=0xf8
224     */
225    retval = m_held_bits >> (m_num_held_bits - uiNumberOfBits);
226    retval &= ~(0xff << uiNumberOfBits);
227    m_num_held_bits -= uiNumberOfBits;
228    ruiBits = retval;
[2]229    return;
230  }
231
[56]232  /* all num_held_bits will go into retval
233   *   => need to mask leftover bits from previous extractions
234   *   => align retval with top of extracted word */
235  /* n=5, len(H)=3: ---- -VVV, mask=0x07, shift_up=5-3=2,
236   * n=9, len(H)=3: ---- -VVV, mask=0x07, shift_up=9-3=6 */
237  uiNumberOfBits -= m_num_held_bits;
238  retval = m_held_bits & ~(0xff << m_num_held_bits);
239  retval <<= uiNumberOfBits;
[2]240
[56]241  /* number of whole bytes that need to be loaded to form retval */
242  /* n=32, len(H)=0, load 4bytes, shift_down=0
243   * n=32, len(H)=1, load 4bytes, shift_down=1
244   * n=31, len(H)=1, load 4bytes, shift_down=1+1
245   * n=8,  len(H)=0, load 1byte,  shift_down=0
246   * n=8,  len(H)=3, load 1byte,  shift_down=3
247   * n=5,  len(H)=1, load 1byte,  shift_down=1+3
248   */
249  unsigned aligned_word = 0;
250  unsigned num_bytes_to_load = (uiNumberOfBits - 1) >> 3;
251  assert(m_fifo_idx + num_bytes_to_load < m_fifo->size());
252
253  switch (num_bytes_to_load)
[2]254  {
[56]255  case 3: aligned_word  = (*m_fifo)[m_fifo_idx++] << 24;
256  case 2: aligned_word |= (*m_fifo)[m_fifo_idx++] << 16;
257  case 1: aligned_word |= (*m_fifo)[m_fifo_idx++] <<  8;
258  case 0: aligned_word |= (*m_fifo)[m_fifo_idx++];
[2]259  }
[56]260
261  /* resolve remainder bits */
262  unsigned next_num_held_bits = (32 - uiNumberOfBits) % 8;
263
264  /* copy required part of aligned_word into retval */
265  retval |= aligned_word >> next_num_held_bits;
266
267  /* store held bits */
268  m_num_held_bits = next_num_held_bits;
269  m_held_bits = aligned_word;
270
271  ruiBits = retval;
[2]272}
273
[56]274/**
275 * insert the contents of the bytealigned (and flushed) bitstream src
276 * into this at byte position pos.
277 */
278void TComOutputBitstream::insertAt(const TComOutputBitstream& src, unsigned pos)
[2]279{
[56]280  unsigned src_bits = src.getNumberOfWrittenBits();
281  assert(0 == src_bits % 8);
[42]282
[56]283  vector<uint8_t>::iterator at = this->m_fifo->begin() + pos;
284  this->m_fifo->insert(at, src.m_fifo->begin(), src.m_fifo->end());
285}
286
287Void TComInputBitstream::readOutTrailingBits ()
288{
289  UInt uiBits = 0;
290
291  while ( ( getNumBitsLeft() > 0 ) && (getNumBitsUntilByteAligned()!=0) )
[2]292  {
[56]293    read ( 1, uiBits );
[2]294  }
295}
296
[56]297TComOutputBitstream& TComOutputBitstream::operator= (const TComOutputBitstream& src)
[2]298{
[56]299  vector<uint8_t>::iterator at = this->m_fifo->begin();
300  this->m_fifo->insert(at, src.m_fifo->begin(), src.m_fifo->end());
301
302  this->m_num_held_bits             = src.m_num_held_bits;
303  this->m_held_bits                 = src.m_held_bits;
304  this->m_uiTileMarkerLocationCount = src.m_uiTileMarkerLocationCount;
305  for (Int uiIdx=0; uiIdx<m_uiTileMarkerLocationCount; uiIdx++)
[2]306  {
[56]307    this->m_puiTileMarkerLocation[uiIdx] = src.m_puiTileMarkerLocation[uiIdx];
[2]308  }
309
[56]310  return *this;
[2]311}
312
[56]313/**
314 - extract substream from the current bitstream
315 .
316 \param  pcBitstream  bitstream which contains substreams
317 \param  uiNumBits    number of bits to transfer
318 */
319TComInputBitstream *TComInputBitstream::extractSubstream( UInt uiNumBits )
[2]320{
[56]321  UInt uiNumBytes = uiNumBits/8;
322  std::vector<uint8_t>* buf = new std::vector<uint8_t>;
323  UInt uiByte;
324  for (UInt ui = 0; ui < uiNumBytes; ui++)
[2]325  {
[56]326    read(8, uiByte);
327    buf->push_back(uiByte);
[2]328  }
[56]329  if (uiNumBits&0x7)
330  {
331    uiByte = 0;
332    read(uiNumBits&0x7, uiByte);
333    uiByte <<= 8-(uiNumBits&0x7);
334    buf->push_back(uiByte);
335  }
336#if OL_FLUSH && !OL_FLUSH_ALIGN
337  buf->push_back(0); // The final chunk might not start byte aligned.
338#endif
339  return new TComInputBitstream(buf);
[2]340}
341
342/**
[56]343 - delete internal fifo
[2]344 */
[56]345Void TComInputBitstream::deleteFifo()
[2]346{
[56]347  delete m_fifo;
348  m_fifo = NULL;
349}
[2]350
[56]351//! \}
Note: See TracBrowser for help on using the repository browser.