📄 uvlcwriter.cpp
字号:
Int iLevel;
Int iRun = 0;
UInt uiPos = uiStart;
UInt uiMaxPos = uiStop;
switch( eResidualMode )
{
case LUMA_I16_DC:
{
pucScan = (bFrame) ? g_aucLumaFrameDCScan : g_aucLumaFieldDCScan;
ROF( uiStart == 0 && uiStop == 16 );
break;
}
case LUMA_I16_AC:
{
pucScan = (bFrame) ? g_aucFrameScan : g_aucFieldScan;
ROF( uiStart == 0 && uiStop == 16 );
uiPos=1;
break;
}
case LUMA_SCAN:
{
pucScan = (bFrame) ? g_aucFrameScan : g_aucFieldScan;
break;
}
default:
return Err::m_nERR;
}
Int aiLevelRun[32];
UInt uiTrailingOnes = 0;
UInt uiTotalRun = 0;
UInt uiCoeffCnt = 0;
while( uiPos < uiMaxPos )
{
if( ( iLevel = piCoeff[ pucScan [ uiPos++ ] ]) )
{
if( abs(iLevel) == 1 )
{
m_uiCoeffCost += COEFF_COST[iRun];
uiTrailingOnes++;
}
else
{
m_uiCoeffCost += MAX_VALUE; // set high cost, shall not be discarded
uiTrailingOnes = 0;
}
aiLevelRun[uiCoeffCnt] = iLevel;
aiLevelRun[uiCoeffCnt+0x10] = iRun;
uiTotalRun += iRun;
uiCoeffCnt++;
iRun = 0;
}
else
{
iRun++;
}
}
if( uiTrailingOnes > 3 )
{
uiTrailingOnes = 3;
}
Bool bDefaultScanIdx = ( uiStart == 0 && uiStop == 16 );
switch( eResidualMode )
{
case LUMA_I16_DC:
{
ETRACE_T( "Luma:" );
ETRACE_V( cIdx );
ETRACE_N;
RNOK( xPredictNonZeroCnt( rcMbDataAccess, cIdx, uiCoeffCnt, uiTrailingOnes, uiStart, uiStop ) );
RNOK( xWriteRunLevel( aiLevelRun, uiCoeffCnt, uiTrailingOnes, 16, uiTotalRun, rcMbDataAccess, bDefaultScanIdx ) );
break;
}
case LUMA_I16_AC:
{
ETRACE_T( "Luma:" );
ETRACE_V( cIdx );
ETRACE_N;
RNOK( xPredictNonZeroCnt( rcMbDataAccess, cIdx, uiCoeffCnt, uiTrailingOnes, uiStart, uiStop ) );
RNOK( xWriteRunLevel( aiLevelRun, uiCoeffCnt, uiTrailingOnes, uiStop-max(1,uiStart), uiTotalRun, rcMbDataAccess, bDefaultScanIdx ) );
break;
}
case LUMA_SCAN:
{
ETRACE_T( "Luma:" );
ETRACE_V( cIdx );
ETRACE_N;
RNOK( xPredictNonZeroCnt( rcMbDataAccess, cIdx, uiCoeffCnt, uiTrailingOnes, uiStart, uiStop ) );
RNOK( xWriteRunLevel( aiLevelRun, uiCoeffCnt, uiTrailingOnes, uiStop-uiStart, uiTotalRun, rcMbDataAccess, bDefaultScanIdx ) );
// this is useful only in AR_FGS
rcMbDataAccess.getMbData().setBCBP( cIdx, uiCoeffCnt != 0, true);
break;
}
default:
{
AF();
}
}
return Err::m_nOK;
}
ErrVal UvlcWriter::residualBlock( MbDataAccess& rcMbDataAccess,
ChromaIdx cIdx,
ResidualMode eResidualMode,
UInt uiStart,
UInt uiStop )
{
TCoeff* piCoeff = rcMbDataAccess.getMbTCoeffs().get( cIdx );
const Bool bFrame = ( FRAME == rcMbDataAccess.getMbPicType());
const UChar* pucScan;
Int iRun = 0, iLevel;
UInt uiPos, uiMaxPos;
switch( eResidualMode )
{
case CHROMA_DC:
{
pucScan = g_aucIndexChromaDCScan;
ROF( uiStart == 0 );
uiPos=0; uiMaxPos= 4;
break;
}
case CHROMA_AC:
{
pucScan = (bFrame) ? g_aucFrameScan : g_aucFieldScan;
ROT( uiStop <= 1 );
uiPos = max( 1, uiStart);
uiMaxPos = uiStop;
break;
}
default:
return Err::m_nERR;
}
Int aiLevelRun[32];
UInt uiTrailingOnes = 0;
UInt uiTotalRun = 0;
UInt uiCoeffCnt = 0;
while( uiPos < uiMaxPos )
{
if( ( iLevel = piCoeff[ pucScan [ uiPos++ ] ]) )
{
if( abs(iLevel) == 1 )
{
m_uiCoeffCost += COEFF_COST[iRun];
uiTrailingOnes++;
}
else
{
m_uiCoeffCost += MAX_VALUE; // set high cost, shall not be discarded
uiTrailingOnes = 0;
}
aiLevelRun[uiCoeffCnt] = iLevel;
aiLevelRun[uiCoeffCnt+0x10] = iRun;
uiTotalRun += iRun;
uiCoeffCnt++;
iRun = 0;
}
else
{
iRun++;
}
}
if( uiTrailingOnes > 3 )
{
uiTrailingOnes = 3;
}
Bool bDefaultScanIdx = ( uiStart == 0 && uiStop == 16 );
switch( eResidualMode )
{
case CHROMA_AC:
{
ETRACE_T( "CHROMA_AC:" );
ETRACE_V( cIdx );
ETRACE_N;
RNOK( xPredictNonZeroCnt( rcMbDataAccess, cIdx, uiCoeffCnt, uiTrailingOnes, uiStart, uiStop ) );
RNOK( xWriteRunLevel( aiLevelRun, uiCoeffCnt, uiTrailingOnes, uiStop - max( 1, uiStart), uiTotalRun, rcMbDataAccess, bDefaultScanIdx ) );
// this is useful only in AR_FGS
rcMbDataAccess.getMbData().setBCBP( 16 + cIdx, uiCoeffCnt != 0, true);
break;
}
case CHROMA_DC:
{
ETRACE_T( "CHROMA_DC:" );
ETRACE_V( cIdx );
ETRACE_N;
RNOK( xWriteTrailingOnes4( uiCoeffCnt, uiTrailingOnes ) );
RNOK( xWriteRunLevel( aiLevelRun, uiCoeffCnt, uiTrailingOnes, 4, uiTotalRun, rcMbDataAccess, bDefaultScanIdx ) );
// this is useful only in AR_FGS
rcMbDataAccess.getMbData().setBCBP( 24 + cIdx.plane(), uiCoeffCnt != 0, true);
break;
}
default:
{
AF();
}
}
return Err::m_nOK;
}
ErrVal UvlcWriter::deltaQp( MbDataAccess& rcMbDataAccess )
{
ETRACE_T ("DQp");
RNOK( xWriteSvlcCode( rcMbDataAccess.getDeltaQp() ) );
ETRACE_TY ("se(v)");
ETRACE_N;
return Err::m_nOK;
}
ErrVal UvlcWriter::finishSlice()
{
if( m_bRunLengthCoding && m_uiRun )
{
ETRACE_T( "Run" );
RNOK( xWriteUvlcCode( m_uiRun ) );
ETRACE_N;
}
return Err::m_nOK;
}
ErrVal UvlcWriter::xPredictNonZeroCnt( MbDataAccess& rcMbDataAccess, ChromaIdx cIdx, UInt uiCoeffCount, UInt uiTrailingOnes, UInt uiStart, UInt uiStop )
{
UInt uiCoeffCountCtx = rcMbDataAccess.getCtxCoeffCount( cIdx, uiStart, uiStop );
if( uiStart != 0 || uiStop != 16 )
{
// Re-pack VLC matrix
// NB: This only needs to be done once at the start of the slice.
UInt uiMapIdx, ui, uj;
UChar aucCwMapTO16[4][17];
UInt uiBw = uiStop-uiStart;
UInt uiXdim = min(16,uiBw)+1;
UInt uiYdim = min(3, uiBw)+1;
UInt uiZ[5] = {0,1,2,4,7};
UInt uiMaxVal = uiXdim*uiYdim - uiZ[uiYdim];
UInt uiCoeffCountCtxMap = min(uiCoeffCountCtx, 2);
memcpy(aucCwMapTO16, g_aucCwMapTO16[uiCoeffCountCtxMap], sizeof(UChar)*4*17);
for( uiMapIdx=1; uiMapIdx<=uiMaxVal; uiMapIdx++ )
{
Bool bFound = false;
for( ui=0; ui<uiYdim; ui++ )
for( uj=1; uj<uiXdim; uj++ )
if( aucCwMapTO16[ui][uj] == uiMapIdx )
{
bFound = true;
break;
}
if( !bFound )
{
for( ui=0; ui<uiYdim; ui++ )
for( uj=1; uj<uiXdim; uj++ )
if( aucCwMapTO16[ui][uj] > uiMapIdx )
aucCwMapTO16[ui][uj]--;
uiMapIdx--;
}
}
xWriteCode(g_aucCwCodeVectTO16[uiCoeffCountCtx][aucCwMapTO16[uiTrailingOnes][uiCoeffCount]], g_aucCwLenVectTO16[uiCoeffCountCtx][aucCwMapTO16[uiTrailingOnes][uiCoeffCount]]);
}
else
{
xWriteTrailingOnes16( uiCoeffCountCtx, uiCoeffCount, uiTrailingOnes );
}
rcMbDataAccess.getMbTCoeffs().setCoeffCount( cIdx, uiCoeffCount );
return Err::m_nOK;
}
ErrVal UvlcWriter::xPredictNonZeroCnt( MbDataAccess& rcMbDataAccess, LumaIdx cIdx, UInt uiCoeffCount, UInt uiTrailingOnes, UInt uiStart, UInt uiStop )
{
UInt uiCoeffCountCtx = rcMbDataAccess.getCtxCoeffCount( cIdx, uiStart, uiStop );
if( uiStart != 0 || uiStop != 16 )
{
// Re-pack VLC matrix
// NB: This only needs to be done once at the start of the slice.
UInt uiMapIdx, ui, uj;
UChar aucCwMapTO16[4][17];
UInt uiBw = uiStop-uiStart;
UInt uiXdim = min(16,uiBw)+1;
UInt uiYdim = min(3, uiBw)+1;
UInt uiZ[5] = {0,1,2,4,7};
UInt uiMaxVal = uiXdim*uiYdim - uiZ[uiYdim];
UInt uiCoeffCountCtxMap = min(uiCoeffCountCtx, 2);
memcpy(aucCwMapTO16, g_aucCwMapTO16[uiCoeffCountCtxMap], sizeof(UChar)*4*17);
for( uiMapIdx=1; uiMapIdx<=uiMaxVal; uiMapIdx++ )
{
Bool bFound = false;
for( ui=0; ui<uiYdim; ui++ )
for( uj=1; uj<uiXdim; uj++ )
if( aucCwMapTO16[ui][uj] == uiMapIdx )
{
bFound = true;
break;
}
if( !bFound )
{
for( ui=0; ui<uiYdim; ui++ )
for( uj=1; uj<uiXdim; uj++ )
if( aucCwMapTO16[ui][uj] > uiMapIdx )
aucCwMapTO16[ui][uj]--;
uiMapIdx--;
}
}
xWriteCode(g_aucCwCodeVectTO16[uiCoeffCountCtx][aucCwMapTO16[uiTrailingOnes][uiCoeffCount]], g_aucCwLenVectTO16[uiCoeffCountCtx][aucCwMapTO16[uiTrailingOnes][uiCoeffCount]]);
}
else
{
xWriteTrailingOnes16( uiCoeffCountCtx, uiCoeffCount, uiTrailingOnes );
}
rcMbDataAccess.getMbTCoeffs().setCoeffCount( cIdx, uiCoeffCount );
return Err::m_nOK;
}
ErrVal UvlcWriter::xWriteRunLevel( Int* aiLevelRun, UInt uiCoeffCnt, UInt uiTrailingOnes, UInt uiMaxCoeffs, UInt uiTotalRun, MbDataAccess &rcMbDataAccess, Bool bDefaultScanIdx )
{
ROTRS( 0 == uiCoeffCnt, Err::m_nOK );
if( uiTrailingOnes )
{
UInt uiBits = 0;
Int n = uiTrailingOnes-1;
for( UInt k = uiCoeffCnt; k > uiCoeffCnt-uiTrailingOnes; k--, n--)
{
if( aiLevelRun[k-1] < 0)
{
uiBits |= 1<<n;
}
}
RNOK( m_pcBitWriteBufferIf->write( uiBits, uiTrailingOnes ))
ETRACE_POS;
ETRACE_T( " TrailingOnesSigns: " );
ETRACE_V( uiBits );
ETRACE_N;
ETRACE_COUNT(uiTrailingOnes);
}
Int iHighLevel = ( uiCoeffCnt > 3 && uiTrailingOnes == 3) ? 0 : 1;
Int iVlcTable = ( uiCoeffCnt > 10 && uiTrailingOnes < 3) ? 1 : 0;
for( Int k = uiCoeffCnt - 1 - uiTrailingOnes; k >= 0; k--)
{
Int iLevel;
iLevel = aiLevelRun[k];
UInt uiAbsLevel = (UInt)abs(iLevel);
if( iHighLevel )
{
iLevel -= ( iLevel > 0 ) ? 1 : -1;
iHighLevel = 0;
}
if( iVlcTable == 0 )
{
xWriteLevelVLC0( iLevel );
}
else
{
xWriteLevelVLCN( iLevel, iVlcTable );
}
// update VLC table
if( uiAbsLevel > g_auiIncVlc[ iVlcTable ] )
{
iVlcTable++;
}
if( k == Int(uiCoeffCnt - 1 - uiTrailingOnes) && uiAbsLevel > 3)
{
iVlcTable = 2;
}
}
ROFRS( uiCoeffCnt < uiMaxCoeffs, Err::m_nOK );
iVlcTable = uiCoeffCnt-1;
if( ! bDefaultScanIdx )
{
if( uiMaxCoeffs <= 4 )
{
UInt uiTempVlcTable = min(iVlcTable + 4-uiMaxCoeffs, 2);
xWriteTotalRun4( uiTempVlcTable, uiTotalRun );
}
else if( uiMaxCoeffs <= 8 )
{
UInt uiTempVlcTable = min(iVlcTable + 8-uiMaxCoeffs, 6);
xWriteTotalRun8( uiTempVlcTable, uiTotalRun );
}
else
{
UInt uiTempVlcTable = iVlcTable;
if( uiMaxCoeffs < 15 )
uiTempVlcTable = min(iVlcTable + 16-uiMaxCoeffs, 14);
xWriteTotalRun16( uiTempVlcTable, uiTotalRun );
}
}
else
{
if( uiMaxCoeffs <= 4 )
{
xWriteTotalRun4( iVlcTable, uiTotalRun );
}
else
{
xWriteTotalRun16( iVlcTable, uiTotalRun );
}
}
// decode run before each coefficient
uiCoeffCnt--;
if( uiTotalRun > 0 && uiCoeffCnt > 0)
{
do
{
iVlcTable = (( uiTotalRun > RUNBEFORE_NUM) ? RUNBEFORE_NUM : uiTotalRun) - 1;
UInt uiRun = aiLevelRun[uiCoeffCnt+0x10];
xWriteRun( iVlcTable, uiRun );
uiTotalRun -= uiRun;
uiCoeffCnt--;
} while( uiTotalRun != 0 && uiCoeffCnt != 0);
}
return Err::m_nOK;
}
ErrVal UvlcWriter::xWriteTrailingOnes16( UInt uiLastCoeffCount, UInt uiCoeffCount, UInt uiTrailingOnes )
{
UInt uiVal;
UInt uiSize;
ETRACE_POS;
if( 3 == uiLastCoeffCount )
{
UInt uiBits = 3;
if( uiCoeffCount )
{
uiBits = (uiCoeffCount-1)<<2 | uiTrailingOnes;
}
RNOK( m_pcBitWriteBufferIf->write( uiBits, 6) );
ETRACE_DO( m_uiBitCounter = 6 );
uiVal = uiBits;
uiSize = 6;
}
else
{
RNOK( m_pcBitWriteBufferIf->write( g_aucCodeTableTO16[uiLastCoeffCount][uiTrailingOnes][uiCoeffCount],
g_aucLenTableTO16[uiLastCoeffCount][uiTrailingOnes][uiCoeffCount] ) );
ETRACE_DO( m_uiBitCounter = g_aucLenTableTO16[uiLastCoeffCount][uiTrailingOnes][uiCoeffCount] );
uiVal = g_aucCodeTableTO16[uiLastCoeffCount][uiTrailingOnes][uiCoeffCount];
uiSize = g_aucLenTableTO16[uiLastCoeffCount][uiTrailingOnes][uiCoeffCount];
}
ETRACE_T( " TrailingOnes16: Vlc: " );
ETRACE_V( uiLastCoeffCount );
ETRACE_T( " CoeffCnt: " );
ETRACE_V( uiCoeffCount );
ETRACE_T( " TraiOnes: " );
ETRACE_V( uiTrailingOnes );
ETRACE_N;
ETRACE_COUNT(m_uiBitCounter);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -