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

Last change on this file since 399 was 296, checked in by tech, 12 years ago

Reintegrated branch 5.1-dev0 rev. 295.

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