HEVC Test Model (HM)  HM-16.18
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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-2017, 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 
64 : m_fifo()
65 , m_emulationPreventionByteLocation()
66 , m_fifo_idx(0)
67 , m_num_held_bits(0)
68 , m_held_bits(0)
69 , m_numBitsRead(0)
70 { }
71 
73 : m_fifo(src.m_fifo)
74 , m_emulationPreventionByteLocation(src.m_emulationPreventionByteLocation)
75 , m_fifo_idx(src.m_fifo_idx)
76 , m_num_held_bits(src.m_num_held_bits)
77 , m_held_bits(src.m_held_bits)
78 , m_numBitsRead(src.m_numBitsRead)
79 { }
80 
81 // ====================================================================================================================
82 // Public member functions
83 // ====================================================================================================================
84 
86 {
87  m_fifo_idx=0;
89  m_held_bits=0;
90  m_numBitsRead=0;
91 }
92 
94 {
95  return (UChar*) &m_fifo.front();
96 }
97 
99 {
100  return UInt(m_fifo.size());
101 }
102 
104 {
105  m_fifo.clear();
106  m_held_bits = 0;
107  m_num_held_bits = 0;
108 }
109 
110 Void TComOutputBitstream::write ( UInt uiBits, UInt uiNumberOfBits )
111 {
112  assert( uiNumberOfBits <= 32 );
113  assert( uiNumberOfBits == 32 || (uiBits & (~0 << uiNumberOfBits)) == 0 );
114 
115  /* any modulo 8 remainder of num_total_bits cannot be written this time,
116  * and will be held until next time. */
117  UInt num_total_bits = uiNumberOfBits + m_num_held_bits;
118  UInt next_num_held_bits = num_total_bits % 8;
119 
120  /* form a byte aligned word (write_bits), by concatenating any held bits
121  * with the new bits, discarding the bits that will form the next_held_bits.
122  * eg: H = held bits, V = n new bits /---- next_held_bits
123  * len(H)=7, len(V)=1: ... ---- HHHH HHHV . 0000 0000, next_num_held_bits=0
124  * len(H)=7, len(V)=2: ... ---- HHHH HHHV . V000 0000, next_num_held_bits=1
125  * if total_bits < 8, the value of v_ is not used */
126  UChar next_held_bits = uiBits << (8 - next_num_held_bits);
127 
128  if (!(num_total_bits >> 3))
129  {
130  /* insufficient bits accumulated to write out, append new_held_bits to
131  * current held_bits */
132  /* NB, this requires that v only contains 0 in bit positions {31..n} */
133  m_held_bits |= next_held_bits;
134  m_num_held_bits = next_num_held_bits;
135  return;
136  }
137 
138  /* topword serves to justify held_bits to align with the msb of uiBits */
139  UInt topword = (uiNumberOfBits - next_num_held_bits) & ~((1 << 3) -1);
140  UInt write_bits = (m_held_bits << topword) | (uiBits >> next_num_held_bits);
141 
142  switch (num_total_bits >> 3)
143  {
144  case 4: m_fifo.push_back(write_bits >> 24);
145  case 3: m_fifo.push_back(write_bits >> 16);
146  case 2: m_fifo.push_back(write_bits >> 8);
147  case 1: m_fifo.push_back(write_bits);
148  }
149 
150  m_held_bits = next_held_bits;
151  m_num_held_bits = next_num_held_bits;
152 }
153 
155 {
156  UInt num_bits = getNumBitsUntilByteAligned();
157  write((1 << num_bits) - 1, num_bits);
158  return;
159 }
160 
162 {
163  if (0 == m_num_held_bits)
164  {
165  return;
166  }
167  m_fifo.push_back(m_held_bits);
168  m_held_bits = 0;
169  m_num_held_bits = 0;
170 }
171 
178 {
179  UInt uiNumBits = pcSubstream->getNumberOfWrittenBits();
180 
181  const vector<uint8_t>& rbsp = pcSubstream->getFIFO();
182  for (vector<uint8_t>::const_iterator it = rbsp.begin(); it != rbsp.end();)
183  {
184  write(*it++, 8);
185  }
186  if (uiNumBits&0x7)
187  {
188  write(pcSubstream->getHeldBits()>>(8-(uiNumBits&0x7)), uiNumBits&0x7);
189  }
190 }
191 
193 {
194  write( 1, 1);
195  writeAlignZero();
196 }
197 
199 {
200  UInt cnt = 0;
201  vector<uint8_t>& rbsp = getFIFO();
202  for (vector<uint8_t>::iterator it = rbsp.begin(); it != rbsp.end();)
203  {
204  vector<uint8_t>::iterator found = it;
205  do
206  {
207  // find the next emulated 00 00 {00,01,02,03}
208  // NB, end()-1, prevents finding a trailing two byte sequence
209  found = search_n(found, rbsp.end()-1, 2, 0);
210  found++;
211  // if not found, found == end, otherwise found = second zero byte
212  if (found == rbsp.end())
213  {
214  break;
215  }
216  if (*(++found) <= 3)
217  {
218  break;
219  }
220  } while (true);
221  it = found;
222  if (found != rbsp.end())
223  {
224  cnt++;
225  }
226  }
227  return cnt;
228 }
229 
238 Void TComInputBitstream::pseudoRead ( UInt uiNumberOfBits, UInt& ruiBits )
239 {
240  UInt saved_num_held_bits = m_num_held_bits;
241  UChar saved_held_bits = m_held_bits;
242  UInt saved_fifo_idx = m_fifo_idx;
243 
244  UInt num_bits_to_read = min(uiNumberOfBits, getNumBitsLeft());
245  read(num_bits_to_read, ruiBits);
246  ruiBits <<= (uiNumberOfBits - num_bits_to_read);
247 
248  m_fifo_idx = saved_fifo_idx;
249  m_held_bits = saved_held_bits;
250  m_num_held_bits = saved_num_held_bits;
251 }
252 
253 
254 Void TComInputBitstream::read (UInt uiNumberOfBits, UInt& ruiBits)
255 {
256  assert( uiNumberOfBits <= 32 );
257 
258  m_numBitsRead += uiNumberOfBits;
259 
260  /* NB, bits are extracted from the MSB of each byte. */
261  UInt retval = 0;
262  if (uiNumberOfBits <= m_num_held_bits)
263  {
264  /* n=1, len(H)=7: -VHH HHHH, shift_down=6, mask=0xfe
265  * n=3, len(H)=7: -VVV HHHH, shift_down=4, mask=0xf8
266  */
267  retval = m_held_bits >> (m_num_held_bits - uiNumberOfBits);
268  retval &= ~(0xff << uiNumberOfBits);
269  m_num_held_bits -= uiNumberOfBits;
270  ruiBits = retval;
271  return;
272  }
273 
274  /* all num_held_bits will go into retval
275  * => need to mask leftover bits from previous extractions
276  * => align retval with top of extracted word */
277  /* n=5, len(H)=3: ---- -VVV, mask=0x07, shift_up=5-3=2,
278  * n=9, len(H)=3: ---- -VVV, mask=0x07, shift_up=9-3=6 */
279  uiNumberOfBits -= m_num_held_bits;
280  retval = m_held_bits & ~(0xff << m_num_held_bits);
281  retval <<= uiNumberOfBits;
282 
283  /* number of whole bytes that need to be loaded to form retval */
284  /* n=32, len(H)=0, load 4bytes, shift_down=0
285  * n=32, len(H)=1, load 4bytes, shift_down=1
286  * n=31, len(H)=1, load 4bytes, shift_down=1+1
287  * n=8, len(H)=0, load 1byte, shift_down=0
288  * n=8, len(H)=3, load 1byte, shift_down=3
289  * n=5, len(H)=1, load 1byte, shift_down=1+3
290  */
291  UInt aligned_word = 0;
292  UInt num_bytes_to_load = (uiNumberOfBits - 1) >> 3;
293  assert(m_fifo_idx + num_bytes_to_load < m_fifo.size());
294 
295  switch (num_bytes_to_load)
296  {
297  case 3: aligned_word = m_fifo[m_fifo_idx++] << 24;
298  case 2: aligned_word |= m_fifo[m_fifo_idx++] << 16;
299  case 1: aligned_word |= m_fifo[m_fifo_idx++] << 8;
300  case 0: aligned_word |= m_fifo[m_fifo_idx++];
301  }
302 
303  /* resolve remainder bits */
304  UInt next_num_held_bits = (32 - uiNumberOfBits) % 8;
305 
306  /* copy required part of aligned_word into retval */
307  retval |= aligned_word >> next_num_held_bits;
308 
309  /* store held bits */
310  m_num_held_bits = next_num_held_bits;
311  m_held_bits = aligned_word;
312 
313  ruiBits = retval;
314 }
315 
321 {
322  UInt src_bits = src.getNumberOfWrittenBits();
323  assert(0 == src_bits % 8);
324 
325  vector<uint8_t>::iterator at = m_fifo.begin() + pos;
326  m_fifo.insert(at, src.m_fifo.begin(), src.m_fifo.end());
327 }
328 
330 {
331  UInt count=0;
332  UInt uiBits = 0;
333 
334  while ( ( getNumBitsLeft() > 0 ) && (getNumBitsUntilByteAligned()!=0) )
335  {
336  count++;
337  read ( 1, uiBits );
338  }
339  return count;
340 }
341 //
342 //TComOutputBitstream& TComOutputBitstream::operator= (const TComOutputBitstream& src)
343 //{
344 // vector<uint8_t>::iterator at = m_fifo.begin();
345 // m_fifo.insert(at, src.m_fifo.begin(), src.m_fifo.end());
346 //
347 // m_num_held_bits = src.m_num_held_bits;
348 // m_held_bits = src.m_held_bits;
349 //
350 // return *this;
351 //}
352 
359 {
360  UInt uiNumBytes = uiNumBits/8;
361  TComInputBitstream *pResult = new TComInputBitstream;
362 
363  std::vector<uint8_t> &buf = pResult->getFifo();
364  buf.reserve((uiNumBits+7)>>3);
365 
366  if (m_num_held_bits == 0)
367  {
368  std::size_t currentOutputBufferSize=buf.size();
369  const UInt uiNumBytesToReadFromFifo = std::min<UInt>(uiNumBytes, (UInt)m_fifo.size() - m_fifo_idx);
370  buf.resize(currentOutputBufferSize+uiNumBytes);
371  memcpy(&(buf[currentOutputBufferSize]), &(m_fifo[m_fifo_idx]), uiNumBytesToReadFromFifo); m_fifo_idx+=uiNumBytesToReadFromFifo;
372  if (uiNumBytesToReadFromFifo != uiNumBytes)
373  {
374  memset(&(buf[currentOutputBufferSize+uiNumBytesToReadFromFifo]), 0, uiNumBytes - uiNumBytesToReadFromFifo);
375  }
376  }
377  else
378  {
379  for (UInt ui = 0; ui < uiNumBytes; ui++)
380  {
381  UInt uiByte;
382  read(8, uiByte);
383  buf.push_back(uiByte);
384  }
385  }
386  if (uiNumBits&0x7)
387  {
388  UInt uiByte = 0;
389  read(uiNumBits&0x7, uiByte);
390  uiByte <<= 8-(uiNumBits&0x7);
391  buf.push_back(uiByte);
392  }
393  return pResult;
394 }
395 
397 {
398  UInt code = 0;
399  read( 1, code );
400  assert(code == 1);
401 
402  UInt numBits = getNumBitsUntilByteAligned();
403  if(numBits)
404  {
405  assert(numBits <= getNumBitsLeft());
406  read( numBits, code );
407  assert(code == 0);
408  }
409  return numBits+1;
410 }
411 
Void insertAt(const TComOutputBitstream &src, UInt pos)
UInt getNumBitsUntilByteAligned()
void Void
Definition: TypeDef.h:203
TComInputBitstream * extractSubstream(UInt uiNumBits)
const std::vector< uint8_t > & getFifo() const
unsigned int UInt
Definition: TypeDef.h:212
Int getNumBitsUntilByteAligned() const
Int countStartCodeEmulations()
returns the number of start code emulations contained in the current buffer
std::vector< uint8_t > & getFIFO()
UChar m_held_bits
number of bits not flushed to bytestream.
Definition: TComBitStream.h:86
std::vector< uint8_t > m_fifo
UInt getNumberOfWrittenBits() const
std::vector< uint8_t > m_fifo
Definition: TComBitStream.h:83
unsigned char UChar
Definition: TypeDef.h:208
Void pseudoRead(UInt uiNumberOfBits, UInt &ruiBits)
class for handling bitstream (header)
Void read(UInt uiNumberOfBits, UInt &ruiBits)
UChar * getByteStream() const
TComOutputBitstream()
this value is always msb-aligned, bigendian.
UInt m_num_held_bits
Read index into m_fifo.
int Int
Definition: TypeDef.h:211
Void write(UInt uiBits, UInt uiNumberOfBits)
Void addSubstream(TComOutputBitstream *pcSubstream)