uvlcwriter.cpp
来自「JVT-S203 contains the JSVM 6 reference s」· C++ 代码 · 共 2,605 行 · 第 1/5 页
CPP
2,605 行
UInt uiStart,
UInt uiStop,
UInt uiVlcTable,
const UChar* pucScan,
UInt& ruiNumMagG1 )
{
// Any magnitudes greater than one?
ruiNumMagG1 = 0;
UInt uiCountMag1 = 0;
UInt uiMaxMag = 0;
UInt ui;
for( ui = uiStart; ui < uiStop; ui++ )
{
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++ )
{
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++ )
{
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 )
{
UInt uiSig = ( piCoeff[pucScan[uiScanIndex]] ? 1 : 0 );
UInt 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);
}
RNOK( m_pSymGrp->Write( uiSym ) );
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;
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();
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, 2, 4, 4, 4...} codebook
for(UInt ui = 0; ui < uiSymbol/3; ui ++)
{
RNOK(xWriteCode (0, 2));
}
RNOK (xWriteCode((3-(uiSymbol%3)), 2));
return Err::m_nOK;
}
UcSymGrpWriter::UcSymGrpWriter( UvlcWriter* pParent )
{
m_pParent = pParent;
Init();
}
ErrVal
UcSymGrpWriter::Init()
{
m_uiCode = 0;
m_uiLen = 0;
m_auiSymCount[0] = m_auiSymCount[1] = m_auiSymCount[2] = 0;
m_uiTable = 0;
m_uiCodedFlag = false;
return Err::m_nOK;
}
ErrVal
UcSymGrpWriter::Write( UChar ucSym )
{
// ucSym takes one of three values {0, 1, 2}
AOF((ucSym & 0xfc) == 0);
{
m_uiCode *= 3;
m_uiCode += ucSym;
m_auiSymCount[ucSym]++;
m_uiLen++;
if ( m_uiLen == CAVLC_SYMGRP_SIZE )
{
m_uiCodedFlag = true;
RNOK( m_pParent->writeCode( g_auiRefSymCode[m_uiTable][m_uiCode], g_auiRefSymLen[m_uiTable][m_uiCode], "" ) );
m_uiCode = 0;
m_uiLen = 0;
}
}
return Err::m_nOK;
}
Bool
UcSymGrpWriter::UpdateVlc()
{
UInt uiFlag = m_uiCodedFlag;
if (uiFlag && m_uiLen == 0) {
// updating
m_uiTable = 0;
if (m_auiSymCount[0] < 2 *(m_auiSymCount[1] + m_auiSymCount[2]) ||
m_auiSymCount[1] < 2 * m_auiSymCount[2]) {
m_uiTable = 1;
}
// scaling
m_auiSymCount[0] = (m_auiSymCount[0] >> 1);
m_auiSymCount[1] = (m_auiSymCount[1] >> 1);
m_auiSymCount[2] = (m_auiSymCount[2] >> 1);
m_uiCodedFlag = false;
}
return (uiFlag != 0);
}
ErrVal
UcSymGrpWriter::Flush()
{
if ( m_uiLen == 0 )
return Err::m_nOK;
{
UInt uiMulti = 1;
for(UInt ui = 0; ui < (CAVLC_SYMGRP_SIZE-m_uiLen); ui++)
uiMulti *= 3;
m_uiCode *= uiMulti;
m_uiLen = 0;
}
RNOK( m_pParent->writeCode( g_auiRefSymCode[m_uiTable][m_uiCode], g_auiRefSymLen[m_u
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?