HEVC Test Model (HM)  HM-16.3
TDecBinCoderCABAC.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 "TDecBinCoderCABAC.h"
39 #include "TLibCommon/Debug.h"
40 #if RExt__DECODER_DEBUG_BIT_STATISTICS
42 #endif
43 
46 
48 : m_pcTComBitstream( 0 )
49 {
50 }
51 
53 {
54 }
55 
56 Void
58 {
59  m_pcTComBitstream = pcTComBitstream;
60 }
61 
62 Void
64 {
66 }
67 
68 Void
70 {
72 #if RExt__DECODER_DEBUG_BIT_STATISTICS
74 #endif
75  m_uiRange = 510;
76  m_bitsNeeded = -8;
79 }
80 
81 Void
83 {
84  UInt lastByte;
85 
87  // Check for proper stop/alignment pattern
88  assert( ((lastByte << (8 + m_bitsNeeded)) & 0xff) == 0x80 );
89 }
90 
96 Void
97 TDecBinCABAC::copyState( const TDecBinIf* pcTDecBinIf )
98 {
99  const TDecBinCABAC* pcTDecBinCABAC = pcTDecBinIf->getTDecBinCABAC();
100  m_uiRange = pcTDecBinCABAC->m_uiRange;
101  m_uiValue = pcTDecBinCABAC->m_uiValue;
102  m_bitsNeeded= pcTDecBinCABAC->m_bitsNeeded;
103 }
104 
105 
106 
107 #if RExt__DECODER_DEBUG_BIT_STATISTICS
108 Void TDecBinCABAC::decodeBin( UInt& ruiBin, ContextModel &rcCtxModel, const TComCodingStatisticsClassType &whichStat )
109 #else
111 #endif
112 {
113 #ifdef DEBUG_CABAC_BINS
114  const UInt startingRange = m_uiRange;
115 #endif
116 
117  UInt uiLPS = TComCABACTables::sm_aucLPSTable[ rcCtxModel.getState() ][ ( m_uiRange >> 6 ) - 4 ];
118  m_uiRange -= uiLPS;
119  UInt scaledRange = m_uiRange << 7;
120 
121  if( m_uiValue < scaledRange )
122  {
123  // MPS path
124  ruiBin = rcCtxModel.getMps();
125 #if RExt__DECODER_DEBUG_BIT_STATISTICS
126  TComCodingStatistics::UpdateCABACStat(whichStat, m_uiRange+uiLPS, m_uiRange, Int(ruiBin));
127 #endif
128  rcCtxModel.updateMPS();
129 
130  if ( scaledRange < ( 256 << 7 ) )
131  {
132  m_uiRange = scaledRange >> 6;
133  m_uiValue += m_uiValue;
134 
135  if ( ++m_bitsNeeded == 0 )
136  {
137  m_bitsNeeded = -8;
138  m_uiValue += m_pcTComBitstream->readByte();
139  }
140  }
141  }
142  else
143  {
144  // LPS path
145  ruiBin = 1 - rcCtxModel.getMps();
146 #if RExt__DECODER_DEBUG_BIT_STATISTICS
147  TComCodingStatistics::UpdateCABACStat(whichStat, m_uiRange+uiLPS, uiLPS, Int(ruiBin));
148 #endif
149  Int numBits = TComCABACTables::sm_aucRenormTable[ uiLPS >> 3 ];
150  m_uiValue = ( m_uiValue - scaledRange ) << numBits;
151  m_uiRange = uiLPS << numBits;
152  rcCtxModel.updateLPS();
153 
154  m_bitsNeeded += numBits;
155 
156  if ( m_bitsNeeded >= 0 )
157  {
158  m_uiValue += m_pcTComBitstream->readByte() << m_bitsNeeded;
159  m_bitsNeeded -= 8;
160  }
161  }
162 
163 #ifdef DEBUG_CABAC_BINS
164  if ((g_debugCounter + debugCabacBinWindow) >= debugCabacBinTargetLine)
165  {
166  std::cout << g_debugCounter << ": coding bin value " << ruiBin << ", range = [" << startingRange << "->" << m_uiRange << "]\n";
167  }
168 
169  if (g_debugCounter >= debugCabacBinTargetLine)
170  {
171  Char breakPointThis;
172  breakPointThis = 7;
173  }
174  if (g_debugCounter >= (debugCabacBinTargetLine + debugCabacBinWindow))
175  {
176  exit(0);
177  }
178  g_debugCounter++;
179 #endif
180 }
181 
182 
183 #if RExt__DECODER_DEBUG_BIT_STATISTICS
185 #else
187 #endif
188 {
189  if (m_uiRange == 256)
190  {
191 #if RExt__DECODER_DEBUG_BIT_STATISTICS
192  decodeAlignedBinsEP(ruiBin, 1, whichStat);
193 #else
194  decodeAlignedBinsEP(ruiBin, 1);
195 #endif
196  return;
197  }
198 
199  m_uiValue += m_uiValue;
200 
201  if ( ++m_bitsNeeded >= 0 )
202  {
203  m_bitsNeeded = -8;
204  m_uiValue += m_pcTComBitstream->readByte();
205  }
206 
207  ruiBin = 0;
208  UInt scaledRange = m_uiRange << 7;
209  if ( m_uiValue >= scaledRange )
210  {
211  ruiBin = 1;
212  m_uiValue -= scaledRange;
213  }
214 #if RExt__DECODER_DEBUG_BIT_STATISTICS
215  TComCodingStatistics::IncrementStatisticEP(whichStat, 1, Int(ruiBin));
216 #endif
217 }
218 
219 #if RExt__DECODER_DEBUG_BIT_STATISTICS
220 Void TDecBinCABAC::decodeBinsEP( UInt& ruiBin, Int numBins, const TComCodingStatisticsClassType &whichStat )
221 #else
223 #endif
224 {
225  if (m_uiRange == 256)
226  {
227 #if RExt__DECODER_DEBUG_BIT_STATISTICS
228  decodeAlignedBinsEP(ruiBin, numBins, whichStat);
229 #else
230  decodeAlignedBinsEP(ruiBin, numBins);
231 #endif
232  return;
233  }
234 
235  UInt bins = 0;
236 #if RExt__DECODER_DEBUG_BIT_STATISTICS
237  Int origNumBins=numBins;
238 #endif
239  while ( numBins > 8 )
240  {
241  m_uiValue = ( m_uiValue << 8 ) + ( m_pcTComBitstream->readByte() << ( 8 + m_bitsNeeded ) );
242 
243  UInt scaledRange = m_uiRange << 15;
244  for ( Int i = 0; i < 8; i++ )
245  {
246  bins += bins;
247  scaledRange >>= 1;
248  if ( m_uiValue >= scaledRange )
249  {
250  bins++;
251  m_uiValue -= scaledRange;
252  }
253  }
254  numBins -= 8;
255  }
256 
257  m_bitsNeeded += numBins;
258  m_uiValue <<= numBins;
259 
260  if ( m_bitsNeeded >= 0 )
261  {
262  m_uiValue += m_pcTComBitstream->readByte() << m_bitsNeeded;
263  m_bitsNeeded -= 8;
264  }
265 
266  UInt scaledRange = m_uiRange << ( numBins + 7 );
267  for ( Int i = 0; i < numBins; i++ )
268  {
269  bins += bins;
270  scaledRange >>= 1;
271  if ( m_uiValue >= scaledRange )
272  {
273  bins++;
274  m_uiValue -= scaledRange;
275  }
276  }
277 
278  ruiBin = bins;
279 #if RExt__DECODER_DEBUG_BIT_STATISTICS
280  TComCodingStatistics::IncrementStatisticEP(whichStat, origNumBins, Int(ruiBin));
281 #endif
282 }
283 
285 {
286 #if RExt__DECODER_DEBUG_BIT_STATISTICS
288 #endif
289  m_uiRange = 256;
290 }
291 
292 #if RExt__DECODER_DEBUG_BIT_STATISTICS
293 Void TDecBinCABAC::decodeAlignedBinsEP( UInt& ruiBins, Int numBins, const class TComCodingStatisticsClassType &whichStat )
294 #else
296 #endif
297 {
298  Int binsRemaining = numBins;
299  ruiBins = 0;
300 
301  assert(m_uiRange == 256); //aligned decode only works when range = 256
302 
303  while (binsRemaining > 0)
304  {
305  const UInt binsToRead = std::min<UInt>(binsRemaining, 8); //read bytes if able to take advantage of the system's byte-read function
306  const UInt binMask = (1 << binsToRead) - 1;
307 
308  //The MSB of m_uiValue is known to be 0 because range is 256. Therefore:
309  // > The comparison against the symbol range of 128 is simply a test on the next-most-significant bit
310  // > "Subtracting" the symbol range if the decoded bin is 1 simply involves clearing that bit.
311  //
312  //As a result, the required bins are simply the <binsToRead> next-most-significant bits of m_uiValue
313  //(m_uiValue is stored MSB-aligned in a 16-bit buffer - hence the shift of 15)
314  //
315  // m_uiValue = |0|V|V|V|V|V|V|V|V|B|B|B|B|B|B|B| (V = usable bit, B = potential buffered bit (buffer refills when m_bitsNeeded >= 0))
316  //
317  const UInt newBins = (m_uiValue >> (15 - binsToRead)) & binMask;
318 
319  ruiBins = (ruiBins << binsToRead) | newBins;
320  m_uiValue = (m_uiValue << binsToRead) & 0x7FFF;
321 
322  binsRemaining -= binsToRead;
323  m_bitsNeeded += binsToRead;
324 
325  if (m_bitsNeeded >= 0)
326  {
327  m_uiValue |= m_pcTComBitstream->readByte() << m_bitsNeeded;
328  m_bitsNeeded -= 8;
329  }
330  }
331 
332 #if RExt__DECODER_DEBUG_BIT_STATISTICS
333  TComCodingStatistics::IncrementStatisticEP(whichStat, numBins, Int(ruiBins));
334 #endif
335 }
336 
337 Void
339 {
340  m_uiRange -= 2;
341  UInt scaledRange = m_uiRange << 7;
342  if( m_uiValue >= scaledRange )
343  {
344  ruiBin = 1;
345 #if RExt__DECODER_DEBUG_BIT_STATISTICS
348 #endif
349  }
350  else
351  {
352  ruiBin = 0;
353 #if RExt__DECODER_DEBUG_BIT_STATISTICS
355 #endif
356  if ( scaledRange < ( 256 << 7 ) )
357  {
358  m_uiRange = scaledRange >> 6;
359  m_uiValue += m_uiValue;
360 
361  if ( ++m_bitsNeeded == 0 )
362  {
363  m_bitsNeeded = -8;
365  }
366  }
367  }
368 }
369 
376 {
377  assert ( uiLength > 0 );
378  m_pcTComBitstream->read (uiLength, ruiCode);
379 #if RExt__DECODER_DEBUG_BIT_STATISTICS
381 #endif
382 }
Void decodeBinTrm(UInt &ruiBin)
UInt getNumBitsUntilByteAligned()
TComInputBitstream * m_pcTComBitstream
void Void
Definition: TypeDef.h:285
Void decodeBinsEP(UInt &ruiBin, Int numBins)
char Char
Definition: TypeDef.h:291
unsigned int UInt
Definition: TypeDef.h:297
UChar getState()
get current state
Definition: ContextModel.h:63
virtual ~TDecBinCABAC()
context model class
Definition: ContextModel.h:57
Void updateLPS()
Definition: ContextModel.h:69
Void peekPreviousByte(UInt &byte)
Void copyState(const TDecBinIf *pcTDecBinIf)
Void decodeBinEP(UInt &ruiBin)
Void init(TComInputBitstream *pcTComBitstream)
static Void UpdateCABACStat(const TComCodingStatisticsClassType &stat, UInt uiRangeBefore, UInt uiRangeAfter, Int val)
Void read(UInt uiNumberOfBits, UInt &ruiBits)
Void decodeBin(UInt &ruiBin, ContextModel &rcCtxModel)
Void decodeAlignedBinsEP(UInt &ruiBins, Int numBins)
UChar getMps()
get curret MPS
Definition: ContextModel.h:64
Void readByte(UInt &ruiBits)
static const UChar sm_aucLPSTable[1<< 6][4]
UInt g_debugCounter
Definition: Debug.cpp:193
int Int
Definition: TypeDef.h:296
Void xReadPCMCode(UInt uiLength, UInt &ruiCode)
virtual TDecBinCABAC * getTDecBinCABAC()
Definition: TDecBinCoder.h:80
static const UChar sm_aucRenormTable[32]
Void updateMPS()
Definition: ContextModel.h:74
static Void IncrementStatisticEP(const TComCodingStatisticsClassType &stat, const Int numBits, const Int value)
Defines types and objects for environment-variable-based debugging and feature control.
binary entropy decoder of CABAC