📄 fgscoder.cpp
字号:
}
else
{
for( UInt ui = 0; ui < 64; ui++ )
{
piCoeff[ui] = ( ( piCoeff[ui] * g_aaiDequantCoef64[rcQP.rem()][ui] * 16 + iAdd ) << rcQP.per() ) >> 6;
}
}
return Err::m_nOK;
}
ErrVal
FGSCoder::xScaleTCoeffs( MbDataAccess& rcMbDataAccess,
Bool bBaseLayer )
{
const Int aaiDequantDcCoef[6] = { 10, 11, 13, 14, 16, 18 };
Quantizer cQuantizer;
cQuantizer.setQp( rcMbDataAccess, false );
const QpParameter& cLQp = cQuantizer.getLumaQp ();
const QpParameter& cCQp = cQuantizer.getChromaQp();
Bool bIntra = rcMbDataAccess.getMbData().isIntra();
Bool b8x8 = rcMbDataAccess.getMbData().isTransformSize8x8();
Bool b16x16 = rcMbDataAccess.getMbData().isIntra16x16();
UInt uiYScalId = ( bIntra ? ( b8x8 && !b16x16 ? 6 : 0 ) : ( b8x8 ? 7 : 3 ) );
UInt uiUScalId = ( bIntra ? 1 : 4 );
UInt uiVScalId = ( bIntra ? 2 : 5 );
const UChar* pucScaleY = rcMbDataAccess.getSH().getScalingMatrix( uiYScalId );
const UChar* pucScaleU = rcMbDataAccess.getSH().getScalingMatrix( uiUScalId );
const UChar* pucScaleV = rcMbDataAccess.getSH().getScalingMatrix( uiVScalId );
Int iScale = 1;
if (!rcMbDataAccess.getMbData().isPCM() )
rcMbDataAccess.getMbTCoeffs().storeLevelData(); // for SVC to AVC rewrite
//===== luma =====
if( b16x16 )
{
//===== INTRA_16x16 =====
for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ )
{
RNOK( xScale4x4Block( rcMbDataAccess.getMbTCoeffs().get ( cIdx ), pucScaleY, 1, cLQp ) );
}
iScale = aaiDequantDcCoef[cLQp.rem()] << cLQp.per();
if( pucScaleY )
{
iScale *= pucScaleY[0];
iScale >>= 4;
}
// perform scaling only
TCoeff* piCoeff = rcMbDataAccess.getMbTCoeffs().get( B4x4Idx(0) );
for( Int uiDCIdx = 0; uiDCIdx < 16; uiDCIdx++ )
{
TCoeff a = piCoeff[16*uiDCIdx] * iScale;
Int b = piCoeff[16*uiDCIdx] * iScale;
if( a != b )
{
printf("Short overflow in FGS Intra16x16 DC-coeffs.\n");
// not good
piCoeff[16*uiDCIdx] = max( (Int)MSYS_SHORT_MIN, min( (Int)MSYS_SHORT_MAX, b ) );
}
else
{
piCoeff[16*uiDCIdx] *= iScale;
}
}
//===== correct CBP =====
rcMbDataAccess.getMbData().setMbCbp( rcMbDataAccess.getAutoCbp() );
}
else if( b8x8 )
{
//===== 8x8 BLOCKS =====
for( B8x8Idx cIdx; cIdx.isLegal(); cIdx++ )
{
RNOK( xScale8x8Block( rcMbDataAccess.getMbTCoeffs().get8x8( cIdx ), pucScaleY, cLQp ) );
}
}
else
{
//===== 4x4 BLOCKS =====
for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ )
{
RNOK( xScale4x4Block( rcMbDataAccess.getMbTCoeffs().get ( cIdx ), pucScaleY, 0, cLQp ) );
}
}
//===== chroma =====
for( CIdx cIdx; cIdx.isLegal(); cIdx++ )
{
RNOK( xScale4x4Block( rcMbDataAccess.getMbTCoeffs().get( cIdx ), ( cIdx.plane() ? pucScaleV : pucScaleU ), 1, cCQp ) );
}
// only performs scaling, not inverse transform
UInt uiMbIndex = rcMbDataAccess.getMbY()*m_uiWidthInMB+rcMbDataAccess.getMbX();
iScale = g_aaiDequantCoef[cCQp.rem()][0] << cCQp.per();
/* HS: old scaling modified:
(I did not work for scaling matrices, when QpPer became less than 5 in an FGS enhancement) */
for( CIdx cCIdx; cCIdx.isLegal(); cCIdx++ )
{
if(! bBaseLayer && ! ( m_pcCoefMap[uiMbIndex].getCoefMap( cCIdx )[0] & CODED ) && !m_bUpdateWithoutMap )
// condition "! bBaseLayer" is needed. When "xScaleTCoeffs is called
// before first FGS layer, m_aapaucChromaDCCoefMap is not initialized
rcMbDataAccess.getMbTCoeffs().get( cCIdx )[0] = 0;
else
rcMbDataAccess.getMbTCoeffs().get( cCIdx )[0] *= iScale;
}
return Err::m_nOK;
}
ErrVal
FGSCoder::xReconstructMacroblock( MbDataAccess& rcMbDataAccess,
IntYuvMbBuffer& rcMbBuffer )
{
m_pcTransform->setClipMode( false );
Int iLStride = rcMbBuffer.getLStride();
Int iCStride = rcMbBuffer.getCStride();
Bool b8x8 = rcMbDataAccess.getMbData().isTransformSize8x8();
MbTransformCoeffs& rcCoeffs = rcMbDataAccess.getMbTCoeffs();
rcMbBuffer.loadBuffer( m_pcBaseLayerSbb->getPic(rcMbDataAccess.getMbPicType())->getFullPelYuvBuffer() );//TMM_INTERLACE
TCoeff lumaDcCoeffs[16];
if ( rcMbDataAccess.getMbData().isIntra16x16() )
{
// backup luma DC
TCoeff *piCoeffs;
UInt uiDCIdx;
piCoeffs = rcCoeffs.get( B4x4Idx(0) );
for( uiDCIdx = 0; uiDCIdx < 16; uiDCIdx++ )
lumaDcCoeffs[uiDCIdx] = piCoeffs[16*uiDCIdx] ;
// inverse transform on luma DC
RNOK( m_pcTransform->invTransformDcCoeff( piCoeffs, 1 ) );
// inverse transform on entire MB
for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ )
{
RNOK( m_pcTransform->invTransform4x4Blk( rcMbBuffer.getYBlk( cIdx ), iLStride, rcCoeffs.get( cIdx ) ) );
}
// restore luma DC
for( uiDCIdx = 0; uiDCIdx < 16; uiDCIdx++ )
piCoeffs[16*uiDCIdx] = lumaDcCoeffs[uiDCIdx];
}
else if( b8x8 )
{
for( B8x8Idx cIdx; cIdx.isLegal(); cIdx++ )
{
RNOK( m_pcTransform->invTransform8x8Blk( rcMbBuffer.getYBlk( cIdx ), iLStride, rcCoeffs.get8x8( cIdx ) ) );
}
}
else
{
for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ )
{
RNOK( m_pcTransform->invTransform4x4Blk( rcMbBuffer.getYBlk( cIdx ), iLStride, rcCoeffs.get( cIdx ) ) );
}
}
TCoeff chromaDcCoeffs[2][4];
UInt uiPlane;
Int iScale;
Bool bIntra = rcMbDataAccess.getMbData().isIntra();
UInt uiUScalId = ( bIntra ? 1 : 4 );
UInt uiVScalId = ( bIntra ? 2 : 5 );
const UChar* pucScaleU = rcMbDataAccess.getSH().getScalingMatrix( uiUScalId );
const UChar* pucScaleV = rcMbDataAccess.getSH().getScalingMatrix( uiVScalId );
// backup chroma DC coefficients
for( uiPlane = 0; uiPlane < 2; uiPlane++ )
{
TCoeff* piCoeff = rcCoeffs.get( CIdx(4*uiPlane) );
for( UInt uiDCIdx = 0; uiDCIdx < 4; uiDCIdx++ )
chromaDcCoeffs[uiPlane][uiDCIdx] = piCoeff[16*uiDCIdx];
}
// scaling has already been performed on DC coefficients
iScale = ( pucScaleU ? pucScaleU[0] : 16 );
m_pcTransform->invTransformChromaDc( rcCoeffs.get( CIdx(0) ), iScale );
iScale = ( pucScaleV ? pucScaleV[0] : 16 );
m_pcTransform->invTransformChromaDc( rcCoeffs.get( CIdx(4) ), iScale );
RNOK( m_pcTransform->invTransformChromaBlocks( rcMbBuffer.getMbCbAddr(), iCStride, rcCoeffs.get( CIdx(0) ) ) );
RNOK( m_pcTransform->invTransformChromaBlocks( rcMbBuffer.getMbCrAddr(), iCStride, rcCoeffs.get( CIdx(4) ) ) );
// restore chroma DC coefficients
for( uiPlane = 0; uiPlane < 2; uiPlane++ )
{
TCoeff* piCoeff = rcCoeffs.get( CIdx(4*uiPlane) );
for( UInt uiDCIdx = 0; uiDCIdx < 4; uiDCIdx++ )
piCoeff[16*uiDCIdx] = chromaDcCoeffs[uiPlane][uiDCIdx];
}
m_pcTransform->setClipMode( true );
return Err::m_nOK;
}
Int
FGSCoder::xScaleLevel4x4( Int iLevel,
Int iIndex,
const QpParameter& cQP,
const QpParameter& cBaseQP )
{
Int iSign = ( iLevel < 0 ? -1 : 1 );
Int iBaseScale = g_aaiDequantCoef[cBaseQP.rem()][iIndex] << cBaseQP.per();
Int iScale = g_aaiDequantCoef[cQP .rem()][iIndex] << cQP .per();
return iSign * ( ( abs(iLevel) * iBaseScale ) + ( iScale >> 1 ) ) / iScale;
}
Int
FGSCoder::xScaleLevel8x8( Int iLevel,
Int iIndex,
const QpParameter& cQP,
const QpParameter& cBaseQP )
{
Int iSign = ( iLevel < 0 ? -1 : 1 );
Int iBaseScale = g_aaiDequantCoef64[cBaseQP.rem()][iIndex] << cBaseQP.per();
Int iScale = g_aaiDequantCoef64[cQP .rem()][iIndex] << cQP .per();
return iSign * ( ( abs(iLevel) * iBaseScale ) + ( iScale >> 1 ) ) / iScale;
}
ErrVal
FGSCoder::xScaleSymbols4x4( TCoeff* piCoeff,
const QpParameter& cQP,
const QpParameter& cBaseQP )
{
for( Int iIndex = 0; iIndex < 16; iIndex++ )
{
if( piCoeff[iIndex] )
{
piCoeff[iIndex] = xScaleLevel4x4( piCoeff[iIndex], iIndex, cQP, cBaseQP );
}
}
return Err::m_nOK;
}
ErrVal
FGSCoder::xScaleSymbols8x8( TCoeff* piCoeff,
const QpParameter& cQP,
const QpParameter& cBaseQP )
{
for( Int iIndex = 0; iIndex < 64; iIndex++ )
{
if( piCoeff[iIndex] )
{
piCoeff[iIndex] = xScaleLevel8x8( piCoeff[iIndex], iIndex, cQP, cBaseQP );
}
}
return Err::m_nOK;
}
ErrVal
FGSCoder::xUpdateSymbols( TCoeff* piCoeff,
TCoeff* piCoeffEL,
Bool& bSigDC,
Bool& bSigAC,
Int iNumCoeff )
{
piCoeff [0] += piCoeffEL[0];
if( piCoeff [0] )
{
bSigDC = true;
}
for( Int iIndex = 1; iIndex < iNumCoeff; iIndex++ )
{
piCoeff [iIndex] += piCoeffEL[iIndex];
if( piCoeff[iIndex] )
{
bSigAC = true;
}
}
return Err::m_nOK;
}
// get 4x4 significance map for luma
Void FGSCoder::getCoeffSigMap( UInt uiMbX, UInt uiMbY, S4x4Idx cIdx, UChar *pucSigMap, Bool bFrame )
{
CoefMap *pcCoefMap = m_pcCoefMap[uiMbY * m_uiWidthInMB + uiMbX ].getCoefMap( cIdx );
const UChar* pucScan = (bFrame) ? g_aucFrameScan : g_aucFieldScan;
for( UInt uiScanIndex = 0; uiScanIndex < 16; uiScanIndex ++ )
{
pucSigMap[pucScan[uiScanIndex]] = SIGNIFICANT & pcCoefMap[uiScanIndex];
}
}
// get 8x8 significance map for luma
Void FGSCoder::getCoeffSigMap( UInt uiMbX, UInt uiMbY, B8x8Idx c8x8Idx, UChar *pucSigMap, Bool bFrame )
{
CoefMap *pcCoefMap = m_pcCoefMap[uiMbY * m_uiWidthInMB + uiMbX].getCoefMap( c8x8Idx );
const UChar* pucScan64 = (bFrame) ? g_aucFrameScan64 : g_aucFieldScan64;
for( UInt ui8x8ScanIndex = 0; ui8x8ScanIndex < 64; ui8x8ScanIndex ++ )
{
pucSigMap[pucScan64[ui8x8ScanIndex]] = SIGNIFICANT & pcCoefMap[ui8x8ScanIndex];
}
}
// get 4x4 significance map for chroma
Void FGSCoder::getCoeffSigMap( UInt uiMbX, UInt uiMbY, CIdx cIdx, UChar *pucSigMap, Bool bFrame )
{
UInt uiMbIndex = uiMbY * m_uiWidthInMB + uiMbX;
CoefMap* pcCoefMap = m_pcCoefMap[uiMbIndex].getCoefMap( cIdx );
const UChar* pucScan = (bFrame) ? g_aucFrameScan : g_aucFieldScan;
for( UInt uiScanIndex = 0; uiScanIndex < 16; uiScanIndex ++ )
pucSigMap[pucScan[uiScanIndex]] = SIGNIFICANT & pcCoefMap[uiScanIndex];
}
// get entire 8x8 significance map for chroma
Void FGSCoder::getCoeffSigMapChroma8x8( UInt uiMbX, UInt uiMbY, UInt uiPlane, UChar *pucSigMap, Bool bFrame )
{
UInt uiMbIndex = uiMbY * m_uiWidthInMB + uiMbX;
const UChar* pucScan = (bFrame) ? g_aucFrameScan : g_aucFieldScan;
for( CIdx cCIdx(( CPlaneIdx(uiPlane) )); cCIdx.isLegal( CPlaneIdx(uiPlane) ); cCIdx++ )
{
UInt uiBlockIdxWithMb = cCIdx.y() * 2 + cCIdx.x();
CoefMap *pcCoefMap = m_pcCoefMap[uiMbIndex].getCoefMap( cCIdx );
for( UInt uiScanIndex = 0; uiScanIndex < 16; uiScanIndex ++ )
pucSigMap[uiBlockIdxWithMb * 16 + pucScan[uiScanIndex]] = SIGNIFICANT & pcCoefMap[uiScanIndex];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -