HEVC Test Model (HM)  HM-16.3
TComBitStream.cpp
Go to the documentation of this file.
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 
38 #include <stdint.h>
39 #include <vector>
40 #include "TComBitStream.h"
41 #include <string.h>
42 #include <memory.h>
43 
44 using namespace std;
45 
48 
49 // ====================================================================================================================
50 // Constructor / destructor / create / destroy
51 // ====================================================================================================================
52 
54 {
55  clear();
56 }
57 
59 {
60 }
61 
62 TComInputBitstream::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 
72 {
73 }
74 
75 // ====================================================================================================================
76 // Public member functions
77 // ====================================================================================================================
78 
80 {
81  return (Char*) &m_fifo.front();
82 }
83 
85 {
86  return UInt(m_fifo.size());
87 }
88 
90 {
91  m_fifo.clear();
92  m_held_bits = 0;
93  m_num_held_bits = 0;
94 }
95 
96 Void 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 
141 {
142  UInt num_bits = getNumBitsUntilByteAligned();
143  write((1 << num_bits) - 1, num_bits);
144  return;
145 }
146 
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 
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 
179 {
180  write( 1, 1);
181  writeAlignZero();
182 }
183 
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 
224 Void 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 
230  UInt num_bits_to_read = min(uiNumberOfBits, getNumBitsLeft());
231  read(num_bits_to_read, ruiBits);
232  ruiBits <<= (uiNumberOfBits - num_bits_to_read);
233 
234  m_fifo_idx = saved_fifo_idx;
235  m_held_bits = saved_held_bits;
236  m_num_held_bits = saved_num_held_bits;
237 }
238 
239 
240 Void TComInputBitstream::read (UInt uiNumberOfBits, UInt& ruiBits)
241 {
242  assert( uiNumberOfBits <= 32 );
243 
244  m_numBitsRead += uiNumberOfBits;
245 
246  /* NB, bits are extracted from the MSB of each byte. */
247  UInt retval = 0;
248  if (uiNumberOfBits <= m_num_held_bits)
249  {
250  /* n=1, len(H)=7: -VHH HHHH, shift_down=6, mask=0xfe
251  * n=3, len(H)=7: -VVV HHHH, shift_down=4, mask=0xf8
252  */
253  retval = m_held_bits >> (m_num_held_bits - uiNumberOfBits);
254  retval &= ~(0xff << uiNumberOfBits);
255  m_num_held_bits -= uiNumberOfBits;
256  ruiBits = retval;
257  return;
258  }
259 
260  /* all num_held_bits will go into retval
261  * => need to mask leftover bits from previous extractions
262  * => align retval with top of extracted word */
263  /* n=5, len(H)=3: ---- -VVV, mask=0x07, shift_up=5-3=2,
264  * n=9, len(H)=3: ---- -VVV, mask=0x07, shift_up=9-3=6 */
265  uiNumberOfBits -= m_num_held_bits;
266  retval = m_held_bits & ~(0xff << m_num_held_bits);
267  retval <<= uiNumberOfBits;
268 
269  /* number of whole bytes that need to be loaded to form retval */
270  /* n=32, len(H)=0, load 4bytes, shift_down=0
271  * n=32, len(H)=1, load 4bytes, shift_down=1
272  * n=31, len(H)=1, load 4bytes, shift_down=1+1
273  * n=8, len(H)=0, load 1byte, shift_down=0
274  * n=8, len(H)=3, load 1byte, shift_down=3
275  * n=5, len(H)=1, load 1byte, shift_down=1+3
276  */
277  UInt aligned_word = 0;
278  UInt num_bytes_to_load = (uiNumberOfBits - 1) >> 3;
279  assert(m_fifo_idx + num_bytes_to_load < m_fifo->size());
280 
281  switch (num_bytes_to_load)
282  {
283  case 3: aligned_word = (*m_fifo)[m_fifo_idx++] << 24;
284  case 2: aligned_word |= (*m_fifo)[m_fifo_idx++] << 16;
285  case 1: aligned_word |= (*m_fifo)[m_fifo_idx++] << 8;
286  case 0: aligned_word |= (*m_fifo)[m_fifo_idx++];
287  }
288 
289  /* resolve remainder bits */
290  UInt next_num_held_bits = (32 - uiNumberOfBits) % 8;
291 
292  /* copy required part of aligned_word into retval */
293  retval |= aligned_word >> next_num_held_bits;
294 
295  /* store held bits */
296  m_num_held_bits = next_num_held_bits;
297  m_held_bits = aligned_word;
298 
299  ruiBits = retval;
300 }
301 
307 {
308  UInt src_bits = src.getNumberOfWrittenBits();
309  assert(0 == src_bits % 8);
310 
311  vector<uint8_t>::iterator at = m_fifo.begin() + pos;
312  m_fifo.insert(at, src.m_fifo.begin(), src.m_fifo.end());
313 }
314 
316 {
317  UInt count=0;
318  UInt uiBits = 0;
319 
320  while ( ( getNumBitsLeft() > 0 ) && (getNumBitsUntilByteAligned()!=0) )
321  {
322  count++;
323  read ( 1, uiBits );
324  }
325  return count;
326 }
327 //
328 //TComOutputBitstream& TComOutputBitstream::operator= (const TComOutputBitstream& src)
329 //{
330 // vector<uint8_t>::iterator at = m_fifo.begin();
331 // m_fifo.insert(at, src.m_fifo.begin(), src.m_fifo.end());
332 //
333 // m_num_held_bits = src.m_num_held_bits;
334 // m_held_bits = src.m_held_bits;
335 //
336 // return *this;
337 //}
338 
345 {
346  UInt uiNumBytes = uiNumBits/8;
347  std::vector<uint8_t>* buf = new std::vector<uint8_t>;
348  UInt uiByte;
349  for (UInt ui = 0; ui < uiNumBytes; ui++)
350  {
351  read(8, uiByte);
352  buf->push_back(uiByte);
353  }
354  if (uiNumBits&0x7)
355  {
356  uiByte = 0;
357  read(uiNumBits&0x7, uiByte);
358  uiByte <<= 8-(uiNumBits&0x7);
359  buf->push_back(uiByte);
360  }
361  return new TComInputBitstream(buf);
362 }
363 
368 {
369  delete m_fifo;
370  m_fifo = NULL;
371 }
372 
374 {
375  UInt code = 0;
376  read( 1, code );
377  assert(code == 1);
378 
379  UInt numBits = getNumBitsUntilByteAligned();
380  if(numBits)
381  {
382  assert(numBits <= getNumBitsLeft());
383  read( numBits, code );
384  assert(code == 0);
385  }
386  return numBits+1;
387 }
388 
Void write(ostream &out, OutputNALUnit &nalu)
Definition: NALwrite.cpp:64
TComInputBitstream(std::vector< uint8_t > *buf)
Void insertAt(const TComOutputBitstream &src, UInt pos)
void Void
Definition: TypeDef.h:285
TComInputBitstream * extractSubstream(UInt uiNumBits)
#define NULL
Definition: CommonDef.h:100
char Char
Definition: TypeDef.h:291
unsigned int UInt
Definition: TypeDef.h:297
STL namespace.
Void read(InputNALUnit &nalu, vector< uint8_t > &nalUnitBuf)
Definition: NALread.cpp:147
Int countStartCodeEmulations()
returns the number of start code emulations contained in the current buffer
std::vector< uint8_t > & getFIFO()
UInt getNumberOfWrittenBits() const
Char * getByteStream() const
std::vector< uint8_t > m_fifo
Definition: TComBitStream.h:82
unsigned char UChar
Definition: TypeDef.h:293
Void pseudoRead(UInt uiNumberOfBits, UInt &ruiBits)
class for handling bitstream (header)
Void read(UInt uiNumberOfBits, UInt &ruiBits)
TComOutputBitstream()
this value is always msb-aligned, bigendian.
int Int
Definition: TypeDef.h:296
Void write(UInt uiBits, UInt uiNumberOfBits)
Void addSubstream(TComOutputBitstream *pcSubstream)