H.266におけるエントロピー符号化のまとめ
4146 ワード
継続的な更新...
1.コンテキストベースの適応コンテキスト算術符号化には、TEncBinCABACクラスのencodeBin関数と、TEncBinCABACCounterクラスのencodeBin関数の2つの関数があり、前者はビットをコードストリームファイルに書き込むことができ、後者はエントロピー符号化のビット数(輝度予測モードで使用されるMPMおよびその他)を計算するだけである
2.nビットの固定長符号化(4ビットの固定長符号化は輝度予測モードにおける16種類の選択モードに用いられる)
3.カットオフ二元符号(輝度予測モードにおける45種類の非選択モード用)
1.コンテキストベースの適応コンテキスト算術符号化には、TEncBinCABACクラスのencodeBin関数と、TEncBinCABACCounterクラスのencodeBin関数の2つの関数があり、前者はビットをコードストリームファイルに書き込むことができ、後者はエントロピー符号化のビット数(輝度予測モードで使用されるMPMおよびその他)を計算するだけである
Void TEncBinCABAC::encodeBin( UInt binValue, ContextModel &rcCtxModel )
{
#if !VCEG_AZ05_MULTI_PARAM_CABAC
m_uiBinsCoded += m_binCountIncrement;
rcCtxModel.setBinsCoded( 1 );
UInt uiCtxIdx = rcCtxModel.getIdx();
if(m_bUpdateStr && m_iCounter[uiCtxIdx] < CABAC_NUM_BINS)
{
m_pbCodedString[uiCtxIdx][m_iCounter[uiCtxIdx]] = (binValue==1? true:false);
m_iCounter[uiCtxIdx] ++;
}
#endif
UShort uiLPS = TComCABACTables::sm_aucLPSTable[rcCtxModel.getState()>>6][(m_uiRange>>2)-64];
m_uiRange -= uiLPS;
if( binValue == 0 )
{
rcCtxModel.updateLPS();
Int numBits = TComCABACTables::sm_aucRenormTable[ uiLPS >> 2 ];
if (numBits)
{
m_uiLow = ( m_uiLow + m_uiRange ) << numBits;
m_uiRange = uiLPS << numBits;
m_bitsLeft -= numBits;
}
else
{
m_uiLow = m_uiLow + m_uiRange ;
m_uiRange = uiLPS ;
}
}
else
{
rcCtxModel.updateMPS();
if ( m_uiRange >= 256 )
{
return;
}
Int numBits = TComCABACTables::sm_aucRenormTable[ m_uiRange >> 2 ];
m_uiLow <<= numBits;
m_uiRange <<= numBits;
m_bitsLeft -= numBits;
}
testAndWriteOut();
}
Void TEncBinCABACCounter::encodeBin( UInt binValue, ContextModel &rcCtxModel )
{
#if DEBUG_ENCODER_SEARCH_BINS
const UInt64 startingFracBits = m_fracBits;
#endif
m_uiBinsCoded += m_binCountIncrement;
m_fracBits += rcCtxModel.getEntropyBits( binValue );
#if VCEG_AZ07_BAC_ADAPT_WDOW || VCEG_AZ05_MULTI_PARAM_CABAC
if( binValue == 0 )
{
rcCtxModel.updateLPS();
}
else
{
rcCtxModel.updateMPS();
}
#else
rcCtxModel.update( binValue );
#endif
#if DEBUG_ENCODER_SEARCH_BINS
if ((g_debugCounter + debugEncoderSearchBinWindow) >= debugEncoderSearchBinTargetLine)
{
std::cout << g_debugCounter << ": coding bin value " << binValue << ", fracBits = [" << startingFracBits << "->" << m_fracBits << "]
";
}
if (g_debugCounter >= debugEncoderSearchBinTargetLine)
{
Char breakPointThis;
breakPointThis = 7;
}
if (g_debugCounter >= (debugEncoderSearchBinTargetLine + debugEncoderSearchBinWindow))
{
exit(0);
}
g_debugCounter++;
#endif
}
2.nビットの固定長符号化(4ビットの固定長符号化は輝度予測モードにおける16種類の選択モードに用いられる)
Void TEncBinCABAC::encodeBinsEP( UInt binValues, Int numBins )
{
m_uiBinsCoded += numBins & -m_binCountIncrement;
if (m_uiRange == 256)
{
encodeAlignedBinsEP(binValues, numBins);
return;
}
while ( numBins > 8 )
{
numBins -= 8;
UInt pattern = binValues >> numBins;
m_uiLow <<= 8;
m_uiLow += m_uiRange * pattern;
binValues -= pattern << numBins;
m_bitsLeft -= 8;
testAndWriteOut();
}
m_uiLow <<= numBins;
m_uiLow += m_uiRange * binValues;
m_bitsLeft -= numBins;
testAndWriteOut();
}
3.カットオフ二元符号(輝度予測モードにおける45種類の非選択モード用)
Void TEncSbac::xWriteTruncBinCode(UInt uiSymbol, UInt uiMaxSymbol)
{
UInt uiThresh;
if (uiMaxSymbol > 256)
{
UInt uiThreshVal = 1 << 8;
uiThresh = 8;
while (uiThreshVal <= uiMaxSymbol)
{
uiThresh++;
uiThreshVal <<= 1;
}
uiThresh--;
}
else
{
uiThresh = g_NonMPM[uiMaxSymbol];
}
UInt uiVal = 1 << uiThresh;
assert(uiVal <= uiMaxSymbol);
assert((uiVal << 1) > uiMaxSymbol);
assert(uiSymbol < uiMaxSymbol);
UInt b = uiMaxSymbol - uiVal;
assert(b < uiVal);
if (uiSymbol < uiVal - b)
{
m_pcBinIf->encodeBinsEP(uiSymbol, uiThresh);
}
else
{
uiSymbol += uiVal - b;
assert(uiSymbol < (uiVal << 1));
assert((uiSymbol >> 1) >= uiVal - b);
m_pcBinIf->encodeBinsEP(uiSymbol, uiThresh + 1);
}
}