source: 3DVCSoftware/branches/HTM-15.1-dev0-NICT/source/Lib/TLibCommon/TComBitStream.cpp @ 1349

Last change on this file since 1349 was 1349, checked in by nict-htm, 9 years ago

FIX: TAppDecoder No Option (Help View) Abnormal end.
FIX: VC10 Compile order.
ADD: VC12, VC14 support.
NEW: ALTERNATIVE_DEPTH_INFO, not TBD.
BUG: TAppDecoder 15 frame abnormal end. (debug now)

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