Newer
Older
cu.mmvdSkip = false;

Karsten Suehring
committed
//cu.affine
cu.predMode = MODE_INTER;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
CU::addPUs( cu );
cu.GBiIdx = g_GbiSearchOrder[gbiLoopIdx];
uint8_t gbiIdx = cu.GBiIdx;
bool testGbi = (gbiIdx != GBI_DEFAULT);

Karsten Suehring
committed
m_pcInterSearch->predInterSearch( cu, partitioner );
const unsigned wIdx = gp_sizeIdxInfo->idxFrom( tempCS->area.lwidth () );
gbiIdx = CU::getValidGbiIdx(cu);
if( testGbi && gbiIdx == GBI_DEFAULT ) // Enabled GBi but the search results is uni.
{
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
continue;
}
CHECK(!(testGbi || (!testGbi && gbiIdx == GBI_DEFAULT)), " !( bTestGbi || (!bTestGbi && gbiIdx == GBI_DEFAULT ) )");
bool isEqualUni = false;
if( m_pcEncCfg->getUseGBiFast() )
{
if( cu.firstPU->interDir != 3 && testGbi == 0 )
{
isEqualUni = true;
}
}
#if JVET_M0464_UNI_MTS
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, 0
, m_pImvTempCS ? m_pImvTempCS[wIdx] : NULL
, 0
, &equGBiCost
#else
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, 0
, 1
, 0
);
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT )
m_pcInterSearch->setAffineModeSelected((bestCS->cus.front()->affine && !(bestCS->cus.front()->firstPU->mergeFlag)));
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
double skipTH = MAX_DOUBLE;
skipTH = (m_pcEncCfg->getUseGBiFast() ? 1.05 : MAX_DOUBLE);
if( equGBiCost > curBestCost * skipTH )
{
break;
}
if( m_pcEncCfg->getUseGBiFast() )
{
if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
{
break;
}
}
if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT && xIsGBiSkip(cu) && m_pcEncCfg->getUseGBiFast() )
{
break;
}
} // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
{
xCalDebCost( *bestCS, partitioner );
}

Karsten Suehring
committed
}
bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{
int iIMV = int( ( encTestMode.opts & ETO_IMV ) >> ETO_IMV_SHIFT );
m_pcInterSearch->setAffineModeSelected(false);

Karsten Suehring
committed
// Only int-Pel, 4-Pel and fast 4-Pel allowed
CHECK( iIMV != 1 && iIMV != 2 && iIMV != 3, "Unsupported IMV Mode" );
// Fast 4-Pel Mode
#if JVET_M0428_ENC_DB_OPT
m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
#endif

Karsten Suehring
committed
EncTestMode encTestModeBase = encTestMode; // copy for clearing non-IMV options
encTestModeBase.opts = EncTestModeOpts( encTestModeBase.opts & ETO_IMV ); // clear non-IMV options (is that intended?)
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
CodingStructure* pcCUInfo2Reuse = nullptr;
m_pcInterSearch->resetBufferedUniMotions();
int gbiLoopNum = (tempCS->slice->isInterB() ? GBI_NUM : 1);
gbiLoopNum = (pcCUInfo2Reuse != NULL ? 1 : gbiLoopNum);
gbiLoopNum = (tempCS->slice->getSPS()->getUseGBi() ? gbiLoopNum : 1);
if( tempCS->area.lwidth() * tempCS->area.lheight() < GBI_SIZE_CONSTRAINT )
{
gbiLoopNum = 1;
}
#if JVET_M0246_AFFINE_AMVR
bool validMode = false;
#endif
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
double curBestCost = bestCS->cost;
double equGBiCost = MAX_DOUBLE;
for( int gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
{
if( m_pcEncCfg->getUseGBiFast() )
{
auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >(m_modeCtrl);
if( blkCache )
{
bool isBestInter = blkCache->getInter(bestCS->area);
uint8_t bestGBiIdx = blkCache->getGbiIdx(bestCS->area);
if( isBestInter && g_GbiSearchOrder[gbiLoopIdx] != GBI_DEFAULT && g_GbiSearchOrder[gbiLoopIdx] != bestGBiIdx )
{
continue;
}
}
}
if( !tempCS->slice->getCheckLDC() )
{
if( gbiLoopIdx != 0 && gbiLoopIdx != 3 && gbiLoopIdx != 4 )
{
continue;
}
}
if( m_pcEncCfg->getUseGBiFast() && tempCS->slice->getCheckLDC() && g_GbiSearchOrder[gbiLoopIdx] != GBI_DEFAULT
&& (m_bestGbiIdx[0] >= 0 && g_GbiSearchOrder[gbiLoopIdx] != m_bestGbiIdx[0])
&& (m_bestGbiIdx[1] >= 0 && g_GbiSearchOrder[gbiLoopIdx] != m_bestGbiIdx[1]))
{
continue;
}

Karsten Suehring
committed
CodingUnit &cu = ( pcCUInfo2Reuse != nullptr ) ? *tempCS->getCU( partitioner.chType ) : tempCS->addCU( tempCS->area, partitioner.chType );
if( pcCUInfo2Reuse == nullptr )
{
partitioner.setCUData( cu );
cu.slice = tempCS->slice;
#if HEVC_TILES_WPP
cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
#endif
cu.skip = false;
cu.mmvdSkip = false;

Karsten Suehring
committed
//cu.affine
cu.predMode = MODE_INTER;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
CU::addPUs( cu );
}
else
{
CHECK( cu.skip, "Mismatch" );
CHECK( cu.qtDepth != partitioner.currQtDepth, "Mismatch" );
CHECK( cu.btDepth != partitioner.currBtDepth, "Mismatch" );
CHECK( cu.mtDepth != partitioner.currMtDepth, "Mismatch" );
CHECK( cu.depth != partitioner.currDepth, "Mismatch" );
}
cu.imv = iIMV > 1 ? 2 : 1;

Karsten Suehring
committed
cu.emtFlag = false;

Karsten Suehring
committed
bool testGbi;
uint8_t gbiIdx;
#if JVET_M0246_AFFINE_AMVR
bool affineAmvrEanbledFlag = cu.slice->getSPS()->getAffineAmvrEnabledFlag();
#endif

Karsten Suehring
committed
if( pcCUInfo2Reuse != nullptr )
{
// reuse the motion info from pcCUInfo2Reuse
CU::resetMVDandMV2Int( cu, m_pcInterSearch );
CHECK(cu.GBiIdx < 0 || cu.GBiIdx >= GBI_NUM, "cu.GBiIdx < 0 || cu.GBiIdx >= GBI_NUM");
gbiIdx = CU::getValidGbiIdx(cu);
testGbi = (gbiIdx != GBI_DEFAULT);
#if JVET_M0246_AFFINE_AMVR
if ( !CU::hasSubCUNonZeroMVd( cu ) && !CU::hasSubCUNonZeroAffineMVd( cu ) )
#else

Karsten Suehring
committed
if( !CU::hasSubCUNonZeroMVd( cu ) )

Karsten Suehring
committed
{
if (m_modeCtrl->useModeResult(encTestModeBase, tempCS, partitioner))
{
std::swap(tempCS, bestCS);
// store temp best CI for next CU coding
m_CurrCtx->best = m_CABACEstimator->getCtx();
}
#if JVET_M0246_AFFINE_AMVR
if ( affineAmvrEanbledFlag )
{
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
continue;
}
else
{
return false;
}
#else

Karsten Suehring
committed
return false;

Karsten Suehring
committed
}
else
{
m_pcInterSearch->motionCompensation( cu );
}
}
else
{
cu.GBiIdx = g_GbiSearchOrder[gbiLoopIdx];
gbiIdx = cu.GBiIdx;
testGbi = (gbiIdx != GBI_DEFAULT);
#if JVET_M0246_AFFINE_AMVR
cu.firstPU->interDir = 10;
#endif

Karsten Suehring
committed
m_pcInterSearch->predInterSearch( cu, partitioner );
#if JVET_M0246_AFFINE_AMVR
if ( cu.firstPU->interDir <= 3 )
{
gbiIdx = CU::getValidGbiIdx(cu);
}
else
{
return false;
}
#else
gbiIdx = CU::getValidGbiIdx(cu);

Karsten Suehring
committed
}
if( testGbi && gbiIdx == GBI_DEFAULT ) // Enabled GBi but the search results is uni.
{
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
continue;
}
CHECK(!(testGbi || (!testGbi && gbiIdx == GBI_DEFAULT)), " !( bTestGbi || (!bTestGbi && gbiIdx == GBI_DEFAULT ) )");
bool isEqualUni = false;
if( m_pcEncCfg->getUseGBiFast() )
{
if( cu.firstPU->interDir != 3 && testGbi == 0 )
{
isEqualUni = true;
}
}
#if JVET_M0246_AFFINE_AMVR
if ( !CU::hasSubCUNonZeroMVd( cu ) && !CU::hasSubCUNonZeroAffineMVd( cu ) )
#else

Karsten Suehring
committed
if( !CU::hasSubCUNonZeroMVd( cu ) )

Karsten Suehring
committed
{
if (m_modeCtrl->useModeResult(encTestModeBase, tempCS, partitioner))
{
std::swap(tempCS, bestCS);
// store temp best CI for next CU coding
m_CurrCtx->best = m_CABACEstimator->getCtx();
}
#if JVET_M0246_AFFINE_AMVR
if ( affineAmvrEanbledFlag )
{
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
continue;
}
else
{
return false;
}
#else

Karsten Suehring
committed
return false;

Karsten Suehring
committed
}
#if JVET_M0464_UNI_MTS
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestModeBase, 0
, NULL
, 0
, &equGBiCost
#else
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestModeBase, 0
, NULL
, true
, 0

Karsten Suehring
committed
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
double skipTH = MAX_DOUBLE;
skipTH = (m_pcEncCfg->getUseGBiFast() ? 1.05 : MAX_DOUBLE);
if( equGBiCost > curBestCost * skipTH )
{
break;
}
if( m_pcEncCfg->getUseGBiFast() )
{
if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
{
break;
}
}
if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT && xIsGBiSkip(cu) && m_pcEncCfg->getUseGBiFast() )
{
break;
}
#if JVET_M0246_AFFINE_AMVR
validMode = true;
#endif
} // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
{
xCalDebCost( *bestCS, partitioner );
}
#if JVET_M0246_AFFINE_AMVR
return tempCS->slice->getSPS()->getAffineAmvrEnabledFlag() ? validMode : true;
#else

Karsten Suehring
committed
return true;

Karsten Suehring
committed
}
void EncCu::xCalDebCost( CodingStructure &cs, Partitioner &partitioner, bool calDist )
if ( cs.slice->getDeblockingFilterDisable() || ( !m_pcEncCfg->getUseEncDbOpt() && !calDist ) )
{
m_pcLoopFilter->setEnc(true);
const ChromaFormat format = cs.area.chromaFormat;
CodingUnit* cu = cs.getCU(partitioner.chType);
const Position lumaPos = cu->Y().valid() ? cu->Y().pos() : recalcPosition( format, cu->chType, CHANNEL_TYPE_LUMA, cu->blocks[cu->chType].pos() );
bool topEdgeAvai = lumaPos.y > 0 && ( ( lumaPos.y % 8 ) == 0 );
bool leftEdgeAvai = lumaPos.x > 0 && ( ( lumaPos.x % 8 ) == 0 );
bool anyEdgeAvai = topEdgeAvai || leftEdgeAvai;
cs.costDbOffset = 0;
const UnitArea currCsArea = clipArea( CS::getArea( cs, cs.area, partitioner.chType ), *cs.picture );
ComponentID compStr = ( CS::isDualITree( cs ) && !isLuma( partitioner.chType ) ) ? COMPONENT_Cb : COMPONENT_Y;
ComponentID compEnd = ( CS::isDualITree( cs ) && isLuma( partitioner.chType ) ) ? COMPONENT_Y : COMPONENT_Cr;
const ComponentID compID = ComponentID( comp );
CPelBuf org = cs.getOrgBuf( compID );
CPelBuf reco = cs.getRecoBuf( compID );
finalDistortion += getDistortionDb( cs, org, reco, compID, currCsArea.block( compID ), false );
ComponentID compStr = ( CS::isDualITree( cs ) && !isLuma( partitioner.chType ) ) ? COMPONENT_Cb : COMPONENT_Y;
ComponentID compEnd = ( CS::isDualITree( cs ) && isLuma( partitioner.chType ) ) ? COMPONENT_Y : COMPONENT_Cr;
const UnitArea currCsArea = clipArea( CS::getArea( cs, cs.area, partitioner.chType ), *cs.picture );
PelStorage& picDbBuf = m_pcLoopFilter->getDbEncPicYuvBuffer();
//deblock neighbour pixels
const Size lumaSize = cu->Y().valid() ? cu->Y().size() : recalcSize( format, cu->chType, CHANNEL_TYPE_LUMA, cu->blocks[cu->chType].size() );
#if JVET_M0471_LONG_DEBLOCKING_FILTERS
const int verOffset = lumaPos.y > 7 ? 8 : 4;
const int horOffset = lumaPos.x > 7 ? 8 : 4;
#else
const int verOffset = 4;
const int horOffset = 4;
#endif
const UnitArea areaTop( format, Area( lumaPos.x, lumaPos.y - verOffset, lumaSize.width, verOffset ) );
const UnitArea areaLeft( format, Area( lumaPos.x - horOffset, lumaPos.y, horOffset, lumaSize.height ) );
for ( int compIdx = compStr; compIdx <= compEnd; compIdx++ )
{
ComponentID compId = (ComponentID)compIdx;
//Copy current CU's reco to Deblock Pic Buffer
const CompArea& curCompArea = currCsArea.block( compId );
picDbBuf.getBuf( curCompArea ).copyFrom( cs.getRecoBuf( curCompArea ) );
if ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma( compId ) )
picDbBuf.getBuf( curCompArea ).rspSignal( m_pcReshape->getInvLUT() );
picDbBuf.getBuf( compArea ).copyFrom( cs.picture->getRecoBuf( compArea ) );
if ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma( compId ) )
picDbBuf.getBuf( compArea ).rspSignal( m_pcReshape->getInvLUT() );
const CompArea& compArea = areaTop.block( compId );
picDbBuf.getBuf( compArea ).copyFrom( cs.picture->getRecoBuf( compArea ) );
if ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma( compId ) )
picDbBuf.getBuf( compArea ).rspSignal( m_pcReshape->getInvLUT() );
for ( int compIdx = compStr; compIdx <= compEnd; compIdx++ )
CPelBuf reco = picDbBuf.getBuf( currCsArea.block( compId ) );
CPelBuf org = cs.getOrgBuf( compId );
distCur += getDistortionDb( cs, org, reco, compId, currCsArea.block( compId ), true );
}
//calculate difference between DB_before_SSE and DB_after_SSE for neighbouring CUs
Distortion distBeforeDb = 0, distAfterDb = 0;
for (int compIdx = compStr; compIdx <= compEnd; compIdx++)
{
ComponentID compId = (ComponentID)compIdx;
const CompArea& compArea = areaLeft.block( compId );
CPelBuf org = cs.picture->getOrigBuf( compArea );
CPelBuf reco = cs.picture->getRecoBuf( compArea );
CPelBuf recoDb = picDbBuf.getBuf( compArea );
distBeforeDb += getDistortionDb( cs, org, reco, compId, compArea, false );
distAfterDb += getDistortionDb( cs, org, recoDb, compId, compArea, true );
const CompArea& compArea = areaTop.block( compId );
CPelBuf org = cs.picture->getOrigBuf( compArea );
CPelBuf reco = cs.picture->getRecoBuf( compArea );
CPelBuf recoDb = picDbBuf.getBuf( compArea );
distBeforeDb += getDistortionDb( cs, org, reco, compId, compArea, false );
distAfterDb += getDistortionDb( cs, org, recoDb, compId, compArea, true );
}
}
//updated cost
int64_t distTmp = distCur - cs.dist + distAfterDb - distBeforeDb;
int sign = distTmp < 0 ? -1 : 1;
distTmp = distTmp < 0 ? -distTmp : distTmp;
cs.costDbOffset = sign * m_pcRdCost->calcRdCost( 0, distTmp );
Distortion EncCu::getDistortionDb( CodingStructure &cs, CPelBuf org, CPelBuf reco, ComponentID compID, const CompArea& compArea, bool afterDb )
if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (
m_pcEncCfg->getReshaper() && ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() ) ) )
if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
CompArea tmpArea( COMPONENT_Y, cs.area.chromaFormat, Position( 0, 0 ), compArea.size() );
PelBuf tmpRecLuma = m_tmpStorageLCU->getBuf( tmpArea );
tmpRecLuma.copyFrom( reco );
tmpRecLuma.rspSignal( m_pcReshape->getInvLUT() );
dist += m_pcRdCost->getDistPart( org, tmpRecLuma, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
dist += m_pcRdCost->getDistPart( org, reco, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
else if ( m_pcEncCfg->getReshaper() && cs.slice->getReshapeInfo().getUseSliceReshaper() && cs.slice->isIntra() ) //intra slice
CompArea tmpArea( COMPONENT_Y, cs.area.chromaFormat, Position( 0, 0 ), compArea.size() );
PelBuf tmpRecLuma = m_tmpStorageLCU->getBuf( tmpArea );
tmpRecLuma.copyFrom( reco );
tmpRecLuma.rspSignal( m_pcReshape->getFwdLUT() );
dist += m_pcRdCost->getDistPart( org, tmpRecLuma, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
dist += m_pcRdCost->getDistPart( org, reco, cs.sps->getBitDepth(toChannelType( compID ) ), compID, DF_SSE );
dist = m_pcRdCost->getDistPart( org, reco, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
#if JVET_M0464_UNI_MTS
void EncCu::xEncodeInterResidual( CodingStructure *&tempCS
, CodingStructure *&bestCS
, Partitioner &partitioner
, const EncTestMode& encTestMode
, int residualPass
, CodingStructure* imvCS
, bool* bestHasNonResi
, double* equGBiCost
#else
void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, int residualPass
, CodingStructure* imvCS
, int emtMode
, bool* bestHasNonResi

Karsten Suehring
committed
{
if( residualPass == 1 && encTestMode.lossless )
{
return;
}
CodingUnit* cu = tempCS->getCU( partitioner.chType );
double bestCostInternal = MAX_DOUBLE;
double bestCost = bestCS->cost;
#if JVET_M0140_SBT
double bestCostBegin = bestCS->cost;
CodingUnit* prevBestCU = bestCS->getCU( partitioner.chType );
uint8_t prevBestSbt = ( prevBestCU == nullptr ) ? 0 : prevBestCU->sbtInfo;
#endif
const SPS& sps = *tempCS->sps;
const int maxSizeEMT = EMT_INTER_MAX_CU_WITH_QTBT;
bool swapped = false; // avoid unwanted data copy
bool reloadCU = false;
const bool considerEmtSecondPass = emtMode && sps.getUseInterEMT() && partitioner.currArea().lwidth() <= maxSizeEMT && partitioner.currArea().lheight() <= maxSizeEMT;
int minEMTMode = 0;
int maxEMTMode = (considerEmtSecondPass?1:0);

Karsten Suehring
committed
// Not allow very big |MVd| to avoid CABAC crash caused by too large MVd. Normally no impact on coding performance.
const int maxMvd = 1 << 15;
const PredictionUnit& pu = *cu->firstPU;
if (!cu->affine)
{
if ((pu.refIdx[0] >= 0 && (pu.mvd[0].getAbsHor() >= maxMvd || pu.mvd[0].getAbsVer() >= maxMvd))
|| (pu.refIdx[1] >= 0 && (pu.mvd[1].getAbsHor() >= maxMvd || pu.mvd[1].getAbsVer() >= maxMvd)))
{
return;
}
}
Xiang Li
committed
else
{
for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
{
if (pu.refIdx[refList] >= 0)
{
for (int ctrlP = 1 + (cu->affineType == AFFINEMODEL_6PARAM); ctrlP >= 0; ctrlP--)
{
if (pu.mvdAffi[refList][ctrlP].getAbsHor() >= maxMvd || pu.mvdAffi[refList][ctrlP].getAbsVer() >= maxMvd)
{
return;
}
}
}
}
}
Yin Zhao
committed
#if JVET_M0464_UNI_MTS
const bool mtsAllowed = tempCS->sps->getUseInterMTS() && partitioner.currArea().lwidth() <= MTS_INTER_MAX_CU_SIZE && partitioner.currArea().lheight() <= MTS_INTER_MAX_CU_SIZE;
Yin Zhao
committed
#else
const bool mtsAllowed = considerEmtSecondPass;
#endif
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
uint8_t sbtAllowed = cu->checkAllowedSbt();
uint8_t numRDOTried = 0;
Distortion sbtOffDist = 0;
bool sbtOffRootCbf = 0;
double sbtOffCost = MAX_DOUBLE;
double currBestCost = MAX_DOUBLE;
bool doPreAnalyzeResi = ( sbtAllowed || mtsAllowed ) && residualPass == 0;
m_pcInterSearch->initTuAnalyzer();
if( doPreAnalyzeResi )
{
m_pcInterSearch->calcMinDistSbt( *tempCS, *cu, sbtAllowed );
}
auto slsSbt = dynamic_cast<SaveLoadEncInfoSbt*>( m_modeCtrl );
int slShift = 4 + std::min( (int)gp_sizeIdxInfo->idxFrom( cu->lwidth() ) + (int)gp_sizeIdxInfo->idxFrom( cu->lheight() ), 9 );
Distortion curPuSse = m_pcInterSearch->getEstDistSbt( NUMBER_SBT_MODE );
uint8_t currBestSbt = 0;
uint8_t currBestTrs = MAX_UCHAR;
uint8_t histBestSbt = MAX_UCHAR;
uint8_t histBestTrs = MAX_UCHAR;
m_pcInterSearch->setHistBestTrs( MAX_UCHAR, MAX_UCHAR );
if( doPreAnalyzeResi )
{
if( m_pcInterSearch->getSkipSbtAll() && !mtsAllowed ) //emt is off
{
histBestSbt = 0; //try DCT2
m_pcInterSearch->setHistBestTrs( histBestSbt, histBestTrs );
}
else
{
assert( curPuSse != std::numeric_limits<uint64_t>::max() );
uint16_t compositeSbtTrs = slsSbt->findBestSbt( cu->cs->area, (uint32_t)( curPuSse >> slShift ) );
histBestSbt = ( compositeSbtTrs >> 0 ) & 0xff;
histBestTrs = ( compositeSbtTrs >> 8 ) & 0xff;
if( m_pcInterSearch->getSkipSbtAll() && CU::isSbtMode( histBestSbt ) ) //special case, skip SBT when loading SBT
{
histBestSbt = 0; //try DCT2
}
m_pcInterSearch->setHistBestTrs( histBestSbt, histBestTrs );
}
}
#endif
if( emtMode == 2 )
{
minEMTMode = maxEMTMode = (cu->emtFlag?1:0);
}

Karsten Suehring
committed
for( int curEmtMode = minEMTMode; curEmtMode <= maxEMTMode; curEmtMode++ )

Karsten Suehring
committed
{
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
if( reloadCU )
{
if( bestCost == bestCS->cost ) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
{
tempCS->clearTUs();
}
else if( false == swapped )
{
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
tempCS->copyStructure( *bestCS, partitioner.chType );
tempCS->getPredBuf().copyFrom( bestCS->getPredBuf() );
bestCost = bestCS->cost;
cu = tempCS->getCU( partitioner.chType );
swapped = true;
}
else
{
tempCS->clearTUs();
bestCost = bestCS->cost;
cu = tempCS->getCU( partitioner.chType );
}
//we need to restart the distortion for the new tempCS, the bit count and the cost
tempCS->dist = 0;
tempCS->fracBits = 0;
tempCS->cost = MAX_DOUBLE;
}
reloadCU = true; // enable cu reloading

Karsten Suehring
committed
cu->skip = false;
cu->emtFlag = curEmtMode;
#if JVET_M0140_SBT
cu->sbtInfo = 0;
#endif

Karsten Suehring
committed
const bool skipResidual = residualPass == 1;
#if JVET_M0140_SBT // skip DCT-2 and EMT if historical best transform mode is SBT
if( skipResidual || histBestSbt == MAX_UCHAR || !CU::isSbtMode( histBestSbt ) )
{
#endif

Karsten Suehring
committed
m_pcInterSearch->encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
Yin Zhao
committed
#if JVET_M0464_UNI_MTS
numRDOTried += mtsAllowed ? 2 : 1;
Yin Zhao
committed
#else
numRDOTried++;
#endif

Karsten Suehring
committed
xEncodeDontSplit( *tempCS, partitioner );
xCheckDQP( *tempCS, partitioner );
#if !JVET_M0140_SBT //harmonize with GBI fast algorithm (move the code to the end of this function)
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
if( ETM_INTER_ME == encTestMode.type )
{
if( equGBiCost != NULL )
{
if( tempCS->cost < (*equGBiCost) && cu->GBiIdx == GBI_DEFAULT )
{
(*equGBiCost) = tempCS->cost;
}
}
else
{
CHECK(equGBiCost == NULL, "equGBiCost == NULL");
}
if( tempCS->slice->getCheckLDC() && !cu->imv && cu->GBiIdx != GBI_DEFAULT && tempCS->cost < m_bestGbiCost[1] )
{
if( tempCS->cost < m_bestGbiCost[0] )
{
m_bestGbiCost[1] = m_bestGbiCost[0];
m_bestGbiCost[0] = tempCS->cost;
m_bestGbiIdx[1] = m_bestGbiIdx[0];
m_bestGbiIdx[0] = cu->GBiIdx;
}
else
{
m_bestGbiCost[1] = tempCS->cost;
m_bestGbiIdx[1] = cu->GBiIdx;
}
}
}
double emtFirstPassCost = tempCS->cost;

Karsten Suehring
committed
if( imvCS && (tempCS->cost < imvCS->cost) )
{
if( imvCS->cost != MAX_DOUBLE )
{
imvCS->initStructData( encTestMode.qp, encTestMode.lossless );
}
imvCS->copyStructure( *tempCS, partitioner.chType );
}
if( NULL != bestHasNonResi && (bestCostInternal > tempCS->cost) )
{
bestCostInternal = tempCS->cost;
if (!(tempCS->getPU(partitioner.chType)->mhIntraFlag))

Karsten Suehring
committed
*bestHasNonResi = !cu->rootCbf;
}
if (cu->rootCbf == false)
{
if (tempCS->getPU(partitioner.chType)->mhIntraFlag)
{
tempCS->cost = MAX_DOUBLE;
return;
}
}
Yin Zhao
committed
#if JVET_M0464_UNI_MTS
currBestCost = tempCS->cost;
sbtOffCost = tempCS->cost;
sbtOffDist = tempCS->dist;
sbtOffRootCbf = cu->rootCbf;
currBestSbt = CU::getSbtInfo( cu->firstTU->mtsIdx > 1 ? SBT_OFF_MTS : SBT_OFF_DCT, 0 );
currBestTrs = cu->firstTU->mtsIdx;
Yin Zhao
committed
#else
if( curEmtMode == 0 )
{
currBestCost = tempCS->cost;
sbtOffCost = tempCS->cost;
sbtOffDist = tempCS->dist;
sbtOffRootCbf = cu->rootCbf;
}
else
{
if( tempCS->cost < currBestCost )
{
currBestSbt = CU::getSbtInfo(SBT_OFF_MTS, 0);
currBestTrs = cu->firstTU->emtIdx;
currBestCost = tempCS->cost;
}
}
#endif
if( cu->lwidth() <= MAX_TU_SIZE_FOR_PROFILE && cu->lheight() <= MAX_TU_SIZE_FOR_PROFILE )
{
CHECK( tempCS->tus.size() != 1, "tu must be only one" );
}
#endif

Karsten Suehring
committed
#if WCG_EXT
DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda( true ) );
#else
DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda() );
#endif
xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
//now we check whether the second pass should be skipped or not
Yin Zhao
committed
#if JVET_M0140_SBT
if( !curEmtMode && maxEMTMode && !CU::isMtsMode(histBestSbt) )
#else
if( !curEmtMode && maxEMTMode )
Yin Zhao
committed
#endif
{
const double thresholdToSkipEmtSecondPass = 1.1; // Skip checking EMT transforms
const bool bCond1 = !cu->firstTU->cbf[COMPONENT_Y];

Karsten Suehring
committed
const bool bCond3 = emtFirstPassCost > ( bestCost * thresholdToSkipEmtSecondPass );
if( m_pcEncCfg->getFastInterEMT() && (bCond1 || bCond3 ) )
{
maxEMTMode = 0; // do not test EMT
}
}
#endif
#if JVET_M0140_SBT // skip DCT-2 and EMT
}
#endif
#if JVET_M0140_SBT //RDO for SBT
Yin Zhao
committed
#if !JVET_M0464_UNI_MTS // skip EMT
if( histBestSbt != MAX_UCHAR && !CU::isMtsMode(histBestSbt) )
{
maxEMTMode = 0;
}
#endif
uint8_t numSbtRdo = CU::numSbtModeRdo( sbtAllowed );
//early termination if all SBT modes are not allowed
//normative
Yin Zhao
committed
#if JVET_M0464_UNI_MTS
if( !sbtAllowed || skipResidual )
Yin Zhao
committed
#else
if( !sbtAllowed || skipResidual || cu->emtFlag )
#endif
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
{
numSbtRdo = 0;
}
//fast algorithm
if( ( histBestSbt != MAX_UCHAR && !CU::isSbtMode( histBestSbt ) ) || m_pcInterSearch->getSkipSbtAll() )
{
numSbtRdo = 0;
}
if( bestCost != MAX_DOUBLE && sbtOffCost != MAX_DOUBLE )
{
double th = 1.07;
if( !( prevBestSbt == 0 || m_sbtCostSave[0] == MAX_DOUBLE ) )
{
assert( m_sbtCostSave[1] <= m_sbtCostSave[0] );
th *= ( m_sbtCostSave[0] / m_sbtCostSave[1] );
}
if( sbtOffCost > bestCost * th )
{
numSbtRdo = 0;
}
}
if( !sbtOffRootCbf && sbtOffCost != MAX_DOUBLE )
{
double th = Clip3( 0.05, 0.55, ( 27 - cu->qp ) * 0.02 + 0.35 );
if( sbtOffCost < m_pcRdCost->calcRdCost( ( cu->lwidth() * cu->lheight() ) << SCALE_BITS, 0 ) * th )
{
numSbtRdo = 0;
}
}
if( histBestSbt != MAX_UCHAR && numSbtRdo != 0 )
{
numSbtRdo = 1;
m_pcInterSearch->initSbtRdoOrder( CU::getSbtMode( CU::getSbtIdx( histBestSbt ), CU::getSbtPos( histBestSbt ) ) );
}
for( int sbtModeIdx = 0; sbtModeIdx < numSbtRdo; sbtModeIdx++ )
{
uint8_t sbtMode = m_pcInterSearch->getSbtRdoOrder( sbtModeIdx );
uint8_t sbtIdx = CU::getSbtIdxFromSbtMode( sbtMode );
uint8_t sbtPos = CU::getSbtPosFromSbtMode( sbtMode );
//fast algorithm (early skip, save & load)
if( histBestSbt == MAX_UCHAR )
{
uint8_t skipCode = m_pcInterSearch->skipSbtByRDCost( cu->lwidth(), cu->lheight(), cu->mtDepth, sbtIdx, sbtPos, bestCS->cost, sbtOffDist, sbtOffCost, sbtOffRootCbf );
if( skipCode != MAX_UCHAR )
{
continue;
}
if( sbtModeIdx > 0 )
{
uint8_t prevSbtMode = m_pcInterSearch->getSbtRdoOrder( sbtModeIdx - 1 );
//make sure the prevSbtMode is the same size as the current SBT mode (otherwise the estimated dist may not be comparable)
if( CU::isSameSbtSize( prevSbtMode, sbtMode ) )
{
Distortion currEstDist = m_pcInterSearch->getEstDistSbt( sbtMode );
Distortion prevEstDist = m_pcInterSearch->getEstDistSbt( prevSbtMode );
if( currEstDist > prevEstDist * 1.15 )
{
continue;
}
}
}
}
//init tempCS and TU
if( bestCost == bestCS->cost ) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
{
tempCS->clearTUs();
}
else if( false == swapped )
{
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
tempCS->copyStructure( *bestCS, partitioner.chType );
tempCS->getPredBuf().copyFrom( bestCS->getPredBuf() );
bestCost = bestCS->cost;
cu = tempCS->getCU( partitioner.chType );
swapped = true;
}
else
{
tempCS->clearTUs();
bestCost = bestCS->cost;
cu = tempCS->getCU( partitioner.chType );
}
//we need to restart the distortion for the new tempCS, the bit count and the cost
tempCS->dist = 0;
tempCS->fracBits = 0;
tempCS->cost = MAX_DOUBLE;
Yin Zhao
committed
#if !JVET_M0464_UNI_MTS
cu->emtFlag = curEmtMode;
#endif
cu->skip = false;
//set SBT info
cu->setSbtIdx( sbtIdx );
cu->setSbtPos( sbtPos );
//try residual coding
m_pcInterSearch->encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
numRDOTried++;
xEncodeDontSplit( *tempCS, partitioner );
xCheckDQP( *tempCS, partitioner );
if( imvCS && ( tempCS->cost < imvCS->cost ) )
{
if( imvCS->cost != MAX_DOUBLE )
{
imvCS->initStructData( encTestMode.qp, encTestMode.lossless );