📄 uvlcwriter.cpp
字号:
uiScanIndex+=uiStride;
}
while ( true );
UInt uiSymbol = ruiNumCoefWritten - ((bSkipEob || ruiNumCoefWritten <= pauiEobShift[uiCycle]) ? 1 : 0);
RNOK( xWriteSigRunCode( uiSymbol, m_auiBestCodeTabMap[uiCycle] ) );
RNOK( xWriteFlag( piCoeff[pucScan[uiScanIndex]] < 0 ? 1 : 0 ) );
// Check whether any more nonzero values
Bool bFinished = true;
for( ui=uiScanIndex+uiStride; ui<uiStop; ui+=uiStride )
{
bFinished &= ( piCoeffBase[pucScan[ui]] != 0 );
if( !bFinished )
break;
}
if( bFinished )
{
UInt uiCountMag2;
RNOK( xRQencodeSigMagGreater1( piCoeff, piCoeffBase, 0, uiStart, uiStop, uiCycle, pucScan, uiCountMag2, uiStride ) );
if( uiCountMag2 == 0 )
{
RNOK( xWriteSigRunCode( 0, m_auiBestCodeTabMap[uiCycle] ) );
}
}
return Err::m_nOK;
}
ErrVal
UvlcWriter::xRQencodeSigMagGreater1( TCoeff* piCoeff,
TCoeff* piCoeffBase,
UInt uiBaseCode,
UInt uiStart,
UInt uiStop,
UInt uiVlcTable,
const UChar* pucScan,
UInt& ruiNumMagG1,
UInt uiStride )
{
// Any magnitudes greater than one?
ruiNumMagG1 = 0;
UInt uiCountMag1 = 0;
UInt uiMaxMag = 0;
UInt ui;
for( ui = uiStart; ui < uiStop; ui+=uiStride )
{
if( piCoeff[pucScan[ui]] && ! piCoeffBase[pucScan[ui]])
{
uiCountMag1++;
UInt uiAbs = ( piCoeff[pucScan[ui]] < 0 ? -piCoeff[pucScan[ui]] : piCoeff[pucScan[ui]] );
if ( uiAbs > 1 )
{
ruiNumMagG1++;
}
if ( uiAbs > uiMaxMag )
{
uiMaxMag = uiAbs;
}
}
}
if( ruiNumMagG1 == 0 )
{
return Err::m_nOK;
}
// Find optimal terminating code
UInt uiTermSym;
if ( uiMaxMag < 4 )
{
uiTermSym = 2*(ruiNumMagG1-1) + uiMaxMag%2;
} else {
uiTermSym = uiCountMag1*(uiMaxMag-2) + ruiNumMagG1 - 1;
}
RNOK( xWriteSigRunCode( uiBaseCode+uiTermSym+1, m_auiBestCodeTabMap[uiVlcTable] ) );
UInt uiFlip = 0;
UInt uiRemaining = ruiNumMagG1;
UInt uiBegin = 0;
UInt uiEnd = uiCountMag1;
UInt uiCount = 0;
for( ui = uiStart; ui < uiStop; ui+=uiStride )
{
if( piCoeff[pucScan[ui]] && ! piCoeffBase[pucScan[ui]])
{
// Coding last value(s) may be unnecessary
if ( uiRemaining == uiEnd-uiCount )
break;
// Range check for interval splitting
uiCount++;
if ( uiCount <= uiBegin )
continue;
if ( uiCount > uiEnd )
break;
UInt uiAbs = ( piCoeff[pucScan[ui]] < 0 ? -piCoeff[pucScan[ui]] : piCoeff[pucScan[ui]] );
RNOK( xWriteFlag( (uiAbs > 1) ? 1 : 0 ) );
uiRemaining -= ( uiAbs > 1 ) ? 1-uiFlip : uiFlip;
if ( uiRemaining == 0 )
break;
}
}
UInt uiOutstanding = ruiNumMagG1;
Bool bSeenMaxMag = false;
for( ui = uiStart; ui < uiStop; ui+=uiStride )
{
if( !bSeenMaxMag && uiOutstanding == 1 )
break;
if( piCoeff[pucScan[ui]] && ! piCoeffBase[pucScan[ui]])
{
UInt uiAbs = ( piCoeff[pucScan[ui]] < 0 ? -piCoeff[pucScan[ui]] : piCoeff[pucScan[ui]] );
bSeenMaxMag |= ( uiAbs == uiMaxMag );
for ( UInt uiCutoff=1; uiAbs>uiCutoff && uiCutoff<uiMaxMag; uiCutoff++ )
{
RNOK( xWriteFlag( uiAbs > (uiCutoff+1) ) );
}
if( uiAbs > 1 )
uiOutstanding--;
if( uiOutstanding == 0 )
break;
}
}
return Err::m_nOK;
}
ErrVal
UvlcWriter::RQencodeTCoeffRef_8x8( MbDataAccess& rcMbDataAccess,
MbDataAccess& rcMbDataAccessBase,
B8x8Idx c8x8Idx,
UInt uiScanIndex )
{
TCoeff* piCoeff = rcMbDataAccess .getMbTCoeffs().get8x8( c8x8Idx );
TCoeff* piCoeffBase = rcMbDataAccessBase.getMbTCoeffs().get8x8( c8x8Idx );
const UChar* pucScan = g_aucFrameScan64;
ETRACE_T( "LUMA_8x8_REF" );
ETRACE_V( c8x8Idx.b8x8Index() );
ETRACE_V( uiScanIndex );
ETRACE_N;
RNOK( xRQencodeTCoeffsRef( piCoeff, piCoeffBase, pucScan, uiScanIndex ) );
return Err::m_nOK;
}
ErrVal
UvlcWriter::RQencodeTCoeffRef_Luma ( MbDataAccess& rcMbDataAccess,
MbDataAccess& rcMbDataAccessBase,
LumaIdx cIdx,
UInt uiScanIndex )
{
TCoeff* piCoeff = rcMbDataAccess .getMbTCoeffs().get( cIdx );
TCoeff* piCoeffBase = rcMbDataAccessBase.getMbTCoeffs().get( cIdx );
const UChar* pucScan = g_aucFrameScan;
ETRACE_T( "LUMA_4x4_REF" );
ETRACE_V( cIdx.b4x4() );
ETRACE_V( uiScanIndex );
ETRACE_N;
RNOK( xRQencodeTCoeffsRef( piCoeff, piCoeffBase, pucScan, uiScanIndex ) );
return Err::m_nOK;
}
ErrVal
UvlcWriter::xRQencodeTCoeffsRef( TCoeff* piCoeff,
TCoeff* piCoeffBase,
const UChar* pucScan,
UInt uiScanIndex )
{
if (m_uiCodedSymbols % 3 == m_uiFragmentedSymbols) {
UInt uiCode = 0;
UInt uiTable = m_pSymGrp->getTable();
for (UInt ui = 0; ui < 3; ui++) {
UInt uiSymbol = m_auiPrescannedSymbols[m_uiCodedSymbols + ui];
m_pSymGrp->incrementCounter(uiSymbol);
uiCode *= 3;
uiCode += uiSymbol;
}
m_pSymGrp->setCodedFlag(true);
RNOK(writeCode( g_auiRefSymCode[uiTable][uiCode], g_auiRefSymLen[uiTable][uiCode], "" ) );
}
if (m_uiFragmentedSymbols) {
m_pSymGrp->setCodedFlag(true);
}
m_uiCodedSymbols++;
return Err::m_nOK;
}
ErrVal
UvlcWriter::xRQprescanTCoeffsRef( TCoeff* piCoeff,
TCoeff* piCoeffBase,
const UChar* pucScan,
UInt uiScanIndex)
{
UInt uiSig = ( piCoeff[pucScan[uiScanIndex]] ? 1 : 0 );
UChar uiSym = 0;
if(uiSig)
{
UInt uiSignBL = ( piCoeffBase[pucScan[uiScanIndex]] < 0 ? 1 : 0 );
UInt uiSignEL = ( piCoeff [pucScan[uiScanIndex]] < 0 ? 1 : 0 );
UInt uiSign = ( uiSignBL ^ uiSignEL );
uiSym = (uiSign ? 2:1);
}
m_auiPrescannedSymbols[m_uiRefSymbols] = uiSym;
m_uiRefSymbols++;
return Err::m_nOK;
}
ErrVal
UvlcWriter::RQencodeTCoeffRef_Chroma ( MbDataAccess& rcMbDataAccess,
MbDataAccess& rcMbDataAccessBase,
ResidualMode eResidualMode,
ChromaIdx cIdx,
UInt uiScanIndex )
{
TCoeff* piCoeff = rcMbDataAccess .getMbTCoeffs().get( cIdx );
TCoeff* piCoeffBase = rcMbDataAccessBase.getMbTCoeffs().get( cIdx );
const UChar* pucScan = ( eResidualMode == CHROMA_DC ? g_aucIndexChromaDCScan : g_aucFrameScan );
ETRACE_T( "CHROMA_4x4_REF" );
ETRACE_V( cIdx );
ETRACE_V( uiScanIndex );
ETRACE_N;
RNOK( xRQencodeTCoeffsRef( piCoeff, piCoeffBase, pucScan, uiScanIndex ) );
return Err::m_nOK;
}
ErrVal
UvlcWriter::RQencodeCycleSymbol( UInt uiCycle )
{
RNOK( xWriteFlag( uiCycle > 0 ) );
if ( uiCycle > 0 )
RNOK( xWriteFlag( uiCycle - 1 ) );
return Err::m_nOK;
}
ErrVal
UvlcWriter::xWriteGolomb(UInt uiSymbol, UInt uiK)
{
UInt uiQ = uiSymbol / uiK;
UInt uiR = uiSymbol - uiQ * uiK;
UInt uiC = 0;
UInt uiT = uiK >> 1;
while ( uiT > 0 )
{
uiC++;
uiT >>= 1;
}
// Unary part
for ( UInt ui = 0; ui < uiQ; ui++ )
{
RNOK( xWriteFlag( 1 ) );
}
RNOK( xWriteFlag( 0 ) );
// Binary part
if ( uiR < uiC )
{
RNOK( xWriteCode( uiR, uiC ) );
} else if ( uiC > 0 ) {
RNOK( xWriteFlag( 1 ) );
RNOK( xWriteCode( uiR - uiC, uiC ) );
}
ETRACE_N;
return Err::m_nOK;
}
UInt
UvlcWriter::peekGolomb(UInt uiSymbol, UInt uiK)
{
UInt uiQ = uiSymbol / uiK;
UInt uiR = uiSymbol - uiQ * uiK;
UInt uiC = 0;
UInt uiT = uiK >> 1;
while ( uiT > 0 )
{
uiC++;
uiT >>= 1;
}
// Unary part
uiT = uiQ + 1 + uiC;
if ( uiR >= uiC && uiC > 0 )
{
uiT++;
}
return uiT;
}
ErrVal
UvlcWriter::RQencodeEobOffsets_Luma( UInt* pauiSeq )
{
m_pSymGrp ->Init();
m_uiCbpStat4x4[0] = m_uiCbpStat4x4[1] = 0;
m_uiCbpStats[0][0] = m_uiCbpStats[0][1] = m_uiCbpStats[1][0] = m_uiCbpStats[1][1] = 0;
m_uiRefSymbols = 0;
m_uiCodedSymbols = 0;
memset(m_auiPrescannedSymbols, 0, sizeof(UChar) * REFSYM_MB);
m_uiFragmentedSymbols = 0;
memcpy( m_auiShiftLuma, pauiSeq, sizeof(UInt)*16 );
return xRQencodeEobOffsets(pauiSeq, 16);
}
ErrVal
UvlcWriter::RQencodeEobOffsets_Chroma( UInt* auiSeq )
{
memcpy( m_auiShiftChroma, auiSeq, sizeof(UInt)*16 );
m_auiShiftChroma[0] = 15;
return xRQencodeEobOffsets(auiSeq+1, 15);
}
ErrVal
UvlcWriter::xRQencodeEobOffsets( UInt* auiSeq, UInt uiMax )
{
UInt uiNumEnd = 0;
for (UInt uiEc=0; uiEc<uiMax && auiSeq[uiEc] == uiMax-1 && uiNumEnd<3; uiEc++)
{
uiNumEnd++;
}
if ( uiNumEnd )
{
RNOK( xWriteGolomb( uiNumEnd-1, 1 ) );
} else {
ETRACE_T("Eob");
RNOK( xWriteCode( 0x7, 3 ) );
ETRACE_N;
}
RNOK( xWriteGolomb( auiSeq[uiNumEnd], 2 ) );
RNOK( xEncodeMonSeq( auiSeq+uiNumEnd+1, auiSeq[uiNumEnd], uiMax-uiNumEnd-1 ) );
ETRACE_N;
return Err::m_nOK;
}
UInt g_auiSigRunTabCode[] = {0x01, 0x01, 0x01, 0x01, 0x00};
UInt g_auiSigRunTabCodeLen[] = {1, 2, 3, 4, 4};
ErrVal
UvlcWriter::RQencodeBestCodeTableMap( UInt* pauiTable, UInt uiMaxH )
{
memset( m_auiBestCodeTabMap, 0, sizeof(UInt)*uiMaxH );
Int uiW = uiMaxH-1;
for(uiW = uiMaxH-1; uiW >= 0; uiW--)
{
if(pauiTable[uiW] != 0)
break;
}
if(uiW < 0)
uiW = 0;
RNOK(xWriteCode(uiW, 4));
for(UInt uiH = 0; uiH <= (UInt)uiW; uiH++)
{
m_auiBestCodeTabMap[uiH] = pauiTable[uiH];
RNOK(xWriteCode(g_auiSigRunTabCode[pauiTable[uiH]], g_auiSigRunTabCodeLen[pauiTable[uiH]]));
}
return Err::m_nOK;
}
ErrVal
UvlcWriter::RQvlcFlush()
{
return Err::m_nOK;
}
ErrVal
UvlcWriter::RQupdateVlcTable()
{
m_pSymGrp->UpdateVlc();
m_uiRefSymbols = 0;
m_uiCodedSymbols = 0;
memset(m_auiPrescannedSymbols, 0, sizeof(UChar) * REFSYM_MB);
return Err::m_nOK;
}
ErrVal
UvlcWriter::RQcountFragmentedSymbols()
{
if ((m_uiRefSymbols - m_uiCodedSymbols) > 0) {
m_pSymGrp->setCodedFlag(false);
switch (m_uiCodedSymbols%3) {
case 0: m_uiFragmentedSymbols = 0; break;
case 1: m_uiFragmentedSymbols = 2; break;
case 2: m_uiFragmentedSymbols = 1; break;
}
}
return Err::m_nOK;
}
ErrVal
UvlcWriter::xEncodeMonSeq ( UInt* auiSeq, UInt uiStartVal, UInt uiLen )
{
UInt uiRun = 0;
UInt uiLevel = uiStartVal;
for (UInt uiPos=0; uiPos<uiLen && uiLevel > 0; uiPos++)
{
if (auiSeq[uiPos] == uiLevel)
{
uiRun++;
} else {
RNOK( xWriteGolomb( uiRun, 1 ) );
uiRun = 1;
uiLevel--;
while ( uiLevel > auiSeq[uiPos] )
{
RNOK( xWriteGolomb( 0, 1 ) );
uiLevel--;
}
}
}
if (uiLevel > 0)
{
RNOK( xWriteGolomb( uiRun, 1 ) );
}
return Err::m_nOK;
}
ErrVal
UvlcWriter::xWriteSigRunCode ( UInt uiSymbol, UInt uiTableIdx )
{
assert( uiTableIdx >= 0 && uiTableIdx <= 4 );
if(uiTableIdx == 0)
{
// unary code
RNOK ( xWriteUnaryCode (uiSymbol) );
}
else if (uiTableIdx == 1)
{
RNOK ( xWriteCodeCB1 (uiSymbol) );
}
else if (uiTableIdx == 2)
{
RNOK ( xWriteCodeCB2 (uiSymbol) );
}
else if (uiTableIdx == 3)
{
if ( uiSymbol == 0 )
{
RNOK( xWriteFlag( 1 ) );
}
else
{
RNOK( xWriteFlag( 0 ) );
RNOK( xWriteCodeCB2 (uiSymbol-1) );
}
}
else // uiTableIdx == 4
{
if(uiSymbol == 0)
{
RNOK (xWriteFlag ( 1 ));
}
else
{
RNOK (xWriteCodeCB1(uiSymbol+1));
}
}
return Err::m_nOK;
}
ErrVal
UvlcWriter::xWriteUnaryCode ( UInt uiSymbol )
{
UInt uiStart = 0;
do
{
if(uiSymbol == uiStart)
{
RNOK( xWriteFlag (1) );
break;
}
else
{
RNOK( xWriteFlag (0) );
uiStart++;
}
}
while (true);
return Err::m_nOK;
}
ErrVal
UvlcWriter::xWriteCodeCB1 ( UInt uiSymbol )
{
// this function writes codeword for the input symbol according to the {2, 2, 3, 3, 4, 4...} codebook
for(UInt ui = 0; ui < uiSymbol/2; ui ++)
{
RNOK (xWriteFlag (0));
}
RNOK (xWriteCode((3-(uiSymbol%2)), 2)) ;
return Err::m_nOK;
}
ErrVal
UvlcWriter::xWriteCodeCB2 ( UInt uiSymbol )
{
// this function writes codeword for the input symbol according to the {2, 2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -