📄 uvlcreader.cpp
字号:
ErrVal UvlcReader::xCodeFromBitstream2D( const UChar* aucCod, const UChar* aucLen, UInt uiWidth, UInt uiHeight, UInt& uiVal1, UInt& uiVal2 )
{
const UChar *paucLenTab;
const UChar *paucCodTab;
UChar uiLenRead = 0;
UChar uiCode = 0;
UChar uiMaxLen = 0;
// Find maximum number of bits to read before generating error
paucLenTab = aucLen;
paucCodTab = aucCod;
for (UInt j = 0; j < uiHeight; j++, paucLenTab += uiWidth, paucCodTab += uiWidth)
{
for ( UInt i = 0; i < uiWidth; i++ )
{
if ( paucLenTab[i] > uiMaxLen )
{
uiMaxLen = paucLenTab[i];
}
}
}
while ( uiLenRead < uiMaxLen )
{
// Read next bit
UInt uiBit;
RNOKS( m_pcBitReadBuffer->get( uiBit, 1 ) );
uiCode = ( uiCode << 1 ) + uiBit;
uiLenRead++;
// Check for matches
paucLenTab = aucLen;
paucCodTab = aucCod;
for (UInt j = 0; j < uiHeight; j++, paucLenTab += uiWidth, paucCodTab += uiWidth)
{
for (UInt i = 0; i < uiWidth; i++)
{
if ( (paucLenTab[i] == uiLenRead) && (paucCodTab[i] == uiCode) )
{
uiVal1 = i;
uiVal2 = j;
return Err::m_nOK;
}
}
}
}
return Err::m_nERR;
}
ErrVal UvlcReader::xGetRunLevel( Int* aiLevelRun, UInt uiCoeffCnt, UInt uiTrailingOnes, UInt uiMaxCoeffs, UInt& uiTotalRun, MbDataAccess &rcMbDataAccess )
{
ROTRS( 0 == uiCoeffCnt, Err::m_nOK );
if( uiTrailingOnes )
{
UInt uiBits;
RNOK( m_pcBitReadBuffer->get( uiBits, uiTrailingOnes ));
Int n = uiTrailingOnes-1;
for( UInt k = uiCoeffCnt; k > uiCoeffCnt-uiTrailingOnes; k--, n--)
{
aiLevelRun[k-1] = (uiBits & (1<<n)) ? -1 : 1;
}
DTRACE_POS;
DTRACE_T( " TrailingOnesSigns: " );
DTRACE_V( uiBits );
DTRACE_N;
DTRACE_COUNT(uiTrailingOnes);
}
UInt uiHighLevel = ( uiCoeffCnt > 3 && uiTrailingOnes == 3) ? 0 : 1;
UInt uiVlcTable = ( uiCoeffCnt > 10 && uiTrailingOnes < 3) ? 1 : 0;
for( Int k = uiCoeffCnt - 1 - uiTrailingOnes; k >= 0; k--)
{
Int iLevel;
if( uiVlcTable == 0 )
{
xGetLevelVLC0( iLevel );
}
else
{
xGetLevelVLCN( iLevel, uiVlcTable );
}
if( uiHighLevel )
{
iLevel += ( iLevel > 0 ) ? 1 : -1;
uiHighLevel = 0;
}
aiLevelRun[k] = iLevel;
UInt uiAbsLevel = (UInt)abs(iLevel);
// update VLC table
if( uiAbsLevel > g_auiIncVlc[ uiVlcTable ] )
{
uiVlcTable++;
}
if( k == Int(uiCoeffCnt - 1 - uiTrailingOnes) && uiAbsLevel > 3)
{
uiVlcTable = 2;
}
}
ROFRS( uiCoeffCnt < uiMaxCoeffs, Err::m_nOK );
uiVlcTable = uiCoeffCnt-1;
if( ! rcMbDataAccess.getSH().hasDefaultScanIdx() )
{
if( uiMaxCoeffs <= 4 )
{
UInt uiTempVlcTable = min(uiVlcTable + 4-uiMaxCoeffs, 2);
xGetTotalRun4( uiTempVlcTable, uiTotalRun );
}
else if( uiMaxCoeffs <= 8 )
{
UInt uiTempVlcTable = min(uiVlcTable + 8-uiMaxCoeffs, 6);
xGetTotalRun8( uiTempVlcTable, uiTotalRun );
}
else
{
UInt uiTempVlcTable = uiVlcTable;
if( uiMaxCoeffs < 15 )
uiTempVlcTable = min(uiVlcTable + 16-uiMaxCoeffs, 14);
xGetTotalRun16( uiTempVlcTable, uiTotalRun );
}
}
else
{
if( uiMaxCoeffs <= 4 )
{
xGetTotalRun4( uiVlcTable, uiTotalRun );
}
else
{
xGetTotalRun16( uiVlcTable, uiTotalRun );
}
}
// decode run before each coefficient
for ( UInt i = 0; i < uiCoeffCnt; i++ )
{
aiLevelRun[i + 0x10] = 0;
}
uiCoeffCnt--;
UInt uiRunCount = uiTotalRun;
if( uiRunCount > 0 && uiCoeffCnt > 0)
{
do
{
uiVlcTable = (( uiRunCount > RUNBEFORE_NUM) ? RUNBEFORE_NUM : uiRunCount) - 1;
UInt uiRun = 0;
xGetRun( uiVlcTable, uiRun );
aiLevelRun[uiCoeffCnt+0x10] = uiRun;
uiRunCount -= uiRun;
uiCoeffCnt--;
} while( uiRunCount != 0 && uiCoeffCnt != 0);
}
return Err::m_nOK;
}
ErrVal UvlcReader::xGetTrailingOnes4( UInt& uiCoeffCount, UInt& uiTrailingOnes )
{
RNOK( xCodeFromBitstream2D( &g_aucCodeTableTO4[0][0], &g_aucLenTableTO4[0][0], 5, 4, uiCoeffCount, uiTrailingOnes ) );
DTRACE_POS;
DTRACE_T( " TrailingOnes4: CoeffCnt: " );
DTRACE_V( uiCoeffCount );
DTRACE_T( " TraiOnes: " );
DTRACE_V( uiTrailingOnes );
DTRACE_N;
DTRACE_COUNT(g_aucLenTableTO4[uiTrailingOnes][uiCoeffCount]);
return Err::m_nOK;
}
ErrVal UvlcReader::xGetTotalRun4( UInt& uiVlcPos, UInt& uiTotalRun )
{
UInt uiTemp;
RNOK( xCodeFromBitstream2D( &g_aucCodeTableTZ4[uiVlcPos][0], &g_aucLenTableTZ4[uiVlcPos][0], 4, 1, uiTotalRun, uiTemp ) );
DTRACE_POS;
DTRACE_T( " TotalZeros4 vlc: " );
DTRACE_V( uiVlcPos );
DTRACE_T( " TotalRun: " );
DTRACE_V( uiTotalRun );
DTRACE_N;
DTRACE_COUNT(g_aucLenTableTZ4[uiVlcPos][uiTotalRun]);
return Err::m_nOK;
}
ErrVal UvlcReader::xGetTotalRun8( UInt& uiVlcPos, UInt& uiTotalRun )
{
UInt uiTemp;
RNOK( xCodeFromBitstream2D( &g_aucCodeTableTZ8[uiVlcPos][0], &g_aucLenTableTZ8[uiVlcPos][0], 8, 1, uiTotalRun, uiTemp ) );
DTRACE_POS;
DTRACE_T( " TotalZeros8 vlc: " );
DTRACE_V( uiVlcPos );
DTRACE_T( " TotalRun: " );
DTRACE_V( uiTotalRun );
DTRACE_N;
DTRACE_COUNT(g_aucLenTableTZ8[uiVlcPos][uiTotalRun]);
return Err::m_nOK;
}
ErrVal UvlcReader::xGetTotalRun16( UInt uiVlcPos, UInt& uiTotalRun )
{
UInt uiTemp;
RNOK( xCodeFromBitstream2D( &g_aucCodeTableTZ16[uiVlcPos][0], &g_aucLenTableTZ16[uiVlcPos][0], 16, 1, uiTotalRun, uiTemp ) );
DTRACE_POS;
DTRACE_T( " TotalRun16 vlc: " );
DTRACE_V( uiVlcPos );
DTRACE_T( " TotalRun: " );
DTRACE_V( uiTotalRun );
DTRACE_N;
DTRACE_COUNT(g_aucLenTableTZ16[uiVlcPos][uiTotalRun]);
return Err::m_nOK;
}
ErrVal UvlcReader::xGetRun( UInt uiVlcPos, UInt& uiRun )
{
UInt uiTemp;
RNOK( xCodeFromBitstream2D( &g_aucCodeTable3[uiVlcPos][0], &g_aucLenTable3[uiVlcPos][0], 15, 1, uiRun, uiTemp ) );
DTRACE_POS;
DTRACE_T( " Run" );
DTRACE_CODE( uiRun );
DTRACE_COUNT (g_aucLenTable3[uiVlcPos][uiRun]);
DTRACE_N;
return Err::m_nOK;
}
ErrVal UvlcReader::xGetLevelVLC0( Int& iLevel )
{
UInt uiLength = 0;
UInt uiCode = 0;
UInt uiTemp = 0;
UInt uiSign = 0;
UInt uiLevel = 0;
do
{
RNOK( m_pcBitReadBuffer->get( uiTemp, 1 ) );
uiLength++;
uiCode = ( uiCode << 1 ) + uiTemp;
} while ( uiCode == 0 );
if ( uiLength < 15 )
{
uiSign = (uiLength - 1) & 1;
uiLevel = (uiLength - 1) / 2 + 1;
}
else if (uiLength == 15)
{
// escape code
RNOK( m_pcBitReadBuffer->get( uiTemp, 4 ) );
uiCode = (uiCode << 4) | uiTemp;
uiLength += 4;
uiSign = (uiCode & 1);
uiLevel = ((uiCode >> 1) & 0x7) + 8;
}
else if (uiLength >= 16)
{
// escape code
UInt uiAddBit = uiLength - 16;
RNOK( m_pcBitReadBuffer->get( uiCode, uiLength-4 ) );
uiLength -= 4;
uiSign = (uiCode & 1);
uiLevel = (uiCode >> 1) + (2048<<uiAddBit)+16-2048;
uiCode |= (1 << (uiLength)); // for display purpose only
uiLength += uiAddBit + 16;
}
iLevel = uiSign ? -(Int)uiLevel : (Int)uiLevel;
DTRACE_POS;
DTRACE_T( " VLC0 lev " );
DTRACE_CODE( iLevel );
DTRACE_N;
DTRACE_COUNT( uiLength );
return Err::m_nOK;
}
ErrVal UvlcReader::xGetLevelVLCN( Int& iLevel, UInt uiVlcLength )
{
UInt uiTemp;
UInt uiLength;
UInt uiCode;
UInt uiLevAbs;
UInt uiSb;
UInt uiSign;
UInt uiAddBit;
UInt uiOffset;
UInt uiNumPrefix = 0;
UInt uiShift = uiVlcLength - 1;
UInt uiEscape = (15<<uiShift)+1;
// read pre zeros
do
{
RNOK( m_pcBitReadBuffer->get( uiTemp, 1 ) );
uiNumPrefix++;
} while ( uiTemp == 0 );
uiLength = uiNumPrefix;
uiCode = 1;
uiNumPrefix--;
if (uiNumPrefix < 15)
{
uiLevAbs = (uiNumPrefix<<uiShift) + 1;
if ( uiVlcLength-1 )
{
RNOK( m_pcBitReadBuffer->get( uiSb, uiVlcLength-1 ) );
uiCode = (uiCode << (uiVlcLength-1) )| uiSb;
uiLevAbs += uiSb;
uiLength += (uiVlcLength-1);
}
// read 1 bit -> sign
RNOK( m_pcBitReadBuffer->get( uiSign, 1 ) );
uiCode = (uiCode << 1)| uiSign;
uiLength++;
}
else // escape
{
uiAddBit = uiNumPrefix - 15;
RNOK( m_pcBitReadBuffer->get( uiSb, (11+uiAddBit) ) );
uiCode = (uiCode << (11+uiAddBit) )| uiSb;
uiLength += (11+uiAddBit);
uiOffset = (2048<<uiAddBit)+uiEscape-2048;
uiLevAbs = uiSb + uiOffset;
// read 1 bit -> sign
RNOK( m_pcBitReadBuffer->get( uiSign, 1 ) );
uiCode = (uiCode << 1)| uiSign;
uiLength++;
}
iLevel = (uiSign) ? -(Int)uiLevAbs : (Int)uiLevAbs;
DTRACE_POS;
DTRACE_T( " VLCN lev: " );
DTRACE_CODE( iLevel );
DTRACE_N;
DTRACE_COUNT( uiLength );
return Err::m_nOK;
}
Bool UvlcReader::isEndOfSlice()
{
UInt uiEOS = ( m_uiRun > 1 ) ? 0 : !( moreRBSPData() );
return (uiEOS == 1);
}
ErrVal UvlcReader::finishSlice( )
{
if( m_bRunLengthCoding && m_uiRun )
{
DTRACE_T( "Run" );
RNOK( xGetUvlcCode( m_uiRun ) );
DTRACE_N;
}
return Err::m_nOK;
}
ErrVal UvlcReader::residualBlock8x8( MbDataAccess& rcMbDataAccess,
B8x8Idx c8x8Idx,
UInt uiStart,
UInt uiStop )
{
const Bool bFrame = ( FRAME == rcMbDataAccess.getMbPicType());
const UChar* pucScan = (bFrame) ? g_aucFrameScan64 : g_aucFieldScan64;
TCoeff* piCoeff = rcMbDataAccess.getMbTCoeffs().get8x8( c8x8Idx );
UInt uiBlk;
UInt uiPos;
Int aaiLevelRun [4][32];
UInt auiTrailingOnes [4] = { 0, 0, 0, 0 };
UInt auiTotalRun [4] = { 0, 0, 0, 0 };
UInt auiCoeffCnt [4] = { 0, 0, 0, 0 };
for ( uiBlk = 0; uiBlk < 4; uiBlk++ )
for ( uiPos = 0; uiPos < 32; uiPos++ )
aaiLevelRun[uiBlk][uiPos] = 0;
{
UInt uiBitPos = c8x8Idx;
rcMbDataAccess.getMbData().setBCBP( uiBitPos, 1);
rcMbDataAccess.getMbData().setBCBP( uiBitPos+1, 1);
rcMbDataAccess.getMbData().setBCBP( uiBitPos+4, 1);
rcMbDataAccess.getMbData().setBCBP( uiBitPos+5, 1);
}
//===== loop over 4x4 blocks =====
for( uiBlk = 0; uiBlk < 4; uiBlk++ )
{
B4x4Idx cIdx( c8x8Idx.b4x4() + 4*(uiBlk/2) + (uiBlk%2) );
xPredictNonZeroCnt( rcMbDataAccess, cIdx, auiCoeffCnt[uiBlk], auiTrailingOnes[uiBlk], uiStart, uiStop );
xGetRunLevel( aaiLevelRun[uiBlk], auiCoeffCnt[uiBlk], auiTrailingOnes[uiBlk], uiStop - uiStart, auiTotalRun[uiBlk], rcMbDataAccess );
uiPos = ((auiTotalRun[uiBlk] + auiCoeffCnt[uiBlk] - 1) << 2) + uiBlk;
uiPos += 4*uiStart;
for ( Int i = (Int)auiCoeffCnt[uiBlk]; i > 0; i-- )
{
piCoeff[ pucScan [uiPos] ] = aaiLevelRun[uiBlk][i-1];
uiPos -= 4;
for ( Int j = 0; j < aaiLevelRun[uiBlk][i-1+0x10]; j++ )
{
piCoeff[ pucScan [uiPos] ] = 0;
uiPos -= 4;
}
}
}
return Err::m_nOK;
}
H264AVC_NAMESPACE_END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -