H.266におけるエントロピー符号化のまとめ

4146 ワード

継続的な更新...
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);
  }
}