source: SHVCSoftware/branches/SHM-temp/source/Lib/TLibCommon/TComBitStream.cpp @ 1164

Last change on this file since 1164 was 1029, checked in by seregin, 10 years ago

merge with SHM-upgrade branch

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