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

Last change on this file since 761 was 608, checked in by tech, 11 years ago

Merged DEV-2.0-dev0@604.

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