source: SHVCSoftware/branches/SHM-1.0-dev/source/Lib/TLibCommon/TComBitStream.cpp @ 1510

Last change on this file since 1510 was 2, checked in by seregin, 12 years ago

Initial import by Vadim Seregin <vseregin@…>

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