Newer
Older

Karsten Suehring
committed
/* The copyright in this software is being made available under the BSD
* License, included below. This software may be subject to other third party
* and contributor rights, including patent rights, and no such rights are
* granted under this license.
*

Karsten Suehring
committed
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file BinDecoder.cpp
* \brief Low level binary symbol writer
*/
#include "BinDecoder.h"
#include "CommonLib/Rom.h"
#if RExt__DECODER_DEBUG_BIT_STATISTICS
#include "CommonLib/CodingStatistics.h"
#endif
#include "CommonLib/dtrace_next.h"
template<class BinProbModel>
BinDecoderBase::BinDecoderBase(const BinProbModel *dummy)
: Ctx(dummy), m_bitstream(nullptr), m_range(0), m_value(0), m_bitsNeeded(0)

Karsten Suehring
committed
{}
void BinDecoderBase::init( InputBitstream* bitstream )
{

Karsten Suehring
committed
}
void BinDecoderBase::uninit()
{

Karsten Suehring
committed
}
void BinDecoderBase::start()
{
CHECK(m_bitstream->getNumBitsUntilByteAligned(), "Bitstream is not byte aligned.");

Karsten Suehring
committed
#if RExt__DECODER_DEBUG_BIT_STATISTICS
CodingStatistics::UpdateCABACStat(STATS__CABAC_INITIALISATION, 512, 510, 0);
#endif
m_range = 510;
m_value = (m_bitstream->readByte() << 8) + m_bitstream->readByte();

Karsten Suehring
committed
m_bitsNeeded = -8;
}
void BinDecoderBase::finish()
{
unsigned lastByte;

Karsten Suehring
committed
CHECK( ( ( lastByte << ( 8 + m_bitsNeeded ) ) & 0xff ) != 0x80,
"No proper stop/alignment pattern at end of CABAC stream." );
}
void BinDecoderBase::reset( int qp, int initId )
{
Ctx::init( qp, initId );
start();
}
void BinDecoderBase::riceStatReset(int bitDepth, bool persistentRiceAdaptationEnabledFlag)
Ctx::riceStatReset(bitDepth, persistentRiceAdaptationEnabledFlag);

Karsten Suehring
committed
unsigned BinDecoderBase::decodeBinEP()
{

Karsten Suehring
committed
if( ++m_bitsNeeded >= 0 )
{

Karsten Suehring
committed
m_bitsNeeded = -8;
}
unsigned bin = 0;
unsigned scaledRange = m_range << 7;
if (m_value >= scaledRange)

Karsten Suehring
committed
{

Karsten Suehring
committed
bin = 1;
}
#if RExt__DECODER_DEBUG_BIT_STATISTICS
CodingStatistics::IncrementStatisticEP( *ptype, 1, int(bin) );
#endif
DTRACE(g_trace_ctx, D_CABAC, "%d %d EP=%d \n", DTRACE_GET_COUNTER(g_trace_ctx, D_CABAC), m_range, bin);

Karsten Suehring
committed
return bin;
}
unsigned BinDecoderBase::decodeBinsEP( unsigned numBins )
{
#if ENABLE_TRACING
int numBinsOrig = numBins;
#endif

Karsten Suehring
committed
{
return decodeAlignedBinsEP( numBins );
}
unsigned remBins = numBins;
unsigned bins = 0;
while( remBins > 8 )
{
m_value = (m_value << 8) + (m_bitstream->readByte() << (8 + m_bitsNeeded));
unsigned scaledRange = m_range << 15;

Karsten Suehring
committed
for( int i = 0; i < 8; i++ )
{
bins += bins;

Karsten Suehring
committed
{
bins ++;

Karsten Suehring
committed
}
}
remBins -= 8;
}
m_bitsNeeded += remBins;

Karsten Suehring
committed
if( m_bitsNeeded >= 0 )
{

Karsten Suehring
committed
m_bitsNeeded -= 8;
}

Karsten Suehring
committed
for ( int i = 0; i < remBins; i++ )
{
bins += bins;

Karsten Suehring
committed
{
bins ++;

Karsten Suehring
committed
}
}
#if RExt__DECODER_DEBUG_BIT_STATISTICS
CodingStatistics::IncrementStatisticEP( *ptype, numBins, int(bins) );
#endif
#if ENABLE_TRACING
for( int i = 0; i < numBinsOrig; i++ )
{
DTRACE(g_trace_ctx, D_CABAC, "%d %d EP=%d \n", DTRACE_GET_COUNTER(g_trace_ctx, D_CABAC), m_range,
(bins >> (numBinsOrig - 1 - i)) & 1);

Karsten Suehring
committed
}
#endif
return bins;
}
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
unsigned BinDecoderBase::decodeRemAbsEP(unsigned goRicePar, unsigned cutoff, int maxLog2TrDynamicRange)
{
unsigned prefix = 0;
{
const unsigned maxPrefix = 32 - maxLog2TrDynamicRange;
unsigned codeWord = 0;
do
{
prefix++;
codeWord = decodeBinEP();
} while (codeWord && prefix < maxPrefix);
prefix -= 1 - codeWord;
}
unsigned length = goRicePar, offset;
if (prefix < cutoff)
{
offset = prefix << goRicePar;
}
else
{
offset = (((1 << (prefix - cutoff)) + cutoff - 1) << goRicePar);
{
length += (prefix == (32 - maxLog2TrDynamicRange) ? maxLog2TrDynamicRange - goRicePar : prefix - cutoff);
}
}
return offset + decodeBinsEP(length);
}

Karsten Suehring
committed
unsigned BinDecoderBase::decodeBinTrm()
{
m_range -= 2;
unsigned scaledRange = m_range << 7;
if (m_value >= scaledRange)

Karsten Suehring
committed
{
#if RExt__DECODER_DEBUG_BIT_STATISTICS
CodingStatistics::UpdateCABACStat(STATS__CABAC_TRM_BITS, m_range + 2, 2, 1);

Karsten Suehring
committed
CodingStatistics::IncrementStatisticEP( STATS__BYTE_ALIGNMENT_BITS, -m_bitsNeeded, 0 );
#endif
return 1;
}
else
{
#if RExt__DECODER_DEBUG_BIT_STATISTICS
CodingStatistics::UpdateCABACStat(STATS__CABAC_TRM_BITS, m_range + 2, m_range, 0);

Karsten Suehring
committed
#endif

Karsten Suehring
committed
{

Karsten Suehring
committed
if( ++m_bitsNeeded == 0 )
{

Karsten Suehring
committed
m_bitsNeeded = -8;
}
}
return 0;
}
}
void BinDecoderBase::align()
{
#if RExt__DECODER_DEBUG_BIT_STATISTICS
CodingStatistics::UpdateCABACStat(STATS__CABAC_EP_BIT_ALIGNMENT, m_range, 256, 0);

Karsten Suehring
committed
#endif

Karsten Suehring
committed
}
unsigned BinDecoderBase::decodeAlignedBinsEP( unsigned numBins )
{
#if ENABLE_TRACING
int numBinsOrig = numBins;
#endif
unsigned remBins = numBins;
unsigned bins = 0;
while( remBins > 0 )
{
// The MSB of m_value is known to be 0 because range is 256. Therefore:

Karsten Suehring
committed
// > The comparison against the symbol range of 128 is simply a test on the next-most-significant bit
// > "Subtracting" the symbol range if the decoded bin is 1 simply involves clearing that bit.
// As a result, the required bins are simply the <binsToRead> next-most-significant bits of m_value
// (m_value is stored MSB-aligned in a 16-bit buffer - hence the shift of 15)

Karsten Suehring
committed
//
// m_value = |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))

Karsten Suehring
committed
//
unsigned binsToRead = std::min<unsigned>( remBins, 8 ); //read bytes if able to take advantage of the system's byte-read function
unsigned binMask = ( 1 << binsToRead ) - 1;
unsigned newBins = (m_value >> (15 - binsToRead)) & binMask;

Karsten Suehring
committed
bins = ( bins << binsToRead) | newBins;

Karsten Suehring
committed
remBins -= binsToRead;
m_bitsNeeded += binsToRead;
if( m_bitsNeeded >= 0 )
{

Karsten Suehring
committed
m_bitsNeeded -= 8;
}
}
#if RExt__DECODER_DEBUG_BIT_STATISTICS
CodingStatistics::IncrementStatisticEP( *ptype, numBins, int(bins) );
#endif
#if ENABLE_TRACING
for( int i = 0; i < numBinsOrig; i++ )
{
DTRACE(g_trace_ctx, D_CABAC, "%d %d EP=%d \n", DTRACE_GET_COUNTER(g_trace_ctx, D_CABAC), m_range,
(bins >> (numBinsOrig - 1 - i)) & 1);

Karsten Suehring
committed
}
#endif
return bins;
}

Karsten Suehring
committed
TBinDecoder<BinProbModel>::TBinDecoder()
: BinDecoderBase(static_cast<const BinProbModel *>(nullptr)), m_ctx(static_cast<CtxStore<BinProbModel> &>(*this))

Karsten Suehring
committed
{}
template <class BinProbModel>
unsigned TBinDecoder<BinProbModel>::decodeBin( unsigned ctxId )
{
BinProbModel &probModel = m_ctx[ctxId];
unsigned bin = probModel.mps();
uint32_t lpsRange = probModel.getLPS(m_range);

Karsten Suehring
committed
DTRACE(g_trace_ctx, D_CABAC, "%d %d %d [%d:%d] %2d(MPS=%d) ", DTRACE_GET_COUNTER(g_trace_ctx, D_CABAC), ctxId,
m_range, m_range - lpsRange, lpsRange, (unsigned int) (probModel.state()),
m_value < ((m_range - lpsRange) << 7));

Karsten Suehring
committed
m_range -= lpsRange;
uint32_t scaledRange = m_range << 7;
if (m_value < scaledRange)

Karsten Suehring
committed
{
#if RExt__DECODER_DEBUG_BIT_STATISTICS
CodingStatistics::UpdateCABACStat(*ptype, m_range + lpsRange, m_range, int(bin));

Karsten Suehring
committed
#endif
// MPS path

Karsten Suehring
committed
{
int numBits = probModel.getRenormBitsRange(m_range);
m_range <<= numBits;
m_value <<= numBits;

Karsten Suehring
committed
m_bitsNeeded += numBits;
if( m_bitsNeeded >= 0 )
{

Karsten Suehring
committed
m_bitsNeeded -= 8;
}
}
}
else
{
bin = 1 - bin;
#if RExt__DECODER_DEBUG_BIT_STATISTICS
CodingStatistics::UpdateCABACStat(*ptype, m_range + lpsRange, lpsRange, int(bin));

Karsten Suehring
committed
#endif
// LPS path
int numBits = probModel.getRenormBitsLPS(lpsRange);
m_value -= scaledRange;
m_value = m_value << numBits;
m_range = lpsRange << numBits;

Karsten Suehring
committed
m_bitsNeeded += numBits;
if( m_bitsNeeded >= 0 )
{

Karsten Suehring
committed
m_bitsNeeded -= 8;
}
}

Karsten Suehring
committed
//DTRACE_DECR_COUNTER( g_trace_ctx, D_CABAC );
DTRACE_WITHOUT_COUNT( g_trace_ctx, D_CABAC, " - " "%d" "\n", bin );
return bin;
}
template class TBinDecoder<BinProbModel_Std>;