CABAC 是唯一一个应用到HEVC中的熵编码方式,效率明显高于CAVLC编码。
但是CABAC有天然的serial operation dependence,致使硬件实施很困难,尤其是real-time 要求和mobile 设备等。
CABAC 用到的上下文模型中, 残差信号也就是转移系数相关的上下文占了70%左右的bins,对熵编码的性能影响也是显而易见的
再者就是MVD(motion vector difference )占据了差不多20% 的 bins
对着来那个部分进行优化,以使得CABAC的计算复杂度和数据依赖性的减少都有着重要意义
至于优化,先要了解这部分的parsing 过程
接下来先分析下残差信号的转移系数的parsing过程的code ,希望可以共同学习
在类TEncSbac下定义了所有模块的syntax elements parsing 过程函数, codeCoeffN*N 就是针对转移系数的函数:
Void TEncSbac::codeCoeffNxN( TComDataCU* pcCU, TCoeff* pcCoef, UInt uiAbsPartIdx, UInt uiWidth, UInt uiHeight, UInt uiDepth, TextType eTType )
{
DTRACE_CABAC_VL( g_nSymbolCounter++ )
DTRACE_CABAC_T( "\tparseCoeffNxN()\teType=" )
DTRACE_CABAC_V( eTType )
DTRACE_CABAC_T( "\twidth=" )
DTRACE_CABAC_V( uiWidth )
DTRACE_CABAC_T( "\theight=" )
DTRACE_CABAC_V( uiHeight )
DTRACE_CABAC_T( "\tdepth=" )
DTRACE_CABAC_V( uiDepth )
DTRACE_CABAC_T( "\tabspartidx=" )
DTRACE_CABAC_V( uiAbsPartIdx )
DTRACE_CABAC_T( "\ttoCU-X=" )
DTRACE_CABAC_V( pcCU->getCUPelX() )
DTRACE_CABAC_T( "\ttoCU-Y=" )
DTRACE_CABAC_V( pcCU->getCUPelY() )
DTRACE_CABAC_T( "\tCU-addr=" )
DTRACE_CABAC_V( pcCU->getAddr() )
DTRACE_CABAC_T( "\tinCU-X=" )
DTRACE_CABAC_V( g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ] )
DTRACE_CABAC_T( "\tinCU-Y=" )
DTRACE_CABAC_V( g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ] )
DTRACE_CABAC_T( "\tpredmode=" )
DTRACE_CABAC_V( pcCU->getPredictionMode( uiAbsPartIdx ) )
DTRACE_CABAC_T( "\n" )
if( uiWidth > m_pcSlice->getSPS()->getMaxTrSize() )
{
uiWidth = m_pcSlice->getSPS()->getMaxTrSize();
uiHeight = m_pcSlice->getSPS()->getMaxTrSize();
}
UInt uiNumSig = 0;
// compute number of significant coefficients
uiNumSig = TEncEntropy::countNonZeroCoeffs(pcCoef, uiWidth * uiHeight); //@Note: the nonzero coefficients are calculted in TU level
if ( uiNumSig == 0 )
return;
if(pcCU->getSlice()->getPPS()->getUseTransformSkip())
{
codeTransformSkipFlags( pcCU,uiAbsPartIdx, uiWidth, uiHeight, eTType );
}
eTType = eTType == TEXT_LUMA ? TEXT_LUMA : ( eTType == TEXT_NONE ? TEXT_NONE : TEXT_CHROMA ); //@Note: fixed the text model: Luma, Chroma, None
//----- encode significance map -----
const UInt uiLog2BlockSize = g_aucConvertToBit[ uiWidth ] + 2; //@Note: Char g_aucConvertToBit [ MAX_CU_SIZE+1 ]; MAX_CU_SIZE = (1<< MAX_CU_DEPTH) = 64
UInt uiScanIdx = pcCU->getCoefScanIdx(uiAbsPartIdx, uiWidth, eTType==TEXT_LUMA, pcCU->isIntra(uiAbsPartIdx)); //@Note: return the scanIdx, Veri. Hori. Diag.
const UInt *scan = g_auiSigLastScan[ uiScanIdx ][ uiLog2BlockSize - 1 ]; //@Note: scan order table [3][6]
Bool beValid;
if (pcCU->getCUTransquantBypass(uiAbsPartIdx)) //@Note: if cu_transquant_bypass_flag = 1, the scanning and transform, in-loop filter are bypass
{
beValid = false;
}
else //@Note: if cu_transquant_bypass_flag = 0, check the hide flag for coefficient sign
{
beValid = pcCU->getSlice()->getPPS()->getSignHideFlag() > 0;
}
// Find position of last coefficient
Int scanPosLast = -1; //@Note: do ... while
Int posLast;
const UInt * scanCG;
{ //@Note: g_auiSigLastScan[3][6]
scanCG = g_auiSigLastScan[ uiScanIdx ][ uiLog2BlockSize > 3 ? uiLog2BlockSize-2-1 : 0 ]; //@Note: TU 16*16: g_auiSigLastScan[uiScanIdx][1]
if( uiLog2BlockSize == 3 ) //@Note: TU 8*8: g_sigL