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

Last change on this file since 1386 was 1386, checked in by tech, 9 years ago

Merged 15.1-dev1@1381.

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