📄 fgssubbandencoder.cpp
字号:
{
ui++;
m_auiScanPosVectLuma[ui] = m_auiScanPosVectLuma[ui-1]+uiGroupingSize;
}
}
else
{
//vector specified
ui = 0;
m_auiScanPosVectLuma[ui] = m_pcSliceHeader->getPosVect(ui) - 1;
while( m_auiScanPosVectLuma[ui] < 15)
{
ui++;
m_auiScanPosVectLuma[ui] = m_auiScanPosVectLuma[ui-1] + m_pcSliceHeader->getPosVect(ui);
}
}
try
{
UInt uiScanPos;
UInt iStartCycle = 0, iCycle = 0;
UInt iLastBitsLuma = 0;
UInt iLastBitsChroma = 0;
UInt iBitsLuma = 0;
UInt iBitsChroma = 0;
UInt iLumaScanIdx = 0;
UInt iChromaDCScanIdx = 0;
UInt iChromaACScanIdx = 1;
UInt uiPass;
UInt uiPassStart;
m_uiFirstMbInSlice = m_pcSliceHeader->getFirstMbInSlice();
UInt uiLastMbInSlice = m_pcSliceHeader->getLastMbInSlice();
//--ICU/ETRI FMO Implementation : start
UInt uiFirstMbY = (UInt) ( m_uiFirstMbInSlice / m_uiWidthInMB );
UInt uiFirstMbX = m_uiFirstMbInSlice % m_uiWidthInMB;
uiLastMbY = (UInt) ( ( uiLastMbInSlice+1) / m_uiWidthInMB );
uiLastMbX = ( uiLastMbInSlice+1) % m_uiWidthInMB;
if(!uiFracNb) //FIX_FRAG_CAVLC
{
// Pre-scan frame to find VLC positions
UInt auiEobShift[16];
UInt auiHighMagHist[16];
UInt auiBestCodeTabMap[16];
UInt* pauiHistLuma = new UInt[16*16*16];
UInt* pauiHistChroma = new UInt[16*16*16];
::memset(pauiHistLuma , 0x00, 16*16*16*sizeof(UInt));
::memset(pauiHistChroma, 0x00, 16*16*16*sizeof(UInt));
::memset(auiHighMagHist, 0x00, 16*sizeof(UInt));
for(UInt uiMbAddress=m_uiFirstMbInSlice ;uiMbAddress<=uiLastMbInSlice ;)
{
UInt uiMbYIdx = uiMbAddress / m_uiWidthInMB;
UInt uiMbXIdx = uiMbAddress % m_uiWidthInMB;
MbDataAccess *pcMbDataAccessCurr = NULL;
RNOK( m_cMbDataCtrlEL .initMb( pcMbDataAccessCurr, uiMbYIdx, uiMbXIdx ) );
const Bool bFrame = (FRAME == pcMbDataAccessCurr->getMbPicType());
{
//===== LUMA =====
for( UInt uiB8YIdx = 2 * uiMbYIdx; uiB8YIdx < 2 * uiMbYIdx + 2; uiB8YIdx++ )
for( UInt uiB8XIdx = 2 * uiMbXIdx; uiB8XIdx < 2 * uiMbXIdx + 2; uiB8XIdx++ )
{
for( UInt uiBlockYIdx = 2 * uiB8YIdx; uiBlockYIdx < 2 * uiB8YIdx + 2; uiBlockYIdx++ )
for( UInt uiBlockXIdx = 2 * uiB8XIdx; uiBlockXIdx < 2 * uiB8XIdx + 2; uiBlockXIdx++ )
{
RNOK( xVLCParseLuma( uiBlockYIdx, uiBlockXIdx, pauiHistLuma, auiHighMagHist, bFrame ) );
} // 4x4 block iteration
} // 8x8 block iteration
// ===== CHROMA AC =====
for( UInt uiPlane = 0; uiPlane < 2; uiPlane ++ )
for( UInt uiB8YIdx = 2 * uiMbYIdx; uiB8YIdx < 2 * uiMbYIdx + 2; uiB8YIdx++ )
for( UInt uiB8XIdx = 2 * uiMbXIdx; uiB8XIdx < 2 * uiMbXIdx + 2; uiB8XIdx++ ) {
RNOK( xVLCParseChromaAC( uiPlane, uiB8YIdx, uiB8XIdx, pauiHistChroma, bFrame ) );
}
} // macroblock iteration
//--ICU/ETRI FMO Implementation
uiMbAddress = m_pcSliceHeader->getFMO()->getNextMBNr(uiMbAddress );
}
RNOK( m_cMbDataCtrlEL .initSlice ( *m_pcSliceHeader, PRE_PROCESS, false, NULL ) );
RNOK( m_pcCurrMbDataCtrl->initSlice ( *m_pcSliceHeader, PRE_PROCESS, false, NULL ) );
// Tally over base pos to find EOB shift
for (uiScanPos=0; uiScanPos<16; uiScanPos++)
{
auiEobShift[uiScanPos] = 0;
for (UInt uiHpos=1; uiHpos<16; uiHpos++) {
UInt uiTotal = 0;
for (UInt uiBase=0; uiBase<16; uiBase++)
uiTotal += pauiHistLuma[(uiScanPos*16+uiBase)*16+uiHpos];
if (uiTotal < auiHighMagHist[uiScanPos])
break;
if (uiScanPos > 0 && auiEobShift[uiScanPos] == auiEobShift[uiScanPos-1])
break;
auiEobShift[uiScanPos]++;
}
}
// 'Outlier' removal
if (auiEobShift[0] > auiEobShift[1] + 8)
auiEobShift[0] = 15;
RNOK( m_pcSymbolWriter->RQencodeEobOffsets_Luma( auiEobShift ) );
UInt uiTempCodeLenCycleBase[][16] = {
{1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16}, // unary 0
{2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}, // flat 2 1
{2, 2, 2, 4, 4, 4, 6, 6, 6, 8, 8, 8,10,10,10,11}, // flat 3 2
{1, 3, 3, 3, 5, 5, 5, 7, 7, 7, 9, 9, 9,11,11,11}, // S3 cutoff 0 3
{1, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,9, 9, 9}}; //
UInt *pauiHistLumaNoBase = new UInt[16*16];
UInt uiTotalNumCodeTable = 5;
UInt uiTotalRunCost = 0;
UInt uiCycle=0;
// tally histogram without LEBL index
memset(pauiHistLumaNoBase, 0, sizeof(UInt)*16*16);
for(uiCycle = 0; uiCycle < 16; uiCycle++)
{
for(ui = 0; ui < 16; ui++)
for(UInt uiBase = 0; uiBase < 16; uiBase++)
pauiHistLumaNoBase[uiCycle*16+ui] += pauiHistLuma[(uiCycle*16+uiBase)*16+ui];
}
uiCycle = 0;
UInt uiBestTable;
UInt uiCost[5], uiBestCost;
UInt uiTableIdx;
// find the cost of using each table
for(uiTableIdx = 0; uiTableIdx < uiTotalNumCodeTable; uiTableIdx++)
{
UInt *uiTable = uiTempCodeLenCycleBase[uiTableIdx];
uiCost[uiTableIdx] = 0;
for(ui = 1; ui < 16; ui++)
{
UInt uiCodeLen = uiTable[ui-1];
uiCost[uiTableIdx] += pauiHistLumaNoBase[ui]*uiCodeLen;
}
}
// find the best table with lowest cost
uiBestTable = 0;
uiBestCost = uiCost[0];
for(uiTableIdx = 1; uiTableIdx < uiTotalNumCodeTable; uiTableIdx++)
{
if(uiCost[uiTableIdx] < uiBestCost)
{
uiBestTable = uiTableIdx;
uiBestCost = uiCost[uiTableIdx];
}
}
auiBestCodeTabMap[uiCycle] = uiBestTable;
uiTotalRunCost += uiBestCost;
for(uiCycle = 1; uiCycle < 16; uiCycle++)
{
// find the cost of using each table
for( uiTableIdx = 0; uiTableIdx < uiTotalNumCodeTable; uiTableIdx++)
{
UInt *uiTable = uiTempCodeLenCycleBase[uiTableIdx];
uiCost[uiTableIdx] = 0;
for(ui = 0; ui < 16; ui++)
{
UInt uiSymbol;
if(ui == 0)
{
uiSymbol = auiEobShift[uiCycle];
}
else
{
uiSymbol = (ui <= auiEobShift[uiCycle])? ui-1:ui;
}
UInt uiCodeLen = uiTable[uiSymbol];
uiCost[uiTableIdx] += pauiHistLumaNoBase[(uiCycle*16)+ui]*uiCodeLen;
}
}
// find the best table with lowest cost
uiBestTable = 0;
uiBestCost = uiCost[0];
for(uiTableIdx = 1; uiTableIdx < uiTotalNumCodeTable; uiTableIdx++)
{
if(uiCost[uiTableIdx] < uiBestCost)
{
uiBestTable = uiTableIdx;
uiBestCost = uiCost[uiTableIdx];
}
}
auiBestCodeTabMap[uiCycle] = uiBestTable;
uiTotalRunCost += uiBestCost;
}
delete pauiHistLumaNoBase;
// Tally over base pos to find EOB shift
for (uiScanPos=0; uiScanPos<16; uiScanPos++)
{
auiEobShift[uiScanPos] = 0;
UInt uiEobTotal = 0;
for (UInt uiBase=0; uiBase<16; uiBase++)
uiEobTotal += pauiHistChroma[(uiScanPos*16+uiBase)*16];
for (UInt uiHpos=1; uiHpos<16; uiHpos++)
{
UInt uiTotal = 0;
for (int uiBase=0; uiBase<16; uiBase++)
uiTotal += pauiHistChroma[(uiScanPos*16+uiBase)*16+uiHpos];
if (uiTotal < uiEobTotal)
break;
if (uiScanPos > 0 && auiEobShift[uiScanPos] == auiEobShift[uiScanPos-1])
break;
auiEobShift[uiScanPos]++;
}
}
// 'Outlier' removal
if (auiEobShift[0] > auiEobShift[1] + 8)
auiEobShift[0] = 15;
RNOK( m_pcSymbolWriter->RQencodeEobOffsets_Chroma( auiEobShift ) );
RNOK( m_pcSymbolWriter->RQencodeBestCodeTableMap( auiBestCodeTabMap, 16 ) );
delete pauiHistLuma;
delete pauiHistChroma;
} //FIX_FRAG_CAVLC
uiLumaCbpBitCount = 0;
uiLumaCbpNextMbX = uiFirstMbX;
uiLumaCbpNextMbY = uiFirstMbY;
uiLumaCbpNext8x8Idx = 0;
uiChromaCbpBitCount = 0;
uiChromaCbpNextMbX = uiFirstMbX;
uiChromaCbpNextMbY = uiFirstMbY;
if( ! m_pcSliceHeader->getPPS().getEntropyCodingModeFlag() && !uiFracNb)
{
xEncodeLumaCbpVlcStart( uiLumaCbpNextMbX, uiLumaCbpNextMbY, uiLumaCbpNext8x8Idx,
uiLastMbX, uiLastMbY, uiLumaCbpBitCount);
xEncodeChromaCbpVlcStart(uiFirstMbX, uiFirstMbY, uiChromaCbpBitCount);
}
ruiNumPDFrags = 0;
puiPDFragBits[0] = 0;
// chroma cycle frequency.
// hard-coded for now, should this be moved to the slice header
iStartCycle = ( m_eSliceType == B_SLICE ) ? 2 : 3;
if( !uiFracNb )
{
m_pcSymbolWriter->RQencodeCycleSymbol( iStartCycle-1 );
}
UInt uiNumFrags;
Int aiMaxPosLuma[16], aiMaxPosChromaAC[16], aiMaxPosChromaDC[16];
uiFragIdx = 0;
uiNumFrags = xDeriveComponentPosVectors( m_auiScanPosVectLuma,
aiMaxPosLuma, aiMaxPosChromaAC, aiMaxPosChromaDC, iStartCycle );
while (iLumaScanIdx < 16 || iChromaDCScanIdx < 4 || iChromaACScanIdx < 16)
{
UInt bAllowChromaDC, bAllowChromaAC;
UInt uiMaxPosLuma;
UInt uiMaxPosChromaAC;
UInt uiMaxPosChromaDC;
if(!uiFracNb)
{
// start values for loops
m_uiMbYIdx = uiFirstMbY;
m_uiMbXIdx = ( m_uiMbYIdx == uiFirstMbY ? uiFirstMbX : 0 );
m_c8x8Idx = B8x8Idx();
m_cIdx = S4x4Idx();
m_uiFGSPart = 0;
uiPassStart = 0;
}
else
{
if(bRestore)
{
bCheck = false;
// restore status
xRestoreFGSState(iLumaScanIdx, iChromaDCScanIdx, iChromaACScanIdx, iStartCycle,
iCycle, uiPassStart, uiFragIdx,
iLastBitsLuma,
iLastQP);
// restore the cbp-related coding states
uiLumaCbpNextMbX = m_uiLumaCbpNextMbX;
uiLumaCbpNextMbY = m_uiLumaCbpNextMbY;
uiLumaCbpNext8x8Idx = m_uiLumaCbpNext8x8Idx;
uiChromaCbpNextMbX = m_uiChromaCbpNextMbX;
uiChromaCbpNextMbY = m_uiChromaCbpNextMbY;
bRestore = false;
}
else
{
uiPassStart = 0;
}
}
uiPass = uiPassStart;
uiMaxPosLuma = aiMaxPosLuma [uiFragIdx];
uiMaxPosChromaAC = aiMaxPosChromaAC[uiFragIdx];
uiMaxPosChromaDC = aiMaxPosChromaDC[uiFragIdx];
if( uiFragIdx == 0 )
{
bAllowChromaDC = true;
bAllowChromaAC = aiMaxPosChromaAC[0] > 0;
}
else
{
bAllowChromaDC = (Int) uiMaxPosChromaDC > aiMaxPosChromaDC[uiFragIdx - 1];
bAllowChromaAC = (Int) uiMaxPosChromaAC > aiMaxPosChromaAC[uiFragIdx - 1];
}
// flush the bitstream, and send the re-sync marker
if( m_pcSliceHeader->getFGSCycleAlignedFragment() )
{
// any more fragment to follow?
if( iLumaScanIdx > 0 )
{
// do not know why the reader can not have enough bits
RNOK( m_pcSymbolWriter->RQencodeTermBit( 1 ) );
RNOK( m_pcSymbolWriter->RQencodeTermBit( 1 ) );
RNOK( m_pcSymbolWriter->finishSlice() );
// byte-aligned, same as NalUnitEncoder::xWriteTrailingBits
RNOK( m_pcSymbolWriter->getWriteBuffer()->write( 1 ) );
RNOK( m_pcSymbolWriter->getWriteBuffer()->writeAlignZero() );
// do not have to flush the buffer as more fragments will be coded
// record the end of the segment
puiPDFragBits[uiFragIdx] = m_pcSymbolWriter->getWriteBuffer()->getNumberOfWrittenBits();
m_pcSliceHeader->setSliceType( m_eSliceType );
m_pcSymbolWriter->RQreset( *m_pcSliceHeader );
m_pcSliceHeader->setSliceType( F_SLICE );
}
}
for(UInt uiMbAddress=m_uiFirstMbInSlice ;uiMbAddress<=uiLastMbInSlice;)
{
const UInt uiMbYIdx = uiMbAddress / m_uiWidthInMB;
const UInt uiMbXIdx = uiMbAddress % m_uiWidthInMB;
MbDataAccess *pcMbDataAccess = NULL;
RNOK( m_pcCurrMbDataCtrl->initMb( pcMbDataAccess, uiMbYIdx, uiMbXIdx ) );
const Bool bFrame = (FRAME == pcMbDataAccess->getMbPicType());
{
if( ! m_pcSliceHeader->getPPS().getEntropyCodingModeFlag() )
{
Bool bFirstPassPrescan = bFirstPass;
UInt uiB8YInit, uiB8XInit, uiBlockYInit, uiBlockXInit;
uiB8YInit = m_uiMbYIdx*2 + m_c8x8Idx.y()/2;
uiB8XInit = m_uiMbXIdx*2 + m_c8x8Idx.x()/2;
uiBlockYInit = 2*uiB8YInit;
uiBlockXInit = 2*uiB8XInit;
if(!bFirstPassPrescan)
{
uiB8YInit = 2*uiMbYIdx;
uiB8XInit = 2*uiMbXIdx;
}
/* refinement coefficients pre-scan */
//===== LUMA =====
if( (m_uiFGSPart == 0) || (!bFirstPassPrescan) )
{
for( UInt uiB8YIdx = uiB8YInit; uiB8YIdx < 2 * uiMbYIdx + 2; uiB8YIdx++ )
{
for( UInt uiB8XIdx = uiB8XInit; uiB8XIdx < 2 * uiMbXIdx + 2; uiB8XIdx++ )
{
if(!bFirstPassPrescan
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -